I got a rule that starts my favorite radio station in the morning. It is triggered by a motion event and active only in between 7 and 8 am:
rule "Breakfast radio"
when
Item HueMotionEvent changed from OFF to ON
then
if(now.getHourOfDay() >= 7 && now.getHourOfDay() < 9){
if(sonosplay3_state.state == "STOPPED"){
sendCommand(sonosplay3_radio, "radio")
}
}
end
This works fine, but the problem is that the rule is triggered every time the motion event is fired in that time range. So if I decide to turn off the radio, it will promptly be turned on again with the next motion event.
I think one way solve that is to run that action (the then part of the rule) only once a day. Perhaps by storing the last execution day in persistent storage (MapDB)?
Can you help a beginner? I have no idea how to express that in code…
Create an Item that holds the information, for example a number item which is normally 0 . When the rule is fired within the timeframe and this item.value is 0 turn on the radio AND set the item to 1.
When the rule is fired again it should the timeframe and the value of the item. Switch on the radio only within the timeframe AND if the item is 0.
Additionally create a Cron triggered rule that resets the item to 0 once a day after the timeframe of the other rule.
…but persisting the new item would help if you restart openhab within your time range and the rule was already triggered.
Then the persistence (with restoreOnStartup) will set the new item to 1 again.
Without persistence, it would stay at 0 (or NULL) after a restart.
This is an example with the code that solves my problem. Thanks for your help!
Item definition Number RunToday
Rule
var ruleName = "test rule"
rule "test rule"
when
Item ManualTrigger changed
then
if(RunToday.state==1){
logWarn(ruleName, "Job already done")
}
else{
logWarn(ruleName, "Trigger!")
// remember we already did our job
postUpdate(RunToday, 1)
// reset the flag after some time
createTimer(now.plusHours(3), [|postUpdate(RunToday, 0)])
}
// optionally persist the flag
RunToday.persist
end
Actually, since it’s a single rule you could use a variable rather than an item. That way if your statement goes down before the timer finishes it will reset.
No, you would set it to null outside the rule (which is what would clear it on a restart), then in the rule you’d have the same if/else logic and set the variable value in place of your postUpdate’s