@matter-server/dashboard 0.3.2 → 0.3.3

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.
Files changed (104) hide show
  1. package/dist/esm/pages/cluster-commands/base-cluster-commands.d.ts +2 -2
  2. package/dist/esm/pages/cluster-commands/base-cluster-commands.d.ts.map +1 -1
  3. package/dist/esm/pages/cluster-commands/base-cluster-commands.js.map +1 -1
  4. package/dist/esm/pages/cluster-commands/clusters/basic-information-commands.d.ts +36 -0
  5. package/dist/esm/pages/cluster-commands/clusters/basic-information-commands.d.ts.map +1 -0
  6. package/dist/esm/pages/cluster-commands/clusters/basic-information-commands.js +159 -0
  7. package/dist/esm/pages/cluster-commands/clusters/basic-information-commands.js.map +6 -0
  8. package/dist/esm/pages/cluster-commands/index.d.ts +1 -0
  9. package/dist/esm/pages/cluster-commands/index.d.ts.map +1 -1
  10. package/dist/esm/pages/cluster-commands/index.js +1 -0
  11. package/dist/esm/pages/cluster-commands/index.js.map +1 -1
  12. package/dist/esm/pages/components/footer.d.ts.map +1 -1
  13. package/dist/esm/pages/components/footer.js +4 -7
  14. package/dist/esm/pages/components/footer.js.map +1 -1
  15. package/dist/esm/pages/components/header.d.ts +5 -0
  16. package/dist/esm/pages/components/header.d.ts.map +1 -1
  17. package/dist/esm/pages/components/header.js +75 -0
  18. package/dist/esm/pages/components/header.js.map +1 -1
  19. package/dist/esm/pages/components/node-details.js +1 -1
  20. package/dist/esm/pages/components/node-details.js.map +1 -1
  21. package/dist/esm/pages/components/server-details.d.ts.map +1 -1
  22. package/dist/esm/pages/components/server-details.js +0 -1
  23. package/dist/esm/pages/components/server-details.js.map +1 -1
  24. package/dist/esm/pages/matter-dashboard-app.d.ts +12 -0
  25. package/dist/esm/pages/matter-dashboard-app.d.ts.map +1 -1
  26. package/dist/esm/pages/matter-dashboard-app.js +84 -4
  27. package/dist/esm/pages/matter-dashboard-app.js.map +1 -1
  28. package/dist/esm/pages/matter-network-view.d.ts +52 -0
  29. package/dist/esm/pages/matter-network-view.d.ts.map +1 -0
  30. package/dist/esm/pages/matter-network-view.js +309 -0
  31. package/dist/esm/pages/matter-network-view.js.map +6 -0
  32. package/dist/esm/pages/matter-node-view.d.ts.map +1 -1
  33. package/dist/esm/pages/matter-node-view.js +70 -1
  34. package/dist/esm/pages/matter-node-view.js.map +1 -1
  35. package/dist/esm/pages/matter-server-view.d.ts +4 -0
  36. package/dist/esm/pages/matter-server-view.d.ts.map +1 -1
  37. package/dist/esm/pages/matter-server-view.js +16 -1
  38. package/dist/esm/pages/matter-server-view.js.map +1 -1
  39. package/dist/esm/pages/network/base-network-graph.d.ts +74 -0
  40. package/dist/esm/pages/network/base-network-graph.d.ts.map +1 -0
  41. package/dist/esm/pages/network/base-network-graph.js +403 -0
  42. package/dist/esm/pages/network/base-network-graph.js.map +6 -0
  43. package/dist/esm/pages/network/device-icons.d.ts +52 -0
  44. package/dist/esm/pages/network/device-icons.d.ts.map +1 -0
  45. package/dist/esm/pages/network/device-icons.js +197 -0
  46. package/dist/esm/pages/network/device-icons.js.map +6 -0
  47. package/dist/esm/pages/network/device-panel.d.ts +31 -0
  48. package/dist/esm/pages/network/device-panel.d.ts.map +1 -0
  49. package/dist/esm/pages/network/device-panel.js +183 -0
  50. package/dist/esm/pages/network/device-panel.js.map +6 -0
  51. package/dist/esm/pages/network/network-details.d.ts +47 -0
  52. package/dist/esm/pages/network/network-details.d.ts.map +1 -0
  53. package/dist/esm/pages/network/network-details.js +686 -0
  54. package/dist/esm/pages/network/network-details.js.map +6 -0
  55. package/dist/esm/pages/network/network-types.d.ts +153 -0
  56. package/dist/esm/pages/network/network-types.d.ts.map +1 -0
  57. package/dist/esm/pages/network/network-types.js +19 -0
  58. package/dist/esm/pages/network/network-types.js.map +6 -0
  59. package/dist/esm/pages/network/network-utils.d.ts +170 -0
  60. package/dist/esm/pages/network/network-utils.d.ts.map +1 -0
  61. package/dist/esm/pages/network/network-utils.js +472 -0
  62. package/dist/esm/pages/network/network-utils.js.map +6 -0
  63. package/dist/esm/pages/network/thread-graph.d.ts +27 -0
  64. package/dist/esm/pages/network/thread-graph.d.ts.map +1 -0
  65. package/dist/esm/pages/network/thread-graph.js +134 -0
  66. package/dist/esm/pages/network/thread-graph.js.map +6 -0
  67. package/dist/esm/pages/network/wifi-graph.d.ts +27 -0
  68. package/dist/esm/pages/network/wifi-graph.d.ts.map +1 -0
  69. package/dist/esm/pages/network/wifi-graph.js +167 -0
  70. package/dist/esm/pages/network/wifi-graph.js.map +6 -0
  71. package/dist/web/js/{commission-node-dialog-CBSDiqRW.js → commission-node-dialog-B1_khzZb.js} +5 -5
  72. package/dist/web/js/{commission-node-existing-TP6s8Tez.js → commission-node-existing-RpdajrwF.js} +2 -5
  73. package/dist/web/js/{commission-node-thread-DOB8pu6x.js → commission-node-thread-5f2itkTG.js} +2 -5
  74. package/dist/web/js/{commission-node-wifi-tzavmk1j.js → commission-node-wifi-DZ_pWqsa.js} +2 -5
  75. package/dist/web/js/{dialog-box-Dknil_Be.js → dialog-box-DEUxM4B1.js} +2 -2
  76. package/dist/web/js/{fire_event-DRpOSjJR.js → fire_event-BczBMT8E.js} +1 -1
  77. package/dist/web/js/{log-level-dialog-TXkma-7Z.js → log-level-dialog-Cr3PfX1X.js} +2 -3
  78. package/dist/web/js/main.js +1 -1
  79. package/dist/web/js/matter-dashboard-app-BuCe_Jxf.js +29990 -0
  80. package/dist/web/js/{node-binding-dialog-D52FCBFP.js → node-binding-dialog-DMiHNDLA.js} +2 -4
  81. package/dist/web/js/{prevent_default-BPgSQsuY.js → prevent_default-D4FX_PIh.js} +2 -42
  82. package/package.json +5 -4
  83. package/src/pages/cluster-commands/base-cluster-commands.ts +2 -2
  84. package/src/pages/cluster-commands/clusters/basic-information-commands.ts +171 -0
  85. package/src/pages/cluster-commands/index.ts +1 -0
  86. package/src/pages/components/footer.ts +4 -7
  87. package/src/pages/components/header.ts +81 -0
  88. package/src/pages/components/node-details.ts +2 -2
  89. package/src/pages/components/server-details.ts +0 -1
  90. package/src/pages/matter-dashboard-app.ts +105 -5
  91. package/src/pages/matter-network-view.ts +325 -0
  92. package/src/pages/matter-node-view.ts +75 -1
  93. package/src/pages/matter-server-view.ts +17 -1
  94. package/src/pages/network/base-network-graph.ts +463 -0
  95. package/src/pages/network/device-icons.ts +283 -0
  96. package/src/pages/network/device-panel.ts +180 -0
  97. package/src/pages/network/network-details.ts +750 -0
  98. package/src/pages/network/network-types.ts +161 -0
  99. package/src/pages/network/network-utils.ts +752 -0
  100. package/src/pages/network/thread-graph.ts +164 -0
  101. package/src/pages/network/wifi-graph.ts +192 -0
  102. package/dist/web/js/matter-dashboard-app-B7GUghkC.js +0 -17254
  103. package/dist/web/js/outlined-text-field-D1DyKQY-.js +0 -968
  104. package/dist/web/js/validator-C735j770.js +0 -1122
