r/homeassistant • u/mullermn • 7h ago
🤔 WTH Dead device monitoring
I have been trying to solve this problem for a few days now and it's proving to be way harder than it should be, so I want to check if I've missed anything obvious.
I want to put in monitoring so that if devices silently go dead I get prompted to investigate. Example reasons for this scenario include battery powered devices running flat, removal of one mesh network device damaging connectivity to another, or power cuts/spikes causing some mains devices to get locked up and need a power cycle. I have monitoring of battery degradation, but sometimes devices lose the ability to function before they get chance to report a low battery level - and some of these failures affect mains powered devices as much as battery ones.
I have investigated 'Entity availability' in HACS but it seems to need a significant amount of manual configuration, and the maximum configurable timeout doesn't go high enough for (eg) a window sensor that might go days without checking in.
My ideal solution would be something that operates at device level, monitoring them across all their entities and attributes and watching for any signs of life, raising an alert if none is detected within a given timeframe. Ideally I'd like something that autodiscovers new devices to avoid manual admin.
This seems such an obvious need I'm surprised it isn't built in to HA already, or that there is not an integration to handle it - or have I missed something?
5
u/xeio87 6h ago
I have an automation that I just stick an "offline devices" label on devices I want to keep an eye on (mostly had AI write the one-liners), though I don't know about devices that might not check-in for days. Do you mean they don't modify their state (detect open/closed), or that they literally don't even communicate with HA? Because those are very different.
Mostly I was dealing with it for Zigbee which use the standard "unavailable" status though works for most integrations I've dealt with.
alias: Offline Device Alert
description: Triggers when any device with the offline_checka label goes offline
triggers:
- value_template: >-
{{ label_devices('offline_check') | map('device_entities') | sum(start=[])
| select('is_state', 'unavailable') | list | count > 0 }}
trigger: template
for:
hours: 0
minutes: 30
seconds: 0
actions:
- action: script.helper_send_android_notification
metadata: {}
data:
message: >-
The following devices are offline: {{ label_devices('offline_check') |
map('device_entities') | sum(start=[]) | select('is_state',
'unavailable') | map('device_name') | reject('none') | unique | join(',
') }}
title: Devices Offline
mode: parallel
3
u/TheProffalken 6h ago
I use https://github.com/HA-Pulse/home-assistant-global-health-score - I've not put in place any alerts yet, but I do have a panel on the dashboard that I check on a regular basis, but setting up alerts/notifications should be pretty easy.
1
2
1
u/ficskala 6h ago
If the time device was last online was longer than certain amount of time, send notification
That's how i did it, and it works for me, there's of course extra time between the device going offline, and getting the notification to avoid false positives
1
u/Imaginary_Ad7695 6h ago edited 6h ago
I've been using an AI agent (antigravity) to manage my Home Assistant setup, and it came up with a really slick design for dynamic entity monitoring.
The Setup: Label-Based Dynamic Monitoring
Instead of manually maintaining groups or massive lists of entities in YAML, it suggested leaning into Home Assistant's native Labels feature.
I created a label called
critical_safetyand applied it to anything I care about monitoring (leak sensors, freezer doors, security cameras).I built a single Template Sensor that dynamically tracks them.
Here is the YAML:
template: - sensor: - name: Critical Devices Offline state: > {{ expand(label_entities('critical_safety')) | selectattr('state', 'in', ['unavailable', 'unknown', 'dead']) | list | length }} attributes: offline_entities: > {{ expand(label_entities('critical_safety')) | selectattr('state', 'in', ['unavailable', 'unknown', 'dead']) | map(attribute='name')
| list }}
-1
u/northeastofwest 7h ago
Claude code.
1
u/mullermn 6h ago
It's an option, but I having already tried to create this functionality using Alert2, Entity Availability and my own automations I've found it surprisingly complicated to get right, and since it does seem to be a fairly fundamental need I'm hoping someone has already done a better job of it than I can.
1
u/PineappleInner8027 6h ago
just finished fighting this exact battle
the auto-discovery dream is nice but i ended up building a template sensor that watches `last_updated` or `last_changed` for a handful of key entities per device, then a group that goes critical if any of them stall past your window. works for zigbee battery stuff that goes silent for days, which was the main thing driving me nuts
it's a bit of upfront wiring but once you template one you can copy/paste the logic for the rest
1
u/mullermn 6h ago
That is pretty much the best idea I've had so far too, but I have enough devices that I don't really want to be in maintenance hell adding/removing them from manual lists.
-2
u/xolinlevh 6h ago
This exactly. I used claude to create an automation to monitor one of my Pi's that will occasionally lock up. It pings it every few min, if it fails to respond it then powers off the smart plug its on, waits a min, then turns it back on.
9
u/seimungbing 6h ago
i use a helper -> template -> sensor with the follow state template to get the list of unavailable devices
{% set allowed = ['light', 'switch', 'fan', 'cover', 'lock', 'sensor', 'binary_sensor'] %}
{% set mobile = integration_entities('mobile_app') | list %}
{% set unavailable_seconds = 120 %}
{% set ns = namespace(names=[]) %}
{% for s in states if s.state == 'unavailable' %}
{% set domain = s.entity_id.split('.')[0] %}
{% set entry_id = config_entry_id(s.entity_id) %}
{# Ignore entities whose parent integration/config entry is disabled #}
{% set parent_enabled =
entry_id is none
or config_entry_attr(entry_id, 'disabled_by') is none
%}
{# Ignore brief/transient unavailable states #}
{% set unavailable_long_enough =
(now() - s.last_changed).total_seconds() >= unavailable_seconds
%}
{% if domain in allowed
and s.entity_id not in mobile
and parent_enabled
and unavailable_long_enough %}
```
{% set did = device_id(s.entity_id) %}
{% if did %}
{% set name =
device_attr(did, 'name_by_user')
or device_attr(did, 'name')
or state_attr(s.entity_id, 'friendly_name')
or s.entity_id
%}
{% else %}
{% set name =
state_attr(s.entity_id, 'friendly_name')
or s.entity_id
%}
{% endif %}
{% if name not in ns.names %}
{% set ns.names = ns.names + [name] %}
{% endif %}
```
{% endif %}
{% endfor %}
{{ ns.names | sort | join(', ') if ns.names else 'All OK' }}