Complicated Heating Rule

  • Platform information:
    • Hardware: Pine A64/1GB/16GB
    • OS: Ubuntu 16.04.3 LTS
    • Java Runtime Environment: Zulu 8
    • openHAB version: 2.1.0-1 (Release Build)

Hi, this is my first problem which I can’t solve by myself or by searching in this forum.

Background info: I live in an apartment which has the “HomeMatic Wireless Room Thermostats” and “HomeMatic Wireless Switch Actuators” build in. So I just bought an CCU2 and connected everything with openhab. The system works great. The switches are connected directly to the thermostats so I can have a backup solution through the CCU2 if one day openhab stops working. So I have to say to the thermostat what temperature I need instead of switching the switches directly ON/OFF.

Here are the used Items

Number Temp_Wohnen "Wohnen Temperatur [%.1f °C]" {channel="homematic:HM-TC-IT-WM-W-EU:64bfae6d:MEQ0089370:2#ACTUAL_TEMPERATURE"}
Number Soll_Temp_Wohnen "Wohnen Soll Temperatur [%.1f C]" {channel="homematic:HM-TC-IT-WM-W-EU:64bfae6d:MEQ0089370:2#SET_TEMPERATURE"}
Group:Switch:OR(ON,OFF) gAnwesenheit "Anwesenheit [MAP(presence.map):%s]"
Switch Urlaub "Urlaub"
Number Heizung_Zusatz "Temperatur Zusatz [%.1f °C]"
Switch Schlafen_Wochentage "Schlafen Wochentage"

And here the Rule

rule "Wohnen Heizen"
when
    Item Temp_Wohnen changed or
    Item gAnwesenheit changed or
    Item Schlafen_Wochentage changed or
    Item Urlaub changed
then
        var Number solltemphoch = 23
        var Number solltempmittel = 19
        var Number solltemptief = 12
        var Number isttemp = Temp_Wohnen.state as DecimalType
        var Number hysteresis = 1
        var Number zusatz = Heizung_Zusatz.state as DecimalType
    /* Heizung Anwesend Wach */
    if (gAnwesenheit.state == ON && Schlafen_Wochentage.state == OFF){
    	if (isttemp <= (solltemphoch - hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltemphoch + hysteresis + zusatz) }
        else if (isttemp > (solltemphoch + hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltemphoch - hysteresis + zusatz) }
    }
    /* Heizung Anwesend Schlafen */
    else if (gAnwesenheit.state == ON && Schlafen_Wochentage.state == ON){
    	if (isttemp <= (solltempmittel - hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltempmittel + hysteresis + zusatz) }
        else if (isttemp > (solltempmittel + hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltempmittel - hysteresis + zusatz) }
    }
    /* Heizung nicht Anwesend */
    else if (gAnwesenheit.state == OFF && Urlaub.state == OFF){
    	if (isttemp <= (solltempmittel - hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltempmittel + hysteresis + zusatz) }
        else if (isttemp > (solltempmittel + hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltempmittel - hysteresis + zusatz) }
    }
    /* Heizung Urlaub */
    else if (gAnwesenheit.state == OFF && Urlaub.state == ON){
    	if (isttemp <= (solltemptief - hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltemptief + hysteresis + zusatz) }
        else if (isttemp > (solltemptief + hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltemptief - hysteresis + zusatz) }
    }
end

Eclipse dosen’t give me any error. Karaf loads the rule normaly without error. BUT the rule won’t execute. If an Item “changed” Openhab does nothing. Somehow it gets ignored. When I replace the rule with an easy ON/OFF switch like

rule "Wohnen Heizen"
when
    Item Temp_Wohnen changed or
    Item gAnwesenheit changed or
    Item Schlafen_Wochentage changed or
    Item Urlaub changed
then
    switch.sendCommand(ON)
end

it fires without hesitation. So I think something with the rule is not correct.

Could someone please look at the rule and give me a hint?

I would first off add in some logging messages in the rule - this will then let you track down what is being done and what is not.

http://docs.openhab.org/administration/logging.html#create-log-entries-in-rules

