Connection pooling in modbus binding

That is correct I was using the 1.8.0 snapshot befor but wanted to try the new binding do I downloaded the jar from the V6 link and it did’t work with 1.8.0snap so I thought I needed to upgrade to the 1.8.1 and it still didn’t work. if I drop the 1.8.0 snap jar back in the folder with 1.8.1 modbus works again

This is what it looks like when I rip the 1.9 out and drop the 1.8 in.

12:07:03.323 [INFO ] [runtime.busevents             :26   ] - Camera_11 state updated to ON
12:07:13.262 [DEBUG] [.o.b.snmp.internal.SnmpBinding:335  ] - Item 'Camera_11' is about to be refreshed
12:07:13.262 [DEBUG] [.o.b.snmp.internal.SnmpBinding:350  ] - SNMP: Send PDU 192.168.1.251/161 GET[requestID=0, errorStatus=Success(0), errorIndex=0, VBS[1.3.6.1.2.1.2.2.1.8.41 = N
ull]]
12:07:13.324 [DEBUG] [.o.b.snmp.internal.SnmpBinding:213  ] - Received PDU from '192.168.1.251/161' 'RESPONSE[requestID=1913326779, errorStatus=Success(0), errorIndex=0, VBS[1.3.6.
1.2.1.2.2.1.8.41 = 1]]'
12:07:13.324 [INFO ] [runtime.busevents             :26   ] - Camera_11 state updated to ON
12:07:16.574 [DEBUG] [o.b.m.internal.ModbusActivator:39   ] - Modbus binding has been stopped.
12:07:20.731 [DEBUG] [o.b.m.internal.ModbusActivator:30   ] - Modbus binding has been started.
12:07:20.731 [DEBUG] [i.internal.GenericItemProvider:341  ] - Start processing binding configuration of Item 'COMP_1_MAIN_Temp (Type=NumberItem, State=Uninitialized)' with 'ModbusG
enericBindingProvider' reader.
12:07:20.731 [DEBUG] [i.internal.GenericItemProvider:341  ] - Start processing binding configuration of Item 'lightstackred (Type=SwitchItem, State=Uninitialized)' with 'ModbusGene
ricBindingProvider' reader.
12:07:20.731 [DEBUG] [i.internal.GenericItemProvider:341  ] - Start processing binding configuration of Item 'lightstackyellow (Type=SwitchItem, State=Uninitialized)' with 'ModbusG
enericBindingProvider' reader.
12:07:20.731 [DEBUG] [i.internal.GenericItemProvider:341  ] - Start processing binding configuration of Item 'lightstackgreen (Type=SwitchItem, State=Uninitialized)' with 'ModbusGe
nericBindingProvider' reader.
12:07:20.731 [DEBUG] [i.internal.GenericItemProvider:341  ] - Start processing binding configuration of Item 'COMP_1_MAIN_Power (Type=SwitchItem, State=Uninitialized)' with 'Modbus
GenericBindingProvider' reader.
12:07:20.731 [DEBUG] [i.internal.GenericItemProvider:341  ] - Start processing binding configuration of Item 'Fan1RPM_H (Type=NumberItem, State=Uninitialized)' with 'ModbusGenericB
indingProvider' reader.
12:07:20.731 [DEBUG] [i.internal.GenericItemProvider:341  ] - Start processing binding configuration of Item 'COMP_1_MAIN_Pressure (Type=NumberItem, State=Uninitialized)' with 'Mod
busGenericBindingProvider' reader.
12:07:20.731 [DEBUG] [i.internal.GenericItemProvider:341  ] - Start processing binding configuration of Item 'Chamber_SET1 (Type=NumberItem, State=Uninitialized)' with 'ModbusGener
icBindingProvider' reader.
12:07:20.731 [DEBUG] [i.internal.GenericItemProvider:341  ] - Start processing binding configuration of Item 'Chamber_TEMP1 (Type=NumberItem, State=Uninitialized)' with 'ModbusGene
ricBindingProvider' reader.
12:07:20.731 [DEBUG] [i.internal.GenericItemProvider:341  ] - Start processing binding configuration of Item 'Chamber_STAT1 (Type=NumberItem, State=Uninitialized)' with 'ModbusGene
ricBindingProvider' reader.
12:07:20.731 [DEBUG] [i.internal.GenericItemProvider:341  ] - Start processing binding configuration of Item 'Chamber_STAT_AL1 (Type=NumberItem, State=Uninitialized)' with 'ModbusG
enericBindingProvider' reader.
12:07:20.731 [DEBUG] [i.internal.GenericItemProvider:341  ] - Start processing binding configuration of Item 'Chamber_Heat (Type=NumberItem, State=Uninitialized)' with 'ModbusGener
icBindingProvider' reader.
12:07:20.731 [DEBUG] [i.internal.GenericItemProvider:341  ] - Start processing binding configuration of Item 'Chamber_STAT_AL2 (Type=NumberItem, State=Uninitialized)' with 'ModbusG
enericBindingProvider' reader.
12:07:20.731 [DEBUG] [i.internal.GenericItemProvider:341  ] - Start processing binding configuration of Item 'Chamber_COOL (Type=NumberItem, State=Uninitialized)' with 'ModbusGener
icBindingProvider' reader.
12:07:20.731 [DEBUG] [i.internal.GenericItemProvider:341  ] - Start processing binding configuration of Item 'Chamber_TARGET (Type=NumberItem, State=Uninitialized)' with 'ModbusGen
ericBindingProvider' reader.
12:07:20.731 [DEBUG] [i.internal.GenericItemProvider:341  ] - Start processing binding configuration of Item 'Chamber_Fan_Run (Type=NumberItem, State=Uninitialized)' with 'ModbusGe
nericBindingProvider' reader.
12:07:20.731 [DEBUG] [i.internal.GenericItemProvider:341  ] - Start processing binding configuration of Item 'Chamber_Fan_Speed (Type=NumberItem, State=Uninitialized)' with 'Modbus
GenericBindingProvider' reader.
12:07:20.762 [DEBUG] [.modbus.internal.ModbusBinding:282  ] - modbusSlave 'slave1' instanciated
12:07:20.762 [DEBUG] [.modbus.internal.ModbusBinding:282  ] - modbusSlave 'slave10' instanciated
12:07:20.762 [DEBUG] [.modbus.internal.ModbusBinding:282  ] - modbusSlave 'slave2' instanciated
12:07:20.762 [DEBUG] [.modbus.internal.ModbusBinding:282  ] - modbusSlave 'slave3' instanciated
12:07:20.762 [DEBUG] [.modbus.internal.ModbusBinding:282  ] - modbusSlave 'slave4' instanciated
12:07:20.762 [DEBUG] [.modbus.internal.ModbusBinding:282  ] - modbusSlave 'slave5' instanciated
12:07:20.762 [DEBUG] [.modbus.internal.ModbusBinding:282  ] - modbusSlave 'slave6' instanciated
12:07:20.762 [DEBUG] [.modbus.internal.ModbusBinding:282  ] - modbusSlave 'slave7' instanciated
12:07:20.762 [DEBUG] [.modbus.internal.ModbusBinding:282  ] - modbusSlave 'slave8' instanciated
12:07:20.762 [DEBUG] [.modbus.internal.ModbusBinding:282  ] - modbusSlave 'slave9' instanciated
12:07:20.762 [DEBUG] [.modbus.internal.ModbusBinding:344  ] - config looked good, proceeding with slave-connections
12:07:20.762 [DEBUG] [modbus.net.TCPMasterConnection:68   ] - connect()
12:07:20.778 [DEBUG] [modbus.net.TCPMasterConnection:68   ] - connect()
12:07:20.793 [DEBUG] [modbus.net.TCPMasterConnection:68   ] - connect()
12:07:20.793 [DEBUG] [modbus.net.TCPMasterConnection:68   ] - connect()
12:07:20.825 [DEBUG] [modbus.net.TCPMasterConnection:68   ] - connect()
12:07:20.825 [DEBUG] [modbus.net.TCPMasterConnection:68   ] - connect()
12:07:20.825 [DEBUG] [modbus.net.TCPMasterConnection:68   ] - connect()
12:07:23.278 [DEBUG] [.o.b.snmp.internal.SnmpBinding:335  ] - Item 'Camera_11' is about to be refreshed
12:07:23.278 [DEBUG] [.o.b.snmp.internal.SnmpBinding:350  ] - SNMP: Send PDU 192.168.1.251/161 GET[requestID=0, errorStatus=Success(0), errorIndex=0, VBS[1.3.6.1.2.1.2.2.1.8.41 = N
ull]]
12:07:23.309 [DEBUG] [.o.b.snmp.internal.SnmpBinding:213  ] - Received PDU from '192.168.1.251/161' 'RESPONSE[requestID=1913326781, errorStatus=Success(0), errorIndex=0, VBS[1.3.6.
1.2.1.2.2.1.8.41 = 1]]'
12:07:23.309 [INFO ] [runtime.busevents             :26   ] - Camera_11 state updated to ON
12:07:33.278 [DEBUG] [.o.b.snmp.internal.SnmpBinding:335  ] - Item 'Camera_11' is about to be refreshed
12:07:33.278 [DEBUG] [.o.b.snmp.internal.SnmpBinding:350  ] - SNMP: Send PDU 192.168.1.251/161 GET[requestID=0, errorStatus=Success(0), errorIndex=0, VBS[1.3.6.1.2.1.2.2.1.8.41 = N
ull]]
12:07:33.341 [DEBUG] [.o.b.snmp.internal.SnmpBinding:213  ] - Received PDU from '192.168.1.251/161' 'RESPONSE[requestID=1913326783, errorStatus=Success(0), errorIndex=0, VBS[1.3.6.
1.2.1.2.2.1.8.41 = 1]]'
12:07:33.341 [INFO ] [runtime.busevents             :26   ] - Camera_11 state updated to ON
12:07:41.732 [DEBUG] [modbus.internal.ModbusTcpSlave:68   ] - ModbusSlave: Error connecting to master: Connection timed out: connect
12:07:41.732 [DEBUG] [modbus.net.TCPMasterConnection:68   ] - connect()
12:07:41.748 [DEBUG] [modbus.net.TCPMasterConnection:68   ] - connect()
12:07:41.763 [DEBUG] [modbus.net.TCPMasterConnection:68   ] - connect()
12:07:43.279 [DEBUG] [.o.b.snmp.internal.SnmpBinding:335  ] - Item 'Camera_11' is about to be refreshed
12:07:43.279 [DEBUG] [.o.b.snmp.internal.SnmpBinding:350  ] - SNMP: Send PDU 192.168.1.251/161 GET[requestID=0, errorStatus=Success(0), errorIndex=0, VBS[1.3.6.1.2.1.2.2.1.8.41 = N
ull]]
12:07:43.310 [DEBUG] [.o.b.snmp.internal.SnmpBinding:213  ] - Received PDU from '192.168.1.251/161' 'RESPONSE[requestID=1913326785, errorStatus=Success(0), errorIndex=0, VBS[1.3.6.
1.2.1.2.2.1.8.41 = 1]]'
12:07:43.310 [INFO ] [runtime.busevents             :26   ] - Camera_11 state updated to ON
12:07:44.701 [INFO ] [.service.AbstractActiveService:169  ] - Modbus Polling Service has been started
12:07:45.154 [DEBUG] [m.r.internal.engine.RuleEngine:305  ] - Executing rule 'Chamber Demand conversion'
12:07:45.170 [TRACE] [et.wimpi.modbus.util.BitVector:137  ] - Get bit #0
12:07:45.170 [DEBUG] [modbus.net.TCPMasterConnection:68   ] - connect()
12:07:45.467 [INFO ] [runtime.busevents             :26   ] - Chamber_TARGET state updated to 0
12:07:45.467 [INFO ] [runtime.busevents             :26   ] - Fan1RPM_H state updated to 0
12:07:45.467 [INFO ] [runtime.busevents             :26   ] - COMP_1_MAIN_Power state updated to ON
12:07:45.514 [DEBUG] [riptExtensionClassNameProvider:63   ] - Script actions have changed: AudioActionService, HTTPActionService, PingActionService, ExecActionService, MailActionSe
rvice, TransformationActionService,
12:07:45.748 [DEBUG] [.p.rrd4j.internal.RRD4jService:130  ] - Stored 'Chamber_TARGET_div' with state '0' in rrd4j database
12:07:45.748 [INFO ] [runtime.busevents             :26   ] - Chamber_TARGET_div state updated to 0

