126 lines
6.3 KiB
Bash
Executable File
126 lines
6.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# LVX6048 → Home Assistant monitoring — reproducible installer.
|
|
#
|
|
# Installs powermon + our patches, drops in udev rule / systemd units / resolver
|
|
# script / powermon configs, and starts the services. Idempotent: safe to re-run.
|
|
#
|
|
# Assumptions:
|
|
# - Debian-family Linux (Raspberry Pi OS, Ubuntu) with systemd
|
|
# - `uv` is installed and on $PATH (https://docs.astral.sh/uv/)
|
|
# - User has sudo
|
|
# - MQTT broker reachable (edit config/powermon/*.yaml first if the broker IP /
|
|
# credentials aren't yet in place)
|
|
#
|
|
# After install, finish by editing:
|
|
# ~/.config/powermon/powermon{,2}.yaml — MQTT broker + credentials
|
|
# /usr/local/sbin/lvx-resolve-links — SERIAL_UNIT_1 / SERIAL_UNIT_2
|
|
# lvx-flash/flash.py — SERIAL_UNIT_1 / SERIAL_UNIT_2
|
|
# then:
|
|
# sudo systemctl restart lvx-resolve-links powermon.service powermon2.service
|
|
|
|
set -euo pipefail
|
|
|
|
PINNED_POWERMON="1.0.18" # version we developed/tested patches against
|
|
BASE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
msg() { printf '\n\033[1;36m== %s ==\033[0m\n' "$*"; }
|
|
|
|
# --- 1. powermon -----------------------------------------------------------
|
|
msg "Installing powermon ${PINNED_POWERMON} via uv"
|
|
command -v uv >/dev/null || { echo "uv not found — install from https://docs.astral.sh/uv/"; exit 1; }
|
|
uv tool install --with bleak "powermon==${PINNED_POWERMON}"
|
|
|
|
POWERMON_VENV="${HOME}/.local/share/uv/tools/powermon"
|
|
POWERMON_SITE="$(ls -d "${POWERMON_VENV}"/lib/python*/site-packages/powermon)"
|
|
POWERMON_PY="${POWERMON_VENV}/bin/python"
|
|
[ -d "$POWERMON_SITE" ] || { echo "could not locate powermon site-packages under ${POWERMON_VENV}"; exit 1; }
|
|
|
|
# --- 2. powermon patches ---------------------------------------------------
|
|
msg "Applying powermon patches into ${POWERMON_SITE}"
|
|
install -m 644 "${BASE}/powermon-patches/pi18.py" "${POWERMON_SITE}/protocols/pi18.py"
|
|
install -m 644 "${BASE}/powermon-patches/port_config_model.py" "${POWERMON_SITE}/configmodel/port_config_model.py"
|
|
install -m 644 "${BASE}/powermon-patches/ports_init.py" "${POWERMON_SITE}/ports/__init__.py"
|
|
install -m 644 "${BASE}/powermon-patches/usbport.py" "${POWERMON_SITE}/ports/usbport.py"
|
|
install -m 644 "${BASE}/powermon-patches/mqttbroker.py" "${POWERMON_SITE}/libs/mqttbroker.py"
|
|
install -m 644 "${BASE}/powermon-patches/hass.py" "${POWERMON_SITE}/outputformats/hass.py"
|
|
|
|
# --- 3. udev (LVX6048 hidraw → dialout perms) ------------------------------
|
|
msg "Installing udev rule"
|
|
sudo install -m 644 "${BASE}/etc/udev/rules.d/99-lvx6048.rules" /etc/udev/rules.d/99-lvx6048.rules
|
|
sudo udevadm control --reload-rules
|
|
sudo udevadm trigger --subsystem-match=hidraw
|
|
|
|
# --- 4. resolver script (serial → /dev/lvx6048-N symlinks) -----------------
|
|
msg "Installing /usr/local/sbin/lvx-resolve-links (shebang → ${POWERMON_PY})"
|
|
TMP_RESOLVER="$(mktemp)"
|
|
trap 'rm -f "$TMP_RESOLVER"' EXIT
|
|
awk -v py="${POWERMON_PY}" 'NR==1 { print "#!" py; next } { print }' \
|
|
"${BASE}/bin/lvx-resolve-links" > "$TMP_RESOLVER"
|
|
sudo install -m 755 "$TMP_RESOLVER" /usr/local/sbin/lvx-resolve-links
|
|
|
|
# --- 5. systemd units + drop-ins -------------------------------------------
|
|
msg "Installing systemd units"
|
|
sudo install -m 644 "${BASE}/etc/systemd/system/lvx-resolve-links.service" /etc/systemd/system/
|
|
sudo install -m 644 "${BASE}/etc/systemd/system/lvx-control.service" /etc/systemd/system/
|
|
sudo install -m 644 "${BASE}/etc/systemd/system/powermon.service" /etc/systemd/system/
|
|
sudo install -m 644 "${BASE}/etc/systemd/system/powermon2.service" /etc/systemd/system/
|
|
sudo mkdir -p /etc/systemd/system/powermon.service.d /etc/systemd/system/powermon2.service.d
|
|
sudo install -m 644 "${BASE}/etc/systemd/system/powermon.service.d/10-resolver.conf" \
|
|
/etc/systemd/system/powermon.service.d/10-resolver.conf
|
|
sudo install -m 644 "${BASE}/etc/systemd/system/powermon2.service.d/10-resolver.conf" \
|
|
/etc/systemd/system/powermon2.service.d/10-resolver.conf
|
|
sudo systemctl daemon-reload
|
|
|
|
# --- 5b. lvx-control script (HA → powermon adhoc bridge) -------------------
|
|
msg "Installing /usr/local/bin/lvx-control (shebang → ${POWERMON_PY})"
|
|
TMP_CONTROL="$(mktemp)"
|
|
trap 'rm -f "$TMP_RESOLVER" "$TMP_CONTROL"' EXIT
|
|
awk -v py="${POWERMON_PY}" 'NR==1 { print "#!" py; next } { print }' \
|
|
"${BASE}/lvx-control/lvx-control" > "$TMP_CONTROL"
|
|
sudo install -m 755 "$TMP_CONTROL" /usr/local/bin/lvx-control
|
|
|
|
# --- 6. user configs (only if not already deployed; don't clobber creds) ---
|
|
msg "Installing powermon configs (skipping existing files — edit creds manually if new)"
|
|
mkdir -p "${HOME}/.config/powermon"
|
|
for f in powermon.yaml powermon2.yaml; do
|
|
dest="${HOME}/.config/powermon/${f}"
|
|
if [ -e "$dest" ]; then
|
|
echo " $dest already exists — not overwriting"
|
|
else
|
|
install -m 600 "${BASE}/config/powermon/${f}" "$dest"
|
|
echo " wrote $dest (mode 600) — edit MQTT credentials before enabling services"
|
|
fi
|
|
done
|
|
|
|
# --- 7. enable services ----------------------------------------------------
|
|
msg "Enabling services"
|
|
sudo systemctl enable --now lvx-resolve-links.service
|
|
# Only auto-start powermon services if credentials look real (no placeholder present)
|
|
if grep -q '<MQTT_PASSWORD>' "${HOME}/.config/powermon/powermon.yaml" 2>/dev/null; then
|
|
cat <<EOF
|
|
|
|
Credentials in ~/.config/powermon/powermon.yaml still contain a placeholder.
|
|
Edit that file + powermon2.yaml, then:
|
|
|
|
sudo systemctl enable --now powermon.service powermon2.service
|
|
journalctl -u powermon.service -u powermon2.service -f
|
|
|
|
EOF
|
|
else
|
|
sudo systemctl enable --now powermon.service powermon2.service
|
|
sleep 3
|
|
systemctl --no-pager status powermon.service powermon2.service | head -30
|
|
fi
|
|
|
|
# lvx-control reads broker creds from ~/.config/powermon/powermon.yaml, so it
|
|
# only needs to start once that file has real credentials.
|
|
if ! grep -q '<MQTT_PASSWORD>' "${HOME}/.config/powermon/powermon.yaml" 2>/dev/null; then
|
|
sudo systemctl enable --now lvx-control.service
|
|
fi
|
|
|
|
msg "Done"
|
|
echo "Next steps (if any of these don't match your hardware, edit and restart):"
|
|
echo " - /usr/local/sbin/lvx-resolve-links : SERIAL_UNIT_1 / SERIAL_UNIT_2"
|
|
echo " - ${BASE}/lvx-flash/flash.py : SERIAL_UNIT_1 / SERIAL_UNIT_2"
|
|
echo " - to re-probe after a cable move : sudo systemctl restart lvx-resolve-links.service powermon.service powermon2.service"
|