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