Mercurial > code > home > repos > homeauto
comparison service/wifi/src/wifi-table.ts @ 1476:817da2dc80fc
kind of running with lit-element and polymer together. lots of data missing from table still
Ignore-this: db24e7b633929b01430b0794c1a065dc
darcs-hash:cdb1d499a42b869d6affa3ee226f408358a59cf4
author | drewp <drewp@bigasterisk.com> |
---|---|
date | Sun, 05 Jan 2020 23:18:27 -0800 |
parents | 4bbc68603168 |
children |
comparison
equal
deleted
inserted
replaced
1475:2e598cbcabf4 | 1476:817da2dc80fc |
---|---|
1 import { html } from 'lit-html'; | 1 import { html } from "lit-html"; |
2 import { NamedNode, DataFactory } from 'n3'; | 2 import { NamedNode, DataFactory } from "n3"; |
3 const { literal, quad, namedNode } = DataFactory; | 3 const { literal, quad, namedNode } = DataFactory; |
4 import * as sgmod from 'streamed-graph'; | 4 import * as sgmod from "streamed-graph"; |
5 import { Literal, Term, N3Store } from 'n3'; | 5 import { Literal, Term, N3Store } from "n3"; |
6 | 6 |
7 interface DevGroup { | 7 interface DevGroup { |
8 connectedToAp: NamedNode, | 8 connectedToAp: NamedNode; |
9 wifiBand: NamedNode, | 9 wifiBand: NamedNode; |
10 devs: Array<Dev> | 10 devs: Array<Dev>; |
11 } | 11 } |
12 interface Dev { | 12 interface Dev { |
13 agoMin: number, | 13 agoMin: number; |
14 ipAddress: Literal, | 14 ipAddress: Literal; |
15 dhcpHostname: string, | 15 dhcpHostname: string; |
16 macAddress: Literal, | 16 macAddress: Literal; |
17 packetsPerSec: number, | 17 packetsPerSec: number; |
18 bytesPerSec: number | 18 bytesPerSec: number; |
19 } | 19 } |
20 | 20 |
21 console.log('got', sgmod); | 21 console.log("got", sgmod); |
22 | 22 |
23 const NS: any = { | 23 const NS: any = { |
24 room: 'http://projects.bigasterisk.com/room/' | 24 room: "http://projects.bigasterisk.com/room/", |
25 } | 25 }; |
26 | 26 |
27 // from rdf-uri.html | 27 // from rdf-uri.html |
28 const BigastUri = { | 28 const BigastUri = { |
29 // not well defined for uri prefixes that are string prefixes of each other | 29 // not well defined for uri prefixes that are string prefixes of each other |
30 compactUri: function (uri: string) { | 30 compactUri: function(uri: string) { |
31 if (uri === undefined) { | 31 if (uri === undefined) { |
32 return uri; | 32 return uri; |
33 } | 33 } |
34 if (typeof (uri) == "object") { throw new Error("type"); } | 34 if (typeof uri == "object") { |
35 throw new Error("type"); | |
36 } | |
35 if (uri == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") { | 37 if (uri == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") { |
36 return "a"; | 38 return "a"; |
37 } | 39 } |
38 for (var short of Object.keys(NS as any)) { | 40 for (var short of Object.keys(NS as any)) { |
39 var prefix = NS[short]; | 41 var prefix = NS[short]; |
40 if (uri.indexOf(prefix) == 0) { | 42 if (uri.indexOf(prefix) == 0) { |
41 return short + ':' + uri.substr(prefix.length); | 43 return short + ":" + uri.substr(prefix.length); |
42 } | 44 } |
43 } | 45 } |
44 return uri; | 46 return uri; |
45 }, | 47 }, |
46 expandUri: function (s: string) { | 48 expandUri: function(s: string) { |
47 for (var short of Object.keys(NS)) { | 49 for (var short of Object.keys(NS)) { |
48 var prefix = NS[short]; | 50 var prefix = NS[short]; |
49 if (s.indexOf(short + ":") == 0) { | 51 if (s.indexOf(short + ":") == 0) { |
50 return prefix + s.substr(short.length + 1); | 52 return prefix + s.substr(short.length + 1); |
51 } | 53 } |
53 return s; | 55 return s; |
54 }, | 56 }, |
55 }; | 57 }; |
56 | 58 |
57 // workaround for uris that don't have good labels in the graph | 59 // workaround for uris that don't have good labels in the graph |
58 function labelFromUri(uri: NamedNode, prefix: string, tailsToLabels: any, defaultLabel: string) { | 60 function labelFromUri( |
61 uri: NamedNode, | |
62 prefix: string, | |
63 tailsToLabels: any, | |
64 defaultLabel: string | |
65 ) { | |
59 let label = defaultLabel === undefined ? uri.value : defaultLabel; | 66 let label = defaultLabel === undefined ? uri.value : defaultLabel; |
60 Object.entries(tailsToLabels).forEach(([tail, useLabel]) => { | 67 Object.entries(tailsToLabels).forEach(([tail, useLabel]) => { |
61 if (uri.equals(namedNode(prefix + tail))) { | 68 if (uri.equals(namedNode(prefix + tail))) { |
62 label = useLabel as string; | 69 label = useLabel as string; |
63 } | 70 } |
64 }); | 71 }); |
65 return label | 72 return label; |
66 } | 73 } |
67 | 74 |
68 // set out[suffix] = graph.get(subj, predPrefix+suffix) for all suffixes | 75 // 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>) { | 76 function getProperties( |
70 predSuffixes.forEach((term) => { | 77 store: N3Store, |
71 store.forEach((q) => { | 78 out: any, |
72 out[term] = q.object; | 79 subject: Term, |
73 }, subject, namedNode(predPrefix + term), null, null); | 80 predPrefix: string, |
81 predSuffixes: Array<string> | |
82 ) { | |
83 predSuffixes.forEach(term => { | |
84 store.forEach( | |
85 q => { | |
86 out[term] = q.object; | |
87 }, | |
88 subject, | |
89 namedNode(predPrefix + term), | |
90 null, | |
91 null | |
92 ); | |
74 | 93 |
75 return out; | 94 return out; |
76 }); | 95 }); |
77 } | 96 } |
78 | 97 |
79 function graphView(store: N3Store, showGroups: boolean): void { | 98 function graphView(store: N3Store, showGroups: boolean): void { |
80 const grouped: Map<string, DevGroup> = new Map(); | 99 const grouped: Map<string, DevGroup> = new Map(); |
81 store.forEach((q) => { | 100 store.forEach( |
82 const row: any = { uri: q.subject }; | 101 q => { |
83 | 102 const row: any = { uri: q.subject }; |
84 getProperties(store, row, row.uri, 'room:', | 103 |
85 ['dhcpHostname', 'ipAddress', 'macAddress', 'connectedToAp', 'wifiBand', 'connected', 'bytesPerSec', 'packetsPerSec']); | 104 getProperties(store, row, row.uri, "room:", [ |
86 if (row.dhcpHostname && row.dhcpHostname.value) { | 105 "dhcpHostname", |
87 row.dhcpHostname = row.dhcpHostname.value; | 106 "ipAddress", |
88 } | 107 "macAddress", |
89 if (!showGroups || row.connectedToAp) { | 108 "connectedToAp", |
90 const key = (showGroups ? `${row.connectedToAp.toNT()}-${row.wifiBand.toNT()}` : 'all'); | 109 "wifiBand", |
91 if (!grouped.has(key)) { | 110 "connected", |
92 grouped.set(key, { connectedToAp: row.connectedToAp, wifiBand: row.wifiBand, devs: [] }); | 111 "bytesPerSec", |
93 } | 112 "packetsPerSec", |
94 grouped.get(key)!.devs.push(row); | 113 ]); |
95 } else { | 114 if (row.dhcpHostname && row.dhcpHostname.value) { |
96 console.log('lost row', row); | 115 row.dhcpHostname = row.dhcpHostname.value; |
97 } | 116 } |
98 if (row.connected) { | 117 if (!showGroups || row.connectedToAp) { |
99 const t = new Date(row.connected.value); | 118 const key = showGroups |
100 const agoMs = (Date.now() as number) - (t as unknown as number); | 119 ? `${row.connectedToAp.toNT()}-${row.wifiBand.toNT()}` |
101 row.agoMin = agoMs / 1000 / 60; | 120 : "all"; |
102 } | 121 if (!grouped.has(key)) { |
103 if (row.bytesPerSec) { row.bytesPerSec = row.bytesPerSec.valueOf() + ' B/s'; } | 122 grouped.set(key, { |
104 if (row.packetsPerSec) { row.packetsPerSec = row.packetsPerSec.valueOf() + ' p/s'; } | 123 connectedToAp: row.connectedToAp, |
105 }, null, namedNode('rdf:type'), namedNode('room:NetworkedDevice'), null); | 124 wifiBand: row.wifiBand, |
125 devs: [], | |
126 }); | |
127 } | |
128 grouped.get(key)!.devs.push(row); | |
129 } else { | |
130 console.log("lost row", row); | |
131 } | |
132 if (row.connected) { | |
133 const t = new Date(row.connected.value); | |
134 const agoMs = (Date.now() as number) - ((t as unknown) as number); | |
135 row.agoMin = agoMs / 1000 / 60; | |
136 } | |
137 if (row.bytesPerSec) { | |
138 row.bytesPerSec = row.bytesPerSec.valueOf() + " B/s"; | |
139 } | |
140 if (row.packetsPerSec) { | |
141 row.packetsPerSec = row.packetsPerSec.valueOf() + " p/s"; | |
142 } | |
143 }, | |
144 null, | |
145 namedNode("rdf:type"), | |
146 namedNode("room:NetworkedDevice"), | |
147 null | |
148 ); | |
106 } | 149 } |
107 | 150 |
108 const renderDevice = (dev: Dev) => { | 151 const renderDevice = (dev: Dev) => { |
109 const glow = Math.max(0, 1 - dev.agoMin / 60); | 152 const glow = Math.max(0, 1 - dev.agoMin / 60); |
110 const agoReport = dev.agoMin < 360 ? ` (${Math.ceil(dev.agoMin * 10) / 10} minutes ago)` : ''; | 153 const agoReport = |
154 dev.agoMin < 360 ? ` (${Math.ceil(dev.agoMin * 10) / 10} minutes ago)` : ""; | |
111 return html` | 155 return html` |
112 <div class="dev" style="background: rgba(185, 5, 138, ${glow});"> | 156 <div class="dev" style="background: rgba(185, 5, 138, ${glow});"> |
113 <span class="mac">${dev.macAddress.value}</span> | 157 <span class="mac">${dev.macAddress.value}</span> |
114 <span class="ip"><a href="http://${dev.ipAddress.value}/">${dev.ipAddress.value}</a></span> | 158 <span class="ip" |
115 <span class="packets">${dev.packetsPerSec}</span> | 159 ><a href="http://${dev.ipAddress.value}/" |
116 <span class="bytes">${dev.bytesPerSec}</span> | 160 >${dev.ipAddress.value}</a |
117 <span class="hostname">${dev.dhcpHostname}</span> | 161 ></span |
118 <span class="ago">${agoReport}</span> | 162 > |
119 <span class="links"> | 163 <span class="packets">${dev.packetsPerSec}</span> |
120 <a href="https://bigasterisk.com/ntop/lua/host_details.lua?ifid=17&host=${dev.ipAddress.value}&page=flows">[flows]</a> | 164 <span class="bytes">${dev.bytesPerSec}</span> |
121 </span> | 165 <span class="hostname">${dev.dhcpHostname}</span> |
122 </div> | 166 <span class="ago">${agoReport}</span> |
123 `; | 167 <span class="links"> |
168 <a | |
169 href="https://bigasterisk.com/ntop/lua/host_details.lua?ifid=17&host=${dev | |
170 .ipAddress.value}&page=flows" | |
171 >[flows]</a | |
172 > | |
173 </span> | |
174 </div> | |
175 `; | |
124 }; | 176 }; |
125 | 177 |
126 const renderGroup = (key: string, group: DevGroup) => { | 178 const renderGroup = (key: string, group: DevGroup) => { |
127 let label; | 179 let label; |
128 if (key != 'all') { | 180 if (key != "all") { |
129 label = labelFromUri(group.connectedToAp, | 181 label = labelFromUri( |
130 'http://bigasterisk.com/mac/', | 182 group.connectedToAp, |
183 "http://bigasterisk.com/mac/", | |
131 { | 184 { |
132 'a0:40:a0:6f:96:d5': "Main router (d5)", | 185 "a0:40:a0:6f:96:d5": "Main router (d5)", |
133 '8c:3b:ad:c4:8d:ce': "Downstairs satellite (ce)", | 186 "8c:3b:ad:c4:8d:ce": "Downstairs satellite (ce)", |
134 'a0:40:a0:6f:aa:f8': "Upstairs satellite (f8)", | 187 "a0:40:a0:6f:aa:f8": "Upstairs satellite (f8)", |
135 }, | 188 }, |
136 "unknown"); | 189 "unknown" |
137 | 190 ); |
138 label += labelFromUri(group.wifiBand, | 191 |
139 'http://projects.bigasterisk.com/room/wifiBand/', | 192 label += labelFromUri( |
193 group.wifiBand, | |
194 "http://projects.bigasterisk.com/room/wifiBand/", | |
140 { | 195 { |
141 '5G': ' 5G', | 196 "5G": " 5G", |
142 '2.4G': ' 2.4G', | 197 "2.4G": " 2.4G", |
143 }, | 198 }, |
144 "unknown"); | 199 "unknown" |
200 ); | |
145 } | 201 } |
146 | 202 |
147 const devs = group.devs; | 203 const devs = group.devs; |
148 function padIp(ip: string) { return ip.replace(/(\d+)/g, (m) => ('00' + m).slice(-3)); } | 204 function padIp(ip: string) { |
149 devs.sort((a, b) => { return padIp(a.ipAddress.value) > padIp(b.ipAddress.value) ? 1 : -1; }); | 205 return ip.replace(/(\d+)/g, m => ("00" + m).slice(-3)); |
206 } | |
207 devs.sort((a, b) => { | |
208 return padIp(a.ipAddress.value) > padIp(b.ipAddress.value) ? 1 : -1; | |
209 }); | |
150 return html` | 210 return html` |
151 <tr> | 211 <tr> |
152 <th>${label}</th> | 212 <th>${label}</th> |
153 <td> | 213 <td> |
154 <div>Devices:</div> | 214 <div>Devices:</div> |
155 ${devs.map((d) => { return renderDevice(d); })} | 215 ${devs.map(d => { |
156 </td> | 216 return renderDevice(d); |
157 </tr> | 217 })} |
158 `; | 218 </td> |
219 </tr> | |
220 `; | |
159 /* | 221 /* |
160 let groups=['?']; | 222 let groups=['?']; |
161 const out = html` | 223 const out = html` |
162 <style> | 224 <style> |
163 | 225 |
187 ${groups.map((row) => { return renderGroup(row[0], row[1]); })} | 249 ${groups.map((row) => { return renderGroup(row[0], row[1]); })} |
188 </table> | 250 </table> |
189 </div> | 251 </div> |
190 `; | 252 `; |
191 return out;*/ | 253 return out;*/ |
192 } | 254 }; |
193 export { graphView } | 255 export { graphView }; |