#!/usr/bin/env bash
# scripts/ups-monitor.sh
# Log apcaccess status to /var/log/ups.log and shut the host down
# cleanly if the battery drops below SHUTDOWN_PCT while on battery.
#
# Ran from cron every minute. apcupsd's own killpower handles the last
# mile; this is only a safety net for the case where apcupsd died.
set -euo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=/dev/null
. "${HERE}/lib/log.sh"
LOG="${UPS_LOG:-/var/log/ups.log}"
SHUTDOWN_PCT="${SHUTDOWN_PCT:-15}"
if ! command -v apcaccess >/dev/null 2>&1; then
exit 0
fi
status=$(apcaccess status 2>/dev/null || true)
if [[ -z "${status}" ]]; then
log_warn "apcaccess returned empty output"
exit 0
fi
state=$(awk -F: '/^STATUS/ {gsub(/^ +/,"",$2); print $2; exit}' <<<"${status}")
charge=$(awk -F: '/^BCHARGE/ {gsub(/[^0-9.]/,"",$2); print $2; exit}' <<<"${status}")
linev=$(awk -F: '/^LINEV/ {gsub(/[^0-9.]/,"",$2); print $2; exit}' <<<"${status}")
printf '%s state=%s charge=%s line=%s\n' \
"$(date -u +%FT%TZ)" "${state:-?}" "${charge:-?}" "${linev:-?}" >> "${LOG}"
if [[ "${state:-}" == *"ONBATT"* ]]; then
# awk comparison keeps this portable across weird decimal locales.
if [[ -n "${charge:-}" ]] && \
awk -v c="${charge}" -v t="${SHUTDOWN_PCT}" 'BEGIN{exit !(c+0 < t+0)}'; then
log_err "battery ${charge}% on battery, shutting down"
systemctl poweroff --no-wall
fi
fi