Skip to content

Instantly share code, notes, and snippets.

@AlexanderBabel
Last active October 20, 2024 18:55
Show Gist options
  • Save AlexanderBabel/487f054b289b61f90afdc837d23cb85e to your computer and use it in GitHub Desktop.
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
@harphere
Copy link

harphere commented Feb 7, 2023

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?

@AlexanderBabel
Copy link
Author

The motion sensor has to detect motion once while the door is closed. When the Motion is detected beforehand it will not count.

@mprzekop-equinix
Copy link

mprzekop-equinix commented Mar 21, 2023

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 ;)

@karteekiitg
Copy link

karteekiitg commented Oct 19, 2024

@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

@AlexanderBabel
Copy link
Author

Thank you for your suggestion. I added the improvement to the original gist :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment