Files
hassio-addon-lifepo4wered/docs/superpowers/specs/2026-07-18-mqtt-monitor-design.md
vaku 25b3e2dcc4 Add MQTT monitor with Home Assistant autodiscovery
Poll lifepo4wered-cli every 30s (configurable), publish all registers as
one JSON state payload, and announce sensors/binary sensor via MQTT
discovery. run.sh pulls broker credentials from the Supervisor mqtt
service (Mosquitto addon) with manual overrides in addon options.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 01:15:03 +03:00

3.0 KiB

LiFePO4wered MQTT Monitor — Design

Date: 2026-07-18. Approved by vaku in conversation.

Goal

Publish LiFePO4wered/Pi+ UPS stats from the Home Assistant OS addon to MQTT, with Home Assistant autodiscovery, so the UPS shows up as a device with sensors.

Approach

A single Python script (lifepo4wered_monitor.py) inside the existing addon container. It shells out to lifepo4wered-cli get (already built into the image), parses the KEY = value output, and publishes to MQTT via paho-mqtt. Bindings via ctypes/PyPI were considered and rejected: the CLI is already present and one subprocess call reads everything at once.

Behavior

  • Poll every POLL_INTERVAL seconds (default 30).
  • One retained JSON state payload per cycle on lifepo4wered/state; all entities read it with value_template — one MQTT message per cycle.
  • Discovery configs (retained) on <DISCOVERY_PREFIX>/<component>/lifepo4wered/<key>/config, republished on every (re)connect. All entities belong to one HA device ("LiFePO4wered/Pi+", manufacturer Silicognition LLC).
  • Main sensors: VIN, VBAT, VOUT (mV → V, device_class voltage), IOUT (mA → A, device_class current).
  • Binary sensor "External power" (device_class power): VIN >= VIN_THRESHOLD → ON.
  • Diagnostic entities (entity_category: diagnostic): threshold/config registers (VBAT_MIN, VBAT_SHDN, VBAT_BOOT, VOUT_MAX, VIN_THRESHOLD scaled to V; timers, watchdog, AUTO_BOOT, LED_STATE, TOUCH_STATE, PI_RUNNING raw; RTC_TIME as timestamp).
  • Skipped: identity/calibration registers (I2C_REG_VER, I2C_ADDRESS, DCO_*, TOUCH_CAP_CYCLES/THRESHOLD/HYSTERESIS, *_OFFSET, CFG_WRITE, RTC_WAKE_TIME, WAKE_TIME).
  • Availability: MQTT LWT on lifepo4wered/availability (online/offline). CLI failure (I2C hiccup): log, publish offline, retry next cycle.
  • Config via env vars: MQTT_HOST, MQTT_PORT, MQTT_USER, MQTT_PASSWORD, POLL_INTERVAL, DISCOVERY_PREFIX, MQTT_TOPIC_PREFIX.
  • LIFEPO4WERED_FAKE=1 uses embedded sample output instead of the CLI, for testing off the Pi.

Addon integration

  • Dockerfile: add python3 + py3-paho-mqtt (Alpine packages), copy script and run.sh, CMD ["/run.sh"].
  • run.sh (bashio): pull MQTT host/port/user/password from Supervisor services API (works out of the box with the Mosquitto addon), allow overrides from addon options, start lifepo4wered-daemon -f in the background, run the monitor in the foreground.
  • config.json: add "services": ["mqtt:need"], addon options (poll_interval, optional MQTT overrides), bump version.

Error handling

  • paho built-in reconnect for broker drops; discovery republished on connect.
  • 10 s subprocess timeout on the CLI; malformed lines skipped with a warning.
  • Script compatible with paho-mqtt 1.x and 2.x callback APIs.

Testing

  • Unit tests (stdlib unittest) for output parsing and discovery payload generation, runnable on any machine without paho or a broker.
  • Fake mode for end-to-end runs against a real broker off the Pi.