My goal is to have ALL of my security floods lights come on when one of my two motion sensors detects motion. After researching several topics on the discussion boards I was able to get the code to work, but I wonder if perhaps there is a more streamlined or logical way to accomplish this. My concern is there are to many rules and if one misfires or the state changes for some reason it will not work correctly.
rule "Set Sunset Motion Proxy"
when
Channel 'astro:sun:local:civilDusk#event' triggered START
then
EX_Dark_Proxy.sendCommand(ON)
end
rule "Set Sunrise Motion Proxy"
when
Channel 'astro:sun:local:civilDawn#event' triggered START
then
EX_Dark_Proxy.sendCommand(OFF)
end
rule "Start Motion Timer"
when
Member of gEX_MotionFld changed from OFF to ON
then
if (EX_Dark_Proxy.state == ON) {
sendCommand(EX_FloodTimer, ON)
}
end
rule "Turn on Flood Lights"
when
Item EX_FloodTimer changed from OFF to ON
then
gEX_Flood.members.forEach(item | { item.sendCommand(ON) } )
end
rule "Turn off Flood Lights"
when
Item EX_FloodTimer changed from ON to OFF
then
gEX_Flood.members.forEach(item | { item.sendCommand(OFF) } )
end
Again, it seems to work but I’m looking for a more efficient way to write this code while ensuring reliability.
If you ever have a need for the lights to turn off at a random time (so the lights don’t appear to be on a timer) just add this bit to your rule and change the 1800 value to whatever is preferred.
then
var int randomTime = (new java.util.Random).nextInt(1800)
createTimer(now.plusSeconds(randomTime)) [|
FrontPorch_Light.sendCommand(OFF)
]
There is nothing really wrong with these rules but I do have some suggestions.
Use the method on the Item instead of the action for sendCommand. sendCommand(EX_FloodTimer, ON) bad. item.sendCommand(ON) good.
As rossko57 already indicated, you can just call gEX_Flood.sendCommand(ON) and all members of that Group will receive an ON command. No need to manually loop through the members like this.
You could consolidate the rules a bit if you really want to. There’s no reason to but you could do it. I’d probably eliminate the turn on flood lights Rule and move that one command to the motion timer rule.
rule "Start Motion Timer"
when
Member of gEX_MotionFld changed from OFF to ON
then
if(EX_Dart_Proxy.state != ON) return;
gEX_Flood.sendCommand(ON)
EX_FloodTimer.sendCommand(ON)
end
rule "Turn off Flood Lights"
when
Item EX_FloodTimer changed from ON to OFF
then
gEX_Flood.sendCommand(OFF)
end
Though you could also merge the EX_FloodTimer Rules.
rule "Flood Lights"
when
Item EX_FloodTimer changed from OFF to ON or
Item EX_FloodTimer changed from ON to OFF
then
gEX_Flood.sendCommand(EX_FloodTimer.state)
end
Or you could combine them all into one Rule and use a Timer (I’ll leave that as an exercise for the reader).
None of these variations are any better or worse than the others in terms of functionality or runtime. In general fewer lines of code is better than more lines of code, but the savings in lines here is not worth the effort.
If you were to have other Rules that care about the time of day, I would eliminate the Sunset/Sunrise Rules in place of Design Pattern: Time Of Day and then your if statement would test vTimeOfDay to see if it’s night time instead of using a Proxy Item. Then you can control other lights and other behaviors using the same reused Rule and Item instead of needing to repeat the same time checking code for each use.