secubox-openwrt/luci-app-mqtt-bridge/root/usr/libexec/rpcd/luci.mqtt-bridge

295 lines
8.7 KiB
Bash
Executable File

#!/bin/sh
# SecuBox MQTT Bridge RPC backend
. /lib/functions.sh
. /usr/share/libubox/jshn.sh
ZIGBEE_VENDOR="0424"
ZIGBEE_PRODUCT="2134"
ZIGBEE_PROFILE_ID="zigbee_usb2134"
find_usb_tty() {
local base="$1"
local sub node tty
for sub in "$base" "$base"/* "$base"/*/*; do
[ -d "$sub/tty" ] || continue
for node in "$sub"/tty/*; do
[ -e "$node" ] || continue
tty="$(basename "$node")"
if [ -e "/dev/$tty" ]; then
echo "/dev/$tty"
return 0
fi
done
done
return 1
}
append_zigbee_profile() {
local matched=0
local dev
for dev in /sys/bus/usb/devices/*; do
[ -f "$dev/idVendor" ] || continue
[ -f "$dev/idProduct" ] || continue
local vendor product
vendor="$(cat "$dev/idVendor" 2>/dev/null)"
product="$(cat "$dev/idProduct" 2>/dev/null)"
[ "$vendor" = "$ZIGBEE_VENDOR" ] || continue
[ "$product" = "$ZIGBEE_PRODUCT" ] || continue
matched=1
local busnum devnum label port
busnum="$(cat "$dev/busnum" 2>/dev/null)"
devnum="$(cat "$dev/devnum" 2>/dev/null)"
if [ -f "$dev/product" ]; then
label="$(cat "$dev/product")"
else
label="SMSC USB2134B"
fi
port="$(find_usb_tty "$dev")"
json_add_object
json_add_string "id" "$ZIGBEE_PROFILE_ID"
json_add_string "label" "$label Zigbee Bridge"
json_add_string "vendor" "$vendor"
json_add_string "product" "$product"
[ -n "$busnum" ] && json_add_string "bus" "$busnum"
[ -n "$devnum" ] && json_add_string "device" "$devnum"
[ -n "$port" ] && json_add_string "port" "$port"
json_add_boolean "detected" 1
json_add_string "notes" "Detected via USB bus $busnum device $devnum"
json_close_object
done
if [ "$matched" -eq 0 ]; then
json_add_object
json_add_string "id" "$ZIGBEE_PROFILE_ID"
json_add_string "label" "SMSC USB2134B Zigbee Bridge"
json_add_string "vendor" "$ZIGBEE_VENDOR"
json_add_string "product" "$ZIGBEE_PRODUCT"
json_add_boolean "detected" 0
json_add_string "notes" "Connect the dongle (Bus 003 Device 002: ID 0424:2134) to auto-fill tty port"
json_close_object
fi
}
add_adapter_json() {
local section="$1"
local enabled vendor product title preset notes detected port bus device health last_seen
config_get enabled "$section" enabled "1"
config_get vendor "$section" vendor
config_get product "$section" product
config_get title "$section" title
config_get preset "$section" preset
config_get notes "$section" notes
config_get detected "$section" detected
config_get port "$section" port
config_get bus "$section" bus
config_get device "$section" device
config_get health "$section" health
config_get last_seen "$section" last_seen
json_add_object
json_add_string "id" "$section"
[ -n "$title" ] && json_add_string "label" "$title"
[ -n "$preset" ] && json_add_string "preset" "$preset"
[ -n "$vendor" ] && json_add_string "vendor" "$vendor"
[ -n "$product" ] && json_add_string "product" "$product"
json_add_boolean "enabled" "${enabled:-0}"
json_add_boolean "detected" "${detected:-0}"
[ -n "$port" ] && json_add_string "port" "$port"
[ -n "$bus" ] && json_add_string "bus" "$bus"
[ -n "$device" ] && json_add_string "device" "$device"
[ -n "$health" ] && json_add_string "health" "$health"
[ -n "$last_seen" ] && json_add_string "last_seen" "$last_seen"
[ -n "$notes" ] && json_add_string "notes" "$notes"
json_close_object
}
append_configured_adapters() {
json_add_array "adapters"
config_load mqtt-bridge
config_foreach add_adapter_json adapter
json_close_array
}
apply_adapter_settings() {
local adapter_keys
json_get_keys adapter_keys
for adapter in $adapter_keys; do
json_select "$adapter" || continue
local enabled label port vendor product preset
json_get_var enabled enabled
json_get_var label label
json_get_var port port
json_get_var vendor vendor
json_get_var product product
json_get_var preset preset
json_select ..
[ -n "$adapter" ] || continue
if ! uci -q get mqtt-bridge.adapter."$adapter" >/dev/null 2>&1; then
uci set mqtt-bridge.adapter."$adapter"="adapter"
fi
[ -n "$enabled" ] && uci set mqtt-bridge.adapter."$adapter".enabled="$enabled"
if [ -n "$label" ]; then
uci set mqtt-bridge.adapter."$adapter".title="$label"
else
uci delete mqtt-bridge.adapter."$adapter".title >/dev/null 2>&1
fi
if [ -n "$port" ]; then
uci set mqtt-bridge.adapter."$adapter".port="$port"
else
uci delete mqtt-bridge.adapter."$adapter".port >/dev/null 2>&1
fi
[ -n "$vendor" ] && uci set mqtt-bridge.adapter."$adapter".vendor="$vendor"
[ -n "$product" ] && uci set mqtt-bridge.adapter."$adapter".product="$product"
[ -n "$preset" ] && uci set mqtt-bridge.adapter."$adapter".preset="$preset"
done
}
status() {
json_init
json_add_string "broker" "$(uci -q get mqtt-bridge.broker.host || echo 'localhost')"
json_add_int "clients" "$(uci -q get mqtt-bridge.stats.clients || echo 0)"
local adapters="$(ls /dev/ttyUSB* 2>/dev/null | wc -l)"
json_add_int "adapters" "$adapters"
json_add_int "messages_per_sec" "$(uci -q get mqtt-bridge.stats.mps || echo 0)"
json_add_int "retained" "$(uci -q get mqtt-bridge.stats.retained || echo 0)"
json_add_string "uptime" "$(uci -q get mqtt-bridge.stats.uptime || echo '0s')"
json_add_string "last_event" "$(uci -q get mqtt-bridge.stats.last_event || echo '')"
# Device statistics
local total=0 online=0
while true; do
local ser=$(uci -q get mqtt-bridge.device.@device[$total].serial)
[ -z "$ser" ] && break
local is_on=$(uci -q get mqtt-bridge.device.@device[$total].online || echo 0)
[ "$is_on" = "1" ] && online=$((online + 1))
total=$((total + 1))
done
json_add_object "device_stats"
json_add_int "total" "$total"
json_add_int "online" "$online"
json_add_int "usb" "$adapters"
json_close_object
json_add_array "recent_payloads"
local idx=0
while true; do
local topic=$(uci -q get mqtt-bridge.payloads.@payload[$idx].topic)
[ -z "$topic" ] && break
json_add_object
json_add_string "topic" "$topic"
json_add_string "payload" "$(uci -q get mqtt-bridge.payloads.@payload[$idx].data)"
json_add_string "timestamp" "$(uci -q get mqtt-bridge.payloads.@payload[$idx].time)"
json_close_object
idx=$((idx + 1))
done
json_close_array
json_add_object "settings"
json_add_string "host" "$(uci -q get mqtt-bridge.broker.host || echo '127.0.0.1')"
json_add_int "port" "$(uci -q get mqtt-bridge.broker.port || echo 1883)"
json_add_string "username" "$(uci -q get mqtt-bridge.broker.username || echo '')"
json_add_string "password" ""
json_add_string "base_topic" "$(uci -q get mqtt-bridge.bridge.base_topic || echo 'secubox/+/state')"
json_add_int "retention" "$(uci -q get mqtt-bridge.bridge.retention || echo 7)"
json_close_object
json_add_array "profiles"
append_zigbee_profile
json_close_array
append_configured_adapters
json_dump
}
list_devices() {
json_init
json_add_array "devices"
local idx=0
while true; do
local serial=$(uci -q get mqtt-bridge.device.@device[$idx].serial)
[ -z "$serial" ] && break
json_add_object
json_add_string "serial" "$serial"
json_add_string "name" "$(uci -q get mqtt-bridge.device.@device[$idx].name)"
json_add_string "protocol" "$(uci -q get mqtt-bridge.device.@device[$idx].protocol || echo 'USB')"
json_add_string "port" "$(uci -q get mqtt-bridge.device.@device[$idx].port || echo '-')"
json_add_boolean "online" "$(uci -q get mqtt-bridge.device.@device[$idx].online || echo 0)"
json_close_object
idx=$((idx + 1))
done
json_close_array
json_dump
}
trigger_pairing() {
json_init
touch /tmp/mqtt-bridge-pairing
json_add_boolean "success" 1
json_add_string "message" "pairing_window_open"
json_dump
}
apply_settings() {
read input
json_load "$input"
json_get_var host host
json_get_var port port
json_get_var username username
json_get_var password password
json_get_var base_topic base_topic
json_get_var retention retention
json_get_type adapters_type adapters
if [ "$adapters_type" = "object" ]; then
json_select adapters
apply_adapter_settings
json_select ..
fi
json_cleanup
[ -n "$host" ] && uci set mqtt-bridge.broker.host="$host"
[ -n "$port" ] && uci set mqtt-bridge.broker.port="$port"
[ -n "$username" ] && uci set mqtt-bridge.broker.username="$username"
[ -n "$password" ] && uci set mqtt-bridge.broker.password="$password"
[ -n "$base_topic" ] && uci set mqtt-bridge.bridge.base_topic="$base_topic"
[ -n "$retention" ] && uci set mqtt-bridge.bridge.retention="$retention"
uci commit mqtt-bridge
json_init
json_add_boolean "success" 1
json_add_string "message" "settings_saved"
json_dump
}
case "$1" in
list)
cat <<'JSON'
{
"status": {},
"list_devices": {},
"trigger_pairing": {},
"apply_settings": {}
}
JSON
;;
call)
case "$2" in
status) status ;;
list_devices) list_devices ;;
trigger_pairing) trigger_pairing ;;
apply_settings) apply_settings ;;
*)
json_init
json_add_boolean "success" 0
json_add_string "error" "unknown_method"
json_dump
;;
esac
;;
esac