Rule check for Motion Detection

Scenario: I want to create a rule that turns ON a light based on a motion that is detected from a sensor item (Fibaro FGMS-001).
After the ON command, the light should stay on for 5 minutes from the last moment of no motion being detected.
Additionally, the rule should apply only when it is dark (below 30 Lux).

Originally, I used the example that is provided in the wiki here: (https://github.com/openhab/openhab/wiki/Samples-Rules#how-to-turn-on-light-when-motion-detected-and-is-dark)

This worked fine, but I saw that the rule “corLightOff” was firing every 2 minutes, sending the “OFF” command to the Light (even though the light had been turned off). Maybe I did a mistake but this is my understanding of how this example rule is supposed to work (spam every 2 minutes the OFF command to the light)…

So, I checked around in the forum and I made a newer version from several examples.

I haven’t tested it yet (I believe that it will work), but I wanted to see if the structure can be optimized and if the logic is properly implemented…

var     Timer   FE02_Timer = null
var     Integer FE02_TimeOut = 5

rule "FE02_ON2" // FibEye02 motion detection turns ON Exterior Lights when dark
when
        Item FibEye02_Movement changed from 0 to 1
then
        if (FibEye02_Lux.state < 30 ) {
                if (FE02_Timer != null) {
                        logInfo("FE02","FE02 Timer rescheduled for " + FE02_TimeOut + " minutes")
                        FE02_Timer.reschedule(now.plusMinutes(FE02_TimeOut))
                } else {
                        logInfo("FE02", "FE02 Motion Detected! Turn ON Exterior Lights")
                        P01_Exterior_Light.sendCommand(ON)
                        logInfo("FE02","FE02 Timer created with " + FE02_TimeOut + " minutes")
                        FE02_Timer = createTimer(now.plusMinutes(FE02_TimeOut))
                        [|
                                if (FibEye02_Movement.state ==  1) {
                                        logInfo("FE02","FE02 Timer triggered, but rescheduled again for " + FE02_TimeOut + " minutes")
                                        FE02_Timer.reschedule(now.plusMinutes(FE02_TimeOut))
                                } else {
                                        logInfo("FE02", "FE02 No Motion Detected! Turn OFF Exterior Lights")
                                        P01_Exterior_Light.sendCommand(OFF)
                                        FE02_Timer = null
                                }
                        ]
                }
        }
end

Thank you in advance :vulcan:

Ps: I used a lot of the examples that @rlkoshak made :slight_smile:

So this rule assumes that the motion detector goes back to 0 after a certain amount of time. That time should be less than FE02_TimeOut or else the rule will not trigger often enough to reschedule the timer.

I don’t think you need the checks in the Timer body on the motion detector. The Rule itself handles rescheduling the timer based on motion so you should never hit a situation where the motion detector is 1 when the Timer actually expires.

Just make the body turn off the light and set the Timer to null.

OK, so there might be an exceptionally rare case where you end up in a TOCTU situation but I wouldn’t go out of my way to address it unless you actually experience a problem. And if you do experience a problem, rather than checking for the state of the motion sensor in the timer, put the rule and the timer body inside a reentrant lock so the two can never run at the same time.

And just in case you didn’t see this example:

Yes, it does. The default setting on the Fibaro Motion Sensor is 30 seconds for the “Motion Alarm Cancellation Delay”. Of course, any motion detected during the cancellation delay time countdown of the Fibaro device will result in the countdown being restarted (in the device). The states for the “FibEye02_Movement” item are: 0 for no motion alarm and 1 for motion alarm.

I just tested my rule manually (changed the state from 0 to 1 and the rule fired properly = turned on the lights and started the 5 min timer). Changed it again manually to 0 during the FE02_Timer period (5 mins) and when the timer expired, the lights went off… All is good :slight_smile:

I will simplify it using your recommendation and your example, thank you!

A quick question: In your first example, you send an OFF command to the “MotionDetector1”… is that a typo or it is intended? Shouldn’t the command be delivered to a switch item (to control a light for example?)

A lot of motion sensors do not go back to OFF. So that simple example is really just implementing turning off the motion detector after a certain amount of time. The complex example on that page pairs the motion sensor with the timer and a switch.

One approach using the Expire binding:

Contact FibEye02_Movement ... { zwave="2:command=sensor_binary" }
Switch P01_Exterior_Light ... { ..., expire="5m,command=OFF" }

rule MotionTurnsOnLight
when
  Item FibEye02_Movement received update OPEN
then
  if (FibEye02_Lux.state < 30 ) P01_Exterior_Light.sendCommand(ON)
end

IFF the FibEye02_Movement item were to continue to receive OPEN updates and it’s dark, it will continue to send ON commands to the light. (It may not work that way.) Because the light switch is set to turn OFF after five minutes of not receiving ON updates or commands, as long as it’s fed ON commands by the rule, the light will stay on for the next five minutes.

The above may not work and it may lack some of the nuances you’re after, but this general approach might help you find a simpler implementation than using timers.

1 Like