I have a switch that i like to switch on with a timer. I created a massive rule, which works but is far from elegant. What i did is as soon as my timer receives a new input, it waits for 1 minutes and then inputs the value minus 1.
So i have my regular on/off switch an item with mappings for the timer and an item that shows how many minutes are left on the timer.
Now the rules i have created is as follows (the countdown rule i made for every minutes from 120 down to 0). So how can I simplify this rule to just one instead of 120 rules.
rule "Test Lights 30 min"
when
Item TestSwitch_Timer received command "2"
then
TestSwitch.sendCommand(ON)
TestSwitch_TimerDur.sendCommand(30)
logInfo("info","Test light 30 min timer activated")
end
rule "Switch Timer to 0"
when
Item TestSwitch_TimerDur received command "0"
then
F1_HW_Stairlight.sendCommand(OFF)
logInfo("info","Test light switches off")
end
rule "Timer from 30 to 29"
when
Item TestSwitch_TimerDur received command "30"
then
logInfo("info","30 min left on timer")
createTimer(now.plusMinutes(1), [ | TestSwitch_TimerDur.sendCommand(29)] )
end
rule "Timer from 29 to 28"
when
Item TestSwitch_TimerDur received command "29"
then
logInfo("info","29 min left on timer")
createTimer(now.plusMinutes(1), [ | TestSwitch_TimerDur.sendCommand(28)] )
end
rule "Timer from 28 to 27"
when
Item TestSwitch_TimerDur received command "28"
then
logInfo("info","28 min left on timer")
createTimer(now.plusMinutes(1), [ | TestSwitch_TimerDur.sendCommand(27)] )
end
var Timer tTimer = null // pointer to timer
rule "Timer"
when
Item TestSwitch_Timer received command
then
if(receivedCommand instanceof Number) { // just to be sure
val Number mins = (receivedCommand as Number).intValue // duration to set
if(mins == 0) { // deactivate timer if set to 0
if(tTimer !== null) // if there is an active timer
logInfo("timer","Timer deactivated!")
tTimer.cancel // cancel
tTimer = null // deinitialize
TestSwitch.sendCommand(OFF) // switch light off
} else { // set timer
logInfo("timer","Timer set to {} Minutes!",mins)
TestSwitch.sendCommand(ON) // switch light on
tTimer?.cancel // cancel existing timer
TestSwitch_Timer.postUpdate(mins) // set display to duration
tTimer = createTimer(now.plusMinutes(1), [ // initialize timer
val Number nDuration = (TestSwitch_Timer.state as Number) - 1 // get new duration
TestSwitch_Timer.postUpdate(nDuration) // set display to duration
if(nDuration > 0) { // already reached end?
logInfo("timer","Timer end pending {} Minutes",nDuration)
tTimer.reschedule(now.plusMinutes(1)) // repeat
} else {
logInfo("timer","Timer ended.")
TestSwitch.sendCommand(OFF) // switch light off
tTimer = null // deinitialize timer
}
])
}
}
end
Timer is created once and is repeated until reached end. Display is updated once a Minute (Display is the same Item as timer control).
You can deactivate the timer. You can simply add other duration by setting the Item state accordingly.
I have even more elegant requirement for rule, but struggling.
I have several Items, and want them work together.
Garage_gate (Open/close)
Garage_door (Open/close)
Light_switch (on/off)
Several move detection items with (open/close)
and I have also event for sunset/sunrise.
I wan something very elegant.
when I open garage door or garage gate, and it’s also after sunset event (possible with delta), then I turn on light. Later I want to keep light on for 2 minutes, for example. but when I receive move detection, I want this timer back reset to 2 minutes. and turn off when a timer get 0 or it’s sunrise (sunrise it’s optional, but preferred).
Hi, I was trying this example as is,same items, same sitemap, but I get a warning and it doesn’t work.
I’m doing a clean install of oh 2.5.10-1.
The warning is:2020-11-13 18:39:24.943 [WARN ] [rest.core.internal.item.ItemResource] - Received HTTP POST request at 'items/TestSwitch_Timer' with an invalid status value '5'.