Modbus openHAB2 binding available for alpha testing

I think you are using the old binding. Can you please open a new post since this thread is about the new version?

Short story is that with old binding that is a known limitation, see the bolded disclaimer in the docs http://docs.openhab.org/addons/bindings/modbus1/readme.html#write

The old binding writes the number as 16bit integer, which is probably not what you want. The slave returns error code, probably because we are trying to write single register and not two.

Sorry just read about the limitation - the new binding is that backwards compatible?

It is not backwards compatible. Actually the point is to introduce things and channels and therefore it cannot be backwards compatible.

The new Binding just works perfect :slight_smile:

Finally able to apply setpoint for heating in my house.

Do you see any problems running the old 1.10 Binding Parallel with the new one - while migrating all existing code ?

Almost finished migrating - This is just great, love it - way better that christmas eve :slight_smile:

It may be late in the day to consider this, but some other bindings use a form of XML to hold device specific info. I know little about this, but am thinking of it as a ‘template’ system.

One might imagine a flexible, configurable - and therefore complicated - Modbus2 binding. With a set of pre-configured device specific XML templates or models, that can be selected from by user. They would need to configure basic info (e.g. address, ID) since discovery ain’t ever going to work in Modbus.

This is way over my head but looks interesting

Thanks for this idea.

Yeah, perhaps we will have device specific “templates” at some point but it seems that coding will be necessary, and it’s not possible to “template”/create things.

One of the targets with this new development was to separate modbus protocol (transport) from the binding. I think it is now much more separated, and basically with relative ease it should be possible to a new binding that uses the modbus protocol (modbus transport) and introduces special things for particular use cases.

The link you pasted is a basic pattern to make things things configurable, something that is already done in this new thing.

I’m pretty far actually with the alternative thing structure described above, will publish that for testing and let’s see how that feels like.

Hi

I’m trying to do a simple invert, it was working with the old binding - i’m trying to figure out what I did wrong.
JSONPath Transformation is installed

[Things]

