It is a very basic thing but this approach with counters is not a very easy way to do it.
Using the example at the top of the threadâŚ
var Timer ezMotionTimer = null
rule "EZ Auge - Licht Aus"
when
Item EZ_Motion received command
then
Scene_EZ.sendCommand(3)
if(ezMotionTimer != null) {
ezMotionTimer.reschedule
}
else {
ezMotionTimer = createTimer(now.plusMinutes(5), [|
Scene_EZ.sendCommand(1)
ezMotionTimer = null
}
}
end
The above will turn on the Lights (i.e. sendCommand 3 to EZ_Scene). Five minutes after the last time the EZ_Motion receives a command the Timer will go off and turn off the lights.
Iâve a few other minor comments about your rule. These are not problems but could help you avoid problems in the future.
It is better to use the sendCommand and postUpdate method on the Item rather than the actions. So you would rewrite:
sendCommand(Scene_ColorSelect_EZ_Deckenlamp, new HSBType(new DecimalType(0),new PercentType(0),new PercentType(70)))
var Timer ezMotionTimer = null
rule "Licht Timer"
when
Item EZ_Auge_Burglar changed from OFF to ON
then
Scene_EZ.sendCommand(3)
if(ezMotionTimer != null) {
ezMotionTimer.reschedule
}
else {
ezMotionTimer = createTimer(now.plusMinutes(1)) [ |
Scene_EZ.sendCommand(1)
ezMotionTimer = null
]
}
end
May I have to import some bibs or place the var at the top of the .rules or need some addons or extra services or so?
I don´t want to make the variables as global variables.
Can i make this inside the rule as well?
If i put val and var to the top of my rules-file, it works. But if i put it inside the rule, nothing happensâŚ
working:
var Timer md1Timer = null
val int timeoutMinutes = 5
// KG Garage Licht aus nach 5 Minuten
rule "KG Garage Licht auto off"
when
Item Licht_KG_Garage_1 changed
then
if (Licht_KG_Garage_1.state == ON) {
md1Timer = createTimer(now.plusMinutes(timeoutMinutes), [|
Licht_KG_Garage_1.sendCommand(OFF)
md1Timer = null
]
}
else {
md1Timer = null
}
end
not working:
// KG Garage Licht aus nach 5 Minuten
rule "KG Garage Licht auto off"
when
Item Licht_KG_Garage_1 changed
then
var Timer md1Timer = null
val int timeoutMinutes = 5
if (Licht_KG_Garage_1.state == ON) {
md1Timer = createTimer(now.plusMinutes(timeoutMinutes), [|
Licht_KG_Garage_1.sendCommand(OFF)
md1Timer = null
]
}
else {
md1Timer = null
}
end
By doing this you are defining local vs. global variables. Local in this case means (as in all programming languages) the scope and the existence of this variable is limited to one execution of the code block, being your rule. The Timer variable will be deleted when reaching end and recreated when executing the rule again.
Yes, i know this. I want to have this variable âvar Timer md1Timer = nullâ only inside my rule. The rule will not reach âendâ while the timer is running.
And when the timer is ânullâ, i don´t need it anymore.
But this doesn´t work with âvar timerâŚâ inside the rule. No error-message in the log-file. I made some logging and the rule will not get triggered, if i put var inside it.
I donât think you understand how Timers work. They do not block the rest of the execution of your Rule. Once created the timer runs in the background while the rest of your Rule continues to execute. So in the above your rule immediately exits once the Timer is created instead of waiting around for the timeout.
This is why you must store the timer variable as a global.
import java.util.Map
val Map<String, Timer> timers = newHashMap
rule "A Motion Detector triggered"
when
Item MS_LivingRoom_MotionSensor1 received update MOTION or
Item MS_LivingRoom_MotionSensor2 received update MOTION
then
Thread::sleep(100) // give persistence time to save the update
val sw = gMotionSensor.members.sortBy[lastUpdate].last as SwitchItem
logInfo("Motion.Sensor", "Motion Sensor Counter start")
val timeoutMinutes = 3 // use an appropriate value
if(timers.get(sw.name) == null){
timers.put(sw.name, createTimer(now.plusMinutes(timeoutMinutes), [|
logInfo("Motion.Sensor", "Motion Sensor Counter works")
sw.sendCommand(OFF)
timers.put(sw.name, null)
]))
}
else {
timers.get(sw.name).reschedule(now.plusMinutes(timeoutMinutes))
logInfo("Motion.Sensor", "Motion Sensor Counter timer extend")
}
logInfo("Motion.Sensor", "Motion Sensor Counter finished")
end
What item types are you motion detectors. Iâve never seen an Item with a MOTION state. In the rule you cast then to a SwitchItem which only has the states of ON and OFF.
Do you get the first log statement in your logs?
You may need to filter out the items that have yet to be saved to persistence.
val sw = gMotionSensor.members.filter.[s.lastUpdate != null].sortBy[lastUpdate].last as SwitchItem
I use mihome, which motion sensor announce MOTION when detect motion,
I set String type at items,
yesterday I have setup mapdb and have * : strategy = everyChange, restoreOnStartup in mapdb.persist
I remove restoreOnStartup from influx and I see item state restored after system startup,
so I assume value should have saved.
I really donât know how to do coding, according to your last reply, does your code only able to apply to item type is switch?
Thanks, I will try again once I am back home,
you mention OH2 prevent update or changed to rule triggers on Strings type,
does that mean if item type is string will not get trigger in rules if itâs not been fixed?
if it is than no wonder why I canât set a test rules which will light up when door open,
I tried it last night without success, I thought I was using wrong code in rules.