Modbus openHAB2 binding available for alpha testing

Ah. Behaviour with expire binding is of future interest to me. This one would have caught me out.

Currently in OH1 I have many coil outputs working like pushbuttons; rule commands ON and after a while expire sets back OFF again. Saves a whole lot of rules and timers.
Some at least I could set up as modbus write-only, that should allow same behaviour using expire.

I guess philosophically I’m subverting the original purpose of the expire binding as a dead man’s switch. It’s convenient in this (ab)use, but not essential as other means are available.
It does not feel like an issue that needs to be addressed by breaking OH guidelines (barring performance effects !!).

I assume a failed write-only slave would be detectable via “last error” channel? Which represents an improvement over using expire for fault detecting purpose.

Thanks for the detailed explanation! I just moved from expire to a rule that turns them off for now.

I’ll take a look.
Max

1 Like

Current situation:

The Schneider M221 PLC (see config attached) controls my lights. I’ve switches on the inputs of the PLC. Some of the outputs direct activates my lights and some outputs control some 5V relays.
I’ve had help programming the PLC, so my knowledge about PLC and Modbus is very poor.

OH 2.2 is running on an micro PC with Win10.

Also i’ve some z-wave devices up and running (dimmers and multi-sensor)

Problem:

I want to keep using my plc to control the lighting in case OH stops running.
OH has to control the outputs of the PLC and also use the inputs.
The ouput of the plc can be triggered by a switch or an sensor (Rules)
Actions on OH can be triggered by input of the PLC (switch) (all active lights off)
I like to combine the functionality of both OH and PLC

I’ve tried an setup with modbus tools slave simulator on other laptop and succeeded in read/write coils and read digital inputs.

Only if I change to the M221 plc nothing happens (with correct settings). Does anyone has some experience with Schneider PLC and modbus?

I’m using the binding of Sami Salonen and tried to program via PaperUI.

@Jakke17, I think you are more likely to find help by opening a new thread regarding this topic. Sounds like you have sorted out the binding but having trouble with the plc.

What do you think?

Best
Sami

@ssalonen, I’ve already tried twice but no reaction. The binding works fine but indeed the M221 plc doesn’t react to the binding. I will try again

Best Jan

[SOLVED] I’m trying to do write to FC16 using the binding but can’t make it work.
I’ve tried sending this raw string from a console program: hex:1E1003EA0001020002+CRC which sets the control parameter to the requested value.

Then I setup my modbus.things file, I made a unique write data thing:

Bridge modbus:serial:nilanCombiPolar [ port="/dev/ttyUSB-48503", baud=19200, id=30, stopBits="1", parity="even",dataBits=8, echo=false, encoding="rtu", flowControlIn="none", flowControlOut="none", receiveTimeoutMillis=1500 ] {
	Bridge poller controlOutput[ start=1000, length=8, refresh=60000, type="holding" ] {
		Thing data outputType   [ readStart="1000", readValueType="int16" ]
		Thing data outputRunSet [ readStart="1001", readValueType="int16" ]
		Thing data outputModeSet  [ readStart="1002", readValueType="int16"]
		Thing data outputVentSet   [ readStart="1003", readValueType="int16" ]
		Thing data outputTempSet  [ readStart="1004", readValueType="int16" ]
		Thing data outputServiceMode  [ readStart="1005", readValueType="int16" ]
		Thing data outputServicePct   [ readStart="1006", readValueType="int16" ]
		Thing data outputPreset  [ readStart="1007", readValueType="int16" ]
	}
	Thing data writeOutputModeSet [ writeStart="1002", writeValueType="int16", writeType="holding", writeMultipleEvenWithSingleRegisterOrCoil=true ]
}
Number ventilationModeSet "Mode set [%d]" { channel="modbus:data:nilanCombiPolar:controlOutput:outputModeSet:number" }
Number ventilationWriteModeSet "Mode write set [%d]" { channel="modbus:data:nilanCombiPolar:writeOutputModeSet:number" }

I then set the ventilationWriteModeSet to 2 using the REST API and the log says that value has changed but nothing happens to the modbus slave when I check its control panel. No errors in the openhab log either. I have no problem reading data.
What is wrong?

Seems the modbus binding doesn’t react to changes in the REST API, when I use the Paper UI it changes.

