Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / www / tools-survey.asp
blob45a39f03c28920b36618c55bb3b002350770ecfd
1 <!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.0//EN'>
2 <!--
3 Tomato GUI
4 Copyright (C) 2006-2010 Jonathan Zarate
5 http://www.polarcloud.com/tomato/
7 For use with Tomato Firmware only.
8 No part of this file may be used without permission.
9 -->
10 <html>
11 <head>
12 <meta http-equiv='content-type' content='text/html;charset=utf-8'>
13 <meta name='robots' content='noindex,nofollow'>
14 <title>[<% ident(); %>] Tools: Wireless Survey</title>
15 <link rel='stylesheet' type='text/css' href='tomato.css'>
16 <link rel='stylesheet' type='text/css' href='color.css'>
17 <script type='text/javascript' src='tomato.js'></script>
19 <!-- / / / -->
21 <style type='text/css'>
22 #survey-grid .brate {
23 color: blue;
25 #survey-grid .grate {
26 color: green;
28 #survey-grid .co4,
29 #survey-grid .co5 {
30 text-align: right;
32 #survey-grid .co6,
33 #survey-grid .co7 {
34 text-align: center;
36 #survey-msg {
37 border: 1px dashed #f0f0f0;
38 background: #fefefe;
39 padding: 5px;
40 width: 300px;
41 position: absolute;
43 #survey-controls {
44 text-align: right;
46 #expire-time {
47 width: 120px;
49 </style>
51 <script type='text/javascript' src='debug.js'></script>
53 <script type='text/javascript'>
54 // <% nvram(''); %> // http_id
56 var wlscandata = [];
57 var entries = [];
58 var dayOfWeek = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
60 Date.prototype.toWHMS = function() {
61 return dayOfWeek[this.getDay()] + ' ' + this.getHours() + ':' + this.getMinutes().pad(2)+ ':' + this.getSeconds().pad(2);
64 var sg = new TomatoGrid();
66 sg.sortCompare = function(a, b) {
67 var col = this.sortColumn;
68 var da = a.getRowData();
69 var db = b.getRowData();
70 var r;
72 switch (col) {
73 case 0:
74 r = -cmpDate(da.lastSeen, db.lastSeen);
75 break;
76 case 3:
77 r = cmpInt(da.rssi, db.rssi);
78 break;
79 case 4:
80 r = cmpInt(da.noise, db.noise);
81 break;
82 case 5:
83 r = cmpInt(da.qual, db.qual);
84 break;
85 case 6:
86 r = cmpInt(da.channel, db.channel);
87 break;
88 default:
89 r = cmpText(a.cells[col].innerHTML, b.cells[col].innerHTML);
91 if (r == 0) r = cmpText(da.bssid, db.bssid);
93 return this.sortAscending ? r : -r;
96 sg.rateSorter = function(a, b)
98 if (a < b) return -1;
99 if (a > b) return 1;
100 return 0;
103 sg.populate = function()
105 var caps = ['infra', 'adhoc', 'poll', 'pollreq', 'wep', 'shortpre', 'pbcc', 'agility', 'spectrum', null, 'shortslot', null, null, 'cck-ofdm'];
106 var ncaps = [null, null /*40MHz*/, null, null, 'gf', 'sgi20', 'sgi40', 'stbc'];
107 var ncap = '802.11n';
108 var cap_maxlen = 14;
109 var added = 0;
110 var removed = 0;
111 var i, j, k, t, e, s;
113 if ((wlscandata.length == 1) && (!wlscandata[0][0])) {
114 setMsg("error: " + wlscandata[0][1]);
115 return;
118 for (i = 0; i < wlscandata.length; ++i) {
119 s = wlscandata[i];
120 e = null;
122 for (j = 0; j < entries.length; ++j) {
123 if (entries[j].bssid == s[0]) {
124 e = entries[j];
125 break;
128 if (!e) {
129 ++added;
130 e = {};
131 e.firstSeen = new Date();
132 entries.push(e);
134 e.lastSeen = new Date();
135 e.bssid = s[0];
136 e.ssid = s[1];
137 e.channel = s[2];
138 if (s[7] != 0 && s[9] != 0) {
139 e.channel = e.channel + '<br><small>' + s[9] + ' MHz</small>';
141 e.rssi = s[4];
142 e.noise = s[5];
143 e.saw = 1;
145 t = '';
146 k = 0;
147 for (j = 0; j < caps.length; ++j) {
148 if ((s[3] & (1 << j)) && (caps[j])) {
149 k += caps[j].length;
150 if (k > cap_maxlen) {
151 t += '<br>';
152 k = caps[j].length;
154 else t += ' ';
155 t += caps[j];
159 if (s[7] != 0) {
160 k += ncap.length;
161 if (k > cap_maxlen) {
162 t += '<br>';
163 k = ncap.length;
165 else t += ' ';
166 t += ncap;
169 for (j = 0; j < ncaps.length; ++j) {
170 if ((s[8] & (1 << j)) && (ncaps[j])) {
171 k += ncaps[j].length;
172 if (k > cap_maxlen) {
173 t += '<br>';
174 k = ncaps[j].length;
176 else t += ' ';
177 t += ncaps[j];
181 e.cap = t;
183 t = '';
184 var rb = [];
185 var rg = [];
186 for (j = 0; j < s[6].length; ++j) {
187 var x = s[6][j];
188 var r = (x & 0x7F) / 2;
189 if (x & 0x80) rb.push(r);
190 else rg.push(r);
192 rb.sort(this.rateSorter);
193 rg.sort(this.rateSorter);
195 t = '';
196 if (rb.length) t = '<span class="brate">' + rb.join(',') + '</span>';
197 if (rg.length) {
198 if (rb.length) t += '<br>';
199 t +='<span class="grate">' + rg.join(',') + '</span>';
201 e.rates = t;
204 t = E('expire-time').value;
205 if (t > 0) {
206 var cut = (new Date()).getTime() - (t * 1000);
207 for (i = 0; i < entries.length; ) {
208 if (entries[i].lastSeen.getTime() < cut) {
209 entries.splice(i, 1);
210 ++removed;
212 else ++i;
216 for (i = 0; i < entries.length; ++i) {
217 var seen, m, mac;
219 e = entries[i];
221 if (!e.saw) {
222 e.rssi = MAX(e.rssi - 5, -101);
223 e.noise = MAX(e.noise - 2, -101);
224 if ((e.rssi == -101) || (e.noise == -101))
225 e.noise = e.rssi = -999;
227 e.saw = 0;
229 e.qual = MAX(e.rssi - e.noise, 0);
231 seen = e.lastSeen.toWHMS();
232 if (useAjax()) {
233 m = Math.floor(((new Date()).getTime() - e.firstSeen.getTime()) / 60000);
234 if (m <= 10) seen += '<br> <b><small>NEW (' + -m + 'm)</small></b>';
237 mac = e.bssid;
238 if (mac.match(/^(..):(..):(..)/))
239 mac = '<a href="http://standards.ieee.org/cgi-bin/ouisearch?' + RegExp.$1 + '-' + RegExp.$2 + '-' + RegExp.$3 + '" target="_new" title="OUI search">' + mac + '</a>';
241 sg.insert(-1, e, [
242 '<small>' + seen + '</small>',
243 '' + e.ssid,
244 mac,
245 (e.rssi == -999) ? '' : (e.rssi + ' <small>dBm</small>'),
246 (e.noise == -999) ? '' : (e.noise + ' <small>dBm</small>'),
247 '<small>' + e.qual + '</small> <img src="bar' + MIN(MAX(Math.floor(e.qual / 10), 1), 6) + '.gif">',
248 '' + e.channel,
249 '' + e.cap,
250 '' + e.rates], false);
253 s = '';
254 if (useAjax()) s = added + ' added, ' + removed + ' removed, ';
255 s += entries.length + ' total.';
257 s += '<br><br><small>Last updated: ' + (new Date()).toWHMS() + '</small>';
258 setMsg(s);
260 wlscandata = [];
263 sg.setup = function() {
264 this.init('survey-grid', 'sort');
265 this.headerSet(['Last Seen', 'SSID', 'BSSID', 'RSSI &nbsp; &nbsp; ', 'Noise &nbsp; &nbsp; ', 'Quality', 'Ch', 'Capabilities', 'Rates']);
266 this.populate();
267 this.sort(0);
271 function setMsg(msg)
273 E('survey-msg').innerHTML = msg;
277 var ref = new TomatoRefresh('update.cgi', 'exec=wlscan', 0, 'tools_survey_refresh');
279 ref.refresh = function(text)
281 try {
282 eval(text);
284 catch (ex) {
285 return;
287 sg.removeAllData();
288 sg.populate();
289 sg.resort();
292 function earlyInit()
294 if (!useAjax()) E('expire-time').style.visibility = 'hidden';
295 sg.setup();
298 function init()
300 sg.recolor();
301 ref.initPage();
303 </script>
304 </head>
305 <body onload='init()'>
306 <form action='javascript:{}'>
307 <table id='container' cellspacing=0>
308 <tr><td colspan=2 id='header'>
309 <div class='title'>Tomato</div>
310 <div class='version'>Version <% version(); %></div>
311 </td></tr>
312 <tr id='body'><td id='navi'><script type='text/javascript'>navi()</script></td>
313 <td id='content'>
314 <div id='ident'><% ident(); %></div>
316 <!-- / / / -->
318 <div class='section-title'>Wireless Site Survey</div>
319 <div class='section'>
320 <table id='survey-grid' class='tomato-grid' cellspacing=0></table>
321 <div id='survey-msg'></div>
322 <div id='survey-controls'>
323 <img src="spin.gif" id="refresh-spinner">
324 <script type='text/javascript'>
325 genStdTimeList('expire-time', 'Auto Expire', 1);
326 genStdTimeList('refresh-time', 'Auto Refresh', 1);
327 </script>
328 <input type="button" value="Refresh" onclick="ref.toggle()" id="refresh-button">
329 </div>
331 <br><br><br><br>
332 <script type='text/javascript'>
333 if ('<% wlclient(); %>' == '0') {
334 document.write('<small>Warning: Wireless connections to this router may be disrupted while using this tool.</small>');
336 </script>
337 </div>
339 <!-- / / / -->
341 </td></tr>
342 <tr><td id='footer' colspan=2>&nbsp;</td></tr>
343 </table>
344 </form>
345 <script type='text/javascript'>earlyInit();</script>
346 </body>
347 </html>