diff options
4 files changed, 165 insertions, 232 deletions
diff --git a/modules/luci-base/luasrc/tools/status.lua b/modules/luci-base/luasrc/tools/status.lua index 06a9ad4154..0059ccceb0 100644 --- a/modules/luci-base/luasrc/tools/status.lua +++ b/modules/luci-base/luasrc/tools/status.lua @@ -113,6 +113,11 @@ function wifi_networks() local net for _, net in ipairs(dev:get_wifinets()) do + local a, an = nil, 0 + for _, a in pairs(net:assoclist() or {}) do + an = an + 1 + end + rd.networks[#rd.networks+1] = { name = net:shortname(), link = net:adminlink(), @@ -128,10 +133,10 @@ function wifi_networks() noise = net:noise(), bitrate = net:bitrate(), ifname = net:ifname(), - assoclist = net:assoclist(), country = net:country(), txpower = net:txpower(), txpoweroff = net:txpower_offset(), + num_assoc = an, disabled = (dev:get("disabled") == "1" or net:get("disabled") == "1") } @@ -165,7 +170,6 @@ function wifi_network(id) noise = net:noise(), bitrate = net:bitrate(), ifname = net:ifname(), - assoclist = net:assoclist(), country = net:country(), txpower = net:txpower(), txpoweroff = net:txpower_offset(), @@ -182,6 +186,52 @@ function wifi_network(id) return { } end +function wifi_assoclist() + local sys = require "luci.sys" + local ntm = require "luci.model.network".init() + local hosts = sys.net.host_hints() + + local assoc = {} + local _, dev, net, bss + + for _, dev in ipairs(ntm:get_wifidevs()) do + local radioname = dev:get_i18n() + + for _, net in ipairs(dev:get_wifinets()) do + local netname = net:shortname() + local netlink = net:adminlink() + local ifname = net:ifname() + + for _, bss in pairs(net:assoclist() or {}) do + local host = hosts[_] + + bss.bssid = _ + bss.ifname = ifname + bss.radio = radioname + bss.name = netname + bss.link = netlink + + bss.host_name = (host) and (host.name or host.ipv4 or host.ipv6) + bss.host_hint = (host and host.name and (host.ipv4 or host.ipv6)) and (host.ipv4 or host.ipv6) + + assoc[#assoc+1] = bss + end + end + end + + table.sort(assoc, function(a, b) + if a.radio ~= b.radio then + return a.radio < b.radio + elseif a.ifname ~= b.ifname then + return a.ifname < b.ifname + else + return a.bssid < b.bssid + end + end) + + return assoc +end + function switch_status(devs) local dev local switches = { } diff --git a/modules/luci-mod-admin-full/luasrc/view/admin_network/wifi_assoclist.htm b/modules/luci-mod-admin-full/luasrc/view/admin_network/wifi_assoclist.htm new file mode 100644 index 0000000000..f3e2313ee6 --- /dev/null +++ b/modules/luci-mod-admin-full/luasrc/view/admin_network/wifi_assoclist.htm @@ -0,0 +1,84 @@ +<script type="text/javascript">//<![CDATA[ + function wifirate(bss, rx) { + var p = rx ? 'rx_' : 'tx_', + s = '%.1f <%:Mbit/s%>, %d<%:MHz%>' + .format(bss[p+'rate'] / 1000, bss[p+'mhz']), + ht = bss[p+'ht'], vht = bss[p+'vht'], + mhz = bss[p+'mhz'], nss = bss[p+'nss'], + mcs = bss[p+'mcs'], sgi = bss[p+'short_gi']; + + if (ht || vht) { + if (vht) s += ', VHT-MCS %d'.format(mcs); + if (nss) s += ', VHT-NSS %d'.format(nss); + if (ht) s += ', MCS %s'.format(mcs); + if (sgi) s += ', <%:Short GI%>'; + } + + return s; + } + + XHR.poll(5, '<%=url('admin/network/wireless_assoclist')%>', null, + function(x, st) + { + var tb = document.getElementById('wifi_assoclist_table'); + if (st && tb) + { + var rows = []; + + st.forEach(function(bss) { + var icon; + var q = (-1 * (bss.noise - bss.signal)) / 5; + if (q < 1) + icon = "<%=resource%>/icons/signal-0.png"; + else if (q < 2) + icon = "<%=resource%>/icons/signal-0-25.png"; + else if (q < 3) + icon = "<%=resource%>/icons/signal-25-50.png"; + else if (q < 4) + icon = "<%=resource%>/icons/signal-50-75.png"; + else + icon = "<%=resource%>/icons/signal-75-100.png"; + + rows.push([ + '<span class="ifacebadge" title="%q"><img src="<%=resource%>/icons/wifi.png" /> <a href="%s">%h</a><small> (%h)</small></span>'.format( + bss.radio, + bss.link, + bss.name, + bss.ifname), + bss.bssid, + bss.host_hint ? '%h (%h)'.format(bss.host_name || '?', bss.host_hint) : (bss.host_name || '?'), + '<span class="ifacebadge" title="<%:Signal%>: %d <%:dBm%> / <%:Noise%>: %d <%:dBm%> / <%:SNR%>: %d"><img src="%s" /> %d / %d <%:dBm%></span>'.format( + bss.signal, + bss.noise, + bss.signal - bss.noise, + icon, + bss.signal, + bss.noise), + E('span', {}, [ + E('span', wifirate(bss, true)), + E('br'), + E('span', wifirate(bss, false)) + ]) + ]); + }); + + cbi_update_table(tb, rows, '<em><%:No information available%></em>'); + } + } + ); +//]]></script> + +<div class="cbi-section-node"> + <div class="table" id="wifi_assoclist_table"> + <div class="tr table-titles"> + <div class="th nowrap"><%:Network%></div> + <div class="th hide-xs"><%:MAC-Address%></div> + <div class="th nowrap"><%:Host%></div> + <div class="th nowrap"><%:Signal%> / <%:Noise%></div> + <div class="th nowrap"><%:RX Rate%> / <%:TX Rate%></div> + </div> + <div class="tr placeholder"> + <div class="td"><em><%:Collecting data...%></em></div> + </div> + </div> +</div> diff --git a/modules/luci-mod-admin-full/luasrc/view/admin_network/wifi_overview.htm b/modules/luci-mod-admin-full/luasrc/view/admin_network/wifi_overview.htm index 8cea5e7eaf..b9602785f4 100644 --- a/modules/luci-mod-admin-full/luasrc/view/admin_network/wifi_overview.htm +++ b/modules/luci-mod-admin-full/luasrc/view/admin_network/wifi_overview.htm @@ -113,28 +113,6 @@ var is_reconnecting = false; - function nowrap(s) { - return s.replace(/ /g, ' '); - } - - function wifirate(bss, rx) { - var p = rx ? 'rx_' : 'tx_', - s = '%.1f <%:Mbit/s%>, %d<%:MHz%>' - .format(bss[p+'rate'] / 1000, bss[p+'mhz']), - ht = bss[p+'ht'], vht = bss[p+'vht'], - mhz = bss[p+'mhz'], nss = bss[p+'nss'], - mcs = bss[p+'mcs'], sgi = bss[p+'short_gi']; - - if (ht || vht) { - if (vht) s += ', VHT-MCS %d'.format(mcs); - if (nss) s += ', VHT-NSS %d'.format(nss); - if (ht) s += ', MCS %s'.format(mcs); - if (sgi) s += ', <%:Short GI%>'; - } - - return s; - } - function wifi_shutdown(id, toggle) { var reconnect = (toggle.getAttribute('active') == 'false'); @@ -193,20 +171,25 @@ { if (st) { - var assoctable = document.getElementById('iw-assoclist'); - if (assoctable) - while (assoctable.firstElementChild !== assoctable.lastElementChild) - assoctable.removeChild(assoctable.lastElementChild); - - var devup = { }; var rowstyle = 1; + var radiostate = { }; + + st.forEach(function(s) { + var r = radiostate[wifidevs[s.id]] || (radiostate[wifidevs[s.id]] = {}); + + s.is_assoc = (s.bssid && s.bssid != '00:00:00:00:00:00' && s.channel && s.mode != 'Unknown' && !s.disabled); + + r.up = r.up || s.is_assoc; + r.channel = r.channel || s.channel; + r.bitrate = r.bitrate || s.bitrate; + r.frequency = r.frequency || s.frequency; + }); for( var i = 0; i < st.length; i++ ) { var iw = st[i]; - var is_assoc = (iw.bssid && iw.bssid != '00:00:00:00:00:00' && iw.channel && iw.mode != 'Unknown' && !iw.disabled); var p = iw.quality; - var q = is_assoc ? p : -1; + var q = iw.is_assoc ? p : -1; var icon; if (q < 0) @@ -222,9 +205,6 @@ else icon = "<%=resource%>/icons/signal-75-100.png"; - if (!devup[wifidevs[iw.id]]) - devup[wifidevs[iw.id]] = is_assoc; - var sig = document.getElementById(iw.id + '-iw-signal'); if (sig) sig.innerHTML = String.format( @@ -254,7 +234,7 @@ var info = document.getElementById(iw.id + '-iw-status'); if (info) { - if (is_assoc) + if (iw.is_assoc) info.innerHTML = String.format( '<strong><%:SSID%>:</strong> %h | ' + '<strong><%:Mode%>:</strong> %s<br />' + @@ -274,83 +254,23 @@ : '<em><%:Wireless is disabled or not associated%></em>' ); } - - var dev = document.getElementById(wifidevs[iw.id] + '-iw-devinfo'); - if (dev) - { - if (is_assoc) - dev.innerHTML = String.format( - '<strong><%:Channel%>:</strong> %s (%s <%:GHz%>) | ' + - '<strong><%:Bitrate%>:</strong> %s <%:Mbit/s%>', - iw.channel ? iw.channel : '?', - iw.frequency ? iw.frequency : '?', - iw.bitrate ? iw.bitrate : '?' - ); - else - dev.innerHTML = ''; - } - - if (assoctable) - { - var assoclist = [ ]; - for (var bssid in iw.assoclist) - { - assoclist.push(iw.assoclist[bssid]); - assoclist[assoclist.length-1].bssid = bssid; - } - - assoclist.sort(function(a, b) { a.bssid < b.bssid }); - - for (var j = 0; j < assoclist.length; j++) - { - var icon; - var q = (-1 * (assoclist[j].noise - assoclist[j].signal)) / 5; - if (q < 1) - icon = "<%=resource%>/icons/signal-0.png"; - else if (q < 2) - icon = "<%=resource%>/icons/signal-0-25.png"; - else if (q < 3) - icon = "<%=resource%>/icons/signal-25-50.png"; - else if (q < 4) - icon = "<%=resource%>/icons/signal-50-75.png"; - else - icon = "<%=resource%>/icons/signal-75-100.png"; - - var host = hosts[assoclist[j].bssid], - name = host ? (host.name || host.ipv4 || host.ipv6) : null, - hint = (host && host.name && (host.ipv4 || host.ipv6)) ? (host.ipv4 || host.ipv6) : null; - - assoctable.appendChild(E('<div class="tr cbi-rowstyle-%d">'.format(rowstyle), [ - E('<div class="td"><span class="ifacebadge" title="%q"><img src="<%=resource%>/icons/wifi.png" /> %h</span></div>' - .format(iw.device.name, iw.ifname)), - E('<div class="td" style="white-space:nowrap">%h</div>' - .format(iw.ssid || '?')), - E('<div class="td">%h</div>' - .format(assoclist[j].bssid)), - E('<div class="td">', hint ? '<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis">%h (%h)</div>' - .format(name || '?', hint) : (name || '?')), - E('<div class="td"><span class="ifacebadge" title="<%:Signal%>: %d <%:dBm%> / <%:Noise%>: %d <%:dBm%> / <%:SNR%>: %d"><img src="%s" /> %d / %d <%:dBm%></span></div>' - .format(assoclist[j].signal, assoclist[j].noise, assoclist[j].signal - assoclist[j].noise, icon, assoclist[j].signal, assoclist[j].noise)), - E('<div class="td">', [ - E('<span style="white-space:nowrap">', wifirate(assoclist[j], true)), - E('<br />'), - E('<span style="white-space:nowrap">', wifirate(assoclist[j], false)) - ]) - ])); - - rowstyle = (rowstyle == 1) ? 2 : 1; - } - } } - if (assoctable && assoctable.firstElementChild === assoctable.lastElementChild) - assoctable.appendChild(E('<div class="tr cbi-section-table-row"><div class="td"><em><br /><%:No information available%></em></div></div>')); - - for (var dev in devup) + for (var dev in radiostate) { var img = document.getElementById(dev + '-iw-upstate'); if (img) - img.src = '<%=resource%>/icons/wifi' + (devup[dev] ? '' : '_disabled') + '.png'; + img.src = '<%=resource%>/icons/wifi' + (radiostate[dev].up ? '' : '_disabled') + '.png'; + + var stat = document.getElementById(dev + '-iw-devinfo'); + if (stat) + stat.innerHTML = String.format( + '<strong><%:Channel%>:</strong> %s (%s <%:GHz%>) | ' + + '<strong><%:Bitrate%>:</strong> %s <%:Mbit/s%>', + radiostate[dev].channel ? radiostate[dev].channel : '?', + radiostate[dev].frequency ? radiostate[dev].frequency : '?', + radiostate[dev].bitrate ? radiostate[dev].bitrate : '?' + ); } } } @@ -428,23 +348,7 @@ <h2><%:Associated Stations%></h2> - <div class="cbi-section-node"> - <div class="table" id="iw-assoclist"> - <div class="tr"> - <div class="th"><%:Interface%></div> - <div class="th"><%:SSID%></div> - <div class="th"><%:MAC-Address%></div> - <div class="th"><%:Host%></div> - <div class="th"><%:Signal%> / <%:Noise%></div> - <div class="th"><%:RX Rate%> / <%:TX Rate%></div> - </div> - <div class="tr cbi-rowstyle-2"> - <div class="td"> - <em><%:Collecting data...%></em> - </div> - </div> - </div> - </div> + <%+admin_network/wifi_assoclist%> </div> <%+footer%> diff --git a/modules/luci-mod-admin-full/luasrc/view/admin_status/index.htm b/modules/luci-mod-admin-full/luasrc/view/admin_status/index.htm index 7c4a5bfc98..6083a8a2c5 100644 --- a/modules/luci-mod-admin-full/luasrc/view/admin_status/index.htm +++ b/modules/luci-mod-admin-full/luasrc/view/admin_status/index.htm @@ -140,24 +140,6 @@ ); } - function wifirate(bss, rx) { - var p = rx ? 'rx_' : 'tx_', - s = '%.1f <%:Mbit/s%>, %d<%:MHz%>' - .format(bss[p+'rate'] / 1000, bss[p+'mhz']), - ht = bss[p+'ht'], vht = bss[p+'vht'], - mhz = bss[p+'mhz'], nss = bss[p+'nss'], - mcs = bss[p+'mcs'], sgi = bss[p+'short_gi']; - - if (ht || vht) { - if (vht) s += ', VHT-MCS %d'.format(mcs); - if (nss) s += ', VHT-NSS %d'.format(nss); - if (ht) s += ', MCS %s'.format(mcs); - if (sgi) s += ', <%:Short GI%>'; - } - - return s; - } - function duid2mac(duid) { // DUID-LLT / Ethernet if (duid.length === 28 && duid.substr(0, 8) === '00010001') @@ -402,8 +384,6 @@ <% end %> <% if has_wifi then %> - var assoclist = [ ]; - var ws = document.getElementById('wifi_status_table'); if (ws) { @@ -420,21 +400,6 @@ { var net = dev.networks[nidx]; var is_assoc = (net.bssid != '00:00:00:00:00:00' && net.channel && !net.disabled); - var num_assoc = 0; - - for (var bssid in net.assoclist) - { - var bss = net.assoclist[bssid]; - - bss.bssid = bssid; - bss.link = net.link; - bss.name = net.name; - bss.ifname = net.ifname; - bss.radio = dev.name; - - assoclist.push(bss); - num_assoc++; - } var icon; if (!is_assoc) @@ -457,7 +422,7 @@ '<%:Mode%>', net.mode, '<%:BSSID%>', is_assoc ? (net.bssid || '-') : null, '<%:Encryption%>', is_assoc ? net.encryption : null, - '<%:Associations%>', is_assoc ? (num_assoc || '-') : null, + '<%:Associations%>', is_assoc ? (net.num_assoc || '-') : null, null, is_assoc ? null : E('em', '<%:Wireless is disabled or not associated%>'))); } @@ -472,63 +437,6 @@ if (!ws.lastElementChild) ws.appendChild(E('<em><%:No information available%></em>')); } - - var ac = document.getElementById('wifi_assoc_table'); - if (ac) - { - var rows = []; - - assoclist.sort(function(a, b) { - return (a.name == b.name) - ? (a.bssid < b.bssid) - : (a.name > b.name ) - ; - }); - - for (var i = 0; i < assoclist.length; i++) - { - var icon; - var q = (-1 * (assoclist[i].noise - assoclist[i].signal)) / 5; - if (q < 1) - icon = "<%=resource%>/icons/signal-0.png"; - else if (q < 2) - icon = "<%=resource%>/icons/signal-0-25.png"; - else if (q < 3) - icon = "<%=resource%>/icons/signal-25-50.png"; - else if (q < 4) - icon = "<%=resource%>/icons/signal-50-75.png"; - else - icon = "<%=resource%>/icons/signal-75-100.png"; - - var host = hosts[assoclist[i].bssid], - name = host ? (host.name || host.ipv4 || host.ipv6) : null, - hint = (host && host.name && (host.ipv4 || host.ipv6)) ? (host.ipv4 || host.ipv6) : null; - - rows.push([ - '<span class="ifacebadge" title="%q"><img src="<%=resource%>/icons/wifi.png" /> <a href="%s">%h</a><small> (%h)</small></span>'.format( - assoclist[i].radio, - assoclist[i].link, - assoclist[i].name, - assoclist[i].ifname), - assoclist[i].bssid, - hint ? '%h (%h)'.format(name || '?', hint) : (name || '?'), - '<span class="ifacebadge" title="<%:Signal%>: %d <%:dBm%> / <%:Noise%>: %d <%:dBm%> / <%:SNR%>: %d"><img src="%s" /> %d / %d <%:dBm%></span>'.format( - assoclist[i].signal, - assoclist[i].noise, - assoclist[i].signal - assoclist[i].noise, - icon, - assoclist[i].signal, - assoclist[i].noise), - E('span', {}, [ - E('span', wifirate(assoclist[i], true)), - E('br'), - E('span', wifirate(assoclist[i], false)) - ]) - ]); - } - - cbi_update_table(ac, rows, '<em><%:No information available%></em>'); - } <% end %> var e; @@ -709,20 +617,7 @@ <div class="cbi-section"> <h3><%:Associated Stations%></h3> - <div class="cbi-section-node"> - <div class="table" id="wifi_assoc_table"> - <div class="tr table-titles"> - <div class="th nowrap"><%:Network%></div> - <div class="th hide-xs"><%:MAC-Address%></div> - <div class="th nowrap"><%:Host%></div> - <div class="th nowrap"><%:Signal%> / <%:Noise%></div> - <div class="th nowrap"><%:RX Rate%> / <%:TX Rate%></div> - </div> - <div class="tr"> - <div class="td" colspan="6"><em><br /><%:Collecting data...%></em></div> - </div> - </div> - </div> + <%+admin_network/wifi_assoclist%> </div> <% end %> |