Edit: Updates for OH 4
Please see Design Pattern: What is a Design Pattern and How Do I Use Them for details on how to use DPs.
Problem Statement
Many motion detectors only report ON when they detect motion but do not send a corresponding OFF after no motion has been detected after a period of time. In addition, often one wants to control a device like a light for a certain period after the last motion is seen, not after the motion sensor goes to OFF. Therefore one needs to keep a Contact OPEN (or Switch ON) until the desired amount of time after the last motion is detected.
This also applies in any cases where you want to do something when a state is first reached, and then doing something else a certain time after.
This approach works any time one wants something to happen a certain amount of time after the last time that an Item received a command or update. It can be easily adapted to report when a device stops reporting, to avoid flapping (e.g the switch constantly switching back and forth when something is on the edge of detection.
Concept
When the motion detector sends an ON
command, create a timer. If subsequent ON
commands are received reschedule the timer. When the timer expires call a rule containing the code to execute when there hasnât been motion events for long enough.
For the examples blow we will assume:
MotionSensor
is a Switch Item linked to the motion sensor, we assume it does not change to OFF on itâs ownLight
is a Switch Item linked to the light controlled by the motion sensor
We will turn the light on upon first motion and will turn it off five minutes after the last motion.
Expire Timer
If you have a case where Light
is only controlled by the MotionSensor
you can use the Expiration Timer
metadata on the Light
Item. Set it to send command OFF
after five minutes. By default it will reschedule itself every time itâs commanded ON
.
Now all you need is something to command Light
to ON
when motion is reported. A simple rule that triggers when MotionSensor
receives an ON
update and which commands the Light
to ON
is sufficient.
Five minutes after the last command to Light
is received, expire
will command the light OFF
.
Rule Template
Threshold Alert and Open Reminder [4.0.0.0;4.9.9.9] provides a rule that supports any time you have to âdo X when Y hasnât changed or remains above/below a threshold for a certain amount of time.â I has additional features like do not disturb periods and hysteresis but those are not needed here.
A motion sensor timer is one of these use cases.
First create a rule commands the Light
ON
when itâs run (weâll use light-on
as the ruleUID) and another rule that commands the Light
OFF
when itâs run (weâll use light-off
as the ruleUID). Also update MotionSensor
to OFF
in this second rule. These rules can be written as simple UI rules or using any script language desired.
- In MainUI navigate to Add-on Store â Automation and under âRule Templatesâ find and add âThreshold Alert and Open Reminderâ.
- Navigate to Rules â + to create a new rule. Fill in a meaningful ID, name, and description and select âThreshold Alertâ as the template to base the rule on.
- This will show a form of parameters to fill out.
Fill in the following for the properties. Any property not listed leave at the default.
Property | Value |
---|---|
Triggering Group | Choose anything here. Weâre going to change it later. |
Threshold State | âONâ |
Reschedule | Toggled on |
Alert Delay | âPT5Mâ |
Alert Rule | light-off |
Initial Alert Rule | light-on |
Now we need to open the rule that was created and change the trigger. Change the trigger type to âan itemâs state is updatedâ and choose MotionDetector
as the Item.
With these settings and changes, the light will be commanded on immediately when MotionSensor
changes to ON
and after five minutes the light will be commanded off and MotionSensor
reset to OFF
.
This approach is best when your requirements for the motion sensor may be more complicated (e.g. you want it to not turn on the light during the day) or you are doing something based on a threshold (e.g. turning on a heater based on the current temperature).
Blockly
Trigger the rule when MotionSensor
receives an update.
If you have lots of motion sensor and light pairs, consider using Timer Manager from openHAB Rules Tools [4.1.0.0;4.9.9.9].
JS Scripting
Trigger the rule when MotionSensor
receives an update.
items.Light.sendCommand('ON');
var timer = cache.private.get('timer');
if(timer === null || timer.hasTerminated()) {
cache.private.put('timer', actions.ScriptExecution.createTimer(time.toZDT('PT5M'), () => {
items.Light.sendCommand('OFF');
items.MotionSensor.postUpdate('OFF');
}
}
else {
timer.reschedule(time.toZDT('PT5M');
}
Rules DSL
Trigger the rule when MotionSensor
receives an update.
Light.sendCommand(ON)
val timer = privateCache.get('timer')
if(timer === null || timer.hasTerminated()) {
privateCache.put('privateCache', createTimer(now.plusMinutes(5), [ |
Light.sendCommand(OFF)
MotionSensor.postUpdate(OFF)
])
}
Jython
from core.rules import rule
from core.triggers import when
from core.actions import ScriptExecution
from org.joda.time import DateTime
occupancyTimer = None
@rule("Motion sensor triggered")
@when("Item MotionSensor received update ON")
def motion(event):
global occupancyTimer
events.sendCommand("Light", "ON");
if occupancyTimer is None or occupancyTimer.hasTerminated():
occupancyTimer = ScriptExecution.createTimer(DateTime.now().plusMinutes(5), lambda: events.sendCommand("MotionSensor", "OFF"))
else:
occupancyTimer.reschedule(DateTime.now().plusMinutes(5))
Related Design Patterns
Design Pattern | How Itâs Used |
---|---|
Design Pattern: Sensor Aggregation | The complex example of Sensor Aggregation uses this DP to implement an ant-flapping timer. |
[Deprecated] Design Pattern: Debounce | A similar DP that involves changes instead of updates. |