diff --git a/docs/superpowers/specs/2026-07-18-mqtt-monitor-design.md b/docs/superpowers/specs/2026-07-18-mqtt-monitor-design.md index 2856d3f..43e5330 100644 --- a/docs/superpowers/specs/2026-07-18-mqtt-monitor-design.md +++ b/docs/superpowers/specs/2026-07-18-mqtt-monitor-design.md @@ -45,10 +45,14 @@ present and one subprocess call reads everything at once. - 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. +- `run.sh` (bashio): `lifepo4wered-daemon -f` is the exec'd main process, + started immediately — it must contact the UPS within PI_BOOT_TO seconds of + power-on or the UPS cuts power, so nothing (Supervisor API calls included) + may delay it and monitor failures must never take it down. The monitor runs + in a background subshell that pulls MQTT host/port/user/password from the + Supervisor services API (works out of the box with the Mosquitto addon, + addon options can override) and restarts the monitor with 30 s backoff if + it exits. - `config.json`: add `"services": ["mqtt:need"]`, addon options (`poll_interval`, optional MQTT overrides), bump version. diff --git a/hassio-addon-lifepo4wered/run.sh b/hassio-addon-lifepo4wered/run.sh index 67f32e5..03577f8 100644 --- a/hassio-addon-lifepo4wered/run.sh +++ b/hassio-addon-lifepo4wered/run.sh @@ -1,33 +1,47 @@ #!/usr/bin/with-contenv bashio -export POLL_INTERVAL="$(bashio::config 'poll_interval')" +# The daemon must contact the UPS within PI_BOOT_TO seconds of power-on, +# otherwise the UPS assumes the boot failed and cuts power. It is therefore +# the main process, started before any MQTT/Supervisor API calls, and the +# monitor runs on the side where its failures can never take the daemon down. -# Manual MQTT settings from addon options win; otherwise use the broker -# provided by the Supervisor (e.g. the Mosquitto addon). -if bashio::config.has_value 'mqtt_host'; then - export MQTT_HOST="$(bashio::config 'mqtt_host')" - if bashio::config.has_value 'mqtt_port'; then - export MQTT_PORT="$(bashio::config 'mqtt_port')" +setup_mqtt_env() { + export POLL_INTERVAL="$(bashio::config 'poll_interval')" + + # Manual MQTT settings from addon options win; otherwise use the broker + # provided by the Supervisor (e.g. the Mosquitto addon). + if bashio::config.has_value 'mqtt_host'; then + export MQTT_HOST="$(bashio::config 'mqtt_host')" + if bashio::config.has_value 'mqtt_port'; then + export MQTT_PORT="$(bashio::config 'mqtt_port')" + fi + if bashio::config.has_value 'mqtt_user'; then + export MQTT_USER="$(bashio::config 'mqtt_user')" + fi + if bashio::config.has_value 'mqtt_password'; then + export MQTT_PASSWORD="$(bashio::config 'mqtt_password')" + fi + elif bashio::services.available "mqtt"; then + export MQTT_HOST="$(bashio::services mqtt 'host')" + export MQTT_PORT="$(bashio::services mqtt 'port')" + export MQTT_USER="$(bashio::services mqtt 'username')" + export MQTT_PASSWORD="$(bashio::services mqtt 'password')" + else + bashio::log.warning \ + "No MQTT broker configured and no mqtt service available;" \ + "trying localhost:1883" fi - if bashio::config.has_value 'mqtt_user'; then - export MQTT_USER="$(bashio::config 'mqtt_user')" - fi - if bashio::config.has_value 'mqtt_password'; then - export MQTT_PASSWORD="$(bashio::config 'mqtt_password')" - fi -elif bashio::services.available "mqtt"; then - export MQTT_HOST="$(bashio::services mqtt 'host')" - export MQTT_PORT="$(bashio::services mqtt 'port')" - export MQTT_USER="$(bashio::services mqtt 'username')" - export MQTT_PASSWORD="$(bashio::services mqtt 'password')" -else - bashio::log.warning \ - "No MQTT broker configured and no mqtt service available;" \ - "trying localhost:1883" -fi +} + +( + setup_mqtt_env + bashio::log.info "Starting MQTT monitor (poll interval: ${POLL_INTERVAL}s)" + while true; do + python3 /usr/bin/lifepo4wered_monitor.py || true + bashio::log.warning "MQTT monitor exited; restarting in 30s" + sleep 30 + done +) & bashio::log.info "Starting lifepo4wered-daemon" -lifepo4wered-daemon -f & - -bashio::log.info "Starting MQTT monitor (poll interval: ${POLL_INTERVAL}s)" -exec python3 /usr/bin/lifepo4wered_monitor.py +exec lifepo4wered-daemon -f