Developing modbus binding for KWB heatings - where to start?

Hi there,
we have two central heating boilers from KWB since a couple of months installed and I’d like to integrate them now into our Openhab installation. Purpose for the moment is mostly monitoring (i.e. reading values) as controlling them is done mostly physically on-site or can be done via the KWB’s own portal.

There is no binding for KWB currently available, so I’m okay to develop and contribute it something. I managed to activate the Modbus TCP interface on both controls, they are already connected to our local network as well. Also I got an excel sheet with all the modbus parameters but as I’m quite new to the modbus topic, I have to admit that I need to learn how to interpret this ,-)

Just wanted to ask how to continue from here best: I noticed there is a generic (?) modbus binding. Would that be the best starting point to work on, parametrize somehow etc.? If it’s generic I suppose developing a standalone binding makes no sense at all, so what would be the best track to start this task for me?

Any hints welcome, thanks!

As usual with software, it depends. Binding gives you a chance to implement logic which is impossible or hard to achieve with modbus binding configuration. For example sunspec binding is there not only to get predefined registers but also to detect different encoding schema in registers and take care of it.

Each binding can also implement discovery, so based on broadcast messages sent by controller, you will be able to create a dedicated thing instance which will handle known KWB registers. Other point are quantities which are not supported by modbus binding core and have to be added later on. This means that if you ie. have an energy value stored in W with two decimal points it is something which will force you to apply read/write transformation. Its basic but makes configuration more complex.

Overall look at the pros and cons - if your configuration is just plain mapping of registers then you will be fine with generic functionality. If you need to merge registers or make various transformations then it is some justification to make a dedicated binding. Another point - update of binding is usually straight as it forces user just to install new version while staying with configuration will force everyone to sync it. The more controllers (and variants of it) you have, the better tooling or the bigger amount of time you will need to complete that.

Okay, fair enough. “It depends” is definitly a good answer, to my experience as well ,-)) I’ll try to start first with a plain modbus client and also get hold of the modbus binding sourcecode. Yet I do not know what is required. I think the current binding is at least a good learning source.

Hi Soeren,
I also own a KWB (EF2) since 2016. I built my own monitoring solution back in the days also based on Modbus (Perl-Script, InfluxDB and Grafana). I used Perl back then because it was simple to parse the Excel with the register definitions.

I’m exploring the possible approaches for a KWB native binding since a few quarters, but I lack the needed Java-skills. I can read/understand what OH bindings do and need to do, but never coded one.

If you want to approach a binding, I’m happy to help.

If you want to explore/debug Modbus, I recommend you start with mbpoll to read/set registers on the CLI.

The native Modbus-binding (that is used via config-files) has already been extended by device-specific ones. There you can study how they done it (e.g E3DC, Studer, Helios aso.)

My oberservations so far:

  • if the binding should be generic, complete and usable for all real-world deployments, it will be a huge undertakting
  • Boiler-types can’t be auto-detected/discovered, they’d need to be specified by the user as things
  • heating-circuits, buffers aso could be discovered (by checking the status-register for each temp-register). But I would start the first binding iteration without any discovery
  • you probably need mapping tables (valid registers per boiler-type) and a info-table how to interpret the registers (based on the Excel)
  • based on Modbus restrictions one can only read a limited number of registers in one go. The register-layout is not really friendly here: eg. buffer-temp T1 registers are at 8708-8737 for all possible 15 buffer-tanks. T2 is 8742-8771 and so on. In my script I get T1, T2 each in one go and later only process the temps from the one buffer I use. Not sure if a binding should do the same or poll each register(pair: value/status) in its own poll-thread

Each of the existing Modbus-extension-bindings use their own approach on how to poll registers, how they define which registers to get and how to interpret them. None fits 100% to be reused IMHO for KWB.
As I said, I can help with experience with KWB Modbus but not really with coding.


I had a look on several of modbus extensions and Stiebel (ISG) is quite basic. You might look at it. It does not have many features (it didn’t work for my deployment), so its fairly easy to compare it with config files.

Hi Markus,

thank you very much for getting into this thread - I will PM you after easter holidays because I think we need to get together ,-))

