smart-home-engine 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/web/assets/{index-Bvl2uECO.css → index-Bu5o4KXc.css} +1 -1
- package/dist/web/assets/index-CqYTIaIG.js +306 -0
- package/dist/web/assets/{tsMode-BJVHqGQB.js → tsMode-20i8zomj.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/src/matter/thread-mesh.js +62 -23
- package/dist/web/assets/index-DLP7FxoS.js +0 -305
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{m as O}from"./monaco-langs-DKJI_o9J.js";import{t as I}from"./index-
|
|
1
|
+
import{m as O}from"./monaco-langs-DKJI_o9J.js";import{t as I}from"./index-CqYTIaIG.js";/*!-----------------------------------------------------------------------------
|
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
3
|
* Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
|
|
4
4
|
* Released under the MIT license
|
package/dist/web/index.html
CHANGED
|
@@ -175,10 +175,10 @@
|
|
|
175
175
|
}
|
|
176
176
|
})();
|
|
177
177
|
</script>
|
|
178
|
-
<script type="module" crossorigin src="/assets/index-
|
|
178
|
+
<script type="module" crossorigin src="/assets/index-CqYTIaIG.js"></script>
|
|
179
179
|
<link rel="modulepreload" crossorigin href="/assets/monaco-langs-DKJI_o9J.js">
|
|
180
180
|
<link rel="stylesheet" crossorigin href="/assets/monaco-langs-DyX1CsEw.css">
|
|
181
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
181
|
+
<link rel="stylesheet" crossorigin href="/assets/index-Bu5o4KXc.css">
|
|
182
182
|
</head>
|
|
183
183
|
<body>
|
|
184
184
|
<div id="app"></div>
|
package/package.json
CHANGED
|
@@ -46,6 +46,39 @@ function hex64(v) {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
/** LQI 3 → good, 2 → fair, 1 → poor, 0 → unknown (the OHF dashboard's colours). */
|
|
49
|
+
/**
|
|
50
|
+
* A Thread partition ID as 8 hex digits: devices report it as a number (Network Diagnostics), border
|
|
51
|
+
* routers as hex (their mDNS TXT record) — the same partition must compare equal.
|
|
52
|
+
*/
|
|
53
|
+
function partitionHex(v) {
|
|
54
|
+
if (typeof v === 'number' || typeof v === 'bigint' || /^\d+$/.test(String(v))) {
|
|
55
|
+
return Number(v).toString(16).toUpperCase().padStart(8, '0');
|
|
56
|
+
}
|
|
57
|
+
return String(v).toUpperCase().padStart(8, '0');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** an IPv6 address from 16 bytes (a Uint8Array or `{ $bytes }`) in the usual short form */
|
|
61
|
+
function _ipv6(v) {
|
|
62
|
+
const buf = v?.$bytes ? Buffer.from(v.$bytes, 'hex') : ArrayBuffer.isView(v) ? Buffer.from(v.buffer, v.byteOffset, v.byteLength) : null;
|
|
63
|
+
if (!buf || buf.length !== 16) return null;
|
|
64
|
+
const groups = [];
|
|
65
|
+
for (let i = 0; i < 16; i += 2) groups.push(buf.readUInt16BE(i).toString(16));
|
|
66
|
+
// the longest run of two or more zero groups becomes "::"
|
|
67
|
+
let best = { at: -1, len: 0 };
|
|
68
|
+
for (let i = 0; i < 8; ) {
|
|
69
|
+
if (groups[i] !== '0') {
|
|
70
|
+
i++;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
let j = i;
|
|
74
|
+
while (j < 8 && groups[j] === '0') j++;
|
|
75
|
+
if (j - i > best.len && j - i > 1) best = { at: i, len: j - i };
|
|
76
|
+
i = j;
|
|
77
|
+
}
|
|
78
|
+
if (best.at < 0) return groups.join(':');
|
|
79
|
+
return `${groups.slice(0, best.at).join(':')}::${groups.slice(best.at + best.len).join(':')}`;
|
|
80
|
+
}
|
|
81
|
+
|
|
49
82
|
function lqiQuality(lqi) {
|
|
50
83
|
if (lqi >= 3) return 'good';
|
|
51
84
|
if (lqi === 2) return 'fair';
|
|
@@ -68,7 +101,7 @@ function rssiQuality(rssi) {
|
|
|
68
101
|
* @param {object[]} bindings M13's binding list
|
|
69
102
|
*/
|
|
70
103
|
function buildGraph(nodes, borderRouters = [], bindings = [], meshcop = []) {
|
|
71
|
-
const out = { nodes: [], links: [], networks: [], meshcop: { nodes: 0, networks: [] } };
|
|
104
|
+
const out = { nodes: [], links: [], networks: [], hidden: { wifi: 0, other: 0 }, meshcop: { nodes: 0, networks: [] } };
|
|
72
105
|
const byExt = new Map();
|
|
73
106
|
const byRloc = new Map();
|
|
74
107
|
const byNodeId = new Map();
|
|
@@ -87,6 +120,8 @@ function buildGraph(nodes, borderRouters = [], bindings = [], meshcop = []) {
|
|
|
87
120
|
channel: n.thread.channel ?? null,
|
|
88
121
|
partitionId: n.thread.partitionId ?? null,
|
|
89
122
|
networkName: n.thread.networkName ?? null,
|
|
123
|
+
extPanId: n.thread.extPanId ?? null,
|
|
124
|
+
ipv6: n.thread.ipv6 ?? [],
|
|
90
125
|
neighbours: (n.thread.neighborTable ?? []).length,
|
|
91
126
|
routes: (n.thread.routeTable ?? []).length,
|
|
92
127
|
readAt: n.thread.readAt ?? null,
|
|
@@ -95,23 +130,10 @@ function buildGraph(nodes, borderRouters = [], bindings = [], meshcop = []) {
|
|
|
95
130
|
byNodeId.set(n.nodeId, g);
|
|
96
131
|
if (g.extAddress) byExt.set(g.extAddress, g);
|
|
97
132
|
if (g.rloc16 !== null) byRloc.set(g.rloc16, g);
|
|
98
|
-
} else if (n.wifi) {
|
|
99
|
-
const g = {
|
|
100
|
-
id: `node:${n.nodeId}`,
|
|
101
|
-
kind: 'wifi',
|
|
102
|
-
nodeId: n.nodeId,
|
|
103
|
-
name: n.name ?? `Node ${n.nodeId}`,
|
|
104
|
-
online: !!n.online,
|
|
105
|
-
rssi: n.wifi.rssi ?? null,
|
|
106
|
-
bssid: n.wifi.bssid ?? null,
|
|
107
|
-
quality: rssiQuality(n.wifi.rssi),
|
|
108
|
-
};
|
|
109
|
-
out.nodes.push(g);
|
|
110
|
-
byNodeId.set(n.nodeId, g);
|
|
111
133
|
} else {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
134
|
+
// Wi-Fi, Ethernet and devices without diagnostics (offline, bridges) are not part of a Thread
|
|
135
|
+
// mesh: counted for the caption, not drawn
|
|
136
|
+
out.hidden[n.wifi ? 'wifi' : 'other']++;
|
|
115
137
|
}
|
|
116
138
|
}
|
|
117
139
|
// border routers: a graph node each, joined to a fabric node when the ext address matches
|
|
@@ -133,6 +155,9 @@ function buildGraph(nodes, borderRouters = [], bindings = [], meshcop = []) {
|
|
|
133
155
|
role: br.state?.role ?? null,
|
|
134
156
|
online: true,
|
|
135
157
|
rloc16: br.rest?.node?.rloc16 ?? null,
|
|
158
|
+
partitionId: br.partitionId ?? null,
|
|
159
|
+
addresses: br.addresses ?? [],
|
|
160
|
+
hostname: br.hostname ?? null,
|
|
136
161
|
};
|
|
137
162
|
out.nodes.push(g);
|
|
138
163
|
if (ext) byExt.set(ext, g);
|
|
@@ -158,6 +183,8 @@ function buildGraph(nodes, borderRouters = [], bindings = [], meshcop = []) {
|
|
|
158
183
|
extAddress: ext,
|
|
159
184
|
rloc16: nb.rloc16 ?? null,
|
|
160
185
|
online: true,
|
|
186
|
+
networkName: from.networkName ?? null,
|
|
187
|
+
extPanId: from.extPanId ?? null,
|
|
161
188
|
explanation:
|
|
162
189
|
"A neighbour of a device in she's fabric that is not paired with she: a device of another controller, or a border router that announces a different address.",
|
|
163
190
|
};
|
|
@@ -263,14 +290,24 @@ function buildGraph(nodes, borderRouters = [], bindings = [], meshcop = []) {
|
|
|
263
290
|
label: `${b.sourceEndpointName ?? 'ep ' + b.sourceEndpointId} → ${b.targetEndpointName ?? 'ep ' + b.endpoint}`,
|
|
264
291
|
});
|
|
265
292
|
}
|
|
266
|
-
// networks
|
|
293
|
+
// the Thread networks: every drawn node belongs to one (by extended PAN ID, else by name), so the graph
|
|
294
|
+
// can group them — border routers of the same network included, whether in she's fabric or not
|
|
267
295
|
const nets = new Map();
|
|
268
296
|
for (const g of out.nodes) {
|
|
269
|
-
if (g.
|
|
270
|
-
|
|
271
|
-
|
|
297
|
+
if (!g.extPanId && g.networkName) {
|
|
298
|
+
const byName = out.nodes.find((x) => x.extPanId && x.networkName === g.networkName);
|
|
299
|
+
if (byName) g.extPanId = byName.extPanId;
|
|
300
|
+
}
|
|
301
|
+
const key = g.extPanId || (g.networkName ? `name:${g.networkName}` : null);
|
|
302
|
+
if (!key) continue;
|
|
303
|
+
g.network = key;
|
|
304
|
+
const n = nets.get(key) ?? { key, extPanId: g.extPanId ?? null, networkName: g.networkName ?? null, partitions: new Set(), channel: null, nodes: 0, borderRouters: 0 };
|
|
305
|
+
if (!n.networkName && g.networkName) n.networkName = g.networkName;
|
|
306
|
+
if (g.partitionId !== null && g.partitionId !== undefined) n.partitions.add(partitionHex(g.partitionId));
|
|
307
|
+
if (n.channel === null && g.channel !== null && g.channel !== undefined) n.channel = g.channel;
|
|
272
308
|
n.nodes++;
|
|
273
|
-
|
|
309
|
+
if (g.kind === 'border-router' || g.borderRouter) n.borderRouters++;
|
|
310
|
+
nets.set(key, n);
|
|
274
311
|
}
|
|
275
312
|
out.networks = [...nets.values()].map((n) => ({ ...n, partitions: [...n.partitions] }));
|
|
276
313
|
return out;
|
|
@@ -297,6 +334,8 @@ function _nodeData(node, nodeId) {
|
|
|
297
334
|
partitionId: tnd.partitionId === undefined || tnd.partitionId === null ? null : Number(tnd.partitionId),
|
|
298
335
|
leaderRouterId: tnd.leaderRouterId ?? null,
|
|
299
336
|
networkName: tnd.networkName ?? null,
|
|
337
|
+
extPanId: hex64(tnd.extendedPanId),
|
|
338
|
+
ipv6: (threadIf?.iPv6Addresses ?? []).map(_ipv6).filter(Boolean),
|
|
300
339
|
neighborTable: fresh?.neighborTable ?? (Array.isArray(tnd.neighborTable) ? tnd.neighborTable : []),
|
|
301
340
|
routeTable: fresh?.routeTable ?? (Array.isArray(tnd.routeTable) ? tnd.routeTable : []),
|
|
302
341
|
readAt: fresh?.readAt ?? null,
|
|
@@ -493,4 +532,4 @@ function stop() {
|
|
|
493
532
|
_lastRefresh = null;
|
|
494
533
|
}
|
|
495
534
|
|
|
496
|
-
module.exports = { buildGraph, getMesh, refresh, meshcopQuery, start, stop, hex64, lqiQuality, rssiQuality, ROLES, _tables, _meshcop, _meshcopNode };
|
|
535
|
+
module.exports = { _ipv6, partitionHex, buildGraph, getMesh, refresh, meshcopQuery, start, stop, hex64, lqiQuality, rssiQuality, ROLES, _tables, _meshcop, _meshcopNode };
|