secubox-openwrt/luci-app-mqtt-bridge/root/usr/sbin/mqtt-bridge-monitor

150 lines
3.7 KiB
Bash
Executable File

#!/bin/sh
#
# MQTT Bridge monitor daemon
# Scans configured USB adapters/presets and updates UCI with live metadata.
. /lib/functions.sh
UCI_NAMESPACE="mqtt-bridge"
LOGTAG="mqtt-bridge-monitor"
SCAN_INTERVAL=10
COMMIT_NEEDED=0
log_msg() {
logger -t "$LOGTAG" "$*"
}
find_usb_device() {
local vendor="$1"
local product="$2"
local dev
for dev in /sys/bus/usb/devices/*; do
[ -f "$dev/idVendor" ] || continue
[ -f "$dev/idProduct" ] || continue
local idVendor idProduct
idVendor="$(cat "$dev/idVendor" 2>/dev/null)"
idProduct="$(cat "$dev/idProduct" 2>/dev/null)"
[ "$idVendor" = "$vendor" ] || continue
[ "$idProduct" = "$product" ] || continue
echo "$dev"
return 0
done
return 1
}
find_usb_tty() {
local base="$1"
local path node
for path in "$base" "$base"/* "$base"/*/*; do
[ -d "$path/tty" ] || continue
for node in "$path"/tty/*; do
[ -e "$node" ] || continue
local tty
tty="$(basename "$node")"
[ -e "/dev/$tty" ] && { echo "/dev/$tty"; return 0; }
done
done
return 1
}
set_option_if_changed() {
local section="$1"
local key="$2"
local value="$3"
local current
current="$(uci -q get ${UCI_NAMESPACE}.adapter.${section}.${key} 2>/dev/null)"
[ "$current" = "$value" ] && return
uci set ${UCI_NAMESPACE}.adapter.${section}.${key}="$value"
COMMIT_NEEDED=1
}
clear_option_if_needed() {
local section="$1"
local key="$2"
local current
current="$(uci -q get ${UCI_NAMESPACE}.adapter.${section}.${key} 2>/dev/null)"
[ -z "$current" ] && return
uci delete ${UCI_NAMESPACE}.adapter.${section}.${key}
COMMIT_NEEDED=1
}
update_adapter_section() {
local section="$1"
local enabled vendor product title preset
config_get enabled "$section" enabled "1"
config_get vendor "$section" vendor
config_get product "$section" product
config_get preset "$section" preset
config_get title "$section" title
if [ "$enabled" != "1" ]; then
set_option_if_changed "$section" detected "0"
set_option_if_changed "$section" health "disabled"
return
fi
if [ -z "$vendor" ] || [ -z "$product" ]; then
set_option_if_changed "$section" detected "0"
set_option_if_changed "$section" health "unknown"
return
fi
local dev_path
dev_path="$(find_usb_device "$vendor" "$product")" || dev_path=""
local prev_detected
prev_detected="$(uci -q get ${UCI_NAMESPACE}.adapter.${section}.detected 2>/dev/null)"
if [ -n "$dev_path" ]; then
local bus devnum port ts
bus="$(cat "$dev_path/busnum" 2>/dev/null)"
devnum="$(cat "$dev_path/devnum" 2>/dev/null)"
port="$(find_usb_tty "$dev_path")"
ts="$(date -Iseconds)"
set_option_if_changed "$section" detected "1"
set_option_if_changed "$section" health "online"
[ -n "$bus" ] && set_option_if_changed "$section" bus "$bus"
[ -n "$devnum" ] && set_option_if_changed "$section" device "$devnum"
if [ -n "$port" ]; then
set_option_if_changed "$section" port "$port"
else
clear_option_if_needed "$section" port
fi
set_option_if_changed "$section" last_seen "$ts"
if [ "$prev_detected" != "1" ]; then
log_msg "Adapter $section ($title) detected on bus $bus dev $devnum $port"
fi
else
set_option_if_changed "$section" detected "0"
set_option_if_changed "$section" health "missing"
clear_option_if_needed "$section" port
clear_option_if_needed "$section" bus
clear_option_if_needed "$section" device
if [ "$prev_detected" = "1" ]; then
log_msg "Adapter $section ($title) disconnected"
fi
fi
}
scan_loop() {
while true; do
COMMIT_NEEDED=0
config_load "$UCI_NAMESPACE"
local interval
config_get interval monitor interval
[ -n "$interval" ] && SCAN_INTERVAL="$interval"
config_foreach update_adapter_section adapter
if [ "$COMMIT_NEEDED" -eq 1 ]; then
uci commit "$UCI_NAMESPACE"
fi
sleep "$SCAN_INTERVAL"
done
}
scan_loop