I need help configuring my heating control

Hello dear Openhab Community,
I need help with the configuration or the plans for my heating control. I currently have 11 Eurotronic Spirit (Zwave) installed on my radiators. These are set to the respective temperature at different times using simple rules. Now I have come across several interesting posts here in the forum (Timeline picker to setup heating, light and so on, https: // Yet another Heating Setup) which in principle (with a few small deviations) completely correspond to my ideas. Due to the large number of requests I have, as a beginner I have absolutely no idea how and with what best to start. I’m not even sure if my plan can be realized at all.

To my ideas:

  • The heating control should have an automatic mode, in which all radiators, as the name suggests, are automatically controlled and have a manual mode in the event that something changes spontaneously (home office) and you want to change the heating plan for a day. This manual mode must of course overwrite the automatic mode for this day and reset by a rule at night or switch back to the automatic mode.
  • I would like to be able to select or set 3 states via the timeline. That would be “night”, “absent” and “heating”
  • I would like to be able to set the radiators with different temperatures for these 3 “states”.
    “Heating” on Monday: 5-8 am. During this time, the bathroom, kitchen, living room and dining room should be heated to a temperature of 21 ° C. The bedroom and study, however, only 18 ° C
  • It should be possible to select different heating modes (normal, vacation, absent and off-summer mode). A separate timeline should run behind each heating mode.

Can you tell me whether my ideas could even be implemented? And don’t get me wrong, nobody should create a complete heating plan for me here. I definitely want to learn something and, above all, understand the background. So far I have been able to implement all of my wishes through Howtos from various forums, possibly in a modified form. But now I’ve come to a point where I can’t get any further. As I have never done anything like this before, as a beginner I don’t know where to start and how to proceed in a structured manner to reach the goal.
So I ask you for help.
At the end I wanted to mention that the timeline from the post (Timeline picker to setup heating, light and so on) goes so far with me is working. I am currently switching a few lamps on the timeline for testing purposes.

Greetings Didschu

  • Platform information:
    • Hardware: CPUArchitecture/RAM/storage
    • OS: what OS is used and which version
    • Java Runtime Environment: which java platform is used and what version
    • openHAB version:
  • Issue of the topic: please be detailed explaining your issue
  • Please post configurations (if applicable):
    • Items configuration related to the issue
    • Sitemap configuration related to the issue
    • Rules code related to the issue
    • Services configuration related to the issue
  • If logs where generated please post these here using code fences:

I am curious about the heating system you are using. I live in North-America and here we have hot water radiators, electric radiators and we have forced air heating systems.
I am interested in your project because I am also working on heating control for an electric radiators system.


As it is a general how do I do this and not such a specific issue or multiple I will give some ideas.

In my system I use time of day rules to know when to do things.

Design Pattern: Time Of Day

This can act to help you adapt your system during the day.

Create a string item named something like

// To track mode of Heating  Acceptable modes are - night absent auto off overide
String Heating_MODE

Next you have to make sure that when oh starts it is put in to a mode and not null. Eater setup a rule or install persistence on the item.

Now that you have an item to manipulate you need to thing of all the conditions you want met to change the string.

eg when the string is override and it is midnight change to auto or night.

As i wrote before, your wishes are a really big challange.
For starting you should define for each room three setpoint items.
Setup a single timelinepicker for global heating mode selection.
Now you can start with coding.
The trigger for setpoint changes is easy. This is the assoziated item from the timeline. So you never need a polling over the day.

I would suggest start with jsr223 not the old rule DSL. I’m using javascript and be able to write good structured code.

First of all, many thanks for the nice description and useful links.
In the last two days I have read in something and then started my configuration.
First, as you recommended, I created a switch item to switch between automatic and manual mode. Finally I created a string item where I can switch between the individual modes (normal, absent, vacation and OFF). In addition, a visibility switch was created in order to hide or show things later when changing between automatic and manual mode.


Switch      Heating_Mode            "Mode []"                   <none>          (gHeating)
String      Heating_Plan            "Heizungsmodus [%s]"        <none>          (gHeating)
Switch      Heating_Visibility                                                  (gHeating)

In the next step I tried, as recommended, that the items are set to the correct state at system start.


Strategies {
  default = everyUpdate

Items {
  gTimepicker* : strategy = everyChange, restoreOnStartup
  Heating_Plan : strategy = everyChange, restoreOnStartup
  Heating_Mode : strategy = everyChange, restoreOnStartup
  Heating_Visibility : strategy = everyChange, restoreOnStartup

Next I took care of the sitemap. In the first frame you can select the heating mode and then switch between auto and manual. Due to the visibility the frame of the automatic mode is hidden in manual mode and it is the same the other way around.


Text label="Heizung" icon="heating" {
            Frame label="Allgemeines" {
                Selection item=Heating_Plan label="Heizmodus (Wohnung) [%s]" mappings=[NORMAL="Normal",URLAUB="Urlaub",ABWESEND="Abwesend",SOMMERMODUS="Aus (Sommer-Standby)"]  
            		Switch item=Heating_Mode label="Betriebsmodus []" mappings=[ON="Manual", OFF="Auto"] 
            Frame label="Automatik Modus" visibility=[Heating_Visibility=="OFF"] {
                Text label="Hier muss die Automatik Temperatur eingestellt werden"
            Frame label="Manueller Modus" visibility=[Heating_Visibility=="ON"] {
                Text label="Hier muss die Manuelle Temperatur eingestellt werden"

The manual mode is also set back to automatic mode at 2 a.m. via rules.

rule "Zurücksetzen des Manuellen Modus um 2 Uhr" 
    Time cron " 0 0 2 1/1 * ? * "
    if(Heating_Mode.state == ON) {
        sendCommand(Heating_Mode, OFF)
        logInfo("Heizung", "Manueller Modus wurde zurück in den Automatik Modus gesetzt")

Now I am faced with the problem that I do not know how to regulate the heating. I would like to have a timeline for Normal, Away and Vacation modes. So far no problem, I created the following items first.


Group                   gTimepicker
Group                   gTimepickerObserver
String                  TimelineHelper                  "[%s]"        (gTimepicker)
String                  TransferItem1                   "[%s]"        (gTimepicker)
String                  TransferItem2                   "[%s]"        (gTimepicker)
String                  TransferItem3                   "[%s]"        (gTimepicker)

String                  Automatik_Heizmodus_Normal      "[%s]" 
String                  Automatik_Heizmodus_Urlaub      "[%s]"
String                  Automatik_Heizmodus_Abwesend    "[%s]"

The transfer items were then set in the timeLinePicker.rules

// -------------------- part of config -----------------------------------------------------------------------

val HashMap<String,ArrayList<String>> timePicker = newHashMap(
    "TransferItem1" -> newArrayList('Automatik_Heizmodus_Normal'),
    "TransferItem2" -> newArrayList('Automatik_Heizmodus_Urlaub'),
    "TransferItem3" -> newArrayList('Automatik_Heizmodus_Abwesend')

// -------------------- end of config ------------------------------------------------------------------------

I then added a webview to the sitemap for the respective mode

Webview icon="none" url=",Heizen,Abwesend&yAxisLabel=1,2,3,4,5,6,7&lang=de&dark=yes&deactivation=true" height=14 visibility=[Heating_Plan==NORMAL]
Webview icon="none" url=",Heizen,Abwesend&yAxisLabel=1,2,3,4,5,6,7&lang=de&dark=yes&deactivation=true" height=14 visibility=[Heating_Plan==URLAUB]
Webview icon="none" url=",Heizen,Abwesend&yAxisLabel=1,2,3,4,5,6,7&lang=de&dark=yes&deactivation=true" height=14 visibility=[Heating_Plan==ABWESEND]

Depending on the automatic mode, the corresponding is then also displayed by the visibility. Here, too, no timeline is displayed when manual mode is selected. On every timeline I now have a status night, heating and absent. The entries I made are also saved by the entry in the mapdb.

Next I have to somehow manage to regulate the radiators depending on the status (night, heating or vacation). Now you could theoretically set a temperature behind each status and thus bring the radiators to this temperature. But I would also like to be able to change this using a setpoint and, as already mentioned in my previous post, not all rooms are given the same temperature. And there is also the fact that when changing the mode from e.g. Normally on vacation the values from the other timeline are also adopted.

Does anyone have any idea how to do this? Possibly. I also think that it is just too complicated and it’s much easier, so I’m open to alternatives.

Greetings Danny

It becomes surely very complex to determine the different states from your items and the three timelines.

Better you define and switch various states in varoius items as global state.
(heating mode global, heating mode over the day, room mode (reduce - yes/no, …)
At each point the ‘heating mode over the day’ or ‘heating mode global’ will changed you can call a function that determines the correct setpoint for the single rooms. Also a restart is not a problem. Call this function at startup.

1 Like

Perhaps you can explain this to me using a short example. I didn’t quite understand it.

I can try it in a short maner:
this is not working code, only an overview

// item's
Number HeatingGlobal       // 0 = off, 1 = auto ,2 = absent, ...
Number HeatingDay          // 1 on, 2 = reduce  !! controlled through the timeline !!

Number living_day          // living setpoint day mode
Number living_reduce       // living setpoint reduce mode
Number living_mode         // redude mode:  0 allowed, 1 = not allowed

Number livingThermostat    // binding information for reeal thermostat

// rules (jsr - javascript)
var heatingGlobal = getItem('HeatingGlobal').state
var heatingDay = getitem('HeatingDay').state
var heatingReduce = getItem('Heatingreduce').state

if (heatingGlobal != 0) {
  if (heatingGlobal = 1) {
    sendCommand('livingThermostat', HeatingDay == 1 ? living_day : living_reduce)
  if (heatingGlobal = 2) {
    sendCommand('livingThermostat',  living_mode == 1 ? living_day : living_reduce)

You need a structure for all rooms and the corresponding data. So you can iterate over this struckture and bind the correct thermostats to the correct room.

Thank you for the example. I slowly understand what you mean.
But that it’s pretty much new territory for me, I’ll try to give it again with my words:

With the item “HeatingGlobal” the respective mode is selected as setpoint via the sitemap. The item “HeatingDay” is the timeline item which us for the rule the respective current
State (heating, absent, night)? With the items “living_day” and “living_reduce” you can set the temperature via the sitemap. With the “living_mode” one could block the reduce mode (absent). The “living thermostat” would then be one of my thermostats which receives the target temperature?

With the excerpt from the example rule, I understand it to mean that a check is first made in which mode (auto, absent, etc.) we are and then a command is triggered?

But what I don’t understand at all is the following:

the “living thermostat” receives the command to heat

but what is happening here? Where does the heating Reduce and heatingDay come from? and what does that stand for? and the :

sorry for these stupid questions, but I also want to learn something.

Oh right, that’s not good. I will correct this in the mail above. Then the next one will not stumble at this point.

This is the short hand for:

if (cond) { true value} else { false value } 

Good evening,

I wanted to test your example rule in my system, unfortunately I’m just reaching my limits.
Here is my test config


Number HeatingGlobal       // 0 = off, 1 = auto ,2 = absent
String HeatingDay          // 0 = Nacht, 1 = Heizen, 2 = Abwesend 
Number living_day          // living setpoint day mode
Number living_reduce       // living setpoint reduce mode
Number living_mode         // redude mode:  0 allowed, 1 = not allowed
Number livingThermostat    // binding information for reeal thermostat


            Frame label="Test" {
                Selection item=HeatingGlobal label="Heizmodus (Wohnung) [%s]" mappings=[0="Aus",1="Auto",2="Komfort", 3="Abwesend",4="Urlaub"]
                Webview icon="none" url=",Heizen,Abwesend&yAxisLabel=1,2,3,4,5,6,7&lang=de&dark=yes&deactivation=true" height=14 
                Setpoint item=living_day label="Stellwert Warm (±1) [%.1f °C]" step=1.0 minValue=8 maxValue=28
                Setpoint item=living_reduce label="Stellwert eco (±1) [%.1f °C]" step=1.0 minValue=8 maxValue=28


rule "rule name"
    Item HeatingGlobal changed or
    Item HeatingDay changed or 
    Item living_day changed or
    Item living_reduce changed
    var heatingGlobal = getItem('HeatingGlobal').state
    var heatingday = getItem('HeatingDay').state

    if(heatingGlobal != 0) {
        if(heatingGlobal = 1 ) {
            sendCommand('AZ_Heizung_SetTemp', HeatingDay == 1 ? living_day : living_reduce) 
        if(heatingGlobal = 2) {
            sendCommand('AZ_Heizung_SetTem', living_mode == 1 ? living_day : living_reduce)

The following error message in the rule

2020-10-21 23:33:49.891 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model 'heizung.rules' has errors, therefore ignoring it: [60,44]: no viable alternative at input '='
[60,46]: extraneous input '1' expecting ')'
[61,61]: no viable alternative at input '?'
[61,76]: mismatched input ':' expecting '}'
[61,91]: extraneous input ')' expecting '}'
[66,5]: extraneous input '}' expecting 'end'

I still have to honestly admit that I just don’t understand the rule completely!
What exactly is going on here in this section?

HeatingDay == 1 ? living_day : living_reduce


living_mode == 1 ? living_day : living_reduce

Thanks for your help…

This was snippets in javascript (jsr223). You have mixed this with a rule in the old rules DSL.

Hm … although it is there I didn’t even notice it. Unfortunately I have absolutely no idea about it. I once looked up a little about jsr223 on the internet. Jython, Javascript and Groovy are used there. is your code javascript? then I would myself first
deal with it. Why would you not advise me to use DSL? I’m not a professional either, but there is at least a bit of basic knowledge here. With Javascript I start from scratch, which I would accept. If I have scanned it correctly, I have to install jsr on my system or make it workable.

Yes, it’s javascript and i’m only working with it. Javascript is much more flexible e.g. working with objects, simple use of functions, …

It’s not so difficult to rework it into DSL.

Can I theoretically use both, so both dsl and jsr?

But only with the right background knowledge. Currently I’m picking up so much new that I’m more confused than I understand anything, especially now with 2 rule engines

There are several rule languages available. They can be run alongside each other.
The two most popular in OH community -
DSL, now considered old school.
Jython, the new black.

Choose your poison, but yes one at a time is probably best for sanity.