Zigbee2MQTT offline devices sensor

I’ve created a sensor for offline zigbee2mqtt devices to show in my network dashboard, the sensor relies on pyscript, subscribes to availability topics and counts the offline devices.
image

pyscript code:

import json
import re

zigbee2mqtt_offline_devices = {}

@state_trigger("sensor.offline_zigbee_devices")
def update_icon():
  sensor.offline_zigbee_devices.icon = "mdi:zigbee"
  sensor.offline_zigbee_devices.friendly_name = "Offline Zigbee Devices"
  sensor.offline_zigbee_devices.state_class = "measurement"

@mqtt_trigger("zigbee2mqtt/+/availability")
@task_unique("zigbee2mqtt_availability", kill_me=True)
def zigbee2mqtt_availability(topic,payload):
    offline = 0
    offline_devices = []
    device = re.search('zigbee2mqtt/(.*)/availability', topic).group(1)
    if(json.loads(payload)['state'] == "offline"):
        zigbee2mqtt_offline_devices[device] = 1
    else:
        zigbee2mqtt_offline_devices[device] = 0

    for dev in zigbee2mqtt_offline_devices:
        if zigbee2mqtt_offline_devices[dev] == 1:
            offline_devices.append(dev)
        offline += zigbee2mqtt_offline_devices[dev]
    sensor.offline_zigbee_devices = offline
    sensor.offline_zigbee_devices.devices = offline_devices
3 Likes

Works great. I had to replace

if(json.loads(payload)['state'] == "offline"):

by

if payload == “offline”:

1 Like

Interesting! I’m receiving availability as {'state':'offline'} json.
You might wanna drop import json from your script then.

Why did you choose to monitor an MQTT topic using pyscript? An alternative approach would be to use a MQTT sensor, which is naive to Home Assistant.

And then you could make a counter:

{{ integration_entities('mqtt') 
  | select('search', '_network_state') 
  | expand 
  | selectattr('state', 'eq', 'off')
  | list 
  | count }}

That would’ve created a separate entity for each device, I have 150+ devices and only need to know which devices are offline. One sensor does the job without cluttering my system.
I also don’t need to add new sensors whenever I add a new device, this way it’s completely dynamic.

sorry for the noob question, but how should I import it into homeassistant for it to work?

Noob questions are the reason for having this community.
You will need to install pyscript via HACS, then create a python script in <config>/pyscript directory and paste the script in it.
something like <config>/pyscript/z2m_offline_devices.py

This is really great!

It seems to be counting both groups and devices though. Is there a way to filter out groups and only monitor actual devices?

Unfortunately, you can’t distinguish groups from devices, however, you can skip counting particular devices/groups by name.
Something like:

device = re.search('zigbee2mqtt/(.*)/availability', topic).group(1)
if device == 'light_group' or device == 'Coordinator':
    return

Thank You.

My problem was, that a device called “901” was always shown as offline. I suppose this is a group in z2m called default_bind_group that has the id “901”. But even if i deleted the group in z2m it was still counted and shown as offline.

I was able to exclude the device like this:

for dev in zigbee2mqtt_offline_devices:
    if dev == "901":
        continue

You can monitor zgibbe devices using uptime kuma and sent notification on mob using telegram.

It’s probably better to use mqttexplorer or any similar tool to delete the availability topic.

Well, that was a much better solution. Thanks! :grinning:

Didn’t even consider that Uptime Kuma could monitor mqtt devices. I was only using it to monitor Docker containers.
Thank You!

I pasted it inside developer tools template and get:
mqtt:
binary_sensor:
Result type: string

This template does not listen for any events and will not update automatically.

I’m with 2025.12.2 core
Z2M 2.7.1

Of course the availability enabled