Battery devices die quietly. A contact that last reported 47% three weeks ago is already empty; a coin cell that chatters unavailable is worse than one that still has a number. This workflow walks every battery sensor Home Assistant knows, keeps the ones at or below your cutoff (default 15%) or stuck unavailable/unknown, and sends one grouped notification — not a page each time a sleepy node wakes.
Entity ids stay in blueprint inputs. Do not publish a live inventory of which rooms still have coin cells.
If you are building the contact yourself, the battery reed door sensor pack already exposes a voltage entity this scan can pick up. Complements offline devices report for nodes that never came back after an outage.
What problem it solves
You want a single “replace these cells” list on a weekday morning, plus a way to ignore the phone at night, without writing one automation per sensor and without paging on every 1% twitch.
How it works
- Discover — the blueprint selects entities with device class
battery(percent sensors and “battery low” binaries). You do not maintain a hand list unless you want a custom group with a stricter cutoff (shade motors that are dead at 50%, for example). - Threshold — any percent at or below the warning level (pack default 15%) is a hit.
unavailableandunknownare hits too; a node that stopped reporting is more urgent than 14%. - Excludes — skip hidden entities, skip specific sensors, skip labels you use for “ignore this cell.” UPS units that sit at 80% by design belong here.
- Quiet hours — if a manual button run lands inside the quiet window, skip the phone push (the persistent UI card can still update). The weekly roll-up is scheduled outside that window, typically a weekday morning.
- Weekly roll-up — one notify with friendly names (and optional area / percent). Actionable Companion buttons can drop the list onto a to-do. A later run with the same
notification_idreplaces the persistent card.
A 1% bounce around the cutoff will not spam you: the scan is periodic, not a numeric_state trigger on every sensor.
Hardware notes
- No extra hardware. This watches battery entities you already have. Zigbee, Z-Wave, ESPHome ADC, and BLE all look the same once they are a
%sensor or a low-battery binary. - Notify. Companion (
notify.mobile_app_your_phone) for the phone; persistent notification for the desktop. Pushover works if you point the notify input at it. - Sleepy ESP32 reeds. A deep-sleep contact that only publishes voltage on wakeup will look unknown between boots. Either exclude it and trust the on-device low-battery binary from the battery reed pack, or give it a timed wakeup long enough that the weekly scan usually catches a fresh reading.
Snippet
The pack ships a blueprint. Inputs replace real entity ids:
trigger:
- platform: time
at: !input weekly_time
id: rollup
- platform: state
entity_id: !input check_button
id: manual
condition:
- condition: or
conditions:
- condition: trigger
id: rollup
- condition: not
conditions:
- condition: time
after: !input quiet_start
before: !input quiet_end
action:
- variables:
low: >
{{ states.sensor
| selectattr('attributes.device_class', 'eq', 'battery')
| selectattr('state', 'lt', threshold)
| map(attribute='name') | list }}
- service: notify.notify
data:
title: "Low batteries"
message: "{{ low | join(', ') }}"
# excludes + unavailable + persistent card: full blueprint in the pack
Setup outline
- In Developer Tools, filter
device_class: batteryand glance at real percentages so 15% is sane for your mix (CR2032 vs LiPo vs NiMH). - Create the optional
input_buttonand a to-do list if you want the action button. - Import the blueprint. Set threshold, weekly time, quiet hours, notify service, and the first excludes (UPS, always-charging tablets).
- Run from the button at a time outside quiet hours. Confirm: one grouped push, persistent card, quiet-hours button run stays silent on the phone, excluded entities stay off the list.
Troubleshooting
- Everything is “low.” The entity is voltage (2.8) not percent (28), or the integration reports 0–1. Exclude it or wrap a template that scales to 0–100 before the scan.
- A binary “battery low” never appears. Some integrations use
onfor low, others invert. The pack treatsonas low; invert in a template helper if your device is backwards. - Night pages. The weekly time sits inside quiet hours, or you used a naive
afterthat does not wrap midnight. Move the roll-up to morning; keep the pack’s wrapping time condition. - Same device listed twice. Percent and a low-battery binary. Exclude one, or you will replace two cells that are the same coin.
Credits
Based on Blacky’s community blueprint Low Battery Notifications & Actions. This write-up is an original overview of the house-wide threshold-plus-roll-up pattern.