@matter-server/ws-client 1.1.8-alpha.0-20260707-c552b9d → 1.2.0
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/esm/client.d.ts +47 -6
- package/dist/esm/client.d.ts.map +1 -1
- package/dist/esm/client.js +88 -14
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/exceptions.d.ts +5 -0
- package/dist/esm/exceptions.d.ts.map +1 -1
- package/dist/esm/exceptions.js +10 -1
- package/dist/esm/exceptions.js.map +1 -1
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/models/model.d.ts +266 -51
- package/dist/esm/models/model.d.ts.map +1 -1
- package/dist/esm/models/model.js +2 -0
- package/dist/esm/models/model.js.map +1 -1
- package/dist/esm/topology/topology-types.d.ts +235 -0
- package/dist/esm/topology/topology-types.d.ts.map +1 -0
- package/dist/esm/topology/topology-types.js +19 -0
- package/dist/esm/topology/topology-types.js.map +6 -0
- package/dist/esm/topology/topology-utils.d.ts +185 -0
- package/dist/esm/topology/topology-utils.d.ts.map +1 -0
- package/dist/esm/topology/topology-utils.js +599 -0
- package/dist/esm/topology/topology-utils.js.map +6 -0
- package/package.json +6 -4
- package/src/client.ts +149 -21
- package/src/exceptions.ts +11 -0
- package/src/index.ts +4 -0
- package/src/models/model.ts +266 -53
- package/src/topology/topology-types.ts +249 -0
- package/src/topology/topology-utils.ts +932 -0
package/src/models/model.ts
CHANGED
|
@@ -4,64 +4,205 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import type { BorderRouterEntry } from "@matter/thread-br-client";
|
|
7
8
|
import type { MatterNodeData } from "./node.js";
|
|
8
9
|
// Re-export so consumers can import the MatterNodeData type from this module
|
|
9
10
|
export type { MatterNodeData } from "./node.js";
|
|
11
|
+
export type { BorderRouterEntry } from "@matter/thread-br-client";
|
|
10
12
|
|
|
11
13
|
/** Attribute data stored as path -> value mapping */
|
|
12
14
|
export type AttributesData = { [key: string]: unknown };
|
|
13
15
|
|
|
16
|
+
/*
|
|
17
|
+
* The interfaces below decode the Thread Network Diagnostic TLVs a Border Router / router
|
|
18
|
+
* reports (per the Thread spec / OpenThread `netdiag`). They are all part of the Thread
|
|
19
|
+
* Network diagnostics feature and are @since schema 12.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/** CONNECTIVITY TLV — a node's view of its links to neighbors and the leader. @since schema 12 */
|
|
23
|
+
export interface ThreadConnectivity {
|
|
24
|
+
/** Suitability as a parent: -1 low, 0 medium, 1 high. */
|
|
25
|
+
parentPriority: -1 | 0 | 1;
|
|
26
|
+
/** Count of neighbors with link quality 3 (best) / 2 / 1 (worst). */
|
|
27
|
+
linkQuality3: number;
|
|
28
|
+
linkQuality2: number;
|
|
29
|
+
linkQuality1: number;
|
|
30
|
+
/** Routing cost from this node to the leader. */
|
|
31
|
+
leaderCost: number;
|
|
32
|
+
/** Router-ID assignment sequence number (bumped when the router set changes). */
|
|
33
|
+
idSequence: number;
|
|
34
|
+
/** Number of active routers in the Thread network. */
|
|
35
|
+
activeRouters: number;
|
|
36
|
+
/** Buffer size a parent reserves for a sleepy child (bytes). */
|
|
37
|
+
sedBufferSize: number;
|
|
38
|
+
/** Max IPv6 datagrams a parent queues for a sleepy child. */
|
|
39
|
+
sedDatagramCount: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** One neighbor-router row within {@link ThreadRoute64}. @since schema 12 */
|
|
43
|
+
export interface ThreadRoute64Entry {
|
|
44
|
+
/** Router ID of the neighbor. */
|
|
45
|
+
routerId: number;
|
|
46
|
+
/** Link quality of packets received from / sent to that router (0–3). */
|
|
47
|
+
linkQualityIn: number;
|
|
48
|
+
linkQualityOut: number;
|
|
49
|
+
/** Routing cost to that router. */
|
|
50
|
+
routeCost: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** ROUTE64 TLV — the node's routing table to other routers. @since schema 12 */
|
|
54
|
+
export interface ThreadRoute64 {
|
|
55
|
+
/** Router-ID assignment sequence number. */
|
|
56
|
+
idSequence: number;
|
|
57
|
+
entries: ThreadRoute64Entry[];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** LEADER_DATA TLV — the current leader / partition identity. @since schema 12 */
|
|
61
|
+
export interface ThreadLeaderData {
|
|
62
|
+
/** Thread partition ID (changes on partition merge/split). */
|
|
63
|
+
partitionId: number;
|
|
64
|
+
/** Leader weighting used to arbitrate leadership. */
|
|
65
|
+
weighting: number;
|
|
66
|
+
/** Full and stable-only Network Data version counters. */
|
|
67
|
+
dataVersion: number;
|
|
68
|
+
stableDataVersion: number;
|
|
69
|
+
/** Router ID of the leader. */
|
|
70
|
+
leaderRouterId: number;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** MAC_COUNTERS TLV — IEEE 802.15.4 MAC packet counters since last reset. @since schema 12 */
|
|
74
|
+
export interface ThreadMacCounters {
|
|
75
|
+
ifInUnknownProtos: number;
|
|
76
|
+
ifInErrors: number;
|
|
77
|
+
ifOutErrors: number;
|
|
78
|
+
ifInUcastPkts: number;
|
|
79
|
+
ifInBroadcastPkts: number;
|
|
80
|
+
ifInDiscards: number;
|
|
81
|
+
ifOutUcastPkts: number;
|
|
82
|
+
ifOutBroadcastPkts: number;
|
|
83
|
+
ifOutDiscards: number;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** MODE TLV — device capability/role flags. @since schema 12 */
|
|
87
|
+
export interface ThreadMode {
|
|
88
|
+
/** Radio stays on when idle (a non-sleepy device). */
|
|
89
|
+
rxOnWhenIdle: boolean;
|
|
90
|
+
/** Full Thread Device (router-eligible) vs a Minimal Thread Device. */
|
|
91
|
+
ftd: boolean;
|
|
92
|
+
/** Requests the full Network Data vs the stable subset. */
|
|
93
|
+
fullNetworkData: boolean;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** CHILD_TABLE TLV entry — one child attached to this (router) node. @since schema 12 */
|
|
97
|
+
export interface ThreadChildTableEntry {
|
|
98
|
+
/** Child timeout as a 2^exponent value and its resolved seconds. */
|
|
99
|
+
timeoutExponent: number;
|
|
100
|
+
timeoutSeconds: number;
|
|
101
|
+
/** Link quality of packets received from the child (0–3). */
|
|
102
|
+
incomingLinkQuality: number;
|
|
103
|
+
/** Child ID (low bits of the child's RLOC16). */
|
|
104
|
+
childId: number;
|
|
105
|
+
mode: ThreadMode;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** MLE_COUNTERS TLV — Mesh Link Establishment role/state counters. @since schema 12 */
|
|
109
|
+
export interface ThreadMleCounters {
|
|
110
|
+
/** Number of times the node entered each role. */
|
|
111
|
+
disabledRole: number;
|
|
112
|
+
detachedRole: number;
|
|
113
|
+
childRole: number;
|
|
114
|
+
routerRole: number;
|
|
115
|
+
leaderRole: number;
|
|
116
|
+
/** Attach / partition-change bookkeeping. */
|
|
117
|
+
attachAttempts: number;
|
|
118
|
+
partitionIdChanges: number;
|
|
119
|
+
betterPartitionAttachAttempts: number;
|
|
120
|
+
parentChanges: number;
|
|
121
|
+
/** Cumulative time spent tracked / in each role, in milliseconds (64-bit). */
|
|
122
|
+
trackedTime: bigint;
|
|
123
|
+
disabledTime: bigint;
|
|
124
|
+
detachedTime: bigint;
|
|
125
|
+
childTime: bigint;
|
|
126
|
+
routerTime: bigint;
|
|
127
|
+
leaderTime: bigint;
|
|
128
|
+
}
|
|
129
|
+
|
|
14
130
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* the primary key. It is the same value as ThreadNetworkDiagnostics.NeighborTable.extAddress
|
|
19
|
-
* for a BR that is itself a Thread router, which is what allows the dashboard to join
|
|
20
|
-
* BRs onto external-device entries seen in commissioned-node neighbor tables.
|
|
131
|
+
* Diagnostics for a single Thread node, assembled from the diagnostic TLVs it returned.
|
|
132
|
+
* Every field is optional: a node only reports the TLVs it supports / were requested.
|
|
133
|
+
* @since schema 12
|
|
21
134
|
*/
|
|
22
|
-
export interface
|
|
23
|
-
/** 16-char uppercase hex of the 64-bit Thread MAC
|
|
24
|
-
|
|
25
|
-
/** 16-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
135
|
+
export interface ThreadDiagnosticsNode {
|
|
136
|
+
/** 16-char uppercase hex of the 64-bit Thread MAC (extended address). */
|
|
137
|
+
extMacAddress?: string;
|
|
138
|
+
/** Short 16-bit routing locator (router+child) within the mesh. */
|
|
139
|
+
rloc16?: number;
|
|
140
|
+
mode?: ThreadMode;
|
|
141
|
+
/** Polling/child timeout in seconds. */
|
|
142
|
+
timeout?: number;
|
|
143
|
+
connectivity?: ThreadConnectivity;
|
|
144
|
+
route64?: ThreadRoute64;
|
|
145
|
+
leaderData?: ThreadLeaderData;
|
|
146
|
+
/** Hex-encoded raw Network Data blob (prefixes, routes, services). */
|
|
147
|
+
networkData?: string;
|
|
148
|
+
/** Per-node IPv6 addresses, each 16-byte address as uppercase hex. */
|
|
149
|
+
ipv6Addresses?: string[];
|
|
150
|
+
macCounters?: ThreadMacCounters;
|
|
151
|
+
childTable?: ThreadChildTableEntry[];
|
|
152
|
+
/** Supported channel pages (radio band identifiers). */
|
|
153
|
+
channelPages?: number[];
|
|
154
|
+
/** Max child timeout this node grants, in seconds. */
|
|
155
|
+
maxChildTimeout?: number;
|
|
156
|
+
/** 16-char uppercase hex EUI-64 (factory-assigned identifier). */
|
|
157
|
+
eui64?: string;
|
|
158
|
+
/** Thread protocol version the node implements. */
|
|
159
|
+
version?: number;
|
|
160
|
+
/** Vendor identity strings (VENDOR_NAME / MODEL / SW_VERSION TLVs). */
|
|
30
161
|
vendorName?: string;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
162
|
+
vendorModel?: string;
|
|
163
|
+
vendorSwVersion?: string;
|
|
164
|
+
/** OpenThread (or other) stack build string. */
|
|
165
|
+
threadStackVersion?: string;
|
|
166
|
+
vendorAppUrl?: string;
|
|
167
|
+
mleCounters?: ThreadMleCounters;
|
|
168
|
+
/** Battery level (0–100%) and supply voltage (mV) for battery-powered nodes. */
|
|
169
|
+
batteryLevel?: number;
|
|
170
|
+
supplyVoltage?: number;
|
|
171
|
+
/** TLVs this decoder does not model, preserved verbatim; `value` is uppercase hex. */
|
|
172
|
+
unknown?: Array<{ type: number; value: string }>;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/** Why a {@link ThreadDiagnosticsBatch} is incomplete (absent when the batch is complete). @since schema 12 */
|
|
176
|
+
export type ThreadDiagnosticsPartialReason =
|
|
177
|
+
| "petition_rejected"
|
|
178
|
+
| "dtls_failed"
|
|
179
|
+
| "border_router_unreachable"
|
|
180
|
+
| "no_credentials"
|
|
181
|
+
| "no_source"
|
|
182
|
+
| "rest_unreachable"
|
|
183
|
+
| "rest_protocol"
|
|
184
|
+
| "timeout"
|
|
185
|
+
/** Streaming multicast query is still active; this is a snapshot, more nodes may follow. */
|
|
186
|
+
| "in_progress"
|
|
187
|
+
/** Streaming multicast query is active but no responses have arrived yet. */
|
|
188
|
+
| "meshcop_no_responses_yet";
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* One Thread network's diagnostics snapshot, keyed by extended PAN ID, delivered by
|
|
192
|
+
* `get_thread_diagnostics` and streamed via the `thread_diagnostics_updated` event.
|
|
193
|
+
* @since schema 12
|
|
194
|
+
*/
|
|
195
|
+
export interface ThreadDiagnosticsBatch {
|
|
196
|
+
/** 16-char uppercase hex extended PAN ID — the network this batch describes. */
|
|
197
|
+
extPanIdHex: string;
|
|
198
|
+
networkName: string;
|
|
199
|
+
/** Epoch ms when the batch was assembled. */
|
|
200
|
+
collectedAt: number;
|
|
201
|
+
/** Which transport produced it: MeshCoP (CoAP/DTLS) or the OTBR REST API. */
|
|
202
|
+
source: "meshcop" | "otbr-rest";
|
|
203
|
+
nodes: ThreadDiagnosticsNode[];
|
|
204
|
+
/** Set when the snapshot is partial or the query could not complete; see {@link ThreadDiagnosticsPartialReason}. */
|
|
205
|
+
partialReason?: ThreadDiagnosticsPartialReason;
|
|
65
206
|
}
|
|
66
207
|
|
|
67
208
|
export type WebRtcEventType = "offer" | "answer" | "ice_candidates" | "end";
|
|
@@ -129,7 +270,7 @@ export interface APICommands {
|
|
|
129
270
|
response: MatterNodeData;
|
|
130
271
|
};
|
|
131
272
|
commission_with_code: {
|
|
132
|
-
requestArgs: { code: string; network_only?: boolean };
|
|
273
|
+
requestArgs: { code: string; network_only?: boolean; wifi_credentials_id?: string; thread_dataset_id?: string };
|
|
133
274
|
response: MatterNodeData;
|
|
134
275
|
};
|
|
135
276
|
commission_on_network: {
|
|
@@ -145,25 +286,41 @@ export interface APICommands {
|
|
|
145
286
|
response: MatterNodeData;
|
|
146
287
|
};
|
|
147
288
|
set_wifi_credentials: {
|
|
148
|
-
requestArgs: { ssid: string; credentials: string };
|
|
289
|
+
requestArgs: { ssid: string; credentials: string; id?: string };
|
|
149
290
|
response: Record<string, never>;
|
|
150
291
|
};
|
|
151
292
|
set_thread_dataset: {
|
|
152
|
-
requestArgs: { dataset: string };
|
|
293
|
+
requestArgs: { dataset: string; id?: string };
|
|
153
294
|
response: Record<string, never>;
|
|
154
295
|
};
|
|
155
296
|
remove_wifi_credentials: {
|
|
156
|
-
requestArgs:
|
|
297
|
+
requestArgs: { id?: string };
|
|
157
298
|
response: Record<string, never>;
|
|
158
299
|
};
|
|
159
300
|
remove_thread_dataset: {
|
|
160
|
-
requestArgs:
|
|
301
|
+
requestArgs: { id?: string };
|
|
161
302
|
response: Record<string, never>;
|
|
162
303
|
};
|
|
304
|
+
/** List stored WiFi/Thread credential summaries (no secrets). @since schema 12 */
|
|
305
|
+
get_all_credentials: {
|
|
306
|
+
requestArgs: Record<string, never>;
|
|
307
|
+
response: AllCredentialsSummary;
|
|
308
|
+
};
|
|
309
|
+
/** mDNS-discovered Thread Border Routers (passive). @since schema 12 */
|
|
163
310
|
get_thread_border_routers: {
|
|
164
311
|
requestArgs: Record<string, never>;
|
|
165
312
|
response: BorderRouterEntry[];
|
|
166
313
|
};
|
|
314
|
+
/**
|
|
315
|
+
* Per-Thread-network diagnostics. `ext_pan_id` selects one network (returns the batch, or `null`
|
|
316
|
+
* when nothing is cached / diagnostics are disabled); omitted returns an array of all known
|
|
317
|
+
* networks. `force` bypasses the cache. Also streamed via the `thread_diagnostics_updated` event.
|
|
318
|
+
* @since schema 12
|
|
319
|
+
*/
|
|
320
|
+
get_thread_diagnostics: {
|
|
321
|
+
requestArgs: { ext_pan_id?: string; force?: boolean };
|
|
322
|
+
response: ThreadDiagnosticsBatch | ThreadDiagnosticsBatch[] | null;
|
|
323
|
+
};
|
|
167
324
|
open_commissioning_window: {
|
|
168
325
|
requestArgs: {
|
|
169
326
|
node_id: number | bigint;
|
|
@@ -187,6 +344,26 @@ export interface APICommands {
|
|
|
187
344
|
requestArgs: { node_id: number | bigint };
|
|
188
345
|
response: null;
|
|
189
346
|
};
|
|
347
|
+
get_icd_state: {
|
|
348
|
+
requestArgs: { node_id: number | bigint };
|
|
349
|
+
response: IcdStateData;
|
|
350
|
+
};
|
|
351
|
+
register_icd: {
|
|
352
|
+
requestArgs: {
|
|
353
|
+
node_id: number | bigint;
|
|
354
|
+
allow_multi_admin?: boolean;
|
|
355
|
+
ignored_vendors?: number[];
|
|
356
|
+
};
|
|
357
|
+
response: IcdStateData;
|
|
358
|
+
};
|
|
359
|
+
resync_icd: {
|
|
360
|
+
requestArgs: { node_id: number | bigint };
|
|
361
|
+
response: null;
|
|
362
|
+
};
|
|
363
|
+
unregister_icd: {
|
|
364
|
+
requestArgs: { node_id: number | bigint; force?: boolean };
|
|
365
|
+
response: IcdStateData;
|
|
366
|
+
};
|
|
190
367
|
device_command: {
|
|
191
368
|
requestArgs: {
|
|
192
369
|
node_id: number | bigint;
|
|
@@ -287,6 +464,10 @@ export interface APICommands {
|
|
|
287
464
|
requestArgs: { label: string | null };
|
|
288
465
|
response: null;
|
|
289
466
|
};
|
|
467
|
+
get_fabric_label: {
|
|
468
|
+
requestArgs: Record<string, never>;
|
|
469
|
+
response: { fabric_label: string | null };
|
|
470
|
+
};
|
|
290
471
|
get_loglevel: {
|
|
291
472
|
requestArgs: Record<string, never>;
|
|
292
473
|
response: LogLevelResponse;
|
|
@@ -368,6 +549,11 @@ export interface CommandMessage {
|
|
|
368
549
|
args?: APICommands[keyof APICommands]["requestArgs"];
|
|
369
550
|
}
|
|
370
551
|
|
|
552
|
+
export interface AllCredentialsSummary {
|
|
553
|
+
wifi: Array<{ id: string; ssid: string }>;
|
|
554
|
+
thread: Array<{ id: string; networkName?: string; extPanId?: string }>;
|
|
555
|
+
}
|
|
556
|
+
|
|
371
557
|
export interface ServerInfoMessage {
|
|
372
558
|
fabric_id: number | bigint;
|
|
373
559
|
compressed_fabric_id: number | bigint;
|
|
@@ -415,6 +601,9 @@ export interface APIEvents {
|
|
|
415
601
|
server_info_updated: {
|
|
416
602
|
data: ServerInfoMessage;
|
|
417
603
|
};
|
|
604
|
+
thread_diagnostics_updated: {
|
|
605
|
+
data: ThreadDiagnosticsBatch;
|
|
606
|
+
};
|
|
418
607
|
webrtc_callback: {
|
|
419
608
|
data: WebRtcCallbackData;
|
|
420
609
|
};
|
|
@@ -459,6 +648,10 @@ interface ServerEventInfoUpdated {
|
|
|
459
648
|
event: "server_info_updated";
|
|
460
649
|
data: ServerInfoMessage;
|
|
461
650
|
}
|
|
651
|
+
interface ServerEventThreadDiagnosticsUpdated {
|
|
652
|
+
event: "thread_diagnostics_updated";
|
|
653
|
+
data: ThreadDiagnosticsBatch;
|
|
654
|
+
}
|
|
462
655
|
interface ServerEventWebRtcCallback {
|
|
463
656
|
event: "webrtc_callback";
|
|
464
657
|
data: WebRtcCallbackData;
|
|
@@ -474,6 +667,7 @@ export type EventMessage =
|
|
|
474
667
|
| ServerEventEndpointAdded
|
|
475
668
|
| ServerEventEndpointRemoved
|
|
476
669
|
| ServerEventInfoUpdated
|
|
670
|
+
| ServerEventThreadDiagnosticsUpdated
|
|
477
671
|
| ServerEventWebRtcCallback;
|
|
478
672
|
|
|
479
673
|
export interface ResultMessageBase {
|
|
@@ -547,6 +741,25 @@ export interface MatterFabricData {
|
|
|
547
741
|
vendor_name?: string;
|
|
548
742
|
}
|
|
549
743
|
|
|
744
|
+
/**
|
|
745
|
+
* Error code used when ICD registration is rejected because other administrator fabrics may not
|
|
746
|
+
* support LIT. OHF extension (python-matter-server codes stop at 11); the error `details` is a JSON
|
|
747
|
+
* string `{"message": string, "admin_vendor_ids": number[]}`.
|
|
748
|
+
*/
|
|
749
|
+
export const ICD_MULTI_ADMIN_ERROR_CODE = 100;
|
|
750
|
+
|
|
751
|
+
/** ICD controller-side state for a node. Note: Only available with OHF Matter Server. */
|
|
752
|
+
export interface IcdStateData {
|
|
753
|
+
supported: boolean;
|
|
754
|
+
lit_supported: boolean;
|
|
755
|
+
registered: boolean;
|
|
756
|
+
operating_mode: "SIT" | "LIT" | null;
|
|
757
|
+
awake: boolean | null;
|
|
758
|
+
available: boolean | null;
|
|
759
|
+
/** Epoch milliseconds of the next expected check-in, if known. */
|
|
760
|
+
next_expected_checkin: number | null;
|
|
761
|
+
}
|
|
762
|
+
|
|
550
763
|
export type NotificationType = "success" | "info" | "warning" | "error";
|
|
551
764
|
export type NodePingResult = Record<string, boolean>;
|
|
552
765
|
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025-2026 Open Home Foundation
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { BorderRouterEntry, MatterNodeData } from "../models/model.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Minimal structural view of a node required to derive network topology.
|
|
11
|
+
*
|
|
12
|
+
* The derivation only ever reads `node_id` and the flat `attributes`
|
|
13
|
+
* map, so it accepts this narrow shape rather than the full {@link MatterNode}
|
|
14
|
+
* class. Both the client-side `MatterNode` and any server-side node record that
|
|
15
|
+
* exposes these fields satisfy it, which lets the topology pipeline run in the
|
|
16
|
+
* browser (dashboard) and in Node (server) without a shared node class.
|
|
17
|
+
*/
|
|
18
|
+
export type TopologySourceNode = Pick<MatterNodeData, "node_id" | "attributes">;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Network type detected from NetworkCommissioning cluster feature map.
|
|
22
|
+
*/
|
|
23
|
+
export type NetworkType = "thread" | "wifi" | "ethernet" | "unknown";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Classification of a Thread mesh link based on LQI.
|
|
27
|
+
* "none" means LQI=0 — neighbor entry exists but no recent valid frames (dead/stale link).
|
|
28
|
+
*/
|
|
29
|
+
export type SignalLevel = "strong" | "medium" | "weak" | "none";
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Thread routing role from ThreadNetworkDiagnostics cluster.
|
|
33
|
+
* Attribute 0/53/1 (RoutingRole)
|
|
34
|
+
*/
|
|
35
|
+
export enum ThreadRoutingRole {
|
|
36
|
+
Unspecified = 0,
|
|
37
|
+
Unassigned = 1,
|
|
38
|
+
SleepyEndDevice = 2,
|
|
39
|
+
EndDevice = 3,
|
|
40
|
+
REED = 4, // Router-Eligible End Device
|
|
41
|
+
Router = 5,
|
|
42
|
+
Leader = 6,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Thread neighbor table entry from ThreadNetworkDiagnostics cluster.
|
|
47
|
+
* Attribute 0/53/7 (NeighborTable)
|
|
48
|
+
*/
|
|
49
|
+
export interface ThreadNeighbor {
|
|
50
|
+
/** Extended address of the neighbor (64-bit) */
|
|
51
|
+
extAddress: bigint;
|
|
52
|
+
/** Age of the entry in seconds */
|
|
53
|
+
age: number;
|
|
54
|
+
/** RLOC16 (Router Locator) */
|
|
55
|
+
rloc16: number;
|
|
56
|
+
/** Link frame counter */
|
|
57
|
+
linkFrameCounter: number;
|
|
58
|
+
/** MLE frame counter */
|
|
59
|
+
mleFrameCounter: number;
|
|
60
|
+
/**
|
|
61
|
+
* Link Quality Indicator. Spec types as uint8 (0-255), but OpenThread reports
|
|
62
|
+
* 0-3 in practice. 0 = no recent valid frames (dead/stale link).
|
|
63
|
+
*/
|
|
64
|
+
lqi: number;
|
|
65
|
+
/** Average RSSI in dBm (nullable) */
|
|
66
|
+
avgRssi: number | null;
|
|
67
|
+
/** Last RSSI in dBm (nullable) */
|
|
68
|
+
lastRssi: number | null;
|
|
69
|
+
/** Frame error rate (0-255) */
|
|
70
|
+
frameErrorRate: number;
|
|
71
|
+
/** Message error rate (0-255) */
|
|
72
|
+
messageErrorRate: number;
|
|
73
|
+
/** Whether RX is on when idle */
|
|
74
|
+
rxOnWhenIdle: boolean;
|
|
75
|
+
/** Whether this is a full Thread device */
|
|
76
|
+
fullThreadDevice: boolean;
|
|
77
|
+
/** Whether this is a full network data device */
|
|
78
|
+
fullNetworkData: boolean;
|
|
79
|
+
/** Whether the neighbor is a child of this node */
|
|
80
|
+
isChild: boolean;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Thread route table entry from ThreadNetworkDiagnostics cluster.
|
|
85
|
+
* Attribute 0/53/8 (RouteTable)
|
|
86
|
+
*/
|
|
87
|
+
export interface ThreadRoute {
|
|
88
|
+
/** Extended address of the destination */
|
|
89
|
+
extAddress: bigint;
|
|
90
|
+
/** RLOC16 of the destination */
|
|
91
|
+
rloc16: number;
|
|
92
|
+
/** Router ID */
|
|
93
|
+
routerId: number;
|
|
94
|
+
/** Next hop RLOC16 */
|
|
95
|
+
nextHop: number;
|
|
96
|
+
/** Path cost */
|
|
97
|
+
pathCost: number;
|
|
98
|
+
/** LQI in (0-3 on OpenThread; 0 = no link). */
|
|
99
|
+
lqiIn: number;
|
|
100
|
+
/** LQI out (0-3 on OpenThread; 0 = no link). */
|
|
101
|
+
lqiOut: number;
|
|
102
|
+
/** Age of the route */
|
|
103
|
+
age: number;
|
|
104
|
+
/** Whether this is allocated */
|
|
105
|
+
allocated: boolean;
|
|
106
|
+
/** Whether link is established */
|
|
107
|
+
linkEstablished: boolean;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* WiFi Diagnostics info from cluster 0x36/54.
|
|
112
|
+
*/
|
|
113
|
+
export interface WiFiDiagnostics {
|
|
114
|
+
/** BSSID as hex string */
|
|
115
|
+
bssid: string | null;
|
|
116
|
+
/** RSSI in dBm (-120 to 0) */
|
|
117
|
+
rssi: number | null;
|
|
118
|
+
/** WiFi channel */
|
|
119
|
+
channel: number | null;
|
|
120
|
+
/** Security type */
|
|
121
|
+
securityType: number | null;
|
|
122
|
+
/** WiFi version */
|
|
123
|
+
wifiVersion: number | null;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Categorized devices by network type.
|
|
128
|
+
* Node IDs are stored as strings to avoid BigInt precision loss.
|
|
129
|
+
*/
|
|
130
|
+
export interface CategorizedDevices {
|
|
131
|
+
thread: string[];
|
|
132
|
+
wifi: string[];
|
|
133
|
+
ethernet: string[];
|
|
134
|
+
unknown: string[];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Thread mesh connection between two nodes.
|
|
139
|
+
*
|
|
140
|
+
* Intentionally carries no color: color is a render concern derived from
|
|
141
|
+
* {@link signalLevel} by the consumer, keeping this model DOM/theme-free so the
|
|
142
|
+
* topology pipeline can run server-side.
|
|
143
|
+
*/
|
|
144
|
+
export interface ThreadConnection {
|
|
145
|
+
fromNodeId: number | string;
|
|
146
|
+
toNodeId: number | string;
|
|
147
|
+
signalLevel: SignalLevel;
|
|
148
|
+
lqi: number;
|
|
149
|
+
rssi: number | null;
|
|
150
|
+
/** Path cost from route table (1 = direct, higher = multi-hop). Only available for routers. */
|
|
151
|
+
pathCost?: number;
|
|
152
|
+
/** Bidirectional LQI from route table (average of lqiIn and lqiOut) */
|
|
153
|
+
bidirectionalLqi?: number;
|
|
154
|
+
/** Whether this connection was supplemented by route table data (vs neighbor table only) */
|
|
155
|
+
fromRouteTable?: boolean;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* A pair of Thread nodes with their directional edge data.
|
|
160
|
+
* Each connected pair has 0-2 edges (one per neighbor/route table direction).
|
|
161
|
+
*/
|
|
162
|
+
export interface ThreadEdgePair {
|
|
163
|
+
/** Canonical pair key (sorted node IDs joined by "|") */
|
|
164
|
+
pairKey: string;
|
|
165
|
+
/** First node ID (lexicographically smaller) */
|
|
166
|
+
nodeA: string;
|
|
167
|
+
/** Second node ID (lexicographically larger) */
|
|
168
|
+
nodeB: string;
|
|
169
|
+
/** Edge where nodeA reports nodeB as neighbor */
|
|
170
|
+
edgeAB?: ThreadConnection;
|
|
171
|
+
/** Edge where nodeB reports nodeA as neighbor */
|
|
172
|
+
edgeBA?: ThreadConnection;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Unknown Thread device seen in neighbor tables but not commissioned.
|
|
177
|
+
*/
|
|
178
|
+
export interface UnknownThreadDevice {
|
|
179
|
+
kind: "unknown";
|
|
180
|
+
/** Unique ID for the unknown device (prefixed with 'unknown_') */
|
|
181
|
+
id: string;
|
|
182
|
+
/** Extended address as hex string */
|
|
183
|
+
extAddressHex: string;
|
|
184
|
+
/** Extended address as BigInt */
|
|
185
|
+
extAddress: bigint;
|
|
186
|
+
/** Node IDs that see this device as a neighbor (as strings to avoid BigInt precision loss) */
|
|
187
|
+
seenBy: string[];
|
|
188
|
+
/** Whether this device appears to be a router */
|
|
189
|
+
isRouter: boolean;
|
|
190
|
+
/** Best signal strength seen */
|
|
191
|
+
bestRssi: number | null;
|
|
192
|
+
/**
|
|
193
|
+
* Extended PAN ID (16-char uppercase hex) inherited from the commissioned node that
|
|
194
|
+
* reports this neighbor. All Thread neighbors share the observing node's network.
|
|
195
|
+
*/
|
|
196
|
+
extendedPanIdHex?: string;
|
|
197
|
+
/**
|
|
198
|
+
* Friendly Thread network name resolved by joining {@link extendedPanIdHex} against the
|
|
199
|
+
* Border Router registry. Some BR vendors (e.g. Apple, Aqara) use a stable border-agent
|
|
200
|
+
* ID as the MeshCoP `xa` while the actual Thread radio MAC differs, so the BR can show
|
|
201
|
+
* up as both a known BR and an "unknown" router on the same network.
|
|
202
|
+
*/
|
|
203
|
+
networkName?: string;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Router/leader sourced purely from diagnostics (route64) that matches no
|
|
208
|
+
* commissioned Matter device, known BR, or neighbor-inferred unknown. Its
|
|
209
|
+
* childTable leaves are not materialized as nodes — they surface as {@link childCount}.
|
|
210
|
+
*/
|
|
211
|
+
export interface DiagnosticMeshNode {
|
|
212
|
+
kind: "diagnostic";
|
|
213
|
+
/** Graph id `thread_<EXTMAC>`, else `meshrloc_<extPanId>_<rloc16>`. */
|
|
214
|
+
id: string;
|
|
215
|
+
rloc16: number;
|
|
216
|
+
/** Uppercase hex Thread MAC if known. */
|
|
217
|
+
extAddressHex?: string;
|
|
218
|
+
isRouter: boolean;
|
|
219
|
+
vendorName?: string;
|
|
220
|
+
/** Number of childTable entries this router reports (shown as a label badge). */
|
|
221
|
+
childCount: number;
|
|
222
|
+
networkName: string;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Thread Border Router enriched via mDNS.
|
|
227
|
+
*
|
|
228
|
+
* Same neighbor-table aggregate fields as UnknownThreadDevice (seenBy, isRouter, bestRssi),
|
|
229
|
+
* plus all BorderRouterEntry fields (network name, vendor, addresses, etc.).
|
|
230
|
+
*/
|
|
231
|
+
export interface KnownBorderRouter extends BorderRouterEntry {
|
|
232
|
+
kind: "br";
|
|
233
|
+
/** DOM/graph ID, formatted "br_<XAHEX>". */
|
|
234
|
+
id: string;
|
|
235
|
+
/** Convenience copy of extAddressHex as bigint, mirroring UnknownThreadDevice. */
|
|
236
|
+
extAddress: bigint;
|
|
237
|
+
/** Commissioned node IDs whose neighbor table sees this xa. */
|
|
238
|
+
seenBy: string[];
|
|
239
|
+
/** Inferred from neighbor entry. */
|
|
240
|
+
isRouter: boolean;
|
|
241
|
+
/** Best signal strength seen across observers. */
|
|
242
|
+
bestRssi: number | null;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* External Thread device discriminated union — either a recognized Border Router
|
|
247
|
+
* or an unidentified neighbor.
|
|
248
|
+
*/
|
|
249
|
+
export type ThreadExternalDevice = KnownBorderRouter | UnknownThreadDevice;
|