[SOLVED] Rule interaction: postUpdate vs sendCommand

Hi,

i have two lights, which i want to turn on and off with a single button (virtual item called livingroomLights) in the dashboard (rule LivingRoom)
If only one lamo is still turned on, the button has to be switched on. If bothlamps turned off, the button has to be switched off (rule LivingRoomSwitch).

My Problem is that both rules mutually influence each other. I thought that postUpdate do not change other rules.

Can somebody help with this problem?

rule "LivingRoom"
when
    Item livingroomLights received command
then
    if(livingroomLights.state == OFF){
        logInfo("Rule LivingRoom", "livingroomLights.state == OFF");
        tradfri_0220_gwa03c2e6d394c_65537_brightness.sendCommand(OFF);    
        tradfri_0220_gwa03c2e6d394c_65538_brightness.sendCommand(OFF);        
    }    
    else if(livingroomLights.state == ON){
        logInfo("Rule LivingRoom", "livingroomLights.state == ON");
        tradfri_0220_gwa03c2e6d394c_65537_brightness.sendCommand(ON);    
        tradfri_0220_gwa03c2e6d394c_65538_brightness.sendCommand(ON);       
    }
end


rule "LivingRoomSwitch"
when    
    Item tradfri_0220_gwa03c2e6d394c_65537_brightness received command or
    Item tradfri_0220_gwa03c2e6d394c_65538_brightness received command
then
    if(tradfri_0220_gwa03c2e6d394c_65537_brightness.state instanceof PercentType || tradfri_0220_gwa03c2e6d394c_65538_brightness.state instanceof PercentType){
        val b1 = tradfri_0220_gwa03c2e6d394c_65537_brightness.state as Number;
        val b2 = tradfri_0220_gwa03c2e6d394c_65538_brightness.state as Number;
        if(b1 > 0 || b2 > 0){           
           livingroomLights.postUpdate(ON);
        }        
        if(b1 == 0 && b2 == 0){           
           livingroomLights.postUpdate(OFF);
        }
    }
end

Thank you in advance.

postUpdate() should not trigger received command. Be aware that there are some small issues:

rule "LivingRoom"
when
    Item livingroomLights received command
then
    logInfo("Rule LivingRoom", "livingroomLights received command {}",receivedCommand.toString)
    if(receivedCommand == OFF) {                                                                 // either OFF or ON
        tradfri_0220_gwa03c2e6d394c_65537_brightness.sendCommand(OFF)
        tradfri_0220_gwa03c2e6d394c_65538_brightness.sendCommand(OFF)
    } else {
        tradfri_0220_gwa03c2e6d394c_65537_brightness.sendCommand(ON)
        tradfri_0220_gwa03c2e6d394c_65538_brightness.sendCommand(ON)
    }
end

rule "LivingRoomSwitch"
when    
    Item tradfri_0220_gwa03c2e6d394c_65537_brightness changed or
    Item tradfri_0220_gwa03c2e6d394c_65538_brightness changed
then
    val b1 = if(tradfri_0220_gwa03c2e6d394c_65537_brightness.state instanceof Number)
        tradfri_0220_gwa03c2e6d394c_65537_brightness.state as Number
    else
        0
    val b2 = if(tradfri_0220_gwa03c2e6d394c_65538_brightness.state instanceof Number)
        tradfri_0220_gwa03c2e6d394c_65538_brightness.state as Number
    else
        0
    if(b1 + b2 > 0) {
        livingroomLights.postUpdate(ON)
    } else {
        livingroomLights.postUpdate(OFF)
    }
end

Please don’t use a semicolon ( ; ) after a command. If using received command as a trigger, better use the receivedCommand implicit var to react to the command, openHAB is asynchronous and there is a good chance that the state is not already the new state.

As the Item is of type Switch, the received command can either be ON or OFF (not NULL, this is no command but only a state!), so you don’t need to check over and over again.

For the second rule, I changed the trigger to changed, as this is more appropriate to the task.
Testing the state type for PercentType is ok, but Number would suffice, but it’s not ok only to test if one of two item states is of type PercentType and then forcing a type Number for both of them :wink:

