2026-04-14 02:35:21 -05:00
2026-04-14 02:35:21 -05:00

Battery Tracker

A self-hosted web app for tracking rechargeable batteries — where they are, what condition they're in, and which devices they're installed in.

Built with Flask + SQLAlchemy. Runs on a Raspberry Pi or any Linux box with a systemd user service.

Features

Batteries

  • Add batteries in bulk (auto-generated labels like "Eneloop 001", "Eneloop 002")
  • Track status: Available, Installed, Retired
  • Store metadata: size (AA/AAA/18650/…), chemistry (NiMH/Li-ion/…), capacity, tested capacity, charge cycles, purchase date, storage location, notes
  • Visual health indicator when tested capacity is recorded (good/warn/bad)
  • Battery percentage field — set manually or synced from Home Assistant; resets to 100% when a charge is logged
  • Retire and unretire batteries

Devices

  • Add devices with a name, battery slot count, type (Remote Control, Flashlight, Sensor, …), and notes
  • Install batteries into devices — by brand/quantity or by picking a specific battery
  • Bulk install multiple batteries at once from the dashboard
  • Mixed-brand warning when batteries from different brands share a device
  • Link a device to a Home Assistant battery sensor to automatically track charge level
  • Edit device details in-place

Dashboard

  • Overview stats (total / available / installed / retired) + Low Battery count when any battery is below 20%
  • Full battery table with client-side filtering by status, brand, size, storage location, and free-text search
  • Column picker (Chemistry, Capacity, Storage, Purchase Date, Cycles, Battery %) stored in localStorage
  • Quick-assign available batteries to a device without leaving the page
  • Bulk actions: Unassign, Retire, Delete, Set Field (storage location or brand), Install in Device

Home Assistant Integration (optional)

  • Link any device to a Home Assistant entity (e.g. sensor.tv_remote_battery)
  • A background poller fetches the current percentage on a configurable interval (default 5 min) and updates all installed batteries in that device
  • Low-battery warning badge (< 20%) on the dashboard, device detail, and battery detail pages
  • Fully optional — when HOMEASSISTANT_URL is not set the app works exactly as before

UI

  • Mobile-friendly: card-style table rows on small screens, full-width filter controls, stacked form buttons
  • Dark mode — follows the OS system preference automatically (prefers-color-scheme)
  • No JavaScript framework — vanilla JS only

Tech Stack

Layer Technology
Web framework Flask 3.x
ORM SQLAlchemy 2.x (raw session, no Flask-SQLAlchemy)
Database SQLite (dev) / MariaDB (prod)
WSGI server Waitress
Process manager systemd user service
Tests pytest (71 acceptance tests)

Setup

Prerequisites

  • Python 3.10+
  • python3-venv

Install

git clone <repo-url>
cd battery-tracker-app

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Run (development)

source .venv/bin/activate
flask run
# → http://127.0.0.1:5000

Run (production — systemd user service)

bash sbin/install-service.sh   # prompts for host/port + optional HA config, installs and enables the service
systemctl --user start battery-tracker
systemctl --user status battery-tracker
journalctl --user -u battery-tracker -f

Database

SQLite is used by default (batteries.db in the project root). To switch to MariaDB, set the environment variable before starting:

export DATABASE_URL="mysql+pymysql://user:pass@host/dbname"

See MIGRATION.md for migrating an existing SQLite database to MariaDB, and for the schema migration commands needed when upgrading an existing database.

Home Assistant integration

Set these environment variables before starting (or enter them when running install-service.sh):

export HOMEASSISTANT_URL="http://homeassistant.local:8123"
export HOMEASSISTANT_API_KEY="<long-lived access token>"
export HOMEASSISTANT_POLL_INTERVAL="300"   # seconds, default 300

Then link a device to its HA sensor entity ID on the device's edit page (e.g. sensor.tv_remote_battery). The app will poll HA every interval and update the battery percentage for all installed batteries in that device.

Seed data (optional)

source .venv/bin/activate
python seed.py

Running Tests

source .venv/bin/activate
pytest tests/ -v

Tests use a fresh temporary SQLite database per test and exercise the full HTTP stack.


Project Structure

app.py                  Flask app factory + all routes
models.py               SQLAlchemy models (Battery, Device)
config.py               Database URL + HA config
ha_client.py            Home Assistant REST API wrapper
ha_poller.py            Background thread — polls HA, updates battery_percentage
seed.py                 Optional seed data script
migrate_to_mariadb.py   SQLite → MariaDB migration script
MIGRATION.md            Schema migration instructions + MariaDB procedure
requirements.txt
sbin/
  install-service.sh    systemd user service installer (prompts for HA config)
templates/
  base.html             Layout, CSS variables, dark mode, nav
  dashboard.html        Battery list with filters, bulk actions, HA% column
  battery_add.html      Add batteries form
  battery_detail.html   Battery detail + edit (includes battery_percentage field)
  battery_delete.html   Delete confirmation
  assign.html           Assign battery to device
  device_list.html      Device list with type filter
  device_add.html       Add device form
  device_detail.html    Device detail + install + edit (includes ha_entity_id field)
tests/
  conftest.py           pytest fixtures
  test_acceptance.py    50 acceptance tests
  test_ha_integration.py  21 HA integration tests
S
Description
No description provided
Readme 4.1 MiB
Languages
Python 52.6%
HTML 46.3%
Shell 1%
JavaScript 0.1%