Modbus Binding for Modbus TCP Configuration

Hi all,

I am trying to configure a smart meter in openhab using the modbus binding. My modbus .things file has the following in it.

Bridge modbus:tcp:localhost "Smart_Meter_One" [host = "<IP_ADDRESS_OF_METER>", port=502, id=2] {

    Bridge poller inputRegisters [start = 4370, length=2, refresh=1000, type="input"]{

        Thing data Voltage [readStart = "4370", readValueType="float32"]    
  }
}

The address I am trying to read is a 32 bit float address. The value is stored in two 16 bit register with a hexadecimal index of 0x1112-0x1113. I originally tried using the hexadecimal address for accessing the registers but I was getting an error code 2 from the slave which was an illegal address register. This did tell me however that there was communication to the slave so a connection is there.

I changed to the addresing described in the docs. Looking at the poller I am assuming:

  1. The parameter type="input means I am in the input address range of 30001 to 39999.
  2. The parameter start=4370 means that the first register I want to read is indexed at 34371.
  3. The parameter length=2 means I want to read two registers.

Then looking at my data Thing:

  1. The parameter readStart = 4370 means the first register to be read is at address 4370.
  2. The parameter readValueType="float32" expects a 32 bit number composed of two 16 bit registers in this format.

My modbus.items file then contains the following

Number Voltage1221Float32 "Input registers 1112-1113 as float32 [%.1f]"  { channel="modbus:data:localhostTCP:inputRegisters:Voltage:number"}

There is no errors in the log and both the poller and the data Thing have a status of online. The Voltage1221Float32 Item however has a constant state of Null.

Is there any errors in my configuration of the modbus connection?

I know that the modbus device is communicating properly as I tried reading the address from a python script and it worked fine in reading the address.

from pymodbus.client.sync import ModbusTcpClient
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder

client = ModbusTcpClient('<IP_ADDRESS_OF_METER>')

def read32bitfloat(address):
    response = client.read_input_registers(address, 2)
    return response

def read_voltage():
    response = read32bitfloat(0x1112)
    decoder = BinaryPayloadDecoder.fromRegisters(response.registers, Endian.Big, wordorder=Endian.Little)
    return decoder.decode_32bit_float()

if __name__ == '__main__':
    print(smart_meters.read_voltage())

1 Like

If you’ve been editing Things, restart the binding at least, to ensure new settings are picked up.

1 Like

I have been using the command

openhab> bundle:restart org.openhab.binding.modbus

In the karaf console when I change Things but doesn’t seem to help.

This might not be a good idea… There is also the modbus transport bundle and restarting only one is problematic.

You can stop both bundles and start transport first, then the binding.

Btw,Thing file changes are also picked up properly by disabling and enabling things, e.g. In paper ui. The buggy behavior has been fixed in snapshot version of the binding.

I have uninstalled the binding completely and reinstalled it. Unfortunately it is the same result below is the current information when I requst the item

{
  "link": "http://<IP_ADDRESS>:8080/rest/items/Voltage1221Float32 ",
  "state": "NULL",
  "stateDescription": {
    "pattern": "%.1f",
    "readOnly": false,
    "options": []
  },
  "editable": false,
  "type": "Number",
  "name": "Voltage1221Float32",
  "label": "Input registers 1112-1113 as float32",
  "tags": [],
  "groupNames": []
}

“it all depends”
4370 is what will actually be sent out in Modbus protocol.
Whether that is interpreted by device as 4370 address or 4371 register number, don’t know.
It is possible the device really does wants 34370 (or 34371).

If you’re not getting complaints from the poller, it’s a data interpretation issue.

For diagnostic purposes you can add more data Things/Items alongside what you have to examine the same registers individually.

By enabling verbose logging you can see what is happening under the hood

It is quite odd, I would expect thing status to reflect clear errors…

Edit : @open123 the channel name (localhostTcp) is wrong in the item definition. This explains the lack of state updates

2 Likes

Thank you, had to change the readValueType="float32_swap" and is now reading it fine. The changing of the log level was helpful too if anyone else wants to see what is happening.

log:set TRACE org.openhab.transport.modbus
log:set TRACE org.openhab.binding.modbus
log:set TRACE org.openhab.io.transport.modbus

Maybe do one at a time to instead of all at once, it is bit easier to read.

2 Likes