Rule Generation, complex triggering and "and"

Hello,
I’m trying to create a specific rule but the only option under the when section is “or” I don’t not want to “or” the rules together, I want to “and” them together. Well i would like to make a complex rule set for this.

The goal is to have the interior lights turn on when i come home from work during a narrow time frame using my phone as the trigger. once the rule has fired it should be locked out for some period of time to prevent random triggers.

what i have :

    rule "Coming Home Lights"
    when
    //Channel "astro:sun:local:set#event" triggered START and 
       
    //Time cron  	"0 0 17 ? * MON,TUE,WED,THU,FRI *" //Monday - Friday after 7pm
    //Time cron  	"0 0 18 ? * MON,TUE,WED,THU,FRI *" //Monday - Friday after 8pm
    Item Presence_KeatonsPhone changed to ON // phone presence detection  

    then
    KitchenDimmer_SwitchDimmer.sendCommand(60)
    logInfo("Light", "Kitchen light turned on by coming home rule")
    end

if i was doing this in embedded C i would expect it to be something like

    if( (astro:sun:local:set#event == True) && (Presence_KeatonsPhone == True) && ( (Time > 7pm) ||( Time <8pm) )
    {
    // do event
    }

since "astro:sun:local:set#event triggered START " looks to be an even that is not persistence interrupt/flag i could use my other exterior light rule to set a flag bit and the off to clear the bit. I know there is an expire binding but i have not tried it yet.

your code goes here

The only way your C example would work is if it’s embedded in an endless loop just waiting for all conditions to be true, or have it in a function that gets called by something else.

The latter is (very simplified) how OH rules work, the rule body gets executed in response to an event, which can be a state change of an item, a channel trigger, a Cron trigger etc.

The thing about events is: they happen once, maybe trigger a rule, and then they’re gone. An if-statement (in any programming language) requires a state (of a variable, or an item in openhab) to compare to.

You can have an if-statement like that (except for the channel trigger since that’s an event), but that goes in the rule body, not in the trigger.

Use your presence detection as the ONLY Trigger of the rule AND check the other conditions in the Then part of the rule.

thank you for your responses.

Yeah that’s true, in most cases it goes into a while (1) or in ISR

so i should do somethings more like

    rule "Coming Home Lights"
    when
    Item Presence_KeatonsPhone changed to ON // phone presence detection  

    then

    if ( Channel "astro:sun:local:set#event"  == START ) &&
       (Time cron  	"0 0 17 ? * MON,TUE,WED,THU,FRI *" //Monday - Friday after 7pm)  &&
       (Time cron  	"0 0 18 ? * MON,TUE,WED,THU,FRI *" //Monday - Friday after 8pm) &&
    }
    KitchenDimmer_SwitchDimmer.sendCommand(60)
    logInfo("Light", "Kitchen light turned on by coming home rule")
    }
    end

oops need to edit. some how hit the accept response in the middle of editing

Example post

1 Like

Sort of, you can’t use the events of the astro binding and the crown statements in this part.
However you can check whether the time now is after the sunset-time (I ca only guess that the astro binding does have a channel for that) and check if the time now is before or after the time of the cron statements.

1 Like

Ok, i will try this when i get home tonight.

looking at the example Rossko57 links to I have another question. maybe kinda dumb, has to do when using var vs val for assignment as i’m going to need it for time. I have a rule that does this and the VCS throws an error about the use of val


val DimmerValue =  KitchenDimmer_SwitchDimmer. state as number
    DimmerValue = DimmerValue  +15

    if (DimmerValue  > 100)
       {
          DimmerValue  = 100
       }

     KitchenDimmer_SwitchDimmer.sendCommand(Dimmer Value)


if i think i understand what i’m doing/attempting, i basically creating a temp variable in the function, reading a state into the variable. doing changes to it. then limit checking the value before writing the value. I’m also doing the same in the other direction. so i cant have a number less than 0.

var as in variable, can change its value.
val as in value, can not change its value.

The error is thrown because you tried to change a val!

not sure if there is a better way but here is what i have and it is working so far. i will be looking into expire/rule lockout and resetting. once it fired for the day dont so it again

rule "Coming Home Lights"
when
    Item Presence_KeatonsPhone changed to ON
   
then
    var Number hour = now.getHourOfDay
    var Number weekday= now.getDayOfWeek
    /*  
    https://docs.oracle.com/javase/8/docs/api/java/time/DayOfWeek.html
    Monday == 1
    Tuesday == 2
    Wednesday ==3
    Thursday == 4
    Friday == 5
    Saturday ==6
    Sunday == 7
    */

    if((weekday == 1) || (weekday == 2) || (weekday == 3) || (weekday == 4) || (weekday == 5)) // monday-friday
    {
        
        if((hour >18) && hour <=21) //24hr time, between 6pm & 9pm
        {
            KitchenDimmer_SwitchDimmer.sendCommand(50) //set dimmer to 50%
        }
    }
    
    logInfo("Light", "Kitchen light turned on to 50% by 'Coming Home Rule'")
end

Note that your logInfo reports, whether or not the dimmer action was actually taken. You might move that line.

You could use val here - the hour is read once as the rule triggers, and never altered. (When the rule ends, the variable is destroyed and a new one gets made next time.)
But it works with either.

Beware if someone else is already home with the light on 100%, they can get dimmed unexpectedly!