|
|
@@ -44,7 +44,9 @@ local function load_state()
|
|
|
local dhcp = {}
|
|
|
for line in content:gmatch("[^\n]+") do
|
|
|
local t, v = line:match("^([^:]+):(.+)$")
|
|
|
- if t == "client" then clients[v] = true
|
|
|
+ if t == "client" then
|
|
|
+ local mac, iface, ssid = v:match("^(.+)|(.+)|(.+)$")
|
|
|
+ if mac and iface then clients[mac] = {iface=iface, ssid=ssid} end
|
|
|
elseif t == "ssid" then ssid_enabled[v] = true
|
|
|
elseif t == "dhcp" then
|
|
|
local mac, ip = v:match("^(.+)->(.+)$")
|
|
|
@@ -59,8 +61,8 @@ end
|
|
|
local function save_state(state)
|
|
|
local f = io.open(cfg.state_file, "w")
|
|
|
if f then
|
|
|
- for mac in pairs(state.clients) do
|
|
|
- f:write("client:" .. mac .. "\n")
|
|
|
+ for mac, info in pairs(state.clients) do
|
|
|
+ f:write("client:" .. mac .. "|" .. (info.iface or "") .. "|" .. (info.ssid or "") .. "\n")
|
|
|
end
|
|
|
for iface in pairs(state.ssid_enabled) do
|
|
|
f:write("ssid:" .. iface .. "\n")
|
|
|
@@ -73,7 +75,7 @@ local function save_state(state)
|
|
|
end
|
|
|
|
|
|
-------------------------------------------------
|
|
|
--- WiFi: Get ALL hostapd interfaces
|
|
|
+-- WiFi: Get ALL hostapd interfaces + SSID names
|
|
|
-------------------------------------------------
|
|
|
local function get_hostapd_interfaces()
|
|
|
local f = io.popen("ubus list | grep hostapd")
|
|
|
@@ -87,17 +89,47 @@ local function get_hostapd_interfaces()
|
|
|
return interfaces
|
|
|
end
|
|
|
|
|
|
--- Get clients from ALL interfaces
|
|
|
+-- Get SSID name for an interface
|
|
|
+local function get_ssid_name(iface)
|
|
|
+ local f = io.popen("ubus call " .. iface .. " get_status 2>/dev/null")
|
|
|
+ if f then
|
|
|
+ local result = f:read("*a")
|
|
|
+ f:close()
|
|
|
+ local ssid = result:match('"ssid":"([^"]+)"')
|
|
|
+ return ssid or iface
|
|
|
+ end
|
|
|
+ return iface
|
|
|
+end
|
|
|
+
|
|
|
+-- Get all SSID statuses
|
|
|
+local function get_all_ssids()
|
|
|
+ local ssids = {}
|
|
|
+ local interfaces = get_hostapd_interfaces()
|
|
|
+ for _, iface in ipairs(interfaces) do
|
|
|
+ local f = io.popen("ubus call " .. iface .. " get_status 2>/dev/null")
|
|
|
+ if f then
|
|
|
+ local result = f:read("*a")
|
|
|
+ f:close()
|
|
|
+ local enabled = result:match('"enabled":%s*(%a+)')
|
|
|
+ local ssid = result:match('"ssid":"([^"]+)"') or iface
|
|
|
+ ssids[iface] = { enabled = (enabled == "true"), ssid = ssid }
|
|
|
+ end
|
|
|
+ end
|
|
|
+ return ssids
|
|
|
+end
|
|
|
+
|
|
|
+-- Get clients from ALL interfaces WITH their SSID
|
|
|
local function get_wifi_clients()
|
|
|
local clients = {}
|
|
|
local interfaces = get_hostapd_interfaces()
|
|
|
for _, iface in ipairs(interfaces) do
|
|
|
+ local ssid = get_ssid_name(iface)
|
|
|
local f = io.popen("ubus call " .. iface .. " get_clients 2>/dev/null")
|
|
|
if f then
|
|
|
local result = f:read("*a")
|
|
|
f:close()
|
|
|
for mac in result:gmatch('"([a-fA-F0-9:]+)"') do
|
|
|
- clients[mac] = true
|
|
|
+ clients[mac] = { iface = iface, ssid = ssid }
|
|
|
end
|
|
|
end
|
|
|
end
|
|
|
@@ -107,16 +139,10 @@ end
|
|
|
-- Get SSID status for ALL interfaces
|
|
|
local function get_ssid_status()
|
|
|
local status = {}
|
|
|
- local interfaces = get_hostapd_interfaces()
|
|
|
- for _, iface in ipairs(interfaces) do
|
|
|
- local f = io.popen("ubus call " .. iface .. " get_status 2>/dev/null")
|
|
|
- if f then
|
|
|
- local result = f:read("*a")
|
|
|
- f:close()
|
|
|
- local enabled = result:match('"enabled":%s*(%a+)')
|
|
|
- if enabled == "true" then
|
|
|
- status[iface] = true
|
|
|
- end
|
|
|
+ local ssids = get_all_ssids()
|
|
|
+ for iface, info in pairs(ssids) do
|
|
|
+ if info.enabled then
|
|
|
+ status[iface] = true
|
|
|
end
|
|
|
end
|
|
|
return status
|
|
|
@@ -177,16 +203,16 @@ function main()
|
|
|
-------------------------------------------------
|
|
|
local current_clients = get_wifi_clients()
|
|
|
|
|
|
- for mac in pairs(current_clients) do
|
|
|
+ for mac, info in pairs(current_clients) do
|
|
|
if not state.clients[mac] then
|
|
|
- log_info("WiFi CONNECTED: " .. mac)
|
|
|
- send_event("wifi_connected", '{"mac":"' .. mac .. '"}')
|
|
|
+ log_info("WiFi CONNECTED: " .. mac .. " on " .. info.ssid)
|
|
|
+ send_event("wifi_connected", '{"mac":"' .. mac .. '","ssid":"' .. info.ssid .. '","interface":"' .. info.iface .. '"}')
|
|
|
end
|
|
|
end
|
|
|
- for mac in pairs(state.clients) do
|
|
|
+ for mac, info in pairs(state.clients) do
|
|
|
if not current_clients[mac] then
|
|
|
- log_info("WiFi DISCONNECTED: " .. mac)
|
|
|
- send_event("wifi_disconnected", '{"mac":"' .. mac .. '"}')
|
|
|
+ log_info("WiFi DISCONNECTED: " .. mac .. " from " .. info.ssid)
|
|
|
+ send_event("wifi_disconnected", '{"mac":"' .. mac .. '","ssid":"' .. info.ssid .. '","interface":"' .. info.iface .. '"}')
|
|
|
end
|
|
|
end
|
|
|
state.clients = current_clients
|
|
|
@@ -198,14 +224,16 @@ function main()
|
|
|
|
|
|
for iface in pairs(current_ssid) do
|
|
|
if not state.ssid_enabled[iface] then
|
|
|
- log_info("SSID ENABLED: " .. iface)
|
|
|
- send_event("ssid_enabled", '{"interface":"' .. iface .. '"}')
|
|
|
+ local ssid = get_ssid_name(iface)
|
|
|
+ log_info("SSID ENABLED: " .. ssid .. " (" .. iface .. ")")
|
|
|
+ send_event("ssid_enabled", '{"interface":"' .. iface .. '","ssid":"' .. ssid .. '"}')
|
|
|
end
|
|
|
end
|
|
|
for iface in pairs(state.ssid_enabled) do
|
|
|
if not current_ssid[iface] then
|
|
|
- log_info("SSID DISABLED: " .. iface)
|
|
|
- send_event("ssid_disabled", '{"interface":"' .. iface .. '"}')
|
|
|
+ local ssid = get_ssid_name(iface)
|
|
|
+ log_info("SSID DISABLED: " .. ssid .. " (" .. iface .. ")")
|
|
|
+ send_event("ssid_disabled", '{"interface":"' .. iface .. '","ssid":"' .. ssid .. '"}')
|
|
|
end
|
|
|
end
|
|
|
state.ssid_enabled = current_ssid
|