Hi Garry

A very good point. Changed the rule to

rule "Wohnen Heizen"
when
	Item Temp_Wohnen received update or
    Item gAnwesenheit changed or
    Item Schlafen_Wochentage changed or
    Item Urlaub changed or
    Item Licht_Kueche_Esstisch changed
then
        var Number solltemphoch = 23
        var Number solltempmittel = 19
        var Number solltemptief = 12
        var Number isttemp = Temp_Wohnen.state as DecimalType
        var Number hysteresis = 1
        var Number zusatz = Heizung_Zusatz.state as DecimalType
    /* Heizung Anwesend Wach */
    if (gAnwesenheit.state == ON && Schlafen_Wochentage.state == OFF){
    	if (isttemp <= (solltemphoch - hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltemphoch + hysteresis + zusatz) }
        else if (isttemp > (solltemphoch + hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltemphoch - hysteresis + zusatz) }
        else logInfo("wohnen.rules", "Heizung Anwesend Wach skipped")
    } 
    /* Heizung Anwesend Schlafen */
    else if (gAnwesenheit.state == ON && Schlafen_Wochentage.state == ON){
    	if (isttemp <= (solltempmittel - hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltempmittel + hysteresis + zusatz) }
        else if (isttemp > (solltempmittel + hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltempmittel - hysteresis + zusatz) }
        else logInfo("wohnen.rules", "Heizung Anwesend Schlafen skipped")
    }
    /* Heizung nicht Anwesend */
    else if (gAnwesenheit.state == OFF && Urlaub.state == OFF){
    	if (isttemp <= (solltempmittel - hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltempmittel + hysteresis + zusatz) }
        else if (isttemp > (solltempmittel + hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltempmittel - hysteresis + zusatz) }
        else logInfo("wohnen.rules", "Heizung nicht Anwesend skipped")
    }
    /* Heizung Urlaub */
    else if (gAnwesenheit.state == OFF && Urlaub.state == ON){
    	if (isttemp <= (solltemptief - hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltemptief + hysteresis + zusatz) }
        else if (isttemp > (solltemptief + hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltemptief - hysteresis + zusatz) }
        else logInfo("wohnen.rules", "Heizung nicht Anwesend skipped")
    }
    else logInfo("wohnen.rules", "Everything skipped")
end

Now I can see that it stops after the first “if”. After that it dosen’t log anymore.

[INFO ] [.smarthome.model.script.wohnen.rules] - Heizung Anwesend Wach skipped

But why? I must have made some stupid mistake in my rule but I can’t see it.

Everything else is in an “else if” - it is matching the state for the first “if” so won’t go into these.

If you want all 4 top level comparisons to be made, have each of them as a separate “if” statement, like this:

rule "Wohnen Heizen"
when
	Item Temp_Wohnen received update or
    Item gAnwesenheit changed or
    Item Schlafen_Wochentage changed or
    Item Urlaub changed or
    Item Licht_Kueche_Esstisch changed
then
        var Number solltemphoch = 23
        var Number solltempmittel = 19
        var Number solltemptief = 12
        var Number isttemp = Temp_Wohnen.state as DecimalType
        var Number hysteresis = 1
        var Number zusatz = Heizung_Zusatz.state as DecimalType
    /* Heizung Anwesend Wach */
    if (gAnwesenheit.state == ON && Schlafen_Wochentage.state == OFF){
    	if (isttemp <= (solltemphoch - hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltemphoch + hysteresis + zusatz) }
        else if (isttemp > (solltemphoch + hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltemphoch - hysteresis + zusatz) }
        else logInfo("wohnen.rules", "Heizung Anwesend Wach skipped")
    } 
    /* Heizung Anwesend Schlafen */
    if (gAnwesenheit.state == ON && Schlafen_Wochentage.state == ON){
    	if (isttemp <= (solltempmittel - hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltempmittel + hysteresis + zusatz) }
        else if (isttemp > (solltempmittel + hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltempmittel - hysteresis + zusatz) }
        else logInfo("wohnen.rules", "Heizung Anwesend Schlafen skipped")
    }
    /* Heizung nicht Anwesend */
    if (gAnwesenheit.state == OFF && Urlaub.state == OFF){
    	if (isttemp <= (solltempmittel - hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltempmittel + hysteresis + zusatz) }
        else if (isttemp > (solltempmittel + hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltempmittel - hysteresis + zusatz) }
        else logInfo("wohnen.rules", "Heizung nicht Anwesend skipped")
    }
    /* Heizung Urlaub */
    if (gAnwesenheit.state == OFF && Urlaub.state == ON){
    	if (isttemp <= (solltemptief - hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltemptief + hysteresis + zusatz) }
        else if (isttemp > (solltemptief + hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltemptief - hysteresis + zusatz) }
        else logInfo("wohnen.rules", "Heizung nicht Anwesend skipped")
    }
