[![GitHub Release][releases-shield]][releases] [![GitHub Activity][commits-shield]][commits] [![hacs][hacsbadge]][hacs]

Dashboard Overview

Intelligent battery health monitoring for Home Assistant — automatically discovers all your batteries, learns their behavior, and tells you which ones actually need attention.

Stop guessing based on percentages. BatteryBrain classifies each battery by how it behaves and applies smart thresholds — so a coin cell sitting at 1% for months doesn't trigger a false alarm, but a steadily draining sensor gets flagged before it dies.


Key Features

  • Zero-config auto-discovery — finds all battery entities automatically, including voltage-based and binary sensors
  • Behavioral classification — categorizes batteries into 7 archetypes based on their actual drain patterns, not just a percentage
  • Smart health status — each battery gets a Normal / Warning / Critical status using category-specific thresholds
  • Stale detection — flags batteries that stop reporting
  • Remaining lifetime estimation — for linear-drain batteries
  • History seeding — imports up to 1 year of existing data from the HA recorder on first setup, so classification starts immediately
  • Summary sensors — ready-made sensors for dashboards and automations

Installation

Open your Home Assistant instance and open a repository inside the Home Assistant Community Store.

  1. Open HACS in your Home Assistant instance
  2. Click the three-dot menu (top right) > Custom repositories
  3. Add this URL with category Integration:
    https://github.com/larsbaum/battery_brain
    
  4. Search for BatteryBrain and click Install
  5. Restart Home Assistant
  6. Go to Settings > Devices & Services > Add Integration and search for BatteryBrain

Manual Installation

  1. Download the latest release
  2. Copy the custom_components/battery_brain/ folder into your Home Assistant config/custom_components/ directory
  3. Restart Home Assistant
  4. Go to Settings > Devices & Services > Add Integration and search for BatteryBrain

Setup

After adding the integration, BatteryBrain starts working immediately:

  1. It discovers all battery entities in your system
  2. It imports historical data from the HA recorder (up to 1 year)
  3. After 7 days of data, it classifies each battery into an archetype
  4. It derives a health status for each battery based on its category

Note: If you have existing recorder history, most batteries will be classified right away. New batteries need about 7 days of data before classification.


Sensors

BatteryBrain creates four summary sensors:

Entity State Attributes
sensor.battery_brain_all_batteries Total number of monitored batteries Per-battery details (category, status, value, confidence, stale)
sensor.battery_brain_batteries_normal Count of healthy batteries List of battery names and details
sensor.battery_brain_batteries_warning Count of batteries needing attention List of battery names and details
sensor.battery_brain_batteries_critical Count of batteries needing replacement List of battery names and details

Each sensor carries detailed attributes for every battery in its group, including:

  • category — the detected archetype (e.g. linear, rechargeable)
  • status — current health status
  • last_value — last reported battery level
  • confidence — classification confidence (default / low / medium / high)
  • stale — whether the battery has stopped reporting
  • source_entity — the original entity ID

Use these attributes to build detailed dashboards or trigger automations.


Configuration Options

Access via Settings > Devices & Services > BatteryBrain > Configure:

Option Default Description
Scan for battery_level attributes Off Also monitor entities that report battery level as an attribute instead of a dedicated sensor
Treat binary low-battery as critical Off Escalate binary battery sensors directly to critical instead of warning
Exclude entities Select specific entities to exclude from monitoring
Developer Mode Off Enables debug logging and developer tools (see below)

Battery Archetypes

BatteryBrain classifies each battery into one of 7 archetypes based on its behavior pattern. Each archetype uses different thresholds for health status — because a rechargeable at 15% means something very different than a linear-drain sensor at 15%.

Archetype Typical Devices How It's Detected
Linear Zigbee door/window sensors, motion sensors Steady, roughly monotonic drain over time
Plateau-Cliff Coin cell devices (CR2032) Stays near 100% for a long time, then drops sharply
Rechargeable Wall panels, phones, tablets Regular charge/discharge cycles detected
Low-Stable Sensors reporting 1% for months Persistently low values with minimal variation
Voltage Sensors reporting in V/mV instead of % Detected by unit or value range (0.3 V – 20 V)
Binary Simple low/normal battery indicators Binary sensor with device_class: battery
Unknown New batteries, insufficient data Fallback until 7+ days of data are available

Dashboard Examples

Quick Overview Card