I used an ternary operator, val a = if (z == y) b else c, this is: if true, use b, if false, use c

Last but not least, as b1 and b2 are numbers between 0 and 100, it’s sufficent to add them and check for 0.

1 Like

You could actually do that part with a Group instead of the first rule
Group:Switch:OR(ON,OFF) livingroomLights “Texty label”
and put the tradfri Items in that group

The Group automatically passes commands through to member Items

@Udo_Hartmann super job with rule and description!:+1:

Thanks

Thank you for your help and the hint to receivedCommand. I deleted the semicolons and also changed the trigger condition to changed.

@rossko57: I found that nice solution, too and i think i will do it so. Temporarily, i help me with a simple, quick & dirty “mutex” :wink:

mutex = 1
sendCmd
mutex=0

While sending the command, the receiving rule does not start if mutex = 1. It works - not nice, but it works stuck_out_tongue:

Update: i will test the postUpdate/sendCommand thing.

I did a test and now it works as plannend. I think it was the hint for the implicit variable and the trigger event change from received command to changed

If i use received command as trigger, postUpdate will trigger the rule!

Here is an exemple code:

virtual.items:

Dimmer allLightsBrightness "MasterLightBrightness" <slider>

Dimmer allLightsBrightness2 "MasterLightBrightness2" <slider>

Switch btn "Testbtn" <switch>

light.rules: sporadically the button is wrong

rule "recvCmd"
when
    Item btn received command
then      
       
            if(receivedCommand == OFF){
                logInfo("Rule recvCmd", "livingroomLights.state == OFF")
                allLightsBrightness.sendCommand(OFF)
                allLightsBrightness2.sendCommand(OFF)
            }    
            else{
                logInfo("Rule recvCmd", "livingroomLights.state == ON")
               allLightsBrightness.sendCommand(ON)
                allLightsBrightness2.sendCommand(ON)
            }   
end

 
rule "postUpdate"
when    
    Item allLightsBrightness received command or 
    Item allLightsBrightness2 received command
then    
        if(allLightsBrightness2.state instanceof Number || allLightsBrightness.state instanceof Number){

            val b1 = allLightsBrightness.state as Number
            val b2 = allLightsBrightness2.state as Number        
            if(b1 + b2 > 0){
                logInfo("Rule postUpdate", "btn.postUpdate(ON)")
                 btn.postUpdate(ON)
            }
            else{
                logInfo("Rule postUpdate", "btn.postUpdate(OFF)")
                btn.postUpdate(OFF)
            }
        }
         
end

Start with “all off”:

==> events.log <==
2018-11-24 00:03:36.369 [ome.event.ItemCommandEvent] - Item 'btn' received command ON
2018-11-24 00:03:36.390 [vent.ItemStateChangedEvent] - btn changed from OFF to ON

==> openhab.log <==
2018-11-24 00:03:36.391 [INFO ] [.smarthome.model.script.Rule recvCmd] - livingroomLights.state == ON

==> events.log <==
2018-11-24 00:03:36.405 [ome.event.ItemCommandEvent] - Item 'allLightsBrightness' received command ON
2018-11-24 00:03:36.422 [ome.event.ItemCommandEvent] - Item 'allLightsBrightness2' received command ON

==> openhab.log <==
2018-11-24 00:03:36.441 [INFO ] [arthome.model.script.Rule postUpdate] - btn.postUpdate(OFF)
2018-11-24 00:03:36.447 [INFO ] [arthome.model.script.Rule postUpdate] - btn.postUpdate(OFF)

==> events.log <==
2018-11-24 00:03:36.450 [vent.ItemStateChangedEvent] - allLightsBrightness changed from 0 to 100
2018-11-24 00:03:36.457 [vent.ItemStateChangedEvent] - allLightsBrightness2 changed from 0 to 100
2018-11-24 00:03:36.460 [vent.ItemStateChangedEvent] - btn changed from ON to OFF

Is this a bug?

but here you are sending a command (not a postUpdate)

AAAAAAHHH…i only thought in one direction. sorry for wasting your time :man_facepalming:

1 Like