@matter-server/ws-client 0.2.7-alpha.0-20260118-993a1c7 → 0.2.7-alpha.0-20260119-49e7237
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/README.md +90 -0
- package/dist/esm/client.d.ts +69 -26
- package/dist/esm/client.d.ts.map +1 -1
- package/dist/esm/client.js +226 -101
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/connection.d.ts.map +1 -1
- package/dist/esm/connection.js +3 -0
- package/dist/esm/connection.js.map +1 -1
- package/dist/esm/exceptions.d.ts +14 -0
- package/dist/esm/exceptions.d.ts.map +1 -1
- package/dist/esm/exceptions.js +16 -0
- package/dist/esm/exceptions.js.map +1 -1
- package/dist/esm/models/model.d.ts +30 -0
- package/dist/esm/models/model.d.ts.map +1 -1
- package/dist/esm/models/model.js +8 -1
- package/dist/esm/models/model.js.map +1 -1
- package/package.json +2 -2
- package/src/client.ts +267 -97
- package/src/connection.ts +5 -0
- package/src/exceptions.ts +23 -0
- package/src/models/model.ts +34 -0
package/README.md
CHANGED
|
@@ -85,6 +85,7 @@ new MatterClient(url: string, wsFactory?: WebSocketFactory)
|
|
|
85
85
|
- `serverInfo`: Server information (fabric ID, SDK version, etc.)
|
|
86
86
|
- `serverBaseAddress`: The base address extracted from the URL
|
|
87
87
|
- `isProduction`: Whether connected to a production server (for UI purposes)
|
|
88
|
+
- `commandTimeout`: Default timeout for commands in milliseconds (default: 5 minutes). Set to `0` to disable timeouts.
|
|
88
89
|
|
|
89
90
|
#### Methods
|
|
90
91
|
|
|
@@ -114,6 +115,90 @@ new MatterClient(url: string, wsFactory?: WebSocketFactory)
|
|
|
114
115
|
- `server_info_updated`: Fired when server info changes
|
|
115
116
|
- `connection_lost`: Fired when connection is lost
|
|
116
117
|
|
|
118
|
+
### Server Info
|
|
119
|
+
|
|
120
|
+
The `serverInfo` property contains information about the connected Matter server:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
interface ServerInfoMessage {
|
|
124
|
+
fabric_id: bigint; // The fabric ID
|
|
125
|
+
compressed_fabric_id: bigint; // Compressed fabric ID (global ID)
|
|
126
|
+
fabric_index?: number; // The fabric index (OHF Matter Server only)
|
|
127
|
+
schema_version: number; // API schema version
|
|
128
|
+
min_supported_schema_version: number;
|
|
129
|
+
sdk_version: string; // Server SDK version string
|
|
130
|
+
wifi_credentials_set: boolean; // Whether WiFi credentials are configured
|
|
131
|
+
thread_credentials_set: boolean; // Whether Thread dataset is configured
|
|
132
|
+
bluetooth_enabled: boolean; // Whether BLE commissioning is available
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Note:** The `fabric_index` field is specific to OHF Matter Server and is not available in Python Matter Server. When connecting to Python Matter Server, this field will be undefined.
|
|
137
|
+
|
|
138
|
+
### Command Timeouts
|
|
139
|
+
|
|
140
|
+
All commands have a default timeout of 5 minutes (300,000ms) to prevent promises from hanging indefinitely if the server doesn't respond. You can configure this behavior globally or per-call:
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
import { MatterClient, CommandTimeoutError, DEFAULT_COMMAND_TIMEOUT } from "@matter-server/ws-client";
|
|
144
|
+
|
|
145
|
+
const client = new MatterClient("ws://localhost:5580/ws");
|
|
146
|
+
|
|
147
|
+
// Check the default timeout (5 minutes)
|
|
148
|
+
console.log(DEFAULT_COMMAND_TIMEOUT); // 300000
|
|
149
|
+
|
|
150
|
+
// Change the default timeout for all commands (e.g., 1 minute)
|
|
151
|
+
client.commandTimeout = 60000;
|
|
152
|
+
|
|
153
|
+
// Disable timeouts entirely (not recommended)
|
|
154
|
+
client.commandTimeout = 0;
|
|
155
|
+
|
|
156
|
+
// Override timeout for a specific call (e.g., 30 seconds for a quick command)
|
|
157
|
+
await client.deviceCommand(nodeId, 1, 6, "toggle", {}, 30000);
|
|
158
|
+
|
|
159
|
+
// Use a longer timeout for operations that take time (e.g., 10 minutes for commissioning)
|
|
160
|
+
await client.commissionWithCode("MT:Y3.5UNQO100KA0648G00", false, 600000);
|
|
161
|
+
|
|
162
|
+
// Handle timeout errors
|
|
163
|
+
try {
|
|
164
|
+
await client.deviceCommand(nodeId, 1, 6, "toggle");
|
|
165
|
+
} catch (err) {
|
|
166
|
+
if (err instanceof CommandTimeoutError) {
|
|
167
|
+
console.log(`Command '${err.command}' timed out after ${err.timeoutMs}ms`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
All client methods accept an optional `timeout` parameter as their last argument to override the default timeout for that specific call.
|
|
173
|
+
|
|
174
|
+
### Connection Handling
|
|
175
|
+
|
|
176
|
+
When the WebSocket connection is closed (either by calling `disconnect()` or due to connection loss), all pending commands are automatically rejected with a `ConnectionClosedError`:
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
import { MatterClient, ConnectionClosedError } from "@matter-server/ws-client";
|
|
180
|
+
|
|
181
|
+
const client = new MatterClient("ws://localhost:5580/ws");
|
|
182
|
+
await client.connect();
|
|
183
|
+
|
|
184
|
+
// Start a long-running command
|
|
185
|
+
const commandPromise = client.commissionWithCode("MT:Y3.5UNQO100KA0648G00", false);
|
|
186
|
+
|
|
187
|
+
// If the connection is lost or disconnected while the command is pending:
|
|
188
|
+
try {
|
|
189
|
+
await commandPromise;
|
|
190
|
+
} catch (err) {
|
|
191
|
+
if (err instanceof ConnectionClosedError) {
|
|
192
|
+
console.log("Connection was closed while command was pending");
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Listen for connection loss events
|
|
197
|
+
client.addEventListener("connection_lost", () => {
|
|
198
|
+
console.log("Connection to server was lost");
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
117
202
|
### Other Exports
|
|
118
203
|
|
|
119
204
|
```typescript
|
|
@@ -126,6 +211,11 @@ import {
|
|
|
126
211
|
// Exceptions
|
|
127
212
|
MatterError,
|
|
128
213
|
InvalidServerVersion,
|
|
214
|
+
CommandTimeoutError,
|
|
215
|
+
ConnectionClosedError,
|
|
216
|
+
|
|
217
|
+
// Constants
|
|
218
|
+
DEFAULT_COMMAND_TIMEOUT,
|
|
129
219
|
|
|
130
220
|
// Types
|
|
131
221
|
ServerInfoMessage,
|
package/dist/esm/client.d.ts
CHANGED
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
import { Connection, WebSocketFactory } from "./connection.js";
|
|
7
|
-
import { AccessControlEntry, APICommands, BindingTarget, CommissionableNodeData, CommissioningParameters, EventMessage, MatterFabricData, MatterSoftwareVersion, NodePingResult } from "./models/model.js";
|
|
7
|
+
import { AccessControlEntry, APICommands, BindingTarget, CommissionableNodeData, CommissioningParameters, EventMessage, LogLevelResponse, LogLevelString, MatterFabricData, MatterSoftwareVersion, NodePingResult } from "./models/model.js";
|
|
8
8
|
import { MatterNode } from "./models/node.js";
|
|
9
|
+
/** Default timeout for WebSocket commands in milliseconds (5 minutes) */
|
|
10
|
+
export declare const DEFAULT_COMMAND_TIMEOUT: number;
|
|
9
11
|
export declare class MatterClient {
|
|
10
12
|
url: string;
|
|
11
13
|
connection: Connection;
|
|
@@ -13,6 +15,8 @@ export declare class MatterClient {
|
|
|
13
15
|
serverBaseAddress: string;
|
|
14
16
|
/** Whether this client is connected to a production server (optional, for UI purposes) */
|
|
15
17
|
isProduction: boolean;
|
|
18
|
+
/** Default timeout for commands in milliseconds. Set to 0 to disable timeouts. */
|
|
19
|
+
commandTimeout: number;
|
|
16
20
|
private result_futures;
|
|
17
21
|
private msgId;
|
|
18
22
|
private eventListeners;
|
|
@@ -26,31 +30,70 @@ export declare class MatterClient {
|
|
|
26
30
|
constructor(url: string, wsFactory?: WebSocketFactory);
|
|
27
31
|
get serverInfo(): import("./models/model.js").ServerInfoMessage;
|
|
28
32
|
addEventListener(event: string, listener: () => void): () => void;
|
|
29
|
-
commissionWithCode(code: string, networkOnly?: boolean): Promise<MatterNode>;
|
|
30
|
-
setWifiCredentials(ssid: string, credentials: string): Promise<void>;
|
|
31
|
-
setThreadOperationalDataset(dataset: string): Promise<void>;
|
|
32
|
-
openCommissioningWindow(nodeId: number | bigint,
|
|
33
|
-
discoverCommissionableNodes(): Promise<CommissionableNodeData[]>;
|
|
34
|
-
getMatterFabrics(nodeId: number | bigint): Promise<MatterFabricData[]>;
|
|
35
|
-
removeMatterFabric(nodeId: number | bigint, fabricIndex: number): Promise<void>;
|
|
36
|
-
pingNode(nodeId: number | bigint, attempts?: number): Promise<NodePingResult>;
|
|
37
|
-
getNodeIPAddresses(nodeId: number | bigint, preferCache?: boolean, scoped?: boolean): Promise<string[]>;
|
|
38
|
-
removeNode(nodeId: number | bigint): Promise<void>;
|
|
39
|
-
interviewNode(nodeId: number | bigint): Promise<void>;
|
|
40
|
-
importTestNode(dump: string): Promise<void>;
|
|
41
|
-
readAttribute(nodeId: number | bigint, attributePath: string | string[]): Promise<Record<string, unknown>>;
|
|
42
|
-
writeAttribute(nodeId: number | bigint, attributePath: string, value: unknown): Promise<unknown>;
|
|
43
|
-
checkNodeUpdate(nodeId: number | bigint): Promise<MatterSoftwareVersion | null>;
|
|
44
|
-
updateNode(nodeId: number | bigint, softwareVersion: number | string): Promise<void>;
|
|
45
|
-
setACLEntry(nodeId: number | bigint, entry: AccessControlEntry[]): Promise<import("./models/model.js").AttributeWriteResult[] | null>;
|
|
46
|
-
setNodeBinding(nodeId: number | bigint, endpoint: number, bindings: BindingTarget[]): Promise<import("./models/model.js").AttributeWriteResult[] | null>;
|
|
47
|
-
deviceCommand(nodeId: number | bigint, endpointId: number, clusterId: number, commandName: string, payload?: Record<string, unknown
|
|
48
|
-
getNodes(onlyAvailable?: boolean): Promise<MatterNode[]>;
|
|
49
|
-
getNode(nodeId: number | bigint): Promise<MatterNode>;
|
|
50
|
-
getVendorNames(filterVendors?: number[]): Promise<Record<string, string>>;
|
|
51
|
-
fetchServerInfo(): Promise<import("./models/model.js").ServerInfoMessage>;
|
|
52
|
-
setDefaultFabricLabel(label: string | null): Promise<void>;
|
|
53
|
-
|
|
33
|
+
commissionWithCode(code: string, networkOnly?: boolean, timeout?: number): Promise<MatterNode>;
|
|
34
|
+
setWifiCredentials(ssid: string, credentials: string, timeout?: number): Promise<void>;
|
|
35
|
+
setThreadOperationalDataset(dataset: string, timeout?: number): Promise<void>;
|
|
36
|
+
openCommissioningWindow(nodeId: number | bigint, windowTimeout?: number, iteration?: number, option?: number, discriminator?: number, timeout?: number): Promise<CommissioningParameters>;
|
|
37
|
+
discoverCommissionableNodes(timeout?: number): Promise<CommissionableNodeData[]>;
|
|
38
|
+
getMatterFabrics(nodeId: number | bigint, timeout?: number): Promise<MatterFabricData[]>;
|
|
39
|
+
removeMatterFabric(nodeId: number | bigint, fabricIndex: number, timeout?: number): Promise<void>;
|
|
40
|
+
pingNode(nodeId: number | bigint, attempts?: number, timeout?: number): Promise<NodePingResult>;
|
|
41
|
+
getNodeIPAddresses(nodeId: number | bigint, preferCache?: boolean, scoped?: boolean, timeout?: number): Promise<string[]>;
|
|
42
|
+
removeNode(nodeId: number | bigint, timeout?: number): Promise<void>;
|
|
43
|
+
interviewNode(nodeId: number | bigint, timeout?: number): Promise<void>;
|
|
44
|
+
importTestNode(dump: string, timeout?: number): Promise<void>;
|
|
45
|
+
readAttribute(nodeId: number | bigint, attributePath: string | string[], timeout?: number): Promise<Record<string, unknown>>;
|
|
46
|
+
writeAttribute(nodeId: number | bigint, attributePath: string, value: unknown, timeout?: number): Promise<unknown>;
|
|
47
|
+
checkNodeUpdate(nodeId: number | bigint, timeout?: number): Promise<MatterSoftwareVersion | null>;
|
|
48
|
+
updateNode(nodeId: number | bigint, softwareVersion: number | string, timeout?: number): Promise<void>;
|
|
49
|
+
setACLEntry(nodeId: number | bigint, entry: AccessControlEntry[], timeout?: number): Promise<import("./models/model.js").AttributeWriteResult[] | null>;
|
|
50
|
+
setNodeBinding(nodeId: number | bigint, endpoint: number, bindings: BindingTarget[], timeout?: number): Promise<import("./models/model.js").AttributeWriteResult[] | null>;
|
|
51
|
+
deviceCommand(nodeId: number | bigint, endpointId: number, clusterId: number, commandName: string, payload?: Record<string, unknown>, timeout?: number): Promise<unknown>;
|
|
52
|
+
getNodes(onlyAvailable?: boolean, timeout?: number): Promise<MatterNode[]>;
|
|
53
|
+
getNode(nodeId: number | bigint, timeout?: number): Promise<MatterNode>;
|
|
54
|
+
getVendorNames(filterVendors?: number[], timeout?: number): Promise<Record<string, string>>;
|
|
55
|
+
fetchServerInfo(timeout?: number): Promise<import("./models/model.js").ServerInfoMessage>;
|
|
56
|
+
setDefaultFabricLabel(label: string | null, timeout?: number): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Get the current log levels for console and file logging.
|
|
59
|
+
* @param timeout Optional command timeout in milliseconds
|
|
60
|
+
* @returns The current log level configuration
|
|
61
|
+
*/
|
|
62
|
+
getLogLevel(timeout?: number): Promise<LogLevelResponse>;
|
|
63
|
+
/**
|
|
64
|
+
* Set the log level for console and/or file logging.
|
|
65
|
+
* Changes are temporary and will be reset when the server restarts.
|
|
66
|
+
* @param consoleLoglevel Console log level to set (optional)
|
|
67
|
+
* @param fileLoglevel File log level to set, only applied if file logging is enabled (optional)
|
|
68
|
+
* @param timeout Optional command timeout in milliseconds
|
|
69
|
+
* @returns The log level configuration after the change
|
|
70
|
+
*/
|
|
71
|
+
setLogLevel(consoleLoglevel?: LogLevelString, fileLoglevel?: LogLevelString, timeout?: number): Promise<LogLevelResponse>;
|
|
72
|
+
/**
|
|
73
|
+
* Send a command to the Matter server.
|
|
74
|
+
* @param command The command name
|
|
75
|
+
* @param require_schema Minimum schema version required (0 for any version)
|
|
76
|
+
* @param args Command arguments
|
|
77
|
+
* @param timeout Optional timeout in milliseconds. Defaults to `commandTimeout`. Set to 0 to disable.
|
|
78
|
+
* @returns Promise that resolves with the command result
|
|
79
|
+
* @throws Error if the command times out or fails
|
|
80
|
+
*/
|
|
81
|
+
sendCommand<T extends keyof APICommands>(command: T, require_schema: number | undefined, args: APICommands[T]["requestArgs"], timeout?: number): Promise<APICommands[T]["response"]>;
|
|
82
|
+
/**
|
|
83
|
+
* Safely resolve a pending command, ensuring it's only resolved once.
|
|
84
|
+
* Clears timeout and removes from pending futures before resolving.
|
|
85
|
+
*/
|
|
86
|
+
private _resolvePendingCommand;
|
|
87
|
+
/**
|
|
88
|
+
* Safely reject a pending command, ensuring it's only rejected once.
|
|
89
|
+
* Clears timeout and removes from pending futures before rejecting.
|
|
90
|
+
*/
|
|
91
|
+
private _rejectPendingCommand;
|
|
92
|
+
/**
|
|
93
|
+
* Reject all pending commands with a ConnectionClosedError.
|
|
94
|
+
* Called when the connection is closed or lost.
|
|
95
|
+
*/
|
|
96
|
+
private _rejectAllPendingCommands;
|
|
54
97
|
connect(): Promise<void>;
|
|
55
98
|
disconnect(clearStorage?: boolean): void;
|
|
56
99
|
startListening(): Promise<void>;
|
package/dist/esm/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAE/D,OAAO,EACH,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,sBAAsB,EACtB,uBAAuB,EAEvB,YAAY,EACZ,gBAAgB,EAChB,qBAAqB,EACrB,cAAc,EAEjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAU9C,qBAAa,YAAY;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/client.js
CHANGED
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
import { Connection } from "./connection.js";
|
|
7
|
-
import { InvalidServerVersion } from "./exceptions.js";
|
|
7
|
+
import { CommandTimeoutError, ConnectionClosedError, InvalidServerVersion } from "./exceptions.js";
|
|
8
8
|
import { MatterNode } from "./models/node.js";
|
|
9
9
|
function toNodeKey(nodeId) {
|
|
10
10
|
return String(nodeId);
|
|
11
11
|
}
|
|
12
|
+
const DEFAULT_COMMAND_TIMEOUT = 5 * 60 * 1e3;
|
|
12
13
|
class MatterClient {
|
|
13
14
|
/**
|
|
14
15
|
* Create a new MatterClient.
|
|
@@ -28,9 +29,12 @@ class MatterClient {
|
|
|
28
29
|
serverBaseAddress;
|
|
29
30
|
/** Whether this client is connected to a production server (optional, for UI purposes) */
|
|
30
31
|
isProduction = false;
|
|
32
|
+
/** Default timeout for commands in milliseconds. Set to 0 to disable timeouts. */
|
|
33
|
+
commandTimeout = DEFAULT_COMMAND_TIMEOUT;
|
|
31
34
|
// Using 'unknown' for resolve since the actual types vary by command
|
|
32
35
|
result_futures = {};
|
|
33
|
-
|
|
36
|
+
// Start with random offset for defense-in-depth and easier debugging across sessions
|
|
37
|
+
msgId = Math.floor(Math.random() * 2147483647);
|
|
34
38
|
eventListeners = {};
|
|
35
39
|
get serverInfo() {
|
|
36
40
|
return this.connection.serverInfo;
|
|
@@ -44,131 +48,255 @@ class MatterClient {
|
|
|
44
48
|
this.eventListeners[event] = this.eventListeners[event].filter((l) => l !== listener);
|
|
45
49
|
};
|
|
46
50
|
}
|
|
47
|
-
async commissionWithCode(code, networkOnly = true) {
|
|
48
|
-
return await this.sendCommand(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
await this.sendCommand("set_thread_dataset", 0, { dataset });
|
|
51
|
+
async commissionWithCode(code, networkOnly = true, timeout) {
|
|
52
|
+
return await this.sendCommand(
|
|
53
|
+
"commission_with_code",
|
|
54
|
+
0,
|
|
55
|
+
{
|
|
56
|
+
code,
|
|
57
|
+
network_only: networkOnly
|
|
58
|
+
},
|
|
59
|
+
timeout
|
|
60
|
+
);
|
|
58
61
|
}
|
|
59
|
-
async
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
async setWifiCredentials(ssid, credentials, timeout) {
|
|
63
|
+
await this.sendCommand("set_wifi_credentials", 0, { ssid, credentials }, timeout);
|
|
64
|
+
}
|
|
65
|
+
async setThreadOperationalDataset(dataset, timeout) {
|
|
66
|
+
await this.sendCommand("set_thread_dataset", 0, { dataset }, timeout);
|
|
67
|
+
}
|
|
68
|
+
async openCommissioningWindow(nodeId, windowTimeout, iteration, option, discriminator, timeout) {
|
|
69
|
+
return await this.sendCommand(
|
|
70
|
+
"open_commissioning_window",
|
|
71
|
+
0,
|
|
72
|
+
{
|
|
73
|
+
node_id: nodeId,
|
|
74
|
+
timeout: windowTimeout,
|
|
75
|
+
iteration,
|
|
76
|
+
option,
|
|
77
|
+
discriminator
|
|
78
|
+
},
|
|
79
|
+
timeout
|
|
80
|
+
);
|
|
67
81
|
}
|
|
68
|
-
async discoverCommissionableNodes() {
|
|
69
|
-
return await this.sendCommand("discover_commissionable_nodes", 0, {});
|
|
82
|
+
async discoverCommissionableNodes(timeout) {
|
|
83
|
+
return await this.sendCommand("discover_commissionable_nodes", 0, {}, timeout);
|
|
70
84
|
}
|
|
71
|
-
async getMatterFabrics(nodeId) {
|
|
72
|
-
return await this.sendCommand("get_matter_fabrics", 3, { node_id: nodeId });
|
|
85
|
+
async getMatterFabrics(nodeId, timeout) {
|
|
86
|
+
return await this.sendCommand("get_matter_fabrics", 3, { node_id: nodeId }, timeout);
|
|
73
87
|
}
|
|
74
|
-
async removeMatterFabric(nodeId, fabricIndex) {
|
|
75
|
-
await this.sendCommand("remove_matter_fabric", 3, { node_id: nodeId, fabric_index: fabricIndex });
|
|
88
|
+
async removeMatterFabric(nodeId, fabricIndex, timeout) {
|
|
89
|
+
await this.sendCommand("remove_matter_fabric", 3, { node_id: nodeId, fabric_index: fabricIndex }, timeout);
|
|
76
90
|
}
|
|
77
|
-
async pingNode(nodeId, attempts = 1) {
|
|
78
|
-
return await this.sendCommand("ping_node", 0, { node_id: nodeId, attempts });
|
|
91
|
+
async pingNode(nodeId, attempts = 1, timeout) {
|
|
92
|
+
return await this.sendCommand("ping_node", 0, { node_id: nodeId, attempts }, timeout);
|
|
79
93
|
}
|
|
80
|
-
async getNodeIPAddresses(nodeId, preferCache, scoped) {
|
|
81
|
-
return await this.sendCommand(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
94
|
+
async getNodeIPAddresses(nodeId, preferCache, scoped, timeout) {
|
|
95
|
+
return await this.sendCommand(
|
|
96
|
+
"get_node_ip_addresses",
|
|
97
|
+
8,
|
|
98
|
+
{
|
|
99
|
+
node_id: nodeId,
|
|
100
|
+
prefer_cache: preferCache,
|
|
101
|
+
scoped
|
|
102
|
+
},
|
|
103
|
+
timeout
|
|
104
|
+
);
|
|
86
105
|
}
|
|
87
|
-
async removeNode(nodeId) {
|
|
88
|
-
await this.sendCommand("remove_node", 0, { node_id: nodeId });
|
|
106
|
+
async removeNode(nodeId, timeout) {
|
|
107
|
+
await this.sendCommand("remove_node", 0, { node_id: nodeId }, timeout);
|
|
89
108
|
}
|
|
90
|
-
async interviewNode(nodeId) {
|
|
91
|
-
await this.sendCommand("interview_node", 0, { node_id: nodeId });
|
|
109
|
+
async interviewNode(nodeId, timeout) {
|
|
110
|
+
await this.sendCommand("interview_node", 0, { node_id: nodeId }, timeout);
|
|
92
111
|
}
|
|
93
|
-
async importTestNode(dump) {
|
|
94
|
-
await this.sendCommand("import_test_node", 0, { dump });
|
|
112
|
+
async importTestNode(dump, timeout) {
|
|
113
|
+
await this.sendCommand("import_test_node", 0, { dump }, timeout);
|
|
95
114
|
}
|
|
96
|
-
async readAttribute(nodeId, attributePath) {
|
|
97
|
-
return await this.sendCommand("read_attribute", 0, { node_id: nodeId, attribute_path: attributePath });
|
|
115
|
+
async readAttribute(nodeId, attributePath, timeout) {
|
|
116
|
+
return await this.sendCommand("read_attribute", 0, { node_id: nodeId, attribute_path: attributePath }, timeout);
|
|
98
117
|
}
|
|
99
|
-
async writeAttribute(nodeId, attributePath, value) {
|
|
100
|
-
return await this.sendCommand(
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
118
|
+
async writeAttribute(nodeId, attributePath, value, timeout) {
|
|
119
|
+
return await this.sendCommand(
|
|
120
|
+
"write_attribute",
|
|
121
|
+
0,
|
|
122
|
+
{
|
|
123
|
+
node_id: nodeId,
|
|
124
|
+
attribute_path: attributePath,
|
|
125
|
+
value
|
|
126
|
+
},
|
|
127
|
+
timeout
|
|
128
|
+
);
|
|
105
129
|
}
|
|
106
|
-
async checkNodeUpdate(nodeId) {
|
|
107
|
-
return await this.sendCommand("check_node_update", 10, { node_id: nodeId });
|
|
130
|
+
async checkNodeUpdate(nodeId, timeout) {
|
|
131
|
+
return await this.sendCommand("check_node_update", 10, { node_id: nodeId }, timeout);
|
|
132
|
+
}
|
|
133
|
+
async updateNode(nodeId, softwareVersion, timeout) {
|
|
134
|
+
await this.sendCommand("update_node", 10, { node_id: nodeId, software_version: softwareVersion }, timeout);
|
|
135
|
+
}
|
|
136
|
+
async setACLEntry(nodeId, entry, timeout) {
|
|
137
|
+
return await this.sendCommand(
|
|
138
|
+
"set_acl_entry",
|
|
139
|
+
0,
|
|
140
|
+
{
|
|
141
|
+
node_id: nodeId,
|
|
142
|
+
entry
|
|
143
|
+
},
|
|
144
|
+
timeout
|
|
145
|
+
);
|
|
108
146
|
}
|
|
109
|
-
async
|
|
110
|
-
await this.sendCommand(
|
|
147
|
+
async setNodeBinding(nodeId, endpoint, bindings, timeout) {
|
|
148
|
+
return await this.sendCommand(
|
|
149
|
+
"set_node_binding",
|
|
150
|
+
0,
|
|
151
|
+
{
|
|
152
|
+
node_id: nodeId,
|
|
153
|
+
endpoint,
|
|
154
|
+
bindings
|
|
155
|
+
},
|
|
156
|
+
timeout
|
|
157
|
+
);
|
|
111
158
|
}
|
|
112
|
-
async
|
|
113
|
-
return await this.sendCommand(
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
159
|
+
async deviceCommand(nodeId, endpointId, clusterId, commandName, payload = {}, timeout) {
|
|
160
|
+
return await this.sendCommand(
|
|
161
|
+
"device_command",
|
|
162
|
+
0,
|
|
163
|
+
{
|
|
164
|
+
node_id: nodeId,
|
|
165
|
+
endpoint_id: endpointId,
|
|
166
|
+
cluster_id: clusterId,
|
|
167
|
+
command_name: commandName,
|
|
168
|
+
payload,
|
|
169
|
+
response_type: null
|
|
170
|
+
},
|
|
171
|
+
timeout
|
|
172
|
+
);
|
|
117
173
|
}
|
|
118
|
-
async
|
|
119
|
-
return await this.sendCommand("
|
|
120
|
-
node_id: nodeId,
|
|
121
|
-
endpoint,
|
|
122
|
-
bindings
|
|
123
|
-
});
|
|
174
|
+
async getNodes(onlyAvailable = false, timeout) {
|
|
175
|
+
return await this.sendCommand("get_nodes", 0, { only_available: onlyAvailable }, timeout);
|
|
124
176
|
}
|
|
125
|
-
async
|
|
126
|
-
return await this.sendCommand("
|
|
127
|
-
node_id: nodeId,
|
|
128
|
-
endpoint_id: endpointId,
|
|
129
|
-
cluster_id: clusterId,
|
|
130
|
-
command_name: commandName,
|
|
131
|
-
payload,
|
|
132
|
-
response_type: null
|
|
133
|
-
});
|
|
177
|
+
async getNode(nodeId, timeout) {
|
|
178
|
+
return await this.sendCommand("get_node", 0, { node_id: nodeId }, timeout);
|
|
134
179
|
}
|
|
135
|
-
async
|
|
136
|
-
return await this.sendCommand("
|
|
180
|
+
async getVendorNames(filterVendors, timeout) {
|
|
181
|
+
return await this.sendCommand("get_vendor_names", 0, { filter_vendors: filterVendors }, timeout);
|
|
137
182
|
}
|
|
138
|
-
async
|
|
139
|
-
return await this.sendCommand("
|
|
183
|
+
async fetchServerInfo(timeout) {
|
|
184
|
+
return await this.sendCommand("server_info", 0, {}, timeout);
|
|
140
185
|
}
|
|
141
|
-
async
|
|
142
|
-
|
|
186
|
+
async setDefaultFabricLabel(label, timeout) {
|
|
187
|
+
await this.sendCommand("set_default_fabric_label", 0, { label }, timeout);
|
|
143
188
|
}
|
|
144
|
-
|
|
145
|
-
|
|
189
|
+
/**
|
|
190
|
+
* Get the current log levels for console and file logging.
|
|
191
|
+
* @param timeout Optional command timeout in milliseconds
|
|
192
|
+
* @returns The current log level configuration
|
|
193
|
+
*/
|
|
194
|
+
async getLogLevel(timeout) {
|
|
195
|
+
return await this.sendCommand("get_loglevel", 0, {}, timeout);
|
|
146
196
|
}
|
|
147
|
-
|
|
148
|
-
|
|
197
|
+
/**
|
|
198
|
+
* Set the log level for console and/or file logging.
|
|
199
|
+
* Changes are temporary and will be reset when the server restarts.
|
|
200
|
+
* @param consoleLoglevel Console log level to set (optional)
|
|
201
|
+
* @param fileLoglevel File log level to set, only applied if file logging is enabled (optional)
|
|
202
|
+
* @param timeout Optional command timeout in milliseconds
|
|
203
|
+
* @returns The log level configuration after the change
|
|
204
|
+
*/
|
|
205
|
+
async setLogLevel(consoleLoglevel, fileLoglevel, timeout) {
|
|
206
|
+
return await this.sendCommand(
|
|
207
|
+
"set_loglevel",
|
|
208
|
+
0,
|
|
209
|
+
{
|
|
210
|
+
console_loglevel: consoleLoglevel,
|
|
211
|
+
file_loglevel: fileLoglevel
|
|
212
|
+
},
|
|
213
|
+
timeout
|
|
214
|
+
);
|
|
149
215
|
}
|
|
150
|
-
|
|
216
|
+
/**
|
|
217
|
+
* Send a command to the Matter server.
|
|
218
|
+
* @param command The command name
|
|
219
|
+
* @param require_schema Minimum schema version required (0 for any version)
|
|
220
|
+
* @param args Command arguments
|
|
221
|
+
* @param timeout Optional timeout in milliseconds. Defaults to `commandTimeout`. Set to 0 to disable.
|
|
222
|
+
* @returns Promise that resolves with the command result
|
|
223
|
+
* @throws Error if the command times out or fails
|
|
224
|
+
*/
|
|
225
|
+
sendCommand(command, require_schema = void 0, args, timeout = this.commandTimeout) {
|
|
151
226
|
if (require_schema && this.serverInfo.schema_version < require_schema) {
|
|
152
227
|
throw new InvalidServerVersion(
|
|
153
228
|
`Command not available due to incompatible server version. Update the Matter Server to a version that supports at least api schema ${require_schema}.`
|
|
154
229
|
);
|
|
155
230
|
}
|
|
156
|
-
|
|
231
|
+
if (this.msgId >= Number.MAX_SAFE_INTEGER) {
|
|
232
|
+
this.msgId = 0;
|
|
233
|
+
}
|
|
234
|
+
const messageId = String(++this.msgId);
|
|
157
235
|
const message = {
|
|
158
|
-
message_id: messageId
|
|
236
|
+
message_id: messageId,
|
|
159
237
|
command,
|
|
160
238
|
args
|
|
161
239
|
};
|
|
162
|
-
|
|
240
|
+
return new Promise((resolve, reject) => {
|
|
241
|
+
let timeoutId;
|
|
242
|
+
if (timeout > 0) {
|
|
243
|
+
timeoutId = setTimeout(() => {
|
|
244
|
+
const pending = this.result_futures[messageId];
|
|
245
|
+
if (pending) {
|
|
246
|
+
if (pending.timeoutId) {
|
|
247
|
+
clearTimeout(pending.timeoutId);
|
|
248
|
+
}
|
|
249
|
+
delete this.result_futures[messageId];
|
|
250
|
+
reject(new CommandTimeoutError(command, timeout));
|
|
251
|
+
}
|
|
252
|
+
}, timeout);
|
|
253
|
+
}
|
|
163
254
|
this.result_futures[messageId] = {
|
|
164
255
|
resolve,
|
|
165
|
-
reject
|
|
256
|
+
reject,
|
|
257
|
+
timeoutId
|
|
166
258
|
};
|
|
167
259
|
this.connection.sendMessage(message);
|
|
168
260
|
});
|
|
169
|
-
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Safely resolve a pending command, ensuring it's only resolved once.
|
|
264
|
+
* Clears timeout and removes from pending futures before resolving.
|
|
265
|
+
*/
|
|
266
|
+
_resolvePendingCommand(messageId, result) {
|
|
267
|
+
const pending = this.result_futures[messageId];
|
|
268
|
+
if (pending) {
|
|
269
|
+
if (pending.timeoutId) {
|
|
270
|
+
clearTimeout(pending.timeoutId);
|
|
271
|
+
}
|
|
170
272
|
delete this.result_futures[messageId];
|
|
171
|
-
|
|
273
|
+
pending.resolve(result);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Safely reject a pending command, ensuring it's only rejected once.
|
|
278
|
+
* Clears timeout and removes from pending futures before rejecting.
|
|
279
|
+
*/
|
|
280
|
+
_rejectPendingCommand(messageId, error) {
|
|
281
|
+
const pending = this.result_futures[messageId];
|
|
282
|
+
if (pending) {
|
|
283
|
+
if (pending.timeoutId) {
|
|
284
|
+
clearTimeout(pending.timeoutId);
|
|
285
|
+
}
|
|
286
|
+
delete this.result_futures[messageId];
|
|
287
|
+
pending.reject(error);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Reject all pending commands with a ConnectionClosedError.
|
|
292
|
+
* Called when the connection is closed or lost.
|
|
293
|
+
*/
|
|
294
|
+
_rejectAllPendingCommands() {
|
|
295
|
+
const error = new ConnectionClosedError();
|
|
296
|
+
const pendingIds = Object.keys(this.result_futures);
|
|
297
|
+
for (const messageId of pendingIds) {
|
|
298
|
+
this._rejectPendingCommand(messageId, error);
|
|
299
|
+
}
|
|
172
300
|
}
|
|
173
301
|
async connect() {
|
|
174
302
|
if (this.connection.connected) {
|
|
@@ -176,10 +304,14 @@ class MatterClient {
|
|
|
176
304
|
}
|
|
177
305
|
await this.connection.connect(
|
|
178
306
|
(msg) => this._handleIncomingMessage(msg),
|
|
179
|
-
() =>
|
|
307
|
+
() => {
|
|
308
|
+
this._rejectAllPendingCommands();
|
|
309
|
+
this.fireEvent("connection_lost");
|
|
310
|
+
}
|
|
180
311
|
);
|
|
181
312
|
}
|
|
182
313
|
disconnect(clearStorage = false) {
|
|
314
|
+
this._rejectAllPendingCommands();
|
|
183
315
|
if (this.connection && this.connection.connected) {
|
|
184
316
|
this.connection.disconnect();
|
|
185
317
|
}
|
|
@@ -203,19 +335,11 @@ class MatterClient {
|
|
|
203
335
|
return;
|
|
204
336
|
}
|
|
205
337
|
if ("error_code" in msg) {
|
|
206
|
-
|
|
207
|
-
if (promise) {
|
|
208
|
-
promise.reject(new Error(msg.details));
|
|
209
|
-
delete this.result_futures[msg.message_id];
|
|
210
|
-
}
|
|
338
|
+
this._rejectPendingCommand(msg.message_id, new Error(msg.details));
|
|
211
339
|
return;
|
|
212
340
|
}
|
|
213
341
|
if ("result" in msg) {
|
|
214
|
-
|
|
215
|
-
if (promise) {
|
|
216
|
-
promise.resolve(msg.result);
|
|
217
|
-
delete this.result_futures[msg.message_id];
|
|
218
|
-
}
|
|
342
|
+
this._resolvePendingCommand(msg.message_id, msg.result);
|
|
219
343
|
return;
|
|
220
344
|
}
|
|
221
345
|
console.warn("Received message with unknown format", msg);
|
|
@@ -281,6 +405,7 @@ class MatterClient {
|
|
|
281
405
|
}
|
|
282
406
|
}
|
|
283
407
|
export {
|
|
408
|
+
DEFAULT_COMMAND_TIMEOUT,
|
|
284
409
|
MatterClient
|
|
285
410
|
};
|
|
286
411
|
//# sourceMappingURL=client.js.map
|