Regarding REST not having an impact: I recommend posting a new general thread about this. It sounds like it might be a general issue (or even intended feature) with things configured via file.

Would you like to post the solution for your previous issue with writing? Perhaps it helps others

Best
Sami

Trying new binding (2.3) yesterday and i have observed problem with things in paper ui - they didnt appear after put them in modbus.things file.

Do you have all the required addons installed? Serial feature, modbus transport and modbus binding.

You can verify bundles from openhab console and using bundle:list command.

Please post logs for further diagnostics.

When testing my rule to set ventilationWriteModeSet I used the REST API as I thougth it was the easiest ui. I assume the result I got was expected.

I did learn than I need to use ventilationWriteModeSet.sendCommand(2) instead of ventilationWriteModeSet.postUpdate(2) in the rule to make it send a Modbus command value of 2.

Still learning openhab…

Thanks for the clarifiication. That is how it should work indeed (regarding your rule example).

There is a whole section regarding state vs commands in openHAB docs if I remember correctly.

Perhaps you have wrong REST call? (analogous to your sendCommand vs postUpdate finding)

Hi,

I have two questions:

  1. Is there a mechanism to ensure consistency of data across registers if they are related? The way I understand the documentation, I will have to collect the values from 10 separate data things if I am doing a read starting at address 1 with length 20. I know that all of them are related and only consistent within the full read operation, which means whenever I analyse the data, the full set of 10 data things need to be taken into account. Is there a trigger that tells me all 10 data things are populated completely? Can I be sure that it is locked until I transfer it into e.g. a variable from within a rule? Is there potentially a way to grab the “list of registers” (directly from read step 1.)?
  2. Is there an issue if I use the same base address with multiple length values for FC16 transfers?

Thanks!

@jotpehenn Hi!

  1. This is a really good question! Due to the nature of openHAB itself, I’m not sure you acertain that data access is “synchronized” or “locked”.

Currently there is no “list of raw register values” (nor “list of parsed states”) exposed directly, although I have been waiting for this request. I can see that it can serve some specific use cases (e.g. more complex interpretation of the data).

I think this completely doable, so might be worth thinking to add it at some point.

Come to think of this, it is actually somewhat generic requirement. Consider e.g. sensor (e.g. zwave) where different measurements are related. How to ensure you are getting a consistent snapshot of values? I am not aware of any generic mechanism in openHAB, but who knows if there is one.

  1. Do you really mean FC16 which is “Write multiple holding registers”? What do you mean by “length values”?

Best,
Sami

Thanks for your fast response.

I would appreaciate this feature, let me know if there is news, I can serve as guinea pig if you need one.

That is also a good point. Maybe there is something along the properties of items and groups that could be used?

I was thinking whether it would be possible to define a write only holding register something like:

Thing data holdinguniversalwrite [writeMultipleEvenWithSingleRegisterOrCoil=“true”, writeTransform=“JS(universalwrite.js)” ]

and then use universalwrite.js to “dynamically” generate the JSON to basically write anything anywhere in any quantity, i.e the data thing is not bound to a specific address, data type or how many registers are written in one go.

Is this assumption correct, or am I misunderstanding something big time?

I suppose one approach might be to have access to some kind of “poll complete” flag, which is only set after the binding has updated OH Items with register values read from Modbus. And presumably unset before commencing a read poll. A property of each Bridge poller?

Seems clonky though. With correct configuration, all registers will get read in a single Modbus transfer. The only asynchronous part is where the binding updates related OH Items one by one. I reckon a simple delay of a couple of milliseconds would allow that to complete (after triggering a rule from any Item update).

Alternatively, figure out which will be the last Item to get updated in each poll, and trigger the rule that demands synchronizing off of that Item?
I think if the binding’s update behaviour is predictable, we already have the tools to ensure a block of data is synchronized.

