Modbus openHAB2 binding available for alpha testing

Hi @ssalonen! Sounds like Finnish lastname :wink: or am I completely on the wrong tracks here?

Anyhow I’m running latest stable Openhabian on RPi3 and modbus server is siemens S7-1200 and here is my findings so far:

Installing through markeplace gives errors

2017-09-04 18:10:00.444 [WARN ] [ace.internal.BindingExtensionHandler] - Installed bundle, but failed to start it: Could not resolve module: org.openhab.binding.modbus [233]
  Unresolved requirement: Import-Package: org.eclipse.jdt.annotation; resolution:="optional"
  Unresolved requirement: Import-Package: org.openhab.io.transport.modbus
2017-09-04 18:10:00.450 [ExtensionEvent            ] - Extension 'market:binding-3528471' has been installed.
2017-09-04 18:10:11.657 [WARN ] [ace.internal.BindingExtensionHandler] - Installed bundle, but failed to start it: Could not resolve module: org.openhab.io.transport.modbus [234]
  Unresolved requirement: Import-Package: gnu.io
2017-09-04 18:10:11.660 [ExtensionEvent            ] - Extension 'market:binding-3528475' has been installed.

PaperUI does not show anything under binding or services configuration.

Next i dropped the binding and transport .jar files to addons folder. Karaf shows they are installed but nothing in logs nor PaperUI. Restarted openhab -->

2017-09-04 19:10:12.592 [ERROR] [org.openhab.binding.modbus          ] - FrameworkEvent ERROR - org.openhab.binding.modbus
org.osgi.framework.BundleException: Could not resolve module: org.openhab.binding.modbus [235]
  Unresolved requirement: Import-Package: org.eclipse.jdt.annotation; resolution:="optional"
  Unresolved requirement: Import-Package: org.openhab.io.transport.modbus
    -> Export-Package: org.openhab.io.transport.modbus; bundle-symbolic-name="org.openhab.io.transport.modbus"; bundle-version="2.2.0.201709031748"; version="0.0.0"
       org.openhab.io.transport.modbus [236]
         Unresolved requirement: Import-Package: gnu.io
	at org.eclipse.osgi.container.Module.start(Module.java:434)[org.eclipse.osgi-3.10.101.v20150820-1432.jar:]
	at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1582)[org.eclipse.osgi-3.10.101.v20150820-1432.jar:]
	at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1561)[org.eclipse.osgi-3.10.101.v20150820-1432.jar:]
	at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1533)[org.eclipse.osgi-3.10.101.v20150820-1432.jar:]
	at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1476)[org.eclipse.osgi-3.10.101.v20150820-1432.jar:]
	at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1)[org.eclipse.osgi-3.10.101.v20150820-1432.jar:]
	at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)[org.eclipse.osgi-3.10.101.v20150820-1432.jar:]
	at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:340)[org.eclipse.osgi-3.10.101.v20150820-1432.jar:]
2017-09-04 19:10:12.611 [ERROR] [org.openhab.io.transport.modbus     ] - FrameworkEvent ERROR - org.openhab.io.transport.modbus
org.osgi.framework.BundleException: Could not resolve module: org.openhab.io.transport.modbus [236]
  Unresolved requirement: Import-Package: gnu.io
	at org.eclipse.osgi.container.Module.start(Module.java:434)[org.eclipse.osgi-3.10.101.v20150820-1432.jar:]
	at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1582)[org.eclipse.osgi-3.10.101.v20150820-1432.jar:]
	at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1561)[org.eclipse.osgi-3.10.101.v20150820-1432.jar:]
	at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1533)[org.eclipse.osgi-3.10.101.v20150820-1432.jar:]
	at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1476)[org.eclipse.osgi-3.10.101.v20150820-1432.jar:]
	at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1)[org.eclipse.osgi-3.10.101.v20150820-1432.jar:]
	at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)[org.eclipse.osgi-3.10.101.v20150820-1432.jar:]
	at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:340)[org.eclipse.osgi-3.10.101.v20150820-1432.jar:]

Stupid question. Does this binding create needed configuration files witch can be modified through ESH Desinger?

Hi!

You are getting the error because you are missing the serial feature. Follow these instructions for installing the serial feature.

I’m not sure how the Oh designer works. You can certainly create configurations using the things file (examples in this thread), or alternatively using the paper ui.

Interesting to find fellow s1200 user! I’m using it as well with my production installation.

P.s. Yeah I’m Finnish indeed :slight_smile:

I’ll give it a new try hopefully tomorrow.

Do you have any readme or wiki that i have missed because this was the first time i heard about installing serial feature?

S7 is quite rare in home automation I think. For now its only controlling few valves, gathering temperatures from 3x logo8 and serving all those through modbus. Planning to use it as kwh counter also. But this might be a topic to continue elsewhere.

There is still some documentation gap for this new experimental version, something that definitely needs to be done before proper release.

I think that features might be installed automatically with final binding version, not sure though…

Got your binding to work after installing that serial transport feature. To say the truth configuring through PaperUi was painful so i used only textual config. Here’s my config files if some other tester gets help from them. These are used to flip on/off Siemens S7-1200 digital outputs Q0.2 -> Q0.5 and read holding register. Are they ok or is there something to change?

