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