diff --git a/bluewalker-vfi-icr/README.md b/bluewalker-vfi-icr/README.md new file mode 100644 index 0000000..5b5c512 --- /dev/null +++ b/bluewalker-vfi-icr/README.md @@ -0,0 +1,63 @@ +# NUT config: PowerWalker VFI ICR IoT + +Network UPS Tools setup for a PowerWalker VFI ICR IoT UPS. + +- **Master**: one host connected to the UPS via **USB** (`nutdrv_qx`), runs + `upsd` + `upsmon`, and serves status to the network on port `3493/tcp`. +- **Clients**: any other Linux hosts run `upsmon` as network slaves and shut + down gracefully when the master signals a power failure (FSD). + +This avoids the undocumented Modbus TCP register map entirely. If you ever +want a pure-network (no USB) setup, you would need the Modbus register map +from PowerWalker support plus the `nutdrv_modbus` driver -- not used here. + +## Layout + +``` +master/etc/nut/ config for the USB-connected host +client/etc/nut/ config for each network slave +install-master.sh deploy + permissions on the master +install-client.sh deploy on a client: sudo ./install-client.sh +``` + +## Quick start + +### Master (USB host) + +``` +sudo ./install-master.sh +# edit /etc/nut/upsd.users -> set monmaster / monslave passwords +# edit /etc/nut/upsmon.conf -> set the same monmaster password +sudo nutdrv_qx -a test -DD -x port=auto # confirm the driver reads values +sudo systemctl enable --now nut-server nut-monitor +upsc ups@localhost +``` + +If the test shows no/garbled values, retry with: + +``` +sudo nutdrv_qx -a test -DD -x port=auto -x protocol=voltronic -x novendor +``` + +and uncomment the matching lines in `master/etc/nut/ups.conf`. + +### Each client + +``` +sudo ./install-client.sh +# edit /etc/nut/upsmon.conf -> set the monslave password +sudo systemctl enable --now nut-monitor +upsc ups@ +``` + +## Notes + +- Open `3493/tcp` on the master firewall for your client subnets. +- `runtimecal` in `ups.conf`: these UPS models may not report runtime; + NUT then estimates it. Format: `sec_at_full,full_pct,sec_at_half,half_pct`. + Adjust to your battery / EBM configuration. +- `upsd.users` holds plaintext credentials and is gitignored. Keep the real + file off the repo; distribute it out of band (or via your secrets tooling). +- To also cut UPS output power after the master shuts down, look into + `upsdrvctl shutdown` / the `POWERDOWNFLAG` mechanism -- intentionally left + out here to keep the first deployment simple. diff --git a/bluewalker-vfi-icr/install-client.sh b/bluewalker-vfi-icr/install-client.sh new file mode 100644 index 0000000..0a0fe26 --- /dev/null +++ b/bluewalker-vfi-icr/install-client.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# install-client.sh -- deploy NUT network-slave config +# Usage: sudo ./install-client.sh +# ASCII only. + +set -euo pipefail + +SRC="$(cd "$(dirname "$0")" && pwd)/client/etc/nut" +DST="/etc/nut" + +if [ "$(id -u)" -ne 0 ]; then + echo "ERROR: run as root (sudo)." >&2 + exit 1 +fi + +MASTER_IP="${1:-}" +if [ -z "$MASTER_IP" ]; then + echo "Usage: sudo $0 " >&2 + exit 1 +fi + +echo "== Installing NUT (if missing) ==" +if command -v apt-get >/dev/null 2>&1; then + apt-get update && apt-get install -y nut +elif command -v dnf >/dev/null 2>&1; then + dnf install -y nut +else + echo "WARN: unknown package manager, install 'nut' manually." >&2 +fi + +echo "== Copying client config to ${DST} ==" +install -d "$DST" +cp -v "$SRC/nut.conf" "$DST/nut.conf" +sed "s/MASTER_IP/${MASTER_IP}/" "$SRC/upsmon.conf" > "$DST/upsmon.conf" + +chown root:nut "$DST/upsmon.conf" 2>/dev/null || true +chmod 640 "$DST/upsmon.conf" + +echo +echo "NEXT STEPS (manual):" +echo " 1. Edit ${DST}/upsmon.conf -- replace CHANGE_ME_SLAVE with the master's monslave password." +echo " 2. Enable the monitor service:" +echo " systemctl enable --now nut-monitor" +echo " 3. Verify connectivity to the master:" +echo " upsc ups@${MASTER_IP}" diff --git a/bluewalker-vfi-icr/install-master.sh b/bluewalker-vfi-icr/install-master.sh new file mode 100644 index 0000000..147f08d --- /dev/null +++ b/bluewalker-vfi-icr/install-master.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# install-master.sh -- deploy NUT master config for PowerWalker VFI ICR IoT +# Run as root on the USB-connected host. ASCII only. + +set -euo pipefail + +SRC="$(cd "$(dirname "$0")" && pwd)/master/etc/nut" +DST="/etc/nut" + +if [ "$(id -u)" -ne 0 ]; then + echo "ERROR: run as root (sudo)." >&2 + exit 1 +fi + +echo "== Installing NUT (if missing) ==" +if command -v apt-get >/dev/null 2>&1; then + apt-get update && apt-get install -y nut +elif command -v dnf >/dev/null 2>&1; then + dnf install -y nut +else + echo "WARN: unknown package manager, install 'nut' manually." >&2 +fi + +echo "== Copying config files to ${DST} ==" +install -d "$DST" +cp -v "$SRC/ups.conf" "$DST/ups.conf" +cp -v "$SRC/nut.conf" "$DST/nut.conf" +cp -v "$SRC/upsd.conf" "$DST/upsd.conf" +cp -v "$SRC/upsmon.conf" "$DST/upsmon.conf" + +if [ ! -f "$DST/upsd.users" ]; then + cp -v "$SRC/upsd.users.example" "$DST/upsd.users" + echo "NOTE: created upsd.users from example -- edit the passwords now." +else + echo "NOTE: upsd.users already exists, left untouched." +fi + +echo "== Setting ownership and permissions ==" +chown root:nut "$DST"/*.conf "$DST/upsd.users" 2>/dev/null || true +chmod 640 "$DST/upsd.users" "$DST/upsmon.conf" + +echo +echo "NEXT STEPS (manual):" +echo " 1. Edit ${DST}/upsd.users and ${DST}/upsmon.conf -- replace CHANGE_ME_* passwords." +echo " 2. Plug in the UPS via USB and test the driver:" +echo " nutdrv_qx -a test -DD -x port=auto" +echo " (add -x protocol=voltronic -x novendor if values are missing)" +echo " 3. Enable services:" +echo " systemctl enable --now nut-server nut-monitor" +echo " 4. Verify:" +echo " upsc ups@localhost" +echo " 5. Open 3493/tcp in the firewall for your client subnets." diff --git a/bluewalker-vfi-icr/nut-powerwalker-vfi-icr-iot.tar.gz b/bluewalker-vfi-icr/nut-powerwalker-vfi-icr-iot.tar.gz new file mode 100644 index 0000000..1ee879d Binary files /dev/null and b/bluewalker-vfi-icr/nut-powerwalker-vfi-icr-iot.tar.gz differ diff --git a/bluewalker-vfi-icr/ups.conf b/bluewalker-vfi-icr/ups.conf new file mode 100644 index 0000000..3bc8089 --- /dev/null +++ b/bluewalker-vfi-icr/ups.conf @@ -0,0 +1,16 @@ +# /etc/nut/ups.conf -- MASTER (USB-connected host) +# PowerWalker VFI ICR IoT via nutdrv_qx over USB. +# +# Uncomment the protocol/novendor/runtimecal lines only if the bare +# config does not return clean values. See README for the test command. + +[ups] + driver = nutdrv_qx + port = auto + desc = "PowerWalker VFI ICR IoT" + pollinterval = 5 + + # Fallbacks (enable if needed): + # protocol = voltronic + # novendor + # runtimecal = 600,100,1200,50