Security Lights on with Motion between Astro Events

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.

What I have:

Items:

//Lights
Switch  EX_E_Garage_Flood "EX Garage Floods" <switch> (gEX_Flood, gEX_Lights)              ["Lighting"]  {channel="zwave:device:a9cfa5f7:node13:switch_binary"}
Switch  EX_NW_BackYard_Flood        "EX Backyard Flood1"          <switch>       (gEX_Flood, gEX_Lights)              ["Lighting"]  {channel="zwave:device:a9cfa5f7:node14:switch_binary"}
Switch  EX_SW_BackYard_Flood        "EX Backyard Flood2"          <switch>       (gEX_Flood, gEX_Lights)              ["Lighting"]  {channel="zwave:device:a9cfa5f7:node9:switch_binary"}
Switch  EX_S_Side_Flood             "EX South Flood"              <switch>       (gEX_Flood, gEX_Lights)              ["Lighting"]  {channel="zwave:device:a9cfa5f7:node8:switch_binary"}

//Motions
Group gEX_Motion         "EX Motions"            <motion>            (gEX)
Group gEX_MotionFld      "EX Lighting Motion"    <motion>            (gEX_Motion)

Switch EX_N_Motion "North Lts Motion" <motion> (gEX_MotionFld) {channel="zwave:device:sensor_binary"}
Switch EX_S_Motion "South Lts Motion" <motion> (gEX_MotionFld){channel="zwave:device:sensor_binary"}

//Proxies
Switch EX_Dark_Proxy

//Timers
Switch EX_FloodTimer {expire="5m,command=OFF"}

Rules

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.

Thank you.

If you send a command to a Group type Item, that command gets automatically propagated to all group member Items.

That doesn’t always suit, say if you want a delay between members.

What do you think is inefficient about those neat little rules? Total runtime is about 100mS per day.

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.

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.