Configuration of MAXCUL and CUL Dongle

This tutorial is a section of my wider series on creating a home automation solution for heating and watering in my house.  Refer to the index here.

In this post I cover the installation of the firmware for the CUL dongle (culfw), the programming of the dongle to work with your raspberry pi, and configuration of the maxcul binding for Openhab.

At the end of this tutorial you should have one wall thermostat and one radiator valve paired to your raspberry pi via the CUL dongle.

The first thing to do is to obtain the CUL firmware.  This downloads from

  mkdir /home/pi/culfw
  cd /home/pi/culfw
  tar -xvf culfw-1.66.tar.gz

You also need to download and install dfu-programmer:

  aptitude install build-essential git make automake autoconf libusb-1.0-0-dev libusb-1.0-0
  git clone
  cd dfu-programmer
  sudo make install

Check that dfu-programmer runs by typing:


Next, plug your CUL stick into your raspberry pi, using a pin or other implement to hold in the small program button on the bottom of it.  The green LED should not be flashing.

Then install the firmware using the supplied program (use the appropriate version – my stick is a v3):

  cd culfw-1.66
  cd Devices/CUL
  sudo make usbprogram_v3

Unplug and replug your usb stick, and the green led should be flashing, and you should have a device at /dev/ttyACM0.

  ls -l /dev/ttyACM0

The device should have a group owner of dialout.  (Note – this section is partly from memory, I flashed my stick earlier, and it doesn’t seem to want to flash again.  I recall a lot of pain in this area….sorry).

Add the openhab user to the dialout group so that they can interact with the device.

  sudo usermod openhab -a -Gdialout

Next, you want to install the maxcul binding for openhab.

  aptitude install openhab-addon-binding-maxcul openhab-addon-io-cul

Create some configuration for the maxcul binding in /etc/openhab/configurations/openhab.cfg:

  ##### General configurations #####

  # Configuration folders (must exist as a subdirectory of "configurations"; the value
  # tells the number of seconds for the next scan of the directory for changes. A
  # value of -1 deactivates the scan).
  # A comma separated list can follow after the refresh value. This list defines a filter
  # for valid file extensions for the models.

  ##### Binding configurations #####

  ################################ Max!CUL Binding  ###########################################
  # set the device of the CUL device
  # set the refresh interval
  # set timezone you want the units to be set to - default is Europe/London

Modify the logging configuration in /etc/openhab/logback.xml, adding the following block after the eventfile appender:

       %d{yyyy-MM-dd HH:mm:ss} - %msg%n

Also change the loglevel on maxcul to debug so we can see what’s going on, do that by adding a block:


Create a basic items file in /etc/openhab/configurations/items/heating.items, we’re just going to have our thermostat, our wall switch, and switches to turn on  pairing and monitoring of the network traffic on the CUL dongle.  We’re creating the placeholders for all the information from the valve and wall thermostat, but won’t put the id onto each until we’ve paired the valve and thermostat.

  Group All
  Group HeatingElements (All)

  Switch swPair "Pair"  (HeatingElements) { maxcul="PairMode" }
  Switch swListen "Listen"  (HeatingElements) { maxcul="ListenMode" }

  Number valveSetpoint "Valve Current Setpoint [%.1f °C]"  (HeatingElements) { maxcul="RadiatorThermostat:TBD" }
  Switch valveBattery "Valve Battery"  (HeatingElements) { maxcul="RadiatorThermostat:TBD:feature=battery" }
  Number valveTemp "Valve Current Temp [%.1f °C]"  (HeatingElements) { maxcul="RadiatorThermostat:TBD:feature=temperature" }
  Number valvePosition "Valve Position [%.1f %%]" (HeatingElements) { maxcul="RadiatorThermostat:TBD:feature=valvepos" }

  Number wallSetpoint "Wall Current Setpoint [%.1f °C]"  (HeatingElements) { maxcul="WallThermostat:TBD" }
  Switch wallBattery "Wall Battery Low"  (HeatingElements) { maxcul="WallThermostat:TBD:feature=battery" }
  Number wallTemp "Wall Current Temp [%.1f °C]"  (HeatingElements) { maxcul="WallThermostat:TBD:feature=temperature" }
  Switch wallDisplay "Wall Display Setting" (HeatingElements) { maxcul="WallThermostat:TBD:feature=displaySetting" }