@@ -0,0 +1,472 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025-2026 Open Home Foundation
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ const WIFI_FEATURE = 1 << 0;
7
+ const THREAD_FEATURE = 1 << 1;
8
+ const ETHERNET_FEATURE = 1 << 2;
9
+ const SIGNAL_STRONG_THRESHOLD = -70;
10
+ const SIGNAL_MEDIUM_THRESHOLD = -85;
11
+ const LQI_STRONG_THRESHOLD = 200;
12
+ const LQI_MEDIUM_THRESHOLD = 100;
13
+ const SIGNAL_COLOR_STRONG = "#4caf50";
14
+ const SIGNAL_COLOR_MEDIUM = "#ff9800";
15
+ const SIGNAL_COLOR_WEAK = "#f44336";
16
+ function base64ToBigInt(base64) {
17
+ try {
18
+ const binary = atob(base64);
19
+ let result = 0n;
20
+ const start = binary.length > 8 ? binary.length - 8 : 0;
21
+ for (let i = start; i < binary.length; i++) {
22
+ result = result << 8n | BigInt(binary.charCodeAt(i));
23
+ }
24
+ return result;
25
+ } catch {
26
+ return 0n;
27
+ }
28
+ }
29
+ function normalizeExtAddress(value) {
30
+ if (typeof value === "bigint") {
31
+ return value;
32
+ }
33
+ if (typeof value === "string") {
34
+ return base64ToBigInt(value);
35
+ }
36
+ if (typeof value === "number") {
37
+ return BigInt(value);
38
+ }
39
+ return 0n;
40
+ }
41
+ function getNetworkType(node) {
42
+ const featureMap = node.attributes["0/49/65532"];
43
+ if (featureMap === void 0) {
44
+ return "unknown";
45
+ }
46
+ if (featureMap & THREAD_FEATURE) {
47
+ return "thread";
48
+ }
49
+ if (featureMap & WIFI_FEATURE) {
50
+ return "wifi";
51
+ }
52
+ if (featureMap & ETHERNET_FEATURE) {
53
+ return "ethernet";
54
+ }
55
+ return "unknown";
56
+ }
57
+ function categorizeDevices(nodes) {
58
+ const result = {
59
+ thread: [],
60
+ wifi: [],
61
+ ethernet: [],
62
+ unknown: []
63
+ };
64
+ for (const node of Object.values(nodes)) {
65
+ const nodeId = String(node.node_id);
66
+ const networkType = getNetworkType(node);
67
+ result[networkType].push(nodeId);
68
+ }
69
+ return result;
70
+ }
71
+ function getThreadRole(node) {
72
+ return node.attributes["0/53/1"];
73
+ }
74
+ function getThreadChannel(node) {
75
+ return node.attributes["0/53/0"];
76
+ }
77
+ function getThreadExtendedPanId(node) {
78
+ return node.attributes["0/53/4"];
79
+ }
80
+ function getThreadExtendedAddress(node) {
81
+ const networkInterfaces = node.attributes["0/51/0"];
82
+ if (!Array.isArray(networkInterfaces) || networkInterfaces.length === 0) {
83
+ return void 0;
84
+ }
85
+ const threadIface = networkInterfaces.find((i) => i["7"] === 4) || networkInterfaces[0];
86
+ if (!threadIface) {
87
+ return void 0;
88
+ }
89
+ const hwAddrB64 = threadIface["4"];
90
+ if (typeof hwAddrB64 !== "string" || !hwAddrB64) {
91
+ return void 0;
92
+ }
93
+ const extAddr = base64ToBigInt(hwAddrB64);
94
+ return extAddr !== 0n ? extAddr : void 0;
95
+ }
96
+ function getThreadExtendedAddressHex(node) {
97
+ const extAddr = getThreadExtendedAddress(node);
98
+ if (extAddr !== void 0) {
99
+ return extAddr.toString(16).padStart(16, "0").toUpperCase();
100
+ }
101
+ return void 0;
102
+ }
103
+ function parseNeighborTable(node) {
104
+ const neighborTable = node.attributes["0/53/7"];
105
+ if (!Array.isArray(neighborTable)) {
106
+ return [];
107
+ }
108
+ return neighborTable.map((entry) => {
109
+ const rawExtAddr = entry["0"] ?? entry.extAddress;
110
+ const extAddress = normalizeExtAddress(rawExtAddr);
111
+ return {
112
+ extAddress,
113
+ // Field 1: age
114
+ age: entry["1"] ?? entry.age ?? 0,
115
+ // Field 2: rloc16
116
+ rloc16: entry["2"] ?? entry.rloc16 ?? 0,
117
+ // Field 3: linkFrameCounter
118
+ linkFrameCounter: entry["3"] ?? entry.linkFrameCounter ?? 0,
119
+ // Field 4: mleFrameCounter
120
+ mleFrameCounter: entry["4"] ?? entry.mleFrameCounter ?? 0,
121
+ // Field 5: lqi
122
+ lqi: entry["5"] ?? entry.lqi ?? 0,
123
+ // Field 6: averageRssi (nullable)
124
+ avgRssi: entry["6"] ?? entry.averageRssi ?? null,
125
+ // Field 7: lastRssi (nullable)
126
+ lastRssi: entry["7"] ?? entry.lastRssi ?? null,
127
+ // Field 8: frameErrorRate
128
+ frameErrorRate: entry["8"] ?? entry.frameErrorRate ?? 0,
129
+ // Field 9: messageErrorRate
130
+ messageErrorRate: entry["9"] ?? entry.messageErrorRate ?? 0,
131
+ // Field 10: rxOnWhenIdle
132
+ rxOnWhenIdle: entry["10"] ?? entry.rxOnWhenIdle ?? false,
133
+ // Field 11: fullThreadDevice
134
+ fullThreadDevice: entry["11"] ?? entry.fullThreadDevice ?? false,
135
+ // Field 12: fullNetworkData
136
+ fullNetworkData: entry["12"] ?? entry.fullNetworkData ?? false,
137
+ // Field 13: isChild
138
+ isChild: entry["13"] ?? entry.isChild ?? false
139
+ };
140
+ });
141
+ }
142
+ function parseRouteTable(node) {
143
+ const routeTable = node.attributes["0/53/8"];
144
+ if (!Array.isArray(routeTable)) {
145
+ return [];
146
+ }
147
+ return routeTable.map((entry) => {
148
+ const rawExtAddr = entry["0"] ?? entry.extAddress;
149
+ const extAddress = normalizeExtAddress(rawExtAddr);
150
+ return {
151
+ extAddress,
152
+ // Field 1: rloc16
153
+ rloc16: entry["1"] ?? entry.rloc16 ?? 0,
154
+ // Field 2: routerId
155
+ routerId: entry["2"] ?? entry.routerId ?? 0,
156
+ // Field 3: nextHop
157
+ nextHop: entry["3"] ?? entry.nextHop ?? 0,
158
+ // Field 4: pathCost
159
+ pathCost: entry["4"] ?? entry.pathCost ?? 0,
160
+ // Field 5: lqiIn
161
+ lqiIn: entry["5"] ?? entry.lqiIn ?? 0,
162
+ // Field 6: lqiOut
163
+ lqiOut: entry["6"] ?? entry.lqiOut ?? 0,
164
+ // Field 7: age
165
+ age: entry["7"] ?? entry.age ?? 0,
166
+ // Field 8: allocated
167
+ allocated: entry["8"] ?? entry.allocated ?? false,
168
+ // Field 9: linkEstablished
169
+ linkEstablished: entry["9"] ?? entry.linkEstablished ?? false
170
+ };
171
+ });
172
+ }
173
+ function getThreadRloc16(node) {
174
+ const value = node.attributes["0/53/64"];
175
+ if (typeof value === "number") {
176
+ return value;
177
+ }
178
+ return void 0;
179
+ }
180
+ function buildExtAddrMap(nodes) {
181
+ const extAddrMap = /* @__PURE__ */ new Map();
182
+ for (const node of Object.values(nodes)) {
183
+ const nodeId = String(node.node_id);
184
+ const extAddr = getThreadExtendedAddress(node);
185
+ if (extAddr !== void 0) {
186
+ extAddrMap.set(extAddr, nodeId);
187
+ }
188
+ }
189
+ return extAddrMap;
190
+ }
191
+ function buildRloc16Map(nodes) {
192
+ const rloc16Map = /* @__PURE__ */ new Map();
193
+ for (const node of Object.values(nodes)) {
194
+ const nodeId = String(node.node_id);
195
+ const rloc16 = getThreadRloc16(node);
196
+ if (rloc16 !== void 0) {
197
+ rloc16Map.set(rloc16, nodeId);
198
+ }
199
+ }
200
+ return rloc16Map;
201
+ }
202
+ function findUnknownDevices(nodes, extAddrMap) {
203
+ const unknownMap = /* @__PURE__ */ new Map();
204
+ for (const node of Object.values(nodes)) {
205
+ const nodeId = String(node.node_id);
206
+ const neighbors = parseNeighborTable(node);
207
+ for (const neighbor of neighbors) {
208
+ if (extAddrMap.has(neighbor.extAddress)) {
209
+ continue;
210
+ }
211
+ const extAddressHex = neighbor.extAddress.toString(16).padStart(16, "0").toUpperCase();
212
+ const id = `unknown_${extAddressHex}`;
213
+ if (!unknownMap.has(id)) {
214
+ unknownMap.set(id, {
215
+ id,
216
+ extAddressHex,
217
+ extAddress: neighbor.extAddress,
218
+ seenBy: [],
219
+ isRouter: false,
220
+ bestRssi: null
221
+ });
222
+ }
223
+ const unknown = unknownMap.get(id);
224
+ if (!unknown.seenBy.includes(nodeId)) {
225
+ unknown.seenBy.push(nodeId);
226
+ }
227
+ if (neighbor.rxOnWhenIdle) {
228
+ unknown.isRouter = true;
229
+ }
230
+ const rssi = neighbor.avgRssi ?? neighbor.lastRssi;
231
+ if (rssi !== null && (unknown.bestRssi === null || rssi > unknown.bestRssi)) {
232
+ unknown.bestRssi = rssi;
233
+ }
234
+ }
235
+ }
236
+ return Array.from(unknownMap.values());
237
+ }
238
+ function getSignalColor(neighbor) {
239
+ const rssi = neighbor.avgRssi ?? neighbor.lastRssi;
240
+ if (rssi !== null) {
241
+ if (rssi > SIGNAL_STRONG_THRESHOLD) {
242
+ return SIGNAL_COLOR_STRONG;
243
+ }
244
+ if (rssi > SIGNAL_MEDIUM_THRESHOLD) {
245
+ return SIGNAL_COLOR_MEDIUM;
246
+ }
247
+ return SIGNAL_COLOR_WEAK;
248
+ }
249
+ if (neighbor.lqi > LQI_STRONG_THRESHOLD) {
250
+ return SIGNAL_COLOR_STRONG;
251
+ }
252
+ if (neighbor.lqi > LQI_MEDIUM_THRESHOLD) {
253
+ return SIGNAL_COLOR_MEDIUM;
254
+ }
255
+ return SIGNAL_COLOR_WEAK;
256
+ }
257
+ function getDeviceName(node) {
258
+ if (node.nodeLabel) {
259
+ return node.nodeLabel;
260
+ }
261
+ const productName = node.productName || "Unknown Device";
262
+ const serialNumber = node.serialNumber;
263
+ if (serialNumber) {
264
+ return `${productName} (${serialNumber})`;
265
+ }
266
+ return productName;
267
+ }
268
+ function getThreadRoleName(role) {
269
+ switch (role) {
270
+ case 0:
271
+ return "Unspecified";
272
+ case 1:
273
+ return "Unassigned";
274
+ case 2:
275
+ return "Sleepy End Device";
276
+ case 3:
277
+ return "End Device";
278
+ case 4:
279
+ return "REED";
280
+ case 5:
281
+ return "Router";
282
+ case 6:
283
+ return "Leader";
284
+ default:
285
+ return "Unknown";
286
+ }
287
+ }
288
+ function getWiFiDiagnostics(node) {
289
+ const bssidRaw = node.attributes["0/54/0"];
290
+ let bssid = null;
291
+ if (bssidRaw) {
292
+ try {
293
+ const binary = atob(bssidRaw);
294
+ bssid = Array.from(binary).map((c) => c.charCodeAt(0).toString(16).padStart(2, "0").toUpperCase()).join(":");
295
+ } catch {
296
+ bssid = null;
297
+ }
298
+ }
299
+ const rssi = node.attributes["0/54/4"];
300
+ const channel = node.attributes["0/54/3"];
301
+ const securityType = node.attributes["0/54/1"];
302
+ const wifiVersion = node.attributes["0/54/2"];
303
+ return {
304
+ bssid,
305
+ rssi: rssi ?? null,
306
+ channel: channel ?? null,
307
+ securityType: securityType ?? null,
308
+ wifiVersion: wifiVersion ?? null
309
+ };
310
+ }
311
+ function getSignalColorFromRssi(rssi) {
312
+ if (rssi === null) {
313
+ return SIGNAL_COLOR_MEDIUM;
314
+ }
315
+ if (rssi > SIGNAL_STRONG_THRESHOLD) {
316
+ return SIGNAL_COLOR_STRONG;
317
+ }
318
+ if (rssi > SIGNAL_MEDIUM_THRESHOLD) {
319
+ return SIGNAL_COLOR_MEDIUM;
320
+ }
321
+ return SIGNAL_COLOR_WEAK;
322
+ }
323
+ function getWiFiSecurityTypeName(securityType) {
324
+ switch (securityType) {
325
+ case 0:
326
+ return "Unspecified";
327
+ case 1:
328
+ return "None";
329
+ case 2:
330
+ return "WEP";
331
+ case 3:
332
+ return "WPA Personal";
333
+ case 4:
334
+ return "WPA2 Personal";
335
+ case 5:
336
+ return "WPA3 Personal";
337
+ default:
338
+ return "Unknown";
339
+ }
340
+ }
341
+ function getWiFiVersionName(version) {
342
+ switch (version) {
343
+ case 0:
344
+ return "802.11a";
345
+ case 1:
346
+ return "802.11b";
347
+ case 2:
348
+ return "802.11g";
349
+ case 3:
350
+ return "802.11n";
351
+ case 4:
352
+ return "802.11ac";
353
+ case 5:
354
+ return "802.11ax";
355
+ case 6:
356
+ return "802.11ah";
357
+ default:
358
+ return "Unknown";
359
+ }
360
+ }
361
+ function buildThreadConnections(nodes, extAddrMap, unknownDevices) {
362
+ const connections = [];
363
+ const seenConnections = /* @__PURE__ */ new Set();
364
+ const unknownExtAddrMap = /* @__PURE__ */ new Map();
365
+ for (const unknown of unknownDevices) {
366
+ unknownExtAddrMap.set(unknown.extAddress, unknown.id);
367
+ }
368
+ for (const node of Object.values(nodes)) {
369
+ const fromNodeId = String(node.node_id);
370
+ const neighbors = parseNeighborTable(node);
371
+ for (const neighbor of neighbors) {
372
+ let toNodeId = extAddrMap.get(neighbor.extAddress);
373
+ if (toNodeId === void 0) {
374
+ toNodeId = unknownExtAddrMap.get(neighbor.extAddress);
375
+ }
376
+ if (toNodeId === void 0) {
377
+ continue;
378
+ }
379
+ if (fromNodeId === toNodeId) {
380
+ continue;
381
+ }
382
+ const connectionKey = `${fromNodeId}-${toNodeId}`;
383
+ const reverseKey = `${toNodeId}-${fromNodeId}`;
384
+ if (seenConnections.has(connectionKey) || seenConnections.has(reverseKey)) {
385
+ continue;
386
+ }
387
+ seenConnections.add(connectionKey);
388
+ connections.push({
389
+ fromNodeId,
390
+ toNodeId,
391
+ signalColor: getSignalColor(neighbor),
392
+ lqi: neighbor.lqi,
393
+ rssi: neighbor.avgRssi ?? neighbor.lastRssi
394
+ });
395
+ }
396
+ }
397
+ return connections;
398
+ }
399
+ function getNodeConnections(nodeId, nodes, extAddrMap) {
400
+ const connections = [];
401
+ const seenConnectedIds = /* @__PURE__ */ new Set();
402
+ const node = nodes[nodeId];
403
+ if (!node) return connections;
404
+ const thisExtAddr = getThreadExtendedAddress(node);
405
+ const neighbors = parseNeighborTable(node);
406
+ for (const neighbor of neighbors) {
407
+ const connectedNodeId = extAddrMap.get(neighbor.extAddress);
408
+ const connectedNode = connectedNodeId ? nodes[connectedNodeId] : void 0;
409
+ const isUnknown = connectedNodeId === void 0;
410
+ const displayId = isUnknown ? `unknown_${neighbor.extAddress.toString(16).toUpperCase().padStart(16, "0")}` : connectedNodeId;
411
+ seenConnectedIds.add(displayId);
412
+ connections.push({
413
+ connectedNodeId: displayId,
414
+ connectedNode,
415
+ extAddressHex: neighbor.extAddress.toString(16).toUpperCase().padStart(16, "0"),
416
+ signalColor: getSignalColor(neighbor),
417
+ lqi: neighbor.lqi,
418
+ rssi: neighbor.avgRssi ?? neighbor.lastRssi,
419
+ isOutgoing: true,
420
+ isUnknown
421
+ });
422
+ }
423
+ if (thisExtAddr !== void 0) {
424
+ for (const otherNode of Object.values(nodes)) {
425
+ const otherNodeId = String(otherNode.node_id);
426
+ if (otherNodeId === nodeId) continue;
427
+ if (seenConnectedIds.has(otherNodeId)) continue;
428
+ const otherNeighbors = parseNeighborTable(otherNode);
429
+ const reverseEntry = otherNeighbors.find((n) => n.extAddress === thisExtAddr);
430
+ if (reverseEntry) {
431
+ const otherExtAddr = getThreadExtendedAddress(otherNode);
432
+ const extAddrHex = otherExtAddr ? otherExtAddr.toString(16).toUpperCase().padStart(16, "0") : "Unknown";
433
+ connections.push({
434
+ connectedNodeId: otherNodeId,
435
+ connectedNode: otherNode,
436
+ extAddressHex: extAddrHex,
437
+ signalColor: getSignalColor(reverseEntry),
438
+ lqi: reverseEntry.lqi,
439
+ rssi: reverseEntry.avgRssi ?? reverseEntry.lastRssi,
440
+ isOutgoing: false,
441
+ isUnknown: false
442
+ });
443
+ }
444
+ }
445
+ }
446
+ return connections;
447
+ }
448
+ export {
449
+ buildExtAddrMap,
450
+ buildRloc16Map,
451
+ buildThreadConnections,
452
+ categorizeDevices,
453
+ findUnknownDevices,
454
+ getDeviceName,
455
+ getNetworkType,
456
+ getNodeConnections,
457
+ getSignalColor,
458
+ getSignalColorFromRssi,
459
+ getThreadChannel,
460
+ getThreadExtendedAddress,
461
+ getThreadExtendedAddressHex,
462
+ getThreadExtendedPanId,
463
+ getThreadRloc16,
464
+ getThreadRole,
465
+ getThreadRoleName,
466
+ getWiFiDiagnostics,
467
+ getWiFiSecurityTypeName,
468
+ getWiFiVersionName,
469
+ parseNeighborTable,
470
+ parseRouteTable
471
+ };
472
+ //# sourceMappingURL=network-utils.js.map
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/pages/network/network-utils.ts"],
4
+ "mappings": "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",
5
+ "names": []
6
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025-2026 Open Home Foundation
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { BaseNetworkGraph } from "./base-network-graph.js";
7
+ declare global {
8
+ interface HTMLElementTagNameMap {
9
+ "thread-graph": ThreadGraph;
10
+ }
11
+ }
12
+ export declare class ThreadGraph extends BaseNetworkGraph {
13
+ /** Cache of unknown devices for the current render */
14
+ private _unknownDevices;
15
+ /** Cached map of unknown devices (rebuilt in _updateGraph) */
16
+ private _unknownDevicesMapCache;
17
+ /** Get unknown devices as a map for use by details panel */
18
+ get unknownDevicesMap(): Map<string, {
19
+ extAddressHex: string;
20
+ isRouter: boolean;
21
+ seenBy: string[];
22
+ bestRssi: number | null;
23
+ }>;
24
+ protected _updateGraph(): void;
25
+ render(): import("lit-html").TemplateResult<1>;
26
+ }
27
+ //# sourceMappingURL=thread-graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thread-graph.d.ts","sourceRoot":"","sources":["../../../../src/pages/network/thread-graph.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAY3D,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,qBAAqB;QAC3B,cAAc,EAAE,WAAW,CAAC;KAC/B;CACJ;AAED,qBACa,WAAY,SAAQ,gBAAgB;IAC7C,sDAAsD;IACtD,OAAO,CAAC,eAAe,CAA6B;IAEpD,8DAA8D;IAC9D,OAAO,CAAC,uBAAuB,CAGjB;IAEd,4DAA4D;IAC5D,IAAW,iBAAiB,IAAI,GAAG,CAC/B,MAAM,EACN;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAC1F,CAEA;cAEkB,YAAY,IAAI,IAAI;IAwG9B,MAAM;CAclB"}
@@ -0,0 +1,134 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __decorateClass = (decorators, target, key, kind) => {
4
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
5
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
6
+ if (decorator = decorators[i])
7
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
8
+ if (kind && result) __defProp(target, key, result);
9
+ return result;
10
+ };
11
+ /**
12
+ * @license
13
+ * Copyright 2025-2026 Open Home Foundation
14
+ * SPDX-License-Identifier: Apache-2.0
15
+ */
16
+ import { html } from "lit";
17
+ import { customElement } from "lit/decorators.js";
18
+ import { BaseNetworkGraph } from "./base-network-graph.js";
19
+ import { createNodeIconDataUrl, createUnknownDeviceIconDataUrl } from "./device-icons.js";
20
+ import {
21
+ buildExtAddrMap,
22
+ buildThreadConnections,
23
+ findUnknownDevices,
24
+ getDeviceName,
25
+ getNetworkType,
26
+ getThreadRole
27
+ } from "./network-utils.js";
28
+ let ThreadGraph = class extends BaseNetworkGraph {
29
+ constructor() {
30
+ super(...arguments);
31
+ /** Cache of unknown devices for the current render */
32
+ this._unknownDevices = [];
33
+ /** Cached map of unknown devices (rebuilt in _updateGraph) */
34
+ this._unknownDevicesMapCache = /* @__PURE__ */ new Map();
35
+ }
36
+ /** Get unknown devices as a map for use by details panel */
37
+ get unknownDevicesMap() {
38
+ return this._unknownDevicesMapCache;
39
+ }
40
+ _updateGraph() {
41
+ if (!this._nodesDataSet || !this._edgesDataSet) return;
42
+ this._clearOriginalEdgeColors();
43
+ const threadNodes = Object.values(this.nodes).filter((node) => getNetworkType(node) === "thread");
44
+ if (threadNodes.length === 0) {
45
+ this._nodesDataSet.clear();
46
+ this._edgesDataSet.clear();
47
+ this._unknownDevices = [];
48
+ this._unknownDevicesMapCache.clear();
49
+ return;
50
+ }
51
+ const extAddrMap = buildExtAddrMap(this.nodes);
52
+ this._unknownDevices = findUnknownDevices(this.nodes, extAddrMap);
53
+ this._unknownDevicesMapCache.clear();
54
+ for (const device of this._unknownDevices) {
55
+ this._unknownDevicesMapCache.set(device.id, {
56
+ extAddressHex: device.extAddressHex,
57
+ isRouter: device.isRouter,
58
+ seenBy: device.seenBy,
59
+ bestRssi: device.bestRssi
60
+ });
61
+ }
62
+ const connections = buildThreadConnections(this.nodes, extAddrMap, this._unknownDevices);
63
+ const graphNodes = threadNodes.map((node) => {
64
+ const nodeId = String(node.node_id);
65
+ const threadRole = getThreadRole(node);
66
+ const isSelected = nodeId === String(this._selectedNodeId);
67
+ const isOffline = node.available === false;
68
+ return {
69
+ id: nodeId,
70
+ label: getDeviceName(node),
71
+ image: createNodeIconDataUrl(node, threadRole, isSelected, isOffline),
72
+ shape: "image",
73
+ networkType: "thread",
74
+ threadRole,
75
+ offline: isOffline
76
+ };
77
+ });
78
+ for (const unknown of this._unknownDevices) {
79
+ const isSelected = unknown.id === this._selectedNodeId;
80
+ graphNodes.push({
81
+ id: unknown.id,
82
+ label: `Unknown (${unknown.extAddressHex.slice(-8)})`,
83
+ image: createUnknownDeviceIconDataUrl(unknown.isRouter, isSelected),
84
+ shape: "image",
85
+ networkType: "thread",
86
+ isUnknown: true
87
+ });
88
+ }
89
+ const graphEdges = connections.map((conn, index) => {
90
+ const isToUnknown = typeof conn.toNodeId === "string" && conn.toNodeId.startsWith("unknown_");
91
+ return {
92
+ id: `edge_${index}`,
93
+ from: conn.fromNodeId,
94
+ to: conn.toNodeId,
95
+ color: {
96
+ color: conn.signalColor,
97
+ highlight: conn.signalColor
98
+ },
99
+ width: 2,
100
+ title: conn.rssi !== null ? `RSSI: ${conn.rssi} dBm, LQI: ${conn.lqi}` : `LQI: ${conn.lqi}`,
101
+ dashes: isToUnknown
102
+ // Dashed lines to unknown devices
103
+ };
104
+ });
105
+ const existingNodeIds = this._nodesDataSet.getIds();
106
+ const newNodeIds = new Set(graphNodes.map((n) => n.id));
107
+ const nodesToRemove = existingNodeIds.filter((id) => !newNodeIds.has(id));
108
+ if (nodesToRemove.length > 0) {
109
+ this._nodesDataSet.remove(nodesToRemove);
110
+ }
111
+ this._nodesDataSet.update(graphNodes);
112
+ this._edgesDataSet.clear();
113
+ this._edgesDataSet.add(graphEdges);
114
+ }
115
+ render() {
116
+ const threadNodes = Object.values(this.nodes).filter((node) => getNetworkType(node) === "thread");
117
+ if (threadNodes.length === 0) {
118
+ return html`
119
+ <div class="empty-state">
120
+ <p>No Thread devices found</p>
121
+ <p class="hint">Thread devices will appear here once commissioned</p>
122
+ </div>
123
+ `;
124
+ }
125
+ return html`<div class="graph-container"></div>`;
126
+ }
127
+ };
128
+ ThreadGraph = __decorateClass([
129
+ customElement("thread-graph")
130
+ ], ThreadGraph);
131
+ export {
132
+ ThreadGraph
133
+ };
134
+ //# sourceMappingURL=thread-graph.js.map
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/pages/network/thread-graph.ts"],
4
+ "mappings": "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",
5
+ "names": []
6
+ }