I think I know what it is slave1 has problems where there is a device on the network with the same IP address and I havn’t been able to track it down. there is an uncaught error on slave one so it just halts.
when I dissabled slave1 and reloaded it it works.

Good to hear that it was IP address conflict.

I tried as well but could not reproduce the issue here (using the v6 + 1.8.1 openhab on linux).

I tried different ways to mess up the binding, for example:

  • non-existent ip -> I get error 19:46:24.913 [ERROR] [dbusSlaveConnectionFactoryImpl:212 ] - connect try 1/3 error: No route to host. Connection TCPMasterConnection@619ffac9[socket=<null>]. Endpoint ModbusTCPSlaveEndpoint@7980c9cb[address=192.168.1.103,port=502]
  • existing ip with no modbus -> Connection refused error

Really weird what you are experiencing since if it has configured only one slave, but not the rest, it should not yet connect to the slaves… What did you mean by “uncaught error”? Did you have some error in the logs?

Please keep me posted if you get any other issues.

no I mean by the binding with the new changes doesn’t know what to do with that connection if two devices have the same ip address and hangs up there.
also I noticed that is the only RTU device I have too

#modbus:tcp.slave1.connection=192.168.1.200:502:rtu:100
#modbus:tcp.slave1.type=holding
#modbus:tcp.slave1.start=39
#modbus:tcp.slave1.length=1
#modbus:tcp.slave1.valuetype=uint16

