-
-
Save AlexanderBabel/487f054b289b61f90afdc837d23cb85e to your computer and use it in GitHub Desktop.
blueprint: | |
name: Occupancy | |
description: | | |
This blueprint is based on the Wasp in a box princible. It is inspired by the AppDaemon app that does the same thing. | |
You can find more information about this blueprint on the Home Assistant Community: https://community.home-assistant.io/t/occupancy-blueprint/477772 | |
domain: automation | |
source_url: https://gist.github.com/AlexanderBabel/487f054b289b61f90afdc837d23cb85e | |
input: | |
door_sensor: | |
name: Single Door Sensor or Door Sensor Group | |
selector: | |
entity: | |
filter: | |
- domain: binary_sensor | |
- domain: input_boolean | |
motion_sensor: | |
name: Single Motion Sensor or Motion Sensor Group | |
selector: | |
entity: | |
filter: | |
- domain: binary_sensor | |
- domain: input_boolean | |
turn_off_delay: | |
name: Motion Sensor turn off delay | |
description: "Time after the sensor no longer detects motion to set the occupancy to clear. (Default = 5s)" | |
default: 5 | |
selector: | |
number: | |
mode: box | |
min: 0 | |
max: 3600 | |
unit_of_measurement: seconds | |
step: 1.0 | |
motion_sensor_delay: | |
name: Motion Sensor Delay | |
description: | | |
The time the motion sensor takes before clearning it's detected state. (Default=-1 [Disabled]) | |
I would recommend to add some extra delay to prevent false positives. E.g. If your sensor has a delay of 10 seconds set a delay of 12s. | |
default: -1 | |
selector: | |
number: | |
mode: box | |
min: -1 | |
max: 3600 | |
unit_of_measurement: seconds | |
step: 1.0 | |
occupancy_helper: | |
name: Occupancy Helper (Type input_boolean) | |
description: This helper saves the occupancy state and can be used as a trigger of e.g. your light automation. | |
selector: | |
entity: | |
domain: input_boolean | |
multiple: false | |
last_motion_helper: | |
name: Last Motion Helper (Type date and time) | |
description: This helper saves when the last movement was detected by the motion sensor or motion sensor group. This is necessary to prevent a false occupancy when you directly close the door behind you. | |
selector: | |
entity: | |
domain: input_datetime | |
multiple: false | |
variables: | |
door_sensor: !input door_sensor | |
motion_sensor: !input motion_sensor | |
last_motion_helper: !input last_motion_helper | |
motion_sensor_delay: !input motion_sensor_delay | |
trigger: | |
- platform: state | |
entity_id: !input motion_sensor | |
from: "off" | |
to: "on" | |
id: motion | |
- platform: state | |
entity_id: !input door_sensor | |
id: door_opened | |
from: "off" | |
to: "on" | |
- platform: state | |
entity_id: !input motion_sensor | |
from: "on" | |
to: "off" | |
for: !input turn_off_delay | |
id: clear | |
condition: [] | |
action: | |
- choose: | |
- conditions: | |
- condition: trigger | |
id: motion | |
sequence: | |
- service: input_datetime.set_datetime | |
data: | |
timestamp: "{{ as_timestamp(now()) }}" | |
target: | |
entity_id: !input last_motion_helper | |
- if: | |
- condition: state | |
entity_id: !input occupancy_helper | |
state: "off" | |
then: | |
- service: input_boolean.turn_on | |
data: {} | |
target: | |
entity_id: !input occupancy_helper | |
- conditions: | |
- condition: state | |
entity_id: !input occupancy_helper | |
state: "on" | |
- condition: or | |
conditions: | |
- condition: and | |
conditions: | |
- condition: trigger | |
id: clear | |
- condition: or | |
conditions: | |
- condition: state | |
entity_id: !input door_sensor | |
state: "on" | |
- condition: template | |
value_template: >- | |
{{ is_state(door_sensor, 'off') and | |
(as_local(as_datetime(states(last_motion_helper))) < states[door_sensor].last_changed and | |
(motion_sensor_delay == -1 or (motion_sensor_delay > -1 and | |
states[motion_sensor].last_changed - timedelta(seconds=motion_sensor_delay) <= states[door_sensor].last_changed))) }} | |
alias: True, when the door is closed and last motion was detected before door was closed and no motion was detected in the timeout period | |
alias: Check if door is open or closed and no motion was detected afterwards | |
- condition: and | |
conditions: | |
- condition: trigger | |
id: door_opened | |
- condition: state | |
entity_id: !input motion_sensor | |
state: "off" | |
sequence: | |
- service: input_boolean.turn_off | |
data: {} | |
target: | |
entity_id: !input occupancy_helper | |
default: [] | |
mode: queued | |
max: 10 |
The motion sensor has to detect motion once while the door is closed. When the Motion is detected beforehand it will not count.
The problem is if you use z2m or a motion sensor that does not send each detection data then this script might not get into the "wasp in box" state.
I have Aqara P1 set for 5sec detection intervals and 30sec timeout in the blueprint
For example my wife "Always triggers"
0min 00sec - Someone opens the door motion is detected Occupancy Helper is set to on, Last Motion set to 0:00
0:03 - Door closed
0:05 - P1 detects motion -> it is not sent to z2m as it does not change the Sensor State, Last Motion is still 0:00
0:10 - P1 detects another motion -> it is not sent to z2m as it does not change the Sensor State, Last Motion is still 0:00
0:15 - Toilet sitting started P1 detects no motion this is sent to z2m.
0:20 - P1 detects no motion -> it is not sent to z2m as it does not change the Sensor State, Last Motion is still 0:00
0:25 - P1 detects no motion -> it is not sent to z2m as it does not change the Sensor State, Last Motion is still 0:00
0:30 - 30s timeout triggered - Wife complaints on lights switching off ;)
@AlexanderBabel Thanks for the blueprint, very useful. Can you allow adding input_boolean as an input for door_sensor and motion_sensor from ui. This would allow for more complex automations. I would have created a pull request, but unfortunately I cant create PRs for gists (stupid github). Code change below for your convenience:
door_sensor:
name: Single Door Sensor or Door Sensor Group
selector:
entity:
filter:
- domain: binary_sensor
- domain: input_boolean
motion_sensor:
name: Single Motion Sensor or Motion Sensor Group
selector:
entity:
filter:
- domain: binary_sensor
- domain: input_boolean
Thank you for your suggestion. I added the improvement to the original gist :)
Good day, I'm trying to use this but every time the motion sensor clears, the boolean turns off which turns the lights off all while the door is closed which indicates occupancy. I thought door closed = lights on always?