Modbus openHAB2 binding available for alpha testing

Hey,

EDIT: as discussed below, the write and read things have addresses relative to poll start. The new data thing has absolute addresses.

actually the write start should be “absolute” addresses, description from Paper UI:

Address of the first holding register or coils in the write. Use zero based address, e.g. in place of 400001 (first holding register), use the address 0. This address is passed to data frame as is.

So in place of

  Bridge poller coils [ start=2, length=4, refresh=5000, type="coil" ] {
        Bridge readwrite DO2 { 
            Thing read readTCP [ start=2, valueType="bit", type="coil" ]
            Thing write writeTCP [ start=2, valueType="bit", type="coil" ]
        }

you would like to have

  Bridge poller coils [ start=2, length=4, refresh=5000, type="coil" ] {
        Bridge readwrite DO2 { 
            Thing read readTCP [ start=2, valueType="bit", type="coil" ]
            Thing write writeTCP [ start=6, valueType="bit", type="coil" ]
        }

Will respond with longer post for your other comments.

Best,
Sami

1 Like

Now something has went totally over my head and still have misunderstood the whole configuration. When I want to control one coil why should I read and write different coils?

I have to revise the config parameter names to avoid this misunderstanding.

The write things address is absolute while read things start address is relative to polled registers/bits.

For example if you have polled 3 coils starting from 2. Let’s call them c2, c3, c4. The two coils before these are called c0 and c1.

Read thing with start=0 refers to coil c2, start=1 to coil c3

Write thing with start=0 refers to coil c0, start=1 refers to c1.

I have tried to open this quite much in paper ui descriptions but obviously it’s of no use with textual config.

Would it make more sense to use absolute addresses with read as well? If we would implement support for entity numbers (eg 400001 for first holding register), much of confusion would be lost (with the old binding zero based indexing has been confusing for some with not much modbus experience)

The motivation for absolute address with write is that it obviously has no connection to read stuff, and you might actually want to write outside the polled items as well.

That post cleared a lot. Thank you.

I’d vote for absolute adresses for both. As in my posted modbus.thing file. If done like this and it’s allready defined as a readwrite thing, could we get rid of double lines separetly defining read and write?

Entity numbers? No. Setting type=“coil” or type=“holding” takes care of offset. You are right that using only numbers would be less confusion to beginners in modbus but I would suggest them to read and learn more. I have been studying http://www.simplymodbus.ca/faq.htm many times.

Tested your config example just now.

  Bridge poller coils [ start=2, length=4, refresh=5000, type="coil" ] {
        Bridge readwrite DO2 { 
            Thing read readTCP [ start=2, valueType="bit", type="coil" ]
            Thing write writeTCP [ start=6, valueType="bit", type="coil" ]
        }

It didn’t work.

Spent an hour testing different addressing and this is the one that’s working.

Bridge modbus:tcp:endpointTCP [ host="192.168.1.100", port=502, id=2 ] {
    Bridge poller coils [ start=2, length=4, refresh=5000, type="coil" ] {
        Bridge readwrite DO2 { 
            Thing read readTCP [ start=0, valueType="bit" ]
            Thing write writeTCP [ start=0, valueType="bit", type="coil" ]
        }
    	Bridge readwrite DO3 { 
            Thing read readTCP [ start=1, valueType="bit" ]
            Thing write writeTCP [ start=1, valueType="bit", type="coil" ]
        }
    	Bridge readwrite DO4 { 
            Thing read readTCP [ start=2, valueType="bit" ]
            Thing write writeTCP [ start=2, valueType="bit", type="coil" ]
        }
    	Bridge readwrite DO5 { 
            Thing read readTCP [ start=3, valueType="bit" ]
            Thing write writeTCP [ start=3, valueType="bit", type="coil" ]
        }
    }
}

Both read and write are not absolute. Could there be some settings in my S7-1200 that’s messing this up?

I’m so sorry – I should have checked the code before commenting. I was sure I implemented it otherwise.

You are right, currently both read and write are with relative address.

You have good point regarding entity numbers, perhaps we need to require the user to understand the minimum basics of modbus addressing.


I have logging on debug and there’s a lot of lines regarding transformations.

To me it seems wasted processing time.

Yeah there is some additional work going on currently, something I might optimize later once the thing structure and other things “stabilize”. Due to the nature of channels in openhab2, it might be hard though. I should probably have logic not to process the channel transformation on read if the channel is not linked in neither read and readwrite things.

For example is it possible to combine connection and poller definitions as one thing?

I have been thinking this as well but it does not really reduce the number of things considerably. I think typically people have only single connection?

And according to thing configuration it would create channels?

I have not found other way except to provide “all” channels (dimmer, number, switch, contact, etc.), such that user can link it to the item of matching type. From modbus configuration alone it is impossible to say which types are necessary?

Naturally we could decide that only Number items are supported (-> only one channel) but this would mean that user needs to introduce additional rules and proxy items to convert the number to Contact, for example. I have been trying to avoid additional rules & proxy items for the typical use cases.

Alternative idea for the thing structure

I have alternative proposal that perhaps could solve the “too many things” issue.

First a bit of history: currently the thing structure is quite one-to-one mapping with openhab1 binding.

For example, the extended item configuration string format in the old binding maps to single readwrite, with read and write things as children. The read things are < definitions in the old binding, Analogously, write things match to > definitions.

Since we want to support multiple < (read) or > (write) definitions (to support e.g. the Rollershutter example above) it was natural to have multiple things in the new binding as well. Having separate things has the benefit of not introducing a new “mini-language” for configuration strings like in openHAB1. Initially for me the < and > looked a bit cryptic initially but I decided to go with those in the old binding as other bindings used similar syntax as well (http, mqtt).

Instead of thinking how it was with the old binding, I have been trying to think the common (?) use cases with the modbus binding, and use that information as basis of designing the binding from scratch.

Known use cases

  1. Same read/write address, same value type (e.g. reading/writing integer to coil/holding register) – the most common use case for sure
  2. “Set coil to true on any command”, writing to different address than reading, write transformed differently than read. example in old binding
  3. read & write different addresses. In new binding must point to same endpoint, though.
  4. Rollershutter example, mix-match of other use cases
  5. converting different commands to different register values (ON=256, OFF=512)
  6. writing an openHAB command to multiple registers (e.g. turning many devices off)
  7. inverting values on read/write

(anything else?)

As you were already thinking, my proposal is to have single “readwrite” thing (EDIT: this is now called data thing in the latest version. Also check the docs for descriptions of parameters), with the following configuration parameters

  • readAddress Can be empty for write-only.
  • readTransform
  • readValueType
  • writeType
  • writeAddress (absolute address, with writeType=holding, writeAddress=0 would refer to holding register #40001 for example). Keep empty for read-only.
  • writeTransform
  • writeValueType
  • writeMultipleEvenWithSingleRegister

Essentially you would have the current thing configurations from read and write things, with the exception of missing trigger. Transformation would take the role of trigger.

I realized that the need to have multiple read (< in openhab1) or write (> in openhab2) can be worked around by using transformations. You can branch the logic based on incoming command, same as with trigger parameter in openHAB1. This would not solve the issue of writing to different register/coil based on command (e.g. roller shutter example). I have proposal below to solve that using “general purpose write”.

This is how the above use cases would be solved

  1. readAddress equals writeAddress, readValueType equals writeValueType
  2. transformation returning always 1
  3. just configure read index and write index
  4. more advanced case – would be solved by “mini binding” or “general purpose write” approaches
  5. solvable e.g. using JS transformation and switch-case
  6. more advanced case – would be solved by “general purpose write” approaches
  7. solvable by JS transformation

general purpose write For complex scenarios we could allow complex output from transformation.
We could represent the raw modbus writes using the JSON syntax:
[ {... write instruction ...}, {... write instruction ...}, ... ]

where each {... write instruction ...} is a JSON object describing a modbus write request.

For example, if the transformation returns the following JSON

[
   {"functionCode":5, "index":0, "value":1}, 
   {"functionCode":6, "index":0, "value":256},
   {"functionCode":16, "index":1, "value":[512, 256]} 
]

EDIT: the JSON keys turned slightly different in the final implementation: functionCode, address, and value.

the binding would execute following modbus write requests

  1. set coil 0 to on, using FC5 (write single coil)
  2. set holding register 0 to 256, using FC6 (write single holding register)
  3. set holding register 1 and 2 to 16-bit values 512, 256, respectively, using FC16 (write multiple holding registers), in a single modbus request.

One can also suppress all writes using empty json list [].

We SHOULD support simple transformations as well (outputting just value), and leave the JSON syntax for advanced cases only (assuming the advanced cases are much more rare).

mini bindings Provide special use-cases as mini bindings

For example, we could introduce rollershutter binding (built on top modbus binding) which would introduce rollershutter-readwrite thing with the following configuration

  • up_down_write_index : in what (coil/holding) index to write UP and DOWN commands
  • up_down_type : coil or holding. What FC is used to write UP/DOWN
  • up_value: value to write with UP, e.g. 1
  • down_value: value to write with DOWN, e.g. -1
  • move_stop_write_index : in what (coil/holding) index to write MOVE and STOP commands
  • move_stop_write_type : coil or holding. What FC is used to write MOVE/STOP
  • move_value: value to write with UP, e.g. 1
  • stop_value: value to write with DOWN, e.g. 0
  • position_index : from what index position is read

There are other ways to encode rollershutter using modbus. These different versions can be incorporated in the binding as the need arises.

Note that the kind of rollershutter mini binding could be implemented also with “general purpose write” described above.

more examples

“Simple case” (use case 0)

Bridge modbus:tcp:endpointTCP [ host="192.168.1.100", port=502, id=2 ] {
    Bridge poller coils [ start=2, length=4, refresh=5000, type="coil" ] {
        Bridge readwrite DO2 { 
            Thing read readTCP [ start=0, valueType="bit" ]
            Thing write writeTCP [ start=0, valueType="bit" ]
        }
    	Bridge readwrite DO3 { 
            Thing read readTCP [ start=1, valueType="bit" ]
            Thing write writeTCP [ start=1, valueType="bit" ]
        }
    }
	Bridge poller holding [ start=0, length=5, refresh=5000, type="holding" ] {
        Bridge readwrite modbusMakuuhuone4 { 
            Thing read mh4 [ start=0, transform="default", trigger="*", valueType="uint16" ]
        	}
        Bridge readwrite modbusPukuhuone {
        	Thing read ph [ start=2, transform="default", trigger="*", valueType="uint16" ]
        	}
        Bridge readwrite modbusMakuuhuone1 {
        	Thing read mh1 [ start=4, transform="default", trigger="*", valueType="uint16" ]
        
        }
    }
}

would transform to roughly something like below

Bridge modbus:tcp:endpointTCP [ host="192.168.1.100", port=502, id=2 ] {
    Bridge poller coils [ start=2, length=4, refresh=5000, type="coil" ] {
        Bridge readwrite DO2 [ readAddress=2, readValueType="bit", readType="coil", writeAddress=2, writeValueType="bit", writeType="coil" ]
        Bridge readwrite DO3 [ readAddress=3, readValueType="bit", readType="coil", writeAddress=3, writeValueType="bit", writeType="coil" ]
    }
	Bridge poller holding [ start=0, length=5, refresh=5000, type="holding" ] {
        Bridge readwrite modbusMakuuhuone4 [ readAddress=0, readValueType="uint16" ]
        Bridge readwrite modbusPukuhuone [ readAddress=2, readValueType="uint16" ]
        Bridge readwrite modbusMakuuhuone1 [ readAddress=4, readValueType="uint16" ]
    }
}

writing an openHAB command to multiple registers (use case 5)

In openhab1 binding

Switch Light "Roller1" (ALL) 
{modbus=">[slave2:0:trigger=UP,transformation=256],>[slave2:0:trigger=STOP,transformation=512],>[slave2:0:trigger=DOWN,transformation=512],>[slave2:1:trigger=UP,transformation=512],>[slave2:1:trigger=STOP,transformation=512],>[slave2:1:trigger=DOWN,transformation=256]"}

(plus some modbus.cfg)

With the new proposed config:

Bridge modbus:tcp:endpointTCP [ host="192.168.1.100", port=502, id=2 ] {
    Bridge poller coils [ start=0, length=4, refresh=0, type="holding" ] { // refresh=0 -> no polling
        Bridge readwrite Roller1 [ writeTransform="JS(myroller.js)", writeValueType="uint", writeType="holding" ]
    }
}

with the following transformation myroller.js (assuming we are writing holding registers)

// Wrap everything in a function
(function(cmd) {
	var cmdToValue = {"UP":256, "STOP":512, "DOWN":512, "UP":512, "STOP":512, "DOWN":256};
	var cmdToAddress = {"UP":0, "STOP":0, "DOWN":0, "UP":1, "STOP":1, "DOWN":1};

	var value = cmdToValue[cmd];
	var address = cmdToAddress[cmd];
	if(value === undefined || address === undefined) {
		// unknown command, do not write anything
		return "[]";
	} else {
		return [
			"[",
	   			"{\"functionCode\":6,  \"index\":" + address.toString() + ", \"value\":" + value +  "}",
			"]",
		].join("\n")
	}
})(input)
// input variable contains data passed by openhab

The transformation transforms UP to

[ {"functionCode":6,  "index":1, "value":512} ]

and DOWN to

[ {"functionCode":6,  "index":1, "value":256} ]

Hopefully this makes sense, it’s always a bit hard to put word to early ideas. I think the above approach would be much more streamlined way of configuring the binding for simple and typical use cases but still allow enough flexibility for some of the “harder” cases.

We could also get rid of the child->parent thing interaction (e.g. read things affect channels of readwrite things), which has felt like a wrong design choice. It seems somehow counterintuitive.

Best
Sami

Hi @ssalonen,

I’m sorry for the late reply but I must have missed the update you’ve posted!

This indeed fixes the issue. Thanks a lot!

Greetings,
Frederic

First of all don’t be sorry. This is a binding in in alpha state for testing and i’m a tester :smile:

You have good point regarding entity numbers, perhaps we need to require the user to understand the minimum basics of modbus addressing.

This is absolutely true. Modbus isn’t the easiest to understand and this can’t be made “idiot proof” so requiring basic knowledge is more than ok.


Yeah there is some additional work going on currently, something I might optimize later once the thing structure and other things “stabilize”. Due to the nature of channels in openhab2, it might be hard though. I should probably have logic not to process the channel transformation on read if the channel is not linked in neither read and readwrite things.

Sounds goo to me.


Hopefully this makes sense, it’s always a bit hard to put word to early ideas.

I’ve been reading on binding development for last couple of days and I think I got better idea of things, bridges and channels. I’m starting to agree with you about needing this much things and channels. Just the nature of modbus and making this binding to serve wide range of users and use cases. All in all your alternative idea seem good and justified. Especially I like your “Simple case” example as it is my case. That approach simplifies textual config and would say that in won’t get any easier. Or maybe few more config options: readAddress and writeAddress combined as rwAddress?


Last but not least that mini bindig and transformation idea about breaking advanced functionality into smaller and optional parts. I like it. And just as you said it:

… for simple and typical use cases but still allow enough flexibility for some of the “harder” cases.

1 Like

Hi @ssalonen,

Once more thanks a lot for your help on the serial connection!
Since i’m still busy with experiments on how to do the final implementation of the modbus communication in OpenHAB, I’m now doing a small experiment with the use a TCP connection.

I encounter a rather small problem but worth mentioning in my opinion.
Here you can find my current config (which should be more or less final): https://pastebin.com/LfxJt734

The problem I encounter occurs at startup.
As you can see in the config I keep the connection open for 5 minutes via reconnectAfterMillis.
But at startup it looks like the modbus binding doesn’t use this parameter since it opens and closes every 10 seconds 7 new connections to the slave (because of the 7 pollers I’ve defined that refresh every 10 seconds).

Now, there seems to be a simple “fix” for this. In my case I save the things file again, this causes all poll tasks to be unregistered (see info/error messages bellow), and after that everything is going fine and only one connection remains.

These info/error messages appear after saving the things file again:

2017-09-11 16:23:46.879 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Unregistering regular poll task PollTaskImpl@5364bc3f[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@535cbf28[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4027,length=8],endpoint=ModbusTCPSlaveEndpoint@7fff2661[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1587] (interrupting if necessary)
2017-09-11 16:23:46.880 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Unregistering regular poll task PollTaskImpl@6a04e204[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@459a1708[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4021,length=5],endpoint=ModbusTCPSlaveEndpoint@7fff2661[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1586] (interrupting if necessary)
2017-09-11 16:23:46.880 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Unregistering regular poll task PollTaskImpl@1865a804[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@6990e825[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4015,length=5],endpoint=ModbusTCPSlaveEndpoint@7fff2661[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1585] (interrupting if necessary)
2017-09-11 16:23:46.881 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Unregistering regular poll task PollTaskImpl@7d5b2382[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@393927aa[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4000,length=12],endpoint=ModbusTCPSlaveEndpoint@7fff2661[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1584] (interrupting if necessary)
2017-09-11 16:23:46.881 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Unregistering regular poll task PollTaskImpl@222c6581[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@3ff7ac94[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4036,length=9],endpoint=ModbusTCPSlaveEndpoint@7fff2661[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1588] (interrupting if necessary)
2017-09-11 16:23:46.881 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Poll task PollTaskImpl@6a04e204[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@459a1708[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4021,length=5],endpoint=ModbusTCPSlaveEndpoint@7fff2661[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1586] canceled
2017-09-11 16:23:46.881 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Poll task PollTaskImpl@222c6581[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@3ff7ac94[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4036,length=9],endpoint=ModbusTCPSlaveEndpoint@7fff2661[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1588] canceled
2017-09-11 16:23:46.882 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Poll task PollTaskImpl@5364bc3f[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@535cbf28[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4027,length=8],endpoint=ModbusTCPSlaveEndpoint@7fff2661[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1587] canceled
2017-09-11 16:23:46.882 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Unregistering regular poll task PollTaskImpl@6e4afca9[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@7b7d943f[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4046,length=5],endpoint=ModbusTCPSlaveEndpoint@7fff2661[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1589] (interrupting if necessary)
2017-09-11 16:23:46.882 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Poll task PollTaskImpl@7d5b2382[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@393927aa[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4000,length=12],endpoint=ModbusTCPSlaveEndpoint@7fff2661[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1584] canceled
2017-09-11 16:23:46.883 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Unregistering regular poll task PollTaskImpl@7c6b98ea[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@a18561c[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4052,length=5],endpoint=ModbusTCPSlaveEndpoint@7fff2661[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe158a] (interrupting if necessary)
2017-09-11 16:23:46.883 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Poll task PollTaskImpl@1865a804[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@6990e825[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4015,length=5],endpoint=ModbusTCPSlaveEndpoint@7fff2661[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1585] canceled
2017-09-11 16:23:46.883 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Poll task PollTaskImpl@7c6b98ea[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@a18561c[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4052,length=5],endpoint=ModbusTCPSlaveEndpoint@7fff2661[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe158a] canceled
2017-09-11 16:23:46.884 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Unregistering regular poll task PollTaskImpl@6825c617[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@3671cfc7[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4015,length=5],endpoint=ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1585] (interrupting if necessary)
2017-09-11 16:23:46.884 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Poll task PollTaskImpl@6825c617[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@3671cfc7[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4015,length=5],endpoint=ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1585] canceled
2017-09-11 16:23:46.885 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Unregistering regular poll task PollTaskImpl@7b7dbe00[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@78698d96[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4021,length=5],endpoint=ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1586] (interrupting if necessary)
2017-09-11 16:23:46.885 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Poll task PollTaskImpl@7b7dbe00[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@78698d96[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4021,length=5],endpoint=ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1586] canceled
2017-09-11 16:23:46.885 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Unregistering regular poll task PollTaskImpl@3c8b1d88[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@3ac1e856[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4027,length=8],endpoint=ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1587] (interrupting if necessary)
2017-09-11 16:23:46.885 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Unregistering regular poll task PollTaskImpl@6dde750c[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@2b8d13de[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4036,length=9],endpoint=ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1588] (interrupting if necessary)
2017-09-11 16:23:46.885 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Poll task PollTaskImpl@3c8b1d88[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@3ac1e856[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4027,length=8],endpoint=ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1587] canceled
2017-09-11 16:23:46.886 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Unregistering regular poll task PollTaskImpl@52ad96cf[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@362ea64f[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4052,length=5],endpoint=ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe158a] (interrupting if necessary)
2017-09-11 16:23:46.886 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Poll task PollTaskImpl@52ad96cf[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@362ea64f[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4052,length=5],endpoint=ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe158a] canceled
2017-09-11 16:23:46.885 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Poll task PollTaskImpl@6dde750c[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@2b8d13de[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4036,length=9],endpoint=ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1588] canceled
2017-09-11 16:23:46.887 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Poll task PollTaskImpl@6e4afca9[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@7b7d943f[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4046,length=5],endpoint=ModbusTCPSlaveEndpoint@7fff2661[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1589] canceled
2017-09-11 16:23:46.884 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Unregistering regular poll task PollTaskImpl@a1c3d4[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@69b6c4b5[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4000,length=12],endpoint=ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1584] (interrupting if necessary)
2017-09-11 16:23:46.887 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Poll task PollTaskImpl@a1c3d4[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@69b6c4b5[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4000,length=12],endpoint=ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1584] canceled
2017-09-11 16:23:46.888 [WARN ] [odbus.handler.ModbusReadThingHandler] - Poller 'Poll definition' of ReadWrite bridge 'Modbus read-write definition' of ReadThing 'Modbus read definition' has no poll task. Aborting config validation
2017-09-11 16:23:46.889 [WARN ] [odbus.handler.ModbusReadThingHandler] - Poller 'Poll definition' of ReadWrite bridge 'Modbus read-write definition' of ReadThing 'Modbus read definition' has no poll task. Aborting config validation
2017-09-11 16:23:46.890 [WARN ] [rt.modbus.internal.ModbusManagerImpl] - Error getting a new connection for endpoint ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502]. Error was: java.lang.InterruptedException null
2017-09-11 16:23:46.890 [WARN ] [rt.modbus.internal.ModbusManagerImpl] - Not connected to endpoint ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502] -- aborting request ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@69b6c4b5[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4000,length=12]
2017-09-11 16:23:46.901 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Unregistering regular poll task PollTaskImpl@42b0da59[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@4c010eb8[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4000,length=12],endpoint=ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1584] (interrupting if necessary)
2017-09-11 16:23:46.891 [WARN ] [rt.modbus.internal.ModbusManagerImpl] - Poll task was unregistered -- not executing/proceeding with the poll
org.openhab.io.transport.modbus.internal.ModbusManagerImpl$PollTaskUnregistered: Poll task PollTaskImpl@a1c3d4[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@69b6c4b5[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4000,length=12],endpoint=ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1584] is unregistered
	at org.openhab.io.transport.modbus.internal.ModbusManagerImpl.verifyTaskIsRegistered(ModbusManagerImpl.java:400) ~[?:?]
	at org.openhab.io.transport.modbus.internal.ModbusManagerImpl.executeOneTimePoll(ModbusManagerImpl.java:433) ~[?:?]
	at org.openhab.io.transport.modbus.internal.ModbusManagerImpl.lambda$11(ModbusManagerImpl.java:500) ~[?:?]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:?]
	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [?:?]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) [?:?]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [?:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:?]
	at java.lang.Thread.run(Thread.java:748) [?:?]
2017-09-11 16:23:46.902 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Poll task PollTaskImpl@42b0da59[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@4c010eb8[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4000,length=12],endpoint=ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1584] canceled
2017-09-11 16:23:46.900 [WARN ] [rt.modbus.internal.ModbusManagerImpl] - Error getting a new connection for endpoint ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502]. Error was: java.lang.InterruptedException null
2017-09-11 16:23:46.903 [WARN ] [rt.modbus.internal.ModbusManagerImpl] - Not connected to endpoint ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502] -- aborting request ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@2b8d13de[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4036,length=9]
2017-09-11 16:23:46.899 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Unregistering regular poll task PollTaskImpl@3928ef77[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@3bb977ca[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4046,length=5],endpoint=ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1589] (interrupting if necessary)
2017-09-11 16:23:46.905 [INFO ] [rt.modbus.internal.ModbusManagerImpl] - Poll task PollTaskImpl@3928ef77[request=ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@3bb977ca[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4046,length=5],endpoint=ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502],callback=org.openhab.binding.modbus.handler.ModbusPollerThingHandlerImpl$ReadCallbackDelegator@5dbe1589] canceled
2017-09-11 16:23:46.906 [WARN ] [.handler.ModbusReadWriteThingHandler] - Read write thing handler got read error: org.openhab.io.transport.modbus.internal.ModbusConnectionException Error connecting to endpoint ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502]
2017-09-11 16:23:46.897 [WARN ] [odbus.handler.ModbusReadThingHandler] - Poller 'Poll definition' of ReadWrite bridge 'Modbus read-write definition' of ReadThing 'Modbus read definition' has no poll task. Aborting config validation
2017-09-11 16:23:46.909 [ERROR] [odbus.handler.ModbusReadThingHandler] - Thing Modbus read definition received read error: org.openhab.io.transport.modbus.internal.ModbusConnectionException Error connecting to endpoint ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502]. Stack trace follows for unexpected errors.
org.openhab.io.transport.modbus.internal.ModbusConnectionException: Error connecting to endpoint ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502]
	at org.openhab.io.transport.modbus.internal.ModbusManagerImpl.lambda$5(ModbusManagerImpl.java:436) ~[?:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:?]
	at java.lang.Thread.run(Thread.java:748) [?:?]
2017-09-11 16:23:46.913 [WARN ] [.handler.ModbusReadWriteThingHandler] - Read write thing handler got read error: org.openhab.io.transport.modbus.internal.ModbusConnectionException Error connecting to endpoint ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502]
2017-09-11 16:23:46.915 [ERROR] [rt.modbus.internal.ModbusManagerImpl] - Error when executing read request (ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@78698d96[slaveId=11,functionCode=READ_MULTIPLE_REGISTERS,start=4021,length=5]): net.wimpi.modbus.ModbusIOException Thread acquiring lock was interrupted.
2017-09-11 16:23:46.914 [ERROR] [odbus.handler.ModbusReadThingHandler] - Thing Modbus read definition received read error: org.openhab.io.transport.modbus.internal.ModbusConnectionException Error connecting to endpoint ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502]. Stack trace follows for unexpected errors.
org.openhab.io.transport.modbus.internal.ModbusConnectionException: Error connecting to endpoint ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502]
	at org.openhab.io.transport.modbus.internal.ModbusManagerImpl.lambda$5(ModbusManagerImpl.java:436) ~[?:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:?]
	at java.lang.Thread.run(Thread.java:748) [?:?]
2017-09-11 16:23:46.918 [WARN ] [.handler.ModbusReadWriteThingHandler] - Read write thing handler got read error: org.openhab.io.transport.modbus.internal.ModbusConnectionException Error connecting to endpoint ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502]
2017-09-11 16:23:46.918 [ERROR] [odbus.handler.ModbusReadThingHandler] - Thing Modbus read definition received read error: org.openhab.io.transport.modbus.internal.ModbusConnectionException Error connecting to endpoint ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502]. Stack trace follows for unexpected errors.
org.openhab.io.transport.modbus.internal.ModbusConnectionException: Error connecting to endpoint ModbusTCPSlaveEndpoint@7b30305b[address=192.168.50.113,port=502]
	at org.openhab.io.transport.modbus.internal.ModbusManagerImpl.lambda$5(ModbusManagerImpl.java:436) ~[?:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:?]
	at java.lang.Thread.run(Thread.java:748) [?:?]

Another important note is that sometimes, at startup I also see this unregistering appearing at startup. In this case everything is fine from startup and I don’t need to save the things file again to fix it.

Question: is there a reason why the connection should be closed after every poll operation or after the timeout defined by reconnectAfterMillis? Isn’t it also fine to leave the connection permanently open?

Thanks!

Greetings,
Frederic

Hi,

thanks for reporting this. I think you might be seeing some sort of transient since things are initializing / changing and thus it might just dispose / re-create some of things “automatically”.

It would help you can repeat the experiment with verbose logging, also include debug level logs from openhab itself, if possible.

Need to try this out also once we have thing structure/hierachy stabilized.

Question: is there a reason why the connection should be closed after every poll operation or after the timeout defined by reconnectAfterMillis? Isn’t it also fine to leave the connection permanently open?

You can probably find some old discussions regarding this but long story short, keeping connection open for a long time is a problem for some users as some modbus slaves support only one outbound connection. This means that other “clients” would be blocked when openHAB accesses the slave.

As with most parameters with the binding, the default setting is conservative and closes connection after every poll (connection time is minimized).

Also, closing connection might be considered more safe/robust by some, as the everything is flushed/cleared between modbus transactions.

Hi,

I’ve uploaded 3 log different log files from different tests via WeTransfer.
Here is the download link: https://we.tl/vAERN610gD

So I did 3 runs with different results:

  • openhab_all_ok.log: here everything went fine, so after startup, only one connection to the slave was created.
  • openhab_not_ok.log: after startup, every 10 seconds, 7 connections are created and closed to the slave.
  • openhab_ok_after_save_at_47-40.log: in this log I had the same effect as the log before (7 connections every 10 seconds) but I saved the things file again during operation which resulted in the expected behavior. This reloading is seen at this point in the log file:
2017-09-12 09:47:35.966 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'modbus.things'

I’ve enabled trace logging on both the binding and the transport service.
In the log configuration I’ve put the root logger to debug as also the smarthome and openhab logging.

I hope these log files can give an indication on what is going on.

Greetings,
Frederic

1 Like

Hi @ssalonen,

Have you found the time to download the files?
I’ve uploaded them with a free account so they will be deleted in 13 hours from now.
If not, let me know so I can upload them again :slight_smile:

Greetings,
Frederic

Thanks, I have now downloaded the files but have not yet time to look into the actual logs.

Really good to have this, I can at least see quite much verbose information on things being created by openHAB so this should help understanding the issue a bit more

Sami

EDIT: hey, in order to debug the logs I need to confirm whether the timestamps in the logs are local time or UTC? Can you double-check this please?

Hi,

The timestamps are local time.

Thanks!

Greetings,
Frederic

What is local time over your server? :smiley:

My time zone is UTC+1 (Belgium)

Thanks!

The logs have been really useful. What I can say that there seems to be inverted boolean logic in the code that determines whether to disconnect the connection or not – this happens after every transaction.

In fact, it seems that connection is disconnected now always, in both the ok and “not ok” logs.

I will post updated version during the next few days and let’s see how that works out.

1 Like

Hi All

Sorry if this is off-topic.

The new modbus binding, will it support Uint64/int64 by any chance?

Hi

No that’s not off-topic at all! Currently it does not but it is certainly pretty straight forward to implement.

The new binding supports reading of bit, int8, and uint8 from registers. Read/write is supported with int16, uint16, int32, uint32, float32 (+ word swapped versions of the 32bit types).

int64, Uint64 would really be a nice thing, as more and more new devices starts using it :slight_smile:

Hope you guys will consider implement it.