Back to Openhab - newbie questions regarding Modbus configuration and transformation

Openhabian4.3.5
Raspberry 3B 1GB ram

Hi everyone, I’m returning to using openHAB in a new installation after many years (I think 8-9). I have limited knowledge of the platform dating back to version 2.1, which I still happily use to manage the home automation of my small residence.
Now I find myself facing a new small “challenge”. Obviously, a lot (almost everything) has changed in terms of the interface in the new version 4.3 compared to the previous 2.1 I’m using.
Therefore, I would like to ask you for some suggestions on how to get reacquainted with openHAB.

The current “challenge” is to interface 28 thermostats via Modbus, extracting 14 registers from each one. As a test platform, I was thinking of using a Raspberry Pi 3B with 1 GB of RAM.
Do you think this will be sufficient?

The configuration of the 28 thermostats will be quite repetitive: for each one, I will always have to extract the same 14 registers. I was thinking of using text files to setup things and items.
Is this configuration method still supported?

I spent Sunday studying the Modbus documentation on the website, and since this is the first time I’m using this add-on, I have many doubts that I hope you can help me solve them.
The thermostat manufacturer’s documentation states that all parameters are managed as HOLDING REGISTERs, while it doesn’t provide much detail regarding Value Types.

305.things

Bridge modbus:serial:305Room [port="/dev/ttyUSB0",baud=9600,id=35,dataBits=8,parity="none",stopBits="1.0",encoding="rtu", receiveTimeoutMillis=3000] {
    Bridge poller 305RoomSetup 		[ start=0, length=13, refresh=600, type="holding" ] {
        Thing data 305RoomTemp					[ readStart="2", readValueType="int16" ]
        Thing data 305GuestSetpoint             [ readStart="3", readValueType="int16" ]
		Thing data 305ONOFF 		            [ readStart="12.1", readValueType="bit", writeStart="12.1", writeValueType="bit", writeType="holding" ]
        Thing data 305FancoilMode 		        [ readStart="12.2", readValueType="bit", writeStart="12.2", writeValueType="bit", writeType="holding" ]
	}
	Bridge poller 305RoomStatus 	[ start=124, length=22, refresh=600, type="holding" ] {
		Thing data 305WaterTemp					[ readStart="124", readValueType="int16" ]
        Thing data 305WindowsStatus             [ readStart="144", readValueType="int16" ]
		Thing data 305GuestStatus             	[ readStart="145", readValueType="int16" ]
	}
	Bridge poller 305RoomDiagnostic [ start=186, length=4, refresh=600, type="holding" ] {
		Thing data 305CoolingValve				[ readStart="186", readValueType="int16" ]
        Thing data 305HeatingValve              [ readStart="187", readValueType="int16" ]
		Thing data 305FanONOFF             		[ readStart="188", readValueType="int16" ]
		Thing data 305FanPower             		[ readStart="189", readValueType="int16" ]
	}
	
	/// write only modbus registry
	Thing data 305MasterSetpoint 	[ writeStart="7", writeValueType="int16", writeType="holding" ]
	Thing data 305CentroSetpoint 	[ writeStart="9", writeValueType="int16", writeType="holding" ]
	Thing data 305RangeSetpoint 	[ writeStart="10", writeValueType="int16", writeType="holding" ]

305.items

Number	Modbus_Temp_305					"Temperatura camera 305 [%.1f °C]"		{ channel="modbus:data:305Room:305RoomSetup:305RoomTemp:number", autoupdate="false"[ profile="modbus:gainOffset", gain="0.1", pre-gain-offset="0" ] }
	Number	Modbus_GuestSetpoint_305		"Setpoint camera 305 [%.1f °C]"			{ channel="modbus:data:305Room:305RoomSetup:305GuestSetpoint:number", autoupdate="false"[ profile="modbus:gainOffset", gain="0.1", pre-gain-offset="0" ] }
	Switch	Modbus_ONOFF_305				"Accensione fancoil 305 [%d]"			{ channel="modbus:data:305Room:305RoomSetup:305ONOFF:switch", autoupdate="false" }
	Switch	Modbus_FancoilMode_305			"Stagione fancoil 305 [%d]"				{ channel="modbus:data:305Room:305RoomSetup:305FancoilMode:switch", autoupdate="false" }
	
	Number	Modbus_WaterTemp_305			"Temp. batteria fancoil 305 [%.1f °C]"			{ channel="modbus:data:305Room:305RoomStatus:305WaterTemp:number", autoupdate="false"[ profile="modbus:gainOffset", gain="0.1", pre-gain-offset="0" ] }
	Contact Modbus_WindowsStatus_305		"Finestra camera 305 [%d]" 						{ channel="modbus:data:305Room:305RoomStatus:305WindowsStatus:contact", autoupdate="false" }
	Contact Modbus_GuestStatus_305			"Presenza cliente camera 305 [%d]" 				{ channel="modbus:data:305Room:305RoomStatus:305GuestStatus:contact", autoupdate="false" }
	
	Contact Modbus_CoolingValve_305			"Valvola condizionamento fancoil 305 [%d]" 		{ channel="modbus:data:305Room:305RoomDiagnostic:305CoolingValve:contact", autoupdate="false" }
	Contact Modbus_HeatingValve_305			"Valvola riscaldamento fancoil 305 [%d]" 		{ channel="modbus:data:305Room:305RoomDiagnostic:305HeatingValve:contact", autoupdate="false" }
	Contact Modbus_FanONOFF_305				"Motore fancoil 305 [%d]" 						{ channel="modbus:data:305Room:305RoomDiagnostic:305FanONOFF:contact", autoupdate="false" }
	Number  Modbus_FanPower_305				"Velocita fancoil 305 [%.1f V]" 				{ channel="modbus:data:305Room:305RoomDiagnostic:305FanPower:number", autoupdate="false"[ profile="modbus:gainOffset", gain="0.1", pre-gain-offset="0" ] }
	
	Number Modbus_MasterSetpoint_305        "Setpoint master camera 305 [%.1f °C]"    { channel="modbus:data:305Room:305MasterSetpoint:number"[ profile="modbus:gainOffset", gain="0.1", pre-gain-offset="0" ] }
	Number Modbus_CentroSetpoint_305        "CentroTemp master camera 305 [%.1f °C]"  { channel="modbus:data:305Room:305CentroSetpoint:number"[ profile="modbus:gainOffset", gain="0.1", pre-gain-offset="0" ] }
	Number Modbus_RangeSetpoint_305       "Range Temp. ammesso camera 305 [%.1f °C]"  { channel="modbus:data:305Room:305RangeSetpoint:number"[ profile="modbus:gainOffset", gain="0.1", pre-gain-offset="0" ] }
  1. Can write-only registers be inserted directly as children of the Modbus Bridge, as in my configuration (things file)?
  2. Is the bridge poller necessary only to cyclically update the value of “read” registers? In that case, would you recommend disabling the autoupdate of the “automagically” polled values, in the items file?
  3. modbus:gainOffset.
    The thermostats return the temperature without decimal notation, so for example, the number 200 is equivalent to 20.0 degrees Celsius. The documentation mentions the possibility of using the “modbus:gainOffset” profile to make these numbers “readable” correctly.
    Does the profile also work automatically for writing back that values?
    For example, if I wanted to change the setpoint temperature to 25.0 degrees, would it then be automatically converted to the raw value 250 before writing it back to the thermostat?
  4. For some items, like the state of a valve, the thermostat will return a binary value 0 (OPEN) / 1 (CLOSED).
Bridge poller 305RoomDiagnostic [ start=186, length=4, refresh=600, type="holding" ] {
		Thing data 305CoolingValve				[ readStart="186", readValueType="int16" ]
Contact Modbus_CoolingValve_305			"Valvola condizionamento fancoil 305 [%d]" 		{ channel="modbus:data:305Room:305RoomDiagnostic:305CoolingValve:contact", autoupdate="false" }

I read in the documentation that to manage these values inside a “Contact” item, I should perform a transformation by specifying the “readTransform” parameter in the things file. However, I didn’t understand if in my case, the “default” readTransform is sufficient and will be automatically applied, or if I still need to specify it inside the things file.
Maybe in my case a simple MAP transformation would be sufficient. Someone can point me out how to use it with modbus?

Thanks in advance for your help and sorry for the long post full of questions, but i would like to be sure to understand well the modbus logic of the openhab addons before to try everything “on the field”

The single best thing you can do is to go through the Getting Started Tutorial. You can still set up and use OH like you did back in 2.1 (except support for 1.x bindings were dropped in 3.0 so you must use Things instead of configuring a binding connection straight on the Item). But Getting Started shows all the new stuff and how it fits in with the old stuff. It’s also the only really user’s guide, with the rest of the docs being reference.

The users who have the hardest time with new versions of OH are old time users of OH 2 who skip Getting Started.

Probably not but you could get lucky. A 3b really had too little ram for most deployments.

Absolutely and it’s not going anywhere.

There are techniques you can use to make it less repetitive in the UI too but using things files is perfectly acceptable.

I don’t use modbus so someone more knowledgeable will have to help out with those questions.

I believe so.

Probably the easiest thing to do is set one Thing up in the UI and get it working. Than you can look at the code tab of the Thing for the names of all the parameters you’ll need to put into your .things file. The file and in the UI all the properties share the same name so it’s not much to translate from one to the other.

This can make getting that first thing to work a little easier

In OH 5, you’ll be able to see the actual .things file syntax in the code tab. You’ll also be able to define your things in yaml format too.

Thank you very much! @rlkoshak
I think I will use the Raspberry 3B as a testing platform to regain familiarity with OpenHAB, then probably i will switch to a more performing 4GB unit.
Honestly, I had forgotten how much attention needs to be paid to the correct formatting of text files in order to achieve a working configuration.
For example, to make the

gainOffset

parameter work correctly, i had to correct my code as follow:

Number  Modbus_FanPower_305				"Velocita fancoil 305 [%.1f V]" 				{ channel="autoupdate="false", modbus:data:305Room:305RoomDiagnostic:305FanPower:number" [ profile="modbus:gainOffset", gain="0.1", pre-gain-offset="0" ] }

So all the small details matters :slight_smile:
Thank you also for the advice to use the UI as a starting point to acquire the correct syntax for textual configuration. I hadn’t noticed this new function in the UI, and it is truly interesting. In short, there is still a long road ahead of me.

That’s a major reason why I only use the UI now. There are far fewer syntax errors to make since you don’t have to get every tiny little detail right. That alone more than makes up for most of the disadvantages of using the UI. And there are tips and techniques to make working in the UI easier. You do not need to point and click everything.

1 Like

maybe helpful for you as a first step here an example of a things definition with read and write. You find the data types either in the docs of the device or you have to try it out

Bridge poller Gw2 "Goodwe 2" [ start=47120, length=8, refresh=5000, type="holding" ] {
   Thing data example1 "Ex 1"		[ readStart="47120", readValueType="int16", writeType="holding", writeStart="47120", writeValueType="int16"]
}   

If I need a multiplier I do that when I create the items from the channels of the thing. I find it much more convenient to use the UI for that. If you need a mapping you can do that there too.