van-leds: drive the R5C power/LAN/WAN/WiFi LEDs (ENABLE_LEDS, LED_* vars, post-check probe)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
This commit is contained in:
2026-09-23 22:04:11 -04:00
co-authored by Claude Sonnet 5
parent e2036c295d
commit 0f643be719
9 changed files with 382 additions and 2 deletions
+44 -2
View File
@@ -27,6 +27,7 @@
# VANLINK_SYSNET=<dir> # test override: sysfs net dir used by --post-check and --apply-preflight (default /sys/class/net)
# VANLINK_HOSTNAME=<name> # test override: host name used by --apply-preflight (default `hostname -s`; ignored when run as root)
# VANLINK_FAILOVER_STATE=<file> # test override: van-failover state file read by --post-check (default /run/van-failover/state.json)
# VANLINK_SYSLEDS=<dir> # test override: sysfs LED dir read by --post-check (default /sys/class/leds; ignored when run as root)
# VANLINK_APPLY_STATUS=<file> # test override: apply-network status file read by --post-check (default /var/lib/vanlink/apply-network.status)
# VANLINK_WAN_NETPLAN=<file> # test override: installed WAN netplan compared by nm_wan_state_netplan (default /etc/netplan/50-van-wan.yaml)
# VANLINK_NM_DIR=<dir> # test override: where existing NM *.nmconnection files are looked up (default /etc/NetworkManager/system-connections;
@@ -51,13 +52,14 @@ REQUIRED_VARS=(
GATEWAY_IP GATEWAY_PREFIX GATEWAY_NETWORK DHCP_RANGE_START DHCP_RANGE_END
DNS_RESOLVERS MODEM_USB_VENDOR AP_SSID_5G AP_SSID_2G AP_5G_RADIO
ENABLE_COCKPIT ENABLE_LI3 ENABLE_NVME_WATCH ENABLE_HA ENABLE_FRIGATE
ENABLE_NM_WAN
ENABLE_NM_WAN ENABLE_LEDS
)
# May be empty or absent; NVME_* are required only when ENABLE_NVME_WATCH=1.
OPTIONAL_VARS=(
WIFI_WAN_IFACE CELLULAR_CONN_NAME CELLULAR_APN
ONBOARD_LAN_IFACE NVME_DEVICE NVME_FS_DEVICE
USB_BACKUP_ROOT_PART USB_BACKUP_MOUNT SD_BACKUP_UUID
LED_POWER LED_LAN LED_WAN LED_WLAN
)
# Computed in load_conf; usable as @TOKEN@ like the rest.
DERIVED_VARS=(ONBOARD_LAN_UNMANAGED CELLULAR_UUID)
@@ -77,7 +79,7 @@ load_conf() { # load_conf <file> — source and validate a host config
[ -n "${!v:-}" ] || missing+=("$v")
done
[ ${#missing[@]} -eq 0 ] || die "$f is missing required variable(s): ${missing[*]}"
for flag in ENABLE_COCKPIT ENABLE_LI3 ENABLE_NVME_WATCH ENABLE_HA ENABLE_FRIGATE ENABLE_NM_WAN; do
for flag in ENABLE_COCKPIT ENABLE_LI3 ENABLE_NVME_WATCH ENABLE_HA ENABLE_FRIGATE ENABLE_NM_WAN ENABLE_LEDS; do
case ${!flag} in
0|1) ;;
*) die "$f: $flag must be 0 or 1 (got '${!flag}')" ;;
@@ -222,6 +224,9 @@ fi
if [ "$ENABLE_LI3" = 1 ]; then
ENABLE_UNITS+=(van-li3-battery)
fi
if [ "$ENABLE_LEDS" = 1 ]; then
ENABLE_UNITS+=(van-leds)
fi
if [ "$ENABLE_NM_WAN" = 1 ]; then
ENABLE_UNITS+=(NetworkManager ModemManager)
fi
@@ -337,6 +342,33 @@ post_check() { # read-only live checks; every probe is guarded, warns instead o
refused) warn "post-deploy: van-router-mqtt is refused by the MQTT broker — add credentials to /etc/van-router-mqtt/credentials.json (see the service journal)" ;;
connected) echo " ok van-router-mqtt: MQTT connection ok" ;;
esac
if [ "$ENABLE_LEDS" = 1 ]; then
# g3. front LEDs (van-leds): each configured LED exists; the static ones carry the expected trigger.
# The WAN LED follows the uplink, so its state is only reported, never warned about.
local sysleds=/sys/class/leds lrole lname ltrig lwant ldev
[ "$(id -u)" = 0 ] || sysleds=${VANLINK_SYSLEDS:-$sysleds}
for lrole in "power|${LED_POWER:-}|default-on|" "lan|${LED_LAN:-}|netdev|$LAN_IFACE" "wlan|${LED_WLAN:-}|netdev|$WIFI_5G_IFACE" "wan|${LED_WAN:-}||"; do
IFS='|' read -r lrole lname lwant ldev <<<"$lrole" # LED names contain ':' so '|' separates
[ -n "$lname" ] || continue
if [ ! -d "$sysleds/$lname" ]; then
warn "post-deploy: LED $lname not present — is the nanopi-r5c-leds overlay enabled in /boot/armbianEnv.txt?"
continue
fi
ltrig=$(sed -n 's/.*\[\(.*\)\].*/\1/p' "$sysleds/$lname/trigger" 2>/dev/null) || ltrig=
if [ "$lrole" = wan ]; then
if [ "$ltrig" = netdev ]; then echo " ok LED $lname (wan): netdev $(cat "$sysleds/$lname/device_name" 2>/dev/null || true)"
else echo " ok LED $lname (wan): ${ltrig:-unknown}"; fi
continue
fi
if [ "$ltrig" != "$lwant" ]; then
warn "post-deploy: LED $lname ($lrole) trigger is '${ltrig:-unknown}', expected $lwant"
elif [ -n "$ldev" ] && [ "$(cat "$sysleds/$lname/device_name" 2>/dev/null || true)" != "$ldev" ]; then
warn "post-deploy: LED $lname ($lrole) device_name is '$(cat "$sysleds/$lname/device_name" 2>/dev/null || true)', expected $ldev"
else
echo " ok LED $lname ($lrole): $ltrig${ldev:+ $ldev}"
fi
done
fi
if [ "$ENABLE_NM_WAN" = 1 ]; then
local sysnet=${VANLINK_SYSNET:-/sys/class/net} nmst fst as_f as_l
# h. NetworkManager must leave the AP/LAN radios and ports alone
@@ -1116,6 +1148,13 @@ if [ "$ENABLE_NVME_WATCH" = 1 ]; then
install -D -m0644 power/van-nvme-watch.service /etc/systemd/system/van-nvme-watch.service
fi
if [ "$ENABLE_LEDS" = 1 ]; then
echo "== front LEDs =="
install -D -m0755 leds/van-leds /usr/local/sbin/van-leds
install_rendered leds/config.json /etc/van-leds/config.json
install -D -m0644 leds/van-leds.service /etc/systemd/system/van-leds.service
fi
echo "== home assistant =="
# Native HA (Podman Quadlet, replaced the ha_van VM). daemon-reload below
# regenerates homeassistant.service; started (not restarted) at the end so a
@@ -1222,6 +1261,9 @@ if [ "$ENABLE_LI3" = 1 ]; then
systemctl restart van-li3-battery
fi
systemctl restart van-router-mqtt
if [ "$ENABLE_LEDS" = 1 ]; then
systemctl restart van-leds
fi
# Pick up unmanaged-devices changes so NM releases/keeps the right interfaces.
nmcli general reload 2>/dev/null || systemctl reload NetworkManager 2>/dev/null || true
# restart in dependency order: bridge + members first, then hostapd enslaves the