@project-chip/matter.js 0.11.0-alpha.0-20240928-08865c2ce → 0.11.0-alpha.0-20241002-e7b377c34
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/cjs/CommissioningController.d.ts +7 -35
- package/dist/cjs/CommissioningController.d.ts.map +1 -1
- package/dist/cjs/CommissioningController.js +2 -1
- package/dist/cjs/CommissioningController.js.map +1 -1
- package/dist/cjs/CommissioningServer.d.ts.map +1 -1
- package/dist/cjs/CommissioningServer.js +2 -2
- package/dist/cjs/CommissioningServer.js.map +1 -1
- package/dist/cjs/MatterController.d.ts +21 -49
- package/dist/cjs/MatterController.d.ts.map +1 -1
- package/dist/cjs/MatterController.js +102 -502
- package/dist/cjs/MatterController.js.map +2 -2
- package/dist/cjs/compat/protocol.d.ts +1 -1
- package/dist/cjs/compat/protocol.d.ts.map +1 -1
- package/dist/cjs/compat/protocol.js +1 -2
- package/dist/cjs/compat/protocol.js.map +1 -1
- package/dist/cjs/device/LegacyInteractionServer.d.ts.map +1 -1
- package/dist/cjs/device/PairedNode.d.ts +1 -2
- package/dist/cjs/device/PairedNode.d.ts.map +1 -1
- package/dist/cjs/device/PairedNode.js +2 -3
- package/dist/cjs/device/PairedNode.js.map +1 -1
- package/dist/esm/CommissioningController.d.ts +7 -35
- package/dist/esm/CommissioningController.d.ts.map +1 -1
- package/dist/esm/CommissioningController.js +2 -1
- package/dist/esm/CommissioningController.js.map +1 -1
- package/dist/esm/CommissioningServer.d.ts.map +1 -1
- package/dist/esm/CommissioningServer.js +2 -2
- package/dist/esm/CommissioningServer.js.map +1 -1
- package/dist/esm/MatterController.d.ts +21 -49
- package/dist/esm/MatterController.d.ts.map +1 -1
- package/dist/esm/MatterController.js +105 -519
- package/dist/esm/MatterController.js.map +2 -2
- package/dist/esm/compat/protocol.d.ts +1 -1
- package/dist/esm/compat/protocol.d.ts.map +1 -1
- package/dist/esm/compat/protocol.js +2 -4
- package/dist/esm/compat/protocol.js.map +1 -1
- package/dist/esm/device/LegacyInteractionServer.d.ts.map +1 -1
- package/dist/esm/device/PairedNode.d.ts +1 -2
- package/dist/esm/device/PairedNode.d.ts.map +1 -1
- package/dist/esm/device/PairedNode.js +1 -1
- package/dist/esm/device/PairedNode.js.map +1 -1
- package/package.json +8 -8
- package/src/CommissioningController.ts +7 -42
- package/src/CommissioningServer.ts +2 -2
- package/src/MatterController.ts +126 -713
- package/src/compat/protocol.ts +2 -3
- package/src/device/PairedNode.ts +1 -1
|
@@ -18,8 +18,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var MatterController_exports = {};
|
|
20
20
|
__export(MatterController_exports, {
|
|
21
|
-
MatterController: () => MatterController
|
|
22
|
-
NodeDiscoveryType: () => NodeDiscoveryType
|
|
21
|
+
MatterController: () => MatterController
|
|
23
22
|
});
|
|
24
23
|
module.exports = __toCommonJS(MatterController_exports);
|
|
25
24
|
var import_clusters = require("#clusters");
|
|
@@ -37,21 +36,12 @@ const TlvCommissioningSuccessFailureResponse = (0, import_types.TlvObject)({
|
|
|
37
36
|
/** Should help developers in troubleshooting errors. The value MAY go into logs or crash reports, not User UIs. */
|
|
38
37
|
debugText: (0, import_types.TlvField)(1, import_types.TlvString.bound({ maxLength: 128 }))
|
|
39
38
|
});
|
|
39
|
+
const DEFAULT_ADMIN_VENDOR_ID = (0, import_types.VendorId)(65521);
|
|
40
40
|
const DEFAULT_FABRIC_INDEX = (0, import_types.FabricIndex)(1);
|
|
41
41
|
const DEFAULT_FABRIC_ID = (0, import_types.FabricId)(1);
|
|
42
|
-
const DEFAULT_ADMIN_VENDOR_ID = (0, import_types.VendorId)(65521);
|
|
43
|
-
const RECONNECTION_POLLING_INTERVAL_MS = 6e5;
|
|
44
|
-
const RETRANSMISSION_DISCOVERY_TIMEOUT_MS = 5e3;
|
|
45
42
|
const CONTROLLER_CONNECTIONS_PER_FABRIC_AND_NODE = 3;
|
|
46
43
|
const CONTROLLER_MAX_PATHS_PER_INVOKE = 10;
|
|
47
44
|
const logger = import_general.Logger.get("MatterController");
|
|
48
|
-
var NodeDiscoveryType = /* @__PURE__ */ ((NodeDiscoveryType2) => {
|
|
49
|
-
NodeDiscoveryType2[NodeDiscoveryType2["None"] = 0] = "None";
|
|
50
|
-
NodeDiscoveryType2[NodeDiscoveryType2["RetransmissionDiscovery"] = 1] = "RetransmissionDiscovery";
|
|
51
|
-
NodeDiscoveryType2[NodeDiscoveryType2["TimedDiscovery"] = 2] = "TimedDiscovery";
|
|
52
|
-
NodeDiscoveryType2[NodeDiscoveryType2["FullDiscovery"] = 3] = "FullDiscovery";
|
|
53
|
-
return NodeDiscoveryType2;
|
|
54
|
-
})(NodeDiscoveryType || {});
|
|
55
45
|
class MatterController {
|
|
56
46
|
static async create(options) {
|
|
57
47
|
const {
|
|
@@ -62,7 +52,7 @@ class MatterController {
|
|
|
62
52
|
scanners,
|
|
63
53
|
netInterfaces,
|
|
64
54
|
sessionClosedCallback,
|
|
65
|
-
adminVendorId
|
|
55
|
+
adminVendorId,
|
|
66
56
|
adminFabricId = (0, import_types.FabricId)(DEFAULT_FABRIC_ID),
|
|
67
57
|
adminFabricIndex = (0, import_types.FabricIndex)(DEFAULT_FABRIC_INDEX),
|
|
68
58
|
caseAuthenticatedTags
|
|
@@ -79,13 +69,12 @@ class MatterController {
|
|
|
79
69
|
netInterfaces,
|
|
80
70
|
certificateManager,
|
|
81
71
|
fabric,
|
|
82
|
-
adminVendorId: fabric.rootVendorId,
|
|
83
72
|
sessionClosedCallback
|
|
84
73
|
});
|
|
85
74
|
} else {
|
|
86
75
|
const rootNodeId = import_types.NodeId.randomOperationalNodeId();
|
|
87
76
|
const ipkValue = import_general.Crypto.getRandomData(import_general.CRYPTO_SYMMETRIC_KEY_LENGTH);
|
|
88
|
-
const fabricBuilder = new import_protocol.FabricBuilder().setRootCert(certificateManager.rootCert).setRootNodeId(rootNodeId).setIdentityProtectionKey(ipkValue).setRootVendorId(adminVendorId);
|
|
77
|
+
const fabricBuilder = new import_protocol.FabricBuilder().setRootCert(certificateManager.rootCert).setRootNodeId(rootNodeId).setIdentityProtectionKey(ipkValue).setRootVendorId(adminVendorId ?? DEFAULT_ADMIN_VENDOR_ID);
|
|
89
78
|
fabricBuilder.setOperationalCert(
|
|
90
79
|
certificateManager.generateNoc(
|
|
91
80
|
fabricBuilder.publicKey,
|
|
@@ -103,7 +92,6 @@ class MatterController {
|
|
|
103
92
|
netInterfaces,
|
|
104
93
|
certificateManager,
|
|
105
94
|
fabric,
|
|
106
|
-
adminVendorId,
|
|
107
95
|
sessionClosedCallback
|
|
108
96
|
});
|
|
109
97
|
}
|
|
@@ -133,7 +121,6 @@ class MatterController {
|
|
|
133
121
|
netInterfaces,
|
|
134
122
|
certificateManager,
|
|
135
123
|
fabric,
|
|
136
|
-
adminVendorId: fabric.rootVendorId,
|
|
137
124
|
sessionClosedCallback
|
|
138
125
|
});
|
|
139
126
|
await controller.construction;
|
|
@@ -143,19 +130,16 @@ class MatterController {
|
|
|
143
130
|
netInterfaces = new import_general.NetInterfaceSet();
|
|
144
131
|
channelManager = new import_protocol.ChannelManager(CONTROLLER_CONNECTIONS_PER_FABRIC_AND_NODE);
|
|
145
132
|
exchangeManager;
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
commissionedNodes = /* @__PURE__ */ new Map();
|
|
133
|
+
peers;
|
|
134
|
+
commissioner;
|
|
149
135
|
#construction;
|
|
150
136
|
sessionStorage;
|
|
151
137
|
fabricStorage;
|
|
152
|
-
|
|
138
|
+
nodesStore;
|
|
153
139
|
scanners;
|
|
154
140
|
certificateManager;
|
|
155
141
|
fabric;
|
|
156
|
-
adminVendorId;
|
|
157
142
|
sessionClosedCallback;
|
|
158
|
-
#runningNodeDiscoveries = /* @__PURE__ */ new Map();
|
|
159
143
|
get construction() {
|
|
160
144
|
return this.#construction;
|
|
161
145
|
}
|
|
@@ -168,18 +152,15 @@ class MatterController {
|
|
|
168
152
|
netInterfaces,
|
|
169
153
|
certificateManager,
|
|
170
154
|
fabric,
|
|
171
|
-
sessionClosedCallback
|
|
172
|
-
adminVendorId
|
|
155
|
+
sessionClosedCallback
|
|
173
156
|
} = options;
|
|
174
157
|
this.sessionStorage = sessionStorage;
|
|
175
158
|
this.fabricStorage = fabricStorage;
|
|
176
|
-
this.nodesStorage = nodesStorage;
|
|
177
159
|
this.scanners = scanners;
|
|
178
160
|
this.netInterfaces = netInterfaces;
|
|
179
161
|
this.certificateManager = certificateManager;
|
|
180
162
|
this.fabric = fabric;
|
|
181
163
|
this.sessionClosedCallback = sessionClosedCallback;
|
|
182
|
-
this.adminVendorId = adminVendorId;
|
|
183
164
|
const fabricManager = new import_protocol.FabricManager();
|
|
184
165
|
fabricManager.addFabric(fabric);
|
|
185
166
|
this.sessionManager = new import_protocol.SessionManager({
|
|
@@ -189,26 +170,34 @@ class MatterController {
|
|
|
189
170
|
maxPathsPerInvoke: CONTROLLER_MAX_PATHS_PER_INVOKE
|
|
190
171
|
}
|
|
191
172
|
});
|
|
192
|
-
this.paseClient = new import_protocol.PaseClient(this.sessionManager);
|
|
193
|
-
this.caseClient = new import_protocol.CaseClient(this.sessionManager);
|
|
194
173
|
this.sessionManager.sessions.deleted.on(async (session) => {
|
|
195
174
|
this.sessionClosedCallback?.(session.peerNodeId);
|
|
196
175
|
});
|
|
197
|
-
this.sessionManager.resubmissionStarted.on(this.#handleResubmissionStarted.bind(this));
|
|
198
176
|
this.exchangeManager = new import_protocol.ExchangeManager({
|
|
199
177
|
sessionManager: this.sessionManager,
|
|
200
178
|
channelManager: this.channelManager,
|
|
201
179
|
transportInterfaces: this.netInterfaces
|
|
202
180
|
});
|
|
203
181
|
this.exchangeManager.addProtocolHandler(new import_protocol.StatusReportOnlySecureChannelProtocol());
|
|
182
|
+
this.nodesStore = new CommissionedNodeStore(nodesStorage, fabric);
|
|
183
|
+
this.nodesStore.peers = this.peers = new import_protocol.PeerSet({
|
|
184
|
+
sessions: this.sessionManager,
|
|
185
|
+
channels: this.channelManager,
|
|
186
|
+
exchanges: this.exchangeManager,
|
|
187
|
+
scanners: this.scanners,
|
|
188
|
+
netInterfaces: this.netInterfaces,
|
|
189
|
+
store: this.nodesStore
|
|
190
|
+
});
|
|
191
|
+
this.commissioner = new import_protocol.ControllerCommissioner({
|
|
192
|
+
peers: this.peers,
|
|
193
|
+
scanners: this.scanners,
|
|
194
|
+
netInterfaces: this.netInterfaces,
|
|
195
|
+
exchanges: this.exchangeManager,
|
|
196
|
+
sessions: this.sessionManager,
|
|
197
|
+
certificates: this.certificateManager
|
|
198
|
+
});
|
|
204
199
|
this.#construction = (0, import_general.Construction)(this, async () => {
|
|
205
|
-
|
|
206
|
-
const commissionedNodes = await this.nodesStorage.get("commissionedNodes");
|
|
207
|
-
this.commissionedNodes.clear();
|
|
208
|
-
for (const [nodeId, details] of commissionedNodes) {
|
|
209
|
-
this.commissionedNodes.set(nodeId, details);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
200
|
+
await this.peers.construction.ready;
|
|
212
201
|
await this.sessionManager.construction.ready;
|
|
213
202
|
});
|
|
214
203
|
}
|
|
@@ -241,191 +230,36 @@ class MatterController {
|
|
|
241
230
|
* Return true when the commissioning process is completed successfully, false on error.
|
|
242
231
|
*/
|
|
243
232
|
async commission(options, completeCommissioningCallback) {
|
|
244
|
-
const {
|
|
245
|
-
commissioning
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
discovery: { discoveryCapabilities = {}, knownAddress }
|
|
256
|
-
} = options;
|
|
257
|
-
let identifierData = "identifierData" in options.discovery ? options.discovery.identifierData : {};
|
|
258
|
-
if (this.scanners.hasScannerFor(import_general.ChannelType.UDP) && this.netInterfaces.hasInterfaceFor(import_general.ChannelType.UDP, "::") !== void 0) {
|
|
259
|
-
discoveryCapabilities.onIpNetwork = true;
|
|
260
|
-
}
|
|
261
|
-
if (commissionableDevice !== void 0) {
|
|
262
|
-
let { addresses } = commissionableDevice;
|
|
263
|
-
if (discoveryCapabilities.ble === true) {
|
|
264
|
-
discoveryCapabilities = { onIpNetwork: true, ble: addresses.some((address) => address.type === "ble") };
|
|
265
|
-
} else if (discoveryCapabilities.onIpNetwork === true) {
|
|
266
|
-
addresses = addresses.filter((address) => address.type !== "ble");
|
|
267
|
-
}
|
|
268
|
-
addresses.sort((a) => a.type === "udp" ? -1 : 1);
|
|
269
|
-
knownAddress = addresses[0];
|
|
270
|
-
if ("instanceId" in commissionableDevice && commissionableDevice.instanceId !== void 0) {
|
|
271
|
-
identifierData = { instanceId: commissionableDevice.instanceId };
|
|
272
|
-
} else {
|
|
273
|
-
identifierData = { longDiscriminator: commissionableDevice.D };
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
const scannersToUse = this.collectScanners(discoveryCapabilities);
|
|
277
|
-
logger.info(
|
|
278
|
-
`Commissioning device with identifier ${import_general.Logger.toJSON(identifierData)} and ${scannersToUse.length} scanners and knownAddress ${import_general.Logger.toJSON(knownAddress)}`
|
|
279
|
-
);
|
|
280
|
-
let paseSecureChannel;
|
|
281
|
-
let discoveryData;
|
|
282
|
-
if (knownAddress !== void 0) {
|
|
283
|
-
try {
|
|
284
|
-
paseSecureChannel = await this.initializePaseSecureChannel(knownAddress, passcode);
|
|
285
|
-
} catch (error) {
|
|
286
|
-
import_general.NoResponseTimeoutError.accept(error);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
if (paseSecureChannel === void 0) {
|
|
290
|
-
const discoveredDevices = await import_protocol.ControllerDiscovery.discoverDeviceAddressesByIdentifier(
|
|
291
|
-
scannersToUse,
|
|
292
|
-
identifierData,
|
|
293
|
-
timeoutSeconds
|
|
294
|
-
);
|
|
295
|
-
const { result } = await import_protocol.ControllerDiscovery.iterateServerAddresses(
|
|
296
|
-
discoveredDevices,
|
|
297
|
-
import_general.NoResponseTimeoutError,
|
|
298
|
-
async () => scannersToUse.flatMap((scanner) => scanner.getDiscoveredCommissionableDevices(identifierData)),
|
|
299
|
-
async (address, device) => {
|
|
300
|
-
const channel = await this.initializePaseSecureChannel(address, passcode, device);
|
|
301
|
-
discoveryData = device;
|
|
302
|
-
return channel;
|
|
233
|
+
const commissioningOptions = {
|
|
234
|
+
...options.commissioning,
|
|
235
|
+
fabric: this.fabric,
|
|
236
|
+
discovery: options.discovery,
|
|
237
|
+
passcode: options.passcode
|
|
238
|
+
};
|
|
239
|
+
if (completeCommissioningCallback) {
|
|
240
|
+
commissioningOptions.performCaseCommissioning = async (peerAddress, discoveryData) => {
|
|
241
|
+
const result = await completeCommissioningCallback(peerAddress.nodeId, discoveryData);
|
|
242
|
+
if (!result) {
|
|
243
|
+
throw new import_protocol.RetransmissionLimitReachedError("Device could not be discovered");
|
|
303
244
|
}
|
|
304
|
-
|
|
305
|
-
paseSecureChannel = result;
|
|
245
|
+
};
|
|
306
246
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
discoveryData,
|
|
311
|
-
completeCommissioningCallback
|
|
312
|
-
);
|
|
247
|
+
const address = await this.commissioner.commission(commissioningOptions);
|
|
248
|
+
await this.fabricStorage?.set("fabric", this.fabric.toStorageObject());
|
|
249
|
+
return address.nodeId;
|
|
313
250
|
}
|
|
314
251
|
async disconnect(nodeId) {
|
|
315
|
-
|
|
316
|
-
await this.channelManager.removeAllNodeChannels(this.fabric, nodeId);
|
|
252
|
+
return this.peers.disconnect(this.fabric.addressOf(nodeId));
|
|
317
253
|
}
|
|
318
254
|
async removeNode(nodeId) {
|
|
319
|
-
|
|
320
|
-
await this.sessionManager.removeAllSessionsForNode(nodeId);
|
|
321
|
-
await this.sessionManager.removeResumptionRecord(nodeId);
|
|
322
|
-
await this.channelManager.removeAllNodeChannels(this.fabric, nodeId);
|
|
323
|
-
this.commissionedNodes.delete(nodeId);
|
|
324
|
-
await this.storeCommissionedNodes();
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* Method to start commission process with a PASE pairing.
|
|
328
|
-
* If this not successful and throws an RetransmissionLimitReachedError the address is invalid or the passcode
|
|
329
|
-
* is wrong.
|
|
330
|
-
*/
|
|
331
|
-
async initializePaseSecureChannel(address, passcode, device) {
|
|
332
|
-
let paseChannel;
|
|
333
|
-
if (device !== void 0) {
|
|
334
|
-
logger.info(`Commissioning device`, import_protocol.MdnsScanner.discoveryDataDiagnostics(device));
|
|
335
|
-
}
|
|
336
|
-
if (address.type === "udp") {
|
|
337
|
-
const { ip } = address;
|
|
338
|
-
const isIpv6Address = (0, import_general.isIPv6)(ip);
|
|
339
|
-
const paseInterface = this.netInterfaces.interfaceFor(import_general.ChannelType.UDP, isIpv6Address ? "::" : "0.0.0.0");
|
|
340
|
-
if (paseInterface === void 0) {
|
|
341
|
-
throw new import_protocol.PairRetransmissionLimitReachedError(
|
|
342
|
-
`IPv${isIpv6Address ? "6" : "4"} interface not initialized. Cannot use ${ip} for commissioning.`
|
|
343
|
-
);
|
|
344
|
-
}
|
|
345
|
-
paseChannel = await paseInterface.openChannel(address);
|
|
346
|
-
} else {
|
|
347
|
-
const ble = this.netInterfaces.interfaceFor(import_general.ChannelType.BLE);
|
|
348
|
-
if (!ble) {
|
|
349
|
-
throw new import_protocol.PairRetransmissionLimitReachedError(
|
|
350
|
-
`BLE interface not initialized. Cannot use ${address.peripheralAddress} for commissioning.`
|
|
351
|
-
);
|
|
352
|
-
}
|
|
353
|
-
paseChannel = await ble.openChannel(address);
|
|
354
|
-
}
|
|
355
|
-
const unsecureSession = this.sessionManager.createInsecureSession({
|
|
356
|
-
// Use the session parameters from MDNS announcements when available and rest is assumed to be fallbacks
|
|
357
|
-
sessionParameters: {
|
|
358
|
-
idleIntervalMs: device?.SII,
|
|
359
|
-
activeIntervalMs: device?.SAI,
|
|
360
|
-
activeThresholdMs: device?.SAT
|
|
361
|
-
},
|
|
362
|
-
isInitiator: true
|
|
363
|
-
});
|
|
364
|
-
const paseUnsecureMessageChannel = new import_protocol.MessageChannel(paseChannel, unsecureSession);
|
|
365
|
-
const paseExchange = this.exchangeManager.initiateExchangeWithChannel(
|
|
366
|
-
paseUnsecureMessageChannel,
|
|
367
|
-
import_types.SECURE_CHANNEL_PROTOCOL_ID
|
|
368
|
-
);
|
|
369
|
-
let paseSecureSession;
|
|
370
|
-
try {
|
|
371
|
-
paseSecureSession = await this.paseClient.pair(
|
|
372
|
-
this.sessionManager.sessionParameters,
|
|
373
|
-
paseExchange,
|
|
374
|
-
passcode
|
|
375
|
-
);
|
|
376
|
-
} catch (e) {
|
|
377
|
-
await paseExchange.close();
|
|
378
|
-
throw e;
|
|
379
|
-
}
|
|
380
|
-
await unsecureSession.destroy();
|
|
381
|
-
return new import_protocol.MessageChannel(paseChannel, paseSecureSession);
|
|
382
|
-
}
|
|
383
|
-
/**
|
|
384
|
-
* Method to commission a device with a PASE secure channel. It returns the NodeId of the commissioned device on
|
|
385
|
-
* success.
|
|
386
|
-
*/
|
|
387
|
-
async commissionDevice(paseSecureMessageChannel, commissioningOptions, discoveryData, completeCommissioningCallback) {
|
|
388
|
-
const peerNodeId = commissioningOptions.nodeId ?? import_types.NodeId.randomOperationalNodeId();
|
|
389
|
-
const commissioningManager = new import_protocol.ControllerCommissioner(
|
|
390
|
-
// Use the created secure session to do the commissioning
|
|
391
|
-
new import_protocol.InteractionClient(new import_protocol.ExchangeProvider(this.exchangeManager, paseSecureMessageChannel), peerNodeId),
|
|
392
|
-
this.certificateManager,
|
|
393
|
-
this.fabric,
|
|
394
|
-
commissioningOptions,
|
|
395
|
-
peerNodeId,
|
|
396
|
-
this.adminVendorId,
|
|
397
|
-
async () => {
|
|
398
|
-
await paseSecureMessageChannel.close();
|
|
399
|
-
if (completeCommissioningCallback !== void 0) {
|
|
400
|
-
if (!await completeCommissioningCallback(peerNodeId, discoveryData)) {
|
|
401
|
-
throw new import_protocol.RetransmissionLimitReachedError("Device could not be discovered");
|
|
402
|
-
}
|
|
403
|
-
throw new import_protocol.CommissioningSuccessfullyFinished();
|
|
404
|
-
}
|
|
405
|
-
return await this.connect(peerNodeId, {
|
|
406
|
-
discoveryType: 2 /* TimedDiscovery */,
|
|
407
|
-
timeoutSeconds: 120,
|
|
408
|
-
discoveryData
|
|
409
|
-
});
|
|
410
|
-
}
|
|
411
|
-
);
|
|
412
|
-
try {
|
|
413
|
-
await commissioningManager.executeCommissioning();
|
|
414
|
-
} catch (error) {
|
|
415
|
-
if (this.commissionedNodes.has(peerNodeId)) {
|
|
416
|
-
this.commissionedNodes.delete(peerNodeId);
|
|
417
|
-
}
|
|
418
|
-
throw error;
|
|
419
|
-
}
|
|
420
|
-
await this.fabricStorage?.set("fabric", this.fabric.toStorageObject());
|
|
421
|
-
return peerNodeId;
|
|
255
|
+
return this.peers.delete(this.fabric.addressOf(nodeId));
|
|
422
256
|
}
|
|
423
257
|
/**
|
|
424
258
|
* Method to complete the commissioning process to a node which was initialized with a PASE secure channel.
|
|
425
259
|
*/
|
|
426
260
|
async completeCommissioning(peerNodeId, discoveryData) {
|
|
427
261
|
const interactionClient = await this.connect(peerNodeId, {
|
|
428
|
-
discoveryType:
|
|
262
|
+
discoveryType: import_protocol.NodeDiscoveryType.TimedDiscovery,
|
|
429
263
|
timeoutSeconds: 120,
|
|
430
264
|
discoveryData
|
|
431
265
|
});
|
|
@@ -438,318 +272,44 @@ class MatterController {
|
|
|
438
272
|
useExtendedFailSafeMessageResponseTimeout: true
|
|
439
273
|
});
|
|
440
274
|
if (errorCode !== import_clusters.GeneralCommissioning.CommissioningError.Ok) {
|
|
441
|
-
|
|
442
|
-
this.commissionedNodes.delete(peerNodeId);
|
|
443
|
-
}
|
|
275
|
+
await this.peers.delete(this.fabric.addressOf(peerNodeId));
|
|
444
276
|
throw new import_protocol.CommissioningError(`Commission error on commissioningComplete: ${errorCode}, ${debugText}`);
|
|
445
277
|
}
|
|
446
278
|
await this.fabricStorage?.set("fabric", this.fabric.toStorageObject());
|
|
447
279
|
}
|
|
448
|
-
#handleResubmissionStarted(peerNodeId) {
|
|
449
|
-
if (peerNodeId === void 0) {
|
|
450
|
-
return;
|
|
451
|
-
}
|
|
452
|
-
if (this.#runningNodeDiscoveries.has(peerNodeId)) {
|
|
453
|
-
return;
|
|
454
|
-
}
|
|
455
|
-
this.#runningNodeDiscoveries.set(peerNodeId, { type: 1 /* RetransmissionDiscovery */ });
|
|
456
|
-
this.scanners.scannerFor(import_general.ChannelType.UDP)?.findOperationalDevice(this.fabric, peerNodeId, RETRANSMISSION_DISCOVERY_TIMEOUT_MS, true).catch((error) => {
|
|
457
|
-
logger.error(`Failed to discover device ${peerNodeId} after resubmission started.`, error);
|
|
458
|
-
}).finally(() => {
|
|
459
|
-
if (this.#runningNodeDiscoveries.get(peerNodeId)?.type === 1 /* RetransmissionDiscovery */) {
|
|
460
|
-
this.#runningNodeDiscoveries.delete(peerNodeId);
|
|
461
|
-
}
|
|
462
|
-
});
|
|
463
|
-
}
|
|
464
|
-
async reconnectKnownAddress(peerNodeId, operationalAddress, discoveryData, expectedProcessingTimeMs) {
|
|
465
|
-
const { ip, port } = operationalAddress;
|
|
466
|
-
try {
|
|
467
|
-
logger.debug(
|
|
468
|
-
`Resume device connection to configured server at ${ip}:${port}${expectedProcessingTimeMs !== void 0 ? ` with expected processing time of ${expectedProcessingTimeMs}ms` : ""} ...`
|
|
469
|
-
);
|
|
470
|
-
const channel = await this.pair(peerNodeId, operationalAddress, discoveryData, expectedProcessingTimeMs);
|
|
471
|
-
await this.setOperationalDeviceData(peerNodeId, operationalAddress);
|
|
472
|
-
return channel;
|
|
473
|
-
} catch (error) {
|
|
474
|
-
if (error instanceof import_general.NoResponseTimeoutError) {
|
|
475
|
-
logger.debug(
|
|
476
|
-
`Failed to resume connection to node ${peerNodeId} connection with ${ip}:${port}, discover the device ...`,
|
|
477
|
-
error
|
|
478
|
-
);
|
|
479
|
-
await this.sessionManager.removeAllSessionsForNode(peerNodeId);
|
|
480
|
-
return void 0;
|
|
481
|
-
} else {
|
|
482
|
-
throw error;
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
async connectOrDiscoverNode(peerNodeId, operationalAddress, discoveryOptions = {}) {
|
|
487
|
-
const {
|
|
488
|
-
discoveryType: requestedDiscoveryType = 3 /* FullDiscovery */,
|
|
489
|
-
timeoutSeconds,
|
|
490
|
-
discoveryData = this.commissionedNodes.get(peerNodeId)?.discoveryData
|
|
491
|
-
} = discoveryOptions;
|
|
492
|
-
if (timeoutSeconds !== void 0 && requestedDiscoveryType !== 2 /* TimedDiscovery */) {
|
|
493
|
-
throw new import_general.ImplementationError("Cannot set timeout without timed discovery.");
|
|
494
|
-
}
|
|
495
|
-
if (requestedDiscoveryType === 1 /* RetransmissionDiscovery */) {
|
|
496
|
-
throw new import_general.ImplementationError("Cannot set retransmission discovery type.");
|
|
497
|
-
}
|
|
498
|
-
const mdnsScanner = this.scanners.scannerFor(import_general.ChannelType.UDP);
|
|
499
|
-
if (!mdnsScanner) {
|
|
500
|
-
throw new import_general.ImplementationError("Cannot discover device without mDNS scanner.");
|
|
501
|
-
}
|
|
502
|
-
const existingDiscoveryDetails = this.#runningNodeDiscoveries.get(peerNodeId) ?? {
|
|
503
|
-
type: 0 /* None */
|
|
504
|
-
};
|
|
505
|
-
if (existingDiscoveryDetails.type !== 0 /* None */ && existingDiscoveryDetails.type < requestedDiscoveryType) {
|
|
506
|
-
mdnsScanner.cancelOperationalDeviceDiscovery(this.fabric, peerNodeId);
|
|
507
|
-
this.#runningNodeDiscoveries.delete(peerNodeId);
|
|
508
|
-
existingDiscoveryDetails.type = 0 /* None */;
|
|
509
|
-
}
|
|
510
|
-
const { type: runningDiscoveryType, promises } = existingDiscoveryDetails;
|
|
511
|
-
if (operationalAddress !== void 0 && (runningDiscoveryType === 0 /* None */ || requestedDiscoveryType === 0 /* None */)) {
|
|
512
|
-
const directReconnection = await this.reconnectKnownAddress(peerNodeId, operationalAddress, discoveryData);
|
|
513
|
-
if (directReconnection !== void 0) {
|
|
514
|
-
return directReconnection;
|
|
515
|
-
}
|
|
516
|
-
if (requestedDiscoveryType === 0 /* None */) {
|
|
517
|
-
throw new import_protocol.DiscoveryError(`Node ${peerNodeId} is not reachable right now.`);
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
if (promises !== void 0) {
|
|
521
|
-
if (runningDiscoveryType > requestedDiscoveryType) {
|
|
522
|
-
throw new import_protocol.DiscoveryError(
|
|
523
|
-
`Node ${peerNodeId} is not reachable right now and discovery already running.`
|
|
524
|
-
);
|
|
525
|
-
} else {
|
|
526
|
-
return await (0, import_general.anyPromise)(promises);
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
const discoveryPromises = new Array();
|
|
530
|
-
let reconnectionPollingTimer;
|
|
531
|
-
if (operationalAddress !== void 0) {
|
|
532
|
-
if (requestedDiscoveryType === 3 /* FullDiscovery */) {
|
|
533
|
-
const { promise, resolver, rejecter } = (0, import_general.createPromise)();
|
|
534
|
-
reconnectionPollingTimer = import_general.Time.getPeriodicTimer(
|
|
535
|
-
"Controller reconnect",
|
|
536
|
-
RECONNECTION_POLLING_INTERVAL_MS,
|
|
537
|
-
async () => {
|
|
538
|
-
try {
|
|
539
|
-
logger.debug(`Polling for device at ${(0, import_general.serverAddressToString)(operationalAddress)} ...`);
|
|
540
|
-
const result = await this.reconnectKnownAddress(
|
|
541
|
-
peerNodeId,
|
|
542
|
-
operationalAddress,
|
|
543
|
-
discoveryData
|
|
544
|
-
);
|
|
545
|
-
if (result !== void 0 && reconnectionPollingTimer?.isRunning) {
|
|
546
|
-
reconnectionPollingTimer?.stop();
|
|
547
|
-
mdnsScanner.cancelOperationalDeviceDiscovery(this.fabric, peerNodeId);
|
|
548
|
-
this.#runningNodeDiscoveries.delete(peerNodeId);
|
|
549
|
-
resolver(result);
|
|
550
|
-
}
|
|
551
|
-
} catch (error) {
|
|
552
|
-
if (reconnectionPollingTimer?.isRunning) {
|
|
553
|
-
reconnectionPollingTimer?.stop();
|
|
554
|
-
mdnsScanner.cancelOperationalDeviceDiscovery(this.fabric, peerNodeId);
|
|
555
|
-
this.#runningNodeDiscoveries.delete(peerNodeId);
|
|
556
|
-
rejecter(error);
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
).start();
|
|
561
|
-
discoveryPromises.push(() => promise);
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
discoveryPromises.push(async () => {
|
|
565
|
-
const scanResult = await import_protocol.ControllerDiscovery.discoverOperationalDevice(
|
|
566
|
-
this.fabric,
|
|
567
|
-
peerNodeId,
|
|
568
|
-
mdnsScanner,
|
|
569
|
-
timeoutSeconds,
|
|
570
|
-
timeoutSeconds === void 0
|
|
571
|
-
);
|
|
572
|
-
const { timer } = this.#runningNodeDiscoveries.get(peerNodeId) ?? {};
|
|
573
|
-
timer?.stop();
|
|
574
|
-
this.#runningNodeDiscoveries.delete(peerNodeId);
|
|
575
|
-
const { result } = await import_protocol.ControllerDiscovery.iterateServerAddresses(
|
|
576
|
-
[scanResult],
|
|
577
|
-
import_general.NoResponseTimeoutError,
|
|
578
|
-
async () => {
|
|
579
|
-
const device = mdnsScanner.getDiscoveredOperationalDevice(this.fabric, peerNodeId);
|
|
580
|
-
return device !== void 0 ? [device] : [];
|
|
581
|
-
},
|
|
582
|
-
async (address, device) => {
|
|
583
|
-
const result2 = await this.pair(peerNodeId, address, device);
|
|
584
|
-
await this.setOperationalDeviceData(peerNodeId, address, {
|
|
585
|
-
...discoveryData,
|
|
586
|
-
...device
|
|
587
|
-
});
|
|
588
|
-
return result2;
|
|
589
|
-
}
|
|
590
|
-
);
|
|
591
|
-
return result;
|
|
592
|
-
});
|
|
593
|
-
this.#runningNodeDiscoveries.set(peerNodeId, {
|
|
594
|
-
type: requestedDiscoveryType,
|
|
595
|
-
promises: discoveryPromises,
|
|
596
|
-
timer: reconnectionPollingTimer
|
|
597
|
-
});
|
|
598
|
-
return await (0, import_general.anyPromise)(discoveryPromises).finally(() => this.#runningNodeDiscoveries.delete(peerNodeId));
|
|
599
|
-
}
|
|
600
|
-
/**
|
|
601
|
-
* Resume a device connection and establish a CASE session that was previously paired with the controller. This
|
|
602
|
-
* method will try to connect to the device using the previously used server address (if set). If that fails, the
|
|
603
|
-
* device is discovered again using its operational instance details.
|
|
604
|
-
* It returns the operational MessageChannel on success.
|
|
605
|
-
*/
|
|
606
|
-
async resume(peerNodeId, discoveryOptions) {
|
|
607
|
-
const operationalAddress = this.getLastOperationalAddress(peerNodeId);
|
|
608
|
-
try {
|
|
609
|
-
return await this.connectOrDiscoverNode(peerNodeId, operationalAddress, discoveryOptions);
|
|
610
|
-
} catch (error) {
|
|
611
|
-
if ((error instanceof import_protocol.DiscoveryError || error instanceof import_general.NoResponseTimeoutError) && this.commissionedNodes.has(peerNodeId)) {
|
|
612
|
-
logger.info(`Resume failed, remove all sessions for node ${peerNodeId}`);
|
|
613
|
-
await this.sessionManager.removeAllSessionsForNode(peerNodeId);
|
|
614
|
-
}
|
|
615
|
-
throw error;
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
/** Pair with an operational device (already commissioned) and establish a CASE session. */
|
|
619
|
-
async pair(peerNodeId, operationalServerAddress, discoveryData, expectedProcessingTimeMs) {
|
|
620
|
-
const { ip, port } = operationalServerAddress;
|
|
621
|
-
const isIpv6Address = (0, import_general.isIPv6)(ip);
|
|
622
|
-
const operationalInterface = this.netInterfaces.interfaceFor(import_general.ChannelType.UDP, isIpv6Address ? "::" : "0.0.0.0");
|
|
623
|
-
if (operationalInterface === void 0) {
|
|
624
|
-
throw new import_protocol.PairRetransmissionLimitReachedError(
|
|
625
|
-
`IPv${isIpv6Address ? "6" : "4"} interface not initialized for port ${port}. Cannot use ${ip} for pairing.`
|
|
626
|
-
);
|
|
627
|
-
}
|
|
628
|
-
const operationalChannel = await operationalInterface.openChannel(operationalServerAddress);
|
|
629
|
-
const { sessionParameters } = this.findResumptionRecordByNodeId(peerNodeId) ?? {};
|
|
630
|
-
const unsecureSession = this.sessionManager.createInsecureSession({
|
|
631
|
-
// Use the session parameters from MDNS announcements when available and rest is assumed to be fallbacks
|
|
632
|
-
sessionParameters: {
|
|
633
|
-
idleIntervalMs: discoveryData?.SII ?? sessionParameters?.idleIntervalMs,
|
|
634
|
-
activeIntervalMs: discoveryData?.SAI ?? sessionParameters?.activeIntervalMs,
|
|
635
|
-
activeThresholdMs: discoveryData?.SAT ?? sessionParameters?.activeThresholdMs
|
|
636
|
-
},
|
|
637
|
-
isInitiator: true
|
|
638
|
-
});
|
|
639
|
-
const operationalUnsecureMessageExchange = new import_protocol.MessageChannel(operationalChannel, unsecureSession);
|
|
640
|
-
let operationalSecureSession;
|
|
641
|
-
try {
|
|
642
|
-
const exchange = this.exchangeManager.initiateExchangeWithChannel(
|
|
643
|
-
operationalUnsecureMessageExchange,
|
|
644
|
-
import_types.SECURE_CHANNEL_PROTOCOL_ID
|
|
645
|
-
);
|
|
646
|
-
try {
|
|
647
|
-
operationalSecureSession = await this.caseClient.pair(
|
|
648
|
-
exchange,
|
|
649
|
-
this.fabric,
|
|
650
|
-
peerNodeId,
|
|
651
|
-
expectedProcessingTimeMs
|
|
652
|
-
);
|
|
653
|
-
} catch (e) {
|
|
654
|
-
await exchange.close();
|
|
655
|
-
throw e;
|
|
656
|
-
}
|
|
657
|
-
} catch (e) {
|
|
658
|
-
import_general.NoResponseTimeoutError.accept(e);
|
|
659
|
-
throw new import_protocol.PairRetransmissionLimitReachedError(e.message);
|
|
660
|
-
}
|
|
661
|
-
await unsecureSession.destroy();
|
|
662
|
-
const channel = new import_protocol.MessageChannel(operationalChannel, operationalSecureSession);
|
|
663
|
-
await this.channelManager.setChannel(this.fabric, peerNodeId, channel);
|
|
664
|
-
return channel;
|
|
665
|
-
}
|
|
666
280
|
isCommissioned() {
|
|
667
|
-
return this.
|
|
281
|
+
return this.peers.size > 0;
|
|
668
282
|
}
|
|
669
283
|
getCommissionedNodes() {
|
|
670
|
-
return
|
|
284
|
+
return this.peers.map((peer) => peer.address.nodeId);
|
|
671
285
|
}
|
|
672
286
|
getCommissionedNodesDetails() {
|
|
673
|
-
return
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
287
|
+
return this.peers.map((peer) => {
|
|
288
|
+
const { address, operationalAddress, discoveryData, basicInformationData } = peer;
|
|
289
|
+
return {
|
|
290
|
+
nodeId: address.nodeId,
|
|
291
|
+
operationalAddress: operationalAddress ? (0, import_general.serverAddressToString)(operationalAddress) : void 0,
|
|
677
292
|
advertisedName: discoveryData?.DN,
|
|
678
293
|
discoveryData,
|
|
679
294
|
basicInformationData
|
|
680
|
-
})
|
|
681
|
-
);
|
|
682
|
-
}
|
|
683
|
-
async setOperationalDeviceData(nodeId, operationalServerAddress, discoveryData) {
|
|
684
|
-
const nodeDetails = this.commissionedNodes.get(nodeId) ?? {};
|
|
685
|
-
nodeDetails.operationalServerAddress = operationalServerAddress;
|
|
686
|
-
if (discoveryData !== void 0) {
|
|
687
|
-
nodeDetails.discoveryData = {
|
|
688
|
-
...nodeDetails.discoveryData,
|
|
689
|
-
...discoveryData
|
|
690
295
|
};
|
|
691
|
-
}
|
|
692
|
-
this.commissionedNodes.set(nodeId, nodeDetails);
|
|
693
|
-
await this.storeCommissionedNodes();
|
|
296
|
+
});
|
|
694
297
|
}
|
|
695
298
|
async enhanceCommissionedNodeDetails(nodeId, data) {
|
|
696
|
-
const nodeDetails = this.
|
|
299
|
+
const nodeDetails = this.peers.get(this.fabric.addressOf(nodeId));
|
|
697
300
|
if (nodeDetails === void 0) {
|
|
698
301
|
throw new Error(`Node ${nodeId} is not commissioned.`);
|
|
699
302
|
}
|
|
700
303
|
const { basicInformationData } = data;
|
|
701
304
|
nodeDetails.basicInformationData = basicInformationData;
|
|
702
|
-
this.
|
|
703
|
-
await this.storeCommissionedNodes();
|
|
704
|
-
}
|
|
705
|
-
getLastOperationalAddress(nodeId) {
|
|
706
|
-
return this.commissionedNodes.get(nodeId)?.operationalServerAddress;
|
|
707
|
-
}
|
|
708
|
-
async storeCommissionedNodes() {
|
|
709
|
-
await this.nodesStorage.set("commissionedNodes", Array.from(this.commissionedNodes.entries()));
|
|
305
|
+
await this.nodesStore.save();
|
|
710
306
|
}
|
|
711
307
|
/**
|
|
712
308
|
* Connect to the device by opening a channel and creating a new CASE session if necessary.
|
|
713
309
|
* Returns a InteractionClient on success.
|
|
714
310
|
*/
|
|
715
311
|
async connect(peerNodeId, discoveryOptions) {
|
|
716
|
-
|
|
717
|
-
let channel;
|
|
718
|
-
try {
|
|
719
|
-
channel = this.channelManager.getChannel(this.fabric, peerNodeId);
|
|
720
|
-
} catch (error) {
|
|
721
|
-
import_protocol.NoChannelError.accept(error);
|
|
722
|
-
channel = await this.resume(peerNodeId, discoveryOptions);
|
|
723
|
-
}
|
|
724
|
-
return new import_protocol.InteractionClient(
|
|
725
|
-
new import_protocol.ExchangeProvider(this.exchangeManager, channel, async () => {
|
|
726
|
-
if (!this.channelManager.hasChannel(this.fabric, peerNodeId)) {
|
|
727
|
-
throw new import_protocol.RetransmissionLimitReachedError(`Device ${peerNodeId} is currently not reachable.`);
|
|
728
|
-
}
|
|
729
|
-
await this.channelManager.removeAllNodeChannels(this.fabric, peerNodeId);
|
|
730
|
-
const mdnsScanner = this.scanners.scannerFor(import_general.ChannelType.UDP);
|
|
731
|
-
const discoveredAddresses = mdnsScanner?.getDiscoveredOperationalDevice(this.fabric, peerNodeId);
|
|
732
|
-
const lastKnownAddress = this.getLastOperationalAddress(peerNodeId);
|
|
733
|
-
if (lastKnownAddress !== void 0 && discoveredAddresses !== void 0 && discoveredAddresses.addresses.some(
|
|
734
|
-
({ ip, port }) => ip === lastKnownAddress.ip && port === lastKnownAddress.port
|
|
735
|
-
)) {
|
|
736
|
-
discoveredAddresses.addresses.length = 0;
|
|
737
|
-
}
|
|
738
|
-
const operationalAddress = discoveredAddresses?.addresses[0];
|
|
739
|
-
if (operationalAddress === void 0) {
|
|
740
|
-
logger.info(
|
|
741
|
-
`Re-Discovering device failed (no address found), remove all sessions for node ${peerNodeId}`
|
|
742
|
-
);
|
|
743
|
-
await this.sessionManager.removeAllSessionsForNode(peerNodeId);
|
|
744
|
-
throw new import_protocol.RetransmissionLimitReachedError(`No operational address found for node ${peerNodeId}`);
|
|
745
|
-
}
|
|
746
|
-
if (await this.reconnectKnownAddress(peerNodeId, operationalAddress, discoveryData, 2e3) === void 0) {
|
|
747
|
-
throw new import_protocol.RetransmissionLimitReachedError(`Device ${peerNodeId} is not reachable.`);
|
|
748
|
-
}
|
|
749
|
-
return this.channelManager.getChannel(this.fabric, peerNodeId);
|
|
750
|
-
}),
|
|
751
|
-
peerNodeId
|
|
752
|
-
);
|
|
312
|
+
return this.peers.connect(this.fabric.addressOf(peerNodeId), discoveryOptions);
|
|
753
313
|
}
|
|
754
314
|
async getNextAvailableSessionId() {
|
|
755
315
|
return this.sessionManager.getNextAvailableSessionId();
|
|
@@ -758,7 +318,7 @@ class MatterController {
|
|
|
758
318
|
return this.sessionManager.findResumptionRecordById(resumptionId);
|
|
759
319
|
}
|
|
760
320
|
findResumptionRecordByNodeId(nodeId) {
|
|
761
|
-
return this.sessionManager.
|
|
321
|
+
return this.sessionManager.findResumptionRecordByAddress(this.fabric.addressOf(nodeId));
|
|
762
322
|
}
|
|
763
323
|
async saveResumptionRecord(resumptionRecord) {
|
|
764
324
|
return this.sessionManager.saveResumptionRecord(resumptionRecord);
|
|
@@ -766,11 +326,7 @@ class MatterController {
|
|
|
766
326
|
announce() {
|
|
767
327
|
}
|
|
768
328
|
async close() {
|
|
769
|
-
|
|
770
|
-
for (const [nodeId, { timer }] of this.#runningNodeDiscoveries.entries()) {
|
|
771
|
-
timer?.stop();
|
|
772
|
-
mdnsScanner?.cancelOperationalDeviceDiscovery(this.fabric, nodeId, false);
|
|
773
|
-
}
|
|
329
|
+
await this.peers.close();
|
|
774
330
|
await this.exchangeManager.close();
|
|
775
331
|
await this.sessionManager.close();
|
|
776
332
|
await this.channelManager.close();
|
|
@@ -780,4 +336,48 @@ class MatterController {
|
|
|
780
336
|
return this.sessionManager.getActiveSessionInformation();
|
|
781
337
|
}
|
|
782
338
|
}
|
|
339
|
+
class CommissionedNodeStore extends import_protocol.PeerStore {
|
|
340
|
+
constructor(nodesStorage, fabric) {
|
|
341
|
+
super();
|
|
342
|
+
this.nodesStorage = nodesStorage;
|
|
343
|
+
this.fabric = fabric;
|
|
344
|
+
}
|
|
345
|
+
async loadPeers() {
|
|
346
|
+
if (!await this.nodesStorage.has("commissionedNodes")) {
|
|
347
|
+
return [];
|
|
348
|
+
}
|
|
349
|
+
const commissionedNodes = await this.nodesStorage.get("commissionedNodes");
|
|
350
|
+
return commissionedNodes.map(
|
|
351
|
+
([nodeId, { operationalServerAddress, discoveryData, basicInformationData }]) => ({
|
|
352
|
+
address: this.fabric.addressOf(nodeId),
|
|
353
|
+
operationalAddress: operationalServerAddress,
|
|
354
|
+
discoveryData,
|
|
355
|
+
basicInformationData
|
|
356
|
+
})
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
async updatePeer() {
|
|
360
|
+
return this.save();
|
|
361
|
+
}
|
|
362
|
+
async deletePeer() {
|
|
363
|
+
return this.save();
|
|
364
|
+
}
|
|
365
|
+
async save() {
|
|
366
|
+
await this.nodesStorage.set(
|
|
367
|
+
"commissionedNodes",
|
|
368
|
+
this.peers.map((peer) => {
|
|
369
|
+
const {
|
|
370
|
+
address,
|
|
371
|
+
operationalAddress: operationalServerAddress,
|
|
372
|
+
basicInformationData,
|
|
373
|
+
discoveryData
|
|
374
|
+
} = peer;
|
|
375
|
+
return [
|
|
376
|
+
address.nodeId,
|
|
377
|
+
{ operationalServerAddress, basicInformationData, discoveryData }
|
|
378
|
+
];
|
|
379
|
+
})
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
783
383
|
//# sourceMappingURL=MatterController.js.map
|