Mercurial > code > home > repos > homeauto
diff service/wifi/src/wifi.ts @ 1464:32d134dbfb1e
start ts config files, but this doesn't share the streamed-graph code properly yet
Ignore-this: ef4e6fdf3369939b062caa5fdc2788e9
darcs-hash:e30e71ea5e8e9958c254c9210cdccde7a74b96bb
author | drewp <drewp@bigasterisk.com> |
---|---|
date | Tue, 17 Dec 2019 23:16:53 -0800 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/service/wifi/src/wifi.ts Tue Dec 17 23:16:53 2019 -0800 @@ -0,0 +1,193 @@ +import { html } from 'lit-html'; +import { NamedNode, DataFactory } from 'n3'; +const { literal, quad, namedNode } = DataFactory; +import * as sgmod from 'streamed-graph'; +import { Literal, Term, N3Store } from 'n3'; + +interface DevGroup { + connectedToAp: NamedNode, + wifiBand: NamedNode, + devs: Array<Dev> +} +interface Dev { + agoMin: number, + ipAddress: Literal, + dhcpHostname: string, + macAddress: Literal, + packetsPerSec: number, + bytesPerSec: number +} + +console.log('got', sgmod); + +const NS: any = { + room: 'http://projects.bigasterisk.com/room/' +} + +// from rdf-uri.html +const BigastUri = { + // not well defined for uri prefixes that are string prefixes of each other + compactUri: function (uri: string) { + if (uri === undefined) { + return uri; + } + if (typeof (uri) == "object") { throw new Error("type"); } + if (uri == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") { + return "a"; + } + for (var short of Object.keys(NS as any)) { + var prefix = NS[short]; + if (uri.indexOf(prefix) == 0) { + return short + ':' + uri.substr(prefix.length); + } + } + return uri; + }, + expandUri: function (s: string) { + for (var short of Object.keys(NS)) { + var prefix = NS[short]; + if (s.indexOf(short + ":") == 0) { + return prefix + s.substr(short.length + 1); + } + } + return s; + }, +}; + +// workaround for uris that don't have good labels in the graph +function labelFromUri(uri: NamedNode, prefix: string, tailsToLabels: any, defaultLabel: string) { + let label = defaultLabel === undefined ? uri.value : defaultLabel; + Object.entries(tailsToLabels).forEach(([tail, useLabel]) => { + if (uri.equals(namedNode(prefix + tail))) { + label = useLabel as string; + } + }); + return label +} + +// set out[suffix] = graph.get(subj, predPrefix+suffix) for all suffixes +function getProperties(store: N3Store, out: any, subject: Term, predPrefix: string, predSuffixes: Array<string>) { + predSuffixes.forEach((term) => { + store.forEach((q) => { + out[term] = q.object; + }, subject, namedNode(predPrefix + term), null, null); + + return out; + }); +} + +function graphView(store: N3Store, showGroups: boolean): void { + const grouped: Map<string, DevGroup> = new Map(); + store.forEach((q) => { + const row: any = { uri: q.subject }; + + getProperties(store, row, row.uri, 'room:', + ['dhcpHostname', 'ipAddress', 'macAddress', 'connectedToAp', 'wifiBand', 'connected', 'bytesPerSec', 'packetsPerSec']); + if (row.dhcpHostname && row.dhcpHostname.value) { + row.dhcpHostname = row.dhcpHostname.value; + } + if (!showGroups || row.connectedToAp) { + const key = (showGroups ? `${row.connectedToAp.toNT()}-${row.wifiBand.toNT()}` : 'all'); + if (!grouped.has(key)) { + grouped.set(key, { connectedToAp: row.connectedToAp, wifiBand: row.wifiBand, devs: [] }); + } + grouped.get(key)!.devs.push(row); + } else { + console.log('lost row', row); + } + if (row.connected) { + const t = new Date(row.connected.value); + const agoMs = (Date.now() as number) - (t as unknown as number); + row.agoMin = agoMs / 1000 / 60; + } + if (row.bytesPerSec) { row.bytesPerSec = row.bytesPerSec.valueOf() + ' B/s'; } + if (row.packetsPerSec) { row.packetsPerSec = row.packetsPerSec.valueOf() + ' p/s'; } + }, null, namedNode('rdf:type'), namedNode('room:NetworkedDevice'), null); +} + +const renderDevice = (dev: Dev) => { + const glow = Math.max(0, 1 - dev.agoMin / 60); + const agoReport = dev.agoMin < 360 ? ` (${Math.ceil(dev.agoMin * 10) / 10} minutes ago)` : ''; + return html` + <div class="dev" style="background: rgba(185, 5, 138, ${glow});"> + <span class="mac">${dev.macAddress.value}</span> + <span class="ip"><a href="http://${dev.ipAddress.value}/">${dev.ipAddress.value}</a></span> + <span class="packets">${dev.packetsPerSec}</span> + <span class="bytes">${dev.bytesPerSec}</span> + <span class="hostname">${dev.dhcpHostname}</span> + <span class="ago">${agoReport}</span> + <span class="links"> + <a href="https://bigasterisk.com/ntop/lua/host_details.lua?ifid=17&host=${dev.ipAddress.value}&page=flows">[flows]</a> + </span> + </div> + `; +}; + +const renderGroup = (key: string, group: DevGroup) => { + let label; + if (key != 'all') { + label = labelFromUri(group.connectedToAp, + 'http://bigasterisk.com/mac/', + { + 'a0:40:a0:6f:96:d5': "Main router (d5)", + '8c:3b:ad:c4:8d:ce': "Downstairs satellite (ce)", + 'a0:40:a0:6f:aa:f8': "Upstairs satellite (f8)", + }, + "unknown"); + + label += labelFromUri(group.wifiBand, + 'http://projects.bigasterisk.com/room/wifiBand/', + { + '5G': ' 5G', + '2.4G': ' 2.4G', + }, + "unknown"); + } + + const devs = group.devs; + function padIp(ip: string) { return ip.replace(/(\d+)/g, (m) => ('00' + m).slice(-3)); } + devs.sort((a, b) => { return padIp(a.ipAddress.value) > padIp(b.ipAddress.value) ? 1 : -1; }); + return html` + <tr> + <th>${label}</th> + <td> + <div>Devices:</div> + ${devs.map((d) => { return renderDevice(d); })} + </td> + </tr> + `; + /* +let groups=['?']; +const out = html` +<style> + + .report { font-family: sans-serif; } + section { margin-left: 1em; } + .dev { margin-bottom: 2px; } + .ip, .mac, .packets, .bytes { + display: inline-block; + font-family: monospace; + } + .packets, .bytes { + text-align: right; + padding-right: 1em; + } + .mac {color: #ccffcc; width: 11em; } + .ip {color: #b5b5d4; width: 6em; } + .packets {color: #2da1a5; width: 6em; } + .bytes {color: #a5912d; width: 9em; } + th,td { vertical-align: top; } + th { background: #333; } + td { background: #252525; } + +</style> +<div class="report"> + report + <table> + ${groups.map((row) => { return renderGroup(row[0], row[1]); })} + </table> +</div> +`; +return out;*/ +} +export { graphView }