Created
July 14, 2026 20:59
-
-
Save paradonym/eec092f74e28928262dfa57697deeb51 to your computer and use it in GitHub Desktop.
Zone Presence of People & Devices — Zigbee2MQTT compatible fork of Blackshome/798cd918c0d078cbc901d5894a0aa6b1. Adds an 'Entity State' tracking mode for Z2M binary_sensors/switches/sensors, guards against unavailable/unknown states, keeps original people + device_tracker zone matching.
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: Zone Presence of People & Devices (Zigbee2MQTT Compatible) | |
| description: > | |
| # 🌐 Zone Presence of People & Devices — Zigbee2MQTT Compatible Fork | |
| **Version: 1.1-z2m** | |
| Smart tracking for smarter living! 🎯 | |
| This is a customized fork of Blackshome's original | |
| [Zone Presence blueprint](https://gist.github.com/Blackshome/798cd918c0d078cbc901d5894a0aa6b1), | |
| adapted to work reliably alongside **Zigbee2MQTT** integrations. | |
| ### What changed vs. the original | |
| The original **Devices** tracking mode only accepted `device_tracker` | |
| entities and matched their *state* against the zone name | |
| (`state == zone_name`). Zigbee2MQTT entities (binary_sensor, switch, | |
| sensor, etc.) do **not** report a zone name as their state, and they are | |
| not `device_tracker` entities, so: | |
| - They could not be selected in the Devices picker, and | |
| - The presence template never matched (this caused the | |
| *"automation couldn't read details from devices"* error). | |
| This fork: | |
| - **Keeps** the original `people` (person entities) mode — unchanged. | |
| - **Keeps** the original `device_tracker` zone-name matching mode | |
| (renamed *Device Trackers*) so existing setups keep working. | |
| - **Adds** a new **Entity State** mode: track ANY entity | |
| (binary_sensor, sensor, switch, etc. — including Zigbee2MQTT | |
| entities) and define what state counts as "present" via a | |
| configurable *Present State* value (default `on`). | |
| - Guards every presence template against `unavailable` / `unknown` | |
| states and missing attributes so a briefly-offline Zigbee device no | |
| longer throws template errors. | |
| **Recommended pattern for your use case:** track *people* (person | |
| entities) for presence, and control your Zigbee2MQTT devices in the | |
| **Custom Actions** section (call `light.turn_on`, `switch.turn_off`, | |
| `homeassistant.turn_on`, etc. on your Z2M entities). | |
| **Original author — if you like these blueprints, show support:** | |
| [Click Here](https://www.paypal.com/donate/?hosted_button_id=WAZS3QSDTPGA8) 🙂 | |
| - Original FAQ: [Click Here](https://community.home-assistant.io/t/940901/2) | |
| - Original community thread: [Click Here](https://community.home-assistant.io/t/940901) | |
| Required = * | |
| domain: automation | |
| input: | |
| trigger: | |
| name: "Trigger *" | |
| icon: mdi:cog-outline | |
| collapsed: true | |
| input: | |
| zone: | |
| name: Zone to Monitor | |
| description: > | |
| The zone where presence should be checked (e.g., Home, Work). | |
| Used by the **People** and **Device Trackers** modes. Not required | |
| for **Entity State** mode. | |
| default: [] | |
| selector: | |
| entity: | |
| filter: | |
| domain: zone | |
| zone_condition: | |
| name: Zone Condition | |
| description: > | |
| Choose whether the automation should turn ON when the selected | |
| people/devices/entities are **inside** (present) or **outside** | |
| (absent) the zone. | |
| default: inside_zone | |
| selector: | |
| select: | |
| options: | |
| - label: Inside Zone / Present | |
| value: "inside_zone" | |
| - label: Outside Zone / Absent | |
| value: "outside_zone" | |
| tracking_mode: | |
| name: Tracking Mode | |
| description: > | |
| Select what you want to track: | |
| - **People** — `person` entities matched against the zone's | |
| `persons` attribute (original behavior). | |
| - **Device Trackers** — `device_tracker` entities whose *state* | |
| equals the zone name (original behavior). | |
| - **Entity State (Zigbee2MQTT compatible)** — ANY entity | |
| (binary_sensor, sensor, switch, etc.). "Present" is decided by | |
| comparing the entity state to a configurable *Present State* | |
| value. Use this for Zigbee2MQTT entities. | |
| default: people | |
| selector: | |
| select: | |
| options: | |
| - label: People | |
| value: "people" | |
| - label: Device Trackers | |
| value: "devices" | |
| - label: Entity State (Zigbee2MQTT compatible) | |
| value: "entities" | |
| people: | |
| name: People to Track | |
| description: > | |
| The person entities to monitor. Only used if Tracking Mode is set | |
| to People. | |
| **Tip** - While you can assign multiple devices to a person, only | |
| one reliable device (usually a phone with location services | |
| enabled) is needed for accurate presence tracking. | |
| default: [] | |
| selector: | |
| entity: | |
| filter: | |
| domain: person | |
| multiple: true | |
| devices: | |
| name: Device Trackers to Track | |
| description: > | |
| The `device_tracker` entities to monitor. Only used if Tracking | |
| Mode is set to Device Trackers. Their state is compared against the | |
| monitored zone name. | |
| default: [] | |
| selector: | |
| entity: | |
| filter: | |
| domain: device_tracker | |
| multiple: true | |
| entities: | |
| name: Entities to Track (Zigbee2MQTT compatible) | |
| description: > | |
| ANY entities to monitor — including Zigbee2MQTT entities such as | |
| occupancy/presence `binary_sensor`s, `switch`es or `sensor`s. Only | |
| used if Tracking Mode is set to **Entity State**. | |
| "Present" is determined by comparing each entity's state to the | |
| **Present State** value below (default `on`). | |
| default: [] | |
| selector: | |
| entity: | |
| multiple: true | |
| present_state: | |
| name: Present State (Entity State mode) | |
| description: > | |
| The state value that counts as "present / inside" for the | |
| **Entity State** mode. For most Zigbee2MQTT occupancy/presence | |
| binary sensors this is `on`. Could also be `home`, `detected`, | |
| `true`, or any custom string your device reports. | |
| default: "on" | |
| selector: | |
| text: | |
| min_count: | |
| name: Minimum Required | |
| description: > | |
| The minimum number of selected people/devices/entities that must | |
| match the condition (inside/present or outside/absent) for the | |
| automation to trigger ON. | |
| default: 1 | |
| selector: | |
| number: | |
| min: 1 | |
| max: 20 | |
| step: 1 | |
| presence_helper_settings: | |
| name: "Presence Helper" | |
| icon: mdi:account-multiple-check-outline | |
| collapsed: true | |
| input: | |
| include_presence_helper: | |
| name: Presence Helper Option (Optional) | |
| description: > | |
| Enable or disable the use of a presence helper (toggle helper) that | |
| can be updated in one place but reused across multiple automations. | |
| default: disable_presence_helper | |
| selector: | |
| select: | |
| options: | |
| - label: Enable presence helper option | |
| value: "enable_presence_helper" | |
| - label: Disable presence helper option | |
| value: "disable_presence_helper" | |
| presence_helper: | |
| name: Presence Helper | |
| description: > | |
| The presence helper (toggle helper) that will be toggled ON and OFF. | |
| default: [] | |
| selector: | |
| entity: | |
| filter: | |
| domain: input_boolean | |
| presence_helper_on_delay: | |
| name: Delay Before Turning ON | |
| description: > | |
| Delay in minutes before turning ON the presence helper after | |
| conditions are met. | |
| default: 0 | |
| selector: | |
| number: | |
| min: 0 | |
| max: 60 | |
| step: 1 | |
| unit_of_measurement: minutes | |
| presence_helper_off_delay: | |
| name: Delay Before Turning OFF | |
| description: > | |
| Delay in minutes to wait before turning OFF the presence helper | |
| after conditions are no longer met. | |
| default: 0 | |
| selector: | |
| number: | |
| min: 0 | |
| max: 60 | |
| step: 1 | |
| unit_of_measurement: minutes | |
| bypass_settings: | |
| name: "Bypass" | |
| icon: mdi:cog-pause-outline | |
| collapsed: true | |
| input: | |
| include_bypass: | |
| name: Bypass Option (Optional) | |
| description: > | |
| Enable or disable the use of a bypass switch to temporarily disable | |
| this automation. | |
| default: disable_bypass | |
| selector: | |
| select: | |
| options: | |
| - label: Enable bypass option | |
| value: "enable_bypass" | |
| - label: Disable bypass option | |
| value: "disable_bypass" | |
| bypass_entity: | |
| name: Bypass Switch | |
| description: > | |
| Select a toggle helper (input_boolean) that will bypass this | |
| automation while it is ON. | |
| default: [] | |
| selector: | |
| entity: | |
| filter: | |
| domain: input_boolean | |
| custom_actions_settings: | |
| name: "Custom Actions" | |
| icon: mdi:code-tags | |
| collapsed: true | |
| input: | |
| include_custom_actions: | |
| name: Use the Custom Action Options (Optional) | |
| description: > | |
| Enable custom actions to run when the automation turns ON or OFF. | |
| **This is where you control your Zigbee2MQTT devices** — e.g. call | |
| `light.turn_on`, `switch.turn_off`, or `homeassistant.turn_on` on | |
| your Z2M entities. | |
| default: [] | |
| selector: | |
| select: | |
| options: | |
| - label: Enable Custom Actions - ON | |
| value: "enable_on_custom_actions" | |
| - label: Enable Custom Actions - OFF | |
| value: "enable_off_custom_actions" | |
| multiple: true | |
| on_custom_actions: | |
| name: Custom Actions - Start | |
| description: > | |
| The actions to run when the automation turns ON. | |
| default: [] | |
| selector: | |
| action: | |
| off_custom_actions: | |
| name: Custom Actions - End | |
| description: > | |
| The actions to run when the automation turns OFF. | |
| default: [] | |
| selector: | |
| action: | |
| mode: restart | |
| variables: | |
| zone_entity: !input zone | |
| zone_name: "{{ zone_entity.split('.')[-1] if zone_entity else '' }}" | |
| zone_condition: !input zone_condition | |
| tracking_mode: !input tracking_mode | |
| people: !input people | |
| devices: !input devices | |
| entities: !input entities | |
| present_state: !input present_state | |
| min_count: !input min_count | |
| include_presence_helper: !input include_presence_helper | |
| presence_helper: !input presence_helper | |
| presence_helper_on_delay: !input presence_helper_on_delay | |
| presence_helper_off_delay: !input presence_helper_off_delay | |
| include_bypass: !input include_bypass | |
| bypass_entity: !input bypass_entity | |
| include_custom_actions: !input include_custom_actions | |
| on_custom_actions: !input on_custom_actions | |
| off_custom_actions: !input off_custom_actions | |
| triggers: | |
| - trigger: state | |
| id: "t0" | |
| entity_id: !input people | |
| to: null | |
| - trigger: state | |
| id: "t1" | |
| entity_id: !input devices | |
| to: null | |
| - trigger: state | |
| id: "t2" | |
| entity_id: !input entities | |
| to: null | |
| # All Conditions | |
| condition: | |
| # Trigger conditions — only continue for the trigger matching the active mode | |
| - condition: or | |
| conditions: | |
| - condition: and # trigger for people | |
| conditions: | |
| - condition: template | |
| value_template: "{{ tracking_mode == 'people' }}" | |
| - condition: trigger | |
| id: 't0' | |
| - condition: and # trigger for device_trackers | |
| conditions: | |
| - condition: template | |
| value_template: "{{ tracking_mode == 'devices' }}" | |
| - condition: trigger | |
| id: 't1' | |
| - condition: and # trigger for generic entities (Zigbee2MQTT) | |
| conditions: | |
| - condition: template | |
| value_template: "{{ tracking_mode == 'entities' }}" | |
| - condition: trigger | |
| id: 't2' | |
| # Check Bypass | |
| - condition: or | |
| conditions: | |
| - "{{ include_bypass == 'disable_bypass' }}" | |
| - "{{ bypass_entity == [] }}" | |
| - "{{ (include_bypass == 'enable_bypass') and (states[bypass_entity].state == 'off') }}" | |
| action: | |
| - choose: | |
| - conditions: | |
| - condition: template | |
| value_template: > | |
| {% if tracking_mode == 'people' %} | |
| {% set persons_in_zone = state_attr(zone_entity, 'persons') | default([], true) | list %} | |
| {% if zone_condition == 'inside_zone' %} | |
| {{ (persons_in_zone | select('in', people) | list | length) >= min_count }} | |
| {% else %} | |
| {{ (people | reject('in', persons_in_zone) | list | length) >= min_count }} | |
| {% endif %} | |
| {% elif tracking_mode == 'devices' %} | |
| {% set tracked = expand(devices) | rejectattr('state', 'in', ['unavailable', 'unknown']) | list %} | |
| {% if zone_condition == 'inside_zone' %} | |
| {{ (tracked | selectattr('state', 'eq', zone_name) | list | length) >= min_count }} | |
| {% else %} | |
| {{ (tracked | rejectattr('state', 'eq', zone_name) | list | length) >= min_count }} | |
| {% endif %} | |
| {% else %} | |
| {% set tracked = expand(entities) | rejectattr('state', 'in', ['unavailable', 'unknown']) | list %} | |
| {% if zone_condition == 'inside_zone' %} | |
| {{ (tracked | selectattr('state', 'eq', present_state) | list | length) >= min_count }} | |
| {% else %} | |
| {{ (tracked | rejectattr('state', 'eq', present_state) | list | length) >= min_count }} | |
| {% endif %} | |
| {% endif %} | |
| sequence: | |
| - alias: "Parallel actions to turn on" | |
| parallel: | |
| - sequence: | |
| - choose: | |
| - alias: "Check if toggle helper is enabled and helper is OFF" | |
| conditions: | |
| - condition: template | |
| value_template: "{{ include_presence_helper == 'enable_presence_helper' }}" | |
| - condition: template | |
| value_template: "{{ is_state(presence_helper, 'off') }}" | |
| sequence: | |
| - delay: | |
| minutes: "{{ presence_helper_on_delay }}" | |
| - action: homeassistant.turn_on | |
| target: | |
| entity_id: "{{ presence_helper }}" | |
| - sequence: | |
| - choose: | |
| - alias: "Perform the custom ON action" | |
| conditions: | |
| - condition: template | |
| value_template: "{{ 'enable_on_custom_actions' in include_custom_actions }}" | |
| sequence: !input on_custom_actions | |
| default: | |
| - alias: "Parallel actions to turn off" | |
| parallel: | |
| - sequence: | |
| - choose: | |
| - alias: "Check if toggle helper is enabled and helper is ON" | |
| conditions: | |
| - condition: template | |
| value_template: "{{ include_presence_helper == 'enable_presence_helper' }}" | |
| - condition: template | |
| value_template: "{{ is_state(presence_helper, 'on') }}" | |
| sequence: | |
| - delay: | |
| minutes: "{{ presence_helper_off_delay }}" | |
| - action: homeassistant.turn_off | |
| target: | |
| entity_id: "{{ presence_helper }}" | |
| - sequence: | |
| - choose: | |
| - alias: "Perform the custom OFF action" | |
| conditions: | |
| - condition: template | |
| value_template: "{{ 'enable_off_custom_actions' in include_custom_actions }}" | |
| sequence: !input off_custom_actions |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment