I would like to create a rule based on time triggers for controlling lights outside some time ranges. For example, if one light changes from off to on, the light will be assigned a timer for 1 hour max and will go off after.
The problem is since I have a a fews lights, I will use a group that will find the state of each member and if is it at ON, a timer will be created with a 1 hour laps. So, how can I create dynamic VAR Timer when each of member group is on a state ON? Do I have to assign a one on one timer and have those created before?
You need a one-to-one mapping between your lights or a whole lot of really ugly logic. This is easy to do with a HashMap. You do not need to create them before. The following approach will work even when you add or remove Items from the group.
Here is how I would solve what I think you are trying to do. It is easier to show in code than explain:
var Map<SwitchItem, Timer> timers = createHashMap
rule "Light turned on"
when
Item gLight received update // NOTE, rule will be triggered multiple times per update, the code handles this
then
gLight.members.forEach[light | // for each light
// If the light is ON and there isn't already a timer, create one
if(light.state == ON && timers.get(light) == null){
timers.put(light, createTimer(now.plusHours(1), [|
light.sendCommand(OFF)
timers.put(light, null)
])
}
// If the light is OFF and there is a timer, cancel it
else if(light.state == OFF && timers.get(light) != null) {
timers.get(light).cancel
timers.put(light, null)
}
]
end
One limitation to this is it does not handle the case where you want to reset the timer even further into the future (e.g. a motion sensor based light). It will turn off in an hour no matter what. If you need this functionality it gets more tricky.
Thanks for your help.
I tested your rule but I have a strange problem.
It does work the first time that I gets updated but the second time, it
doesn’t.
I put some traces in the rule (logging) and the first time it logs activity
but not the second time.
Do you think that the timer ainst getting the null condition?
One thing I have learned recently is that it is best not to use a SwitchItem or a GroupItem as the key in a Map. Also, it might be having a problem with timers not being final as we are trying to use it inside a forEach.
So change timers to a val Map<String, Timer> timers = createHashMap
Then everywhere you have timers.put( or timers.get( replace light with light.name.