Last active
September 7, 2025 16:48
-
-
Save thomasmaxson/635084f3a7f8e1877542c210b39c6ed5 to your computer and use it in GitHub Desktop.
Home Assistant Blueprint to manage room occupancy state via door and presence sensors.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| blueprint: | |
| name: Manage Area State via Sensors | |
| description: >- | |
| Manage occupancy state via multiple sensors. | |
| - Control what happens when a door opens or occupancy is detected. | |
| - Control what happens when a door closes or occupancy is cleared. | |
| author: Thomas Maxson | |
| source_url: https://gist.github.com/thomasmaxson/635084f3a7f8e1877542c210b39c6ed5 | |
| homeassistant: | |
| min_version: 2024.6.0 | |
| domain: automation | |
| input: | |
| sensor_door: | |
| name: Door Sensor | |
| selector: | |
| entity: | |
| multiple: false | |
| filter: | |
| domain: binary_sensor | |
| sensor_occupancy: | |
| name: Occupancy Sensor | |
| selector: | |
| entity: | |
| multiple: false | |
| filter: | |
| domain: binary_sensor | |
| group_door_specific_actions: | |
| name: Door Actions | |
| icon: mdi:door | |
| collapsed: true | |
| input: | |
| enable_door_action: | |
| name: Door Opened Action(s) | |
| description: "Action(s) to perform when the door is opened." | |
| default: [] | |
| selector: | |
| action: | |
| disable_door_action: | |
| name: Door Closed Action(s) | |
| description: "Action(s) to perform when the door is closed." | |
| default: [] | |
| selector: | |
| action: | |
| group_occupancy_specific_actions: | |
| name: Occupancy Actions | |
| icon: mdi:account | |
| collapsed: true | |
| input: | |
| enable_occupancy_action_now: | |
| name: Occupancy Detected Action(s) | |
| description: "Action(s) to perform when occupancy is detected." | |
| default: [] | |
| selector: | |
| action: | |
| disable_occupancy_action_now: | |
| name: Occupancy Cleared Action(s) | |
| description: "Action(s) to perform when occupancy is cleared." | |
| default: [] | |
| selector: | |
| action: | |
| enable_action_wait_duration: | |
| name: Action Delay Duration | |
| description: "The amount of time to wait until delayed active actions are triggered." | |
| default: 60 | |
| selector: | |
| number: | |
| mode: box | |
| unit_of_measurement: seconds | |
| min: 0.0 | |
| max: 3600.0 | |
| step: 1.0 | |
| enable_occupancy_action_wait: | |
| name: Delayed Occupancy Detected Action(s) | |
| description: "Action(s) to perform when activity is detected, after a specified delay." | |
| default: [] | |
| selector: | |
| action: | |
| disable_action_wait_duration: | |
| name: Inaction Delay Duration | |
| description: "The amount of time to wait until delayed inactive actions are triggered." | |
| default: 60 | |
| selector: | |
| number: | |
| mode: box | |
| unit_of_measurement: seconds | |
| min: 0.0 | |
| max: 3600.0 | |
| step: 1.0 | |
| disable_occupancy_action_wait: | |
| name: Delayed Occupancy Cleared Action(s) | |
| description: "Action(s) to perform when activity is no longer detected, after a specified delay." | |
| default: [] | |
| selector: | |
| action: | |
| group_area_config: | |
| name: Helpers | |
| icon: mdi:cog | |
| collapsed: true | |
| input: | |
| idle_timer: | |
| name: Idle Timer | |
| description: "After this timer elapses, devices will automatically revert to their inactive state." | |
| default: "timer.undefined" | |
| selector: | |
| entity: | |
| multiple: false | |
| filter: | |
| domain: timer | |
| # variables: | |
| # sensor_door: !input sensor_door | |
| # sensor_occupancy: !input sensor_occupancy | |
| # enable_door_action: !input enable_door_action | |
| # disable_door_action: !input disable_door_action | |
| # enable_occupancy_action_now: !input enable_occupancy_action_now | |
| # disable_occupancy_action_now: !input disable_occupancy_action_now | |
| # enable_action_wait_duration: !input enable_action_wait_duration | |
| # disable_action_wait_duration: !input disable_action_wait_duration | |
| # enable_occupancy_action_wait: !input enable_occupancy_action_wait | |
| # disable_occupancy_action_wait: !input disable_occupancy_action_wait | |
| # idle_timer: !input idle_timer | |
| triggers: | |
| - alias: "When door is OPENED - IMMEDIATE" | |
| trigger: state | |
| entity_id: !input sensor_door | |
| from: "off" | |
| to: "on" | |
| id: event_now_door_open | |
| - alias: "When door is OPENED - DELAYED" | |
| trigger: state | |
| entity_id: !input sensor_door | |
| from: "off" | |
| to: "on" | |
| for: !input enable_action_wait_duration | |
| id: event_wait_door_open | |
| - alias: "When door is CLOSED - IMMEDIATE" | |
| trigger: state | |
| entity_id: !input sensor_door | |
| from: "on" | |
| to: "off" | |
| id: event_now_door_close | |
| - alias: "When door is CLOSED - DELAYED" | |
| trigger: state | |
| entity_id: !input sensor_door | |
| from: "on" | |
| to: "off" | |
| for: !input disable_action_wait_duration | |
| id: event_wait_door_close | |
| - alias: "When motion is DETECTED - IMMEDIATE" | |
| trigger: state | |
| entity_id: !input sensor_occupancy | |
| from: "off" | |
| to: "on" | |
| id: event_now_motion_detect | |
| - alias: "When motion is DETECTED - DELAYED" | |
| trigger: state | |
| entity_id: !input sensor_occupancy | |
| from: "on" | |
| to: "off" | |
| for: !input enable_action_wait_duration | |
| id: event_wait_motion_detect | |
| - alias: "When motion is CLEARED - IMMEDIATE" | |
| trigger: state | |
| entity_id: !input sensor_occupancy | |
| from: "on" | |
| to: "off" | |
| id: event_now_motion_clear | |
| - alias: "When motion is CLEARED - DELAYED" | |
| trigger: state | |
| entity_id: !input sensor_occupancy | |
| from: "on" | |
| to: "off" | |
| for: !input disable_action_wait_duration | |
| id: event_wait_motion_clear | |
| - alias: "When idle timer ENDS - IMMEDIATE" | |
| trigger: event | |
| event_type: timer.finished | |
| event_data: | |
| entity_id: !input idle_timer | |
| id: event_idle_timer_finished | |
| actions: | |
| - alias: "Choose actions to check and run" | |
| choose: | |
| - alias: "Actions to perform if DOOR OPENED" | |
| conditions: | |
| - alias: "Check if trigged by event" | |
| condition: trigger | |
| id: event_now_door_open | |
| sequence: !input enable_door_action | |
| - alias: "Actions to perform if DOOR CLOSED" | |
| conditions: | |
| - alias: "Check if trigged by event" | |
| condition: trigger | |
| id: event_now_door_close | |
| sequence: !input disable_door_action | |
| - alias: "Actions to perform if DOOR OPENED, and MOTION DETECTED" | |
| conditions: | |
| - alias: "Ensure all events are true" | |
| condition: and | |
| conditions: | |
| - alias: "Check if trigged by event" | |
| condition: trigger | |
| id: event_wait_door_open | |
| - alias: "Check if occupancy is detected" | |
| condition: state | |
| entity_id: !input sensor_occupancy | |
| state: "on" | |
| sequence: !input enable_occupancy_action_wait | |
| - alias: "Actions to perform if DOOR OPENED, and MOTION CLEAR" | |
| conditions: | |
| - alias: "Ensure all events are true" | |
| condition: and | |
| conditions: | |
| - alias: "Check if trigged by event" | |
| condition: trigger | |
| id: event_now_door_open | |
| - alias: "Check if occupancy is not detected" | |
| condition: state | |
| entity_id: !input sensor_occupancy | |
| state: "off" | |
| sequence: | |
| - alias: "If configured, manage idle TIMER" | |
| if: | |
| - alias: "Confirm idle time is set" | |
| condition: template | |
| value_template: "{{ true if idle_timer != 'timer.undefined' }}" | |
| then: | |
| - alias: "Idle Timer, RESET" | |
| action: timer.cancel | |
| target: | |
| entity_id: !input idle_timer | |
| data: {} | |
| - alias: "Idle Timer, START" | |
| action: timer.start | |
| metadata: {} | |
| data: {} | |
| target: | |
| entity_id: !input idle_timer | |
| # Action: IMMEDIATE DISABLE | |
| - alias: "Actions to perform if DOOR CLOSED, and MOTION CLEAR" | |
| conditions: | |
| - alias: "Ensure all events are true" | |
| condition: and | |
| conditions: | |
| - alias: "Check if trigged by event" | |
| condition: trigger | |
| id: event_now_door_close | |
| - alias: "Check if occupancy is not detected" | |
| condition: state | |
| entity_id: !input sensor_occupancy | |
| state: "off" | |
| sequence: !input disable_occupancy_action_now | |
| - alias: "Actions to perform when DOOR CLOSED, and MOTION CLEARED after delay" | |
| conditions: | |
| - alias: "Ensure all events are true" | |
| condition: and | |
| conditions: | |
| - alias: "Check if trigged by event" | |
| condition: trigger | |
| id: event_wait_door_close | |
| - alias: "Check if occupancy is not detected" | |
| condition: state | |
| entity_id: !input sensor_occupancy | |
| state: "off" | |
| sequence: | |
| - alias: "If configured, RUN delayed disable ACTIONS" | |
| if: | |
| - condition: template | |
| value_template: "{{ disable_occupancy_action_wait | length > 0 }}" | |
| then: !input disable_occupancy_action_wait | |
| - alias: "If configured, CANCEL idle TIMER" | |
| if: | |
| - alias: "Ensure all events are true" | |
| condition: and | |
| conditions: | |
| - alias: "Confirm idle time is set" | |
| condition: template | |
| value_template: "{{ true if idle_timer != 'timer.undefined' }}" | |
| - alias: "Check if idle time is running" | |
| condition: state | |
| entity_id: !input idle_timer | |
| state: active | |
| then: | |
| - alias: "Idle Timer, RESET" | |
| action: timer.cancel | |
| data: {} | |
| target: | |
| entity_id: !input idle_timer | |
| - alias: "Actions to perform when DOOR OPEN, and MOTION DETECTED" | |
| conditions: | |
| - alias: "Ensure all events are true" | |
| condition: and | |
| conditions: | |
| - alias: "Check if trigged by event" | |
| condition: trigger | |
| id: event_now_motion_detect | |
| - alias: "Check if door is open" | |
| condition: state | |
| entity_id: !input sensor_door | |
| state: "on" | |
| sequence: | |
| - alias: "If configured, RUN immediate enable ACTIONS" | |
| if: | |
| - condition: template | |
| value_template: "{{ enable_occupancy_action_now | length > 0 }}" | |
| then: !input enable_occupancy_action_now | |
| - alias: "" | |
| if: | |
| - condition: template | |
| value_template: "{{ enable_occupancy_action_wait | length > 0 }}" | |
| then: !input enable_occupancy_action_wait | |
| - alias: "If configured, START idle TIMER" | |
| if: | |
| - alias: "Ensure all events are true" | |
| condition: and | |
| conditions: | |
| - alias: "Confirm idle time is set" | |
| condition: template | |
| value_template: "{{ true if idle_timer != 'timer.undefined' }}" | |
| - alias: "Check if idle timer is active" | |
| condition: state | |
| entity_id: !input idle_timer | |
| state: active | |
| then: | |
| - alias: "Idle Timer, RESET" | |
| action: timer.cancel | |
| data: {} | |
| target: | |
| entity_id: !input idle_timer | |
| - alias: "Actions to perform when MOTION CLEARED" | |
| conditions: | |
| - alias: "Check if trigged by event" | |
| condition: trigger | |
| id: event_wait_motion_clear | |
| sequence: | |
| - alias: "If configured, RUN immediate disable ACTIONS" | |
| if: | |
| - condition: template | |
| value_template: "{{ disable_occupancy_action_now | length > 0 }}" | |
| then: !input disable_occupancy_action_now | |
| # - if: | |
| # - condition: template | |
| # value_template: "{{ disable_occupancy_action_wait | length > 0 }}" | |
| # then: !input disable_occupancy_action_wait | |
| - alias: "If DOOR is OPEN" | |
| if: | |
| - alias: "Ensure all events are true" | |
| condition: and | |
| conditions: | |
| - alias: "Confirm idle time is set" | |
| condition: template | |
| value_template: "{{ true if idle_timer != 'timer.undefined' }}" | |
| - alias: "Check if door is open" | |
| condition: state | |
| entity_id: !input sensor_door | |
| state: "on" | |
| then: | |
| - alias: "Idle Timer, RESET" | |
| action: timer.cancel | |
| target: | |
| entity_id: !input idle_timer | |
| data: {} | |
| - alias: "Idle Timer, START" | |
| action: timer.start | |
| metadata: {} | |
| data: {} | |
| target: | |
| entity_id: !input idle_timer | |
| - alias: "Actions to perform when occupancy TIMER FINISHED" | |
| conditions: | |
| - condition: trigger | |
| id: event_idle_timer_finished | |
| sequence: | |
| - if: | |
| - alias: "Check if occupancy is not detected" | |
| condition: state | |
| entity_id: !input sensor_occupancy | |
| state: "off" | |
| then: | |
| - alias: "Idle Timer, RESET" | |
| action: timer.cancel | |
| data: {} | |
| target: | |
| entity_id: !input idle_timer | |
| - alias: "If configured, RUN immediate disable ACTIONS" | |
| if: | |
| - condition: template | |
| value_template: "{{ disable_occupancy_action_now | length > 0 }}" | |
| then: !input disable_occupancy_action_now | |
| - alias: "If configured, RUN delayed disable ACTIONS" | |
| if: | |
| - condition: template | |
| value_template: "{{ disable_occupancy_action_wait | length > 0 }}" | |
| then: !input disable_occupancy_action_wait | |
| else: | |
| - alias: "Idle Timer, RESET" | |
| action: timer.cancel | |
| data: {} | |
| target: | |
| entity_id: !input idle_timer | |
| - alias: "Idle Timer, START" | |
| action: timer.start | |
| metadata: {} | |
| data: {} | |
| target: | |
| entity_id: !input idle_timer | |
| mode: single | |
| max_exceeded: silent |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment