top of page

Daily Low Battery Notification for All Devices

  • Writer: Andrea Leandri
    Andrea Leandri
  • 5 days ago
  • 4 min read

Skill level: Beginner to Intermediate | Time to complete: 15-20 minutes

What you'll build: A Home Assistant automation that runs every morning at 09:00 and sends a single push notification listing every device whose battery has dropped below 20% - across all integrations, automatically, with no device list to maintain.

The Problem It Solves

Smart home devices run on batteries. Zigbee door sensors, remote controls, smoke detectors, motion sensors - they all drain quietly until one day a device stops responding and you spend an hour troubleshooting before realising it was a dead battery all along.

This automation catches that before it happens. Every morning at 09:00, if anything is running low, you get a single time-sensitive notification listing every affected device with its current level. If everything is fine, nothing happens - no unnecessary noise. And because it scans all sensor entities dynamically, you never need to update a device list when you add new hardware.

What You'll Need

Just Home Assistant and the Companion App for push notifications. No integrations, no add-ons, no configuration.yaml changes required.

How the Template Works

The automation uses a Jinja2 template that scans all sensor entities in HA automatically - one of the most useful patterns in Home Assistant:

{% set threshold = 20 %}
{% set ns = namespace(lines=[]) %}
{% for state in states.sensor
   if state.state not in ['unavailable', 'unknown']
   and state.state | int(-1) >= 0
   and state.state | int(-1) < threshold
   and (
     state.attributes.device_class == 'battery'
     or 'battery' in state.name | lower
     or 'battery' in state.entity_id | lower
   ) %}
  {% set ns.lines = ns.lines + ['- ' ~ state.name ~ ' (' ~ state.state ~ '%)'] %}
{% endfor %}
{{ ns.lines | join('\n') }}

states.sensor iterates over every sensor entity in HA - the dynamic scan that makes the automation self-maintaining. state.state not in ['unavailable', 'unknown'] skips sensors that are offline. state.state | int(-1) >= 0 filters out non-numeric sensors. device_class == 'battery' is the clean way; the 'battery' in name/entity_id checks catch integrations that don't set device_class correctly. namespace(lines=[]) works around Jinja2's limitation of not allowing variable modification inside a for loop.

The result is a message like: Aqara Door Sensor Bedroom (14%) / IKEA Remote Control Living Room (8%) / Zigbee Motion Sensor Kitchen (19%)

The Automation

Settings -> Automations & Scenes -> Create Automation -> Edit in YAML:

alias: "Daily Battery Level Check"
description: >
  Runs every day at 09:00 and sends a notification listing all devices
  whose battery level has dropped below 20%.

triggers:
  - at: "09:00:00"
    trigger: time

conditions: []

actions:
  - variables:
      low_battery_message: |-
        {% set threshold = 20 %}
        {% set exclude = [
          'Example Sensor To Exclude',
          'Another Sensor To Exclude'
        ] %}
        {% set ns = namespace(lines=[]) %}
        {% for state in states.sensor
           if state.state not in ['unavailable', 'unknown']
           and state.state | int(-1) >= 0
           and state.state | int(-1) < threshold
           and state.name not in exclude
           and (
             state.attributes.device_class == 'battery'
             or 'battery' in state.name | lower
             or 'battery' in state.entity_id | lower
           ) %}
          {% set ns.lines = ns.lines + [
            '- ' ~ state.name ~ ' (' ~ state.state ~ '%)'
          ] %}
        {% endfor %}
        {{ ns.lines | join('\n') }}

  # Only send if there is actually something to report
  - condition: template
    value_template: "{{ low_battery_message | trim | length > 0 }}"

  - action: notify.mobile_app_iphone_XXXXXX   # replace with your device
    data:
      title: "Low Battery Warning"
      message: "{{ low_battery_message | trim }}"
      data:
        push:
          interruption-level: time-sensitive
          sound: default

mode: single

Key Details

The mobile device that notifies

Ensure that the notify.mobile_app_iphone_XXXXXX is replaced with your actual device where the companion app is installed.

The exclude list

Some sensors contain "battery" in their name but represent something different - a car starter battery state, a battery temperature reading, or a UPS runtime. Add their exact friendly names to the exclude list. Find the exact name in Developer Tools -> States.

The condition

The condition: template step with low_battery_message | trim | length > 0 is the silence gate. If all batteries are above 20%, the message is empty, the condition evaluates to false, and the automation stops without sending anything. This is what keeps it quiet on good days.

Time-sensitive notification

Interruption-level: time-sensitive means the notification breaks through iOS Focus modes including Do Not Disturb and Sleep - appropriate for a battery warning you might genuinely need to see. Change to active if you prefer it to respect Focus modes.

Preview the Template Without Waiting

To see every battery sensor HA can find right now, go to Developer Tools -> Template and paste the template with threshold = 100. This shows all battery sensors regardless of level - useful for auditing what will appear and what to add to the exclude list.

Customise It

Change threshold from 20 to any value you prefer - 15 for fewer alerts, 30 to get more warning time. Change the trigger time from 09:00 to whenever suits you. Add multiple notify actions for a shared household. Add a WhatsApp notification using the WhatsApp integration from the guide on this site.

Troubleshooting

  • No notification with low batteries: Test with threshold 100 in Developer Tools - Template. Check Traces to see if condition evaluated to false.

  • False positives in the list: Add those sensor names exactly to the exclude list.

  • Some battery sensors not appearing: They may not have device_class: battery set and lack battery in their name or entity ID. Check in Developer Tools -> States.

  • Notification doesn't break through Do Not Disturb: Confirm interruption-level: time-sensitive is set. Check iOS Settings -> Notifications -> Home Assistant.


Guide written by a Home Assistant enthusiast in Utrecht. Nothing ends a perfectly working automation like a dead battery you didn't know about.

Comments

Rated 0 out of 5 stars.
No ratings yet

Add a rating
bottom of page