thats all I did and it started working with the others

Btw, the connection string for TCP slaves follow this convention in the new binding

colon ( : ) separated connection settings for a tcp/udp modbus slave. Expecting at most 2 parameters: hostname (mandatory) and optionally (in this order) port number, interTransactionDelayMillis, reconnectAfterMillis, interConnectDelayMillis, connectMaxTries.

Most often you do not need to touch any of the optional parameters with TCP slaves but they are to resolve issues with some specific devices. For example, I need to use interTransactionDelayMillis=50 to give some time for the PLC to “recover” from the previous request.

what about the RTU setting could that have thrown it off?

Ah I didn’t even notice that error in the config! Yes that apparently crashes some part of openhab itself (likely better error handling would be in order in core as well).

I have to improve the error handling.

Note that the binding handles the situation that two openhab modbus slaves have the same ip. Actually, that is the whole point the of this “connection pooling”.

Not sure what you are trying to achieve by setting ip and “rtu” – RTU is supported only with serial connections, not TCP connections. Or was it a pure typo?

The binding fails to parse “rtu” as number (as it should represent inter transaction delay in millis), and apparently makes openhab stuck…

I think it was left there when I was first started messing with modbus tcp and openhab. and I never know it was an error because the previous bindings must have ignored it.

It is true that they used to ignore additional parameters since previously you could only input host and port with TCP slaves. I believe you might get the old binding crash with 192.168.100.1:ThisIsInvalidPort since ThisIsInvalidPort is not a number…