Bridge poller K104_BDD [ start=3422, length=3, refresh=5000, type=“input” ] {
Bridge readwrite Window_GF_Bryggers_Door {
Thing read I3422 [ start=2, transform=“JS(mbinvert.js)”, trigger="", valueType=“uint16”, type=“input” ]
Thing write I3422 [ start=2, transform=“JS(mbinvert.js)”, trigger="
", valueType=“uint16”, type=“input” ]

[Item]

Contact Window_GF_Bryggers_Door “Fordør [MAP(da.map):%s]” (GF_Bryggers, Windows)
{ channel=“modbus:readwrite:endpointSmarthouse:K104_BDD:Window_GF_Bryggers_Door:contact” }

[mbinvert.js]

(function(i) {
var t = i ; // allow Undefined to pass through
if (i == ‘OPEN’) {
t = ‘CLOSED’ ;
} else if (i == ‘CLOSED’) {
t = ‘OPEN’ ;
}
return t ; // return a string
})(input)

It seems that your post is malformed, please format the code as described here

Some other comments

  • trigger is empty (or just code format issue?), matches only empty commands. Check paperUI for more information. Use wildcard * to match all
  • type is only applicable to write
  • use verbose logging to understand how the transform now works. Some specifics might be slightly different…

Sami

Hi

I have changed the trigger to * match all, removed the “Thing write” (Only need the status) and removed type from “Thing read”

My invert function still gives me the wrong state, Ill try logging in verbose to see whats happening

// function to invert Modbus binary states
// input variable i contains data passed by OpenHAB binding
(function(i) {
    var t = i ;      // allow Undefined to pass through
    if (i == 'OPEN') {
    	t = 'CLOSED' ;
    } else if (i == 'CLOSED') {
    	t = 'OPEN' ;
    }
    return t ;      // return a string 
})(input)

Any luck?

I think the transformation input has changed a little from the old binding. On read, the transformation gets the numeric data as input. With coils or discrete inputs this means 0 or 1. On write, the transformation gets the command as is.

I hope that verbose logs would tell more what is inputted to the transformation.

YES :slight_smile: As you explained, the new binding gets the inputs as 0 or 1.

I changed the transformation function to this, and it works perfect.

// function to invert Modbus binary states
// input variable i contains data passed by OpenHAB binding
(function(i) {
    var t = i ;      // allow Undefined to pass through
    if (i == '1') {
    	t = 'CLOSED' ;
    } else if (i == '0') {
    	t = 'OPEN' ;
    }
    return t ;      // return a string 
})(input)

Would you actually need slightly a different transformation for write transformation? Or you can generalize what you have to both cases.

In this case I only need to read the state of a holding register (Door/Window) contact. The holding register is in my case inverted 0=open 1=closed.

Did I understand your question correct?

OK, if you are just reading then there is no issue.

In this post you did have

Thing write I3422 [ start=2, transform=“JS(mbinvert.js)”, trigger="", valueType=“uint16”, type=“input” ]

Btw, you are reading input registers, not holding registers. Hope that is what you are after.

If you do not need the write, you can actually just remove the write thing.

Yes in this scenario i’m only reading, and just did a Cleanup and removed the write thing.

Can you explain how I enable “Write Multiple Holding Registers”, I don’t use PaperUI?

I assume you mean that you want to use FC16 (write multiple holding registers) even when writing single register. You can set “writeMultipleEvenWithSingleRegister” parameter to true in the write thing.

Note that when writing multiple registers (e.g. int32), function code 16 is always used.

One other thing to note, I will hopefully soon publish a new version of this experimental binding which has the streamlined thing structure as discussed in this thread. The idea is to get rid of read, write and readwrite; and replace them with a single thing called “data”.

I will not remove the old things right away, to allow testing with both.

Great looking forward to try out the new version :slight_smile:

I’m trying to convert the last part of my old code to the new binding, but having alot of trouble with a Modbus device that needs to have WriteMultiple=true - I did what you wrote and I can see in Paper-UI it’s enabled for the wanted Write thing.

I do get this when I try to write to the device:

17:14:35.308 [ERROR] [ort.modbus.internal.ModbusManagerImpl] - Error when executing write request (org.openhab.io.transport.modbus.ModbusWriteRegisterRequestBlueprintImpl@b11b43a): net.wimpi.modbus.ModbusSlaveException Error Code = 1
17:14:35.309 [ERROR] [odbus.handler.ModbusWriteThingHandler] - Unsuccessful write: net.wimpi.modbus.ModbusSlaveException Error Code = 1

My .Thing config

Bridge modbus:tcp:endpointNilan [ host="192.168.100.30", port=502, id=30 ] {
Bridge poller Nilan_Holding_Control [ start=1000, length=8, refresh=5000, type="holding" ] {
        Bridge readwrite Nilan_Control_Type { 
	         Thing read NilanH1000 [ start=0, transform="default", trigger="*", valueType="uint16" ]  
		 Thing write NilanH1000 [ start=0, transform="default", trigger="*", valueType="uint16", type="holding", writeMultipleEvenWithSingleRegister="true" ]  
		 }
	Bridge readwrite Nilan_Control_RunSet { 
		 Thing read NilanH1001 [ start=1, transform="default", trigger="*", valueType="uint16" ]    
		 Thing write NilanH1001 [ start=1, transform="default", trigger="*", valueType="uint16", type="holding", writeMultipleEvenWithSingleRegister="true" ]		 
		 }
	Bridge readwrite Nilan_Control_ModeSet {
		 Thing read NilanH1002 [ start=2, transform="default", trigger="*", valueType="uint16" ]  
		 Thing write NilanH1002 [ start=2, transform="default", trigger="*", valueType="uint16", type="holding", writeMultipleEvenWithSingleRegister="true" ]  
		 }	
	Bridge readwrite Nilan_Control_VentSet {
		 Thing read NilanH1003 [ start=3, transform="default", trigger="*", valueType="uint16" ]  
		 Thing write NilanH1003 [ start=3, transform="default", trigger="*", valueType="uint16", type="holding", writeMultipleEvenWithSingleRegister="true" ]  
	  	 }
	Bridge readwrite Nilan_Control_TempSet {
        	 Thing read NilanH1004 [ start=4, transform="JS(divide100.js)", trigger="*", valueType="uint16" ] 
		 Thing write NilanH1004 [ start=4, transform="JS(multiply100.js)", trigger="*", valueType="uint16", type="holding", writeMultipleEvenWithSingleRegister="true" ]   
		 }
	Bridge readwrite Nilan_Control_ServiceMode { 
		 Thing read NilanH1005 [ start=5, transform="default", trigger="*", valueType="uint16" ] 
		 Thing write NilanH1005 [ start=5, transform="default", trigger="*", valueType="uint16", type="holding", writeMultipleEvenWithSingleRegister="true" ]  
		 }
	Bridge readwrite Nilan_Control_ServicePct {
		 Thing read NilanH1006 [ start=6, transform="default", trigger="*", valueType="uint16" ] 
		 Thing write NilanH1006 [ start=6, transform="default", trigger="*", valueType="uint16", type="holding", writeMultipleEvenWithSingleRegister="true" ]   
		 }	
	Bridge readwrite Nilan_Control_Preset {
		 Thing read NilanH1007 [ start=7, transform="default", trigger="*", valueType="uint16" ] 
		 Thing write NilanH1007 [ start=7, transform="default", trigger="*", valueType="uint16", type="holding", writeMultipleEvenWithSingleRegister="true" ]   
	  	 }	
	

  }

}

Do you have a clue of what i’m doing wrong here?

Best Nanna

Hmm… According to this error code 1 means that the function code is illegal. So the slave is responding with this error code…

Could you share your old binding config just to double check and correlate for differences?

Perhaps also you can enable more verbose log, trace level for net.wimpi.modbus, org.openhab.io.transport.modbus and org.openhab.binding.modbus. (log:set TRACE org.openhab.io.transport.modbus for example if I recall correctly) and see if that reveals more.

Really appreciate the effort of testing this out. Huge Thanks!

Best
Sami

I’m the one thanking YOU for your effort, making the most important binding ‘Modbus’.

I have included the relevant part of the modbus.cfg and the binding.

tcp.nilan_holding_control.connection=192.168.100.30:502:60:0:0:3:100
tcp.nilan_holding_control.id=30
tcp.nilan_holding_control.start=1000
tcp.nilan_holding_control.length=8
tcp.nilan_holding_control.type=holding

The Binding

Number Nilan_Control_Type             "Machine type select [%d]"                                             	       (gNilan) {modbus="nilan_holding_control:0"}
Switch Nilan_Control_RunSet           "User on / off select"                                           <switch>        (gNilan) {modbus="nilan_holding_control:1"}
Number Nilan_Control_ModeSet          "User operation mode select [MAP(nilan_control_modeact.map):%s]" <settings>      (gNilan) {modbus="nilan_holding_control:2"}
Number Nilan_Control_VentSet          "User ventilation step select [MAP(nilan_ventset.map):%s]"       <fan_ceiling>   (gNilan) {modbus="nilan_holding_control:3"}
Number Nilan_Control_TempSet          "User temperature setpoint [%.1f °C]"                            <temperature>   (gNilan) {modbus="<[nilan_holding_control:4:transformation=JS(divide100.js)], >[nilan_holding_control:4:transformation=JS(multiply100.js)]"}
Number Nilan_Control_ServiceMode      "Service mode select [MAP(nilan_control_servicemode.map):%s]"    <lock>          (gNilan) {modbus="nilan_holding_control:5"}
Number Nilan_Control_ServicePct       "Service mode capacity [%.1f %%]"                                                (gNilan) {modbus="nilan_holding_control:6"} 
Number Nilan_Control_Preset           "Request preset to factory [%d]"                                                 (gNilan) {modbus="nilan_holding_control:7"}

Nanna