My Java skill are quite okay and I always wanted to provide some added value to OH. As of my understanding modbus is a very basic protocoll (from what I tried out already, seems to be pretty basic / easy to understand from a protocol level), but the individualy implementation of vendor specific interpretation is >90% of the efforts. If you you have good knowledge of the KWB specific modbus interpreation, that could be a nice match for the two of us ,-) So I’ll get in contact with you next week.
I’ll also try to approach KWB directly, maybe it’s overly optimistic, but one has to do it


Hello Sören!

Did you find a way to work with your EasyFire KWB?


Hello Michael,

I solved everything with the Modbus Addin. I setup two large item/things files with about ~100 values that get read and it really works good. As an advantage over the confort-online service all data is in realtime and without delays by using the KWB portal and without using any cloud.
I have’t configured anything so far for writing back i.e. controlling as the few times I need to change something it’s ok for me to change settings directly in the boiler room. Currently I’ setting up some UI using the openhab floorplan designer, but this is work in progress and very specific to our installation. Will likely publish this here in the forum later, but I’m on vacation right now with no access to my dev environmet.
Kudos goes to @mdillman also who provided me with some very helpful information around the Modbus topic.

Hello Soeren,
I am very keen on replicating on my KWB installation the solution you have found with Markus. Would you be able to share the details of your solution here?
Thanks in advance!

Hi Bob,

