Modbus performance management in openHAB 2

TCP tuning

If you are a user only of Modbus-RTU over serial, ignore this section. Modbus-TCP users read on…

I wondered whether to make this a separate guide, as this is more about performance external to openHAB, but it is closely related.

In Modbus-TCP, we use the standard TCP/IP communications protocol as a “carrier” for our Modbus flavoured data transactions. TCP in general is really peer-to-peer, but with Modbus our Master (openHAB) becomes a TCP Client, initiating communications with TCP Servers – which are our Modbus Slaves.

To make best use of the TCP parameters available in the OH Modbus binding, we should know a little about how TCP/IP works.

TCP connections – a really simplistic view

IP carries data packets between here and there, without much intelligence and few guarantees – not even that data arrives in the same order it was sent.

TCP adds some controlling rules on top of that – hence “TCP/IP” – and allows receipt acknowledgments, retries, proper ordering. All the stuff we need for Modbus!
We don’t need to know how exactly, but the important part is the connection concept.

openHAB (as TCP client) contacts a remote device (TCP server) and they do some introductions and handshaking, and agree to establish a connection.
Once that TCP connection is open, they can exchange data packets (our Modbus transactions) easily and reliably.

Connections do not last forever – it all goes wrong if anything changes at either end or along the way inbetween.
Either end can close the connection, and that’s the end of that until you establish a new one.
Connections can last just one exchange, or for days with gigabytes of transfers – it all depends on use and environment.

Alright, that is the child’s eye view but it is good enough here.

Modbus binding TCP defaults

By default, the binding opens a new TCP connection for each data poll (or data write) and then closes it again.

What? Well, why not. It works in most cases, and the defaults are there to get you started in first simple use of the binding.

Why close the connection?
Modbus has a lot of history, slaves can be very old designs with few resources to spare.
It is not that uncommon for a slave to support only one TCP connection at a time, rejecting other attempts while connected.
In that circumstance, keeping a connection open is anti-social behaviour – you are hogging the slave’s attention and no-one else can talk to it. Especially frustrating in an environment like a HVAC system where another “user” like a display panel might need a turn.

So, safest for openHAB to be a “good neighbour” and close the connection after each binding transaction.

Isn’t that an overhead, making work?
Yes it is. Creating a connection uses resource, at both ends.
So as your system grows beyond reading just a few registers we must pay more attention. Creating hundreds of connections per minute can begin to stress the host systems. That probably isn’t going to matter very much to your openHAB host, but remembering our resource-limited slaves it can definitely be a problem at that end.

IF you find out that your slave can support more than one TCP connection, you’ll almost certainly want to change this behaviour in any non-trivial setup.

You can do this separately for each slave, so you can run a configuration with a mix of capabilities.

The reconnectAfterMillis parameter

This is a time value, giving the effect that the TCP connection will be held open for at least the given time, then closed and established anew at the next read poll or write.

Where you’re probably polling each second, you might typically set that for one or ten minutes (60000mS). You can go up to a week here.
All those Modbus transactions for that slave then take place over the existing TCP connection.
Don’t be tempted to go much longer than an hour without good reason, or you may accidentally make it harder to recover from any environment changes. Also, occasionally there might be a firewall or suchlike in the path that can block off connections it thinks have been open too long.

Don’t worry about error recovery here, a serious error during a connection will likely cause one or the other end to close it pre-emptively, that’s all part of the TCP hidden machinery. If we can successfully re-establish a new connection, the timing starts over.

The timeBetweenReconnectMillis parameter

Another time value, this sets a minimum delay between closing a connection and establishing a new one.

Why not immediately? There is housekeeping for both ends to do when closing a TCP connection, as well as opening, so we want to be sure that’s all finished before starting over. Again, remember a resource limited slave could take much longer to tidy up than our openHAB host. For some slaves, you may need to make this more generous than the default 0mS (for immediate attempt).
You might try 100mS or more if you seem to get a timeout at each reconnect.

That all assumes an orderly planned connection closure. But if there was an error of some kind, we don’t know how long the other end will take to recognize for itself that there is a problem, and make its own closure. Again, for some devices we may need to be generous here.

Note for users of Gateways
A device like a radio or serial gateway allows many real Modbus slaves to be available at the same IP address and port - but with different slave IDs.
The binding requires you to set up separate TCP Bridge Things for each slave, but using the shared IP/port.
You must make sure you use the same TCP option parameters for each Bridge with the common IP/port.

Summary

In most Modbus-TCP uses, overheads (and very often occasional timeout-retry incidents) can be much reduced by holding TCP connections for a considerable time.

6 Likes