Major structural reorganization and feature additions: ## Folder Reorganization - Move 17 luci-app-* packages to package/secubox/ (except luci-app-secubox core hub) - Update all tooling to support new structure: - secubox-tools/quick-deploy.sh: search both locations - secubox-tools/validate-modules.sh: validate both directories - secubox-tools/fix-permissions.sh: fix permissions in both locations - .github/workflows/test-validate.yml: build from both paths - Update README.md links to new package/secubox/ paths ## AppStore Migration (Complete) - Add catalog entries for all remaining luci-app packages: - network-tweaks.json: Network optimization tools - secubox-bonus.json: Documentation & demos hub - Total: 24 apps in AppStore catalog (22 existing + 2 new) - New category: 'documentation' for docs/demos/tutorials ## VHost Manager v2.0 Enhancements - Add profile activation system for Internal Services and Redirects - Implement createVHost() API wrapper for template-based deployment - Fix Virtual Hosts view rendering with proper LuCI patterns - Fix RPCD backend shell script errors (remove invalid local declarations) - Extend backend validation for nginx return directives (redirect support) - Add section_id parameter for named VHost profiles - Add Remove button to Redirects page for feature parity - Update README to v2.0 with comprehensive feature documentation ## Network Tweaks Dashboard - Close button added to component details modal Files changed: 340+ (336 renames with preserved git history) Packages affected: 19 luci-app, 2 secubox-app, 1 theme, 4 tools 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
674 lines
20 KiB
Bash
Executable File
674 lines
20 KiB
Bash
Executable File
#!/bin/sh
|
|
# SecuBox MQTT Bridge RPC backend
|
|
|
|
. /lib/functions.sh
|
|
. /usr/share/libubox/jshn.sh
|
|
. /usr/share/mqtt-bridge/usb-database.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
|
|
}
|
|
|
|
add_template_json() {
|
|
local section="$1"
|
|
local device_type topic qos retain
|
|
config_get device_type "$section" device_type
|
|
config_get topic "$section" topic
|
|
config_get qos "$section" qos
|
|
config_get retain "$section" retain
|
|
json_add_object
|
|
json_add_string "id" "$section"
|
|
[ -n "$device_type" ] && json_add_string "device_type" "$device_type"
|
|
[ -n "$topic" ] && json_add_string "topic" "$topic"
|
|
[ -n "$qos" ] && json_add_string "qos" "$qos"
|
|
[ -n "$retain" ] && json_add_string "retain" "$retain"
|
|
json_close_object
|
|
}
|
|
|
|
append_templates() {
|
|
json_add_array "templates"
|
|
config_load mqtt-bridge
|
|
config_foreach add_template_json template
|
|
json_close_array
|
|
}
|
|
|
|
add_rule_json() {
|
|
local section="$1"
|
|
local type adapter when action message topic
|
|
config_get type "$section" type
|
|
config_get adapter "$section" adapter
|
|
config_get when "$section" when
|
|
config_get action "$section" action
|
|
config_get message "$section" message
|
|
config_get topic "$section" topic
|
|
json_add_object
|
|
json_add_string "id" "$section"
|
|
[ -n "$type" ] && json_add_string "type" "$type"
|
|
[ -n "$adapter" ] && json_add_string "adapter" "$adapter"
|
|
[ -n "$when" ] && json_add_string "when" "$when"
|
|
[ -n "$action" ] && json_add_string "action" "$action"
|
|
[ -n "$message" ] && json_add_string "message" "$message"
|
|
[ -n "$topic" ] && json_add_string "topic" "$topic"
|
|
json_close_object
|
|
}
|
|
|
|
append_rules() {
|
|
json_add_array "rules"
|
|
config_load mqtt-bridge
|
|
config_foreach add_rule_json rule
|
|
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
|
|
append_templates
|
|
append_rules
|
|
|
|
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
|
|
}
|
|
|
|
rescan_adapters() {
|
|
/usr/sbin/mqtt-bridge --rescan >/dev/null 2>&1 &
|
|
json_init
|
|
json_add_boolean "success" 1
|
|
json_add_string "message" "rescan_triggered"
|
|
json_dump
|
|
}
|
|
|
|
reset_adapter() {
|
|
read input
|
|
json_load "$input"
|
|
json_get_var adapter adapter
|
|
json_cleanup
|
|
|
|
if [ -z "$adapter" ]; then
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "missing_adapter"
|
|
json_dump
|
|
return
|
|
fi
|
|
|
|
uci delete mqtt-bridge.adapter."$adapter".port >/dev/null 2>&1
|
|
uci delete mqtt-bridge.adapter."$adapter".bus >/dev/null 2>&1
|
|
uci delete mqtt-bridge.adapter."$adapter".device >/dev/null 2>&1
|
|
uci delete mqtt-bridge.adapter."$adapter".detected >/dev/null 2>&1
|
|
uci delete mqtt-bridge.adapter."$adapter".health >/dev/null 2>&1
|
|
uci delete mqtt-bridge.adapter."$adapter".last_seen >/dev/null 2>&1
|
|
uci commit mqtt-bridge
|
|
|
|
json_init
|
|
json_add_boolean "success" 1
|
|
json_add_string "message" "adapter_reset"
|
|
json_dump
|
|
}
|
|
|
|
# === NEW USB DETECTION RPC METHODS ===
|
|
|
|
get_usb_devices() {
|
|
json_init
|
|
json_add_array "devices"
|
|
|
|
for dev in /sys/bus/usb/devices/*; do
|
|
[ -f "$dev/idVendor" ] || continue
|
|
[ -f "$dev/idProduct" ] || continue
|
|
|
|
local vendor="$(cat "$dev/idVendor" 2>/dev/null)"
|
|
local product="$(cat "$dev/idProduct" 2>/dev/null)"
|
|
local busnum="$(cat "$dev/busnum" 2>/dev/null)"
|
|
local devnum="$(cat "$dev/devnum" 2>/dev/null)"
|
|
local manufacturer="$(cat "$dev/manufacturer" 2>/dev/null || echo "Unknown")"
|
|
local prod_name="$(cat "$dev/product" 2>/dev/null || echo "Unknown")"
|
|
|
|
local adapter_type="$(detect_adapter_type "$vendor" "$product")"
|
|
local device_name="$(get_device_name "$vendor" "$product")"
|
|
local port="$(find_usb_tty "$dev")"
|
|
|
|
json_add_object
|
|
json_add_string "vid" "$vendor"
|
|
json_add_string "pid" "$product"
|
|
json_add_string "bus" "$busnum"
|
|
json_add_string "device" "$devnum"
|
|
json_add_string "manufacturer" "$manufacturer"
|
|
json_add_string "product" "$prod_name"
|
|
json_add_string "type" "$adapter_type"
|
|
json_add_string "name" "$device_name"
|
|
[ -n "$port" ] && json_add_string "port" "$port"
|
|
json_close_object
|
|
done
|
|
|
|
json_close_array
|
|
json_dump
|
|
}
|
|
|
|
detect_iot_adapters() {
|
|
json_init
|
|
|
|
detect_zigbee_adapters
|
|
detect_zwave_adapters
|
|
detect_modbus_adapters
|
|
|
|
json_dump
|
|
}
|
|
|
|
get_serial_ports() {
|
|
json_init
|
|
list_serial_ports
|
|
json_dump
|
|
}
|
|
|
|
get_adapter_info() {
|
|
read input
|
|
json_load "$input"
|
|
json_get_var adapter_id adapter
|
|
json_cleanup
|
|
|
|
if [ -z "$adapter_id" ]; then
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "missing_adapter_id"
|
|
json_dump
|
|
return
|
|
fi
|
|
|
|
json_init
|
|
|
|
# Get UCI configuration
|
|
local enabled="$(uci -q get mqtt-bridge.adapter."$adapter_id".enabled || echo 0)"
|
|
local type="$(uci -q get mqtt-bridge.adapter."$adapter_id".type || echo 'unknown')"
|
|
local title="$(uci -q get mqtt-bridge.adapter."$adapter_id".title || echo 'Unknown Adapter')"
|
|
local vendor="$(uci -q get mqtt-bridge.adapter."$adapter_id".vendor || echo '')"
|
|
local product="$(uci -q get mqtt-bridge.adapter."$adapter_id".product || echo '')"
|
|
local port="$(uci -q get mqtt-bridge.adapter."$adapter_id".port || echo '')"
|
|
local detected="$(uci -q get mqtt-bridge.adapter."$adapter_id".detected || echo 0)"
|
|
local health="$(uci -q get mqtt-bridge.adapter."$adapter_id".health || echo 'unknown')"
|
|
|
|
json_add_string "id" "$adapter_id"
|
|
json_add_boolean "enabled" "$enabled"
|
|
json_add_string "type" "$type"
|
|
json_add_string "title" "$title"
|
|
json_add_string "vid" "$vendor"
|
|
json_add_string "pid" "$product"
|
|
json_add_string "port" "$port"
|
|
json_add_boolean "detected" "$detected"
|
|
json_add_string "health" "$health"
|
|
|
|
# Add type-specific config
|
|
case "$type" in
|
|
zigbee)
|
|
json_add_string "baud" "$(uci -q get mqtt-bridge.adapter."$adapter_id".baud || echo '115200')"
|
|
json_add_string "channel" "$(uci -q get mqtt-bridge.adapter."$adapter_id".channel || echo '11')"
|
|
json_add_string "pan_id" "$(uci -q get mqtt-bridge.adapter."$adapter_id".pan_id || echo '0x1A62')"
|
|
;;
|
|
zwave)
|
|
json_add_string "baud" "$(uci -q get mqtt-bridge.adapter."$adapter_id".baud || echo '115200')"
|
|
;;
|
|
modbus)
|
|
json_add_string "baud" "$(uci -q get mqtt-bridge.adapter."$adapter_id".baud || echo '9600')"
|
|
json_add_string "parity" "$(uci -q get mqtt-bridge.adapter."$adapter_id".parity || echo 'N')"
|
|
json_add_string "databits" "$(uci -q get mqtt-bridge.adapter."$adapter_id".databits || echo '8')"
|
|
json_add_string "stopbits" "$(uci -q get mqtt-bridge.adapter."$adapter_id".stopbits || echo '1')"
|
|
json_add_string "slave_id" "$(uci -q get mqtt-bridge.adapter."$adapter_id".slave_id || echo '1')"
|
|
;;
|
|
esac
|
|
|
|
# Check current USB presence if VID:PID known
|
|
if [ -n "$vendor" ] && [ -n "$product" ]; then
|
|
local found=0
|
|
for dev in /sys/bus/usb/devices/*; do
|
|
[ -f "$dev/idVendor" ] || continue
|
|
local v="$(cat "$dev/idVendor")"
|
|
local p="$(cat "$dev/idProduct")"
|
|
if [ "$v" = "$vendor" ] && [ "$p" = "$product" ]; then
|
|
found=1
|
|
local current_port="$(find_usb_tty "$dev")"
|
|
[ -n "$current_port" ] && json_add_string "current_port" "$current_port"
|
|
break
|
|
fi
|
|
done
|
|
json_add_boolean "usb_present" "$found"
|
|
fi
|
|
|
|
json_dump
|
|
}
|
|
|
|
test_connection() {
|
|
read input
|
|
json_load "$input"
|
|
json_get_var port port
|
|
json_cleanup
|
|
|
|
if [ -z "$port" ]; then
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "missing_port"
|
|
json_dump
|
|
return
|
|
fi
|
|
|
|
json_init
|
|
if test_serial_port "$port"; then
|
|
json_add_boolean "success" 1
|
|
json_add_boolean "accessible" 1
|
|
json_add_string "message" "port_accessible"
|
|
else
|
|
json_add_boolean "success" 1
|
|
json_add_boolean "accessible" 0
|
|
json_add_string "message" "port_not_accessible"
|
|
fi
|
|
json_dump
|
|
}
|
|
|
|
configure_adapter() {
|
|
read input
|
|
json_load "$input"
|
|
json_get_var adapter_id id
|
|
json_get_var enabled enabled
|
|
json_get_var type type
|
|
json_get_var title title
|
|
json_get_var vendor vid
|
|
json_get_var product pid
|
|
json_get_var port port
|
|
json_cleanup
|
|
|
|
if [ -z "$adapter_id" ]; then
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "missing_adapter_id"
|
|
json_dump
|
|
return
|
|
fi
|
|
|
|
# Create or update adapter section
|
|
uci -q get mqtt-bridge.adapter."$adapter_id" >/dev/null 2>&1 || {
|
|
uci set mqtt-bridge.adapter."$adapter_id"=adapter
|
|
}
|
|
|
|
[ -n "$enabled" ] && uci set mqtt-bridge.adapter."$adapter_id".enabled="$enabled"
|
|
[ -n "$type" ] && uci set mqtt-bridge.adapter."$adapter_id".type="$type"
|
|
[ -n "$title" ] && uci set mqtt-bridge.adapter."$adapter_id".title="$title"
|
|
[ -n "$vendor" ] && uci set mqtt-bridge.adapter."$adapter_id".vendor="$vendor"
|
|
[ -n "$product" ] && uci set mqtt-bridge.adapter."$adapter_id".product="$product"
|
|
[ -n "$port" ] && uci set mqtt-bridge.adapter."$adapter_id".port="$port"
|
|
|
|
# Mark as detected if port is present
|
|
if [ -n "$port" ] && [ -c "$port" ]; then
|
|
uci set mqtt-bridge.adapter."$adapter_id".detected=1
|
|
uci set mqtt-bridge.adapter."$adapter_id".health="online"
|
|
else
|
|
uci set mqtt-bridge.adapter."$adapter_id".detected=0
|
|
uci set mqtt-bridge.adapter."$adapter_id".health="unknown"
|
|
fi
|
|
|
|
uci commit mqtt-bridge
|
|
|
|
json_init
|
|
json_add_boolean "success" 1
|
|
json_add_string "message" "adapter_configured"
|
|
json_add_string "id" "$adapter_id"
|
|
json_dump
|
|
}
|
|
|
|
get_adapter_status() {
|
|
json_init
|
|
json_add_array "adapters"
|
|
|
|
# Iterate through all adapter sections in UCI
|
|
local idx=0
|
|
while uci -q get mqtt-bridge.@adapter[$idx] >/dev/null 2>&1; do
|
|
local adapter_id="$(uci -q get mqtt-bridge.@adapter[$idx])"
|
|
idx=$((idx + 1))
|
|
done
|
|
|
|
# Get named adapter sections
|
|
for adapter_id in $(uci -q show mqtt-bridge.adapter 2>/dev/null | grep '=adapter$' | cut -d. -f3 | cut -d= -f1); do
|
|
local enabled="$(uci -q get mqtt-bridge.adapter."$adapter_id".enabled || echo 0)"
|
|
local type="$(uci -q get mqtt-bridge.adapter."$adapter_id".type || echo 'unknown')"
|
|
local title="$(uci -q get mqtt-bridge.adapter."$adapter_id".title || echo 'Unknown')"
|
|
local vendor="$(uci -q get mqtt-bridge.adapter."$adapter_id".vendor || echo '')"
|
|
local product="$(uci -q get mqtt-bridge.adapter."$adapter_id".product || echo '')"
|
|
local port="$(uci -q get mqtt-bridge.adapter."$adapter_id".port || echo '')"
|
|
|
|
# Real-time health check
|
|
local health="unknown"
|
|
local usb_present=0
|
|
local port_accessible=0
|
|
|
|
# Check USB presence
|
|
if [ -n "$vendor" ] && [ -n "$product" ]; then
|
|
for dev in /sys/bus/usb/devices/*; do
|
|
[ -f "$dev/idVendor" ] || continue
|
|
local v="$(cat "$dev/idVendor")"
|
|
local p="$(cat "$dev/idProduct")"
|
|
if [ "$v" = "$vendor" ] && [ "$p" = "$product" ]; then
|
|
usb_present=1
|
|
local detected_port="$(find_usb_tty "$dev")"
|
|
[ -n "$detected_port" ] && port="$detected_port"
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Check port accessibility
|
|
if [ -n "$port" ] && test_serial_port "$port"; then
|
|
port_accessible=1
|
|
health="online"
|
|
elif [ "$usb_present" = "1" ]; then
|
|
health="error"
|
|
elif [ -n "$port" ]; then
|
|
health="missing"
|
|
fi
|
|
|
|
json_add_object
|
|
json_add_string "id" "$adapter_id"
|
|
json_add_boolean "enabled" "$enabled"
|
|
json_add_string "type" "$type"
|
|
json_add_string "title" "$title"
|
|
json_add_string "port" "$port"
|
|
json_add_string "health" "$health"
|
|
json_add_boolean "usb_present" "$usb_present"
|
|
json_add_boolean "port_accessible" "$port_accessible"
|
|
json_close_object
|
|
done
|
|
|
|
json_close_array
|
|
json_dump
|
|
}
|
|
|
|
case "$1" in
|
|
list)
|
|
cat <<'JSON'
|
|
{
|
|
"status": {},
|
|
"list_devices": {},
|
|
"trigger_pairing": {},
|
|
"apply_settings": {},
|
|
"rescan_adapters": {},
|
|
"reset_adapter": {},
|
|
"get_usb_devices": {},
|
|
"detect_iot_adapters": {},
|
|
"get_serial_ports": {},
|
|
"get_adapter_info": { "adapter": "string" },
|
|
"test_connection": { "port": "string" },
|
|
"configure_adapter": { "id": "string", "enabled": "boolean", "type": "string", "title": "string", "vid": "string", "pid": "string", "port": "string" },
|
|
"get_adapter_status": {}
|
|
}
|
|
JSON
|
|
;;
|
|
call)
|
|
case "$2" in
|
|
status) status ;;
|
|
list_devices) list_devices ;;
|
|
trigger_pairing) trigger_pairing ;;
|
|
apply_settings) apply_settings ;;
|
|
rescan_adapters) rescan_adapters ;;
|
|
reset_adapter) reset_adapter ;;
|
|
get_usb_devices) get_usb_devices ;;
|
|
detect_iot_adapters) detect_iot_adapters ;;
|
|
get_serial_ports) get_serial_ports ;;
|
|
get_adapter_info) get_adapter_info ;;
|
|
test_connection) test_connection ;;
|
|
configure_adapter) configure_adapter ;;
|
|
get_adapter_status) get_adapter_status ;;
|
|
*)
|
|
json_init
|
|
json_add_boolean "success" 0
|
|
json_add_string "error" "unknown_method"
|
|
json_dump
|
|
;;
|
|
esac
|
|
;;
|
|
esac
|