mirror of https://github.com/aredn/aredn.git
Scan cache (#1160)
* Cache the last wifi scan and update it when a re-scan is requested. This change was suggested as a way of handling Ubiquiti AC devices which disconnect while scanning and making retrieving the results problematic if that was your connection. Now we scan and store the results so they can be retrieved later. In fact we no longer scan when navigating to this page but require an explicity scan button push. This make the page generally more responsive when initially navigated to.
This commit is contained in:
parent
c25be28b97
commit
86271040a0
|
@ -36,6 +36,7 @@
|
|||
--]]
|
||||
|
||||
require("nixio")
|
||||
require("luci.jsonc")
|
||||
require("aredn.http")
|
||||
require("aredn.hardware")
|
||||
require("aredn.utils")
|
||||
|
@ -55,19 +56,32 @@ if board_type:match("^ubnt,") and board_type:match("ac") then
|
|||
ubnt_ac = true
|
||||
end
|
||||
|
||||
local channels = aredn.hardware.get_rfchannels(wifiiface)
|
||||
local scan_list = ""
|
||||
for _, channel in ipairs(channels)
|
||||
do
|
||||
scan_list = scan_list .. " " .. channel.frequency
|
||||
local rescan = string.find((nixio.getenv("QUERY_STRING") or ""):lower(),"rescan=1")
|
||||
|
||||
local scanlist = {}
|
||||
-- Show the last scan if we have one, it's not too old, and we're not rescanning
|
||||
if not rescan then
|
||||
local lscan = io.open("/tmp/last-scan.json")
|
||||
if lscan then
|
||||
scanlist = luci.jsonc.parse(lscan:read("*a") or "")
|
||||
lscan:close()
|
||||
end
|
||||
end
|
||||
|
||||
-- scan start
|
||||
if rescan then
|
||||
local channels = aredn.hardware.get_rfchannels(wifiiface)
|
||||
local scan_list = ""
|
||||
for _, channel in ipairs(channels)
|
||||
do
|
||||
scan_list = scan_list .. " " .. channel.frequency
|
||||
end
|
||||
|
||||
local scanned = {}
|
||||
-- scan start
|
||||
|
||||
local f = io.popen("iw dev " .. wifiiface .. " station dump")
|
||||
if f then
|
||||
local scanned = {}
|
||||
|
||||
local f = io.popen("iw dev " .. wifiiface .. " station dump")
|
||||
if f then
|
||||
local scan = {}
|
||||
local myssid = aredn.info.getSSID()
|
||||
for line in f:lines()
|
||||
|
@ -87,7 +101,7 @@ if f then
|
|||
end
|
||||
scan.mode = "Connected Ad-Hoc Station"
|
||||
scan.ssid = myssid
|
||||
scan.freq[myfreq] = true
|
||||
scan.freq[tostring(myfreq)] = true
|
||||
end
|
||||
m = line:match("signal avg:%s+([%d%-]+)")
|
||||
if m then
|
||||
|
@ -95,10 +109,10 @@ if f then
|
|||
end
|
||||
end
|
||||
f:close()
|
||||
end
|
||||
end
|
||||
|
||||
-- Ubiquiti AC device workaround
|
||||
if ubnt_ac then
|
||||
-- Ubiquiti AC device workaround
|
||||
if ubnt_ac then
|
||||
os.execute("iw dev " .. wifiiface .. " ibss leave > /dev/null 2>&1")
|
||||
os.execute("wifi up > /dev/null 2>&1")
|
||||
local attempt = 10
|
||||
|
@ -114,10 +128,10 @@ if ubnt_ac then
|
|||
end
|
||||
nixio.nanosleep(2, 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local f = io.popen("iw dev " .. wifiiface .. " scan freq" .. scan_list .. " passive")
|
||||
if f then
|
||||
local f = io.popen("iw dev " .. wifiiface .. " scan freq" .. scan_list .. " passive")
|
||||
if f then
|
||||
local scan = {}
|
||||
for line in f:lines()
|
||||
do
|
||||
|
@ -170,69 +184,26 @@ if f then
|
|||
end
|
||||
end
|
||||
f:close()
|
||||
end
|
||||
end
|
||||
|
||||
-- scan end
|
||||
-- scan end
|
||||
|
||||
-- generate page
|
||||
http_header()
|
||||
html.header(node .. " WiFi scan", false)
|
||||
local autoscan = string.find((nixio.getenv("QUERY_STRING") or ""):lower(),"autoscan=1")
|
||||
if autoscan then
|
||||
html.print("<script>setTimeout(function(){ window.location.reload(); }, 10000);</script>")
|
||||
end
|
||||
html.print([[
|
||||
<script src="/js/sorttable-min.js"></script>
|
||||
<style>
|
||||
table {
|
||||
border-collapse:collapse;
|
||||
}
|
||||
table.sortable thead {
|
||||
background-color:#eee;
|
||||
color:#666666;
|
||||
font-weight: bold;
|
||||
cursor: default;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body><form method=post action=/cgi-bin/scan enctype='multipart/form-data'>
|
||||
<center>
|
||||
]])
|
||||
|
||||
html.alert_banner()
|
||||
html.print("<h1>" .. node .. " WiFi scan</h1><hr>")
|
||||
|
||||
if autoscan then
|
||||
html.print("<input type=button name=stop value=Stop title='Abort continuous scan' onclick='window.location = window.location.origin + window.location.pathname'>")
|
||||
else
|
||||
html.print("<input type=button name=refresh value=Refresh title='Refresh this page' onclick='window.location.reload();'>")
|
||||
html.print(" ")
|
||||
html.print([[<input type=button name=auto value=Auto title='Begin continuous scan' onclick='window.location = window.location.origin + window.location.pathname + "?autoscan=1"'>]])
|
||||
end
|
||||
|
||||
html.print(" ")
|
||||
html.print("<button type=button onClick='window.location=\"status\"' title='Return to status page'>Quit</button><br><br>")
|
||||
|
||||
-- display scan
|
||||
html.print("<table class=sortable border=1 cellpadding=5>")
|
||||
html.print("<tr><th>SNR</th><th>Signal</th><th>Chan</th><th>Enc</th><th>SSID</th><th>Hostname</th><th>MAC/BSSID</th><th>802.11 Mode</th></tr>")
|
||||
|
||||
-- load arp cache
|
||||
local arpcache = {}
|
||||
arptable(function(a)
|
||||
-- load arp cache
|
||||
local arpcache = {}
|
||||
arptable(function(a)
|
||||
arpcache[a["HW address"]] = a["IP address"]
|
||||
end)
|
||||
end)
|
||||
|
||||
local scanlist = {}
|
||||
for _, v in pairs(scanned)
|
||||
do
|
||||
scanlist = {}
|
||||
for _, v in pairs(scanned)
|
||||
do
|
||||
if v.signal ~= 9999 or v.joined then
|
||||
scanlist[#scanlist + 1] = v
|
||||
end
|
||||
end
|
||||
table.sort(scanlist, function(a, b) return a.signal > b.signal end)
|
||||
for _, scan in ipairs(scanlist)
|
||||
do
|
||||
end
|
||||
table.sort(scanlist, function(a, b) return a.signal > b.signal end)
|
||||
for _, scan in ipairs(scanlist)
|
||||
do
|
||||
-- freq to chan
|
||||
local chan = {}
|
||||
for f, _ in pairs(scan.freq)
|
||||
|
@ -255,39 +226,120 @@ do
|
|||
end
|
||||
end
|
||||
table.sort(chan)
|
||||
chan = table.concat(chan, " ")
|
||||
scan.chan = table.concat(chan, " ")
|
||||
if scan.joined then
|
||||
hostname = node
|
||||
scan.hostname = node
|
||||
else
|
||||
-- ip lookup then host lookup
|
||||
local ip = arpcache[scan.mac]
|
||||
if ip then
|
||||
hostname = ip
|
||||
scan.hostname = ip
|
||||
local f = io.popen("nslookup " .. ip)
|
||||
if f then
|
||||
for line in f:lines()
|
||||
do
|
||||
local m = line:match("name = (.*)%.local%.mesh")
|
||||
if m then
|
||||
hostname = m:gsub("^mid[0-9]*%.",""):gsub("^dtdlink%.",""):gsub("%.local%.mesh$","")
|
||||
scan.hostname = m:gsub("^mid[0-9]*%.",""):gsub("^dtdlink%.",""):gsub("%.local%.mesh$","")
|
||||
break
|
||||
end
|
||||
end
|
||||
f:close()
|
||||
end
|
||||
else
|
||||
hostname = "-"
|
||||
scan.hostname = "-"
|
||||
end
|
||||
end
|
||||
end
|
||||
lscan = io.open("/tmp/last-scan.json", "w")
|
||||
if lscan then
|
||||
lscan:write(luci.jsonc.stringify(scanlist, true))
|
||||
lscan:close()
|
||||
end
|
||||
end
|
||||
|
||||
-- generate page
|
||||
http_header()
|
||||
html.header(node .. " WiFi scan", false)
|
||||
local autoscan = string.find((nixio.getenv("QUERY_STRING") or ""):lower(),"autoscan=1")
|
||||
if autoscan then
|
||||
html.print("<script>setTimeout(function(){ window.location.reload(); }, 10000);</script>")
|
||||
end
|
||||
if rescan then
|
||||
html.print([[
|
||||
<script>
|
||||
if (history.replaceState) {
|
||||
history.replaceState(null, "", window.location.origin + window.location.pathname)
|
||||
}
|
||||
</script>
|
||||
]])
|
||||
end
|
||||
html.print([[
|
||||
<script src="/js/sorttable-min.js"></script>
|
||||
<style>
|
||||
table {
|
||||
border-collapse:collapse;
|
||||
}
|
||||
table.sortable thead {
|
||||
background-color:#eee;
|
||||
color:#666666;
|
||||
font-weight: bold;
|
||||
cursor: default;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
]])
|
||||
|
||||
html.alert_banner()
|
||||
html.print("<h1>" .. node .. " WiFi scan</h1><hr>")
|
||||
|
||||
if autoscan then
|
||||
html.print("<input type=button name=stop value=Stop title='Abort continuous scan' onclick='window.location = window.location.origin + window.location.pathname'>")
|
||||
else
|
||||
html.print([[<input type=button name=refresh value=Rescan title='Run a new scan' onclick='window.location = window.location.origin + window.location.pathname + "?rescan=1"'>]])
|
||||
if not ubnt_ac then
|
||||
html.print(" ")
|
||||
html.print([[<input type=button name=auto value=Auto title='Begin continuous scan' onclick='window.location = window.location.origin + window.location.pathname + "?autoscan=1"'>]])
|
||||
end
|
||||
end
|
||||
|
||||
html.print(" ")
|
||||
html.print("<button type=button onClick='window.location=\"status\"' title='Return to status page'>Quit</button><br><br>")
|
||||
|
||||
-- display scan
|
||||
html.print("<table class=sortable border=1 cellpadding=5>")
|
||||
html.print("<tr><th>SNR</th><th>Signal</th><th>Chan</th><th>Enc</th><th>SSID</th><th>Hostname</th><th>MAC/BSSID</th><th>802.11 Mode</th></tr>")
|
||||
|
||||
for _, scan in ipairs(scanlist)
|
||||
do
|
||||
if scan.ssid:match("^AREDN-") then
|
||||
html.print("<tr class=\"wscan-row-node\">")
|
||||
else
|
||||
html.print("<tr>")
|
||||
end
|
||||
html.print("<td>" .. (scan.signal - nf) .. "</td><td>" .. scan.signal .. "</td><td>" .. chan .. "</td><td>" .. scan.key .. "</td><td>" .. scan.ssid .. "</td><td align=center>" .. hostname .. "</td><td>" .. scan.mac:upper() .. "</td><td>" .. scan.mode .. "</td>")
|
||||
html.print("<td>" .. (scan.signal - nf) .. "</td><td>" .. scan.signal .. "</td><td>" .. scan.chan .. "</td><td>" .. scan.key .. "</td><td>" .. scan.ssid .. "</td><td align=center>" .. scan.hostname .. "</td><td>" .. scan.mac:upper() .. "</td><td>" .. scan.mode .. "</td>")
|
||||
html.print("</tr>")
|
||||
end
|
||||
|
||||
html.print("</table><br></center>")
|
||||
html.print("</table><br>")
|
||||
local lastscan = nixio.fs.stat("/tmp/last-scan.json", "mtime")
|
||||
if lastscan then
|
||||
lastscan = os.time() - lastscan
|
||||
if lastscan == 1 then
|
||||
html.print("<div>Last scan: 1 second ago")
|
||||
elseif lastscan < 60 then
|
||||
html.print("<div>Last scan: " .. lastscan .. " seconds ago")
|
||||
elseif lastscan < 120 then
|
||||
html.print("<div>Last scan: 1 minute ago")
|
||||
elseif lastscan < 3600 then
|
||||
html.print("<div>Last scan: " .. math.floor(lastscan / 60) .. " minutes ago")
|
||||
else
|
||||
html.print("<div>Last scan: a long time ago")
|
||||
end
|
||||
else
|
||||
html.print("<div>Last scan: none")
|
||||
end
|
||||
html.footer()
|
||||
html.print("</body></html>")
|
||||
html.print("</center></body></html>")
|
||||
|
|
Loading…
Reference in New Issue