'require rpc';
'require network';
-var callLuciRealtimeStats = rpc.declare({
+const callLuciRealtimeStats = rpc.declare({
object: 'luci',
method: 'getRealtimeStats',
params: [ 'mode', 'device' ],
expect: { result: [] }
});
-var graphPolls = [],
- pollInterval = 3;
+const graphPolls = [];
+const pollInterval = 3;
Math.log2 = Math.log2 || function(x) { return Math.log(x) * Math.LOG2E; };
}
return view.extend({
- load: function() {
+ load() {
return Promise.all([
this.loadSVG(L.resource('svg/bandwidth.svg')),
network.getDevices()
]);
},
- updateGraph: function(ifname, svg, lines, cb) {
- var G = svg.firstElementChild;
+ updateGraph(ifname, svg, lines, cb) {
+ const G = svg.firstElementChild;
- var view = document.querySelector('#view');
+ const view = document.querySelector('#view');
- var width = view.offsetWidth - 2;
- var height = 300 - 2;
- var step = 5;
+ const width = view.offsetWidth - 2;
+ const height = 300 - 2;
+ const step = 5;
- var data_wanted = Math.floor(width / step);
+ const data_wanted = Math.floor(width / step);
- var data_values = [],
- line_elements = [];
+ const data_values = [];
+ const line_elements = [];
- for (var i = 0; i < lines.length; i++)
- if (lines[i] != null)
+ for (const line of lines)
+ if (line)
data_values.push([]);
- var info = {
+ const info = {
line_current: [],
line_average: [],
line_peak: []
};
/* prefill datasets */
- for (var i = 0; i < data_values.length; i++)
- for (var j = 0; j < data_wanted; j++)
+ for (let i = 0; i < data_values.length; i++)
+ for (let j = 0; j < data_wanted; j++)
data_values[i][j] = 0;
/* plot horizontal time interval lines */
- for (var i = width % (step * 60); i < width; i += step * 60) {
- var line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
- line.setAttribute('x1', i);
- line.setAttribute('y1', 0);
- line.setAttribute('x2', i);
- line.setAttribute('y2', '100%');
- line.setAttribute('style', 'stroke:black;stroke-width:0.1');
-
- var text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
- text.setAttribute('x', i + 5);
- text.setAttribute('y', 15);
- text.setAttribute('style', 'fill:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000');
- text.appendChild(document.createTextNode(Math.round((width - i) / step / 60) + 'm'));
+ for (let i = width % (step * 60); i < width; i += step * 60) {
+ const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
+ line.setAttribute('x1', i);
+ line.setAttribute('y1', 0);
+ line.setAttribute('x2', i);
+ line.setAttribute('y2', '100%');
+ line.setAttribute('style', 'stroke:black;stroke-width:0.1');
+
+ const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
+ text.setAttribute('x', i + 5);
+ text.setAttribute('y', 15);
+ text.setAttribute('style', 'fill:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000');
+ text.appendChild(document.createTextNode(Math.round((width - i) / step / 60) + 'm'));
G.appendChild(line);
G.appendChild(text);
});
},
- pollData: function() {
+ pollData() {
poll.add(L.bind(function() {
- var tasks = [];
+ const tasks = [];
- for (var i = 0; i < graphPolls.length; i++) {
- var ctx = graphPolls[i];
+ for (const ctx of graphPolls) {
tasks.push(L.resolveDefault(callLuciRealtimeStats('interface', ctx.ifname), []));
}
return Promise.all(tasks).then(L.bind(function(datasets) {
- for (var gi = 0; gi < graphPolls.length; gi++) {
- var ctx = graphPolls[gi],
- data = datasets[gi],
- values = ctx.values,
- lines = ctx.lines,
- info = ctx.info;
-
- var data_scale = 0;
- var data_wanted = Math.floor(ctx.width / ctx.step);
- var last_timestamp = NaN;
-
- for (var i = 0, di = 0; di < lines.length; di++) {
+ for (let gi = 0; gi < graphPolls.length; gi++) {
+ let ctx = graphPolls[gi];
+ const data = datasets[gi];
+ const values = ctx.values;
+ const lines = ctx.lines;
+ const info = ctx.info;
+
+ let data_scale = 0;
+ const data_wanted = Math.floor(ctx.width / ctx.step);
+ let last_timestamp = NaN;
+
+ for (let i = 0, di = 0; di < lines.length; di++) {
if (lines[di] == null)
continue;
- var multiply = (lines[di].multiply != null) ? lines[di].multiply : 1,
- offset = (lines[di].offset != null) ? lines[di].offset : 0;
+ const multiply = (lines[di].multiply != null) ? lines[di].multiply : 1;
+ const offset = (lines[di].offset != null) ? lines[di].offset : 0;
- for (var j = ctx.timestamp ? 0 : 1; j < data.length; j++) {
+ for (let j = ctx.timestamp ? 0 : 1; j < data.length; j++) {
/* skip overlapping entries */
if (data[j][0] <= ctx.timestamp)
continue;
/* cut off outdated entries */
ctx.fill = Math.min(ctx.fill, data_wanted);
- for (var i = 0; i < values.length; i++) {
- var len = values[i].length;
+ for (let i = 0; i < values.length; i++) {
+ const len = values[i].length;
values[i] = values[i].slice(len - data_wanted, len);
/* find peaks, averages */
info.line_peak[i] = NaN;
info.line_average[i] = 0;
- for (var j = 0; j < values[i].length; j++) {
+ for (let j = 0; j < values[i].length; j++) {
info.line_peak[i] = isNaN(info.line_peak[i]) ? values[i][j] : Math.max(info.line_peak[i], values[i][j]);
info.line_average[i] += values[i][j];
}
if (!isNaN(last_timestamp))
ctx.timestamp = last_timestamp;
- var size = Math.floor(Math.log2(info.peak)),
- div = Math.pow(2, size - (size % 10)),
- mult = info.peak / div,
- mult = (mult < 5) ? 2 : ((mult < 50) ? 10 : ((mult < 500) ? 100 : 1000));
+ const size = Math.floor(Math.log2(info.peak));
+ const div = Math.pow(2, size - (size % 10));
+ const p_o_d = info.peak / div;
+ const mult = (p_o_d < 5) ? 2 : ((p_o_d < 50) ? 10 : ((p_o_d < 500) ? 100 : 1000));
info.peak = info.peak + (mult * div) - (info.peak % (mult * div));
data_scale = ctx.height / info.peak;
/* plot data */
- for (var i = 0, di = 0; di < lines.length; di++) {
+ for (let i = 0, di = 0; di < lines.length; di++) {
if (lines[di] == null)
continue;
- var el = ctx.svg.firstElementChild.getElementById(lines[di].line),
- pt = '0,' + ctx.height,
- y = 0;
+ const el = ctx.svg.firstElementChild.getElementById(lines[di].line);
+ let pt = `0,${ctx.height}`;
+ let y = 0;
if (!el)
continue;
- for (var j = 0; j < values[i].length; j++) {
- var x = j * ctx.step;
+ for (let j = 0; j < values[i].length; j++) {
+ const x = j * ctx.step;
y = ctx.height - Math.floor(values[i][j] * data_scale);
//y -= Math.floor(y % (1 / data_scale));
y = isNaN(y) ? ctx.height : y;
- pt += ' ' + x + ',' + y;
+ pt += ` ${x},${y}`;
}
- pt += ' ' + ctx.width + ',' + y + ' ' + ctx.width + ',' + ctx.height;
+ pt += ` ${ctx.width},${y} ${ctx.width},${ctx.height}`;
el.setAttribute('points', pt);
}, this), pollInterval);
},
- loadSVG: function(src) {
+ loadSVG(src) {
return request.get(src).then(function(response) {
if (!response.ok)
throw new Error(response.statusText);
});
},
- render: function([svg, devs]) {
+ render([svg, devs]) {
var v = E('div', { 'class': 'cbi-map', 'id': 'map' }, E('div'));
- for (var i = 0; i < devs.length; i++) {
- var ifname = devs[i].getName();
- const ssid = devs[i].wif?.getSSID?.() || null;
+ for (const dev of devs) {
+ var ifname = dev.getName();
+ const ssid = dev.wif?.getSSID?.() || null;
- if (!ifname || !devs[i].isUp() || devs[i].wif?.isDisabled())
+ if (!ifname || !dev.isUp() || dev.wif?.isDisabled())
continue;
- var csvg = svg.cloneNode(true);
+ const csvg = svg.cloneNode(true);
v.firstElementChild.appendChild(E('div', { 'class': 'cbi-section', 'data-tab': ifname, 'data-tab-title': ssid ? `${ifname} ${ssid}` : ifname }, [
csvg,
]));
this.updateGraph(ifname, csvg, [ { line: 'rx', counter: true }, null, { line: 'tx', counter: true } ], function(svg, info) {
- var G = svg.firstElementChild, tab = svg.parentNode;
+ const G = svg.firstElementChild, tab = svg.parentNode;
G.getElementById('label_25').firstChild.data = rate(info.label_25).join('');
G.getElementById('label_50').firstChild.data = rate(info.label_50).join('');