Skip to content

Monitor sensor health

Intermediate Home Assistant

An unavailable door contact can silently undermine an otherwise good automation. A low battery can produce the same result a few days later. This guide creates one quiet, daily health check for sensors you choose yourself. It sends a message only when the list contains a real problem.

Home Assistant distinguishes unknown, where the state is not yet known, from unavailable, where the entity is unavailable. These definitions come from the official sensor documentation. Both states deserve investigation, but neither one proves by itself that the hardware has failed.

Avoid scanning every entity in Home Assistant automatically. A system-wide search catches test entities, disabled devices, and cloud services that do not need a daily alert. Start with a short list:

  • contact, leak, and motion sensors used by important automations;
  • temperature or freezer sensors whose readings require action;
  • the numeric battery sensors belonging to those same devices.

Find the exact entity IDs under Settings → Tools → States. Battery sensors with device_class: battery normally use percentages. Some devices expose a binary low-battery sensor instead; this example deliberately handles numeric battery percentages only. Home Assistant’s battery tutorial explains the difference.

You can also open States directly. Older versions call that page Developer tools.

Confirm that a test message reaches your phone. The example requires an available notify entity, as described in the notification documentation. If you only have an older notify.mobile_app_... action, use that phone’s specific action instead of the final notify.send_message action in the example. The mobile notifications guide covers setup and testing of the newer recipients.

The example runs at 09:00. It includes an optional startup trigger, disabled by default. If you enable it, the action waits five minutes so integrations have time to start. Home Assistant documents both the normal time trigger and the special Home Assistant startup trigger.

  1. Create an empty automation

    Go to Settings → Automations & scenes → Create automation → Create new automation. Open the three-dot menu and select Edit in YAML.

  2. Paste the complete example below

    Replace the entity IDs in both lists. notify.my_phone is illustrative; select your own notify entity or notification group.

  3. Save it with a clear name

    Run the manual test below first. Enable the startup trigger only if you also want a check five minutes after a restart.

Automation editor – complete automation
alias: "Sensor health: daily check"
description: "Alerts for selected unavailable sensors and low batteries"
mode: single
triggers:
- trigger: time
at: "09:00:00"
id: daily
- trigger: homeassistant
event: start
id: startup
enabled: false
variables:
watched_entities:
- binary_sensor.front_door_contact
- binary_sensor.utility_room_leak
- sensor.freezer_temperature
battery_entities:
- sensor.front_door_battery
- sensor.utility_room_leak_battery
battery_limit: 20
actions:
- if:
- condition: trigger
id: startup
then:
- delay: "00:05:00"
- variables:
health_report: >-
{% set ns = namespace(lines=[]) %}
{% for entity_id in watched_entities + battery_entities %}
{% set value = states(entity_id) %}
{% set name = state_attr(entity_id, 'friendly_name') or entity_id %}
{% if value in ['unknown', 'unavailable'] %}
{% set ns.lines = ns.lines + [name ~ ': ' ~ value] %}
{% endif %}
{% endfor %}
{% for entity_id in battery_entities %}
{% set value = states(entity_id) %}
{% set name = state_attr(entity_id, 'friendly_name') or entity_id %}
{% if is_number(value) and value | float < battery_limit %}
{% set ns.lines = ns.lines + [name ~ ': ' ~ value ~ '%'] %}
{% endif %}
{% endfor %}
{{ ns.lines | join('\n') }}
- condition: template
value_template: "{{ health_report | trim != '' }}"
- action: notify.send_message
target:
entity_id: notify.my_phone
data:
title: "Sensors need attention"
message: "{{ health_report | trim }}"

If you maintain automations.yaml manually, the destination is its list of automations: add - before alias and indent the rest of the block by two spaces. Do not paste that file-style variant into the editor.

Why the battery check does not use float(0)

Section titled “Why the battery check does not use float(0)”

Every entity state is read as text. unknown | float(0) therefore becomes 0 and can cause a false empty-battery alert. The example first requires is_number(value) and only then compares the number with the threshold. This follows Home Assistant’s documentation for types and conversion and keeps unavailability separate from a low battery. A battery sensor with unknown or unavailable therefore appears with that state in the message, never as 0%.

A battery at exactly 20% does not trigger this example; the threshold means “below 20.” Adjust the number for the battery type and your experience. One daily check usually creates less noise than a message for every small change.

Battery-powered Zigbee, Z-Wave, and Matter sensors may sleep between reports to conserve energy. An old temperature value is therefore not automatically an outage. Check the device’s normal reporting pattern and its integration’s own diagnostics before declaring it dead.

last_changed is not a universal “last seen” measurement either. Home Assistant’s state object updates that field when the state itself changes, but not when only attributes change. A door contact that remains closed can therefore have a very old last_changed even if it has communicated. last_reported also depends on whether the integration writes unchanged reports. Do not apply an arbitrary 6-, 12-, or 24-hour threshold to every kind of sensor.

  1. Save the automation and select Run actions. If everything is healthy, the template condition stops execution without sending a message.
  2. Temporarily replace one watched_entities entry with a nonexistent test ID. Run it again and confirm that the message reports unknown.
  3. Temporarily raise battery_limit above a known numeric battery value. Run it again and verify the wording and recipient.
  4. Restore both edits. Inspect the latest run under the automation’s Traces.
  5. Test the real phone physically. A completed notify action does not prove that the phone displayed the message.

These steps exercise the template and notification on your own installation. The example on this page has only been checked statically; it has not been run against your Home Assistant instance.


Comments