LogicMachine Forum
Modbus mappings automation - Printable Version

+- LogicMachine Forum (https://forum.logicmachine.net)
+-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1)
+--- Forum: Scripting (https://forum.logicmachine.net/forumdisplay.php?fid=8)
+--- Thread: Modbus mappings automation (/showthread.php?tid=6054)



Modbus mappings automation - pawel200388 - 21.07.2025

Hi,

I strive to add a funtion to automatically map modbus registers to selected group addresses.

Code:
function mapModbusRegisterToKnx(knxGA, regNum, regType, valueBitmask) local sql = string.format(   "SELECT id FROM modbus_mapping WHERE type='%s' AND address=%d",   regType, reg ) local rows = db:getall(sql) if not rows or #rows == 0 then   return false end local updateFields = {   bus_address  = gaDec,   bus_write    = 1,   value_delta  = 0.1,   value_custom = "rfid" } if valueBitmask ~= nil then   updateFields.value_bitmask = valueBitmask end for _, rec in ipairs(rows) do   db:update("modbus_mapping", updateFields, { id = rec.id })   log(("✅ Zaktualizowano Modbus %s[%d] → KNX %s (id=%d)%s")     :format(       regType, reg, knxGA, rec.id,       valueBitmask and (", bitmask=" .. tostring(valueBitmask)) or ""     )   ) end end

The problem it works for registers without bitmask:
Code:
mapModbusRegisterToKnx("60/0/93",1299,"register")


but I can't figure out how to make it to work with bitmasks:
Code:
mapModbusRegisterToKnx("60/0/94",1300,"register", "0x01") mapModbusRegisterToKnx("60/0/95",1300,"register", "0x02")



RE: Modbus mappings automation - admin - 21.07.2025

1. Don't modify value_bitmask, change the SELECT statement to look for a specific value_bitmask if specified.

2. Remove quotes around hexadecimal numbers (0x01 instead of "0x01").

3. value_custom = "rfid"[/b] is not a valid custom value.

4. If you have multiple Modbus devices then all devices with matching registers will be mapped to the same group address.


RE: Modbus mappings automation - pawel200388 - 21.07.2025

Hello admin,
thank you for your fast response. This code is part of a larger solution, in which in the first step I add group addresses, in the second I create a modbus device and attach a status object to it, and in the third I map selected points. It's a kind of "wizard" for my customers.


1. Ok, perfect. I changed it to:

Code:
(...)   if valueBitmask ~= nil then     sql = string.format(       "SELECT id FROM modbus_mapping WHERE type='%s' AND address=%d AND value_bitmask='%s'",       regType, regNum, valueBitmask     )   else     sql = string.format(       "SELECT id FROM modbus_mapping WHERE type='%s' AND address=%d",       regType, regNum     )   end (...) local rows = db:getall(sql)
and it works smootly.

2. In fact I tried it as a hex. Now I have conversions, so both versions are OK Wink

3. I know, it was temporary. It's a kind of note that shows me where changes in the database have been saved and where they haven't.

4. Unfortunately I know. For now 1 device is enough, but in the future I'l have to rebuild the code to support more modbus devices. I assume I'll use the device column somehow.

Lastly...
5. Is there any simple way to clear modbus_mapping table? Smile I have some rubbish left there.
6. As I can see modbus doesn't start on its own. For now my solution was to automatically reboot it, but maybe there is other way?


RE: Modbus mappings automation - admin - 21.07.2025

5. Run this once:
Code:
db:query('DELETE FROM modbus_mapping')

6. You can send reload signal to Modbus daemon after making changes to the modbus_mapping DB table:
Code:
pid = os.checkproc('gs-modbus') if pid then   os.kill(pid, signal.SIGUSR1) end