modbus.things

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=2, valueType="bit", type="coil" ]
            Thing write writeTCP [ start=2, valueType="bit", type="coil" ]
        }
    	Bridge readwrite DO3 { 
            Thing read readTCP [ start=3, valueType="bit", type="coil" ]
            Thing write writeTCP [ start=3, valueType="bit", type="coil" ]
        }
    	Bridge readwrite DO4 { 
            Thing read readTCP [ start=4, valueType="bit", type="coil" ]
            Thing write writeTCP [ start=4, valueType="bit", type="coil" ]
        }
    	Bridge readwrite DO5 { 
            Thing read readTCP [ start=5, valueType="bit", type="coil" ]
            Thing write writeTCP [ start=5, valueType="bit", type="coil" ]
        }
    }
	Bridge poller holding [ start=0, length=5, refresh=5000, type="holding" ] {
        Bridge readwrite modbusMakuuhuone4 { 
            Thing read mh4 [ start=0, transform="default", trigger="*", valueType="uint16", type="holding" ]
        	}
        Bridge readwrite modbusPukuhuone {
        	Thing read ph [ start=2, transform="default", trigger="*", valueType="uint16", type="holding" ]
        	}
        Bridge readwrite modbusMakuuhuone1 {
        	Thing read mh1 [ start=4, transform="default", trigger="*", valueType="uint16", type="holding" ]
        
        }
    }
}

modbus.items

Switch ModbusTest2            "S7 Coil 2"    { channel="modbus:readwrite:endpointTCP:coils:DO2:switch" }
Switch ModbusTest3            "S7 Coil 3"    { channel="modbus:readwrite:endpointTCP:coils:DO3:switch" }
Switch ModbusTest4            "S7 Coil 4"    { channel="modbus:readwrite:endpointTCP:coils:DO4:switch" }
Switch ModbusTest5            "S7 Coil 5"    { channel="modbus:readwrite:endpointTCP:coils:DO5:switch" }

Number modbusMakuuhuone4	 "Makuuhuone 4 [%.1f °C]"	  <office> { channel="modbus:readwrite:endpointTCP:holding:modbusMakuuhuone4:number" }
Number modbusPukuhuone	 	 "Pukuhuone [%.1f °C]"   <temperature> { channel="modbus:readwrite:endpointTCP:holding:modbusPukuhuone:number" }
Number modbusMakuuhuone1	 "Makuuhuone 1 [%.1f °C]"	 <bedroom> { channel="modbus:readwrite:endpointTCP:holding:modbusMakuuhuone1:number" }

Only thing missing is the right transformation. I need to divide the holding register value by 10 before displaying it. How to use transform=“default” option?

Great to hear! Yes, Siemens s7 1200 maps outputs to coils in modbus.

The things config looks good to me. I think the type parameter is only applicable to write types, the read type gets it from the poller Bridge.

You can indeed use the transforms to divide/multiply values on read/write.

I suggest you try out the JS transform. You might need to install openhab-transformation-javascript feature. You can use transform examples from this post, pasted here for your convenenience:

transform/multiply10.js:

// Wrap everything in a function
(function(i) {
    return Math.round(parseFloat(i, 10) * 10);
})(input)
// input variable contains data passed by openhab

transform/divide10.js:

// Wrap everything in a function
(function(i) {
    return parseFloat(i) / 10;
})(input)
// input variable contains data passed by openhab

Similar to openhab1 modbus binding, where you would say

Number NumberItem "Number [%.1f]" <temperature> {modbus=">[slave1:0:transformation=JS(multiply10.js)],<[slave1:0:transformation=JS(divide10.js)]"}

With the openhab2 modbus binding you would have

Bridge readwrite modbusMakuuhuone4 { 
    Thing read mh4 [ start=0, transform="JS(divide10.js)", trigger="*", valueType="uint16", type="holding" ]
}

You can use transform also with write things, e.g. to multiply openhab commands by 10.

Btw, with Siemens S7 1200 you also have the option to use Siemens data type REAL, and read/write it directly with the binding using valueType=float32. The transformations work equally well of course.

Hope this helps to get you forward!

P.S. Yes I can see the Paper UI is quite much work with so many things… Any ideas how to improve it?

1 Like

That helped really much! Transformations work, all 9 different values are polled from holding register and show in my sitemap. I had the exact same transform script with the old modbus binding but didn’t think it was this obivious to use it same way with this binding.

I have logging on debug and there’s a lot of lines regarding transformations. Seems that they are for datetime and contact channels. You probably know that already but I’ll paste some logs if you want. I my case only switch and number channels are used. To me it seems wasted processing time. How are the channels created? Could some of them be disabled depending on different usage?

In fact I have been thinking about binding configuration. For average user including myself there’s too much things to create and link togerther. For example is it possible to combine connection and poller definitions as one thing? And according to thing configuration it would create channels? I my case one channel would be one holding register or one coil.

But that’s just for PaperUI. Configuration through text files was hard at first but with little help from you I got it working just fine. I think it’s doable for everybody if you just have good wiki or readme files.

PaperUI with simpler config for beginners and textual config for advanced users with advanced modbus devices?

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?