How to do several things in a rule with sertain time inbetween

Running Openhabian on RPI3 OH2.4.0 & oracle java.

Hi I’m trying to make a rule (in a script) That turnes on the lights in the bedroom when i wake up, after 3 minutes the lights should be turned off and the chromecast in the bedroom should first “say hello”, and after 3 sec turn on my favorite radio station. But i’m not shure how to do this. I tried a timer within a timer (if that makes any sense) but openhab doesn’t like this. Can anyone point me to some docs on how to do this? I have searched but not shure how to discribe this situation in a search querry.

This is how i tried but doesn’t work:

timer = createTimer(now.plusMinutes(1)) [|
    GF_Bedroom_Light_State.sendCommand(OFF)
    GF_Hallway_Light_State.sendCommand(OFF)
    timer = rescheduleTimer(now.plusSeconds(3)) [|
    radioStation.sendCommand(4)
    ]
    callScript("sayHello")
]
GF_Bedroom_Light_His_Level.sendCommand(70)
GF_Bedroom_Light_Central_Level.sendCommand(70)
GF_Hallway_Light_BrDoor_Level.sendCommand(30)
logInfo("Home", "Waking up")

I’m not competent with timers yet, have been reading some docs though

What are you using to determine when you wake up?

Also please post your entire rule.

Hi, thanks for your response.

I’m not shure yet what is going to trigger the rule, thats why i made the rule in a script so i can add the script to any rule with any trigger. Probably an android alarm that i get into openhab through the rest interface or a bedoccupancy sensor i still need to develop (parts are on the way). This actually is the complete rule (well actualy script that can be executed using any rule). I’m actually looking for a sort of design pattern that lets me do something, a certain time later do another thing, a certain time later do another thing, … . It doesnt matter what the things are, im just lost at how to structure the timer to create the different waiting times. Thanks for your time btw

Rich has several design patterns just search the forum and you should find what your looking for.

Here’s a link to one of them.

At the bottom you will find more links to others as well.

That can work but you can’t do it with reschedule. Since you have a new lambda to execute (stuff in [ ]) you need create a new timer. You can call timer.reschedule(now.plusSeconds(3)) but you can’t change the code that executes when it runs again.

To do this the way I would recommend, you can’t implement it in a Script.

The two that I think are relevant here would be Looping Timers or Cascading Timers. But I think Cascading Timers may be overkill for this case as I suspect you are OK hard coding the times. So let’s look at what this would look like using Looping Timers.

The reason that you can’t do this in a Script is because we need to preserve the variable that the Timer is stored in and I’m not sure we can do that in a Script.

var Timer bedroomTimer = null

rule "Bedroom routine"
when
    // some trigger
then
    if(bedroomTimer !== null) return; // only let one routine run at a time, ignore repeated events 

    var step = 0
    bedroomTimer = createTimer(now.plusMinutes(0), [ |
        var rescheduleTime = -1
        switch(step) {
            case 0: {
                // turn on the lights
                step = 1
                rescheduleTime = 3 * 60 
            }
            case 1: {
                 // turn off the lights
                 // tell the Chromecast to say hello
                 step = 2
                 rescheduleTime = 3
            }
            case 2: {
                // turn on the radio station
            }
        }
        if(rescheduleTime != -1) bedroomTimer.reschedule(now.plusSeconds(rescheduleTime))
        else bedroomTimer = null
    ])
end

Theory of operation. We keep track of what step we are on and perform the three steps based on that value. Depending on what step we are on we do the correct actions and reschedule the Timer for the right amount of time.

You could also implement this using three independent Timers. Dealing with avoiding having more than one set of these running at the same time is a little more complex (you have three Timers to check instead of just the one). But then the body of the Timers is WAY more straight forward.

var Timer step1Timer = null
var Timer step2Timer = null

rule "Bedroom routine"
when
    // some trigger
then
    if(step1Timer !== null || step2Timer !== null || step3Timer !== null) return; // only let one routine run at a time, ignore repeated events 

    // turn on the lights

    step1Timer = createTimer(now.plusMinutes(3), [ |
        // turn off lights
        // say hello on Chromecast
        step1Timer = null
    ])
    step2Timer = createTimer(now.plusSeconds(3*60 + 3), [ |
        // turn on radio station
        step2Timer = null
    ])
end
1 Like

Thanks Rich, this is exactly what i need.