Seems to work. No errors.

1200 Baud => 8.3ms/Character => 3.5*8,3ms = 29.05ms
=> 35ms should be ok for every application

What’s way more important anyway is the value of readTimeout where 280ms is actually quite low. The spec says:

Typically the Response time-out is from 1s to several second at 9600 bps

Although most devices are a lot faster we shouldn’t make something as low as 280ms the default - or at least suggest sth like 1.5s for debugging purposes.

Of course all I’m saying applies to serial lines only. I’ve got no real clue about ModBus TCP :smile:

1 Like

Excellent feedback @mbs38! I agree that it makes sense to have large read time out, since I expect the 280ms to become tight if reading many many registers.

I shall go with the 35ms and 1.5s with serial slaves. For TCP I shall use 50ms inter transaction delay since it was required at least for my (pretty hefty, but with default settings) PLC.

I am playing with my settings and trying to get it to run smooth.
I am in a old and quite network heavy building at my company monitoring various devices around the plant.
Using wireshark with the filter set to “mbtcp” I can watch all the trafic go by one thing I noticed is when a device stops communicateing it brings the updates down to a snails pace as it retries the connection.

I am setting mine up as

modbus:poll=1000

#                            (IP)       
#                            |             (PORT)
#                            |             |   (interTransactionDelayMillis)
#                            |             |   |  (reconnectAfterMillis)
#                            |             |   |  |   (interConnectDelayMillis)
#                            |             |   |  |   |   (connectMaxTries)
#                            |             |   |  |   |   |
modbus:tcp.slave1.connection=192.168.1.200:502:50:500:100:2

