Managing a smart home can sometimes feel like a game of whack-a-mole, especially when sensors go offline. With devices scattered across different platforms and protocols, tracking down which sensors are down can turn into a frustrating scavenger hunt.
This prompted my to build a Home Assistant template sensor that consolidates this critical information into a single, streamlined output. This sensor provides a real-time list of all offline sensors, giving you a centralized view of your smart home’s health. By adding it to your smart home health dashboard, you can easily monitor and address issues from one “single pane of glass,” making maintenance simpler and more efficient.
When everything is up, the sensor reports like this:
{% set result = namespace(sensors=[]) %}
{# Match Zigbee devices (via Zigbee2MQTT) #}
{% for state in states.sensor | rejectattr('attributes.device_class', 'undefined') | selectattr('attributes.device_class', '==', 'timestamp') %}
{% if 'last_seen' in state.entity_id %}
{% set state_value = states(state.entity_id) %}
{% if state_value != 'unavailable' and state_value != 'unknown' and ((as_timestamp(now()) - as_timestamp(state_value)) > (36 * 60 * 60)) %}
{% set result.sensors = result.sensors + [state.name | regex_replace(find=' Last seen', replace='') ~ ' (' ~ relative_time(strptime(state_value, '%Y-%m-%dT%H:%M:%S%z')) ~ ')'] %}
{% endif %}
{% endif %}
{% endfor %}
{# Match ZWaveJS devices #}
{% for state in states.sensor | selectattr('entity_id', 'search', '_node_status$') %}
{% if states(state.entity_id) == 'dead' %}
{% set result.sensors = result.sensors + [state.name | regex_replace(find=' Node status', replace='') ~ ' (unavailable)'] %}
{% endif %}
{% endfor %}
{# Match Tasmota devices #}
{% for state in states.sensor | selectattr('entity_id', 'search', '_mqtt_connect_count$') %}
{% if states(state.entity_id) == 'unavailable' %}
{% set result.sensors = result.sensors + [state.name | regex_replace(find=' MQTT Connect Count', replace='') ~ ' (unavailable)'] %}
{% endif %}
{% endfor %}
{# Match BLE GOvee Temperature / Humidity devices #}
{% for state in states.sensor | selectattr('entity_id', 'search', '_h5075_temperature$') %}
{% if states(state.entity_id) == 'unavailable' %}
{% set result.sensors = result.sensors + [state.name | regex_replace(find=' Temperature', replace='') ~ ' (unavailable)'] %}
{% endif %}
{% endfor %}
{# Match arbitrary list of sensors not captured above #}
{% set sensor_list = [
{'entity_id': 'sensor.bed_load_cell', 'name': 'Bed'},
{'entity_id': 'sensor.airgradient_temperature', 'name': 'Airgradient'},
{'entity_id': 'binary_sensor.his_office_mmwave_occupancy_0', 'name': 'His office mmWave'},
{'entity_id': 'assist_satellite.ha_voice_0_assist_satellite', 'name': 'HA Voice'},
{'entity_id': 'binary_sensor.gl_s10_bt_proxy_cfdef4_reset_button', 'name': 'Pantry BLE Proxy'},
{'entity_id': 'binary_sensor.gl_s10_bt_proxy_29b254_reset_button', 'name': 'Laundry BLE Proxy'},
{'entity_id': 'button.esp32_ble_proxy_on_azure_iot_dev_kit_safe_mode_boot', 'name': 'Garage BLE Proxy'},
{'entity_id': 'button.emporia_vue_2_two_beeps', 'name': 'Emporia Vue 2'},
{'entity_id': 'sensor.sunroom_floor_right_led_count', 'name': 'Sunroom floor right'},
{'entity_id': 'sensor.sunroom_floor_left_led_count', 'name': 'Sunroom floor left'},
{'entity_id': 'sensor.3d_printer_led_led_count', 'name': '3D printer LED'},
] %}
{% for sensor in sensor_list %}
{% if states(sensor.entity_id) == 'unavailable' %}
{% set result.sensors = result.sensors + [sensor.name ~ ' (unavailable)'] %}
{% endif %}
{% endfor %}
{# Output the combined result or fallback message if empty #}
{{ result.sensors | join('\n') | truncate(254, True) if result.sensors else 'All sensors are up!' }}
sensor.overall_sensor_health