[SOLVED] Timer "Reset"

Hi

Wrote this, and its working :slight_smile:
But, I have problem. In case a BI_FC_Motion change to ON during running timer, the previous timer will turn of the lights before the new timer will.
So I need to reset the timer to X every time new movement happen (Movement is BI_FC_Motion=ON)
I saw I can reschedule a timer, but what if I didn’t have this timer ?
I can create timer and immediately reschedule it, but I think its not the right solution

rule “BI Motion FC”
when
Item BI_FC_Motion changed from OFF to ON
then
var boolean MovementLightsOn = false
logInfo(“home.rules”, "MovementLightOn Before State: " + MovementLightsOn )
logInfo(“home.rules”, "Sun State: " + sun )
if (sun == false && LS_FrontOutside.state == OFF) {
MovementLightsOn = true
logInfo(“home.rules”, "MovementLightOn During State: " + MovementLightsOn )
LS_FrontOutside.sendCommand(ON)
logInfo(“home.rules”, “Lights on for Camera”)
}
Thread::sleep(2500)
sendTelegramPhoto(“sec”, “http://xxx/image/Cam201”, “”)
Thread::sleep(1000)
sendTelegramPhoto(“sec”, “http://xxx/image/Cam201”, “”)
Thread::sleep(1000)
sendTelegramPhoto(“sec”, “http://xxx/image/Cam201”, “”)
Thread::sleep(2000)
sendTelegramPhoto(“sec”, “http://xxx/image/Cam201”, “”)
if (MovementLightsOn == true) {
createTimer(now.plusSeconds(20), [| LS_FrontOutside.sendCommand(OFF)])
MovementLightsOn = false
logInfo(“home.rules”, "MovementLightOn After State: " + MovementLightsOn )
}
end

Make sure you define a Timer variable globally within the rules file and cancel that every time before (re)setting the timer, like so:

var Timer MovementTimer = null
rule “BI Motion FC”
when
    Item BI_FC_Motion changed from OFF to ON
then
....
    if (MovementLightsOn == true) {
        MovementTimer?.cancel
        MovementTimer = createTimer(now.plusSeconds(20), [| LS_FrontOutside.sendCommand(OFF)])
        ...
    }
end

Next to that, you are potentially creating an issue with those Thread::sleeps, see here:

That’s actually a good place to use fire-and-forget anonymous timers (no handle variable needed to cancel/reschedule later)

createTimer(now.plusMillis(2500), [| 
    sendTelegramPhoto(“sec”, “http://xxx/image/Cam201”, “”)
])
createTimer(now.plusMillis(3500), [| 
    sendTelegramPhoto(“sec”, “http://xxx/image/Cam201”, “”)
])
// etc
// this will set up a set of timers for later
// and not sit waiting in the rule

I used method of timer without variable becuase I’ve read its safe.
but In my case I better use variable bound timer right ?

I’ve read about sleep, but since mine are short I decided to use it.
But I guess this method is better. nothing to clear after this timer ?

No idea what would be “unsafe” about using a variable.

If you want to cancel or reschedule a timer after you have started it, then you must use the variable method.

Nah, 6.5 seconds waiting in a rule isn’t really short.

I smell a connection … got many rules like this one?

No, fire and forget.

1 Like

Thanks.
Why did you write MovementTimer?.cancel ?
what the question mark after variable means ?

The question mark means that it will not try to perform the cancel method if MovementTimer is not defined. More practically: when MovementTimer has never been set with createTimer, there is nothing to cancel, and then it can just skip that line. If it has been set, it cancels that timer.

1 Like