Issue with logic of nested conditions

  • Platform information:
    • Hardware: rPi3
    • OS: Openhabian
    • openHAB version: 2.2

Issue of the topic: I want to drive activate a fan in the bathroom based on humidity sensor. If the humidity goes above 55% the fan should be turned on. However the fan should be never deactivate when it was turned on manually. In order accomplish this i created a virtual fan switch, when the rule turns on the fan it turns on the virtual fan switch. The rule can only turn off the fan if the virtual fan switch has been turned on. In order to avoid the fan to be reactivated with each temperature change i added a condition that the fan can only be turned on when it it is off.

The rule works fine at first but it than breaks somewhere and the fan turns itself off and the vfan does not match the humidity anymore. This leads me to believe there is some logical error but I am a newbie at programming so I am not able to find it.

Therefore I am hoping some smarter people can help me figure it out.

Number B2_Humidity    "Badkamer Boven [%.1f %%]"          <humidity>    [ "CurrentHumidity" ]    { channel="mihome:sensor_ht:158d0001e878ef:humidity" }
Switch vFan1           "Vochtig Beneden"   // Ventilator aan door vochtigheid
rule "MANAGE FAN B1"
when 
     Item B1_Humidity changed
then
     if (B1_Humidity.state > 55) && (Ventilator == OFF) {
       sendCommand(vFan1,ON)
       sendCommand(Ventilator,ON)
       logInfo("logFan", "Hoge Vochtigheid Boven, zet ventilator aan.")
       }
      else (B1_Humidity.state < 55) && (vFan1 == ON) {
       sendCommand(Ventilator,OFF)
       sendCommand(vFan1,OFF)     
       logInfo("logFan", "Lage Vochtigheid B1, zet ventilator uit.")
       }
end

Remove this I think… (B1_Humidity.state < 55) && (vFan1 == ON)

So, just,

else { …
…}

If you looked at this in VS Code or watched the openhab.log after saving the file, you’d see a few issues reported.

rule "MANAGE FAN B1"
when
    Item B1_Humidity changed
then
    if (B1_Humidity.state >= 55) {// changed to >= so 55 wouldn't be left out
        if (Ventilator.state == OFF) {// missing .state, added new block to help logic
            sendCommand(vFan1,ON)
            sendCommand(Ventilator,ON)
            logInfo("logFan", "Hoge Vochtigheid Boven, zet ventilator aan.")
        }
    }
    else {
        if (Ventilator.state == ON && vFan1.state == ON) {
            sendCommand(Ventilator,OFF)
            sendCommand(vFan1,OFF)     
            logInfo("logFan", "Lage Vochtigheid B1, zet ventilator uit.")
        }
    }
end

[EDIT: Corrected mistakes pointed out by @hr_2. Gotta stop replying from my phone :roll_eyes:!]

If @jmccoy555’s suggestion is not what you want, change the line to this…

else if ((B1_Humidity.state &lt; 55) && (vFan1 == ON)) {

or this style as I cant check your actual conditions are correct…

else if (Ventilator.state == ON && vFan1 == ON) {

the syntax is
if (condition){
}
else if (condtiion){
}
else{
}

First thanks for the input from everyone. Much appreciated.
I found the issue but I can not explain it myself. I went back to basics and cut the rule in two. This showed me that the issue was in the 2nd part. When i have one circular reference (reference the item in the if and the action) if works like below.

   ...
then
     if (B1_Humidity.state > 60)
      {
       if  (Ventilator.state == ON)
	   {
            sendCommand(Ventilator,OFF)
            sendCommand(vFan1,OFF) 
           }
      }
end

but when have two circular references like below rule breaks. The issue is not the vFan1 item i switched in the above example with a single reference and there it works. It really is the two if statements with items that are also present in the action. I find this really weird and sounds like a bug.

   ...
then
     if (B1_Humidity.state > 60)
      {
       if  (Ventilator.state == ON)
       {
        if (vFan1.state == ON)
	   {
            sendCommand(Ventilator,OFF)
            sendCommand(vFan1,OFF) 
           }
        }
      }
end

I now have the below rule which if functionally fine because the 2nd if was actually redundant in the logic. The ventilator would always be on of vFan1 would be on.
It would be good however to understand the source of the issue.

// ------------------------SET FAN BY HUMIDITY

rule "START FAN B1"
when 
     Item B1_Humidity changed
then
     if (B1_Humidity.state > 60)
      {
       if  (Ventilator.state == OFF)
	   {
       sendCommand(Ventilator,ON)
       sendCommand(vFan1,ON)
	   logInfo("logFan", "Hoge Vochtigheid B1, zet ventilator aan.")
       }
	  }
end

rule "STOP FAN B1"
when 
     Item B1_Humidity changed
then
     if (B1_Humidity.state < 59)
      {
       if  (vFan1.state == ON)
	   {
            sendCommand(Ventilator,OFF)
            sendCommand(vFan1,OFF)     
            logInfo("logFan", "Lage Vochtigheid B1, zet ventilator uit.")
        }
	   }
end

Two problems:

You define B2_ and use later B1_

The example from @5iver is good, but I corrected 2 little mistakes

rule "MANAGE FAN B1"
when
    Item B1_Humidity changed
then
    if (B1_Humidity.state >= 55) {// changed to >= so 55 wouldn't be left out
        if (Ventilator.state == OFF) {// missing .state, added new block to help logic
            sendCommand(vFan1,ON)
            sendCommand(Ventilator,ON)
            logInfo("logFan", "Hoge Vochtigheid Boven, zet ventilator aan.")
        }
    }
    else {
        if (Ventilator.state == ON && vFan1.state == ON) {
            sendCommand(Ventilator,OFF)
            sendCommand(vFan1,OFF)     
            logInfo("logFan", "Lage Vochtigheid B1, zet ventilator uit.")
        }
    }
end

I checked. It works.

2 Likes

This is just a typo as I have 2 setup B1 and B2. My item definition and rules have it setup for B1 and B2. But good eye!

The below finally did the trick and is more elegant than my solution of cutting the rules in pieces.
Thanks to all

rule "MANAGE FAN B1"
when
    Item B1_Humidity changed
then
    if (B1_Humidity.state >= 55) {// changed to >= so 55 wouldn't be left out
        if (Ventilator.state == OFF) {// missing .state, added new block to help logic
            sendCommand(vFan1,ON)
            sendCommand(Ventilator,ON)
            logInfo("logFan", "Hoge Vochtigheid Beneden, zet ventilator aan.")
        }
    }
    else {
        if (Ventilator.state == ON && vFan1.state == ON && B1_Humidity.state < 55) {
            sendCommand(Ventilator,OFF)
            sendCommand(vFan1,OFF)     
            logInfo("logFan", "Lage Vochtigheid B1, zet ventilator uit.")
        }
    }
end

You really don’t need this, since it will always be true.

I agree with @5iver. So the statement doesn’t make sence.

Only if you wont to have a gap between ON and OFF, because not permanantly switching, take

if (B1_Humidity.state > 57 && Ventilator.state == OFF) {
    ...
    }
else if (B1_Humidity.state < 55 && Ventilator.state == ON && vFan1.state == ON) {
2 Likes

Recommend you watch some of these videos…
This one is nested If statements, but he has a heap which they are only 5minutes long and exactly to the point. Issue is the rules are not pure java (xtend) so it is limited but some of the basics will be helpful.