(@jotpehenn:slight_smile: I would appreaciate this feature, let me know if there is news, I can serve as guinea pig if you need one.

(@rossko57:slight_smile: Alternatively, figure out which will be the last Item to get updated in each poll, and trigger the rule that demands synchronizing off of that Item?
I think if the binding’s update behaviour is predictable, we already have the tools to ensure a block of data is synchronized.

I checked the code – the current order is “arbitrary”/unspecified but probably the same every poll. Not sure if the order would be different over time (when openHAB is rebooted). In other words, it’s all error-prone implementation details…

Following from @rossko57 clunky idea, I guess it would be easier if the poller would have the the lastReadSuccess and lastReadError as channels. You could then use these to process the data. However, you would have to assume that data would not be changed in the meanwhile while you are iterating over the individual pieces of data.

Will think about this…

For now I’m not proceeding with implementation, would like to get the pull request through, and then introduce incremental improvements and new features. So don’t hold your breath…

(@jotpehenn:slight_smile: … then use universalwrite.js to “dynamically” generate the JSON to basically write anything anywhere in any quantity, i.e the data thing is not bound to a specific address, data type or how many registers are written in one go.

This is possible using “Advanced write using JSON”, quoting README:

There are some more advanced use cases which need more control how the command is converted to set of bits or requests. Due to this reason, one can return a special JSON output from the transformation (step 3). The JSON directly specifies the write requests to send to Modbus slave.

You should even specify the writeMultipleEvenWithSingleRegisterOrCoil since the transform output specifies the exact function code that will be used.

Please also find the Rollershutter config example as practical tutorial how to use the feature.

Ah, knocks that plan down. I presume this (binding updating multiple Items) is a fairly rapid process though, happening before/while update events are put on the bus? A short delay at the beginning of a rule triggered from an Item update should surely allow ‘associated’ Items to all settle down.

There may be other benefits in having those poller properties available, dunno what they might be yet. A user needing synchronised data is going to have to manage polling carefully, to ensure processing completes in between polls.

Hi, I have avr device with modbus implementing by MBS38. It works fine. it works with mbpoll and openHAB ver2.3.0 market bindings - PAPER UI.
but I try to use .items . things .sitemap files. with using this files my data are unavalaible - in BASIC UI. Can anybody look at this files? is there any mistake?
thanx Martin

file .things
//poller thing -lenght, type are required
Bridge modbus:serial:endpointMOXA[port=“COM7”,baud=9600,id=11,dataBits=8,
parity=“none”,stopBits=“1”,encoding=“rtu”] {
Bridge poller holdingsREG[ start=0, length=6, refresh=2000, type=“holding”] {
Thing data temp1 [ readStart=“0”, readValueType=“int16” ]
Thing data temp2 [ readStart=“1”, readValueType=“int16” ]
Thing data temp3 [ readStart=“2”, readValueType=“int16” ]
Thing data temp4 [ readStart=“3”, readValueType=“int16” ]
Thing data temp5 [ readStart=“4”, readValueType=“int16” ]
Thing data temp6 [ readStart=“5”, readValueType=“int16” ]
}

}

file .items
//itemtype itemname “labeltext [stateformat]” //<iconname{channel=“modbus:data:nameOfBridge:nameOfPoller:nameOfVariable:number”
Number S1 “Temperature [%d]” {channel=“modbus:data:endpointMOXA:holdingsREG:temp1:number”}
Number S2 “Temperature [%d]” {channel=“modbus:data:endpointMOXA:holdingsREG:temp2:number”}
Number S3 “Temperature [%d]” {channel=“modbus:data:endpointMOXA:holdingsREG:temp3:number”}
Number S4 “Temperature [%d]” {channel=“modbus:data:endpointMOXA:holdingsREG:temp4:number”}
Number S5 “Temperature [%d]” {channel=“modbus:data:endpointMOXA:holdingsREG:temp5:number”}
Number S6 “Temperature [%d]” {channel=“modbus:data:endpointMOXA:holdingsREG:temp6:number”}

file .sitemap
sitemap default label=“My house” {
Frame label=“Temperatures” {
//Text item=datum
Text item=vychodS
Text item=zapadS
Text item=S1 label=“Sensor1[%d °C]” icon=“temperature”
Text item=S2 label=“Sensor2[%d °C]” icon=“temperature”
Text item=S3 label=“Sensor3[%d °C]” icon=“temperature”
Text item=S4 label=“Sensor4[%d °C]” icon=“temperature”
Text item=S5 label=“Sensor5[%d °C]” icon=“temperature”
Text item=S6 label=“Sensor6[%d °C]” icon=“temperature”
}

}