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