From ac8a4b88f0d7e4de6dcd977bb39479fa3b1322e3 Mon Sep 17 00:00:00 2001 From: vaku Date: Sun, 19 Jul 2026 01:51:50 +0300 Subject: [PATCH] Make daemon stop behavior configurable via signal_ups_on_stop Off (default): SIGKILL the daemon on addon stop so the UPS keeps power on. On: SIGTERM it (native behavior) so it saves the RTC and tells the UPS to cut power. Add translations so the option is documented in the HA config UI, and document the difference in the README. Co-Authored-By: Claude Fable 5 --- README.md | 19 +++++++++---- hassio-addon-lifepo4wered/config.json | 6 ++-- hassio-addon-lifepo4wered/run.sh | 23 +++++++++++---- .../translations/en.yaml | 28 +++++++++++++++++++ 4 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 hassio-addon-lifepo4wered/translations/en.yaml diff --git a/README.md b/README.md index 836c92a..5185080 100644 --- a/README.md +++ b/README.md @@ -32,12 +32,19 @@ LIFEPO4WERED_FAKE=1 MQTT_HOST=... python3 hassio-addon-lifepo4wered/lifepo4wered ## Stopping the addon vs. shutting down -Stopping the addon does **not** power off the Pi: the daemon is killed -without notifying the UPS, so power stays on (`run.sh` traps the stop -signal — the daemon would otherwise report "system shutting down" and the -UPS would cut power seconds later). While the addon is stopped, UPS-side -features (button shutdown, low-battery clean shutdown, boot watchdog -handshake) are inactive until it starts again. +The `signal_ups_on_stop` option controls what happens to the daemon when +the addon is stopped: + +- **Off (default)** — the daemon is killed (SIGKILL) without notifying the + UPS, so power stays on. Addon stops, restarts and updates are safe. The + system clock is not saved to the UPS RTC on stop (it still is on + UPS-commanded shutdowns), and while the addon is stopped, UPS-side + features (button shutdown, low-battery clean shutdown) are inactive. +- **On** — the daemon is terminated gracefully (SIGTERM), the native + LiFePO4wered behavior: it saves the clock to the UPS RTC and reports + "system shutting down" (`PI_RUNNING = 0`), so the UPS **cuts power to + the Pi a few seconds after the addon stops**. Only use this if you stop + the addon exclusively as part of powering the system down. When the UPS itself commands a shutdown (button press, low battery, `AUTO_SHDN_TIME` after power loss), the addon performs a clean host diff --git a/hassio-addon-lifepo4wered/config.json b/hassio-addon-lifepo4wered/config.json index 8a1d259..9534d01 100644 --- a/hassio-addon-lifepo4wered/config.json +++ b/hassio-addon-lifepo4wered/config.json @@ -1,6 +1,6 @@ { "name": "LiFePO4wered Addon", - "version": "0.1.4", + "version": "0.1.5", "init": false, "hassio_api": true, "hassio_role": "admin", @@ -11,10 +11,12 @@ "boot": "auto", "services": ["mqtt:want"], "options": { - "poll_interval": 30 + "poll_interval": 30, + "signal_ups_on_stop": false }, "schema": { "poll_interval": "int(5,3600)", + "signal_ups_on_stop": "bool", "mqtt_host": "str?", "mqtt_port": "port?", "mqtt_user": "str?", diff --git a/hassio-addon-lifepo4wered/run.sh b/hassio-addon-lifepo4wered/run.sh index a826a45..572068b 100644 --- a/hassio-addon-lifepo4wered/run.sh +++ b/hassio-addon-lifepo4wered/run.sh @@ -47,12 +47,23 @@ bashio::log.info "Starting lifepo4wered-daemon" lifepo4wered-daemon -f & DAEMON_PID=$! -# Stopping the addon must not power off the Pi: the daemon interprets -# SIGTERM as "system is shutting down" and tells the UPS to cut power -# (PI_RUNNING=0). SIGKILL it so it cannot signal the UPS; it will pick -# up again when the addon restarts. -trap 'bashio::log.info "Addon stopping; daemon killed without signaling UPS"; \ - kill -9 "$DAEMON_PID" 2>/dev/null; exit 0' TERM INT +# The daemon interprets SIGTERM as "system is shutting down" and tells +# the UPS to cut power (PI_RUNNING=0). By default we SIGKILL it instead +# so stopping the addon leaves the Pi powered; signal_ups_on_stop=true +# restores the daemon's native behavior (UPS cuts power after the stop). +on_stop() { + if bashio::config.true 'signal_ups_on_stop'; then + bashio::log.warning \ + "Addon stopping; signaling UPS - power will be cut in seconds" + kill -TERM "$DAEMON_PID" 2>/dev/null + wait "$DAEMON_PID" + else + bashio::log.info "Addon stopping; daemon killed without signaling UPS" + kill -9 "$DAEMON_PID" 2>/dev/null + fi + exit 0 +} +trap on_stop TERM INT wait "$DAEMON_PID" diff --git a/hassio-addon-lifepo4wered/translations/en.yaml b/hassio-addon-lifepo4wered/translations/en.yaml new file mode 100644 index 0000000..6720a5e --- /dev/null +++ b/hassio-addon-lifepo4wered/translations/en.yaml @@ -0,0 +1,28 @@ +configuration: + poll_interval: + name: Poll interval + description: >- + How often (in seconds) UPS registers are read and published to MQTT. + signal_ups_on_stop: + name: Signal UPS on addon stop + description: >- + Off (default): stopping the addon kills the daemon silently and the + UPS keeps powering the Pi; use this so addon restarts and updates are + safe. On: stopping the addon terminates the daemon gracefully, which + saves the clock to the UPS RTC but tells the UPS the system is + shutting down — the UPS WILL CUT POWER to the Pi a few seconds after + the addon stops. + mqtt_host: + name: MQTT host + description: >- + Optional MQTT broker override. Leave empty to auto-detect the broker + provided by the Mosquitto addon. + mqtt_port: + name: MQTT port + description: Optional broker port override (default 1883). + mqtt_user: + name: MQTT username + description: Optional broker username override. + mqtt_password: + name: MQTT password + description: Optional broker password override.