@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
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025-2026 Open Home Foundation
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import type { BorderRouterEntry, MatterNodeData } from "../models/model.js";
|
|
7
|
+
/**
|
|
8
|
+
* Minimal structural view of a node required to derive network topology.
|
|
9
|
+
*
|
|
10
|
+
* The derivation only ever reads `node_id` and the flat `attributes`
|
|
11
|
+
* map, so it accepts this narrow shape rather than the full {@link MatterNode}
|
|
12
|
+
* class. Both the client-side `MatterNode` and any server-side node record that
|
|
13
|
+
* exposes these fields satisfy it, which lets the topology pipeline run in the
|
|
14
|
+
* browser (dashboard) and in Node (server) without a shared node class.
|
|
15
|
+
*/
|
|
16
|
+
export type TopologySourceNode = Pick<MatterNodeData, "node_id" | "attributes">;
|
|
17
|
+
/**
|
|
18
|
+
* Network type detected from NetworkCommissioning cluster feature map.
|
|
19
|
+
*/
|
|
20
|
+
export type NetworkType = "thread" | "wifi" | "ethernet" | "unknown";
|
|
21
|
+
/**
|
|
22
|
+
* Classification of a Thread mesh link based on LQI.
|
|
23
|
+
* "none" means LQI=0 — neighbor entry exists but no recent valid frames (dead/stale link).
|
|
24
|
+
*/
|
|
25
|
+
export type SignalLevel = "strong" | "medium" | "weak" | "none";
|
|
26
|
+
/**
|
|
27
|
+
* Thread routing role from ThreadNetworkDiagnostics cluster.
|
|
28
|
+
* Attribute 0/53/1 (RoutingRole)
|
|
29
|
+
*/
|
|
30
|
+
export declare enum ThreadRoutingRole {
|
|
31
|
+
Unspecified = 0,
|
|
32
|
+
Unassigned = 1,
|
|
33
|
+
SleepyEndDevice = 2,
|
|
34
|
+
EndDevice = 3,
|
|
35
|
+
REED = 4,// Router-Eligible End Device
|
|
36
|
+
Router = 5,
|
|
37
|
+
Leader = 6
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Thread neighbor table entry from ThreadNetworkDiagnostics cluster.
|
|
41
|
+
* Attribute 0/53/7 (NeighborTable)
|
|
42
|
+
*/
|
|
43
|
+
export interface ThreadNeighbor {
|
|
44
|
+
/** Extended address of the neighbor (64-bit) */
|
|
45
|
+
extAddress: bigint;
|
|
46
|
+
/** Age of the entry in seconds */
|
|
47
|
+
age: number;
|
|
48
|
+
/** RLOC16 (Router Locator) */
|
|
49
|
+
rloc16: number;
|
|
50
|
+
/** Link frame counter */
|
|
51
|
+
linkFrameCounter: number;
|
|
52
|
+
/** MLE frame counter */
|
|
53
|
+
mleFrameCounter: number;
|
|
54
|
+
/**
|
|
55
|
+
* Link Quality Indicator. Spec types as uint8 (0-255), but OpenThread reports
|
|
56
|
+
* 0-3 in practice. 0 = no recent valid frames (dead/stale link).
|
|
57
|
+
*/
|
|
58
|
+
lqi: number;
|
|
59
|
+
/** Average RSSI in dBm (nullable) */
|
|
60
|
+
avgRssi: number | null;
|
|
61
|
+
/** Last RSSI in dBm (nullable) */
|
|
62
|
+
lastRssi: number | null;
|
|
63
|
+
/** Frame error rate (0-255) */
|
|
64
|
+
frameErrorRate: number;
|
|
65
|
+
/** Message error rate (0-255) */
|
|
66
|
+
messageErrorRate: number;
|
|
67
|
+
/** Whether RX is on when idle */
|
|
68
|
+
rxOnWhenIdle: boolean;
|
|
69
|
+
/** Whether this is a full Thread device */
|
|
70
|
+
fullThreadDevice: boolean;
|
|
71
|
+
/** Whether this is a full network data device */
|
|
72
|
+
fullNetworkData: boolean;
|
|
73
|
+
/** Whether the neighbor is a child of this node */
|
|
74
|
+
isChild: boolean;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Thread route table entry from ThreadNetworkDiagnostics cluster.
|
|
78
|
+
* Attribute 0/53/8 (RouteTable)
|
|
79
|
+
*/
|
|
80
|
+
export interface ThreadRoute {
|
|
81
|
+
/** Extended address of the destination */
|
|
82
|
+
extAddress: bigint;
|
|
83
|
+
/** RLOC16 of the destination */
|
|
84
|
+
rloc16: number;
|
|
85
|
+
/** Router ID */
|
|
86
|
+
routerId: number;
|
|
87
|
+
/** Next hop RLOC16 */
|
|
88
|
+
nextHop: number;
|
|
89
|
+
/** Path cost */
|
|
90
|
+
pathCost: number;
|
|
91
|
+
/** LQI in (0-3 on OpenThread; 0 = no link). */
|
|
92
|
+
lqiIn: number;
|
|
93
|
+
/** LQI out (0-3 on OpenThread; 0 = no link). */
|
|
94
|
+
lqiOut: number;
|
|
95
|
+
/** Age of the route */
|
|
96
|
+
age: number;
|
|
97
|
+
/** Whether this is allocated */
|
|
98
|
+
allocated: boolean;
|
|
99
|
+
/** Whether link is established */
|
|
100
|
+
linkEstablished: boolean;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* WiFi Diagnostics info from cluster 0x36/54.
|
|
104
|
+
*/
|
|
105
|
+
export interface WiFiDiagnostics {
|
|
106
|
+
/** BSSID as hex string */
|
|
107
|
+
bssid: string | null;
|
|
108
|
+
/** RSSI in dBm (-120 to 0) */
|
|
109
|
+
rssi: number | null;
|
|
110
|
+
/** WiFi channel */
|
|
111
|
+
channel: number | null;
|
|
112
|
+
/** Security type */
|
|
113
|
+
securityType: number | null;
|
|
114
|
+
/** WiFi version */
|
|
115
|
+
wifiVersion: number | null;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Categorized devices by network type.
|
|
119
|
+
* Node IDs are stored as strings to avoid BigInt precision loss.
|
|
120
|
+
*/
|
|
121
|
+
export interface CategorizedDevices {
|
|
122
|
+
thread: string[];
|
|
123
|
+
wifi: string[];
|
|
124
|
+
ethernet: string[];
|
|
125
|
+
unknown: string[];
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Thread mesh connection between two nodes.
|
|
129
|
+
*
|
|
130
|
+
* Intentionally carries no color: color is a render concern derived from
|
|
131
|
+
* {@link signalLevel} by the consumer, keeping this model DOM/theme-free so the
|
|
132
|
+
* topology pipeline can run server-side.
|
|
133
|
+
*/
|
|
134
|
+
export interface ThreadConnection {
|
|
135
|
+
fromNodeId: number | string;
|
|
136
|
+
toNodeId: number | string;
|
|
137
|
+
signalLevel: SignalLevel;
|
|
138
|
+
lqi: number;
|
|
139
|
+
rssi: number | null;
|
|
140
|
+
/** Path cost from route table (1 = direct, higher = multi-hop). Only available for routers. */
|
|
141
|
+
pathCost?: number;
|
|
142
|
+
/** Bidirectional LQI from route table (average of lqiIn and lqiOut) */
|
|
143
|
+
bidirectionalLqi?: number;
|
|
144
|
+
/** Whether this connection was supplemented by route table data (vs neighbor table only) */
|
|
145
|
+
fromRouteTable?: boolean;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* A pair of Thread nodes with their directional edge data.
|
|
149
|
+
* Each connected pair has 0-2 edges (one per neighbor/route table direction).
|
|
150
|
+
*/
|
|
151
|
+
export interface ThreadEdgePair {
|
|
152
|
+
/** Canonical pair key (sorted node IDs joined by "|") */
|
|
153
|
+
pairKey: string;
|
|
154
|
+
/** First node ID (lexicographically smaller) */
|
|
155
|
+
nodeA: string;
|
|
156
|
+
/** Second node ID (lexicographically larger) */
|
|
157
|
+
nodeB: string;
|
|
158
|
+
/** Edge where nodeA reports nodeB as neighbor */
|
|
159
|
+
edgeAB?: ThreadConnection;
|
|
160
|
+
/** Edge where nodeB reports nodeA as neighbor */
|
|
161
|
+
edgeBA?: ThreadConnection;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Unknown Thread device seen in neighbor tables but not commissioned.
|
|
165
|
+
*/
|
|
166
|
+
export interface UnknownThreadDevice {
|
|
167
|
+
kind: "unknown";
|
|
168
|
+
/** Unique ID for the unknown device (prefixed with 'unknown_') */
|
|
169
|
+
id: string;
|
|
170
|
+
/** Extended address as hex string */
|
|
171
|
+
extAddressHex: string;
|
|
172
|
+
/** Extended address as BigInt */
|
|
173
|
+
extAddress: bigint;
|
|
174
|
+
/** Node IDs that see this device as a neighbor (as strings to avoid BigInt precision loss) */
|
|
175
|
+
seenBy: string[];
|
|
176
|
+
/** Whether this device appears to be a router */
|
|
177
|
+
isRouter: boolean;
|
|
178
|
+
/** Best signal strength seen */
|
|
179
|
+
bestRssi: number | null;
|
|
180
|
+
/**
|
|
181
|
+
* Extended PAN ID (16-char uppercase hex) inherited from the commissioned node that
|
|
182
|
+
* reports this neighbor. All Thread neighbors share the observing node's network.
|
|
183
|
+
*/
|
|
184
|
+
extendedPanIdHex?: string;
|
|
185
|
+
/**
|
|
186
|
+
* Friendly Thread network name resolved by joining {@link extendedPanIdHex} against the
|
|
187
|
+
* Border Router registry. Some BR vendors (e.g. Apple, Aqara) use a stable border-agent
|
|
188
|
+
* ID as the MeshCoP `xa` while the actual Thread radio MAC differs, so the BR can show
|
|
189
|
+
* up as both a known BR and an "unknown" router on the same network.
|
|
190
|
+
*/
|
|
191
|
+
networkName?: string;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Router/leader sourced purely from diagnostics (route64) that matches no
|
|
195
|
+
* commissioned Matter device, known BR, or neighbor-inferred unknown. Its
|
|
196
|
+
* childTable leaves are not materialized as nodes — they surface as {@link childCount}.
|
|
197
|
+
*/
|
|
198
|
+
export interface DiagnosticMeshNode {
|
|
199
|
+
kind: "diagnostic";
|
|
200
|
+
/** Graph id `thread_<EXTMAC>`, else `meshrloc_<extPanId>_<rloc16>`. */
|
|
201
|
+
id: string;
|
|
202
|
+
rloc16: number;
|
|
203
|
+
/** Uppercase hex Thread MAC if known. */
|
|
204
|
+
extAddressHex?: string;
|
|
205
|
+
isRouter: boolean;
|
|
206
|
+
vendorName?: string;
|
|
207
|
+
/** Number of childTable entries this router reports (shown as a label badge). */
|
|
208
|
+
childCount: number;
|
|
209
|
+
networkName: string;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Thread Border Router enriched via mDNS.
|
|
213
|
+
*
|
|
214
|
+
* Same neighbor-table aggregate fields as UnknownThreadDevice (seenBy, isRouter, bestRssi),
|
|
215
|
+
* plus all BorderRouterEntry fields (network name, vendor, addresses, etc.).
|
|
216
|
+
*/
|
|
217
|
+
export interface KnownBorderRouter extends BorderRouterEntry {
|
|
218
|
+
kind: "br";
|
|
219
|
+
/** DOM/graph ID, formatted "br_<XAHEX>". */
|
|
220
|
+
id: string;
|
|
221
|
+
/** Convenience copy of extAddressHex as bigint, mirroring UnknownThreadDevice. */
|
|
222
|
+
extAddress: bigint;
|
|
223
|
+
/** Commissioned node IDs whose neighbor table sees this xa. */
|
|
224
|
+
seenBy: string[];
|
|
225
|
+
/** Inferred from neighbor entry. */
|
|
226
|
+
isRouter: boolean;
|
|
227
|
+
/** Best signal strength seen across observers. */
|
|
228
|
+
bestRssi: number | null;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* External Thread device discriminated union — either a recognized Border Router
|
|
232
|
+
* or an unidentified neighbor.
|
|
233
|
+
*/
|
|
234
|
+
export type ThreadExternalDevice = KnownBorderRouter | UnknownThreadDevice;
|
|
235
|
+
//# sourceMappingURL=topology-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"topology-types.d.ts","sourceRoot":"","sources":["../../../src/topology/topology-types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAE5E;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,cAAc,EAAE,SAAS,GAAG,YAAY,CAAC,CAAC;AAEhF;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;AAErE;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAEhE;;;GAGG;AACH,oBAAY,iBAAiB;IACzB,WAAW,IAAI;IACf,UAAU,IAAI;IACd,eAAe,IAAI;IACnB,SAAS,IAAI;IACb,IAAI,IAAI,CAAE,6BAA6B;IACvC,MAAM,IAAI;IACV,MAAM,IAAI;CACb;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC3B,gDAAgD;IAChD,UAAU,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,wBAAwB;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,qCAAqC;IACrC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,kCAAkC;IAClC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,+BAA+B;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,iCAAiC;IACjC,YAAY,EAAE,OAAO,CAAC;IACtB,2CAA2C;IAC3C,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iDAAiD;IACjD,eAAe,EAAE,OAAO,CAAC;IACzB,mDAAmD;IACnD,OAAO,EAAE,OAAO,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IACxB,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,sBAAsB;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,uBAAuB;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,gCAAgC;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,kCAAkC;IAClC,eAAe,EAAE,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,0BAA0B;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,8BAA8B;IAC9B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,mBAAmB;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,oBAAoB;IACpB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mBAAmB;IACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IAC/B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC7B,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,WAAW,EAAE,WAAW,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,+FAA+F;IAC/F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,4FAA4F;IAC5F,cAAc,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC3B,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,iDAAiD;IACjD,MAAM,CAAC,EAAE,gBAAgB,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAChC,IAAI,EAAE,SAAS,CAAC;IAChB,kEAAkE;IAClE,EAAE,EAAE,MAAM,CAAC;IACX,qCAAqC;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,8FAA8F;IAC9F,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,iDAAiD;IACjD,QAAQ,EAAE,OAAO,CAAC;IAClB,gCAAgC;IAChC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IAC/B,IAAI,EAAE,YAAY,CAAC;IACnB,uEAAuE;IACvE,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACvB;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IACxD,IAAI,EAAE,IAAI,CAAC;IACX,4CAA4C;IAC5C,EAAE,EAAE,MAAM,CAAC;IACX,kFAAkF;IAClF,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,oCAAoC;IACpC,QAAQ,EAAE,OAAO,CAAC;IAClB,kDAAkD;IAClD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG,iBAAiB,GAAG,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025-2026 Open Home Foundation
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
var ThreadRoutingRole = /* @__PURE__ */ ((ThreadRoutingRole2) => {
|
|
7
|
+
ThreadRoutingRole2[ThreadRoutingRole2["Unspecified"] = 0] = "Unspecified";
|
|
8
|
+
ThreadRoutingRole2[ThreadRoutingRole2["Unassigned"] = 1] = "Unassigned";
|
|
9
|
+
ThreadRoutingRole2[ThreadRoutingRole2["SleepyEndDevice"] = 2] = "SleepyEndDevice";
|
|
10
|
+
ThreadRoutingRole2[ThreadRoutingRole2["EndDevice"] = 3] = "EndDevice";
|
|
11
|
+
ThreadRoutingRole2[ThreadRoutingRole2["REED"] = 4] = "REED";
|
|
12
|
+
ThreadRoutingRole2[ThreadRoutingRole2["Router"] = 5] = "Router";
|
|
13
|
+
ThreadRoutingRole2[ThreadRoutingRole2["Leader"] = 6] = "Leader";
|
|
14
|
+
return ThreadRoutingRole2;
|
|
15
|
+
})(ThreadRoutingRole || {});
|
|
16
|
+
export {
|
|
17
|
+
ThreadRoutingRole
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=topology-types.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/topology/topology-types.ts"],
|
|
4
|
+
"mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAkCO,IAAK,oBAAL,kBAAKA,uBAAL;AACH,EAAAA,sCAAA,iBAAc,KAAd;AACA,EAAAA,sCAAA,gBAAa,KAAb;AACA,EAAAA,sCAAA,qBAAkB,KAAlB;AACA,EAAAA,sCAAA,eAAY,KAAZ;AACA,EAAAA,sCAAA,UAAO,KAAP;AACA,EAAAA,sCAAA,YAAS,KAAT;AACA,EAAAA,sCAAA,YAAS,KAAT;AAPQ,SAAAA;AAAA,GAAA;",
|
|
5
|
+
"names": ["ThreadRoutingRole"]
|
|
6
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025-2026 Open Home Foundation
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import type { BorderRouterEntry, ThreadDiagnosticsBatch, ThreadDiagnosticsNode } from "../models/model.js";
|
|
7
|
+
import type { CategorizedDevices, DiagnosticMeshNode, NetworkType, SignalLevel, ThreadConnection, ThreadEdgePair, ThreadExternalDevice, ThreadNeighbor, ThreadRoute, TopologySourceNode, WiFiDiagnostics } from "./topology-types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Detects the network type from the NetworkCommissioning cluster feature map.
|
|
10
|
+
* Uses attribute 0/49/65532 (FeatureMap).
|
|
11
|
+
*/
|
|
12
|
+
export declare function getNetworkType(node: TopologySourceNode): NetworkType;
|
|
13
|
+
/**
|
|
14
|
+
* Thread protocol version supported by the device's Thread interface.
|
|
15
|
+
* Uses NetworkCommissioning cluster (0x31/49) ThreadVersion attribute (0x0A/10).
|
|
16
|
+
*/
|
|
17
|
+
export declare function getThreadVersion(node: TopologySourceNode): number | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Categorizes nodes by their network type.
|
|
20
|
+
* Node IDs are stored as strings to avoid BigInt precision loss.
|
|
21
|
+
*/
|
|
22
|
+
export declare function categorizeDevices(nodes: Record<string, TopologySourceNode>): CategorizedDevices;
|
|
23
|
+
/**
|
|
24
|
+
* Gets the Thread routing role for a node.
|
|
25
|
+
* Uses attribute 0/53/1 (RoutingRole, nullable per Matter spec).
|
|
26
|
+
*/
|
|
27
|
+
export declare function getThreadRole(node: TopologySourceNode): number | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Gets the Thread channel for a node.
|
|
30
|
+
* Uses attribute 0/53/0 (Channel, nullable per Matter spec).
|
|
31
|
+
*/
|
|
32
|
+
export declare function getThreadChannel(node: TopologySourceNode): number | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Gets the Thread extended PAN ID for a node.
|
|
35
|
+
* Uses attribute 0/53/4 (ExtendedPanId, nullable per Matter spec).
|
|
36
|
+
*
|
|
37
|
+
* The WebSocket JSON reviver only revives integers above Number.MAX_SAFE_INTEGER
|
|
38
|
+
* as bigint; smaller uint64 values arrive as plain number, so accept both.
|
|
39
|
+
*/
|
|
40
|
+
export declare function getThreadExtendedPanId(node: TopologySourceNode): bigint | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Gets the Thread extended address (EUI-64) for a node.
|
|
43
|
+
*
|
|
44
|
+
* Uses General Diagnostics cluster (0x0033/51) NetworkInterfaces attribute (0/51/0).
|
|
45
|
+
* The NetworkInterface struct has:
|
|
46
|
+
* - Field 4: HardwareAddress (base64 encoded EUI-64)
|
|
47
|
+
* - Field 7: Type (4 = Thread)
|
|
48
|
+
*
|
|
49
|
+
* Returns the full EUI-64 as BigInt. Decoded from the base64 hardware address,
|
|
50
|
+
* so it is exact and used whole for matching — the JSON number-precision caveat
|
|
51
|
+
* that applies to revived integers does not apply here.
|
|
52
|
+
*/
|
|
53
|
+
export declare function getThreadExtendedAddress(node: TopologySourceNode): bigint | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* Gets the Thread extended address as a hex string for display.
|
|
56
|
+
* Uses General Diagnostics NetworkInterfaces (0/51/0).
|
|
57
|
+
*/
|
|
58
|
+
export declare function getThreadExtendedAddressHex(node: TopologySourceNode): string | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* Counts entries in the Thread neighbor table without normalizing each entry.
|
|
61
|
+
* Use this in hot paths where only the cardinality matters; the full parse
|
|
62
|
+
* does a base64 decode per entry that adds up across re-renders.
|
|
63
|
+
*/
|
|
64
|
+
export declare function getNeighborTableLength(node: TopologySourceNode): number;
|
|
65
|
+
/**
|
|
66
|
+
* Parses the Thread neighbor table from a node's attributes.
|
|
67
|
+
* Attribute 0/53/7 (NeighborTable) is an array of neighbor objects.
|
|
68
|
+
* The data uses numeric keys matching the Matter spec field IDs.
|
|
69
|
+
*/
|
|
70
|
+
export declare function parseNeighborTable(node: TopologySourceNode): ThreadNeighbor[];
|
|
71
|
+
/**
|
|
72
|
+
* Parses the Thread route table from a node's attributes.
|
|
73
|
+
* Attribute 0/53/8 (RouteTable) is an array of route objects.
|
|
74
|
+
* The data uses numeric keys matching the Matter spec field IDs.
|
|
75
|
+
*/
|
|
76
|
+
export declare function parseRouteTable(node: TopologySourceNode): ThreadRoute[];
|
|
77
|
+
/**
|
|
78
|
+
* Find a route table entry for a specific destination by extended address.
|
|
79
|
+
* Returns the route entry if found, undefined otherwise.
|
|
80
|
+
*/
|
|
81
|
+
export declare function findRouteByExtAddress(node: TopologySourceNode, targetExtAddr: bigint): ThreadRoute | undefined;
|
|
82
|
+
/**
|
|
83
|
+
* Count the number of routable destinations for a node (from route table).
|
|
84
|
+
* Only counts entries where allocated=true and linkEstablished=true.
|
|
85
|
+
* This is typically only meaningful for router nodes.
|
|
86
|
+
*/
|
|
87
|
+
export declare function getRoutableDestinationsCount(node: TopologySourceNode): number;
|
|
88
|
+
/**
|
|
89
|
+
* Calculate combined bidirectional LQI from route table entry.
|
|
90
|
+
* Returns average of lqiIn and lqiOut if both are non-zero.
|
|
91
|
+
*/
|
|
92
|
+
export declare function getRouteBidirectionalLqi(route: Pick<ThreadRoute, "lqiIn" | "lqiOut">): number | undefined;
|
|
93
|
+
/**
|
|
94
|
+
* Gets the RLOC16 (short address) for a Thread node.
|
|
95
|
+
* Uses attribute 0/53/64 (Rloc16, 0x0040).
|
|
96
|
+
*/
|
|
97
|
+
export declare function getThreadRloc16(node: TopologySourceNode): number | undefined;
|
|
98
|
+
/**
|
|
99
|
+
* Builds a map of extended addresses (BigInt) to node IDs for Thread devices.
|
|
100
|
+
* Uses General Diagnostics NetworkInterfaces (0/51/0) for the hardware address.
|
|
101
|
+
* Node IDs are stored as strings to avoid BigInt precision loss.
|
|
102
|
+
*/
|
|
103
|
+
export declare function buildExtAddrMap(nodes: Record<string, TopologySourceNode>): Map<bigint, string>;
|
|
104
|
+
/**
|
|
105
|
+
* Builds a map of RLOC16 (short addresses) to node IDs for Thread devices.
|
|
106
|
+
* Used as fallback when ExtAddress is not available.
|
|
107
|
+
* Node IDs are stored as strings to avoid BigInt precision loss.
|
|
108
|
+
*/
|
|
109
|
+
export declare function buildRloc16Map(nodes: Record<string, TopologySourceNode>): Map<number, string>;
|
|
110
|
+
/**
|
|
111
|
+
* Stable graph id for a diagnostic mesh node: prefer the globally-unique extMac,
|
|
112
|
+
* else an rloc16 namespaced by extPanId (rloc16 is only unique within a network).
|
|
113
|
+
*/
|
|
114
|
+
export declare function diagnosticNodeId(node: Pick<ThreadDiagnosticsNode, "extMacAddress" | "rloc16">, extPanIdHex: string): string;
|
|
115
|
+
/**
|
|
116
|
+
* `extPanId:rloc16` -> Matter node id, scoped per Thread network. rloc16 is only
|
|
117
|
+
* unique within a network, so a global rloc16 map would mis-attach diagnostic
|
|
118
|
+
* edges from one network onto a Matter device on another. Keyed via {@link diagRlocKey}.
|
|
119
|
+
*/
|
|
120
|
+
export declare function buildMatterRloc16ByXp(nodes: Record<string, TopologySourceNode>): Map<string, string>;
|
|
121
|
+
/**
|
|
122
|
+
* `extPanId:rloc16` -> graph node id across diagnostic batches, layered UNDER the
|
|
123
|
+
* Matter rloc16 map. Resolves route64/childTable references within the referencing
|
|
124
|
+
* node's own network to whatever id that node is drawn as (Matter / `br_` /
|
|
125
|
+
* `unknown_` / diagnostic). Keyed via {@link diagRlocKey}.
|
|
126
|
+
*/
|
|
127
|
+
export declare function buildDiagnosticRloc16Map(batches: ReadonlyMap<string, ThreadDiagnosticsBatch>, matterRloc16ByXp: Map<string, string>, matterExtAddrMap: Map<bigint, string>, borderRouters: ReadonlyMap<string, BorderRouterEntry>, unknownDevices: ThreadExternalDevice[]): Map<string, string>;
|
|
128
|
+
/**
|
|
129
|
+
* Build a per-network rloc16 resolver: a Matter device on the same Thread network
|
|
130
|
+
* wins, else the diagnostic node id within the same extPanId. Returns undefined
|
|
131
|
+
* when unresolved. Both lookups are keyed by `extPanId:rloc16` so identical rloc16
|
|
132
|
+
* values across networks never cross-attach.
|
|
133
|
+
*/
|
|
134
|
+
export declare function makeDiagnosticRloc16Resolver(matterRloc16ByXp: Map<string, string>, diagRloc16Map: Map<string, string>): (rloc16: number, extPanIdHex: string) => string | undefined;
|
|
135
|
+
/**
|
|
136
|
+
* Finds external Thread devices - addresses seen in neighbor tables that don't match
|
|
137
|
+
* any commissioned device. Classifies each against the optional Border Router registry:
|
|
138
|
+
* matched ones are emitted as kind:"br" with full mDNS enrichment; the rest stay as
|
|
139
|
+
* kind:"unknown". Uses RLOC16 as fallback when extended address matching fails.
|
|
140
|
+
*/
|
|
141
|
+
export declare function findUnknownDevices(nodes: Record<string, TopologySourceNode>, extAddrMap: Map<bigint, string>, rloc16Map: Map<number, string>, borderRouters?: ReadonlyMap<string, BorderRouterEntry>): ThreadExternalDevice[];
|
|
142
|
+
/** Determine signal level from a Thread neighbor's LQI. */
|
|
143
|
+
export declare function getSignalLevel(neighbor: ThreadNeighbor): SignalLevel;
|
|
144
|
+
/**
|
|
145
|
+
* Map an LQI value (0-3 in practice on OpenThread) to a signal level.
|
|
146
|
+
* 0 = "none" (no recent valid frames — stale/dead link).
|
|
147
|
+
*/
|
|
148
|
+
export declare function getSignalLevelFromLqi(lqi: number): SignalLevel;
|
|
149
|
+
/**
|
|
150
|
+
* Materialize mesh nodes that exist only in diagnostics: router records and
|
|
151
|
+
* childTable children whose rloc16/extMac matches no Matter device, BR, or
|
|
152
|
+
* already-found unknown. Matter/BR/unknown matches are enriched in place, not
|
|
153
|
+
* duplicated.
|
|
154
|
+
*/
|
|
155
|
+
export declare function findDiagnosticMeshNodes(batches: ReadonlyMap<string, ThreadDiagnosticsBatch>, matterRloc16ByXp: Map<string, string>, matterExtAddrMap: Map<bigint, string>, borderRouters: ReadonlyMap<string, BorderRouterEntry>, unknownDevices: ThreadExternalDevice[]): DiagnosticMeshNode[];
|
|
156
|
+
/**
|
|
157
|
+
* Creates a canonical pair key from two node IDs.
|
|
158
|
+
* The key is always ordered so that the same pair produces the same key regardless of direction.
|
|
159
|
+
*/
|
|
160
|
+
export declare function makePairKey(a: string, b: string): string;
|
|
161
|
+
/**
|
|
162
|
+
* Computes a numeric signal score for edge comparison.
|
|
163
|
+
* Lower score = weaker signal (worst case).
|
|
164
|
+
*/
|
|
165
|
+
export declare function getEdgeSignalScore(conn: ThreadConnection): number;
|
|
166
|
+
/**
|
|
167
|
+
* Builds edge pairs for all Thread connections.
|
|
168
|
+
* Each pair represents two connected nodes with up to 2 directional edges
|
|
169
|
+
* (one from each node's neighbor/route table). No dedup is performed —
|
|
170
|
+
* callers are responsible for selecting which edge to display per pair.
|
|
171
|
+
*/
|
|
172
|
+
export declare function buildThreadEdgePairs(nodes: Record<string, TopologySourceNode>, extAddrMap: Map<bigint, string>, rloc16Map: Map<number, string>, unknownDevices: ThreadExternalDevice[]): Map<string, ThreadEdgePair>;
|
|
173
|
+
/**
|
|
174
|
+
* Merge route64 (router<->router) and childTable (router->child) edges from
|
|
175
|
+
* diagnostics into an existing edge-pair map. Resolves references to graph node
|
|
176
|
+
* ids via `resolveRloc16`; unresolved references are dropped (no phantom nodes).
|
|
177
|
+
* Existing edges (Matter-sourced) take precedence per direction.
|
|
178
|
+
*/
|
|
179
|
+
export declare function mergeDiagnosticEdges(pairs: Map<string, ThreadEdgePair>, batches: ReadonlyMap<string, ThreadDiagnosticsBatch>, resolveRloc16: (rloc16: number, extPanIdHex: string) => string | undefined): void;
|
|
180
|
+
/**
|
|
181
|
+
* Parses WiFi diagnostics from a node's attributes.
|
|
182
|
+
* Cluster 0x36/54 - WiFi Network Diagnostics.
|
|
183
|
+
*/
|
|
184
|
+
export declare function getWiFiDiagnostics(node: TopologySourceNode): WiFiDiagnostics;
|
|
185
|
+
//# sourceMappingURL=topology-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"topology-utils.d.ts","sourceRoot":"","sources":["../../../src/topology/topology-utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3G,OAAO,KAAK,EACR,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACpB,cAAc,EACd,WAAW,EACX,kBAAkB,EAClB,eAAe,EAClB,MAAM,qBAAqB,CAAC;AAqD7B;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,WAAW,CAmBpE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,GAAG,SAAS,CAG7E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAAG,kBAAkB,CAe/F;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,GAAG,SAAS,CAG1E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,GAAG,SAAS,CAG7E;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,GAAG,SAAS,CAKnF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,GAAG,SAAS,CAyBrF;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,GAAG,SAAS,CAMxF;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAGvE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,kBAAkB,GAAG,cAAc,EAAE,CA0C7E;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,kBAAkB,GAAG,WAAW,EAAE,CAkCvE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAG9G;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAG7E;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,QAAQ,CAAC,GAAG,MAAM,GAAG,SAAS,CAOzG;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,GAAG,SAAS,CAM5E;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAa9F;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAa7F;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC5B,IAAI,EAAE,IAAI,CAAC,qBAAqB,EAAE,eAAe,GAAG,QAAQ,CAAC,EAC7D,WAAW,EAAE,MAAM,GACpB,MAAM,CAGR;AAOD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CASpG;AA2BD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACpC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,sBAAsB,CAAC,EACpD,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,EACrD,cAAc,EAAE,oBAAoB,EAAE,GACvC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAiBrB;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CACxC,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAG7D;AAYD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,EACzC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,aAAa,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,GACvD,oBAAoB,EAAE,CAyFxB;AAED,2DAA2D;AAC3D,wBAAgB,cAAc,CAAC,QAAQ,EAAE,cAAc,GAAG,WAAW,CAEpE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAK9D;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACnC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,sBAAsB,CAAC,EACpD,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,EACrD,cAAc,EAAE,oBAAoB,EAAE,GACvC,kBAAkB,EAAE,CAqCtB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAWjE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,EACzC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,cAAc,EAAE,oBAAoB,EAAE,GACvC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAiH7B;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAChC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,EAClC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,sBAAsB,CAAC,EACpD,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,GAC3E,IAAI,CAsDN;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,kBAAkB,GAAG,eAAe,CAkC5E"}
|