"use strict" define([ "lib/helper", "lib/gui/signalgraph", "lib/gui/signal"], function (Helper, SignalGraph, Signal) { var graphColors = ["#396AB1", "#DA7C30", "#3E9651", "#CC2529", "#535154", "#6B4C9A", "#922428", "#948B3D"] //graphColors = ["#7293CB", "#E1974C", "#84BA5B", "#D35E60", "#808585", "#9067A7", "#AB6857", "#CCC210"]; var inactiveTime = 200 function SignalEntry(graph, color, stream) { var signal = new Signal(color) var remove = graph.add(signal) var unsubscribe = stream.onValue(update) this.destroy = function () { unsubscribe() remove() } this.getSignal = function () { return signal } return this function update(d) { if ("wifi" in d) signal.set(d.wifi.inactive > inactiveTime ? null : d.wifi.signal) } } function TableEntry(parent, nodeInfo, color, stream, mgmtBus, signal) { var el = document.createElement("tr") parent.appendChild(el) var tdHostname = document.createElement("td") var tdTQ = document.createElement("td") var tdSignal = document.createElement("td") var tdDistance = document.createElement("td") var tdInactive = document.createElement("td") el.appendChild(tdHostname) el.appendChild(tdTQ) el.appendChild(tdSignal) el.appendChild(tdDistance) el.appendChild(tdInactive) var marker = document.createElement("span") marker.textContent = "⬤ " marker.style.color = color tdHostname.appendChild(marker) var hostname = document.createElement("span") tdHostname.appendChild(hostname) var infoSet = false var unsubscribe = stream.onValue(update) el.onmouseenter = function () { el.classList.add("highlight") signal.setHighlight(true) } el.onmouseleave = function () { el.classList.remove("highlight") signal.setHighlight(false) } el.destroy = function () { unsubscribe() parent.removeChild(el) } return el function update(d) { if ("wifi" in d) { var signal = d.wifi.signal var inactive = d.wifi.inactive el.classList.toggle("inactive", inactive > inactiveTime) tdSignal.textContent = signal tdInactive.textContent = Math.round(inactive / 1000) + " s" } if ("batadv" in d) tdTQ.textContent = Math.round(d.batadv.tq / 2.55) + " %" else tdTQ.textContent = "‒" if (infoSet) return if ("nodeInfo" in d) { infoSet = true var link = document.createElement("a") link.textContent = d.nodeInfo.hostname link.href = "#" link.nodeInfo = d.nodeInfo link.onclick = function () { mgmtBus.pushEvent("goto", this.nodeInfo) return false } while (hostname.firstChild) hostname.removeChild(hostname.firstChild) hostname.appendChild(link) try { var distance = Helper.haversine(nodeInfo.location.latitude, nodeInfo.location.longitude, d.nodeInfo.location.latitude, d.nodeInfo.location.longitude) tdDistance.textContent = Math.round(distance * 1000) + " m" } catch (e) { tdDistance.textContent = "‒" } } else hostname.textContent = d.id } } function Interface(parent, nodeInfo, iface, stream, mgmtBus) { var colors = graphColors.slice(0) var el = document.createElement("div") el.ifname = iface parent.appendChild(el) var h = document.createElement("h3") h.textContent = iface el.appendChild(h) var table = document.createElement("table") var tr = document.createElement("tr") table.appendChild(tr) table.classList.add("datatable") var th = document.createElement("th") th.textContent = "Knoten" tr.appendChild(th) th = document.createElement("th") th.textContent = "TQ" tr.appendChild(th) th = document.createElement("th") th.textContent = "dBm" tr.appendChild(th) th = document.createElement("th") th.textContent = "Entfernung" tr.appendChild(th) th = document.createElement("th") th.textContent = "Inaktiv" tr.appendChild(th) el.appendChild(table) var wrapper = document.createElement("div") wrapper.className = "signalgraph" el.appendChild(wrapper) var canvas = document.createElement("canvas") canvas.className = "signal-history" canvas.height = 200 wrapper.appendChild(canvas) var graph = new SignalGraph(canvas, -100, 0, true) var stopStream = stream.skipDuplicates(sameKeys).onValue(update) var managedNeighbours = {} function update(d) { var notUpdated = new Set() var id for (id in managedNeighbours) notUpdated.add(id) for (id in d) { if (!(id in managedNeighbours)) { var neighbourStream = stream.map("." + id).filter( function (d) { return d !== undefined }) var color = colors.shift() var signal = new SignalEntry(graph, color, neighbourStream) managedNeighbours[id] = { views: [ signal, new TableEntry(table, nodeInfo, color, neighbourStream, mgmtBus, signal.getSignal()) ], color: color } } notUpdated.delete(id) } for (id in notUpdated) { managedNeighbours[id].views.forEach( function (d) { d.destroy() }) colors.push(managedNeighbours[id].color) delete managedNeighbours[id] } } el.destroy = function () { stopStream() for (var id in managedNeighbours) managedNeighbours[id].views.forEach( function (d) { d.destroy() }) el.removeChild(h) el.removeChild(wrapper) el.removeChild(table) } } function sameKeys(a, b) { a = Object.keys(a).sort() b = Object.keys(b).sort() return !(a < b || a > b) } return function (nodeInfo, stream, mgmtBus) { var stopStream, div function render(el) { div = document.createElement("div") el.appendChild(div) stopStream = stream.skipDuplicates(sameKeys).onValue(update) function update(d) { var have = {} var remove = [] if (div.hasChildNodes()) { var children = div.childNodes for (var i = 0; i < children.length; i++) { var a = children[i] if (a.ifname in d) have[a.ifname] = true else { a.destroy() remove.push(a) } } } remove.forEach(function (d) { div.removeChild(d) }) for (var k in d) if (!(k in have)) new Interface(div, nodeInfo, k, stream.map("." + k), mgmtBus) } } function destroy() { stopStream() while (div.firstChild) { div.firstChild.destroy() div.removeChild(div.firstChild) } } return { title: document.createTextNode("Nachbarknoten") , render: render , destroy: destroy } } })