M-Bus
This category contains functions specific to M-Bus devices.
api.mbusTransaction(arg, timeout)
- Overview
- Arguments
- Return
- Examples
Sends and receives M-Bus frames.
Ensure M-Bus is enabled by first calling api.mbusState(1)
.
api.mbusTransaction(msg, timeout, retry)
- msg (string) - Message sent to M-Bus, leave empty to wait only for a response
- timeout (integer) - Maximum time in milliseconds to wait for a response from the M-Bus device
- retry (integer) - Optional number of retransmissions, default number is 1
Sends a custom message.
api.mbusTransaction(index, timeout, retry)
- index (integer) - Index of the secondary address in the table created by api.mbusFilter() (starting with 0)
- timeout (integer) - Maximum time in milliseconds to wait for a response from the M-Bus device
- retry (integer) - Optional number of retransmissions, default number is 1
Sends a readout request with the specified secondary address.
- status (integer) - Number of bytes received, zero on failure
- c (integer) - M-Bus c frame field
- a (integer) - M-Bus a frame field
- ci (integer) - M-Bus ci frame field
- answer (string) - M-Bus frame payload received from the bus
- raw (string) - Complete M-Bus frame with header
Example how to send a custom M-Bus message and wait for the response:
api.mbusState(1) --turn on M-Bus
-- Send M-Bus frame [0x10, 0x50, 0x30, 0x16] and wait 5s for the response, retry twice
msg = pack.pack('<b4', 0x10, 0x50, 0x30, 0x16)
status,c,a,ci,ans = api.mbusTransaction(msg, 5000, 2)
api.mbusState(0) --turn off M-Bus
Example how to use while function to get complete mbus frame (if it's available):
--"i"=index in the table created by api.mbusFilter() (starting with 0)
status,_,_,_,_,raw = api.mbusTransaction(i,3000,1)
if status > 1 then
while status > 1 do
status,_,_,_,_,rawNext = api.mbusTransaction("",200,1) -- Wait for the next frame part
if status > 1 then
raw = raw .. rawNext
else
break
end
end
end
api.dumpArray(raw)
api.mbusSetup(baudrate, parity, stopBits, dataBits)
- Overview
- Arguments
- Example
Configures the M-Bus communication interface.
After configuring the M-Bus parameters with this function, activate the M-Bus by calling api.mbusState(1)
.
- baudrate (integer) - Baudrate to use for communication (up to 921600 baud)
- parity (integer) - Parity, 0 for none, 1 for odd and 2 for even parity
- stopBits (integer) - Number of stop bits, 1 or 2 allowed
- dataBits (integer) - Number of data bits, 7 or 8 allowed
--setup M-Bus interface to 9600 Baud, 8E2
api.mbusSetup(9600, 2, 2, 8)
api.mbusState(state)
- Overview
- Arguments
- Return
- Example
Controls the M-Bus circuitry.
Use api.mbusState(1)
before api.mbusTransaction()
and api.mbusState(0)
after to reduce consumption. The consumption significantly raises if the circuitry is turned on for too long.
Do not use the api.mbusState(1)
during LoRaWAN or NB-IoT message transmition.
- state (integer) - New state of M-Bus circuitry: 1 for on, 0 for off
Approximately 30s is needed to turn on the M-Bus circuitry.
- UL (integer) - Returns approximate UL value when turing on
Valid only for new topology, otherwise there's no return value
api.mbusState(1) --turn on M-Bus
api.mbusScan()
- Overview
- Arguments
- Return
- Example
Scans for M-Bus devices.
api.mbusScan(filter, timeout, mode)
- filter (string, optional) - Filter by (no option selected = 0 = scan for everything):
- identification
- manufacturer
- version
- medium
- timeout (integer, optional) - By default set to 3000 ms
- mode (integer, optional) - If true, scan in range 0-E instead of default 0-9 (true/false)
- var (hex)(table of variables) - Table of variable (identification, manufacturer, version, medium), look at the example to see how to index in table
- cnt (integer) - Number of found devices
api.mbusSetup(2400,2,1,8)
api.mbusState(1) --turn on M-Bus
e,cnt = api.mbusScan() -- scan for everything(ID, man, ...) & use default timeout 3000 ms
for i = 1, cnt do
print(string.format("%08X", (e[i].identification)))
end
api.mbusState(0) --turn off M-Bus
api.mbusFilter(operation, ...)
- Overview
- Operations
- Arguments
- Return
- Examples
Creates and manages internal table of secondary addresses.
- "purge" - Purges the table, removing all stored secondary addresses
- "populate" - Populates the table with a set of secondary addresses provided as input
- "show" - Displays all secondary addresses currently in the table
- "fetch" - Fetches the table from EEPROM, retrieving the previously saved secondary addresses
- "scan"* - Performs a scan of devices using secondary addressing, based on the filter provided
This function is used for secondary addressing using 0xFD address internally. For more details check the example.
api.mbusFilter("purge")
- operation (string)
api.mbusFilter("populate", filter)
- operation (string)
- filter (string) - Filter, array of ids
api.mbusFilter("show")
- operation (string)
api.mbusFilter("fetch")
- operation (string)
api.mbusFilter("scan", filter, save, timeout, scan_mode, useBatteryMonitor, initialDelay, batteryMonitorTimeout, targetVoltage, minimalVoltage, minimalRaise)
- operation (string)
- filter (string) - Filter, array of IDs
- save (integer, optional) - 1 to save the found addresses in the filter
- timeout (integer, optional) - Timeout in ms
- scan_mode (integer, optional) - Mode for the scan operation
- useBatteryMonitor (integer, optional) - 1 to enable battery monitoring
- initialDelay (integer, optional) - Initial delay before scanning in ms
- batteryMonitorTimeout (integer, optional) - Timeout for battery monitoring in ms
- targetVoltage (integer, optional) - Target voltage for the battery monitor
- minimalVoltage (integer, optional) - Minimal voltage for the battery monitor
- minimalRaise (integer, optional) - Minimal raise for the battery monitor
api.mbusFilter("purge")
- status (integer) - 0 on success, negative values on failure
api.mbusFilter("populate", filter)
- number (integer) - Number of secondary addresses, negative values on failure
api.mbusFilter("show")
- number (integer) - Number of secondary addresses in the table, 0 if empty
- addresses (string) - Secondary addresses in the table, empty string if empty
api.mbusFilter("fetch")
- status (integer) - 0 on success, negative values on failure
- number (integer) - Number of secondary addresses in the table
api.mbusFilter("scan", filter, save, timeout, scan_mode, useBatteryMonitor, initialDelay, batteryMonitorTimeout, targetVoltage, minimalVoltage, minimalRaise)
- addresses (string) - Found secondary addresses
Example how to purge the table:
api.mbusFilter("purge") -- purge the table
Example how to populate the table with one secondary address:
x=pack.pack("<I",0x22003287) -- store little endian unsigned integer value of 0x22003287 to "x" variable
api.mbusFilter("populate",x) -- insert the meter ID to mbusFilter
status,_,_,_,_,raw = api.mbusTransaction(0,3000,1) -- "mbusFilter" is a table to manage secondary addresses starting with index 0. Since ID "0x22003287" is first inserted value, the index of this ID is "0"
api.dumpArray(raw) -- print the content of variable raw
Example how to populate the table with multiple secondary addresses:
local ids = {0x22003287, 0x22004567, 0x22005678} -- define a table of IDs
local x = "" -- prepare the string to pack the IDs
for _, id in ipairs(ids) do -- pack each ID into the x string
x = x .. pack.pack("<I", id)
end
api.mbusFilter("populate", x) -- insert the meter ID to mbusFilter
Example how to show the table:
status, raw = api.mbusFilter("show") -- show the table
api.dumpArray(raw) -- print the content of variable raw
Example how to fetch the table:
status, number = api.mbusFilter("fetch") -- fetch the table
print("Number of secondary addresses: " .. number) -- print the number of secondary addresses
Example how to scan the table:
filter = ""
ids = {0x22003287, 0x22004567, 0x22005678} -- IDs to scan for
for _, id in ipairs(ids) do
filter = filter .. pack.pack("<I", id) -- pack each ID into the filter string
end
save = 1 -- 1 to save the found addresses in the filter
raw = api.mbusFilter("scan", filter, save) -- perform the scan
api.dumpArray(raw) -- print the content of variable raw
api.mbusVifDifFilter(operation, ...)
- Overview
- Operations
- Arguments
- Return
- Examples
Filters received M-Bus frames by given group of bytes (VIF/DIF).
- "purge" - Purge the filter
- "populate" - Populates the filter with a set of VIF/DIF filters provided as input
- "show" - Displays all VIF/DIF filters currently in the filter
- "fetch" - Fetches the filter from EEPROM, retrieving the previously saved VIF/DIF filters
- "activate" - Activates specified filter
- "deactivate" - Deactivates all filters
- "activated" - Returns the index of the activated filter
api.mbusVifDifFilter("purge")
- operation (string)
api.mbusVifDifFilter("populate", filters)
- operation (string)
- filters (string) - Array of VIF/DIF filters
api.mbusVifDifFilter("show")
- operation (string)
api.mbusVifDifFilter("fetch")
- operation (string)
api.mbusVifDifFilter("activate", index)
- operation (string)
- index (integer, optional) - Index of the filter to activate, if nothing or -1 is provided, all filters are deactivated
api.mbusVifDifFilter("deactivate")
- operation (string)
api.mbusVifDifFilter("activated")
- operation (string)
api.mbusVifDifFilter("purge")
- status (integer) - 0 on success
api.mbusVifDifFilter("populate", filters)
- number (integer) - Length of the filter, negative values on failure
api.mbusVifDifFilter("show")
- number (integer) - Length of the filter, 0 if empty
- filters (string) - VIF/DIF filter entries, empty if none
api.mbusVifDifFilter("fetch")
- status (integer) - 0 on success, negative values on failure
- number (integer) - Length of the filter
api.mbusVifDifFilter("activate", index)
- status (integer) - 0 on success, -1 on failure
api.mbusVifDifFilter("deactivate")
- status (integer) - 0 on success
api.mbusVifDifFilter("activated")
- index (integer) - Index of activated filter, -1 if none
Example how to purge the filter:
api.mbusVifDifFilter("purge") -- purge the filter
Example how to populate the filter:
baudrate = 2400 -- baudrate: up to 921600 baud
parity = 2 -- communication parity: 0 for none, 1 for odd and 2 for even parity
stopBits = 1 -- number of stop bits: 1 or 2
dataBits = 8 -- number of data bits: 7 or 8
-- b18 = bytes to pack in total
-- 0x02 = number of physical quantities/filters in this first group
-- 0x03 = number of following bytes
-- 0xFD, 0xDC, 0xFF = first applied filter in first group
-- 0xFD, 0xC9, 0xFF = second applied filter in first group
api.mbusVifDifFilter("populate",pack.pack("b18", 0x02, -- first group (index 0)
0x03, 0xFD, 0xDC, 0xFF, -- current
0x03, 0xFD, 0xC9, 0xFF, -- voltage
0x02, -- second group (index 1)
0x03, 0xFD, 0xDA, 0xFF, -- current
0x03, 0xFD, 0xC8, 0xFF)) -- voltage
api.mbusSetup(baudrate,parity,stopBits,dataBits)
api.mbusState(1)
api.delayms(2000)
-- choose only one index
api.mbusVifDifFilter("activate", 0) -- index 0
-- api.mbusVifDifFilter("activate", 1) -- index 1
b=pack.pack('<b5', 0x10, 0x7B, 0xFE, (0x7B+0xFE)%256, 0x16)
status,_,_,_,_,raw = api.mbusTransaction(b,3000,1)
api.mbusState(0)
print("From M-Bus Calorimeter: ")
api.dumpArray(raw)
Example how to show the filter:
status, raw = api.mbusVifDifFilter("show") -- show the filter
api.dumpArray(raw) -- print the content of variable raw
Example how to fetch the filter:
status, number = api.mbusVifDifFilter("fetch") -- fetch the filter
print("Number of VIF/DIF filters: " .. number) -- print the number of VIF/DIF filters
Example how to activate the filter:
status, index = api.mbusVifDifFilter("activate", 0) -- activate the filter
print("Activated filter index: " .. index) -- print the index of the activated filter
Example how to deactivate the filter:
api.mbusVifDifFilter("deactivate") -- deactivate the filter
Example how to check if the filter is activated:
status, index = api.mbusVifDifFilter("activated") -- check if the filter is activated
print("Activated filter index: " .. index) -- print the index of the activated filter