This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

Modbus mappings automation
#1
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")
Reply
#2
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.
Reply
#3
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?
Reply
#4
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
Reply


Forum Jump: