2 or more modbus slaves

Hi, I am using openhab2-addons modbus binding from marketplace. it works fine with 1 modbus slave. But I need to talk with more than 1 slave. I tried create thnigs configuration - but unsuccessufully last week.

//Bridge modbus:serial:endpointMOXA [port="/dev/ttyr01",baud=9600,id=11,dataBits=8,parity="none",stopBits="1.0",encoding="rtu"] {
//	 Bridge poller holdingsREG1[ start=0, length=6, refresh=4000, type="holding"] {
//		Thing data temp1 [ readStart="0", readValueType="int16", readTransform="JS(divide10.js)" ]
//		Thing data temp2 [ readStart="1", readValueType="int16", readTransform="JS(divide10.js)" ]
//		Thing data temp3 [ readStart="2", readValueType="int16", readTransform="JS(divide10.js)" ]
//		Thing data temp4 [ readStart="3", readValueType="int16", readTransform="JS(divide10.js)" ]
//		Thing data temp5 [ readStart="4", readValueType="int16", readTransform="JS(divide10.js)" ]
//		Thing data temp6 [ readStart="5", readValueType="int16", readTransform="JS(divide10.js)" ]
//	}
//
//}
Bridge modbus:serial:endpointMOXA2 [port="/dev/ttyr01",baud=9600,id=10,dataBits=8,parity="none",stopBits="1.0",encoding="rtu"] {
	 Bridge poller holdingsREG1[ start=0, length=8, refresh=4000, type="holding"] {
		Thing data teplota1 [ readStart="0", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota2 [ readStart="1", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota3 [ readStart="2", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota4 [ readStart="3", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota5 [ readStart="4", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota6 [ readStart="5", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data tlakBMP  [ readStart="6", readValueType="int16" ]
		Thing data teplotaBMP[ readStart="7", readValueType="int16", readTransform="JS(divide10.js)"]
	}
	
}

I don`t know , where is mistake. If anybody has any experiences with this, please help mi with it.
Thanx Martin

it is no my situation. I use only modbus binding from market place from Sami Salonen (Modbus openHAB2 binding available for alpha testing). it works fine for 1 slave. In my config - I must REM rows of second slave - because it is not functionally.

Have anybody config for more than 1 slave ?

Thanx Martin

I think you need to give each of your pollers a unique name e.g. holdingsMOXAreg1 , holdingsMOXA2reg1

Maybe, I did it a week ago. I think - I have same errors - access serial port by 2 pollers .
If I will see operational config ,than I will write my config.
Thanx

it is solved.
this is right config .things

Bridge modbus:serial:endpointMOXA [port="/dev/ttyr01",baud=9600,id=11,dataBits=8,parity="none",stopBits="1.0",encoding="rtu"] {
	 Bridge poller holdingsREG[ start=0, length=6, refresh=4000, type="holding"] {
		Thing data temp1 [ readStart="0", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data temp2 [ readStart="1", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data temp3 [ readStart="2", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data temp4 [ readStart="3", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data temp5 [ readStart="4", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data temp6 [ readStart="5", readValueType="int16", readTransform="JS(divide10.js)" ]
	}
}

Bridge modbus:serial:endpointMOXA2 [port="/dev/ttyr01",baud=9600,id=10,dataBits=8,parity="none",stopBits="1.0",encoding="rtu"] {
	 Bridge poller holdingsREG2[ start=0, length=8, refresh=4000, type="holding"] {
		Thing data teplota1 [ readStart="0", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota2 [ readStart="1", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota3 [ readStart="2", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota4 [ readStart="3", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota5 [ readStart="4", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota6 [ readStart="5", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data tlakBMP  [ readStart="6", readValueType="int16" ]
		Thing data teplotaBMP[ readStart="7", readValueType="int16", readTransform="JS(divide10.js)"]
	}
	
}

this is right .items

Group teploty1
Number prvy  (teploty1) { channel="modbus:data:endpointMOXA:holdingsREG:temp1:number" }
Number druhy (teploty1) { channel="modbus:data:endpointMOXA:holdingsREG:temp2:number" }
Number treti (teploty1) { channel="modbus:data:endpointMOXA:holdingsREG:temp3:number" }

Group teploty2
Number stvrty (teploty2) { channel="modbus:data:endpointMOXA:holdingsREG:temp4:number" }
Number piaty (teploty2) { channel="modbus:data:endpointMOXA:holdingsREG:temp5:number" }
Number siesty (teploty2) { channel="modbus:data:endpointMOXA:holdingsREG:temp6:number" }

Group teploty3
Number prvy2  (teploty3) { channel="modbus:data:endpointMOXA2:holdingsREG2:teplota1:number" }
Number druhy2 (teploty3) { channel="modbus:data:endpointMOXA2:holdingsREG2:teplota2:number" }
Number treti2 (teploty3) { channel="modbus:data:endpointMOXA2:holdingsREG2:teplota3:number" }

Group teploty4
Number stvrty2 (teploty4) { channel="modbus:data:endpointMOXA2:holdingsREG2:teplota4:number" }
Number piaty2  (teploty4) { channel="modbus:data:endpointMOXA2:holdingsREG2:teplota5:number" }
Number siesty2 (teploty4) { channel="modbus:data:endpointMOXA2:holdingsREG2:teplota6:number" }

Group tlaky
Number tlak		(tlaky) { channel="modbus:data:endpointMOXA2:holdingsREG2:tlakBMP:number" }
Number teplotaP 	(tlaky) { channel="modbus:data:endpointMOXA2:holdingsREG2:teplotaBMP:number" }

this is example of work 2 slaves on modbus bus. My HW configuration is : Raspberry Pi3 B - virtual serial port MOXA - nport MOXA 5230 - two arduinos with address 10 and 11.
thanx to all for help.

Martin

1 Like

Do you think giving the poller-Things a unique name was the fix?
It is not the obvious thing to do, when they belong to different endpoint-Things.
We might need to clarify this in the readme docs?

2 weeks ago i did many changes, maybe raspberry and karaf was fool from it. maybe I have to restart after each change… but now it is clear.
this is the result of yesterday. I cleared syntax with Sami S. I modified my config .things, and .items yesterday after chat with Sami. You can see my config before and after. it is just all.

Martin

Hi guys

Have a close to problem above, but with 2 or more devices on the same port


    // hall.things
    Bridge modbus:serial:hall "controller" @ "hall" [ port="/dev/ttyUSB_modbus_static", id=2, baud=115200, stopBits="1.0", parity="none", dataBits=8, encoding="rtu", receiveTimeoutMillis=200 ] {

    Bridge poller relaysAndButtons [ start=0, length=16, refresh=300, type="coil" ] {
        Thing data mainLightWindowSide      [ readStart="0", writeStart="0", readValueType="bit", writeValueType="bit", writeType="coil" ]
        ...

    // kitchen.things
    Bridge modbus:serial:kitchen "controller" @ "kitchen" [ port="/dev/ttyUSB_modbus_static", id=1, baud=115200, stopBits="1.0", parity="none", dataBits=8, encoding="rtu", receiveTimeoutMillis=200 ] {

        Bridge poller relaysAndButtons [ start=0, length=16, refresh=300, type="coil" ] {
            Thing data mainLight        [ readStart="0", writeStart="0", readValueType="bit", writeValueType="bit", writeType="coil" ]
    ...

The only difference in configs (and devices, of course) is id=2 and id=1

When I put single file to things folder - it works well, but with both - I can see errors at log

13:19:54.494 [ERROR] [ternal.handler.ModbusDataThingHandler] - Thing modbus:data:kitchen:relaysAndButtons:radiatorFlow 'Modbus data' had ModbusSlaveIOExceptionImpl error on read: ModbusSlaveIOException(cause=ModbusIOException, EOF=false, message='I/O exception: IOException Error reading response (EOF)', cause2=null)

Enlarging receiveTimeoutMillis and refresh (what is not a good idea because, I need to use light switching by button press) does not help

How can I fix that ?

As discussed earlier, you must give each of your pollers some unique name.

Bridge poller relaysAndButtons2 [ ...

Bridge poller relaysAndButtons1 [ ...

There is little wired for me, because of nested things config structure and uniq link to thing at items config.

With different names, looks like working as expected - thanks!

@ssalonen the error message resulting is a bit cryptic; is there any easy way to improve binding validation ?

I don’t think it can be improved, openhab core is parsing the configurations from things. Perhaps in this case wrong configuration gets picked up, and as a side effect io errors appear? With io errors there is not much else to log down

I actually thought as well that it is enough that fully qualified thing id would be unique but apparently problems appear already with two things with same id in same file.

1 Like

This is quite interesting, I wanted to try out the following configuration:

Bridge modbus:tcp:endpointMOXA [] {
	 Bridge poller holdingsREG1[ start=5, length=6, refresh=4000, type="holding"] {
		Thing data temp1 [ readStart="5", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data temp2 [ readStart="6", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data temp3 [ readStart="7", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data temp4 [ readStart="8", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data temp5 [ readStart="9", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data temp6 [ readStart="10", readValueType="int16", readTransform="JS(divide10.js)" ]
	}

}
Bridge modbus:tcp:endpointMOXA2 [] {
	 Bridge poller holdingsREG1[ start=0, length=8, refresh=4000, type="holding"] {
		Thing data teplota1 [ readStart="0", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota2 [ readStart="1", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota3 [ readStart="2", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota4 [ readStart="3", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota5 [ readStart="4", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota6 [ readStart="5", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data tlakBMP  [ readStart="6", readValueType="int16" ]
		Thing data teplotaBMP[ readStart="7", readValueType="int16", readTransform="JS(divide10.js)"]
	}
	
}

Notice how the two pollers have the same name, while the top level bridges have different name.

All the things come up ONLINE without any issues. I have diagslave running in the background (at localhost:502, default destination for the tcp things), and can confirm correct polls arriving in:

validateMasterIpAddr: accepting connection from 127.0.0.1
Slave   1: readHoldingRegisters from 1, 8 references
..
validateMasterIpAddr: accepting connection from 127.0.0.1
Slave   1: readHoldingRegisters from 6, 6 references

Now, this makes me wonder what is different in above configurations…?

I suppose there would quite some difficulty in detecting “duplicate” name/ID, as this essentially what happens as a normal event when (re)loading an edited version of a Thing.

Maybe it’s the serial workings that have a problem with duplicate Thng id and throw the “EOF” error.

Testing this more, I can see that there is something wrong the way things file is read, even with unique IDs. Perhaps detecting changes in thing files and/or commenting is causing problems for openHAB? Looks like there is some sort of caching happening

For example,

  1. Start with configuration
Bridge modbus:tcp:endpointMOXA1 [] {
	 Bridge poller holdingsREG1[ start=5, length=6, refresh=4000, type="holding"] {
		Thing data temp1 [ readStart="5", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data temp2 [ readStart="6", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data temp3 [ readStart="7", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data temp4 [ readStart="8", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data temp5 [ readStart="9", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data temp6 [ readStart="10", readValueType="int16", readTransform="JS(divide10.js)" ]
	}
}
Bridge modbus:tcp:endpointMOXA2 [] {
	 Bridge poller holdingsREG2[ start=0, length=8, refresh=4000, type="holding"] {
		Thing data teplota1 [ readStart="0", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota2 [ readStart="1", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota3 [ readStart="2", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota4 [ readStart="3", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota5 [ readStart="4", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota6 [ readStart="5", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data tlakBMP  [ readStart="6", readValueType="int16" ]
		Thing data teplotaBMP[ readStart="7", readValueType="int16", readTransform="JS(divide10.js)"]
	}
	
}

Polling go as expected.

  1. Comment first tcp thing and all children of it
// Bridge modbus:tcp:endpointMOXA1 [] {
// 	 Bridge poller holdingsREG1[ start=5, length=6, refresh=4000, type="holding"] {
// 		Thing data temp1 [ readStart="5", readValueType="int16", readTransform="JS(divide10.js)" ]
// 		Thing data temp2 [ readStart="6", readValueType="int16", readTransform="JS(divide10.js)" ]
// 		Thing data temp3 [ readStart="7", readValueType="int16", readTransform="JS(divide10.js)" ]
// 		Thing data temp4 [ readStart="8", readValueType="int16", readTransform="JS(divide10.js)" ]
// 		Thing data temp5 [ readStart="9", readValueType="int16", readTransform="JS(divide10.js)" ]
// 		Thing data temp6 [ readStart="10", readValueType="int16", readTransform="JS(divide10.js)" ]
// 	}
// }
Bridge modbus:tcp:endpointMOXA2 [] {
	 Bridge poller holdingsREG2[ start=0, length=8, refresh=4000, type="holding"] {
		Thing data teplota1 [ readStart="0", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota2 [ readStart="1", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota3 [ readStart="2", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota4 [ readStart="3", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota5 [ readStart="4", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data teplota6 [ readStart="5", readValueType="int16", readTransform="JS(divide10.js)" ]
		Thing data tlakBMP  [ readStart="6", readValueType="int16" ]
		Thing data teplotaBMP[ readStart="7", readValueType="int16", readTransform="JS(divide10.js)"]
	}
	
}

Polling gets disabled as expected
3. Uncomment the first tcp thing (-> same config as in the first step). Original things do not come back
4. Restart openHAB -> all things are present. Alternatively, the things re-appear if you rename endpointMOXA1 to something new, e.g. endpointMOXA1New.

Perhaps this symptom (Thing remove/reintroduce in flight failure) is another manifestation of this issue

Thinking about the duplicate Thing name/id issue … if the parser treats that like an edit it might all go down a similar path (remove/reintroduce “updated” version) and end up here where the Thing doesn’t work.

I’ve added more detailed thoughts to the issue, but experimented with PaperUI - it rejects attempts to create any poller with a duplicate ‘thing ID’, even if it belongs to a different tcp/serial bridge.

EDIT - PaperUI also rejects duplicate data thing IDs.
You cannot do this, for example

Bridge modbus:tcp:endpointMOXA1 [] {
	 Bridge poller holdingsREG1[ start=5, length=6, refresh=4000, type="holding"] {
		Thing data temp1 [ readStart="5", readValueType="int16", readTransform="JS(divide10.js)" ]
	}
}
Bridge modbus:tcp:endpointMOXA2 [] {
	 Bridge poller holdingsREG2[ start=0, length=8, refresh=4000, type="holding"] {
		Thing data temp1 [ readStart="0", readValueType="int16", readTransform="JS(divide10.js)" ]

I begin to think PaperUI is right (and it’ll be up to us to configure xxx.things files carefully)