Compare commits

4 Commits

Author SHA1 Message Date
vaku
29a7c2586e Ignore .venv
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 01:54:25 +03:00
vaku
ac8a4b88f0 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 <noreply@anthropic.com>
2026-07-19 01:51:50 +03:00
vaku
fac31b4d3d Keep UPS power on when the addon is stopped
The daemon treats SIGTERM as system shutdown and clears PI_RUNNING,
making the UPS cut power seconds after the addon stops. Trap the stop
signal and SIGKILL the daemon instead so the UPS is never notified.

When the daemon exits on its own because the UPS commanded a shutdown
(button, low battery, auto shutdown), its init-0 trigger is useless in
a container, so run.sh now performs a clean host shutdown through the
Supervisor (requires hassio admin role).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 01:43:26 +03:00
vaku
6fcef57e7a Remove committed __pycache__ files and add .gitignore
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 01:01:24 +03:00
10 changed files with 93 additions and 3 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
__pycache__/
*.pyc
.venv/

View File

@@ -30,6 +30,27 @@ LIFEPO4WERED_FAKE=1 MQTT_HOST=... python3 hassio-addon-lifepo4wered/lifepo4wered
`LIFEPO4WERED_FAKE=1` replaces the CLI with embedded sample data.
## Stopping the addon vs. shutting down
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
shutdown through the Supervisor, and the UPS cuts power once shutdown
completes.
## Setup notes

View File

@@ -1,7 +1,9 @@
{
"name": "LiFePO4wered Addon",
"version": "0.1.3",
"version": "0.1.5",
"init": false,
"hassio_api": true,
"hassio_role": "admin",
"slug": "lifepo4wered",
"description": "Add-on with service and MQTT monitor for LiFePO4wered/Pi+ UPS",
"url": "https://github.com/vakius/hassio-addon-lifepo4wered/tree/master/hassio-addon-lifepo4wered",
@@ -9,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?",

View File

@@ -44,4 +44,38 @@ setup_mqtt_env() {
) &
bashio::log.info "Starting lifepo4wered-daemon"
exec lifepo4wered-daemon -f
lifepo4wered-daemon -f &
DAEMON_PID=$!
# 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"
# The daemon exited on its own: either the UPS commanded a shutdown
# (button press, low battery, auto shutdown after power loss) or the
# daemon crashed. Its own shutdown trigger (init 0) is useless inside
# a container, so perform a clean host shutdown via the Supervisor.
if [ "$(lifepo4wered-cli get PI_RUNNING 2>/dev/null)" = "0" ]; then
bashio::log.warning "UPS commanded shutdown; shutting down the host"
bashio::host.shutdown
exit 0
fi
bashio::log.error "lifepo4wered-daemon exited unexpectedly"
exit 1

View File

@@ -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.