1 <!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML
4.0//EN'
>
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.
12 <meta http-equiv='content-type' content='text/html;charset=utf-
8'
>
13 <meta name='robots' content='noindex,nofollow'
>
14 <meta name=
"viewport" content=
"width=device-width">
15 <title>[<%
ident(); %>] Tools: Wireless Survey
</title>
16 <link rel='stylesheet' type='text/css' href='tomato.css'
>
17 <link rel='stylesheet' type='text/css' href='color.css'
>
18 <script type='text/javascript' src='tomato.js'
></script>
21 <style type='text/css'
>
37 border: 1px dashed
#f0f0f0;
51 <script type='text/javascript' src='debug.js'
></script>
53 <script type='text/javascript'
>
54 // <% nvram(''); %> // http_id
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();
74 r
= -cmpDate(da
.lastSeen
, db
.lastSeen
);
77 r
= cmpInt(da
.rssi
, db
.rssi
);
80 r
= cmpInt(da
.noise
, db
.noise
);
83 r
= cmpInt(da
.qual
, db
.qual
);
86 r
= cmpInt(da
.channel
, db
.channel
);
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
)
103 sg
.populate = function()
105 var caps
= ['infra', 'adhoc', 'poll', 'pollreq', 'wep', 'shortpre', 'pbcc', 'agility', 'X', 'Y', 'shortslot'];
106 var ncap
= '802.11n';
109 var i
, j
, k
, t
, e
, s
;
111 if ((wlscandata
.length
== 1) && (!wlscandata
[0][0])) {
112 setMsg("error: " + wlscandata
[0][1]);
116 for (i
= 0; i
< wlscandata
.length
; ++i
) {
120 for (j
= 0; j
< entries
.length
; ++j
) {
121 if (entries
[j
].bssid
== s
[0]) {
129 e
.firstSeen
= new Date();
132 e
.lastSeen
= new Date();
142 for (j
= 0; j
< caps
.length
; ++j
) {
143 if ((s
[3] & (1 << j
)) && (caps
[j
])) {
155 t
+= ((k
> 12) ? '<br>' : ' ') + ncap
;
162 for (j
= 0; j
< s
[6].length
; ++j
) {
164 var r
= (x
& 0x7F) / 2;
165 if (x
& 0x80) rb
.push(r
);
168 rb
.sort(this.rateSorter
);
169 rg
.sort(this.rateSorter
);
172 if (rb
.length
) t
= '<span class="brate">' + rb
.join(',') + '</span>';
174 if (rb
.length
) t
+= '<br>';
175 t
+='<span class="grate">' + rg
.join(',') + '</span>';
180 t
= E('expire-time').value
;
182 var cut
= (new Date()).getTime() - (t
* 1000);
183 for (i
= 0; i
< entries
.length
; ) {
184 if (entries
[i
].lastSeen
.getTime() < cut
) {
185 entries
.splice(i
, 1);
192 for (i
= 0; i
< entries
.length
; ++i
) {
198 e
.rssi
= MAX(e
.rssi
- 5, -101);
199 e
.noise
= MAX(e
.noise
- 2, -101);
200 if ((e
.rssi
== -101) || (e
.noise
== -101))
201 e
.noise
= e
.rssi
= -999;
205 e
.qual
= MAX(e
.rssi
- e
.noise
, 0);
207 seen
= e
.lastSeen
.toWHMS();
209 m
= Math
.floor(((new Date()).getTime() - e
.firstSeen
.getTime()) / 60000);
210 if (m
<= 10) seen
+= '<br> <b><small>NEW (' + -m
+ 'm)</small></b>';
214 if (mac
.match(/^(..):(..):(..)/))
215 mac
= '<a href="http://api.macvendors.com/' + RegExp
.$1 + '-' + RegExp
.$2 + '-' + RegExp
.$3 + '" target="_new" title="OUI Search">' + mac
+ '</a>';
218 '<small>' + seen
+ '</small>',
221 (e
.rssi
== -999) ? '' : (e
.rssi
+ ' <small>dBm</small>'),
222 (e
.noise
== -999) ? '' : (e
.noise
+ ' <small>dBm</small>'),
223 '<small>' + e
.qual
+ '</small> <img src="bar' + MIN(MAX(Math
.floor(e
.qual
/ 10), 1), 6) + '.gif">',
226 '' + e
.rates
], false);
230 if (useAjax()) s
= added
+ ' added, ' + removed
+ ' removed, ';
231 s
+= entries
.length
+ ' total.';
233 s
+= '<br><br><small>Last updated: ' + (new Date()).toWHMS() + '</small>';
239 sg
.setup = function() {
240 this.init('survey-grid', 'sort');
241 this.headerSet(['Last Seen', 'SSID', 'BSSID', 'RSSI ', 'Noise ', 'Quality', 'Ch', 'Capabilities', 'Rates']);
249 E('survey-msg').innerHTML
= msg
;
253 var ref
= new TomatoRefresh('update.cgi', 'exec=wlscan', 0, 'tools_survey_refresh');
255 ref
.refresh = function(text
)
270 if (!useAjax()) E('expire-time').style
.visibility
= 'hidden';
281 <body onload='init()'
>
282 <form action='javascript:{}'
>
283 <table id='container' cellspacing=
0>
284 <tr><td colspan=
2 id='header'
>
285 <div class='title'
>Tomato
</div>
286 <div class='version'
>Version <%
version(); %></div>
288 <tr id='body'
><td id='navi'
><script type='text/javascript'
>navi()</script></td>
290 <div id='ident'
><%
ident(); %></div>
294 <div class='section-title'
>Wireless Site Survey
</div>
295 <div class='section'
>
296 <table id='survey-grid' class='tomato-grid' cellspacing=
0></table>
297 <div id='survey-msg'
></div>
298 <div id='survey-controls'
>
299 <img src=
"spin.gif" id=
"refresh-spinner">
300 <script type='text/javascript'
>
301 genStdTimeList('expire-time', 'Auto Expire', 0);
302 genStdTimeList('refresh-time', 'Auto Refresh', 0);
304 <input type=
"button" value=
"Refresh" onclick=
"ref.toggle()" id=
"refresh-button">
308 <script type='text/javascript'
>
309 if ('<% wlclient(); %>' == '0') {
310 document
.write('<small>Warning: Wireless connections to this router may be disrupted while using this tool.</small>');
318 <tr><td id='footer' colspan=
2> </td></tr>
321 <script type='text/javascript'
>earlyInit();</script>