'use strict'; 'require uci'; 'require view'; 'require poll'; 'require rpc'; 'require ui'; 'require network'; function etx_color(etx) { let color = '#bb3333'; if (etx === 0) { color = '#bb3333'; } else if (etx < 2) { color = '#00cc00'; } else if (etx < 4) { color = '#ffcb05'; } else if (etx < 10) { color = '#ff6600'; } return color; } function snr_colors(snr) { let color = '#bb3333'; if (snr === 0) { color = '#bb3333'; } else if (snr > 30) { color = '#00cc00'; } else if (snr > 20) { color = '#ffcb05'; } else if (snr > 5) { color = '#ff6600'; } return color; } return view.extend({ callGetJsonStatus: rpc.declare({ object: 'olsrinfo', method: 'getjsondata', params: ['otable', 'v4_port', 'v6_port'], }), callGetHosts: rpc.declare({ object: 'olsrinfo', method: 'hosts', }), fetch_jsoninfo: function (otable) { var jsonreq4 = ''; var jsonreq6 = ''; var v4_port = parseInt(uci.get('olsrd', 'olsrd_jsoninfo', 'port') || '') || 9090; var v6_port = parseInt(uci.get('olsrd6', 'olsrd_jsoninfo', 'port') || '') || 9090; var json; var self = this; return new Promise(function (resolve, reject) { L.resolveDefault(self.callGetJsonStatus(otable, v4_port, v6_port), {}) .then(function (res) { json = res; jsonreq4 = JSON.parse(json.jsonreq4); jsonreq6 = json.jsonreq6 !== '' ? JSON.parse(json.jsonreq6) : []; var jsondata4 = {}; var jsondata6 = {}; var data4 = []; var data6 = []; var has_v4 = false; var has_v6 = false; if (jsonreq4 === '' && jsonreq6 === '') { window.location.href = 'error_olsr'; reject([null, 0, 0, true]); return; } if (jsonreq4 !== '') { has_v4 = true; jsondata4 = jsonreq4 || {}; if (otable === 'status') { data4 = jsondata4; } else { data4 = jsondata4[otable] || []; } for (var i = 0; i < data4.length; i++) { data4[i]['proto'] = '4'; } } if (jsonreq6 !== '') { has_v6 = true; jsondata6 = jsonreq6 || {}; if (otable === 'status') { data6 = jsondata6; } else { data6 = jsondata6[otable] || []; } for (var j = 0; j < data6.length; j++) { data6[j]['proto'] = '6'; } } for (var k = 0; k < data6.length; k++) { data4.push(data6[k]); } resolve([data4, has_v4, has_v6, false]); }) .catch(function (err) { console.error(err); reject([null, 0, 0, true]); }); }); }, action_neigh: async function () { try { const [data, has_v4, has_v6, error] = await this.fetch_jsoninfo('links'); if (error) { throw error; } function compare(a, b) { if (a.proto === b.proto) { return a.linkCost < b.linkCost; } else { return a.proto < b.proto; } } var assoclist = []; var resolveVal = uci.get('luci_olsr', 'general', 'resolve'); var devices; var defaultgw; devices = await network.getWifiDevices(); var rts = await network.getWANNetworks(); rts.forEach(function (rt) { defaultgw = rt.getGatewayAddr() || '0.0.0.0'; }); var networkPromises = devices.map(async function (dev) { var networks = await dev.getWifiNetworks(); var promiseArr = networks.map(async function (net) { var radio = await net.getDevice(); var [ifname, devnetwork, device, list] = await Promise.all([net.getIfname(), net.getNetworkNames(), radio ? radio.getName() : null, net.getAssocList()]); assoclist.push({ ifname: ifname, network: devnetwork[0], device: device, list: list, }); }); await Promise.all(promiseArr); }); await Promise.all(networkPromises); var res = ''; var self = this; await (async function () { try { res = await self.callGetHosts(); } catch (e) { console.error(e); } })(); function matchHostnames(ip) { var lines = res.hosts.split('\n'); for (var i = 0; i < lines.length; i++) { var ipandhostname = lines[i].trim().split(/\s+/); if (ipandhostname[0] === ip) { return ipandhostname[1]; } } return null; } var modifiedData = await Promise.all( data.map(async function (v) { var snr = 0; var signal = 0; var noise = 0; var mac = ''; var ip; var neihgt = []; if (resolveVal === '1') { var hostname = matchHostnames(v.remoteIP); if (hostname) { v.hostname = hostname; } } var hosthints = await network.getHostHints(); var networkStatus = await network.getStatusByAddress(v.localIP); var lmac = await hosthints.getMACAddrByIPAddr(v.localIP); var rmac = await hosthints.getMACAddrByIPAddr(v.remoteIP); for (let i = 0; i < assoclist.length; i++) { var val = assoclist[i]; if (networkStatus != undefined && val.network === networkStatus.interface && val.list) { for (var assocmac in val.list) { var assot = val.list[assocmac]; if (rmac == assot.mac) { signal = parseInt(assot.signal); noise = parseInt(assot.noise); snr = noise * -1 - signal * -1; } } } } if (networkStatus) { v.interface = networkStatus; } v.snr = snr || null; v.signal = signal || null; v.noise = noise || null; if (rmac) { v.remoteMAC = rmac; } if (lmac) { v.localMAC = lmac; } if (defaultgw === v.remoteIP) { v.defaultgw = 1; } return v; }) ); modifiedData.sort(compare); var result = { links: modifiedData, has_v4: has_v4, has_v6: has_v6 }; return result; } catch (err) { console.error(err); throw err; } }, load: function () { var self = this; poll.add(function () { self.render(); }, 5); return Promise.all([uci.load('olsrd'), uci.load('luci_olsr')]); }, render: function () { var neigh_res; var has_v4; var has_v6; var self = this; return this.action_neigh() .then(function (result) { neigh_res = result.links; has_v4 = result.has_v4; has_v6 = result.has_v6; var table = E('div', { 'class': 'table cbi-section-table', 'id': 'olsr_neigh_table' }, [ E('div', { 'class': 'tr cbi-section-table-cell' }, [ E('div', { 'class': 'th cbi-section-table-cell' }, _('Neighbour IP')), E('div', { 'class': 'th cbi-section-table-cell' }, _('Hostname')), E('div', { 'class': 'th cbi-section-table-cell' }, _('Interface')), E('div', { 'class': 'th cbi-section-table-cell' }, _('Local interface IP')), E('div', { 'class': 'th cbi-section-table-cell' }, 'LQ'), E('div', { 'class': 'th cbi-section-table-cell' }, 'NLQ'), E('div', { 'class': 'th cbi-section-table-cell' }, 'ETX'), E('div', { 'class': 'th cbi-section-table-cell' }, 'SNR'), ]), ]); var rv = []; for (var k = 0; k < neigh_res.length; k++) { var link = neigh_res[k]; link.linkCost = (link.linkCost).toFixed(3) || 0; if (link.linkCost === 4194304) { link.linkCost = 0; } var color = etx_color(link.linkCost); var snr_color = snr_colors(link.snr); var defaultgw_color = ''; if (link.defaultgw === 1) { defaultgw_color = '#ffff99'; } rv.push({ rip: link.remoteIP, hn: link.hostname, lip: link.localIP, ifn: link.interface, lq: link.linkQuality.toFixed(3), nlq: link.neighborLinkQuality.toFixed(3), cost: link.linkCost, snr: link.snr, signal: link.signal, noise: link.noise, color: color, snr_color: snr_color, dfgcolor: defaultgw_color, proto: link.proto, }); } var nt = document.getElementById('olsr_neigh_table'); if (nt) { var s = '