end
rule "Wohnen Heizen"
when
	Item Temp_Wohnen received update or
    Item gAnwesenheit changed or
    Item Schlafen_Wochentage changed or
    Item Urlaub changed or
    Item Licht_Kueche_Esstisch changed
then
        var Number solltemphoch = 23
        var Number solltempmittel = 19
        var Number solltemptief = 12
        var Number isttemp = Temp_Wohnen.state as DecimalType
        var Number hysteresis = 1
        var Number zusatz = Heizung_Zusatz.state as DecimalType
    /* Heizung Anwesend Wach */
    if (gAnwesenheit.state == ON && Schlafen_Wochentage.state == OFF){
    	if (isttemp <= (solltemphoch - hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltemphoch + hysteresis + zusatz) }
        else if (isttemp > (solltemphoch + hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltemphoch - hysteresis + zusatz) }
        else logInfo("wohnen.rules", "Heizung Anwesend Wach skipped")
    } 
    /* Heizung Anwesend Schlafen */
    if (gAnwesenheit.state == ON && Schlafen_Wochentage.state == ON){
    	if (isttemp <= (solltempmittel - hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltempmittel + hysteresis + zusatz) }
        else if (isttemp > (solltempmittel + hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltempmittel - hysteresis + zusatz) }
        else logInfo("wohnen.rules", "Heizung Anwesend Schlafen skipped")
    }
    /* Heizung nicht Anwesend */
    if (gAnwesenheit.state == OFF && Urlaub.state == OFF){
    	if (isttemp <= (solltempmittel - hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltempmittel + hysteresis + zusatz) }
        else if (isttemp > (solltempmittel + hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltempmittel - hysteresis + zusatz) }
        else logInfo("wohnen.rules", "Heizung nicht Anwesend skipped")
    }
    /* Heizung Urlaub */
    if (gAnwesenheit.state == OFF && Urlaub.state == ON){
    	if (isttemp <= (solltemptief - hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltemptief + hysteresis + zusatz) }
        else if (isttemp > (solltemptief + hysteresis)) { Soll_Temp_Wohnen.sendCommand(solltemptief - hysteresis + zusatz) }
        else logInfo("wohnen.rules", "Heizung nicht Anwesend skipped")
    }
    else logInfo("wohnen.rules", "Everything skipped")
end

Changed it to your suggestion. The output is

[INFO ] [.smarthome.model.script.wohnen.rules] - Heizung Anwesend Wach skipped
[INFO ] [.smarthome.model.script.wohnen.rules] - Everything skipped

So now the rule ends but it still skips the other “if”. I am trying/triggering the rule with the “Schlafen_Wochentage Switch” so it should do the first or the second “if”.

It looks to me like it’s working OK, based on what you’re asking it to do… It’s going into 1 of the 4 top-level if statements only :slight_smile:

The next question is whether the calculations you’re trying to do are correct - add a log line to log the values of isttemp and zusatz, such as:

logDebug("wohnen.rules", "isttemp: %1$.1f, zusatz: %2$.1f", isttemp, zusatz)

You are right. The rule syntax is correct. Also correct are the calculations. Due to your tip to add some logging to the rule I could manage to find where the problem resides. It is in the presence (FritzTR064) bindning which has detection problems with their new wifi-mesh system. I hope they figure it out so it doesn’t come to interupts anymore.

I am posting the final working rule code for everyone who needs heating calculations based on hysteresis, vacation, sleeptime, presence and logging info.

rule "Wohnen Heizen"
when
	Item Temp_Wohnen received update or
    Item gAnwesenheit changed or
    Item Schlafen_Wochentage changed or
    Item Urlaub changed
then
        var Number hysteresis = 1
        var Number solltempanwesend = 17
        var Number solltempschlafen = 18
        var Number solltempnichtanwesend = 16
        var Number solltempurlaub = 12
        var Number isttemp = Temp_Wohnen.state as DecimalType
        var Number zusatz = Heizung_Zusatz.state as DecimalType
    /* Heizung Anwesend Wach */
    if (gAnwesenheit.state == ON && Schlafen_Wochentage.state == OFF){
	   	if (isttemp <= (solltempanwesend - hysteresis)) {logInfo("wohnen.rules", "Condition1/1") Soll_Temp_Wohnen.sendCommand(solltempanwesend + hysteresis + zusatz)}
        if (isttemp > (solltempanwesend + hysteresis)) {logInfo("wohnen.rules", "Condition1/2") Soll_Temp_Wohnen.sendCommand(solltempanwesend - hysteresis + zusatz)}
        if ((isttemp >= (solltempanwesend - hysteresis)) && (isttemp <= (solltempanwesend + hysteresis))) {logInfo("wohnen.rules", "Condition1/im Hysteresebereich")}
    } 
    /* Heizung Anwesend Schlafen */
    if (gAnwesenheit.state == ON && Schlafen_Wochentage.state == ON){
    	if (isttemp <= (solltempschlafen - hysteresis)) {logInfo("wohnen.rules", "Condition2/1") Soll_Temp_Wohnen.sendCommand(solltempschlafen + hysteresis + zusatz)}
        if (isttemp > (solltempschlafen + hysteresis)) {logInfo("wohnen.rules", "Condition2/2") Soll_Temp_Wohnen.sendCommand(solltempschlafen - hysteresis + zusatz)}
        if ((isttemp >= (solltempschlafen - hysteresis)) && (isttemp <= (solltempschlafen + hysteresis))) {logInfo("wohnen.rules", "Condition2/im Hysteresebereich")}
    }
    /* Heizung nicht Anwesend */
    if (gAnwesenheit.state == OFF && Urlaub.state == OFF){
    	if (isttemp <= (solltempnichtanwesend - hysteresis)) {logInfo("wohnen.rules", "Condition3/1") Soll_Temp_Wohnen.sendCommand(solltempnichtanwesend + hysteresis + zusatz)}
        if (isttemp > (solltempnichtanwesend + hysteresis)) {logInfo("wohnen.rules", "Condition3/2") Soll_Temp_Wohnen.sendCommand(solltempnichtanwesend - hysteresis + zusatz)}
        if ((isttemp >= (solltempnichtanwesend - hysteresis)) && (isttemp <= (solltempnichtanwesend + hysteresis))) {logInfo("wohnen.rules", "Condition3/im Hysteresebereich")}
    }
    /* Heizung Urlaub */
    if (gAnwesenheit.state == OFF && Urlaub.state == ON){
    	if (isttemp <= (solltempurlaub - hysteresis)) {logInfo("wohnen.rules", "Condition4/1") Soll_Temp_Wohnen.sendCommand(solltempurlaub + hysteresis + zusatz)}
        if (isttemp > (solltempurlaub + hysteresis)) {logInfo("wohnen.rules", "Condition4/2") Soll_Temp_Wohnen.sendCommand(solltempurlaub - hysteresis + zusatz)}
        if ((isttemp >= (solltempurlaub - hysteresis)) && (isttemp <= (solltempurlaub + hysteresis))) {logInfo("wohnen.rules", "Condition4/im Hysteresebereich")}
    }
end

Thank you Garry for pointing me to the right direction.

1 Like