Next we configure a sitemap in /etc/openhab/configurations/sitemaps/default.sitemap:

  sitemap heating label="Home Heating" {
    Frame {
      Group item=HeatingElements label="Heating" icon="none"
      Setpoint item=valveSetpoint icon="temperature" minValue=5 maxValue=30 step=0.5
      Setpoint item=wallSetpoint icon="temperature" minValue=5 maxValue=30 step=0.5

Create a directory /usr/share/openhab/etc/maxcul, which is where the pairing information is stored.

  sudo mkdir /usr/share/openhab/etc/maxcul
  sudo chown openhab:openhab /usr/share/openhab/etc/maxcul

NOTE: more recent versions may store this information in /var/lib/openhab/maxcul, so you may need to create this directory / grant permissions here instead.

Go to the sitemap at http://raspberrypi2:8080, and set the pair switch.

Put the batteries into your wall thermostat, and hold in the boost button to pair with openhab.  You should see a 30 second timer appear on the screen.  Look in /var/log/openhab/maxcul.log, and you should see an error message along the lines of:

  Unable to find configuration for serial MEQ0856945. Do you have a binding for it?

Edit your heating.items file to replace the TBD for the wall thermostat with MEQ0856945 on each of the wall thermostat items, for example:

  Switch wallBattery "Wall Battery"  (HeatingElements) { maxcul="WallThermostat:MEQ0856945:feature=battery" }

Toggle the pairing switch again, and again hold in the boost button to trigger pairing.  When you look in the maxcul.log you should see the device successfully pairing, and you should receive a temperature in the wall thermostat temperature, and you should be able to directly change the setpoint in openhab with it reflecting (after a short delay) on the wall thermostat.

Next we want to pair a valve.  The process is quite similar.  Hold in the boost button on the valve, and flick the pairing switch in the openhab ui.  Again copy the device name, and add it to the valve configurations in heating.items.  Pair again, and look to see the settings update in the UI (again there’ll be a bit of a lag).

Finally, we’ll associate the wall thermostat with the valve, so that changes to the wall thermostat update the valve setting.  Edit the valve setpoint line to create an association with the wall thermostat, also adding in a specification that we’re using feature=thermostat, as using default doesn’t seem to work with an association:

  Number valveSetpoint "Valve Current Setpoint [%.1f °C]"  (HeatingElements) { maxcul="RadiatorThermostat:LEQ1133856:feature=thermostat:associate=MEQ0856945" }

and edit the wall thermostat setpoint line to create an association with the wall thermostat:

  Number wallSetpoint "Wall Current Setpoint [%.1f °C]"  (HeatingElements) { maxcul="WallThermostat:MEQ0856945:feature=thermostat:associate=LEQ1133856" }

Now you should see that changes to the setpoint on the wall thermostat ripple through to the setting on the valve.


39 thoughts on “Configuration of MAXCUL and CUL Dongle

  1. Pingback: Using Pi and OpenHab to control radiators and watering | technpol

  2. Hi! THX for the great post, but i’ve a Problem. I get an Error in my logfile and its equal what iam doing – devices not able to pair:

    2016-12-05 21:02:46 – Processing item valvePosition
    2016-12-05 21:02:46 – Found real device
    2016-12-05 21:02:46 – Part 0/2 -> RadiatorThermostat
    2016-12-05 21:02:46 – Part 1/2 -> TBD
    2016-12-05 21:02:46 – Part 2/2 -> feature=valvepos
    2016-12-05 21:02:46 – Unable to locate information for RADIATOR_THERMOSTAT TBD it may not yet be paired

    Any ideas?

  3. Yeah, there’s a text file you have to put the valve information into to pair it. I’m at work at the moment, so I can’t remember exactly where, but it’s where the Maxcul stuff stores pairing information. I feel like there was either a permissions thing (so it needs to write there itself), or it needed manual editing – I can’t remember which.

  4. I thing u mean that:
    sudo mkdir /usr/share/openhab/etc/maxcul
    sudo chown openhab:openhab /usr/share/openhab/etc/maxcul

    But i did that, so it can’t be the mistake 😉

  5. Things going less better…now i’ve got these log-data:

    2016-12-05 22:52:21 – Received command ON for item swPair
    2016-12-05 22:52:21 – Found config for swPair
    2016-12-05 22:52:21 – swPair pairMode enabled & timeout scheduled
    2016-12-05 22:53:01 – Received command OFF for item swPair
    2016-12-05 22:53:01 – Found config for swPair
    2016-12-05 22:53:01 – swPair pairMode timer cancelled
    2016-12-05 22:53:01 – swPair pairMode cleared

    Is it possible that the CUL is wrong or something else? I followed you’re post but pairing is not possible…help would be great! Greetings from Hamburg!

  6. The pairing mode auto-cancels after a time – presumably 40 seconds given your log. So that behaviour is expected.

    Are you sure the files aren’t in a different location in your install? It took me a while to find the right location on my install, and I’m pretty sure it wasn’t the documented location. The error you’re getting is an error that indicates the pairing file isn’t there – when you look in that location is the file present?

    I’m working out of town this week, so I’m not back home until Friday – that’d be the earliest I can look at the running install to see exactly what files I have in which location.

  7. Thx for help. Can u give me a hint how to find the files? I cant see anything helpful in the code on git…

  8. No, it doesn’t look useful to me either. Are you running openhab as user openhab? If you `su openhab` and then try to go to /usr/share/openhab/etc/maxcul and `touch x` does that work?

    I have a vague memory that there is another location it is supposed to write to, because I shouldn’t have had to create the directory that I did. It may have been under /etc/openhab/ somewhere. Is there anything anywhere in there? Alternatively, there’s a config to run as root, which lets lots of things work, then you can chase down what it changed and where to reset the permissions back.

  9. Ok, so i can write in that dir but not able to find different locations of other needed files. Main.Install dir is same as u described…i will wait for you’re answer on friday when u back home. Thx for help so far!

  10. One last idea. Is it possible that my CUL is not flashed correctly? If iam typing lsusb i get
    ID 03eb:204b Atmel Corp. LUFA USB to Serial Adapter Project

    But i another post i found that lsusb need to return this:
    ID 03eb:2ff4 Atmel Corp.

    Or is there an error-message if the stick is not correct? LED is flashing continous…

  11. This is possible – I don’t believe mine normally flash continuously. However, it would normally say that it couldn’t find CUL device, and just refuse to start the binding, if the CUL wasn’t flashed correctly (at least this was my experience when mine was improperly flashed). It’s more likely that it’s failing with pairing.

    Have you turned the logging on the MAXCUL binding all the way up – to debug I think? This lists all the packets going backwards and forwards, and I can’t remember if it also gives a bit more information about what it’s writing and when.

  12. Ok i thing the CUL is OK. in “screen” i can see V 1.66 CUL 868 if iam typing V in it…

  13. Yeah i get all the loginfos on maxul.log – or is there one more place where loginfos beeing stored?

  14. 2016-12-06 10:21:27 – Processing item swPair
    2016-12-06 10:21:27 – Pair Mode switch found
    2016-12-06 10:21:27 – Processing item valveSetpoint
    2016-12-06 10:21:27 – Found real device
    2016-12-06 10:21:27 – Part 0/1 -> RadiatorThermostat
    2016-12-06 10:21:27 – Part 1/1 -> TND
    2016-12-06 10:21:27 – Unable to locate information for RADIATOR_THERMOSTAT TND it may not yet be paired

    This is the content of my latest try. “Found real device” – means that the cul found the device in the real world and is only not able to wirte down the pairing information in a file?

  15. What is the “TND”? I’m pretty sure mine has a thermostat number appearing in there. But I don’t have logs in front of me. Is there a thermostat number reported somewhere in there? I also get a full packet dump when I turn on the debugging, but I cannot recall the exact flag I set for that, or which log it wrote to. Mine’s been working with not much fiddling for about 6 months now, so the memory is a bit hazy.

  16. The TND is the placeholder (in your tut u used TBD). In the maxcul.log-file there are no id’s of an device as u descirbed above. But its equal – if iam entering the real id (i knew it from the earlier configuration and its not beeing changed after factory-reset) the result is the same. But for me the binding is not useful and that makes me sad 😉 hopefully u can refresh the memory and check youre installation. THX!

  17. OK, that’s likely the problem. You need the actual thermostat id there, not the placeholder. So the way I was doing things was turning on the logging, then pressing pair, then looking in the log to see what ID the thermostat had. I then put that id into the config and restarted. Then pressed pair again, and now it should pair to the thermostat.

    I think the logging setting was the one that set Maxcul to debug (I appear to not be able to embed code blocks in comments).

  18. Ok i try but what exactly do u mean with config? An example good and the, place where i need to save the config file. And logging – what loggingpossibilities i can active? There is only one in youre tutorial…thx very much for help!

  19. With the id i got that in the maxcul.log in /var/log/openhab:
    2016-12-06 19:45:02 – MaxCul binding has been started.
    2016-12-06 19:45:02 – Processing item swPair
    2016-12-06 19:45:02 – Pair Mode switch found
    2016-12-06 19:45:02 – Processing item valveSetpoint
    2016-12-06 19:45:02 – Found real device
    2016-12-06 19:45:02 – Part 0/1 -> RadiatorThermostat
    2016-12-06 19:45:02 – Part 1/1 -> NKF0000778
    2016-12-06 19:45:02 – Unable to locate information for RADIATOR_THERMOSTAT NKF0000778 it may not yet be paired
    2016-12-06 19:45:02 – Activating MaxCul binding
    2016-12-06 19:45:02 – MaxCUL Reading config
    2016-12-06 19:45:37 – Received command ON for item swPair
    2016-12-06 19:45:37 – Found config for swPair
    2016-12-06 19:45:37 – swPair pairMode enabled & timeout scheduled
    2016-12-06 19:46:37 – swPair pairMode time out executed

  20. You need to turn on the logging:
    logger name=”org.openhab.binding.maxcul” level=”DEBUG”

    Then it should turn up in the maxcul log, and you update in the items file.

  21. Logging debug OK – was part of the tutorial and pairing button yes – timer from 30 to 0 starts. But nothing is able to pair…no files created – nothing happen 😦

  22. I’m still surprised you’re not getting full message logging – there’s something about that that is material. I can take a look at that on Friday.

  23. OK thx. I’ll break here until friday. But i thing we can be sure that the cul is working. I’am getting some code in “screen” view which is the same as in another post and the version-check is ok, too. So, i thing the issue is in the binding or in the transport-cul or permissions…thx for help! Will be back on Friday 🙂

  24. Maybe one last idea. I found this post – u remember 🙂
    OK, I’ve now had the time to get this working. I think three things were needed:

    1.” into the “addons” folder
    2. actually have a device that is accessible (in my case, serial:/dev/ttyACM0), with permissions set for the user I’m running as. I think this was a key step – previously I was testing on my Mac rather than my Pi, and it looks like the binding just silently doesn’t start when the CUL dongle isn’t connected
    3. the pairing data gets stored in etc/maxcul, you have to create this directory and grant permissions to the user that openhab is running as (I’ve installed via apt-get on debian, and the default config doesn’t permit this)

    My Questions: 1. Where can i get that version? 2. What do u mean with that exactly? 3. Which etc/maxcul-dir u focus? etc in openhab or etc in main-pi?

    Maybe there is one key to bring my system up!

  25. 1. I’m not using 1.7.1 any more, and the later versions should work fine

    2. I had a lot of difficulty getting the binding to work at all – it was silently just not working. You’re past that because it’s recognising the items in the item file and recognising the CUL dongle – you shouldn’t need to worry about this

    3. I think this is the directory that I had in my blog post.

  26. In the openhab.log there is an info that MaxCUL Binding started – but not the CUL Transport binding. Should it be there?

  27. OK, I think the trick is maybe turning on the listen flag as well.

    When I set my log level to DEBUG (for MAXCUL), and I turn on the pair and listen flags, then in my openhab/openhab.log I get something like:

    2016-12-10 14:08:31.876 [DEBUG] [.maxcul.internal.MaxCulBinding] – Received command ON for item swPair
    2016-12-10 14:08:31.883 [DEBUG] [.maxcul.internal.MaxCulBinding] – Found config for swPair
    2016-12-10 14:08:31.888 [DEBUG] [.maxcul.internal.MaxCulBinding] – swPair pairMode enabled & timeout scheduled
    2016-12-10 14:08:42.329 [DEBUG] [.maxcul.internal.MaxCulBinding] – Received command ON for item swListen
    2016-12-10 14:08:42.339 [DEBUG] [.maxcul.internal.MaxCulBinding] – Found config for swListen
    2016-12-10 14:08:42.340 [DEBUG] [.b.m.internal.MaxCulMsgHandler] – Listen Mode is ON
    2016-12-10 14:09:01.553 [DEBUG] [.b.m.internal.MaxCulMsgHandler] – MaxCulSender Received Z0BC805401367420102030068E7
    2016-12-10 14:09:01.555 [DEBUG] [m.i.messages.SetTemperatureMsg] – SET_TEMPERATURE Payload Len -> 1
    2016-12-10 14:09:01.556 [DEBUG] [.b.m.internal.messages.BaseMsg] – Raw Message: Z0BC805401367420102030068E7
    2016-12-10 14:09:01.557 [DEBUG] [.b.m.internal.messages.BaseMsg] – Length => 11
    2016-12-10 14:09:01.557 [DEBUG] [.b.m.internal.messages.BaseMsg] – Msg Count => 0xc8
    2016-12-10 14:09:01.557 [DEBUG] [.b.m.internal.messages.BaseMsg] – Msg Flag => 0x5
    2016-12-10 14:09:01.558 [DEBUG] [.b.m.internal.messages.BaseMsg] – Msg Type => SET_TEMPERATURE
    2016-12-10 14:09:01.558 [DEBUG] [.b.m.internal.messages.BaseMsg] – Src Addr => 136742
    2016-12-10 14:09:01.559 [DEBUG] [.b.m.internal.messages.BaseMsg] – Dst Addr => 010203
    2016-12-10 14:09:01.559 [DEBUG] [.b.m.internal.messages.BaseMsg] – Group ID => 0
    2016-12-10 14:09:01.559 [DEBUG] [m.i.messages.SetTemperatureMsg] – Desired Temperature => 20.0
    2016-12-10 14:09:01.560 [DEBUG] [m.i.messages.SetTemperatureMsg] – Control Mode => MANUAL
    2016-12-10 14:09:01.597 [DEBUG] [.b.m.internal.MaxCulMsgHandler] – MaxCulSender Received Z0CC80002010203136742000100C4
    2016-12-10 14:09:01.598 [DEBUG] [.b.m.internal.messages.BaseMsg] – Raw Message: Z0CC80002010203136742000100C4
    2016-12-10 14:09:01.598 [DEBUG] [.b.m.internal.messages.BaseMsg] – Length => 12
    2016-12-10 14:09:01.599 [DEBUG] [.b.m.internal.messages.BaseMsg] – Msg Count => 0xc8
    2016-12-10 14:09:01.599 [DEBUG] [.b.m.internal.messages.BaseMsg] – Msg Flag => 0x0
    2016-12-10 14:09:01.599 [DEBUG] [.b.m.internal.messages.BaseMsg] – Msg Type => ACK
    2016-12-10 14:09:01.600 [DEBUG] [.b.m.internal.messages.BaseMsg] – Src Addr => 010203
    2016-12-10 14:09:01.600 [DEBUG] [.b.m.internal.messages.BaseMsg] – Dst Addr => 136742
    2016-12-10 14:09:01.601 [DEBUG] [.b.m.internal.messages.BaseMsg] – Group ID => 0
    2016-12-10 14:09:01.601 [DEBUG] [o.b.m.internal.messages.AckMsg] – Is ACK? => true
    2016-12-10 14:09:01.602 [DEBUG] [o.b.m.internal.messages.AckMsg] – Unknown ACK payload byte => 0
    2016-12-10 14:09:01.648 [DEBUG] [.b.m.internal.MaxCulMsgHandler] – MaxCulSender Received Z0BC800401367421426450068E7

    Either you’re not turning on the right flags, or there’s something in your setup that’s not working and therefore you’re seeing no traffic. That wouldn’t make sense because you’re getting the thermostat ID through, so it must be transmitting something.

    Ignoring that, it looks like the files are no longer in /usr/share/openhab/etc/maxcul, I can now see them in /var/lib/openhab/maxcul. So you’d need to set permissions on that location. In there I have files like this:

    [pi@raspberrypi3:/var/lib/openhab/maxcul $ ls
    pi@raspberrypi3:/var/lib/openhab/maxcul $

    And one of those files looks like this:
    [pi@raspberrypi3:/var/lib/openhab/maxcul $ cat
    #Autogenerated by MaxCul binding on Sun Jun 19 12:25:26 NZST 2016
    #Sun Jun 19 12:25:26 NZST 2016

    Hopefully that helps.

  28. Thx for the ideas. But – iam sorry – no change! The Log-file is empty, the path exist but no files created. At this point i stopped trying to start the CUL with the binding running. I installed oh2 and i use the refactored Max!Cube-binding. The setup works fine and there is no problem. I’am sorry! Thank you so much for you’re help!

  29. Hallo, first of all, thank you very much for this great guide. Unfortunatly, I may be doing something wrong. I have 5 radiator valves, no wall thermostates and a cubietruck with a CUL connected via USB. The radiator valves seem to be connected correctly, as changes at a radiator valve seem to ripple through, but I cannot set a temperature or valve position. This is the output I get whenever I try something like that via the web interface:

    2017-01-19 09:59:07.173 [INFO ] [runtime.busevents ] – txCredit state updated to 900
    2017-01-19 09:59:26.914 [DEBUG] [.maxcul.internal.MaxCulBinding] – Received command 21.0 for item bedValveSetpoint
    2017-01-19 09:59:26.921 [DEBUG] [.maxcul.internal.MaxCulBinding] – Found config for bedValveSetpoint
    2017-01-19 09:59:26.927 [WARN ] [.maxcul.internal.MaxCulBinding] – Command not handled for RADIATOR_THERMOSTAT that is not OnOffType or DecimalType
    2017-01-19 09:59:26.937 [INFO ] [runtime.busevents ] – bedValveSetpoint received command 21.0
    2017-01-19 09:59:27.027 [INFO ] [runtime.busevents ] – txCredit state updated to 900
    2017-01-19 09:59:28.726 [DEBUG] [.maxcul.internal.MaxCulBinding] – Received command 21.5 for item bedValveSetpoint
    2017-01-19 09:59:28.732 [DEBUG] [.maxcul.internal.MaxCulBinding] – Found config for bedValveSetpoint
    2017-01-19 09:59:28.739 [WARN ] [.maxcul.internal.MaxCulBinding] – Command not handled for RADIATOR_THERMOSTAT that is not OnOffType or DecimalType
    2017-01-19 09:59:28.751 [INFO ] [runtime.busevents ] – bedValveSetpoint received command 21.5
    2017-01-19 09:59:28.978 [INFO ] [runtime.busevents ] – txCredit state updated to 900
    2017-01-19 09:59:37.567 [DEBUG] [.b.m.internal.MaxCulMsgHandler] – MaxCulSender Received Z0F000460129CE800000000180A2A00E00B
    2017-01-19 09:59:37.576 [DEBUG] [.maxcul.internal.MaxCulBinding] – Received data from CUL: Z0F000460129CE800000000180A2A00E00B
    2017-01-19 09:59:37.583 [DEBUG] [o.o.b.m.i.m.ThermostatStateMsg] – THERMOSTAT_STATE Payload Len -> 5
    2017-01-19 09:59:37.591 [DEBUG] [.b.m.internal.messages.BaseMsg] – Raw Message: Z0F000460129CE800000000180A2A00E00B
    2017-01-19 09:59:37.597 [DEBUG] [.b.m.internal.messages.BaseMsg] – Length => 15
    2017-01-19 09:59:37.603 [DEBUG] [.b.m.internal.messages.BaseMsg] – Msg Count => 0x0
    2017-01-19 09:59:37.609 [DEBUG] [.b.m.internal.messages.BaseMsg] – Msg Flag => 0x4
    2017-01-19 09:59:37.616 [DEBUG] [.b.m.internal.messages.BaseMsg] – Msg Type => THERMOSTAT_STATE
    2017-01-19 09:59:37.622 [DEBUG] [.b.m.internal.messages.BaseMsg] – Src Addr => 129CE8
    2017-01-19 09:59:37.629 [DEBUG] [.b.m.internal.messages.BaseMsg] – Dst Addr => 000000
    2017-01-19 09:59:37.636 [DEBUG] [.b.m.internal.messages.BaseMsg] – Group ID => 0
    2017-01-19 09:59:37.642 [DEBUG] [o.o.b.m.i.m.ThermostatStateMsg] – Desired Temperature => 21.0
    2017-01-19 09:59:37.649 [DEBUG] [o.o.b.m.i.m.ThermostatStateMsg] – Measured Temperature=> 22.4
    2017-01-19 09:59:37.655 [DEBUG] [o.o.b.m.i.m.ThermostatStateMsg] – Valve Position => 10
    2017-01-19 09:59:37.662 [DEBUG] [o.o.b.m.i.m.ThermostatStateMsg] – Control Mode => AUTO
    2017-01-19 09:59:37.668 [DEBUG] [o.o.b.m.i.m.ThermostatStateMsg] – DST Active => true
    2017-01-19 09:59:37.675 [DEBUG] [o.o.b.m.i.m.ThermostatStateMsg] – LAN Gateway => true
    2017-01-19 09:59:37.682 [DEBUG] [o.o.b.m.i.m.ThermostatStateMsg] – Panel locked => false
    2017-01-19 09:59:37.688 [DEBUG] [o.o.b.m.i.m.ThermostatStateMsg] – RF Error => false
    2017-01-19 09:59:37.695 [DEBUG] [o.o.b.m.i.m.ThermostatStateMsg] – Battery Low => false
    2017-01-19 09:59:38.830 [INFO ] [runtime.busevents ] – bedValveBattery state updated to OFF
    2017-01-19 09:59:39.881 [INFO ] [runtime.busevents ] – bedValveTemp state updated to 22.39999999999999857891452847979962825775146484375
    2017-01-19 09:59:42.348 [INFO ] [runtime.busevents ] – bedValvePosition state updated to 10
    2017-01-19 09:59:42.468 [INFO ] [runtime.busevents ] – txCredit state updated to 900
    2017-01-19 09:59:47.306 [DEBUG] [.maxcul.internal.MaxCulBinding] – Received command 22.0 for item bedValveSetpoint
    2017-01-19 09:59:47.312 [DEBUG] [.maxcul.internal.MaxCulBinding] – Found config for bedValveSetpoint
    2017-01-19 09:59:47.319 [WARN ] [.maxcul.internal.MaxCulBinding] – Command not handled for RADIATOR_THERMOSTAT that is not OnOffType or DecimalType
    2017-01-19 09:59:47.329 [INFO ] [runtime.busevents ] – bedValveSetpoint received command 22.0
    2017-01-19 09:59:47.420 [INFO ] [runtime.busevents ] – txCredit state updated to 900
    2017-01-19 09:59:51.185 [DEBUG] [.maxcul.internal.MaxCulBinding] – Received command 22.5 for item bedValveSetpoint
    2017-01-19 09:59:51.192 [DEBUG] [.maxcul.internal.MaxCulBinding] – Found config for bedValveSetpoint
    2017-01-19 09:59:51.199 [WARN ] [.maxcul.internal.MaxCulBinding] – Command not handled for RADIATOR_THERMOSTAT that is not OnOffType or DecimalType
    2017-01-19 09:59:51.210 [INFO ] [runtime.busevents ] – bedValveSetpoint received command 22.5
    2017-01-19 09:59:51.301 [INFO ] [runtime.busevents ] – txCredit state updated to 900

    As you can see, I always get the warning “Command not handled for RADIATOR_THERMOSTAT that is not OnOffType or DecimalType” whenever I try to change the temperature via the web interface. I have seen the code at github, but cannot (yet) figure out why in “” line 223 that error is thrown. Obviously because, the “bindingConfig.getFeature()” is not equal to “MaxCulFeature.THERMOSTAT”, “MaxCulFeature.DISPLAYSETTING” or “MaxCulFeature.RESET”. Any help would be greatly appreciated.

  30. Most likely is that you’re trying to postUpdate a value that isn’t a DecimalType – so perhaps you’re feeding it a string somehow? You may need to do an explicit type conversion somewhere via “as DecimalType”. Are you using the exact code (i.e. is it my bug or is it yours?).

    You could try hardcoding the value as a decimal where it tries to postUpdate / sendMessage (can’t remember which I was using), and see if that works, that would then give you a lead on the exact cause. I find the rules language and debugger to be dreadful, so there’s a lot of old school printing out of values and hard coding things to see which exact bit is causing the issue.

  31. Thanks for that immediate response, I am using that those button obtained via the following in default.sitemap.

    Group label=”Einstellungen” icon=”settings” {
    Switch item=swPair
    Switch item=swListen
    Text item=txCredit

    Setpoint item=bedValveSetpoint icon=”temperature” minValue=5 maxValue=30 step=0.5
    Setpoint item=kidValveSetpoint icon=”temperature” minValue=5 maxValue=30 step=0.5
    Setpoint item=livingValveSetpoint icon=”temperature” minValue=5 maxValue=30 step=0.5
    Setpoint item=kitchenValveSetpoint icon=”temperature” minValue=5 maxValue=30 step=0.5
    Setpoint item=bathValveSetpoint icon=”temperature” minValue=5 maxValue=30 step=0.5

    Setpoint item=bedValvePosition step=10
    Setpoint item=kidValvePosition step=10
    Setpoint item=kitchenValvePosition step=10
    Setpoint item=livingValvePosition step=10
    Setpoint item=bathValvePosition step=10
    Text item=DeviceValves label=”Total Valve Openings [%.1f]”

  32. Could you also provide the relevant lines for the item file for bedValveSetpoint, and the rule that’s giving the error? I suspect one or other of them has a data type problem.

  33. Hmm. Sort of looks OK. The error is coming from here:
    I think line 223.

    What that says to me is that it’s recognised it as a radiator_thermostat, but that bindingConfig.getFeature() isn’t one of the values it’s expecting. It would be interesting to know what it is instead.

    Hypotheses about what could be going on:
    1. Newer version of code with a defect. What version of OpenHab and the binding are you using? It doesn’t look like there are any recent code changes when I hit the blame link, so I’m guessing it’s not that

    2. Looking closer, my setpoints look like this:
    Number MasterSetpoint “Master Current Setpoint [%.1f °C]” (valveMaster, DeviceSetpoints, InitSetpoints) { maxcul=”RadiatorThermostat:LEQ1133856:feature=thermostat:associate=MEQ0856945:configTemp=21.0/17.0/30.5/4.5/4.5/0.0/0.0″, mqtt=”[pi2:/heating/MasterActualSetpoint:state:*:default]” }

    From the code that’s complaining, it looks to me like the “feature=thermostat” is probably the bit that’s missing. Do you want to try adding that to your heating.items?

  34. That was it. I added “feature=thermostat” to my setpoints. Now it seems to be working. Great! Thanks!!

    Perhaps two more questions:
    – I have seen on the github website, that windows shutter contacts may be supported in the future, but looking at the code in line 227 of it seems that there is already some implementation?! Can you please give an example of what is already possible, if anything at all?
    – In the next step of the guide, you have added a lot of rules to allow for 4 different settings starting at 4 different times. Can you please give me an example or a hint how to extend this to a week-day-dependet setup? Eventually, I would like to treat weekends differently than week days and possibly add something for minimal heating during vacations.

    Again thank you very much!!

  35. Window shutters I have no knowledge of – I agree it’s in the code, so it’s possibly working, but I haven’t personally used them and I’m not the original author.

    To shift to a week day dependant setup I think you’d need probably a concept of “day group” or similar, and then mark which days you applied which rules (so perhaps each day group would have a set of 7 tickboxes for days of the week, and you’d tick which days it applied to). Or you could just have “weekday” and “weekend” as two separate groups, and avoid that extra configurability. Essentially you’d end up with two groups of times – one for weekday and one for weekend – for each zone.

    I’d probably lean towards the weekend logic, because you could also then write code that was aware of public holidays, and so public holidays could automatically be treated as weekend days.

    Then in the “zone_setpoints_from_times” rules you’d add a block that determines whether you’re a weekday or a weekend day, and chooses which group of settings to run for the rest of the function.

    I have implemented an away mode in my code, along with a bunch of other stuff since I wrote this post, let me work out how to best share that as a whole, but the bits that relate directly to away mode are (and the related master on/off, and an ability to turn the guest zone on/off when nobody is visiting):


    Switch swMasterHeating “Heating Master On/Off” (InternalFlags, Switches, InitSwitchesOn)
    Switch swHeatingAway “Heating Away Mode” (InternalFlags, Switches, InitSwitchesOff)


    sitemap default label=”Home Heating” {
    Frame label=”Master Settings” {
    Switch item=swMasterHeating
    Switch item=swHeatingAway
    Switch item=swGuest


    This function calculates the correct temp for a given zone, and only changes that
    setpoint if it’s different than what’s already set (to avoid needlessly cascading changes, which
    would override any temporary settings made via a wall thermostat).
    If the zone is turned off, it sets the temp to 5

    val org.eclipse.xtext.xbase.lib.Functions$Function1 setZoneSetpoint = [
    org.openhab.core.items.GroupItem zone |

    var int currentHours = now().getHourOfDay()
    var int currentMinutes = now().getMinuteOfHour()
    var int currentTime = currentHours * 100 + currentMinutes

    logDebug( ‘zones’, ‘Calculating setpoint for ‘ + + ‘ at time ‘ + currentTime )

    var org.openhab.core.items.GroupItem settings = zone.members.filter( m |‘zoneSettings’)).last
    var org.openhab.core.items.GroupItem times = settings.members.filter( m |‘zoneSettingsTimes’)).last

    /* we use the setpoint from the highest time that is less than the current time. If there isn’t one less than current time,
    then we use the last setpoint, which should be the night setpoint. We assume settings are in time order, if someone
    sets time1 to be higher than time2, then this will break */
    var org.openhab.core.items.GroupItem lastTime = times.members.last
    var int setpointNumber = 0

    times.members.forEach( aTime | {
    var int time = (aTime.state as DecimalType).intValue

    logDebug( ‘zones’, ‘Checking time ‘ + time + ‘ against currentTime ‘ + currentTime )

    if( time <= currentTime ) {
    setpointNumber = setpointNumber + 1
    lastTime = aTime
    logDebug( 'zones', 'Was less than or equal' )

    /* night setpoint when early hours of morning */
    if( setpointNumber == 0 ){
    setpointNumber = 4

    var org.openhab.core.items.GroupItem setPoints = settings.members.filter( m |'zoneSettingsSetpoints')).last
    var int newSetpoint = ( setPoints.members.filter( m |'set' + setpointNumber)).last.state as DecimalType )
    var org.openhab.core.library.items.NumberItem currentSetpoint = settings.members.filter( m |'setCurrent')).last

    if( settings.members.filter( m |'sw')).last.state == OFF ){
    newSetpoint = 10 // set the valve to 10 degrees, which we treat as effectively off

    logDebug( 'zones', 'Calculated setpoint for zone ' + + ' is setpointNumber ' + setpointNumber + ' with value of ' + newSetpoint + ', old setpoint was ' + currentSetpoint.state )

    if( swHeatingAway.state == ON ){
    if( currentSetpoint.state as DecimalType != numberHeatingAwaySetpoint.state as DecimalType ){
    logDebug( 'zones', 'Set to away, use awaySetpoint' )
    postUpdate( currentSetpoint, numberHeatingAwaySetpoint.state as DecimalType )
    // no else – if the setpoint matches nothing to do
    } else if( currentSetpoint.state == Uninitialized || newSetpoint != (currentSetpoint.state as DecimalType) ) {
    postUpdate( currentSetpoint, newSetpoint )

  36. I’d also note that writing rules is incredibly fiddly – the syntax is annoyingly obscure and therefore generates a lot of errors, and there are basically no error messages, so things just stop working sometimes with a stack trace, and sometimes silently. Lots of debug statements is the secret, and lots and lots of testing as you write code – basically testing after every line of code that you write to make sure it does what you think it does (including debug statements to print out the values of what you thought you changed).

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s