BWM and static ARP optimizations
[tomato.git] / release / src / router / www / tools-survey.asp
blob9e745db0b7fcbb0f34ec7acd01539c829ce29d03
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 <!-- / / / -->
20 <style type='text/css'>
21 #survey-grid .brate {
22 color: blue;
24 #survey-grid .grate {
25 color: green;
27 #survey-grid .co4,
28 #survey-grid .co5 {
29 text-align: right;
31 #survey-grid .co6,
32 #survey-grid .co7 {
33 text-align: center;
35 #survey-msg {
36 border: 1px dashed #f0f0f0;
37 background: #fefefe;
38 padding: 5px;
39 width: 300px;
40 position: absolute;
42 #survey-controls {
43 text-align: right;
45 #expire-time {
46 width: 120px;
48 </style>
50 <script type='text/javascript' src='debug.js'></script>
52 <script type='text/javascript'>
53 // <% nvram(''); %> // http_id
55 var wlscandata = [];
56 var entries = [];
57 var dayOfWeek = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
59 Date.prototype.toWHMS = function() {
60 return dayOfWeek[this.getDay()] + ' ' + this.getHours() + ':' + this.getMinutes().pad(2)+ ':' + this.getSeconds().pad(2);
63 var sg = new TomatoGrid();
65 sg.sortCompare = function(a, b) {
66 var col = this.sortColumn;
67 var da = a.getRowData();
68 var db = b.getRowData();
69 var r;
71 switch (col) {
72 case 0:
73 r = -cmpDate(da.lastSeen, db.lastSeen);
74 break;
75 case 3:
76 r = cmpInt(da.rssi, db.rssi);
77 break;
78 case 4:
79 r = cmpInt(da.noise, db.noise);
80 break;
81 case 5:
82 r = cmpInt(da.qual, db.qual);
83 break;
84 case 6:
85 r = cmpInt(da.channel, db.channel);
86 break;
87 default:
88 r = cmpText(a.cells[col].innerHTML, b.cells[col].innerHTML);
90 if (r == 0) r = cmpText(da.bssid, db.bssid);
92 return this.sortAscending ? r : -r;
95 sg.rateSorter = function(a, b)
97 if (a < b) return -1;
98 if (a > b) return 1;
99 return 0;
102 sg.populate = function()
104 var caps = ['infra', 'adhoc', 'poll', 'pollreq', 'wep', 'shortpre', 'pbcc', 'agility', 'X', 'Y', 'shortslot'];
105 var ncap = '802.11n';
106 var added = 0;
107 var removed = 0;
108 var i, j, k, t, e, s;
110 if ((wlscandata.length == 1) && (!wlscandata[0][0])) {
111 setMsg("error: " + wlscandata[0][1]);
112 return;
115 for (i = 0; i < wlscandata.length; ++i) {
116 s = wlscandata[i];
117 e = null;
119 for (j = 0; j < entries.length; ++j) {
120 if (entries[j].bssid == s[0]) {
121 e = entries[j];
122 break;
125 if (!e) {
126 ++added;
127 e = {};
128 e.firstSeen = new Date();
129 entries.push(e);
131 e.lastSeen = new Date();
132 e.bssid = s[0];
133 e.ssid = s[1];
134 e.channel = s[2];
135 e.rssi = s[4];
136 e.noise = s[5];
137 e.saw = 1;
139 t = '';
140 k = 0;
141 for (j = 0; j < caps.length; ++j) {
142 if ((s[3] & (1 << j)) && (caps[j])) {
143 k += caps[j].length;
144 if (k > 12) {
145 t += '<br>';
146 k = caps[j].length;
148 else t += ' ';
149 t += caps[j];
152 if (s[7] != 0) {
153 k += ncap.length;
154 t += ((k > 12) ? '<br>' : ' ') + ncap;
156 e.cap = t;
158 t = '';
159 var rb = [];
160 var rg = [];
161 for (j = 0; j < s[6].length; ++j) {
162 var x = s[6][j];
163 var r = (x & 0x7F) / 2;
164 if (x & 0x80) rb.push(r);
165 else rg.push(r);
167 rb.sort(this.rateSorter);
168 rg.sort(this.rateSorter);
170 t = '';
171 if (rb.length) t = '<span class="brate">' + rb.join(',') + '</span>';
172 if (rg.length) {
173 if (rb.length) t += '<br>';
174 t +='<span class="grate">' + rg.join(',') + '</span>';
176 e.rates = t;
179 t = E('expire-time').value;
180 if (t > 0) {
181 var cut = (new Date()).getTime() - (t * 1000);
182 for (i = 0; i < entries.length; ) {
183 if (entries[i].lastSeen.getTime() < cut) {
184 entries.splice(i, 1);
185 ++removed;
187 else ++i;
191 for (i = 0; i < entries.length; ++i) {
192 var seen, m, mac;
194 e = entries[i];
196 if (!e.saw) {
197 e.rssi = MAX(e.rssi - 5, -101);
198 e.noise = MAX(e.noise - 2, -101);
199 if ((e.rssi == -101) || (e.noise == -101))
200 e.noise = e.rssi = -999;
202 e.saw = 0;
204 e.qual = MAX(e.rssi - e.noise, 0);
206 seen = e.lastSeen.toWHMS();
207 if (useAjax()) {
208 m = Math.floor(((new Date()).getTime() - e.firstSeen.getTime()) / 60000);
209 if (m <= 10) seen += '<br> <b><small>NEW (' + -m + 'm)</small></b>';
212 mac = e.bssid;
213 if (mac.match(/^(..):(..):(..)/))
214 mac = '<a href="http://standards.ieee.org/cgi-bin/ouisearch?' + RegExp.$1 + '-' + RegExp.$2 + '-' + RegExp.$3 + '" target="_new" title="OUI search">' + mac + '</a>';
216 sg.insert(-1, e, [
217 '<small>' + seen + '</small>',
218 '' + e.ssid,
219 mac,
220 (e.rssi == -999) ? '' : (e.rssi + ' <small>dBm</small>'),
221 (e.noise == -999) ? '' : (e.noise + ' <small>dBm</small>'),
222 '<small>' + e.qual + '</small> <img src="bar' + MIN(MAX(Math.floor(e.qual / 10), 1), 6) + '.gif">',
223 '' + e.channel,
224 '' + e.cap,
225 '' + e.rates], false);
228 s = '';
229 if (useAjax()) s = added + ' added, ' + removed + ' removed, ';
230 s += entries.length + ' total.';
232 s += '<br><br><small>Last updated: ' + (new Date()).toWHMS() + '</small>';
233 setMsg(s);
235 wlscandata = [];
238 sg.setup = function() {
239 this.init('survey-grid', 'sort');
240 this.headerSet(['Last Seen', 'SSID', 'BSSID', 'RSSI &nbsp; &nbsp; ', 'Noise &nbsp; &nbsp; ', 'Quality', 'Ch', 'Capabilities', 'Rates']);
241 this.populate();
242 this.sort(0);
246 function setMsg(msg)
248 E('survey-msg').innerHTML = msg;
252 var ref = new TomatoRefresh('update.cgi', 'exec=wlscan', 0, 'tools_survey_refresh');
254 ref.refresh = function(text)
256 try {
257 eval(text);
259 catch (ex) {
260 return;
262 sg.removeAllData();
263 sg.populate();
264 sg.resort();
267 function earlyInit()
269 if (!useAjax()) E('expire-time').style.visibility = 'hidden';
270 sg.setup();
273 function init()
275 sg.recolor();
276 ref.initPage();
278 </script>
279 </head>
280 <body onload='init()'>
281 <form action='javascript:{}'>
282 <table id='container' cellspacing=0>
283 <tr><td colspan=2 id='header'>
284 <div class='title'>Tomato</div>
285 <div class='version'>Version <% version(); %></div>
286 </td></tr>
287 <tr id='body'><td id='navi'><script type='text/javascript'>navi()</script></td>
288 <td id='content'>
289 <div id='ident'><% ident(); %></div>
291 <!-- / / / -->
293 <div class='section-title'>Wireless Site Survey</div>
294 <div class='section'>
295 <table id='survey-grid' class='tomato-grid' cellspacing=0></table>
296 <div id='survey-msg'></div>
297 <div id='survey-controls'>
298 <img src="spin.gif" id="refresh-spinner">
299 <script type='text/javascript'>
300 genStdTimeList('expire-time', 'Auto Expire', 1);
301 genStdTimeList('refresh-time', 'Auto Refresh', 1);
302 </script>
303 <input type="button" value="Refresh" onclick="ref.toggle()" id="refresh-button">
304 </div>
306 <br><br><br><br>
307 <script type='text/javascript'>
308 if ('<% wlclient(); %>' == '0') {
309 document.write('<small>Warning: Wireless connections to this router may be disrupted while using this tool.</small>');
311 </script>
312 </div>
314 <!-- / / / -->
316 </td></tr>
317 <tr><td id='footer' colspan=2>&nbsp;</td></tr>
318 </table>
319 </form>
320 <script type='text/javascript'>earlyInit();</script>
321 </body>
322 </html>