[SOLVED] Migrate Stiebel-Eltron LWZ403+ISGWeb to OH2.4 and new modbus-binding-2.4.0

Dear all,

I am trying to migrate to the latest modbus binding and found this guide Modbus binding V1-V2 Config Update very useful.

[SOLVED] However, I do not get any data from Modbus anymore - I must be overlooking something (mistakes?) and would be happy for help:

Old Code services/modbus.cfg
Lüfter (lesen/schreiben)


Heizungsdaten (lesen)


New code things/lwz.thing

Bridge modbus:tcp:lwz [ host="", port=502, id=1 ] {   
        Bridge poller luefter [ start=1017, length=2, refresh=200, type="holding" ] {
    		Thing data tag [ readStart="1017", readValueType="int16" ]
    		Thing data nacht [ readStart="1018", readValueType="int16" ]

    	Bridge poller heizungsdaten [ start=1, length=32, refresh=200, type="input" ] {
    		Thing data RAUMISTTEMPHK1 [ readStart="1", readValueType="int16" ]
    		Thing data RAUMSOLLTEMPHK1  [ readStart="2", readValueType="int16" ]

New Code items/lwz.items

Number RAUMISTTEMPHK "Raum-Ist [%d]" {channel="modbus:data:lwz:heizungsdaten:RAUMISTTEMPHK1:number", autopudate="false" }
Number RAUMSOLLTEMPHK "Raum-Soll [%d]" {channel="modbus:data:lwz:heizungsdaten:RAUMSOLLTEMPHK1:number", autopudate="false" }
Number tag "Stufe Tag [%d]" {channel="modbus:data:lwz:luefter:tag:number", autopudate="false" }
Number nacht "Stufe Nacht [%d]" {channel="modbus:data:lwz:luefter:nacht:number", autopudate="false" }

** Sitemap **

sitemap lwz label="LWZ"
     Frame {
         Text item=RAUMISTTEMPHK
         Text item=RAUMSOLLTEMPHK
         Text item=tag
	Text item=nacht

Thank you so much, the new binding looks really great and I hope to figure this out soon.


1 Like

I think the problem is with the start values. Try

Bridge poller heizungsdaten [ start=1017, length=32, refresh=200, type="input" ] {
		Thing data RAUMISTTEMPHK1 [ readStart="1017", readValueType="int16" ]
		Thing data RAUMSOLLTEMPHK1  [ readStart="1018", readValueType="int16" ]




Hi Wolfgang,

thank you for the fast response. And sorry, stupid mistake: I copied the wrong slave in the above code. Fixed it now, but I still cannot retrieve data.


Maybe try to set higher poll cycle (refresh) attribute - 200 ms might be a bit to fast for some baud rates with additional IP overheat. Also try to separate both pollers to see which one is failing.

Check events.log to see if your Items get updated.

Add [%d] or similar in your Item labels if you expect to see values on the sitemap.

Consider whether you really want autoupdate=“true” in your Items. It doesn’t make much sense with read-only registers, and is rarely wanted with regularly polled writeable registers. “false” often works better.

Dear all,

thank you for your suggestions & help! The configuration is now working and I adjusted the code above correcting my mistakes (some if which were stupid):

  1. I had some undiscovered syntax errors that probably caused me most of the trouble :wink: 2. I changed the polling time to 5000 ms as this is the value I had used with the old modbus binding and it works
  2. I changed from autoupdate=“true” to autoupdate=“false” as recommended

Happy for now and will move on implement the Stiebel-Eltron automation now. Once I am completed I will share my results!

THANK YOU so much - this is really great stuff and way more simple than the previous version!


1 Like

Hi Jens,
Thanks for your great work, really appreciate it!!

Is it now also possible to extract and save (in a database or file, eg csv) the consumption data (kWh per hour/day) and outside temperature?


Yes this should work now:
I plan to use OpenHAB persistence with InfluxDB and will build some KPI dashboards using Grafana.

My time is currently limited but I have some vacation upcoming towards end of the month and hope to finish it then

I already found out that obviously not all parameters of the Stiebel Modbus give back values, eg. WW-SOLL-TEMP input register is not delivering a value however WW-SOLL-TAG Holding Register returns my actual SOLL-TEMP, will try out all values…

Todo list:

  • config Switch & automatic rules (depending on outside temperature) for venting levels
  • transformation of values (since integer is used, need to devide values eg by 10 for temperature)
  • Monitor Energy consumption and warm water temp using influx/Grafana (actually OH persistence will record all item values into the database)


1 Like

Hi Jens,

i have implemented your code above.
But I get these errors (constantly):

2019-01-14 19:05:54.562 [WARN ] [rt.modbus.internal.ModbusManagerImpl] - Could not connect to endpoint ModbusTCPSlaveEndpoint@18c3b85[address=,port=502] -- aborting request ModbusPollerThingHandlerImpl.ModbusPollerReadRequest@1366b72[slaveId=1,functionCode=READ_INPUT_REGISTERS,start=1,length=32,maxTries=3] [operation ID dbac5dc8-7b94-43ab-a8a3-2d63386176d4]
2019-01-14 19:05:54.565 [ERROR] [ernal.handler.ModbusDataThingHandler] - Thing modbus:data:lwz:heizungsdaten:RAUMISTTEMPHK1 'Modbus data' had ModbusConnectionException error on read: ModbusConnectionException(Error connecting to endpoint=ModbusTCPSlaveEndpoint@18c3b85[address=,port=502])
2019-01-14 19:05:54.569 [ERROR] [ernal.handler.ModbusDataThingHandler] - Thing modbus:data:lwz:heizungsdaten:RAUMSOLLTEMPHK1 'Modbus data' had ModbusConnectionException error on read: ModbusConnectionException(Error connecting to endpoint=ModbusTCPSlaveEndpoint@18c3b85[address=,port=502])
2019-01-14 19:05:54.606 [ERROR] [ing.ModbusSlaveConnectionFactoryImpl] - connect try 1/1 error: Connection refused (Connection refused). Connection TCPMasterConnection@ba8f70[socket=Socket[unconnected]]. Endpoint ModbusTCPSlaveEndpoint@18c3b85[address=,port=502]
2019-01-14 19:05:54.609 [ERROR] [ing.ModbusSlaveConnectionFactoryImpl] - re-connect reached max tries 1, throwing last error: Connection refused (Connection refused). Connection TCPMasterConnection@ba8f70[socket=Socket[unconnected]]. Endpoint ModbusTCPSlaveEndpoint@18c3b85[address=,port=502]
2019-01-14 19:05:54.612 [ERROR] [ing.ModbusSlaveConnectionFactoryImpl] - Error connecting connection TCPMasterConnection@ba8f70[socket=Socket[unconnected]] for endpoint ModbusTCPSlaveEndpoint@18c3b85[address=,port=502]: Connection refused (Connection refused)

What could be the issue?


Hi Stefan,

the error says that OpenHAB cannot connect to your ISG. There is two options:

Option 1: Modbus is not active on your ISG

Could you please check if MODBUS is active on your ISG - if you have an early version, MODBUS was at extra license cost and not included. Only the latest versions of ISG have Modbus. Connection refused sounds to me like MODBUS is not active.

To check go to Servicewelt (I guess: and then from the menu go to “Diagnose” and there “Busteilnehmer”.

The new screen should show on the right “MODBUS” and a green dot in a cricle. My firmware version of ISG is 8.6.0 -> on the same screen just below MODBUS there is an entry for “Hauptversionsnummer” (in my case 8) followed by “Nebenversionsnummer” (in my case 6) and last “Revisionsnummer” (in my case 0). If MODBUS is not enabled, you have to call Stiebel Eltron and check if you can get a new firmware with it enabled. It is for free noadays, so I hope they do not charge you extra!

AS well: you do not need the Servicewelt-Portal (which comes at subscription, too) if you want to use Servicewelt from Mobile, you can do so via OpenHAB app once MODBUS is working and you opened a port on your router/firewall to access OpenHAB from the internet (please consider the security impact of opening OpenHAB to the Internet!)

Option 2: ISG and OpenHAB are located in different networks (or there is a general network issue)

Can you confirm that from the OS where you have OpenHAB running you can ping the Servicewelt IP address (assuming you are not using a firewall in between OpenHAB and Servicewelt - b/c if so you would likely have checked this already).

Hope this helps.


Dear all,

does somebody happen to know what valueTypes I have to use for Stiebel-Eltron? Their MODBUS implementation is separating the following datatypes:


Datatype 2 can be read with “int16” and as described has to be devided by 10 to show the real value (eg. 210 °C equals 21.0 °C)

I Would need Datatype 7, too. Trying “float32” at least returns values while “int16” for sure returns a configuration error (since the StiebelEltron documentation shows the value range is not integer :slight_smile: ). Yet the data seems odd even if multiplied by 100 as described.

Reading the Modbus documentation on ValueTypes did not help me much and try- and error did not provide meaningful results as well.

Finding: with int16 I do not get anything but an error, with float32 I get weird data.


int16 is one16-bit Modbus register, float32 is two registers. If you go changing those about you will also need to look at things like addresses, lengths.

From your chart, Stiebel’s idea of a datatype 7 just appears to be int16 with a divide by 100 transform

Thank you Rossko57 - this time I was simply stupid! I had a typo “init16” instead of “int16”. Once I corrected it all worked :slight_smile:

Your fast support is really appreciated - I now can read all values from LWZ that I am interested in and have 2 JavaScript transformations each for multiply and divide (1x 10 and 1x 100) as explained in the MODBUS docu!

Really happy folks! Thank you for all your support.


1 Like

Hi Jens,
yes, it’s “Option 1”.
I just had a phone conversation with the technical support of Tecalor.
The problem is, that on my ISGweb “EMI Energymanagement” is active (for connecting with my SMAphotovoltaic system). And: You can’t have Modbus and EMI active on the same ISGweb :roll_eyes:
Learning never stops!
So i have to find another way to get the data from my tecalor system.

I assume you now have created many more things / items to read data from your heating.
I am just connecting now opnehab to my ISG and if you have more things / items to share that would be a real timesaver :slight_smile:

Hi Shorty,

here is my latest config:


Bridge modbus:tcp:lwz [ host="", port=502, id=1 ] {   
// Lueftersteuerung
Bridge poller luefter [ start=1000, length=27, refresh=1000, type="holding" ] {
	Thing data STUFETAG [ readStart="1017", readValueType="int16", writeStart="1017", writeValueType="int16", writeType="holding" ]
	Thing data STUFENACHT [ readStart="1018", readValueType="int16", writeStart="1018", writeValueType="int16", writeType="holding" ]

// Systemparameter (Holding r+w)
Bridge poller heizungsdaten1 [ start=1000, length=27, refresh=1000, type="holding" ] {
	Thing data WWSOLLTAG [ readStart="1011", readValueType="int16", readTransform="JS(divide10.js)" ]
	Thing data WWSOLLNACHT [ readStart="1012", readValueType="int16", readTransform="JS(divide10.js)" ]
	// Issue with datatype 7
	Thing data HK1STEIGUNG [ readStart="1007", readValueType="int16", readTransform="JS(divide100.js)" ]
	Thing data HK1FUSSPUNKT [ readStart="1008", readValueType="int16", readTransform="JS(divide10.js)" ]
	Thing data HK2STEIGUNG [ readStart="1009", readValueType="int16", readTransform="JS(divide100.js)" ]
	Thing data HK2FUSSPUNKT [ readStart="1010", readValueType="int16", readTransform="JS(divide10.js)" ]

// Systemwerte (InputRegister)
Bridge poller heizungsdaten2 [ start=0, length=31, refresh=1000, type="input" ] {
	Thing data RAUMISTTEMPHK1 [ readStart="0", readValueType="int16", readTransform="JS(divide10.js)" ]
	Thing data RAUMSOLLTEMPHK1 [ readStart="1", readValueType="int16", readTransform="JS(divide10.js)" ]
	Thing data AUSSENTEMPERATUR [ readStart="6", readValueType="int16", readTransform="JS(divide10.js)" ]
	Thing data WWISTTEMP [ readStart="15", readValueType="int16", readTransform="JS(divide10.js)" ]
	Thing data WWSOLLTEMP [ readStart="16", readValueType="int16", readTransform="JS(divide10.js)" ]
	Thing data KOLLEKTORTEMPERATUR [ readStart="26", readValueType="int16", readTransform="JS(divide10.js)" ]	

// Energetische Daten (InputRegsiter)
Bridge poller energetik [ start=3000, length=32, refresh=1000, type="input" ] {
	Thing data PHEIZUNGTAG [ readStart="3021", readValueType="int16" ]
	Thing data PHEIZUNGSUMME1 [ readStart="3022", readValueType="int16" ]
	Thing data PHEIZUNGSUMME2 [ readStart="3023", readValueType="int16" ]
	Thing data PWWTAG [ readStart="3024", readValueType="int16" ]
	Thing data PWWSUMME1 [ readStart="3025", readValueType="int16" ]
	Thing data PWWSUMME2 [ readStart="3026", readValueType="int16" ]
	Thing data ELEKTRNEHEIZEN [ readStart="3030", readValueType="int16" ]
	Thing data ELEKTRNEWW [ readStart="3031", readValueType="int16" ]


// Systemparameter
Number WWSOLLTAG “WW-Soll-Tag [%.1f °C]” { channel=“modbus:data:lwz:heizungsdaten1:WWSOLLTAG:number”, autopudate=“false” }
Number WWSOLLNACHT “WW-Soll-Nacht [%.1f °C]” { channel=“modbus:data:lwz:heizungsdaten1:WWSOLLNACHT:number”, autopudate=“false” }
Number HK1FUSSPUNKT “Fusspunkt HK1 [%.1f °C]” { channel=“modbus:data:lwz:heizungsdaten1:HK1FUSSPUNKT:number”, autopudate=“false” }
Number HK1STEIGUNG “Steigung HK1 [%.2f]” { channel=“modbus:data:lwz:heizungsdaten1:HK1STEIGUNG:number”, autopudate=“false” }
Number HK2FUSSPUNKT “Fusspunkt HK2 [%.1f °C]” { channel=“modbus:data:lwz:heizungsdaten1:HK2FUSSPUNKT:number”, autopudate=“false” }
Number HK2STEIGUNG “Steigung HK2 [%.2f]” { channel=“modbus:data:lwz:heizungsdaten1:HK2STEIGUNG:number”, autopudate=“false” }

// Systemwerte
Number RAUMISTTEMPHK	"Raum-Ist [%.1f °C]"			{ channel="modbus:data:lwz:heizungsdaten2:RAUMISTTEMPHK1:number", autopudate="false" }
Number RAUMSOLLTEMPHK	"Raum-Soll [%.1f °C]"			{ channel="modbus:data:lwz:heizungsdaten2:RAUMSOLLTEMPHK1:number", autopudate="false" }
Number WWISTTEMP        "WW-Ist [%.1f °C]"				{ channel="modbus:data:lwz:heizungsdaten2:WWISTTEMP:number", autopudate="false" }
Number WWSOLLTEMP		"WW-Soll [%.1f °C]"				{ channel="modbus:data:lwz:heizungsdaten2:WWSOLlTEMP:number", autopudate="false" }
Number AUSSENTEMPERATUR	"Aussen-Temp [%.1f °C]"			{ channel="modbus:data:lwz:heizungsdaten2:AUSSENTEMPERATUR:number", autopudate="false" }
Number KOLLEKTORTEMPERATUR "Kollektor-Temp [%.1f °C]"	{ channel="modbus:data:lwz:heizungsdaten2:KOLLEKTORTEMPERATUR:number", autopudate="false" }

// Energetische Daten
Number PHEIZUNGTAG		"P-Heizung-Tag [%d kWh]"		{ channel="modbus:data:lwz:energetik:PHEIZUNGTAG:number", autopudate="false" }
Number PHEIZUNGSUMME1	"P-Heizung-Summe1 [%d kWh]"		{ channel="modbus:data:lwz:energetik:PHEIZUNGSUMME1:number", autopudate="false" }
Number PHEIZUNGSUMME2	"P-Heizung-Summe2 [%d mWh]"		{ channel="modbus:data:lwz:energetik:PHEIZUNGSUMME2:number", autopudate="false" }
Number ELEKTRNEHEIZEN	"ELEKTR. NE HEIZEN [%d h]" 		{ channel="modbus:data:lwz:energetik:ELEKTRNEHEIZEN:number", autopudate="false" }
Number ELEKTRNEWW 		"ELEKTR. NE WW [%d h]" 			{ channel="modbus:data:lwz:energetik:ELEKTRNEWW:number", autopudate="false" }
Number PWWTAG			"P-WW-Tag [%d kWh]"				{ channel="modbus:data:lwz:energetik:PWWTAG:number", autopudate="false" }
Number PWWSUMME1		"P-WW-Summe1 [%d kWh]"			{ channel="modbus:data:lwz:energetik:PWWSUMME1:number", autopudate="false" }
Number PWWSUMME2		"P-WW-Summe2 [%d mWh]"			{ channel="modbus:data:lwz:energetik:PWWSUMME2:number", autopudate="false" }

// Luefter
Number STUFETAG			"Stufe Tag"						{ channel="modbus:data:lwz:luefter:STUFETAG:number", autopudate="false" }
Number STUFENACHT		"Stufe Nacht"					{ channel="modbus:data:lwz:luefter:STUFENACHT:number", autopudate="false" }


sitemap lwz label=“LWZ”

Frame label=“Lueftersteuerung” {
Switch item=STUFETAG mappings=[0=“OFF”, 1=“MIN”, 2=“MED”, 3=“MAX”]
Switch item=STUFENACHT mappings=[0=“OFF”, 1=“MIN”, 2=“MED”, 3=“MAX”]

Frame label=“Sytemwerte” {

  Text item=WWISTTEMP
  Text item=WWSOLLTAG


Frame label=“Energetische Werte” {
Text item=PWWTAG
Text item=PWWSUMME2
Text item=PWWSUMME1

Frame label=“Heizungssteuerung” {

Did not yet configure rules :slight_smile:


I already read some values because of your great support which helps so much to learn fast!

I have ISG on latest firmware and a WPM4 heatpump.
Odd thing … the registers from the manual PDF are incorrect for WPM4 …
I definately e.g. read “Outside Temp (Aussentemperatur)” on 506 … manual says 507.

My next question would be …
could you share the divide10.js etc scripts for the transformations ? :slight_smile:
does that transformation “on the fly” also work for write actions?

thanks !!

OK - found this on the manual now… for some reason they say everything could off by 1 register index.
Modbus is too new for me to understand what they mean with “1 based”.

See the modbus binding documentation, ‘Transformations’

Hi Shorty,

yes you are correct the addressing is -1 so if you want to read register 1001 you have to put register 1000 in your OpenHab configuration.


// Wrap everything in a function (no global variable pollution)
// variable "input" contains data passed by openhab
(function(inputData) {
// on read: the polled number as string
// on write: openHAB command as string
var DIVIDE_BY = 10;
return parseFloat(inputData) / DIVIDE_BY;

I did not try to write value that need to be transformed, but this works similarly. I think it was explained in the docu: https://www.openhab.org/addons/bindings/modbus/#modbus-binding

I will as well look into this once I have more time.


Hi Jens,

I would like to control the fan with Alexa. Can you help me with that?