These notes apply to modbus binding version 2.x
This is not a Modbus how-to, but rather a tuning guide for advanced users.
Related - Modbus performance management in openHAB 2
Fault detection
Later we’ll look at ways to handle faults and errors. But to begin, we’ll look at how you can detect a Modbus problem using openHAB, so that you can build rules to take some action; send a warning message, put control systems into a fallback mode, or whatever.
A serious fault with your Modbus slave or network will most often show up in openHAB as a persistent failure to communicate. The binding will log error messages into openhab.log of course, but that won’t trigger a rule.
Detecting UNDEF state
If you use the ‘stale data’ technique described later to set Items to UNDEF
, it is of course easy to trigger a rule from state change. As this is Item based, you may gather many into a Group to “share” a rule.
Rule "modbus fault"
when
Member of gTellTales changed to UNDEF
then
sendMail([you@email.net](mailto:you@email.net), "Fault report", "Modbus Item faulty " + triggeringItem.name)
end
Note that any fault is likely to affect all of the Things defined under one TCP/serial Bridge Thing (representing a physical slave); potentially several poller and many data Things.
You need only check on one Item from each slave for simple reporting of in-service faults.
Be aware that Items linked with a slave already broken at openHAB boot time will stay at NULL
state, and not change. The binding would normally complete its first read poll before rules become available, and update “good” Items; so you could trigger a rule at System started
and check for Items remaining NULL at that time.
Detecting Thing offline
Note that the TCP or serial bridge Thing representing your Modbus slave would NOT normally go OFFLINE
in response to an error. That may seem odd, but the TCP or serial pathway to attempt communications is in fact still available.
A faulty slave will instead be detected by a poller Thing, this being the Thing that actually fails to read. In your configuration, it could have several poller Things.
We can detect a change using Thing based rule triggers.
Rule "modbus thing fault"
when
Thing "modbus:poller:slave22:s22_coils" changed
then
var Tstatus = getThingStatusInfo("modbus:poller:slave22:s22_coils").getStatus()
if (Tstatus.toString == "OFFLINE") {
sendMail([you@email.net](mailto:you@email.net), "Fault report", "Modbus slave22 offline")
}
end
Unfortunately there is not at the moment (OH 2.4) any elegant way to share rule code by using “group” style Thing triggers and finding out which Thing it was.
Write errors
None of the preceding methods will detect a problem writing over Modbus. In most cases, you will be reading from the same slave so a problem will get noticed eventually.
However, write-only slaves are not impossible, or perhaps you have some Very Important data that you need to be sure of, like a fire alarm.
The binding supplies extra channels for each data Thing, as described in the documentation, providing datestamps for last read and write error.
You could create an extra Item linked to one of those, as well as your “real” Item.
Switch my_coil_switch "my output" {channel= "modbus:data:slave22:s22_coils:d03:switch"}
Datetime MB_write_stamp "Last write error" {channel= "modbus:data:slave22:s22_coils:d03:lastWriteError"}
If there is a failure to write my_coil_switch
, the timestamp Item will be changed.
Rule "modbus write fault"
when
Item MB_write_stamp changed
then
sendMail([you@email.net](mailto:you@email.net), "Fault report", "Modbus slave22 important write error")
end
Stale data
If your Modbus slave has an error or fault, note what it says in the binding documentation:
In case of read errors, all data channels are left unchanged
So, your openHAB Items will contain the last valid data (from the last good read poll) indefinitely.
Often, that is desirable. Perhaps the fault is transient, perhaps your slave is rebooting, perhaps that cable will be plugged back in with an “Oops”, and another poll attempt will be successful soon.
But at some point the frozen data will become ‘stale’, and you will not want to continue to use it in your rules. Example, a “stuck” room temperature could result in heating never turning off.
How to avoid stale data
The easiest way is to make use of the expire binding. You may choose for each Item how long to tolerate stale data. To be consistent with other bindings, update the Item to UNDEF
.
Number KitchenT "Kitchen Temp [%d]" {expire="2m, state=UNDEF", channel="modbus:data:sl22:temp:number"}
Regular updates from your Modbus poller keep restarting the expire timeout.
But beware – if you have used the updateUnchangedValuesEveryMillis
parameter to reduce the frequency of updates to your Item, you must take that into account and set expire for some longer time.
Remember to configure your rules to handle UNDEF
states without error. Also, should a slave be broken at system start, Item states will remain as NULL
. Deal with both cases.