What I would like to achieve is every second it polls the 10 modbus devices with minimum delay between devices then essentially rest till the next second

Hi

Do you need all the parameters?

You could lower connection rtries (1), inter transaction delay (as low as your device can go), and inter connect delay (0ms)

With these settings it would try to connect only once, and if the slave is down it goes to next.

Edit : please note that with unreliable slaves the write commands will vanish if the retries are not enough…

I don’t know. can I skip parameters by having two colons next to each other?

modbus:tcp.slave1.connection=192.168.1.200::50::0:1

Oh sorry yeah that’s not possible. I was thinking that now some of the settings are more conservative than the defaults but I realized that defaults of these new settings are naturally not documented anywhere yet. :slight_smile:

Please try out the parameters I suggested and see if the performance is feasible for you.

Thanks

ok well I have come up with another fun modbus config question I am trying to JS transform a number I am receiving but it’s not working :confused: I have tried two different ways. The number is 6.10HZ the register returns 61 so I am dividing it by 10 the multiplying it by 60 to get RPM. When I have the JS inside the quotation marks it kicks an error when I have it outside the quotation marks it does nothing and I see the raw number.
HZ_RPM.js

(function(i){ return Math.round(i / 10 * 60); })(input)
Number Fan1RPM_H "Compressor Exaust Fan RPM [%d]" (modbus_raw,modbus) {modbus="slave5:0":JS(HZ_RPM.js)}
Number Fan1RPM_H "Compressor Exaust Fan RPM [%d]" (modbus_raw,modbus) {modbus="slave5:0:JS(HZ_RPM.js)"}

here is the error

org.openhab.model.item.binding.BindingConfigParseException: Register references should be either :X or :<X:>Y
        at org.openhab.binding.modbus.internal.ModbusGenericBindingProvider$ModbusBindingConfig.<init>(ModbusGenericBindingProvider.java:207) ~[na:na]
        at org.openhab.binding.modbus.internal.ModbusGenericBindingProvider.parseBindingConfig(ModbusGenericBindingProvider.java:108) ~[na:na]
        at org.openhab.binding.modbus.internal.ModbusGenericBindingProvider.processBindingConfiguration(ModbusGenericBindingProvider.java:91) ~[na:na]
        at org.openhab.model.item.internal.GenericItemProvider.internalDispatchBindings(GenericItemProvider.java:348) [org.openhab.model.item_1.8.1.jar:na]
        at org.openhab.model.item.internal.GenericItemProvider.internalDispatchBindings(GenericItemProvider.java:324) [org.openhab.model.item_1.8.1.jar:na]
        at org.openhab.model.item.internal.GenericItemProvider.processBindingConfigsFromModel(GenericItemProvider.java:171) [org.openhab.model.item_1.8.1.jar:na]
        at org.openhab.model.item.internal.GenericItemProvider.modelChanged(GenericItemProvider.java:390) [org.openhab.model.item_1.8.1.jar:na]
        at org.openhab.model.core.internal.ModelRepositoryImpl.notifyListeners(ModelRepositoryImpl.java:159) [org.openhab.model.core_1.8.1.jar:na]
        at org.openhab.model.core.internal.ModelRepositoryImpl.addOrRefreshModel(ModelRepositoryImpl.java:100) [org.openhab.model.core_1.8.1.jar:na]
        at org.openhab.model.core.internal.folder.FolderObserver.checkFolder(FolderObserver.java:142) [org.openhab.model.core_1.8.1.jar:na]
        at org.openhab.model.core.internal.folder.FolderObserver.run(FolderObserver.java:99) [org.openhab.model.core_1.8.1.jar:na]

Hi

Do you mind opening a separate thread about this as it is unrelated to this topic. Let’s continue the discussion on transformations there

Did you manage to configure modbus for sufficient performance? How did it perform with my configuration advice?

Best
Sami

The reason I kept it here is I believe that the binding needs to be setup to allow transform.

I agree that is quire relevant discussion but I try to keep this topic focused on the new version of the binding and especially the connection related and multi slave enchantments it include.

It just makes it easier to follow later on when I eventually submit a pull request for all the changes. I’m afraid it would otherwise be too easy to connect the error messages with this new version of the binding… I hope you understand!

I actually have something you could try with the transforms… Let me know when you have made the new thread and Let’s continue it there