A simple entities card showing the battery counts at a glance. No extra frontend cards required.

Show YAML
type: entities
title: Battery Brain
entities:
  - entity: sensor.battery_brain_batteries_critical
    name: Critical
    icon: mdi:battery-alert
  - entity: sensor.battery_brain_batteries_warning
    name: Warning
    icon: mdi:battery-low
  - entity: sensor.battery_brain_batteries_normal
    name: Normal
    icon: mdi:battery
  - entity: sensor.battery_brain_all_batteries
    name: Total Monitored
    icon: mdi:battery-heart

Detailed Battery Dashboard

For a full battery overview grouped by health status, you can use auto-entities + mushroom cards. Each battery shows its current value, archetype, and confidence — color-coded by status.

Battery Dashboard Example

Show dashboard YAML

Three columns side by side — critical, warning, normal — each with mushroom cards showing value, archetype, and confidence. Tap any card to open the entity details.

type: horizontal-stack
cards:
  - type: vertical-stack
    cards:
      - type: custom:mushroom-title-card
        title: Critical
        subtitle: "{{ states('sensor.battery_brain_batteries_critical') }} batteries"
        title_tap_action:
          action: more-info
          entity: sensor.battery_brain_batteries_critical
        card_mod:
          style: |
            ha-card { --title-color: var(--error-color, #db4437); }
      - type: custom:auto-entities
        card:
          type: grid
          columns: 1
          square: false
        card_param: cards
        filter:
          template: >
            {%- set ent = 'sensor.battery_brain_batteries_critical' -%} {%- set
            ns = namespace(cards=[]) -%} {%- for n in states[ent].attributes -%}
              {%- set d = states[ent].attributes[n] -%}
              {%- if d is mapping and d.source_entity is defined -%}
                {%- set ns.cards = ns.cards + [{'type': 'tile', 'entity': d.source_entity, 'color': 'red'}] -%}
              {%- endif -%}
            {%- endfor -%} {{ ns.cards }}
        sort:
          method: friendly_name
          ignore_case: true
        show_empty: false
  - type: vertical-stack
    cards:
      - type: custom:mushroom-title-card
        title: Warning
        subtitle: "{{ states('sensor.battery_brain_batteries_warning') }} batteries"
        title_tap_action:
          action: more-info
          entity: sensor.battery_brain_batteries_warning
        card_mod:
          style: |
            ha-card { --title-color: var(--warning-color, #ffa726); }
      - type: custom:auto-entities
        card:
          type: grid
          columns: 1
          square: false
        card_param: cards
        filter:
          template: >
            {%- set ent = 'sensor.battery_brain_batteries_warning' -%} {%- set
            ns = namespace(cards=[]) -%} {%- for n in states[ent].attributes -%}
              {%- set d = states[ent].attributes[n] -%}
              {%- if d is mapping and d.source_entity is defined -%}
                {%- set ns.cards = ns.cards + [{'type': 'tile', 'entity': d.source_entity, 'color': 'orange'}] -%}
              {%- endif -%}
            {%- endfor -%} {{ ns.cards }}
        sort:
          method: friendly_name
          ignore_case: true
        show_empty: false
  - type: vertical-stack
    cards:
      - type: custom:mushroom-title-card
        title: Normal
        subtitle: "{{ states('sensor.battery_brain_batteries_normal') }} batteries"
        title_tap_action:
          action: more-info
          entity: sensor.battery_brain_batteries_normal
        card_mod:
          style: |
            ha-card { --title-color: var(--success-color, #43a047); }
      - type: custom:auto-entities
        card:
          type: grid
          columns: 1
          square: false
        card_param: cards
        filter:
          template: >
            {%- set ent = 'sensor.battery_brain_batteries_normal' -%} {%- set ns
            = namespace(cards=[]) -%} {%- for n in states[ent].attributes -%}
              {%- set d = states[ent].attributes[n] -%}
              {%- if d is mapping and d.source_entity is defined -%}
                {%- set ns.cards = ns.cards + [{'type': 'tile', 'entity': d.source_entity, 'color': 'green'}] -%}
              {%- endif -%}
            {%- endfor -%} {{ ns.cards }}
        sort:
          method: friendly_name
          ignore_case: true
        show_empty: false
grid_options:
  columns: 24
  rows: auto

Requires HACS frontend cards: auto-entities and mushroom.


Troubleshooting

Common Issues

Some batteries are not discovered

BatteryBrain discovers batteries in three ways:

  • Sensors with device_class: battery
  • Sensors with device_class: voltage in the 0.3 V – 20 V range
  • Binary sensors with device_class: battery

If a battery is missing:

  1. Check that the entity has the correct device_class set
  2. Enable "Scan for battery_level attributes" in the integration options — some integrations report battery level as an attribute rather than a dedicated sensor
  3. Make sure the entity is not in the excluded entities list
  4. Wait for the next scan cycle (every 5 minutes)
A battery is classified incorrectly

Classification improves over time as more data becomes available. Confidence levels:

  • default — less than 7 days of data, using fallback thresholds
  • low — 7–14 days
  • medium — 14–30 days
  • high — 30+ days of data

If a battery is still misclassified after 30+ days, please report it as an issue (see Reporting Issues below).

A battery shows as "critical" but is still working fine

This can happen when:

  • The battery reports very low percentages but is still functional (common with some Zigbee devices). BatteryBrain should eventually classify this as low_stable and stop alerting.
  • The battery has stopped sending updates and is marked as stale. Check if the device is still online.

If the issue persists, please report it.

No batteries found after installation

BatteryBrain runs a second discovery pass after Home Assistant is fully started, because some integrations (Mobile App, Zigbee2MQTT, etc.) load after BatteryBrain. If batteries are still missing after a few minutes, try restarting Home Assistant once more.


Reporting Issues

If you encounter a problem, please open an issue on GitHub. To help us diagnose the problem, include:

  1. What battery is affected — the entity ID (e.g. sensor.kitchen_motion_battery) and what kind of device it is
  2. What you expected vs. what happened (e.g. "classified as rechargeable but it's a CR2032 coin cell")
  3. The log file — BatteryBrain writes a daily log file at:
    config/battery_brain/logs/YYYY-MM-DD_batterybrain_logging.jsonl
    
    Attach the log file from the day the issue occurred (or the last few days). The log contains classification events and state changes that are essential for debugging.
  4. A screenshot of the battery's history graph from Home Assistant (the entity's History tab) — this helps us understand the drain pattern

Privacy: The log files only contain battery entity IDs, values, and classification data. No personal information is logged.


Developer Mode

For advanced debugging, you can enable Developer Mode in the integration options. This provides:

  • Debug log file at config/battery_brain_debug.jsonl — verbose logging with full classification details
  • Test Mode switch — for development only, accelerates time by 200x (destroys real sensor data — do not use in production!)
  • Reclassify button — forces immediate reclassification of all batteries

How It Works (Technical Details)

Discovery

Every 5 minutes, BatteryBrain scans all entities for:

  1. sensor entities with device_class: battery
  2. sensor entities with device_class: voltage and values between 0.3 V – 20 V (filters out mains voltage sensors)
  3. binary_sensor entities with device_class: battery
  4. Optionally: any entity with a battery_level attribute
History & Storage
  • On first discovery, imports up to 365 days of history from the HA recorder (Long-Term Statistics first, raw states as fallback)
  • Stores the last 30 days of raw data points (hourly resolution)
  • Aggregates older data into daily summaries (up to 365 days)
  • All data is stored locally in .storage/battery_brain — independent of the HA recorder
Classification

Batteries are classified after 7+ days of data. The classification algorithm checks archetypes in this order (first match wins):

  1. Binary — is it a binary sensor?
  2. Voltage — does it report in volts?
  3. Rechargeable — are there gradual charge/discharge cycles?
  4. Low-Stable — is it stuck at a low value with minimal variation?
  5. Plateau-Cliff — does it stay near max and then drop sharply?
  6. Linear — is it steadily declining?
  7. Unknown — fallback

Reclassification runs automatically every hour.

Status Derivation

Each archetype has its own thresholds:

Archetype Warning Critical
Linear ≤ 20% ≤ 10%
Plateau-Cliff < 95% of plateau < 70% of plateau
Rechargeable ≤ 15% ≤ 5%
Low-Stable Deviation from stable floor Large deviation from floor
Voltage ≤ 25% of range ≤ 10% of range
Binary Low signal Low for 3+ days
Unknown ≤ 20% ≤ 10%

Requirements

  • Home Assistant 2024.6 or newer
  • HACS (for easy installation — manual install also works)
  • The Recorder integration must be enabled (it is by default)