Advertisement
rs232

FreshTomato - wireless survey.asp

Apr 10th, 2024 (edited)
742
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <!DOCTYPE html>
  2. <html lang="en-GB">
  3. <head>
  4. <meta http-equiv="content-type" content="text/html;charset=utf-8">
  5. <meta name="robots" content="noindex,nofollow">
  6. <title>[<% ident(); %>] Tools: Wireless Survey</title>
  7. <link rel="stylesheet" type="text/css" href="tomato.css">
  8. <% css(); %>
  9. <script src="tomato.js"></script>
  10. <style>
  11. #ellipses2 { border: 1px solid #AAAAAA; }
  12. #ellipses5 { border: 1px solid #AAAAAA; }
  13. }
  14. </style>
  15. <script>
  16. // <% nvram("wl0_radio,wl1_radio,wl2_radio,wl0_nband,wl1_nband,wl2_nband,wl0_mode,wl1_mode,wl2_mode,wl0_closed,wl1_closed,wl2_closed,wl_ifname,wl_ifnames,wl0_ifname,wl1_ifname,wl2_ifname"); %>
  17. function internalWiFI(interface) {
  18.     return new Promise(function(resolve, reject) {
  19.         const cmd = new XmlHttp();
  20.         cmd.onCompleted = function(text, xml) {
  21.             const result = text.replace(/\x0a/g, ' '); // Replace newline characters
  22.             resolve(result); // Resolve the Promise with the result
  23.         };
  24.         cmd.onError = function(x) {
  25.             const error = 'ERROR: ' + x.replace(/\x0a/g, ' '); // Replace newline characters
  26.             reject(error); // Reject the Promise with the error
  27.         };
  28.         const c = '/usr/sbin/wl -i ' + interface + ' status';
  29.         // const c = '/usr/sbin/wl -i ' + interface + ' status | grep Chanspec | awk {\'print $4,$5\'} | grep -Eo \'[0-9]{1,3}\' ; /usr/sbin/wl -i ' + interface + ' status | grep -Eo \'noise:\ -[0-9]{2}\' | awk {\'print $2\'}';
  30.         cmd.post('shell.cgi', 'action=execute&command=' + encodeURIComponent(c.replace(/\r/g, '')));
  31.     });
  32. }
  33. var res0a, res1a, res2a;
  34. // var wl0_b, wl1_b, wl2_b, wl0_d, wl1_d, wl2_d, wl0_n, wl1_n, wl2_n, wl0_coc, wl1_coc, wl2_coc, wl0_cec, wl1_cec, wl2_cec, wl0_w, wl1_w, wl2_w;
  35. // var a;
  36. // var b;
  37. // var inta=nvram.wl0_ifname;
  38. // var intb=nvram.wl1_ifname;
  39. // var intc=nvram.wl2_ifname;
  40. // get list of interfaces from nvram
  41. // identify their frequencies based of _nband
  42. const delayPromise = new Promise(resolve => {
  43.     setTimeout(resolve, 1000);
  44. });
  45. var wl_i = []; //wl_i is an array containing the list of enabled interfaces
  46. if (nvram.wl_ifnames === '' ) {
  47. var interfaces = nvram.wl_ifname;
  48. wl_i[0] = interfaces;
  49. } else {
  50. var interfaces = nvram.wl_ifnames;
  51. wl_i = interfaces.split(/\s+/); //array
  52. }
  53.  
  54. // var wl_if = {};
  55. // var intBind0 = {};
  56. // var intBind1 = {};
  57. // var intBind2 = {};
  58. var wl0 = {
  59.             ifname: { value: nvram.wl0_ifname },
  60.             band:   { value: nvram.wl0_nband },
  61.             radio:  { value: nvram.wl0_radio },
  62.             mode:   { value: nvram.wl0_mode },
  63.             closed: { value: nvram.wl0_closed } }
  64. var wl1 = {
  65.             ifname: { value: nvram.wl1_ifname },
  66.             band:   { value: nvram.wl1_nband },
  67.             radio:  { value: nvram.wl1_radio },
  68.             mode:   { value: nvram.wl1_mode },
  69.             closed: { value: nvram.wl1_closed } }
  70. var wl2 = {
  71.             ifname: { value: nvram.wl2_ifname },
  72.             band:   { value: nvram.wl2_nband },
  73.             radio:  { value: nvram.wl2_radio },
  74.             mode:   { value: nvram.wl2_mode },
  75.             closed: { value: nvram.wl2_closed } }
  76.            
  77. // var ifw = { wl0, wl1, wl2, wl_i }
  78.  
  79. // console.log(wl_i);
  80.  
  81. //
  82. // for (let i = 0; i < wl_i.length; i++) {
  83. // if ('eth' + i + "_ifname)") === )
  84.     // console.log(wl_i[i]);
  85. // if ( eval("parseInt(" + 'nvram.wl' + i + "_nband)") === 1 && eval("parseInt(" + 'nvram.wl' + i + "_radio)") === 1) {
  86. // }
  87.     // if (eth[i].length === 0) {
  88. // }
  89. // console.log(intBind);
  90.  
  91.     // wl0: [nvram.wl0_ifname, nvram.wl0_radio, nvram.wl0_nband],
  92.     // wl1: [nvram.wl1_ifname, nvram.wl1_radio, nvram.wl0_nband],
  93.     // wl2: [nvram.wl2_ifname, nvram.wl2_radio, nvram.wl0_nband]
  94.  
  95.  
  96. // console.log(wl_i);
  97.  
  98. // console.log('inta = '+inta);
  99. // console.log('intb = '+intb);
  100. // console.log('a = '+a);
  101. // console.log('b = '+b);
  102. var res0 = internalWiFI(wl0.ifname.value);
  103. var res1 = internalWiFI(wl1.ifname.value);
  104. var res2 = internalWiFI(wl2.ifname.value);
  105. res0.then(function(res) {
  106.     res0a=res.replace(/\\x([0-9A-Fa-f]{2})/g, (match, p1) => String.fromCharCode(parseInt(p1, 16)));
  107. }).catch(function(error) {
  108.     console.error('Error fetching result for eth1:', error);
  109. });
  110. res1.then(function(res) {
  111.     res1a=res.replace(/\\x([0-9A-Fa-f]{2})/g, (match, p1) => String.fromCharCode(parseInt(p1, 16)));
  112. }).catch(function(error) {
  113.     console.error('Error fetching result for eth2:', error);
  114. });
  115. res2.then(function(res) {
  116.     res2a=res.replace(/\\x([0-9A-Fa-f]{2})/g, (match, p1) => String.fromCharCode(parseInt(p1, 16)));
  117. }).catch(function(error) {
  118.     console.error('Error fetching result for eth3:', error);
  119. });
  120. // var wl0_r = eval("parseInt(" + 'nvram.wl' + a + "_radio)");
  121. // // var wl0_c;
  122. // // var wl0_w;
  123. // // var wl0_n; // noise level
  124. // // var wl0_d = eval('nvram.wl' + a + '_ssid');
  125. // var wl0_m = eval('nvram.wl' + a + '_mode');
  126. // var wl0_h = eval('nvram.wl' + a + '_closed');
  127. // var wl1_r = eval("parseInt(" + 'nvram.wl' + b + "_radio)");
  128. // // var wl1_c;
  129. // // var wl1_d = eval('nvram.wl' + b + '_ssid');
  130. // var wl1_m = eval('nvram.wl' + b + '_mode');
  131. // var wl1_h = eval('nvram.wl' + b + '_closed');
  132. // // var wl1_n; // noise level
  133. // var wl2_r = parseInt(nvram.wl2_radio);
  134. // // var wl2_c;
  135. // // var wl2_d = nvram.wl2_ssid;
  136. // var wl2_m = nvram.wl2_mode;
  137. // var wl2_h = nvram.wl2_closed;
  138.  
  139. if (parseInt(nvram.wl0_nband) === 1) {
  140. // _nband = "1" ==> 5 GHz radio
  141. // _nband = "2" ==> 2,4 GHz radio
  142. // inta=nvram.wl0_ifname;
  143. // intb=nvram.wl1_ifname;
  144. // intc=nvram.wl2_ifname;
  145. const temp = wl0;
  146. wl0 = wl1;
  147. wl1 = temp;
  148. // var a = 1;
  149. // var b = 0;
  150. // var inta = 'eth2';
  151. // var intb = 'eth1';
  152. }
  153. // else {
  154. // var a = 0;
  155. // var b = 1;
  156. // var inta = 'eth1';
  157. // var intb = 'eth2';
  158. // }
  159.  
  160. // var wl2_n; // noise level
  161. var cprefix = 'tools_wlsurvey';
  162. const div24 = 21; // 2.4GHz horizontal divisions
  163. const div5 = 39; // 5GHz horizontal divisions
  164. const vdiv = 9; // Vertical divisions
  165. const vsize = 200; //absolute canvas height
  166. const hsize = 750; //absolute canvas width
  167. function hexToDecimal(hexColor) {
  168. hexColor = hexColor.replace('#', '');
  169. var red = parseInt(hexColor.substring(0, 2), 16);
  170. var green = parseInt(hexColor.substring(2, 4), 16);
  171. var blue = parseInt(hexColor.substring(4, 6), 16);
  172. // Return comma-separated decimal values
  173. return red + ', ' + green + ', ' + blue;
  174. }
  175. function redraw() {
  176. clearCanvas('ellipses2');
  177. clearCanvas('ellipses5');
  178. drawBoard('ellipses2');
  179. drawBoard('ellipses5');
  180. }
  181. function doit() {
  182. fillstyle = document.getElementById("fill-style").value;
  183. var ssidshow = document.getElementById("ssid-show").value;
  184. if (ssidlimit>40) { ssidlimit=40; }
  185. ssidlimit = document.getElementById("ssid-limit").value;
  186. sg.removeAllData();
  187. sg.populate(fillstyle, ssidshow);
  188. sg.resort();
  189. drawNoise('ellipses2');
  190. drawNoise('ellipses5');
  191. }
  192. var colors = [
  193.     "#FF0000", // Red
  194.     "#00FF00", // Lime
  195.     "#0000FF", // Blue
  196.     "#FFA500", // Orange
  197.     "#FF00FF", // Magenta
  198.     "#FFFF00", // Yellow
  199.     "#00FFFF", // Cyan
  200.     "#800080", // Purple
  201.     "#FF4500", // OrangeRed
  202.     "#32CD32", // LimeGreen
  203.     "#87CEEB", // SkyBlue
  204.     "#FF69B4", // HotPink
  205.     "#DC143C", // Crimson
  206.     "#00CED1", // DarkTurquoise
  207.     "#FF8C00", // DarkOrange
  208.     "#4169E1", // RoyalBlue
  209.     "#8A2BE2", // BlueViolet
  210.     "#FFD700", // Gold
  211.     "#ADFF2F", // GreenYellow
  212.     "#9400D3", // DarkViolet
  213.     "#7CFC00", // LawnGreen
  214.     "#8B008B", // DarkMagenta
  215.     "#20B2AA", // LightSeaGreen
  216.     "#800000", // Maroon
  217.     "#000080", // Navy
  218.     "#008000", // Green
  219.     "#008080", // Teal
  220.     "#808000", // Olive
  221.     "#800080", // Purple
  222.     "#800000", // Maroon
  223.     "#2E8B57", // SeaGreen
  224.     "#4682B4", // SteelBlue
  225.     "#808000", // Olive
  226.     "#FF1493", // DeepPink
  227.     "#00FFFF", // Aqua
  228.     "#008B8B", // DarkCyan
  229.     "#0000CD", // MediumBlue
  230.     "#D2691E", // Chocolate
  231.     "#800080", // Purple
  232.     "#20B2AA", // LightSeaGreen
  233.     "#556B2F" // DarkOliveGreen
  234. ];
  235. var wlscandata = [];
  236. var entries = [];
  237. var dayOfWeek = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
  238. var cmd = null;
  239. var ref = new TomatoRefresh('update.cgi', 'exec=wlscan', 0, 'tools_survey_refresh');
  240. ref.refresh = function(text) {
  241. try {
  242. eval(text);
  243. }
  244. catch (ex) {
  245. }
  246. doit();
  247. }
  248. var sg = new TomatoGrid();
  249. sg.setup = function() {
  250. this.init('survey-grid','sort');
  251. this.headerSet(['Last Seen','RGB','SSID','BSSID','RSSI<br>dBm','Quality','Ctrl/Centr<br>Channel','Security','802.11']);
  252. this.populate();
  253. this.sort(0);
  254. }
  255. function drawNoise(board) {
  256. var noise1;
  257. var noise2;
  258. var canvas  = document.getElementById(board);
  259. var ctx = canvas.getContext('2d');     
  260. if (wl0.radio.value == 1 && wl0.mode != 'sta' && board == 'ellipses2') {
  261. if (res0a !== null) { var noise = ((-wl0.noise-10) * (canvas.height/100) * (10/vdiv)); }
  262. var noiseV = Number(wl0.noise);
  263. }
  264. if (wl1.radio.value == 1 && wl1.mode != 'sta' && board == 'ellipses5') {
  265. res1=String(res1).replace(/\\x0a/g, ',').match(/\d+/g);
  266. if (res1a !== null) { var noise = ((-wl1.noise-10) * (canvas.height/100) * (10/vdiv)); }
  267. var noiseV = Number(wl1.noise);
  268. }
  269. if (wl2.radio.value == 1 && wl2.mode != 'sta' && board == 'ellipses5') {
  270. res2=String(res2).replace(/\\x0a/g, ',').match(/\d+/g);
  271. if (res2a !== null) { var noise = ((-wl2.noise-10) * (canvas.height/100) * (10/vdiv)); }
  272. var noiseV = Number(wl2.noise);
  273. }
  274. if (typeof noise1 !== 'undefined' && typeof noise2 !== 'undefined' ) {
  275.     console.log('noise1 : '+noise1);
  276.     console.log('noise2 : '+noise2);
  277.     var noise = Math.max(noise1,noise2);
  278.     console.log('result : '+noise);
  279. }
  280.         ctx.beginPath();
  281.         ctx.save();
  282.         // console.log('noise = '+noise);
  283.         if (noise != 0) {
  284.         ctx.lineWidth = 0.2;
  285.         ctx.moveTo(0, noise+1);
  286.         // ctx.lineTo(0, noise);
  287.         ctx.lineTo(canvas.width, noise+1);
  288.         ctx.strokeStyle = "rgba(80,0,0,0.5";   
  289.         ctx.stroke();      
  290.         ctx.fillStyle = "rgba(220,200,80,0.15";    
  291.         // ctx.fillStyle = "rgba(139,128,0,0.12";      
  292.         ctx.fillRect(0, noise, canvas.width, noise);
  293.         ctx.fillStyle = "#660000";
  294.         ctx.textBaseline = "center";
  295.         ctx.textAlign = "right";
  296.         ctx.fillText('noise '+noiseV, (canvas.width-14), noise);
  297.         ctx.fill();
  298.         }
  299.         ctx.restore();
  300.         ctx.closePath();   
  301.     }
  302. function drawEllipse(c=-100, m=20, q, col, ssid, noise, style, sshow)
  303.     {
  304.         if (c<35){ var canvas  = document.getElementById("ellipses2");
  305.         var ctx = canvas.getContext('2d');
  306.         if (m==20) { mf = (canvas.width/div24)*2.20; }
  307.         else if (m==40){ mf = (canvas.width/div24)*4.2; }
  308.         if (c==1) { cf = (canvas.width/div24)*3; }
  309.         else if (c==14) { cf = ( canvas.width / div24)*18 }
  310.         else { cf = ((canvas.width/div24)*3) + ((canvas.width/div24)*(c-1)); }
  311.         rf = q*(canvas.height/100)*(10/vdiv);  // adapt calculation for -10 to -100 only
  312. }
  313.         else if (c>35){ var canvas  = document.getElementById("ellipses5");
  314.         var ctx = canvas.getContext('2d');
  315.         var cc = c;
  316.         if (m==20) { mf = ((canvas.width/div5)*0.5); }
  317.         else if (m==40) { mf = ((canvas.width/div5)*1); // 52 =54 [ 50 - 58 ]
  318.                 cc = c;
  319.                 }
  320.         else if (m==80) { mf = ((canvas.width/div5)*2); // 100 = 106 [ 98 - 114 ]
  321.                 cc = c;
  322.                 }
  323.         cc = cc-36+4;
  324.         cf = (canvas.width/div5) + ((canvas.width/div5)*(cc/4));
  325.         rf = q*(canvas.height/100)*(10/vdiv);  // adapt calculation for -10 to -100 only
  326. }      
  327.         ctx.beginPath();
  328.         ctx.save();
  329.         var decimalColor = hexToDecimal(col);
  330.         ctx.ellipse(cf, vsize, mf, rf, 0, 0, 2 * Math.PI, false);
  331.         ctx.strokeStyle = "rgba( " + decimalColor + ", 1)";
  332.         if (style == '0') {
  333.         ctx.fillStyle = "rgba( " + decimalColor + ", 0)";
  334.         ctx.lineWidth = 1; 
  335.         } else {           
  336.         var density = (style/100);
  337.         ctx.fillStyle = "rgba( " + decimalColor + ", " + density +")"; 
  338.         }
  339.         ctx.stroke();
  340.         ctx.fill();
  341.         ctx.restore();
  342.         ctx.save();
  343.         ctx.fillStyle = "#000000";
  344.         ctx.font = sshow+'px Arial';
  345.         ctx.textAlign = 'center';
  346.         ctx.textBaseline = "middle";
  347.         var lines = ssid.split('¬');
  348.         ctx.fillText(lines[0], cf, (vsize+1+sshow/2)-rf);
  349.         if (typeof lines[1] !== 'undefined' )
  350.         { ctx.fillText(lines[1], cf, (vsize+1+sshow*1.5)-rf);
  351.           ctx.fillText(lines[2], cf, (vsize+1+sshow*2.5)-rf); }
  352.         ctx.restore();
  353.         ctx.closePath();
  354. }
  355. function sortByProperty(array, property) {
  356. array.sort(function(a, b) {
  357. return b[property] - a[property];
  358. });
  359. return array;
  360. }
  361.  
  362. // const internalWl0 = [
  363. // "", //bssid
  364. // "PoPoo", //ssid
  365. // -10, //rssi
  366. // 100, //control channel
  367. // 20, //width
  368. // 100, //quality
  369. // "", //capabilities
  370. // "", //security
  371. // "", //security 2nd line
  372. // "", // 5GHz
  373. // 102, // central channel
  374. // 0 // unused
  375. // ];
  376. // console.log(wlscandata);
  377. sg.populate = function(style, sshow) {
  378. var added = 0;
  379. var removed = 0;
  380. var i, j, k, t, e, s;
  381. redraw();
  382. var lim2 = 1;
  383. var lim5 = 1;
  384. var col2 = 0;
  385. var col5 = colors.length-1;
  386. // console.log(wlscandata);
  387. if ((wlscandata.length == 1) && (!wlscandata[0][0])) {
  388. setMsg('error: '+wlscandata[0][1]);
  389. return;
  390. }
  391. drawFT();
  392.  
  393. // console.log(wlscandata);
  394. for (i = 0; i < wlscandata.length; ++i) {
  395. s = wlscandata[i];
  396. e = null;
  397. sortByProperty(entries, "rssi");
  398. // console.log(entries);
  399. for (j = 0; j < entries.length; ++j) { 
  400. if (entries[j].bssid == s[0]) {
  401. e = entries[j];
  402. break;
  403. }
  404. }
  405. if (!e) {
  406. ++added;
  407. e = {};
  408. e.firstSeen = new Date();
  409. entries.push(e);
  410. }
  411. // console.log(e);
  412. e.lastSeen = new Date();
  413. e.bssid = s[0];
  414. if (s[1] === '') {
  415. // e.ssid = "HIDDEN";
  416. e.ssid = "🕶️";
  417. } else {
  418. e.ssid = s[1];
  419. }
  420. e.control = s[3];
  421. e.channel = s[10];
  422. e.channel = e.channel+'<br><small>'+s[9]+' GHz<\/small><br><small>'+s[4]+' MHz<\/small>';
  423. e.rssi = s[2];
  424. e.mhz = s[4];
  425. e.cap = s[7]+ '<br>'+s[8];
  426. e.rates =s[6].replace("11", "");;
  427. if (e.rssi != -999) {
  428. if (e.rssi >= -50)
  429. e.qual = 100;
  430. else if (e.rssi >= -80)
  431. e.qual = Math.round(24 + ((e.rssi + 80) * 26)/10);
  432. else if (e.rssi >= -90)
  433. e.qual = Math.round(24 + ((e.rssi + 90) * 26)/10);
  434. else
  435. e.qual = 0;
  436. }
  437. else {
  438. e.qual = -1;
  439. }
  440. }
  441. t = E('expire-time').value;
  442. if (t > 0) {
  443. var cut = (new Date()).getTime() - (t * 1000);
  444. for (i = 0; i < entries.length; ) {
  445. if (entries[i].lastSeen.getTime() < cut) {
  446. entries.splice(i, 1);
  447. ++removed;
  448. }
  449. else
  450. ++i;
  451. }
  452. }
  453. if (typeof sshow === 'undefined' ) { var sshow = 'hide'; }
  454. // drawFT(sshow);
  455. for (i = 0; i < entries.length; ++i) {
  456. var seen, m, mac;
  457. e = entries[i];
  458. seen = e.lastSeen.toWHMS();
  459. if (useAjax()) {
  460. m = Math.floor(((new Date()).getTime() - e.firstSeen.getTime()) / 60000);
  461. if (m <= 10)
  462. seen += '<br> <b><small>NEW ('+m+'m)<\/small><\/b>';
  463. }
  464. mac = e.bssid;
  465. var chan = e.channel.split("<");
  466. if (style == 0) {
  467. var density = 100; 
  468. } else {
  469. var density = (style/100);
  470. }
  471. var colo;
  472. // console.log('e.bssid = '+e.bssid);
  473. // console.log('wl0_b = '+typeof wl0_b);
  474. // console.log('wl1_b = '+typeof wl1_b);
  475. // console.log('wl2_b = '+typeof wl2_b);
  476. // console.log('channel = '+chan[0]);
  477. // console.log(typeof e.bssid);
  478. // debugger;
  479. if (lim2<=ssidlimit && chan[0]<35 && col2<=colors.length-1) {
  480.     // console.log('2.4GHz - step1');
  481. if (e.bssid === wl0.bssid) { colo = "#aaaaaa";} else { colo = colors[col2]; lim2++; col2++;}   
  482.             var decimalColor = hexToDecimal(colo);
  483.             // console.log(decimalColor);
  484. e.col = '<CENTER><div style="padding: 0px; width: 20px; height: 40px; background-color: rgba(' + decimalColor + ', ' + density +');border: 1px solid black;"></CENTER></div>';
  485. // console.log('colo = '+colo);
  486. drawEllipse(chan[0], e.mhz, (100+e.rssi), colo, e.ssid, 0, style, sshow);
  487. } else if (lim5<=ssidlimit && chan[0]>35) {
  488.         // console.log('5GHz - step1');
  489. if (e.bssid === wl1.bssid || e.bssid === wl2.bssid ) { colo = "#aaaaaa";} else { var colo = colors[col5]; lim5++; col5--;} 
  490.             var decimalColor = hexToDecimal(colo);
  491.             // console.log(decimalColor);
  492. e.col = '<CENTER><div style="padding: 0px; width: 20px; height: 40px; background-color: rgba(' + decimalColor + ', ' + density +');border: 1px solid black;"></CENTER></div>';
  493. // console.log('colo = '+colo);
  494. drawEllipse(chan[0], e.mhz, (100+e.rssi), colo, e.ssid, 0, style, sshow);
  495. } else {
  496. e.col = '<div></div>';
  497. }
  498. if (mac.match(/^(..):(..):(..)/))
  499. mac = '<div style="display:none" id="gW_'+i+'">&nbsp; <img src="spin.gif" alt="" style="vertical-align:middle"><\/div><a href="javascript:searchOUI(\''+RegExp.$1+'-'+RegExp.$2+'-'+RegExp.$3+'\','+i+')" title="OUI Search">'+mac+'<\/a>';
  500. sg.insert(-1, e, [ '<small>'+seen+'<\/small>', ''+e.col, ''+e.ssid, mac, (e.rssi < 0 ? e.rssi+'' : ''),
  501. (e.qual < 0 ? '' : '<small>'+e.qual+'<\/small><br><img src="bar'+MIN(MAX(Math.floor(e.qual / 12), 1), 6)+'.gif" id="bar_'+i+'" alt="">'),
  502. ''+e.control+'/'+e.channel, '<small>'+e.cap, '</small>'+e.rates], false);
  503. }
  504. var max2 = div24 - 2 ;
  505. drawCoordinates('ellipses2', -2, max2 , 1, 13, div24, 1); //min, max, display min, display max, total num, increment
  506. drawCoordinates('ellipses5', 28, 184, 36, 180, div5, 4);
  507. s = '';
  508. if (useAjax())
  509. s = added+' added, '+removed+' removed, ';
  510. s += entries.length+' total.';
  511. s += '<br><br><small>Last updated: '+(new Date()).toWHMS()+'<\/small>';
  512. setMsg(s);
  513. wlscandata = [];
  514. }
  515. sg.sortCompare = function(a, b) {
  516. var col = this.sortColumn;
  517. var da = a.getRowData();
  518. var db = b.getRowData();
  519. var r;
  520. switch (col) {
  521. case 0:
  522. r = -cmpDate(da.lastSeen, db.lastSeen);
  523. break;
  524. case 2:
  525. r = -cmpText(da.ssid.toLowerCase(), db.ssid.toLowerCase());
  526. break;
  527. case 3:
  528. r = -cmpText(da.bssid.toString(), db.bssid.toString());
  529. break;
  530. case 4:
  531. r = cmpInt(da.rssi, db.rssi);
  532. break;
  533. case 5:
  534. r = cmpInt(da.qual, db.qual);
  535. break;
  536. case 6:
  537. r = cmpInt(da.channel, db.channel);
  538. break;
  539. default:
  540. r = cmpText(a.cells[col].innerHTML, b.cells[col].innerHTML);
  541. }
  542. if (r == 0)
  543. r = cmpText(da.bssid, db.bssid);
  544. return this.sortAscending ? r : -r;
  545. }
  546. Date.prototype.toWHMS = function() {
  547. return dayOfWeek[this.getDay()]+' '+this.getHours()+':'+this.getMinutes().pad(2)+ ':'+this.getSeconds().pad(2);
  548. }
  549. function setMsg(msg) {
  550. elem.setInnerHTML(E('survey-msg'), msg);
  551. }
  552. function drawFT(show) {
  553.     if (typeof res0a === 'undefined') { return; }
  554.     var noiseMatch = res0a.match(/noise: (-?\d+)/);
  555.     wl0.noise = noiseMatch ? noiseMatch[1] : null;
  556.     var ssidMatch = res0a.match(/SSID: "([^"]+)"/);
  557.     wl0.ssid = ssidMatch ? ssidMatch[1] : null;
  558.     var bssidMatch = res0a.match(/BSSID: (\S+)/);
  559.     wl0.bssid = bssidMatch ? bssidMatch[1] : null;
  560.     var channelMatch = res0a.match(/Primary channel: (\d+)/);
  561.     wl0.controlchannel = channelMatch ? channelMatch[1] : null;
  562.     var chanspecMatch = res0a.match(/Chanspec: (\d+(?:\.\d+)?)GHz channel (\d+) (\d+)MHz/);
  563.     wl0.centralchannel = chanspecMatch ? chanspecMatch[2] : null;
  564.     wl0.width = chanspecMatch ? chanspecMatch[3] : null;
  565.     var noiseMatch = res1a.match(/noise: (-?\d+)/);
  566.     wl1.noise = noiseMatch ? noiseMatch[1] : null;
  567.     var ssidMatch = res1a.match(/SSID: "([^"]+)"/);
  568.     wl1.ssid = ssidMatch ? ssidMatch[1] : null;
  569.     var bssidMatch = res1a.match(/BSSID: (\S+)/);
  570.     wl1.bssid = bssidMatch ? bssidMatch[1] : null;
  571.     var channelMatch = res1a.match(/Primary channel: (\d+)/);
  572.     wl1.controlchannel = channelMatch ? channelMatch[1] : null;
  573.     var chanspecMatch = res1a.match(/Chanspec: (\d+(?:\.\d+)?)GHz channel (\d+) (\d+)MHz/);
  574.     wl1.centralchannel = chanspecMatch ? chanspecMatch[2] : null;
  575.     wl1.width = chanspecMatch ? chanspecMatch[3] : null;
  576.     var noiseMatch = res2a.match(/noise: (-?\d+)/);
  577.     wl2.noise = noiseMatch ? noiseMatch[1] : null;
  578.     var ssidMatch = res2a.match(/SSID: "([^"]+)"/);
  579.     wl2.ssid = ssidMatch ? ssidMatch[1] : null;
  580.     var bssidMatch = res2a.match(/BSSID: (\S+)/);
  581.     wl2.bssid = bssidMatch ? bssidMatch[1] : null;
  582.     var channelMatch = res2a.match(/Primary channel: (\d+)/);
  583.     wl2.controlchannel = channelMatch ? channelMatch[1] : null;
  584.     var chanspecMatch = res2a.match(/Chanspec: (\d+(?:\.\d+)?)GHz channel (\d+) (\d+)MHz/);
  585.     wl2.centralchannel = chanspecMatch ? chanspecMatch[2] : null;
  586.     wl2.width = chanspecMatch ? chanspecMatch[3] : null;
  587. if (Number(wl0.radio.value) === 1) {   
  588. const internalWl0 = [ wl0.bssid, wl0.ssid, -10, wl0.controlchannel, wl0.width, 100, "", "", "", "2.4", wl0.centralchannel, 0 ];
  589. // console.log(internalWl0);
  590. if (wlscandata.find(obj => obj.bssid === wl0.bssid.value) == -1 ) { wlscandata.push(internalWl0); }
  591. }
  592. if (Number(wl1.radio.value) === 1) {   
  593. const internalWl1 = [ wl1.bssid, wl1.ssid, -10, wl1.controlchannel, wl1.width, 100, "", "", "", "5", wl1.centralchannel, 0 ];
  594. // console.log(internalWl1);
  595. if (wlscandata.find(obj => obj.bssid === wl1.bssid.value) == -1 ) { wlscandata.push(internalWl1); }
  596. }
  597. if (Number(wl2.radio.value) === 1) {   
  598. const internalWl2 = [ wl2.bssid, wl2.ssid, -10, wl2.controlchannel, wl2.width, 100, "", "", "", "5", wl2.centralchannel, 0 ];
  599. if (wlscandata.find(obj => obj.bssid === wl2.bssid.value) == -1 ) { wlscandata.push(internalWl2); }
  600. }
  601. // const me=55;
  602. // const clocal="#aaaaaa"
  603. // if (typeof wl0_r !== 'undefined' && wl0_r == 1 && wl0_m != 'sta') {
  604. // // res0=String(res0).replace(/\\x0a/g, ',').match(/\d+/g);
  605. // if (res0 !== null) {
  606. // // wl0_c = parseInt(res0[0]); // channel
  607. // // wl0_w = parseInt(res0[1]); // width
  608. // if (wl0_h == 1) { wl0_d = "🕶️"; }
  609. // drawEllipse(wl0_cec, wl0_w, (vdiv*10), clocal, wl0_d, 0, me, show);
  610. // }
  611. // }
  612. // if (typeof wl1_r !== 'undefined' && wl1_r == 1 && wl1_m != 'sta') {
  613. // // res1=String(res1).replace(/\\x0a/g, ',').match(/\d+/g);
  614. // if (res1 !== null) {
  615. // // wl1_c = parseInt(res1[0]);
  616. // // wl1_w = parseInt(res1[1]);
  617. // if (wl1_h == 1) { wl1_d = "🕶️"; }
  618. // drawEllipse(wl1_cec, wl1_w, (vdiv*10), clocal, wl1_d, 0, me, show);
  619. // // +'¬Ch '+wl1_c+'¬'+wl1_w+'MHz'
  620. // }
  621. // }
  622. // if (typeof wl2_r !== 'undefined' && wl2_r == 1 && wl2_m != 'sta') {
  623. // // res2=String(res2).replace(/\\x0a/g, ',').match(/\d+/g);
  624. // if (res2 !== null) {
  625. // // wl2_c = parseInt(res2[0]);
  626. // // wl2_w = parseInt(res2[1]);
  627. // if (wl2_h == 1) { wl2_d = "🕶️"; }
  628. // drawEllipse(wl2_cec, wl2_w, (vdiv*10), clocal, wl2_d, 0, me, show);
  629. // }
  630. // }
  631. }
  632. function drawCoordinates(a, b, c, d, e, f, g) {
  633.     var canvas = document.getElementById(a);
  634.     var ctx = canvas.getContext('2d');
  635.     var minX = b
  636.     var maxX = c
  637.     var minV = d
  638.     var maxV = e
  639.     var numDivisions = f;
  640.     var incrementX = g;
  641. const fontSize = 10;
  642. const fontFamily = "Arial Narrow";
  643.     ctx.font = fontSize + "px " + fontFamily;
  644.     // Draw x-axis
  645.     ctx.beginPath();   
  646.     ctx.moveTo(0, canvas.height);
  647.     ctx.lineTo(canvas.width, canvas.height);
  648.     ctx.fillStyle = "black";
  649.     ctx.textBaseline = "bottom";   
  650. if (a=='ellipses2') {
  651. for (var i = 0; i <= numDivisions; i++) {
  652.   var x;
  653.   if (i === 0) {
  654.     x = minX + 2 * incrementX;
  655.   } else if (i === numDivisions) {
  656.     x = maxX - 2 * incrementX;
  657.   } else {
  658.     x = minX + i * incrementX;
  659.   }
  660.   if (x >= 1 && x <= 13) {
  661.     var xPos = (canvas.width / (maxX - minX)) * (x - minX);
  662.     ctx.textAlign = "center";  
  663.     ctx.fillText(x, xPos, canvas.height + 2);
  664.   }
  665. }
  666.     ctx.textAlign = "center";
  667.     xPos = ( canvas.width / (maxX - minX)) * 18
  668.     ctx.fillText(14, xPos, canvas.height + 2);
  669. }
  670. else if (a=='ellipses5') {
  671. for (var i = 0; i <= numDivisions; i++) {
  672.   var x;
  673.   if (i === 0) {
  674.     x = minX + 1 * incrementX;
  675.   } else if (i === numDivisions) {
  676.     x = maxX - 1 * incrementX;
  677.   } else {
  678.     x = minX + (i + 1) * incrementX;
  679.   }
  680.   if (x > 32 && x <= 64 || x >=100 && x <= 144 ) {
  681.     var xPos = (canvas.width / (maxX - minX)) * (x - minX);
  682.     ctx.textAlign = "center";
  683.     ctx.fillText(x, xPos, canvas.height+2);
  684.   }
  685. }
  686. for (var i = 0; i <= div5; i++) {
  687.   var x;
  688.   if (i === 0) {
  689.     x = 33 + 1 * 4;
  690.   } else if (i === div5) {
  691.     x = 184 - 1 * 4;
  692.   } else {
  693.     x = 33 + (i + 1) * 4;
  694.   }
  695.   if (x >= 149 && x <= 177 ) {
  696.     var xPos = (canvas.width / (184 - 33)) * (x - 33);
  697.     ctx.textAlign = "center";
  698.     ctx.fillText(x, xPos, canvas.height + 2);
  699.   }
  700. }
  701. }
  702. // draw y-axis
  703. for (var i = 0; i < 10; i++) {
  704.   var y = -10 * i;
  705.  
  706.   if (y !== -10 && y >= -90) { // Exclude -100 from being displayed
  707.     var yPos = (canvas.height / (vdiv*10)) * (-y - 10);
  708.     // Draw y-axis 
  709.     ctx.textBaseline = "middle"; // Align text vertically at the middle
  710.     ctx.fillText(y.toString(), 6, yPos); // Adjust yPos for vertical centering
  711.     ctx.fillText(y.toString(), hsize, yPos); // Adjust yPos for vertical centering
  712.   }
  713. }
  714.  
  715. }
  716. function drawBoard(can){
  717.     // Padding
  718.     var p = 0;
  719.     var canvas = document.getElementById(can);
  720.     var ctx = canvas.getContext("2d");
  721.         ctx.beginPath();
  722.     // Add sepia areas
  723.     if (can == 'ellipses2') {
  724.         for (var x = 0; x <= hsize; x += (canvas.width/div24)) {
  725.         ctx.moveTo(0.5 + x + p, p);
  726.         ctx.lineTo(0.5 + x + p, vsize + p);
  727.     }
  728.             for (var x = 0; x <= vsize; x += (canvas.height/vdiv)) {
  729.         ctx.moveTo(p, 0.5 + x + p);
  730.         ctx.lineTo(hsize + p, 0.5 + x + p);
  731.     }
  732.         ctx.strokeStyle = "#f4f4f4";
  733.         ctx.stroke();
  734.         ctx.rect(0, 0, canvas.width/div24*3, vsize);
  735.         ctx.rect(canvas.width/div24*15, 0, canvas.width/div24*11, vsize);
  736.         ctx.fillStyle = "rgba(112,66,20,0.06)";
  737.         ctx.fill();
  738.         ctx.rect(canvas.width/div24*13, 0, canvas.width/div24*15, vsize);
  739.         ctx.fillStyle = "rgba(112,66,20,0.06)";
  740.         ctx.fill();
  741.     }  
  742.     else if (can == 'ellipses5') {
  743.         for (var x = 0; x <= hsize; x += (canvas.width/div5)) {
  744.         ctx.moveTo(0.5 + x + p, p);
  745.         ctx.lineTo(0.5 + x + p, vsize + p);
  746.     }
  747.             for (var x = 0; x <= vsize; x += (canvas.height/vdiv)) {
  748.         ctx.moveTo(p, 0.5 + x + p);
  749.         ctx.lineTo(hsize + p, 0.5 + x + p);
  750.     }
  751.         ctx.strokeStyle = "#f4f4f4";
  752.         ctx.stroke();
  753.         ctx.rect(0, 0, (canvas.width/div5)*2, vsize);
  754.         ctx.rect(canvas.width/div5*9, 0, canvas.width/div5*9, vsize);
  755.         ctx.rect(canvas.width/div5*37, 0, canvas.width, vsize);
  756.         ctx.fillStyle = "rgba(112,66,20,0.06";
  757.         ctx.fill();
  758.         ctx.rect(canvas.width/div5*29.3, 0, canvas.width/div5*0.6, vsize);
  759.         ctx.fillStyle = "rgba(112,66,20,0.06)";
  760.         ctx.fill();    
  761.     }
  762.     ctx.closePath();
  763. }
  764. function clearCanvas(canvas) {
  765. canvas = document.getElementById(canvas);
  766. const ctx = canvas.getContext('2d');
  767. ctx.clearRect(0, 0, canvas.width, canvas.height);
  768. ctx.fillStyle = "#fdfdfd";
  769. // ctx.fillStyle = "rgba(255, 255, 255, 0.3)";
  770. ctx.fillRect(0, 0, canvas.width, canvas.height);
  771. }
  772. function earlyInit() {
  773. if (!useAjax())
  774. E('expire-time').style.display = 'none';
  775. sg.setup();
  776. var expiretime = document.getElementById("expire-time");
  777. expiretime.addEventListener("change", function() {
  778. cookie.set(cprefix+'_expire_time', expiretime.selectedIndex);
  779. });
  780. var fillstyle = document.getElementById("fill-style");
  781. fillstyle.addEventListener("change", function() {
  782. cookie.set(cprefix+'_fill_style', fillstyle.selectedIndex);
  783. });
  784. var ssidshow = document.getElementById("ssid-show");
  785. ssidshow.addEventListener("change", function() {
  786. cookie.set(cprefix+'_ssid_show', ssidshow.selectedIndex);
  787. });
  788. var ssidlimit = document.getElementById("ssid-limit");
  789. ssidlimit.addEventListener("change", function() {
  790. cookie.set(cprefix+'_ssid_limit', ssidlimit.value);
  791. });
  792. }
  793. function init() {
  794. var ellipses2Div = document.getElementById('tomato-chart2');
  795. var ellipses5Div = document.getElementById('tomato-chart5');
  796. // console.log(wl0.mode);
  797. // console.log(wl1.mode);
  798. // console.log(wl2.mode);
  799. // console.log(wl1.radio.value);
  800. if (Number(wl0.radio.value) === 1 && wl0.mode.value !== '') {
  801. ellipses2Div.style.display = 'block';
  802. } else {
  803. ellipses2Div.style.display = 'none';
  804. }
  805. if ((Number(wl1.radio.value) === 1 && wl1.mode.value !== '') || (Number(wl2.radio.value) === 1 && wl2.mode.value !== '') ) {
  806. ellipses5Div.style.display = 'block';
  807. } else {
  808. ellipses5Div.style.display = 'none';
  809. }
  810. sg.recolor();
  811. ref.initPage();
  812. }
  813. </script>
  814. </head>
  815. <body onload="init()">
  816. <form action="javascript:{}">
  817. <table id="container">
  818. <tr><td colspan="2" id="header">
  819. <div class="title">FreshTomato</div>
  820. <div class="version">Version <% version(); %> on <% nv("t_model_name"); %></div>
  821. </td></tr>
  822. <tr id="body"><td id="navi"><script>navi()</script></td>
  823. <td id="content">
  824. <div id="ident"><% ident(); %> | <script>wikiLink();</script></div>
  825. <div id="tomato-chart2">Channel Congestion: <b>2.4 GHz</b><br>
  826. <canvas id="ellipses2" width="756" height="200" border=1></canvas>
  827. <p></div>
  828. <div id="tomato-chart5">Channel Congestion: <b>5 GHz</b><br>
  829. <canvas id="ellipses5" width="756" height="200" border=1></canvas></div>
  830. <div id="wl-controls">
  831. <table border=0><tr><td>
  832. <label for="fill-style">Style: </label>
  833. <select id="fill-style" onchange="doit();">
  834. <option value="100">100%</option>
  835. <option value="90">90%</option>
  836. <option value="80">80%</option>
  837. <option value="70">70%</option>
  838. <option value="60">60%</option>
  839. <option value="50">50%</option>
  840. <option value="40">40%</option>
  841. <option value="30">30%</option>
  842. <option value="20">20%</option>
  843. <option value="10">10%</option>
  844. <option value="5">5%</option>
  845. <option value="0">0%</option>
  846. </select>&nbsp;&nbsp;&nbsp;&nbsp;</td><td>
  847. <label for="ssid-show">SSID text: </label>
  848. <select id="ssid-show" onchange="doit();">
  849. <option value="20">20px</option>
  850. <option value="18">18px</option>
  851. <option value="16">16px</option>
  852. <option value="14">14px</option>
  853. <option value="12">12px</option>
  854. <option value="10">10px</option>
  855. <option value="8">8px</option>
  856. <option value="0">Hide</option>
  857. </select>&nbsp;&nbsp;&nbsp;&nbsp;</td><td>
  858. <label for="ssid-limit">Limit SSIDs: </label>
  859. <input type="number" id="ssid-limit" name="ssid-limit" style="width:33px" min="0" max="40" value="20" onchange="doit();">
  860. </td></tr></table></div>
  861. <p>
  862. <div class="section-title">Wireless Site Survey</div>
  863. <div class="section">
  864. <div id="survey-grid" class="tomato-grid"></div>
  865. <div id="survey-msg"></div>
  866. <div class="section-title">Notes <small><i><a href="javascript:toggleVisibility(cprefix,'notes');"><span id="sesdiv_notes_showhide">(Show)</span></a></i></small></div>
  867. <div class="section" id="sesdiv_notes" style="display:none">
  868. <ul>
  869. <script>
  870. if ('<% wlclient(); %>' == '0')
  871. document.write('<li><b>Warning:<\/b> Wireless connections to this router may be disrupted while using this tool.<br></li>');
  872. </script>
  873. <li><b>Wireless Survey:</b> will not show any results with WL filter turned on in 'permit only' mode. </li>
  874. <li><b>Internal SSID:</b> a full page reload is needed if any of the internal SSID parameters (grey ellipse) ever change.</li>
  875. <li><b>Protocols:</b> 802.11ac based FT routers may not accurately detect 160, 240, or 320 MHz channel widths used by 802.11ax (WiFi 6) and 802.11be (WiFi 7) routers. Conversely, 802.11ax-based FT routers may misinterpret 240 or 320 MHz widths in 802.11be routers as 160 MHz. Consider these limitations when assessing network configurations for compatibility and performance.</li>
  876. </ul>
  877. </div>
  878. </div>
  879. <div id="footer">
  880. <div id="survey-controls">
  881. <img src="spin.gif" alt="" id="refresh-spinner">
  882. <script>
  883. expiretime = cookie.get(cprefix+'_expire_time');
  884. if (expiretime === null) { expiretime = 9; }
  885. ssidlimit = cookie.get(cprefix+'_ssid_limit');
  886. if (ssidlimit === null) { ssidlimit = 20; }
  887. fillstyle = cookie.get(cprefix+'_fill_style');
  888. if (fillstyle === null) { fillstyle = 7; }
  889. ssidshow = cookie.get(cprefix+'_ssid_show');
  890. if (ssidshow === null) { ssidshow = 4; }
  891. genStdTimeList('expire-time', 'Expires = ♾️', 6);
  892. genStdTimeList('refresh-time', 'One off', 10);
  893. var dropdown = document.getElementById("expire-time");
  894. dropdown.selectedIndex = expiretime;
  895. var dropdown = document.getElementById("ssid-limit");
  896. dropdown.value = ssidlimit;
  897. var dropdown = document.getElementById("fill-style");
  898. dropdown.selectedIndex = fillstyle;
  899. var dropdown = document.getElementById("ssid-show");
  900. dropdown.selectedIndex = ssidshow;
  901. </script>
  902. <input type="button" value="Refresh" onclick="ref.toggle()" id="refresh-button">
  903. </div>
  904. </div>
  905. </td></tr>
  906. </table>
  907. </form>
  908. <script>earlyInit();</script>
  909. </body>
  910. </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement