comparison service/wifi/src/wifi-table.ts @ 1473:4bbc68603168

npm run build works now, accessing streamed-graph. But, s-g isn't in the output bundle yet. Ignore-this: 2b08220ad8d275f4dd242c3aa1a8647a darcs-hash:713c0960d19658e35685d64dc855ca63e1fde660
author drewp <drewp@bigasterisk.com>
date Sun, 29 Dec 2019 19:41:48 -0800
parents
children 817da2dc80fc
comparison
equal deleted inserted replaced
1472:dda4c0bcca65 1473:4bbc68603168
1 import { html } from 'lit-html';
2 import { NamedNode, DataFactory } from 'n3';
3 const { literal, quad, namedNode } = DataFactory;
4 import * as sgmod from 'streamed-graph';
5 import { Literal, Term, N3Store } from 'n3';
6
7 interface DevGroup {
8 connectedToAp: NamedNode,
9 wifiBand: NamedNode,
10 devs: Array<Dev>
11 }
12 interface Dev {
13 agoMin: number,
14 ipAddress: Literal,
15 dhcpHostname: string,
16 macAddress: Literal,
17 packetsPerSec: number,
18 bytesPerSec: number
19 }
20
21 console.log('got', sgmod);
22
23 const NS: any = {
24 room: 'http://projects.bigasterisk.com/room/'
25 }
26
27 // from rdf-uri.html
28 const BigastUri = {
29 // not well defined for uri prefixes that are string prefixes of each other
30 compactUri: function (uri: string) {
31 if (uri === undefined) {
32 return uri;
33 }
34 if (typeof (uri) == "object") { throw new Error("type"); }
35 if (uri == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") {
36 return "a";
37 }
38 for (var short of Object.keys(NS as any)) {
39 var prefix = NS[short];
40 if (uri.indexOf(prefix) == 0) {
41 return short + ':' + uri.substr(prefix.length);
42 }
43 }
44 return uri;
45 },
46 expandUri: function (s: string) {
47 for (var short of Object.keys(NS)) {
48 var prefix = NS[short];
49 if (s.indexOf(short + ":") == 0) {
50 return prefix + s.substr(short.length + 1);
51 }
52 }
53 return s;
54 },
55 };
56
57 // workaround for uris that don't have good labels in the graph
58 function labelFromUri(uri: NamedNode, prefix: string, tailsToLabels: any, defaultLabel: string) {
59 let label = defaultLabel === undefined ? uri.value : defaultLabel;
60 Object.entries(tailsToLabels).forEach(([tail, useLabel]) => {
61 if (uri.equals(namedNode(prefix + tail))) {
62 label = useLabel as string;
63 }
64 });
65 return label
66 }
67
68 // set out[suffix] = graph.get(subj, predPrefix+suffix) for all suffixes
69 function getProperties(store: N3Store, out: any, subject: Term, predPrefix: string, predSuffixes: Array<string>) {
70 predSuffixes.forEach((term) => {
71 store.forEach((q) => {
72 out[term] = q.object;
73 }, subject, namedNode(predPrefix + term), null, null);
74
75 return out;
76 });
77 }
78
79 function graphView(store: N3Store, showGroups: boolean): void {
80 const grouped: Map<string, DevGroup> = new Map();
81 store.forEach((q) => {
82 const row: any = { uri: q.subject };
83
84 getProperties(store, row, row.uri, 'room:',
85 ['dhcpHostname', 'ipAddress', 'macAddress', 'connectedToAp', 'wifiBand', 'connected', 'bytesPerSec', 'packetsPerSec']);
86 if (row.dhcpHostname && row.dhcpHostname.value) {
87 row.dhcpHostname = row.dhcpHostname.value;
88 }
89 if (!showGroups || row.connectedToAp) {
90 const key = (showGroups ? `${row.connectedToAp.toNT()}-${row.wifiBand.toNT()}` : 'all');
91 if (!grouped.has(key)) {
92 grouped.set(key, { connectedToAp: row.connectedToAp, wifiBand: row.wifiBand, devs: [] });
93 }
94 grouped.get(key)!.devs.push(row);
95 } else {
96 console.log('lost row', row);
97 }
98 if (row.connected) {
99 const t = new Date(row.connected.value);
100 const agoMs = (Date.now() as number) - (t as unknown as number);
101 row.agoMin = agoMs / 1000 / 60;
102 }
103 if (row.bytesPerSec) { row.bytesPerSec = row.bytesPerSec.valueOf() + ' B/s'; }
104 if (row.packetsPerSec) { row.packetsPerSec = row.packetsPerSec.valueOf() + ' p/s'; }
105 }, null, namedNode('rdf:type'), namedNode('room:NetworkedDevice'), null);
106 }
107
108 const renderDevice = (dev: Dev) => {
109 const glow = Math.max(0, 1 - dev.agoMin / 60);
110 const agoReport = dev.agoMin < 360 ? ` (${Math.ceil(dev.agoMin * 10) / 10} minutes ago)` : '';
111 return html`
112 <div class="dev" style="background: rgba(185, 5, 138, ${glow});">
113 <span class="mac">${dev.macAddress.value}</span>
114 <span class="ip"><a href="http://${dev.ipAddress.value}/">${dev.ipAddress.value}</a></span>
115 <span class="packets">${dev.packetsPerSec}</span>
116 <span class="bytes">${dev.bytesPerSec}</span>
117 <span class="hostname">${dev.dhcpHostname}</span>
118 <span class="ago">${agoReport}</span>
119 <span class="links">
120 <a href="https://bigasterisk.com/ntop/lua/host_details.lua?ifid=17&amp;host=${dev.ipAddress.value}&amp;page=flows">[flows]</a>
121 </span>
122 </div>
123 `;
124 };
125
126 const renderGroup = (key: string, group: DevGroup) => {
127 let label;
128 if (key != 'all') {
129 label = labelFromUri(group.connectedToAp,
130 'http://bigasterisk.com/mac/',
131 {
132 'a0:40:a0:6f:96:d5': "Main router (d5)",
133 '8c:3b:ad:c4:8d:ce': "Downstairs satellite (ce)",
134 'a0:40:a0:6f:aa:f8': "Upstairs satellite (f8)",
135 },
136 "unknown");
137
138 label += labelFromUri(group.wifiBand,
139 'http://projects.bigasterisk.com/room/wifiBand/',
140 {
141 '5G': ' 5G',
142 '2.4G': ' 2.4G',
143 },
144 "unknown");
145 }
146
147 const devs = group.devs;
148 function padIp(ip: string) { return ip.replace(/(\d+)/g, (m) => ('00' + m).slice(-3)); }
149 devs.sort((a, b) => { return padIp(a.ipAddress.value) > padIp(b.ipAddress.value) ? 1 : -1; });
150 return html`
151 <tr>
152 <th>${label}</th>
153 <td>
154 <div>Devices:</div>
155 ${devs.map((d) => { return renderDevice(d); })}
156 </td>
157 </tr>
158 `;
159 /*
160 let groups=['?'];
161 const out = html`
162 <style>
163
164 .report { font-family: sans-serif; }
165 section { margin-left: 1em; }
166 .dev { margin-bottom: 2px; }
167 .ip, .mac, .packets, .bytes {
168 display: inline-block;
169 font-family: monospace;
170 }
171 .packets, .bytes {
172 text-align: right;
173 padding-right: 1em;
174 }
175 .mac {color: #ccffcc; width: 11em; }
176 .ip {color: #b5b5d4; width: 6em; }
177 .packets {color: #2da1a5; width: 6em; }
178 .bytes {color: #a5912d; width: 9em; }
179 th,td { vertical-align: top; }
180 th { background: #333; }
181 td { background: #252525; }
182
183 </style>
184 <div class="report">
185 report
186 <table>
187 ${groups.map((row) => { return renderGroup(row[0], row[1]); })}
188 </table>
189 </div>
190 `;
191 return out;*/
192 }
193 export { graphView }