Skip to content

Instantly share code, notes, and snippets.

@paradonym
Created July 14, 2026 20:59
Show Gist options
  • Select an option

  • Save paradonym/eec092f74e28928262dfa57697deeb51 to your computer and use it in GitHub Desktop.

Select an option

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.
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