luci-base, luci-mod-admin-full: unify wifi assoclist code
authorJo-Philipp Wich <jo@mein.io>
Mon, 25 Jun 2018 07:01:33 +0000 (09:01 +0200)
committerJo-Philipp Wich <jo@mein.io>
Mon, 25 Jun 2018 07:01:33 +0000 (09:01 +0200)
Merge the assoclist code of the status overview and wireless overview pages
into a single shared partial template.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
modules/luci-base/luasrc/tools/status.lua
modules/luci-mod-admin-full/luasrc/view/admin_network/wifi_assoclist.htm [new file with mode: 0644]
modules/luci-mod-admin-full/luasrc/view/admin_network/wifi_overview.htm
modules/luci-mod-admin-full/luasrc/view/admin_status/index.htm

index 06a9ad41546ef5d7fc6b849af5ce7684cb9e560a..0059ccceb03100ef567f61bc989574c72a1f9c06 100644 (file)
@@ -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 (file)
index 0000000..f3e2313
--- /dev/null
@@ -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>&#160;(%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>
index 8cea5e7eaf2bb2d9d4cd30be9cfc6c5ae9c3de70..b9602785f4ae45a30f7883efaa13acdcfde86aac 100644 (file)
 
        var is_reconnecting = false;
 
-       function nowrap(s) {
-               return s.replace(/ /g, '&#160;');
-       }
-
-       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');
 
                {
                        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)
                                        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(
                                        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 />' +
                                                                                : '<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 : '?'
+                                               );
                                }
                        }
                }
 
        <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%>
index 7c4a5bfc98705ce391787b7becfa32126510e402..6083a8a2c538c2db4470b2b7581a2dd3f7a5b4ca 100644 (file)
                );
        }
 
-       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')
                        <% end %>
 
                        <% if has_wifi then %>
-                       var assoclist = [ ];
-
                        var ws = document.getElementById('wifi_status_table');
                        if (ws)
                        {
                                        {
                                                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)
                                                        '<%: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%>')));
                                        }
 
                                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>&#160;(%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;
 <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 %>