Turn light off when no one is in the room (no motion)

I have read many posts here that relate to this topic, including Design Pattern: Motion Sensor Timer, but couldn’t find an answer to my question.

I am using a Fibaro motion sensor in my system.
I think it is unique in the motion detected / undetected reports it sends to the hub:

  • Whenever a motion is detected - the hub is notified.
  • In order to save battery, additional motion detection (within specific defined time period) are NOT being sent to the hub.
  • If no motion was detected for the duration of the defined time period, a NO MOTION report is sent to the hub.

I would like to turn off a light after 10 minutes it was on with no motion in the room.

I created the items and rules below, and everything seems to work correctly.

Items:

Switch MotionSensor "Motion Sensor [%s]" <motion> (gMotion) {channel="zwave:device:11a1111a:node1:alarm_motion"}
Switch Light "" <light> {channel="zwave:device:11a1111a:node2:switch_binary"}
Switch Timer10min {expire="10m,command=OFF"}

Rules:

rule MotionDetected
when
        Item MotionSensor changed to ON
then
        Timer10min.postUpdate(OFF)

end


rule NoMotionDetected
when
        Item MotionSensor changed to OFF
then
        Timer10min.sendCommand(ON)
end


rule LightTurnedOn
when
        Item Light changed to ON
then
        Timer10min.sendCommand(ON)
end


rule LightTurnedOff
when
        Item Light changed to OFF
then
        Timer10min.postUpdate(OFF)
end


rule TurnOffLight
when
        Item Timer10min received command OFF
then
        if (MotionSensor.state == OFF) {
                Light.sendCommand(OFF)
        }
end

I do have a question, though.

Let’s assume the following scenario:

  • Someone entered the room --> motion is detected --> MOTION event sent to hub --> timer is turned off by the MotionDetected rule
  • He turns the light manually --> timer is turned on by the LightTurnedOn rule
  • He keeps moving (nothing is sent to hub: not MOTION and not NO MOTION)
  • After 10 minutes the timer is off --> because MotionSensor.state is still ON nothing happens
  • After some more time, the person manually turns off the light (and goes to sleep) --> timer is turned on by the LightTurnedOff rule
  • After some time (with no motion), a NO MOTION is sent to the hub --> timer is turned on by the NoMotionDetected rule (even though the light is off, and there is no need for the timer)
  • After 10 minutes the timer is off --> a OFF command is being sent to the Light (which is already off) by the TurnOffLight rule

My question:
Would you modify the NoMotionDetected rule, to check if the light is on, before turning on the timer:

rule NoMotionDetected
when
        Item MotionSensor changed to OFF
then
		If (Light.state == ON) {
			Timer10min.sendCommand(ON)
		}
end

The PRO: It will save the Z-Wave network to send a command to turn off the light, when it is actually off
The CON: It requires a check every time a NO MOTION is sent to the hub.

Which way should I go?

Also - Is there a completely different approach to this, which I should take?

In the worst case scenario there might be what, three or four extraneous OFF commands sent in a given day? Even for battery powered devices that isn’t going to be even noticeable. In practical terms, it’s costing you more energy in brain power thinking about it than the extra off commands would use in a lifetime.

But if you have a hundred of these devices, then you might be causing some trouble because it’s not that hard to spam the zwave network and cause messages to be lost.

So yes, it would be better to check whether the light is OFF and not send another OFF command than to send the OFF command when you don’t need to because the check in Rules code is going to use much much much much less resources than the zwave network will use to transmit the OFF command. But if you only have two or three of these devices, it might not even be worth the energy to type out the if statement to do the check.

Why not just set the Timer to ON when you receive the NoMotionDetected ON command. You only want the light to turn OFF ten minutes after this event so it does you no good to to set the Timer when the light turns ON. That is unless somehow the light can turn ON without the motion sensor detecting the motion. In that case, cancel the Timer when the motion is detected.

This description doesn’t match the code. In the light turned off rule the Timer is updated to OFF which effectively cancels the Timer. This is good as we don’t need the Timer to turn a light off that has just turned off.

Yes.

  1. Turn on the Timer when the Light turns ON only if MotionSensor is OFF
  2. When MotionSensor goes ON, cancel the Timer
  3. When NoMotionSensor goes to ON, turn on the Timer, but only if the light is ON
  4. When the Timer goes OFF, turn off the Light.

We turn on the Timer when the light turns on only if the MotionSensor is OFF to handle the case where the light was turned ON without motion being detected. This ensures that the light will turn off on it’s own if Motion is never detected.

We turn OFF the Timer when ever the light turns OFF. We don’t need it any more.

We turn ON the Timer only when the NoMotionSensor turns ON and the Light is ON because we want the light to turn OFF 10 minutes after No Motion. It doesn’t matter when MotionSensor turned ON, we are not timing from that.

2 Likes

This is, of course, a typo - it should have been “timer is turned OFF by the LightTurnedOff rule”.

So it should actually be this way?

rule MotionDetected
when
        Item MotionSensor changed to ON
then
        Timer10min.postUpdate(OFF)

end


rule NoMotionDetected
when
        Item MotionSensor changed to OFF
then
		If (Light.state == ON) {
			Timer10min.sendCommand(ON)
		}
end


rule LightTurnedOn
when
        Item Light changed to ON
then
        if (MotionSensor.state == OFF) {        
			Timer10min.sendCommand(ON)
		}
end


rule TurnOffLight
when
        Item Timer10min received command OFF
then
        Light.sendCommand(OFF)
end

Why not keeping also:

rule LightTurnedOff
when
        Item Light changed to OFF
then
        Timer10min.postUpdate(OFF)
end

You can keep that. It doesn’t hurt either way really.

1 Like