I try to create a “night mode” which should do following things:
Activated on one switch of the Sonoff T1 3CH:
activate (ON) all other switches in the group “nightModeSwitches”
OFF all in the group “LightsInNightModeOFF”
ON all in the group “LightsInNightModeON”
When deactivating one Night-Mode-Switch OR activating one switch of the group “LightsInNightModeOFF” then:
deactivate (OFF) all other switches in the group “nightModeSwitches”
OFF all in the group “LightsInNightModeON”
Is that even possible? My first attempt with a rule produced an endless loop
rule "nightModeSwitches received command ON"
when
Item nightMode1 received command or
Item nightMode2 received command or
Item nightMode3 received command or
Item nightMode4 received command or
Item nightMode5 received command or
Item nightMode6 received command or
Item nightMode7 received command or
Item nightMode8 received command
then
if (receivedCommand == ON) {
sendCommand(LightsInNightModeOFF, OFF)
sendCommand(nightModeSwitches, ON)
}
end
Yes, you created an endless loop by triggering your items on “received command” and then sending commands to all of them from within the rule.
You need a virtual item that determines when night mode is on or off. When that item gets turned on, it triggers a rule with the actions you want to take when night mode is enabled. Here’s a shortened version of mine.
rule "Night Mode"
when
Item Flag_Night changed to ON
then
Outlet_Bedside.sendCommand(ON)
createTimer(now.plusSeconds(5))
[
Group_Living_Room.sendCommand(OFF)
Group_Kitchen.sendCommand(OFF)
]
end
This rule turns on my bedside light, waits five seconds, and then turns off the lights in my living room and kitchen.
You can then have a separate rule that turns off the night mode virtual item, and runs any other commands you want to fire at the same time. I use the astro binding to turn my night mode off at sunrise.
rule "nightModeSwitches changed"
when
Item nightModeSwitches changed
then
if(nightModeSwitches.state == OFF) {
nightModeSwitches.sendCommand(OFF)
} else if(nightModeSwitches.state == ON) {
nightModeSwitches.sendCommand(ON)
LightsInNightModeOFF.sendCommand(OFF)
LightsInNightModeON.sendCommand(ON)
}
end
If this does not work as expected, try this:
var boolean bMyLock = false
rule "nightModeSwitches changed"
when
Member of nightModeSwitches received command
then
if(!bMyLock) {
bMyLock = true
if(receivedCommand == OFF) {
nightModeSwitches.members.forEach[i | i.sendCommand(OFF)]
} else if(receivedCommand == ON) {
nightModeSwitches.members.forEach[i | i.sendCommand(ON)]
LightsInNightModeOFF.members.forEach[i | i.sendCommand(OFF)]
LightsInNightModeON.members.forEach[i | i.sendCommand(ON)]
}
createTimer(now.plusSeconds(1),[ |bMyLock = false ])
}
end
The second rule will lock itself and therefor prevent an endless loop. As an alternative, you can do a loop through group members, which is a more stable way to send commands to all items. I did this in the second rule. As It will take some time to set all Items, the lock is set to false a second later, just to be sure.
You don’t need more than one trigger for the rule.
You don’t need more than one rule for ON and OFF
It’s better to use the method myItem.sendCommand(status) instead of the action sendCommand(myItem,status) as the latter needs two strings as parameter, where the former allows to use status, string, number (when Item is of type number), …
Good points as always, Udo! I should have provided more context for why I use the virtual item. I like having an indicator on my sitemap that tells me what mode my house is in, and it also enables me to activate it at any time using Google Home. As well, I use it as a check condition to determine if other rules should run. For example, my motion sensor turns on the kitchen lights at 30% if Night Mode is on.
The point of the “proper” locking mechanism is, it won’t work here.
Afaik when using lock.lock, and try, the locked rule will do it’s job as soon as unlocked. see the excellent statement from @rlkoshak: Explain lock() command?
But here it should just ignore all sendCommands() for the members as long as the rule is executed.