I’m attaching a file with things, items and transformations as beeing part of my installation. You need to copy that into the respective folders of your OH installation. That should hopefully work on your side as a good starting point. Some additional notes from my side:

  • On the SD card that comes with your “Comfort 4” control box is a spreadsheet that contains a fully list of Modbus registers available, with types, short explanation and possible mappings. So you can easily look up additional data that is not part of my files and add them.
  • I wanted to get quite some data from our installations (we have actually a CF2 and a MF2) and found, that the registers were kind of scattered. Due to the nature of Modbus and the binding I had to create a larger number of “poller” things that would just poll a small amount of registers. You could change this of course to some quite large polls and just pick the required registers, this is however disregarded in Modbus (but technically spoken correct). It looks like however that the Comfort 4 control seems to have problems with large Modus pools so I decided to go for the smaller one. Once everything is setup it doesn’t harm anyhow, you just end up with more pollers.
  • The polling interval is currently mostly set to 60 seconds. Initially I set it to 5 seconds, but one of the controls crashed after 2 days normally with the 5 second interval. I relaxed it and now I’m at one crash every 2~3 weeks (but only one control!) - I tried to open a ticket at KWB for this but they seem not to be interested to look after this problem - not so nice ;-((
  • Mappings are comming directly from their Modbus description spreadsheet.
  • Currently all registers are used for reading only. I have one use case currently for writing something, but had no time so far to implement it. Therefore all pollers are just set to input.

Everything is stored from OH in an influxdb, which is convenient for analyzing problems if you have a longer timeseries. Just for operating the boilers I created a small drawing of some core components of our installation and used a “floorplan” page to visualize some item data on it.

Hope that gives you a good starting point,

PS: I just noticed I cannot upload a ZIP file ,-// So I had to concatenate all the files into a single txt, sorry, you need to extract them from the txt one by one.

kwb_all_files.txt (25.6 KB)

Many thanks for all the detail, Soeren. This gives a great starting point for getting data from our three MF2’s into a database for what looks like the same purpose as you. I will check the SD card for the spreadsheet and will probably be offline for a few weekends of experimentation. Will report back with results when I get there.
Best wishes,

am I right when I think that you are using the “Comfort Online” upgrade of your Comfort 4, and that you are directly reading data from this module (not via the KWB online portal)?

Or are you dirctly linked to the RS485 bus that runs between the main unit, display and external control units?

I am realy interested in getting my Easyfire 2 (with Comfort 3) into Openhab; now I use a strange setup where a WEMOS reads the data stream from RS485 and tries to interpret the data based on some guys reverse engineering, but many parameters are not visible to me.

KWB provides very few information on the Online module, and nothing about using it locally.


Hi Phil,

that is correct: We bought the modbus extension, so no RS485 hack. Instead it’s standard Modbus/TCP which requires just a TCP connection between the openhab box and the KWB controller. With this extension from KWB you will receive also a full fledged list of all Modbus registers, which can be directly turned into items/things in Modbus, completely transparent.


Thanks Soeren,
I will now check the availability of Comfort Intercom at my most trusted heating dealer :slight_smile:

Just an update as I’ve been quiet for a while (the usual problem lack of time) with occasional tinkering with the info I got from Soeren. I’ve been successful querying the boilers using Python on a Raspberry Pi (24/7 on) using command line tool modpoll.exe (Free Modbus Master Simulator and Test Tool ) . Python calls the tool and appends the data received from the respective boilers to a text file for further offline analysis. Need to experiment a bit more with the number of registers I pull in one go. Now 20 and once per 2 minutes. I want to prevent crashing controllers at all (wintertime) and thought I’d start slow (I read about Soerens 5 seconds cycle, see above posts). I think I read somewhere that querying a too large number of registers in one request also creates problems, so splitting up into smaller batches leads to more stable performance.

For the eventual analysis of the historic data I’ll start looking for a visualizing tool the next quiet weekend. KWB’s own comfort-online web version does this quite nicely in fact in the paid functionality packages, overlaying the different selected parameters and ability to pan/zoom in/out on the graphs by dragging the mouse etc. If anyone has a tip here for a data visualizing tool do let me know.

Another interesting tool to get to know the KWB boilers registers and their output I find is Modbus Monitor’ (free functional demo with plenty of time to discover). When using this to query your KWB registers add “30” before the KWB address list number. So 8147 becomes 308147. And Swap Type ‘ABCD_BE’ works. But this tool does not work for creating a large historic data file (my goal).

Best, Bob

Hi Soeren, in one of your previous post you mentioned that you were not yet able to send commands towards KWB. Could you improve your setup in that direction?

For me reading values is a nice thing, but what is really required is to influence the daily schedule of the heating. Setting that within the KWB UI is a horror, and it is static.

As the switching between day and night temperature level is done via a hardware switch at the room thermostat I suppose that only shifting the (e.g.) night time demand temperature via openhab would lead to an openhab-controlled temperature profile.

Hi Phil and others,

actually I just tried this and it works flawless. So just as background: I wanted to control the min/max temperature of the domestic water accumulator (“Brauchwasserspeicher”) as we are heating it also through electrical power (fed by our PV installation) and using PV estimation for the next 12 hours I wanted e.g. to lower the max temperature when I would “knew” that enough PV energy would be there to heat it up. This actually required writing to the min/max value in order to lower the energy from from the large deposit into the demoestic water accumulator.

So basically everything is straight forward, here the excerpts

Things file below. Read/write transform just divides and multiplies the values by 10 as KWB delivers the temperature in 1/10 degrees.

    Bridge poller acs_4 "Poller KWBBoilerCF2 - ACS #4" [ start = 24711, length = 2, refresh = 60000, type = "holding" ] {

        Thing data ACSMinTemperature    [ readStart = "24711", readValueType = "int16", readTransform = "JS(divide_by_10.js)", writeStart = "24711", writeValueType = "int16", writeTransform = "JS(multiply_by_10.js)", writeType = "holding" ]
        Thing data ACSMaxTemperature    [ readStart = "24712", readValueType = "int16", readTransform = "JS(divide_by_10.js)", writeStart = "24712", writeValueType = "int16", writeTransform = "JS(multiply_by_10.js)", writeType = "holding" ]


Then the item file

Number:Temperature KWB_BOILER_CF2_ACSMinTemperature		<temperature>	(KWB_BOILER_CF2) { channel="modbus:data:KWBBoilerCF2:acs_4:ACSMinTemperature:number" }
Number:Temperature KWB_BOILER_CF2_ACSMaxTemperature		<temperature>	(KWB_BOILER_CF2) { channel="modbus:data:KWBBoilerCF2:acs_4:ACSMaxTemperature:number" }

From here it is available in scripts and I also have a sitemap file for it with slider to manually adjust it.

So far it works perfectly, hope that helps.

Best regards,