Mercurial > code > home > repos > homeauto
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&host=${dev.ipAddress.value}&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 } |