@matter/protocol 0.13.0-alpha.0-20250318-c1aa38b08 → 0.13.0-alpha.0-20250323-770919c6a
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/ble/BtpSessionHandler.js +2 -2
- package/dist/cjs/ble/BtpSessionHandler.js.map +1 -1
- package/dist/cjs/certificate/CertificateAuthority.d.ts +1 -0
- package/dist/cjs/certificate/CertificateAuthority.d.ts.map +1 -1
- package/dist/cjs/certificate/CertificateAuthority.js.map +1 -1
- package/dist/cjs/certificate/CertificateManager.d.ts.map +1 -1
- package/dist/cjs/certificate/CertificateManager.js +21 -19
- package/dist/cjs/certificate/CertificateManager.js.map +1 -1
- package/dist/cjs/cluster/client/ClusterClient.d.ts.map +1 -1
- package/dist/cjs/cluster/client/ClusterClient.js +3 -0
- package/dist/cjs/cluster/client/ClusterClient.js.map +1 -1
- package/dist/cjs/cluster/server/AttributeServer.d.ts.map +1 -1
- package/dist/cjs/cluster/server/AttributeServer.js +5 -5
- package/dist/cjs/cluster/server/AttributeServer.js.map +1 -1
- package/dist/cjs/cluster/server/CommandServer.js +2 -2
- package/dist/cjs/cluster/server/CommandServer.js.map +1 -1
- package/dist/cjs/common/FailsafeContext.js +1 -1
- package/dist/cjs/common/FailsafeContext.js.map +1 -1
- package/dist/cjs/endpoint/EndpointStructureLogger.js +1 -1
- package/dist/cjs/endpoint/EndpointStructureLogger.js.map +1 -1
- package/dist/cjs/events/OccurrenceManager.d.ts.map +1 -1
- package/dist/cjs/events/OccurrenceManager.js +2 -2
- package/dist/cjs/events/OccurrenceManager.js.map +1 -1
- package/dist/cjs/interaction/AttributeDataDecoder.d.ts +21 -4
- package/dist/cjs/interaction/AttributeDataDecoder.d.ts.map +1 -1
- package/dist/cjs/interaction/AttributeDataDecoder.js +41 -2
- package/dist/cjs/interaction/AttributeDataDecoder.js.map +1 -1
- package/dist/cjs/interaction/AttributeDataEncoder.d.ts.map +1 -1
- package/dist/cjs/interaction/AttributeDataEncoder.js +3 -3
- package/dist/cjs/interaction/AttributeDataEncoder.js.map +1 -1
- package/dist/cjs/interaction/DecodedDataReport.d.ts +4 -2
- package/dist/cjs/interaction/DecodedDataReport.d.ts.map +1 -1
- package/dist/cjs/interaction/DecodedDataReport.js +6 -2
- package/dist/cjs/interaction/DecodedDataReport.js.map +1 -1
- package/dist/cjs/interaction/EventDataDecoder.d.ts +15 -3
- package/dist/cjs/interaction/EventDataDecoder.d.ts.map +1 -1
- package/dist/cjs/interaction/EventDataDecoder.js +39 -2
- package/dist/cjs/interaction/EventDataDecoder.js.map +1 -1
- package/dist/cjs/interaction/InteractionClient.d.ts +44 -4
- package/dist/cjs/interaction/InteractionClient.d.ts.map +1 -1
- package/dist/cjs/interaction/InteractionClient.js +71 -18
- package/dist/cjs/interaction/InteractionClient.js.map +1 -1
- package/dist/cjs/interaction/InteractionMessenger.d.ts.map +1 -1
- package/dist/cjs/interaction/InteractionMessenger.js +7 -4
- package/dist/cjs/interaction/InteractionMessenger.js.map +1 -1
- package/dist/cjs/interaction/InteractionServer.d.ts.map +1 -1
- package/dist/cjs/interaction/InteractionServer.js +7 -7
- package/dist/cjs/interaction/InteractionServer.js.map +1 -1
- package/dist/cjs/interaction/ServerSubscription.d.ts.map +1 -1
- package/dist/cjs/interaction/ServerSubscription.js +1 -1
- package/dist/cjs/interaction/ServerSubscription.js.map +1 -1
- package/dist/cjs/mdns/MdnsScanner.js +2 -2
- package/dist/cjs/mdns/MdnsScanner.js.map +1 -1
- package/dist/cjs/peer/ControllerCommissioner.d.ts +15 -3
- package/dist/cjs/peer/ControllerCommissioner.d.ts.map +1 -1
- package/dist/cjs/peer/ControllerCommissioner.js +17 -6
- package/dist/cjs/peer/ControllerCommissioner.js.map +1 -1
- package/dist/cjs/peer/ControllerCommissioningFlow.d.ts +47 -1
- package/dist/cjs/peer/ControllerCommissioningFlow.d.ts.map +1 -1
- package/dist/cjs/peer/ControllerCommissioningFlow.js +136 -136
- package/dist/cjs/peer/ControllerCommissioningFlow.js.map +1 -1
- package/dist/cjs/peer/ControllerDiscovery.d.ts.map +1 -1
- package/dist/cjs/peer/ControllerDiscovery.js +4 -4
- package/dist/cjs/peer/ControllerDiscovery.js.map +1 -1
- package/dist/cjs/peer/PeerSet.d.ts +2 -2
- package/dist/cjs/peer/PeerSet.d.ts.map +1 -1
- package/dist/cjs/peer/PeerSet.js +6 -1
- package/dist/cjs/peer/PeerSet.js.map +1 -1
- package/dist/cjs/protocol/ChannelManager.d.ts.map +1 -1
- package/dist/cjs/protocol/ChannelManager.js +11 -4
- package/dist/cjs/protocol/ChannelManager.js.map +1 -1
- package/dist/cjs/protocol/ExchangeManager.d.ts.map +1 -1
- package/dist/cjs/protocol/ExchangeManager.js +1 -2
- package/dist/cjs/protocol/ExchangeManager.js.map +1 -1
- package/dist/esm/ble/BtpSessionHandler.js +2 -2
- package/dist/esm/ble/BtpSessionHandler.js.map +1 -1
- package/dist/esm/certificate/CertificateAuthority.d.ts +1 -0
- package/dist/esm/certificate/CertificateAuthority.d.ts.map +1 -1
- package/dist/esm/certificate/CertificateAuthority.js.map +1 -1
- package/dist/esm/certificate/CertificateManager.d.ts.map +1 -1
- package/dist/esm/certificate/CertificateManager.js +22 -19
- package/dist/esm/certificate/CertificateManager.js.map +1 -1
- package/dist/esm/cluster/client/ClusterClient.d.ts.map +1 -1
- package/dist/esm/cluster/client/ClusterClient.js +3 -0
- package/dist/esm/cluster/client/ClusterClient.js.map +1 -1
- package/dist/esm/cluster/server/AttributeServer.d.ts.map +1 -1
- package/dist/esm/cluster/server/AttributeServer.js +15 -6
- package/dist/esm/cluster/server/AttributeServer.js.map +1 -1
- package/dist/esm/cluster/server/CommandServer.js +3 -3
- package/dist/esm/cluster/server/CommandServer.js.map +1 -1
- package/dist/esm/common/FailsafeContext.js +1 -1
- package/dist/esm/common/FailsafeContext.js.map +1 -1
- package/dist/esm/endpoint/EndpointStructureLogger.js +1 -1
- package/dist/esm/endpoint/EndpointStructureLogger.js.map +1 -1
- package/dist/esm/events/OccurrenceManager.d.ts.map +1 -1
- package/dist/esm/events/OccurrenceManager.js +3 -2
- package/dist/esm/events/OccurrenceManager.js.map +1 -1
- package/dist/esm/interaction/AttributeDataDecoder.d.ts +21 -4
- package/dist/esm/interaction/AttributeDataDecoder.d.ts.map +1 -1
- package/dist/esm/interaction/AttributeDataDecoder.js +41 -2
- package/dist/esm/interaction/AttributeDataDecoder.js.map +1 -1
- package/dist/esm/interaction/AttributeDataEncoder.d.ts.map +1 -1
- package/dist/esm/interaction/AttributeDataEncoder.js +4 -4
- package/dist/esm/interaction/AttributeDataEncoder.js.map +1 -1
- package/dist/esm/interaction/DecodedDataReport.d.ts +4 -2
- package/dist/esm/interaction/DecodedDataReport.d.ts.map +1 -1
- package/dist/esm/interaction/DecodedDataReport.js +12 -4
- package/dist/esm/interaction/DecodedDataReport.js.map +1 -1
- package/dist/esm/interaction/EventDataDecoder.d.ts +15 -3
- package/dist/esm/interaction/EventDataDecoder.d.ts.map +1 -1
- package/dist/esm/interaction/EventDataDecoder.js +39 -2
- package/dist/esm/interaction/EventDataDecoder.js.map +1 -1
- package/dist/esm/interaction/InteractionClient.d.ts +44 -4
- package/dist/esm/interaction/InteractionClient.d.ts.map +1 -1
- package/dist/esm/interaction/InteractionClient.js +74 -18
- package/dist/esm/interaction/InteractionClient.js.map +1 -1
- package/dist/esm/interaction/InteractionMessenger.d.ts.map +1 -1
- package/dist/esm/interaction/InteractionMessenger.js +8 -4
- package/dist/esm/interaction/InteractionMessenger.js.map +1 -1
- package/dist/esm/interaction/InteractionServer.d.ts.map +1 -1
- package/dist/esm/interaction/InteractionServer.js +17 -8
- package/dist/esm/interaction/InteractionServer.js.map +1 -1
- package/dist/esm/interaction/ServerSubscription.d.ts.map +1 -1
- package/dist/esm/interaction/ServerSubscription.js +2 -1
- package/dist/esm/interaction/ServerSubscription.js.map +1 -1
- package/dist/esm/mdns/MdnsScanner.js +2 -2
- package/dist/esm/mdns/MdnsScanner.js.map +1 -1
- package/dist/esm/peer/ControllerCommissioner.d.ts +15 -3
- package/dist/esm/peer/ControllerCommissioner.d.ts.map +1 -1
- package/dist/esm/peer/ControllerCommissioner.js +18 -6
- package/dist/esm/peer/ControllerCommissioner.js.map +1 -1
- package/dist/esm/peer/ControllerCommissioningFlow.d.ts +47 -1
- package/dist/esm/peer/ControllerCommissioningFlow.d.ts.map +1 -1
- package/dist/esm/peer/ControllerCommissioningFlow.js +147 -137
- package/dist/esm/peer/ControllerCommissioningFlow.js.map +1 -1
- package/dist/esm/peer/ControllerDiscovery.d.ts.map +1 -1
- package/dist/esm/peer/ControllerDiscovery.js +5 -5
- package/dist/esm/peer/ControllerDiscovery.js.map +1 -1
- package/dist/esm/peer/PeerSet.d.ts +2 -2
- package/dist/esm/peer/PeerSet.d.ts.map +1 -1
- package/dist/esm/peer/PeerSet.js +7 -2
- package/dist/esm/peer/PeerSet.js.map +1 -1
- package/dist/esm/protocol/ChannelManager.d.ts.map +1 -1
- package/dist/esm/protocol/ChannelManager.js +11 -4
- package/dist/esm/protocol/ChannelManager.js.map +1 -1
- package/dist/esm/protocol/ExchangeManager.d.ts.map +1 -1
- package/dist/esm/protocol/ExchangeManager.js +2 -2
- package/dist/esm/protocol/ExchangeManager.js.map +1 -1
- package/package.json +6 -6
- package/src/ble/BtpSessionHandler.ts +2 -2
- package/src/certificate/CertificateAuthority.ts +1 -0
- package/src/certificate/CertificateManager.ts +22 -19
- package/src/cluster/client/ClusterClient.ts +3 -0
- package/src/cluster/server/AttributeServer.ts +15 -6
- package/src/cluster/server/CommandServer.ts +3 -3
- package/src/common/FailsafeContext.ts +1 -1
- package/src/endpoint/EndpointStructureLogger.ts +1 -1
- package/src/events/OccurrenceManager.ts +3 -2
- package/src/interaction/AttributeDataDecoder.ts +67 -7
- package/src/interaction/AttributeDataEncoder.ts +4 -4
- package/src/interaction/DecodedDataReport.ts +24 -5
- package/src/interaction/EventDataDecoder.ts +57 -5
- package/src/interaction/InteractionClient.ts +112 -18
- package/src/interaction/InteractionMessenger.ts +8 -4
- package/src/interaction/InteractionServer.ts +19 -9
- package/src/interaction/ServerSubscription.ts +2 -1
- package/src/mdns/MdnsScanner.ts +2 -2
- package/src/peer/ControllerCommissioner.ts +32 -7
- package/src/peer/ControllerCommissioningFlow.ts +160 -146
- package/src/peer/ControllerDiscovery.ts +5 -5
- package/src/peer/PeerSet.ts +7 -2
- package/src/protocol/ChannelManager.ts +11 -4
- package/src/protocol/ExchangeManager.ts +2 -2
|
@@ -10,7 +10,17 @@ import { GeneralCommissioning } from "#clusters/general-commissioning";
|
|
|
10
10
|
import { NetworkCommissioning } from "#clusters/network-commissioning";
|
|
11
11
|
import { OperationalCredentials } from "#clusters/operational-credentials";
|
|
12
12
|
import { TimeSynchronizationCluster } from "#clusters/time-synchronization";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
Bytes,
|
|
15
|
+
ChannelType,
|
|
16
|
+
Crypto,
|
|
17
|
+
Diagnostic,
|
|
18
|
+
Logger,
|
|
19
|
+
MatterError,
|
|
20
|
+
repackErrorAs,
|
|
21
|
+
Time,
|
|
22
|
+
UnexpectedDataError,
|
|
23
|
+
} from "#general";
|
|
14
24
|
import {
|
|
15
25
|
ClusterId,
|
|
16
26
|
ClusterType,
|
|
@@ -142,22 +152,22 @@ const DEFAULT_FAILSAFE_TIME_MS = 60_000; // 60 seconds
|
|
|
142
152
|
* Class to abstract the Device commission flow in a step wise way as defined in Specs. The specs are not 100%
|
|
143
153
|
*/
|
|
144
154
|
export class ControllerCommissioningFlow {
|
|
145
|
-
|
|
146
|
-
readonly
|
|
147
|
-
readonly
|
|
148
|
-
readonly
|
|
155
|
+
protected interactionClient: InteractionClient;
|
|
156
|
+
protected readonly ca: CertificateAuthority;
|
|
157
|
+
protected readonly fabric: Fabric;
|
|
158
|
+
protected readonly transitionToCase: (
|
|
149
159
|
peerAddress: PeerAddress,
|
|
150
160
|
supportsConcurrentConnections: boolean,
|
|
151
161
|
) => Promise<InteractionClient | undefined>;
|
|
152
|
-
readonly
|
|
153
|
-
readonly
|
|
154
|
-
readonly
|
|
162
|
+
protected readonly commissioningOptions: ControllerCommissioningFlowOptions;
|
|
163
|
+
protected readonly commissioningSteps = new Array<CommissioningStep>();
|
|
164
|
+
protected readonly commissioningStepResults = new Map<string, CommissioningStepResult>();
|
|
155
165
|
readonly #clusterClients = new Map<ClusterId, ClusterClientObj>();
|
|
156
166
|
#commissioningStartedTime: number | undefined;
|
|
157
167
|
#commissioningExpiryTime: number | undefined;
|
|
158
168
|
#lastFailSafeTime: number | undefined;
|
|
159
|
-
|
|
160
|
-
|
|
169
|
+
protected lastBreadcrumb = 1;
|
|
170
|
+
protected collectedCommissioningData: CollectedCommissioningData = {};
|
|
161
171
|
#failSafeTimeMs = DEFAULT_FAILSAFE_TIME_MS;
|
|
162
172
|
|
|
163
173
|
constructor(
|
|
@@ -179,12 +189,12 @@ export class ControllerCommissioningFlow {
|
|
|
179
189
|
supportsConcurrentConnections: boolean,
|
|
180
190
|
) => Promise<InteractionClient | undefined>,
|
|
181
191
|
) {
|
|
182
|
-
this
|
|
183
|
-
this
|
|
184
|
-
this
|
|
185
|
-
this
|
|
186
|
-
this
|
|
187
|
-
logger.debug(`Commissioning options: ${
|
|
192
|
+
this.interactionClient = interactionClient;
|
|
193
|
+
this.ca = ca;
|
|
194
|
+
this.fabric = fabric;
|
|
195
|
+
this.transitionToCase = transitionToCase;
|
|
196
|
+
this.commissioningOptions = commissioningOptions;
|
|
197
|
+
logger.debug(`Commissioning options: ${Diagnostic.json(commissioningOptions)}`);
|
|
188
198
|
this.#initializeCommissioningSteps();
|
|
189
199
|
}
|
|
190
200
|
|
|
@@ -198,7 +208,7 @@ export class ControllerCommissioningFlow {
|
|
|
198
208
|
this.#sortSteps();
|
|
199
209
|
|
|
200
210
|
let failSafeTimerReArmedAfterPreviousStep = false;
|
|
201
|
-
for (const step of this
|
|
211
|
+
for (const step of this.commissioningSteps) {
|
|
202
212
|
logger.info(`Executing commissioning step ${step.stepNumber}.${step.subStepNumber}: ${step.name}`);
|
|
203
213
|
try {
|
|
204
214
|
if (step.reArmFailsafe && !failSafeTimerReArmedAfterPreviousStep) {
|
|
@@ -294,7 +304,7 @@ export class ControllerCommissioningFlow {
|
|
|
294
304
|
logger.debug(
|
|
295
305
|
`Creating new cluster client for cluster ${cluster.name} (endpoint ${endpointId}, isFeatureSpecific ${isFeatureSpecific})`,
|
|
296
306
|
);
|
|
297
|
-
const client = ClusterClient(cluster, endpointId, this
|
|
307
|
+
const client = ClusterClient(cluster, endpointId, this.interactionClient);
|
|
298
308
|
this.#clusterClients.set(cluster.id, client);
|
|
299
309
|
return client;
|
|
300
310
|
}
|
|
@@ -304,7 +314,7 @@ export class ControllerCommissioningFlow {
|
|
|
304
314
|
* @see {@link MatterSpecification.v13.Core} § 5.5
|
|
305
315
|
*/
|
|
306
316
|
#initializeCommissioningSteps() {
|
|
307
|
-
this
|
|
317
|
+
this.commissioningSteps.push({
|
|
308
318
|
stepNumber: 0, // Preparation
|
|
309
319
|
subStepNumber: 1,
|
|
310
320
|
name: "GetInitialData",
|
|
@@ -316,21 +326,21 @@ export class ControllerCommissioningFlow {
|
|
|
316
326
|
// TODO Step 3-5: Commissioner handles/prepares for T&C Ack, if supported
|
|
317
327
|
// Step 6: is the PASE session establishment which is done before this starts here
|
|
318
328
|
|
|
319
|
-
this
|
|
329
|
+
this.commissioningSteps.push({
|
|
320
330
|
stepNumber: 7,
|
|
321
331
|
subStepNumber: 1,
|
|
322
332
|
name: "GeneralCommissioning.ArmFailsafe",
|
|
323
333
|
stepLogic: () => this.#armFailsafe(),
|
|
324
334
|
});
|
|
325
335
|
|
|
326
|
-
this
|
|
336
|
+
this.commissioningSteps.push({
|
|
327
337
|
stepNumber: 8,
|
|
328
338
|
subStepNumber: 1,
|
|
329
339
|
name: "GeneralCommissioning.ConfigureRegulatoryInformation",
|
|
330
340
|
stepLogic: () => this.#configureRegulatoryInformation(),
|
|
331
341
|
});
|
|
332
342
|
|
|
333
|
-
this
|
|
343
|
+
this.commissioningSteps.push({
|
|
334
344
|
stepNumber: 8,
|
|
335
345
|
subStepNumber: 2,
|
|
336
346
|
name: "TimeSynchronization.SynchronizeTime",
|
|
@@ -339,14 +349,14 @@ export class ControllerCommissioningFlow {
|
|
|
339
349
|
|
|
340
350
|
// TODO Step 9: If device and Controller supports T&C Feature then User consent is handled
|
|
341
351
|
|
|
342
|
-
this
|
|
352
|
+
this.commissioningSteps.push({
|
|
343
353
|
stepNumber: 10,
|
|
344
354
|
subStepNumber: 1,
|
|
345
355
|
name: "OperationalCredentials.DeviceAttestation",
|
|
346
356
|
stepLogic: () => this.#deviceAttestation(),
|
|
347
357
|
});
|
|
348
358
|
|
|
349
|
-
this
|
|
359
|
+
this.commissioningSteps.push({
|
|
350
360
|
stepNumber: 11, // includes 11-13
|
|
351
361
|
subStepNumber: 1,
|
|
352
362
|
name: "OperationalCredentials.Certificates",
|
|
@@ -355,7 +365,7 @@ export class ControllerCommissioningFlow {
|
|
|
355
365
|
|
|
356
366
|
// TODO Step 14: TimeSynchronization.SetTrustedTimeSource if supported
|
|
357
367
|
|
|
358
|
-
this
|
|
368
|
+
this.commissioningSteps.push({
|
|
359
369
|
stepNumber: 15,
|
|
360
370
|
subStepNumber: 1,
|
|
361
371
|
name: "AccessControl",
|
|
@@ -363,15 +373,15 @@ export class ControllerCommissioningFlow {
|
|
|
363
373
|
});
|
|
364
374
|
|
|
365
375
|
// Care about Network commissioning only when we are on BLE, because else we are already on IP network
|
|
366
|
-
if (this
|
|
367
|
-
this
|
|
376
|
+
if (this.interactionClient.channelType === ChannelType.BLE) {
|
|
377
|
+
this.commissioningSteps.push({
|
|
368
378
|
stepNumber: 16,
|
|
369
379
|
subStepNumber: 1,
|
|
370
380
|
name: "NetworkCommissioning.Validate",
|
|
371
381
|
stepLogic: () => this.#validateNetwork(),
|
|
372
382
|
});
|
|
373
|
-
if (this
|
|
374
|
-
this
|
|
383
|
+
if (this.commissioningOptions.wifiNetwork !== undefined) {
|
|
384
|
+
this.commissioningSteps.push({
|
|
375
385
|
stepNumber: 16, // includes step 17
|
|
376
386
|
subStepNumber: 2,
|
|
377
387
|
name: "NetworkCommissioning.Wifi",
|
|
@@ -379,8 +389,8 @@ export class ControllerCommissioningFlow {
|
|
|
379
389
|
stepLogic: () => this.#configureNetworkWifi(),
|
|
380
390
|
});
|
|
381
391
|
}
|
|
382
|
-
if (this
|
|
383
|
-
this
|
|
392
|
+
if (this.commissioningOptions.threadNetwork !== undefined) {
|
|
393
|
+
this.commissioningSteps.push({
|
|
384
394
|
stepNumber: 16, // includes step 17
|
|
385
395
|
subStepNumber: 3,
|
|
386
396
|
name: "NetworkCommissioning.Thread",
|
|
@@ -390,11 +400,11 @@ export class ControllerCommissioningFlow {
|
|
|
390
400
|
}
|
|
391
401
|
} else {
|
|
392
402
|
logger.info(
|
|
393
|
-
`Skipping NetworkCommissioning steps because the device is already on IP network (${this
|
|
403
|
+
`Skipping NetworkCommissioning steps because the device is already on IP network (${this.interactionClient.channelType})`,
|
|
394
404
|
);
|
|
395
405
|
}
|
|
396
406
|
|
|
397
|
-
this
|
|
407
|
+
this.commissioningSteps.push({
|
|
398
408
|
stepNumber: 18, // includes step 19 (CASE connection)
|
|
399
409
|
subStepNumber: 1,
|
|
400
410
|
name: "Reconnect",
|
|
@@ -402,14 +412,14 @@ export class ControllerCommissioningFlow {
|
|
|
402
412
|
stepLogic: () => this.#reconnectWithDevice(),
|
|
403
413
|
});
|
|
404
414
|
|
|
405
|
-
this
|
|
415
|
+
this.commissioningSteps.push({
|
|
406
416
|
stepNumber: 20,
|
|
407
417
|
subStepNumber: 1,
|
|
408
418
|
name: "GeneralCommissioning.Complete",
|
|
409
419
|
stepLogic: () => this.#completeCommissioning(),
|
|
410
420
|
});
|
|
411
421
|
|
|
412
|
-
this
|
|
422
|
+
this.commissioningSteps.push({
|
|
413
423
|
stepNumber: 99, // Should be allowed in Step 13, but Tasmota is not supporting this
|
|
414
424
|
subStepNumber: 1,
|
|
415
425
|
name: "OperationalCredentials.UpdateFabricLabel",
|
|
@@ -418,18 +428,18 @@ export class ControllerCommissioningFlow {
|
|
|
418
428
|
}
|
|
419
429
|
|
|
420
430
|
#sortSteps() {
|
|
421
|
-
this
|
|
431
|
+
this.commissioningSteps.sort((a, b) => {
|
|
422
432
|
if (a.stepNumber !== b.stepNumber) return a.stepNumber - b.stepNumber;
|
|
423
433
|
return a.subStepNumber - b.subStepNumber;
|
|
424
434
|
});
|
|
425
435
|
}
|
|
426
436
|
|
|
427
437
|
#setCommissioningStepResult(step: CommissioningStep, result: CommissioningStepResult) {
|
|
428
|
-
this
|
|
438
|
+
this.commissioningStepResults.set(`${step.stepNumber}-${step.subStepNumber}`, result);
|
|
429
439
|
}
|
|
430
440
|
|
|
431
441
|
getCommissioningStepResult(stepNumber: number, subStepNumber: number) {
|
|
432
|
-
return this
|
|
442
|
+
return this.commissioningStepResults.get(`${stepNumber}-${subStepNumber}`);
|
|
433
443
|
}
|
|
434
444
|
|
|
435
445
|
/** Helper method to check for errorCode/debugTest responses and throw error on failure */
|
|
@@ -472,10 +482,10 @@ export class ControllerCommissioningFlow {
|
|
|
472
482
|
*/
|
|
473
483
|
async #getInitialData() {
|
|
474
484
|
const descriptorClient = this.#getClusterClient(Descriptor.Cluster);
|
|
475
|
-
this
|
|
476
|
-
this
|
|
485
|
+
this.collectedCommissioningData.rootPartsList = await descriptorClient.getPartsListAttribute();
|
|
486
|
+
this.collectedCommissioningData.rootServerList = await descriptorClient.getServerListAttribute();
|
|
477
487
|
|
|
478
|
-
const networkData = await this
|
|
488
|
+
const networkData = await this.interactionClient.getMultipleAttributes({
|
|
479
489
|
attributes: [
|
|
480
490
|
{
|
|
481
491
|
clusterId: NetworkCommissioning.Complete.id,
|
|
@@ -505,16 +515,16 @@ export class ControllerCommissioningFlow {
|
|
|
505
515
|
networkStatus.push({ endpointId, value });
|
|
506
516
|
}
|
|
507
517
|
}
|
|
508
|
-
this
|
|
509
|
-
this
|
|
518
|
+
this.collectedCommissioningData.networkFeatures = networkFeatures;
|
|
519
|
+
this.collectedCommissioningData.networkStatus = networkStatus;
|
|
510
520
|
|
|
511
521
|
const basicInfoClient = this.#getClusterClient(BasicInformation.Cluster);
|
|
512
|
-
this
|
|
513
|
-
this
|
|
514
|
-
this
|
|
522
|
+
this.collectedCommissioningData.vendorId = await basicInfoClient.getVendorIdAttribute();
|
|
523
|
+
this.collectedCommissioningData.productId = await basicInfoClient.getProductIdAttribute();
|
|
524
|
+
this.collectedCommissioningData.productName = await basicInfoClient.getProductNameAttribute();
|
|
515
525
|
|
|
516
526
|
const generalCommissioningClient = this.#getClusterClient(GeneralCommissioning.Cluster);
|
|
517
|
-
this
|
|
527
|
+
this.collectedCommissioningData.supportsConcurrentConnection =
|
|
518
528
|
await generalCommissioningClient.getSupportsConcurrentConnectionAttribute();
|
|
519
529
|
|
|
520
530
|
/*
|
|
@@ -529,7 +539,7 @@ export class ControllerCommissioningFlow {
|
|
|
529
539
|
|
|
530
540
|
return {
|
|
531
541
|
code: CommissioningStepResultCode.Success,
|
|
532
|
-
breadcrumb: this
|
|
542
|
+
breadcrumb: this.lastBreadcrumb,
|
|
533
543
|
};
|
|
534
544
|
}
|
|
535
545
|
|
|
@@ -544,9 +554,9 @@ export class ControllerCommissioningFlow {
|
|
|
544
554
|
*/
|
|
545
555
|
async #armFailsafe() {
|
|
546
556
|
const client = this.#getClusterClient(GeneralCommissioning.Cluster);
|
|
547
|
-
if (this
|
|
557
|
+
if (this.collectedCommissioningData.basicCommissioningInfo === undefined) {
|
|
548
558
|
const basicCommissioningInfo = await client.getBasicCommissioningInfoAttribute();
|
|
549
|
-
this
|
|
559
|
+
this.collectedCommissioningData.basicCommissioningInfo = basicCommissioningInfo;
|
|
550
560
|
this.#failSafeTimeMs = basicCommissioningInfo.failSafeExpiryLengthSeconds * 1000;
|
|
551
561
|
this.#commissioningStartedTime = Time.nowMs();
|
|
552
562
|
this.#commissioningExpiryTime =
|
|
@@ -555,15 +565,15 @@ export class ControllerCommissioningFlow {
|
|
|
555
565
|
this.#ensureGeneralCommissioningSuccess(
|
|
556
566
|
"armFailSafe",
|
|
557
567
|
await client.armFailSafe({
|
|
558
|
-
breadcrumb: this
|
|
568
|
+
breadcrumb: this.lastBreadcrumb,
|
|
559
569
|
expiryLengthSeconds:
|
|
560
|
-
this
|
|
570
|
+
this.collectedCommissioningData.basicCommissioningInfo?.failSafeExpiryLengthSeconds,
|
|
561
571
|
}),
|
|
562
572
|
);
|
|
563
573
|
this.#lastFailSafeTime = Time.nowMs();
|
|
564
574
|
return {
|
|
565
575
|
code: CommissioningStepResultCode.Success,
|
|
566
|
-
breadcrumb: this
|
|
576
|
+
breadcrumb: this.lastBreadcrumb,
|
|
567
577
|
};
|
|
568
578
|
}
|
|
569
579
|
|
|
@@ -572,7 +582,7 @@ export class ControllerCommissioningFlow {
|
|
|
572
582
|
try {
|
|
573
583
|
const client = this.#getClusterClient(GeneralCommissioning.Cluster);
|
|
574
584
|
await client.armFailSafe({
|
|
575
|
-
breadcrumb: this
|
|
585
|
+
breadcrumb: this.lastBreadcrumb,
|
|
576
586
|
expiryLengthSeconds: 0,
|
|
577
587
|
});
|
|
578
588
|
this.#lastFailSafeTime = undefined; // No failsafe active anymore
|
|
@@ -589,11 +599,11 @@ export class ControllerCommissioningFlow {
|
|
|
589
599
|
* Commissionee using the SetRegulatoryConfig command.
|
|
590
600
|
*/
|
|
591
601
|
async #configureRegulatoryInformation() {
|
|
592
|
-
if (this
|
|
602
|
+
if (this.collectedCommissioningData.networkFeatures === undefined) {
|
|
593
603
|
throw new CommissioningError("No network features collected. This should never happen.");
|
|
594
604
|
}
|
|
595
605
|
// Read the infos for all Network Commissioning clusters
|
|
596
|
-
const hasRadioNetwork = this
|
|
606
|
+
const hasRadioNetwork = this.collectedCommissioningData.networkFeatures.some(
|
|
597
607
|
({ value: { wiFiNetworkInterface, threadNetworkInterface } }) =>
|
|
598
608
|
wiFiNetworkInterface || threadNetworkInterface,
|
|
599
609
|
);
|
|
@@ -602,7 +612,7 @@ export class ControllerCommissioningFlow {
|
|
|
602
612
|
const client = this.#getClusterClient(GeneralCommissioning.Cluster);
|
|
603
613
|
let locationCapability = await client.getLocationCapabilityAttribute();
|
|
604
614
|
if (locationCapability === GeneralCommissioning.RegulatoryLocationType.IndoorOutdoor) {
|
|
605
|
-
locationCapability = this
|
|
615
|
+
locationCapability = this.commissioningOptions.regulatoryLocation;
|
|
606
616
|
} else {
|
|
607
617
|
logger.debug(
|
|
608
618
|
`Device does not support a configurable regulatory location type. Location is set to "${
|
|
@@ -610,10 +620,10 @@ export class ControllerCommissioningFlow {
|
|
|
610
620
|
}"`,
|
|
611
621
|
);
|
|
612
622
|
}
|
|
613
|
-
let countryCode = this
|
|
623
|
+
let countryCode = this.commissioningOptions.regulatoryCountryCode;
|
|
614
624
|
const regulatoryResult = await client.setRegulatoryConfig(
|
|
615
625
|
{
|
|
616
|
-
breadcrumb: this
|
|
626
|
+
breadcrumb: this.lastBreadcrumb++,
|
|
617
627
|
newRegulatoryConfig: locationCapability,
|
|
618
628
|
countryCode,
|
|
619
629
|
},
|
|
@@ -631,7 +641,7 @@ export class ControllerCommissioningFlow {
|
|
|
631
641
|
"setRegulatoryConfig",
|
|
632
642
|
await client.setRegulatoryConfig(
|
|
633
643
|
{
|
|
634
|
-
breadcrumb: this
|
|
644
|
+
breadcrumb: this.lastBreadcrumb,
|
|
635
645
|
newRegulatoryConfig: locationCapability,
|
|
636
646
|
countryCode,
|
|
637
647
|
},
|
|
@@ -643,12 +653,12 @@ export class ControllerCommissioningFlow {
|
|
|
643
653
|
}
|
|
644
654
|
return {
|
|
645
655
|
code: CommissioningStepResultCode.Success,
|
|
646
|
-
breadcrumb: this
|
|
656
|
+
breadcrumb: this.lastBreadcrumb,
|
|
647
657
|
};
|
|
648
658
|
}
|
|
649
659
|
return {
|
|
650
660
|
code: CommissioningStepResultCode.Skipped,
|
|
651
|
-
breadcrumb: this
|
|
661
|
+
breadcrumb: this.lastBreadcrumb,
|
|
652
662
|
};
|
|
653
663
|
}
|
|
654
664
|
|
|
@@ -663,8 +673,8 @@ export class ControllerCommissioningFlow {
|
|
|
663
673
|
*/
|
|
664
674
|
async #synchronizeTime() {
|
|
665
675
|
if (
|
|
666
|
-
this
|
|
667
|
-
this
|
|
676
|
+
this.collectedCommissioningData.rootServerList !== undefined &&
|
|
677
|
+
this.collectedCommissioningData.rootServerList.find(
|
|
668
678
|
clusterId => clusterId === TimeSynchronizationCluster.id,
|
|
669
679
|
)
|
|
670
680
|
) {
|
|
@@ -673,7 +683,7 @@ export class ControllerCommissioningFlow {
|
|
|
673
683
|
}
|
|
674
684
|
return {
|
|
675
685
|
code: CommissioningStepResultCode.Skipped,
|
|
676
|
-
breadcrumb: this
|
|
686
|
+
breadcrumb: this.lastBreadcrumb,
|
|
677
687
|
};
|
|
678
688
|
}
|
|
679
689
|
|
|
@@ -717,7 +727,7 @@ export class ControllerCommissioningFlow {
|
|
|
717
727
|
}
|
|
718
728
|
return {
|
|
719
729
|
code: CommissioningStepResultCode.Success,
|
|
720
|
-
breadcrumb: this
|
|
730
|
+
breadcrumb: this.lastBreadcrumb,
|
|
721
731
|
};
|
|
722
732
|
|
|
723
733
|
// TODO consider Distributed Compliance Ledger Info about Commissioning Flow
|
|
@@ -756,23 +766,23 @@ export class ControllerCommissioningFlow {
|
|
|
756
766
|
|
|
757
767
|
await operationalCredentialsClusterClient.addTrustedRootCertificate(
|
|
758
768
|
{
|
|
759
|
-
rootCaCertificate: this
|
|
769
|
+
rootCaCertificate: this.ca.rootCert,
|
|
760
770
|
},
|
|
761
771
|
{ useExtendedFailSafeMessageResponseTimeout: true },
|
|
762
772
|
);
|
|
763
|
-
const peerOperationalCert = this
|
|
773
|
+
const peerOperationalCert = this.ca.generateNoc(
|
|
764
774
|
operationalPublicKey,
|
|
765
|
-
this
|
|
766
|
-
this
|
|
775
|
+
this.fabric.fabricId,
|
|
776
|
+
this.interactionClient.address.nodeId,
|
|
767
777
|
);
|
|
768
778
|
|
|
769
779
|
const addNocResponse = await operationalCredentialsClusterClient.addNoc(
|
|
770
780
|
{
|
|
771
781
|
nocValue: peerOperationalCert,
|
|
772
782
|
icacValue: new Uint8Array(0),
|
|
773
|
-
ipkValue: this
|
|
774
|
-
adminVendorId: this
|
|
775
|
-
caseAdminSubject: this
|
|
783
|
+
ipkValue: this.fabric.identityProtectionKey,
|
|
784
|
+
adminVendorId: this.fabric.rootVendorId,
|
|
785
|
+
caseAdminSubject: this.fabric.rootNodeId,
|
|
776
786
|
},
|
|
777
787
|
{ useExtendedFailSafeMessageResponseTimeout: true },
|
|
778
788
|
);
|
|
@@ -780,11 +790,11 @@ export class ControllerCommissioningFlow {
|
|
|
780
790
|
this.#ensureOperationalCredentialsSuccess("addNoc", addNocResponse);
|
|
781
791
|
|
|
782
792
|
const { fabricIndex } = addNocResponse;
|
|
783
|
-
this
|
|
793
|
+
this.collectedCommissioningData.fabricIndex = fabricIndex;
|
|
784
794
|
|
|
785
795
|
return {
|
|
786
796
|
code: CommissioningStepResultCode.Success,
|
|
787
|
-
breadcrumb: this
|
|
797
|
+
breadcrumb: this.lastBreadcrumb,
|
|
788
798
|
};
|
|
789
799
|
}
|
|
790
800
|
|
|
@@ -796,12 +806,12 @@ export class ControllerCommissioningFlow {
|
|
|
796
806
|
* the commissioning process.
|
|
797
807
|
*/
|
|
798
808
|
async #updateFabricLabel() {
|
|
799
|
-
const { fabricIndex } = this
|
|
809
|
+
const { fabricIndex } = this.collectedCommissioningData;
|
|
800
810
|
if (fabricIndex === undefined) {
|
|
801
811
|
logger.error("No fabric index available after addNoc. This should never happen.");
|
|
802
812
|
return {
|
|
803
813
|
code: CommissioningStepResultCode.Failure,
|
|
804
|
-
breadcrumb: this
|
|
814
|
+
breadcrumb: this.lastBreadcrumb,
|
|
805
815
|
};
|
|
806
816
|
}
|
|
807
817
|
const operationalCredentialCluster = this.#getClusterClient(OperationalCredentials.Cluster);
|
|
@@ -809,7 +819,7 @@ export class ControllerCommissioningFlow {
|
|
|
809
819
|
this.#ensureOperationalCredentialsSuccess(
|
|
810
820
|
"updateFabricLabel",
|
|
811
821
|
await operationalCredentialCluster.updateFabricLabel({
|
|
812
|
-
label: this
|
|
822
|
+
label: this.fabric.label,
|
|
813
823
|
fabricIndex,
|
|
814
824
|
}),
|
|
815
825
|
);
|
|
@@ -820,7 +830,7 @@ export class ControllerCommissioningFlow {
|
|
|
820
830
|
|
|
821
831
|
return {
|
|
822
832
|
code: CommissioningStepResultCode.Success,
|
|
823
|
-
breadcrumb: this
|
|
833
|
+
breadcrumb: this.lastBreadcrumb,
|
|
824
834
|
};
|
|
825
835
|
}
|
|
826
836
|
|
|
@@ -836,7 +846,7 @@ export class ControllerCommissioningFlow {
|
|
|
836
846
|
|
|
837
847
|
return {
|
|
838
848
|
code: CommissioningStepResultCode.Skipped,
|
|
839
|
-
breadcrumb: this
|
|
849
|
+
breadcrumb: this.lastBreadcrumb,
|
|
840
850
|
};
|
|
841
851
|
}
|
|
842
852
|
|
|
@@ -855,24 +865,28 @@ export class ControllerCommissioningFlow {
|
|
|
855
865
|
*/
|
|
856
866
|
async #validateNetwork() {
|
|
857
867
|
if (
|
|
858
|
-
this
|
|
859
|
-
this
|
|
868
|
+
this.collectedCommissioningData.networkFeatures === undefined ||
|
|
869
|
+
this.collectedCommissioningData.networkStatus === undefined
|
|
860
870
|
) {
|
|
861
871
|
throw new CommissioningError("No network features or status collected. This should never happen.");
|
|
862
872
|
}
|
|
863
873
|
if (
|
|
864
|
-
this
|
|
865
|
-
|
|
874
|
+
(this.commissioningOptions.wifiNetwork === undefined ||
|
|
875
|
+
!this.commissioningOptions.wifiNetwork.wifiSsid ||
|
|
876
|
+
!this.commissioningOptions.wifiNetwork.wifiCredentials) &&
|
|
877
|
+
(this.commissioningOptions.threadNetwork === undefined ||
|
|
878
|
+
!this.commissioningOptions.threadNetwork.networkName ||
|
|
879
|
+
!this.commissioningOptions.threadNetwork.operationalDataset)
|
|
866
880
|
) {
|
|
867
881
|
// Check if we have no networkCommissioning cluster or an Ethernet one
|
|
868
882
|
const anyEthernetInterface =
|
|
869
|
-
this
|
|
870
|
-
this
|
|
883
|
+
this.collectedCommissioningData.networkFeatures.length === 0 ||
|
|
884
|
+
this.collectedCommissioningData.networkFeatures.some(
|
|
871
885
|
({ value: { ethernetNetworkInterface } }) => ethernetNetworkInterface === true,
|
|
872
886
|
);
|
|
873
887
|
const anyInterfaceConnected =
|
|
874
|
-
this
|
|
875
|
-
this
|
|
888
|
+
this.collectedCommissioningData.networkStatus.length === 0 ||
|
|
889
|
+
this.collectedCommissioningData.networkStatus.some(({ value }) =>
|
|
876
890
|
value.some(({ connected }) => connected),
|
|
877
891
|
);
|
|
878
892
|
if (!anyEthernetInterface && !anyInterfaceConnected) {
|
|
@@ -884,46 +898,46 @@ export class ControllerCommissioningFlow {
|
|
|
884
898
|
|
|
885
899
|
return {
|
|
886
900
|
code: CommissioningStepResultCode.Success,
|
|
887
|
-
breadcrumb: this
|
|
901
|
+
breadcrumb: this.lastBreadcrumb,
|
|
888
902
|
};
|
|
889
903
|
}
|
|
890
904
|
|
|
891
905
|
async #configureNetworkWifi() {
|
|
892
|
-
if (this
|
|
906
|
+
if (this.commissioningOptions.wifiNetwork === undefined) {
|
|
893
907
|
logger.debug("WiFi network is not configured");
|
|
894
908
|
return {
|
|
895
909
|
code: CommissioningStepResultCode.Skipped,
|
|
896
|
-
breadcrumb: this
|
|
910
|
+
breadcrumb: this.lastBreadcrumb,
|
|
897
911
|
};
|
|
898
912
|
}
|
|
899
913
|
if (
|
|
900
|
-
this
|
|
901
|
-
this
|
|
914
|
+
this.collectedCommissioningData.networkFeatures !== undefined &&
|
|
915
|
+
this.collectedCommissioningData.networkStatus !== undefined
|
|
902
916
|
) {
|
|
903
|
-
const rootNetworkFeatures = this
|
|
917
|
+
const rootNetworkFeatures = this.collectedCommissioningData.networkFeatures.find(
|
|
904
918
|
({ endpointId }) => endpointId === 0,
|
|
905
919
|
)?.value;
|
|
906
|
-
const rootNetworkStatus = this
|
|
920
|
+
const rootNetworkStatus = this.collectedCommissioningData.networkStatus.find(
|
|
907
921
|
({ endpointId }) => endpointId === 0,
|
|
908
922
|
)?.value;
|
|
909
923
|
|
|
910
924
|
logger.debug(
|
|
911
|
-
`Root Networks found: ${
|
|
925
|
+
`Root Networks found: ${Diagnostic.json(rootNetworkFeatures)} - ${Diagnostic.json(rootNetworkStatus)}`,
|
|
912
926
|
);
|
|
913
927
|
|
|
914
928
|
if (rootNetworkFeatures?.wiFiNetworkInterface !== true) {
|
|
915
929
|
logger.debug("Commissionee does not support any WiFi network interface");
|
|
916
930
|
return {
|
|
917
931
|
code: CommissioningStepResultCode.Skipped,
|
|
918
|
-
breadcrumb: this
|
|
932
|
+
breadcrumb: this.lastBreadcrumb,
|
|
919
933
|
};
|
|
920
934
|
}
|
|
921
935
|
if (rootNetworkStatus !== undefined && rootNetworkStatus.length > 0 && rootNetworkStatus[0].connected) {
|
|
922
936
|
logger.debug("Commissionee is already connected to the WiFi network");
|
|
923
|
-
this
|
|
937
|
+
this.collectedCommissioningData.successfullyConnectedToNetwork = true;
|
|
924
938
|
return {
|
|
925
939
|
code: CommissioningStepResultCode.Skipped,
|
|
926
|
-
breadcrumb: this
|
|
940
|
+
breadcrumb: this.lastBreadcrumb,
|
|
927
941
|
};
|
|
928
942
|
}
|
|
929
943
|
}
|
|
@@ -934,13 +948,13 @@ export class ControllerCommissioningFlow {
|
|
|
934
948
|
EndpointNumber(0),
|
|
935
949
|
true,
|
|
936
950
|
);
|
|
937
|
-
const ssid = Bytes.fromString(this
|
|
938
|
-
const credentials = Bytes.fromString(this
|
|
951
|
+
const ssid = Bytes.fromString(this.commissioningOptions.wifiNetwork.wifiSsid);
|
|
952
|
+
const credentials = Bytes.fromString(this.commissioningOptions.wifiNetwork.wifiCredentials);
|
|
939
953
|
|
|
940
954
|
const { networkingStatus, wiFiScanResults, debugText } = await networkCommissioningClusterClient.scanNetworks(
|
|
941
955
|
{
|
|
942
956
|
ssid,
|
|
943
|
-
breadcrumb: this
|
|
957
|
+
breadcrumb: this.lastBreadcrumb++,
|
|
944
958
|
},
|
|
945
959
|
{ useExtendedFailSafeMessageResponseTimeout: true },
|
|
946
960
|
);
|
|
@@ -949,7 +963,7 @@ export class ControllerCommissioningFlow {
|
|
|
949
963
|
}
|
|
950
964
|
if (wiFiScanResults === undefined || wiFiScanResults.length === 0) {
|
|
951
965
|
throw new CommissioningError(
|
|
952
|
-
`Commissionee did not return any WiFi networks for the requested SSID ${this
|
|
966
|
+
`Commissionee did not return any WiFi networks for the requested SSID ${this.commissioningOptions.wifiNetwork.wifiSsid}`,
|
|
953
967
|
);
|
|
954
968
|
}
|
|
955
969
|
|
|
@@ -961,7 +975,7 @@ export class ControllerCommissioningFlow {
|
|
|
961
975
|
{
|
|
962
976
|
ssid,
|
|
963
977
|
credentials,
|
|
964
|
-
breadcrumb: this
|
|
978
|
+
breadcrumb: this.lastBreadcrumb++,
|
|
965
979
|
},
|
|
966
980
|
{ useExtendedFailSafeMessageResponseTimeout: true },
|
|
967
981
|
);
|
|
@@ -972,7 +986,7 @@ export class ControllerCommissioningFlow {
|
|
|
972
986
|
throw new CommissioningError(`Commissionee did not return network index`);
|
|
973
987
|
}
|
|
974
988
|
logger.debug(
|
|
975
|
-
`Commissionee added WiFi network ${this
|
|
989
|
+
`Commissionee added WiFi network ${this.commissioningOptions.wifiNetwork.wifiSsid} with network index ${networkIndex}`,
|
|
976
990
|
);
|
|
977
991
|
|
|
978
992
|
const updatedNetworks = await networkCommissioningClusterClient.getNetworksAttribute();
|
|
@@ -981,22 +995,22 @@ export class ControllerCommissioningFlow {
|
|
|
981
995
|
}
|
|
982
996
|
const { networkId, connected } = updatedNetworks[networkIndex];
|
|
983
997
|
if (connected) {
|
|
984
|
-
this
|
|
998
|
+
this.collectedCommissioningData.successfullyConnectedToNetwork = true;
|
|
985
999
|
logger.debug(
|
|
986
1000
|
`Commissionee is already connected to WiFi network ${
|
|
987
|
-
this
|
|
1001
|
+
this.commissioningOptions.wifiNetwork.wifiSsid
|
|
988
1002
|
} (networkId ${Bytes.toHex(networkId)})`,
|
|
989
1003
|
);
|
|
990
1004
|
return {
|
|
991
1005
|
code: CommissioningStepResultCode.Success,
|
|
992
|
-
breadcrumb: this
|
|
1006
|
+
breadcrumb: this.lastBreadcrumb,
|
|
993
1007
|
};
|
|
994
1008
|
}
|
|
995
1009
|
|
|
996
1010
|
const connectResult = await networkCommissioningClusterClient.connectNetwork(
|
|
997
1011
|
{
|
|
998
1012
|
networkId: networkId,
|
|
999
|
-
breadcrumb: this
|
|
1013
|
+
breadcrumb: this.lastBreadcrumb++,
|
|
1000
1014
|
},
|
|
1001
1015
|
{ useExtendedFailSafeMessageResponseTimeout: true },
|
|
1002
1016
|
);
|
|
@@ -1004,61 +1018,61 @@ export class ControllerCommissioningFlow {
|
|
|
1004
1018
|
if (connectResult.networkingStatus !== NetworkCommissioning.NetworkCommissioningStatus.Success) {
|
|
1005
1019
|
throw new CommissioningError(`Commissionee failed to connect to WiFi network: ${connectResult.debugText}`);
|
|
1006
1020
|
}
|
|
1007
|
-
this
|
|
1021
|
+
this.collectedCommissioningData.successfullyConnectedToNetwork = true;
|
|
1008
1022
|
logger.debug(
|
|
1009
1023
|
`Commissionee successfully connected to WiFi network ${
|
|
1010
|
-
this
|
|
1024
|
+
this.commissioningOptions.wifiNetwork.wifiSsid
|
|
1011
1025
|
} (networkId ${Bytes.toHex(networkId)})`,
|
|
1012
1026
|
);
|
|
1013
1027
|
|
|
1014
1028
|
return {
|
|
1015
1029
|
code: CommissioningStepResultCode.Success,
|
|
1016
|
-
breadcrumb: this
|
|
1030
|
+
breadcrumb: this.lastBreadcrumb,
|
|
1017
1031
|
};
|
|
1018
1032
|
}
|
|
1019
1033
|
|
|
1020
1034
|
async #configureNetworkThread() {
|
|
1021
|
-
if (this
|
|
1022
|
-
logger.
|
|
1035
|
+
if (this.collectedCommissioningData.successfullyConnectedToNetwork) {
|
|
1036
|
+
logger.info("Node is already connected to a network. Skipping Thread configuration.");
|
|
1023
1037
|
return {
|
|
1024
1038
|
code: CommissioningStepResultCode.Skipped,
|
|
1025
|
-
breadcrumb: this
|
|
1039
|
+
breadcrumb: this.lastBreadcrumb,
|
|
1026
1040
|
};
|
|
1027
1041
|
}
|
|
1028
|
-
if (this
|
|
1042
|
+
if (this.commissioningOptions.threadNetwork === undefined) {
|
|
1029
1043
|
logger.debug("Thread network is not configured");
|
|
1030
1044
|
return {
|
|
1031
1045
|
code: CommissioningStepResultCode.Skipped,
|
|
1032
|
-
breadcrumb: this
|
|
1046
|
+
breadcrumb: this.lastBreadcrumb,
|
|
1033
1047
|
};
|
|
1034
1048
|
}
|
|
1035
1049
|
if (
|
|
1036
|
-
this
|
|
1037
|
-
this
|
|
1050
|
+
this.collectedCommissioningData.networkFeatures !== undefined &&
|
|
1051
|
+
this.collectedCommissioningData.networkStatus !== undefined
|
|
1038
1052
|
) {
|
|
1039
|
-
const rootNetworkFeatures = this
|
|
1053
|
+
const rootNetworkFeatures = this.collectedCommissioningData.networkFeatures.find(
|
|
1040
1054
|
({ endpointId }) => endpointId === 0,
|
|
1041
1055
|
)?.value;
|
|
1042
|
-
const rootNetworkStatus = this
|
|
1056
|
+
const rootNetworkStatus = this.collectedCommissioningData.networkStatus.find(
|
|
1043
1057
|
({ endpointId }) => endpointId === 0,
|
|
1044
1058
|
)?.value;
|
|
1045
1059
|
|
|
1046
1060
|
logger.debug(
|
|
1047
|
-
`Root Networks found: ${
|
|
1061
|
+
`Root Networks found: ${Diagnostic.json(rootNetworkFeatures)} - ${Diagnostic.json(rootNetworkStatus)}`,
|
|
1048
1062
|
);
|
|
1049
1063
|
|
|
1050
1064
|
if (rootNetworkFeatures?.threadNetworkInterface !== true) {
|
|
1051
1065
|
logger.debug("Commissionee does not support any Thread network interface");
|
|
1052
1066
|
return {
|
|
1053
1067
|
code: CommissioningStepResultCode.Skipped,
|
|
1054
|
-
breadcrumb: this
|
|
1068
|
+
breadcrumb: this.lastBreadcrumb,
|
|
1055
1069
|
};
|
|
1056
1070
|
}
|
|
1057
1071
|
if (rootNetworkStatus !== undefined && rootNetworkStatus.length > 0 && rootNetworkStatus[0].connected) {
|
|
1058
1072
|
logger.debug("Commissionee is already connected to the Thread network");
|
|
1059
1073
|
return {
|
|
1060
1074
|
code: CommissioningStepResultCode.Skipped,
|
|
1061
|
-
breadcrumb: this
|
|
1075
|
+
breadcrumb: this.lastBreadcrumb,
|
|
1062
1076
|
};
|
|
1063
1077
|
}
|
|
1064
1078
|
}
|
|
@@ -1071,7 +1085,7 @@ export class ControllerCommissioningFlow {
|
|
|
1071
1085
|
);
|
|
1072
1086
|
|
|
1073
1087
|
const { networkingStatus, threadScanResults, debugText } = await networkCommissioningClusterClient.scanNetworks(
|
|
1074
|
-
{ breadcrumb: this
|
|
1088
|
+
{ breadcrumb: this.lastBreadcrumb++ },
|
|
1075
1089
|
{ useExtendedFailSafeMessageResponseTimeout: true },
|
|
1076
1090
|
);
|
|
1077
1091
|
if (networkingStatus !== NetworkCommissioning.NetworkCommissioningStatus.Success) {
|
|
@@ -1079,23 +1093,23 @@ export class ControllerCommissioningFlow {
|
|
|
1079
1093
|
}
|
|
1080
1094
|
if (threadScanResults === undefined || threadScanResults.length === 0) {
|
|
1081
1095
|
throw new CommissioningError(
|
|
1082
|
-
`Commissionee did not return any Thread networks for the requested Network ${this
|
|
1096
|
+
`Commissionee did not return any Thread networks for the requested Network ${this.commissioningOptions.threadNetwork.networkName}`,
|
|
1083
1097
|
);
|
|
1084
1098
|
}
|
|
1085
1099
|
const wantedNetworkFound = threadScanResults.find(
|
|
1086
|
-
({ networkName }) => networkName === this
|
|
1100
|
+
({ networkName }) => networkName === this.commissioningOptions.threadNetwork?.networkName,
|
|
1087
1101
|
);
|
|
1088
1102
|
if (wantedNetworkFound === undefined) {
|
|
1089
1103
|
throw new CommissioningError(
|
|
1090
1104
|
`Commissionee did not return the requested Network ${
|
|
1091
|
-
this
|
|
1092
|
-
}: ${
|
|
1105
|
+
this.commissioningOptions.threadNetwork.networkName
|
|
1106
|
+
}: ${Diagnostic.json(threadScanResults)}`,
|
|
1093
1107
|
);
|
|
1094
1108
|
}
|
|
1095
1109
|
logger.debug(
|
|
1096
1110
|
`Commissionee found wanted Thread network ${
|
|
1097
|
-
this
|
|
1098
|
-
}: ${
|
|
1111
|
+
this.commissioningOptions.threadNetwork.networkName
|
|
1112
|
+
}: ${Diagnostic.json(wantedNetworkFound)}`,
|
|
1099
1113
|
);
|
|
1100
1114
|
|
|
1101
1115
|
const {
|
|
@@ -1104,8 +1118,8 @@ export class ControllerCommissioningFlow {
|
|
|
1104
1118
|
networkIndex,
|
|
1105
1119
|
} = await networkCommissioningClusterClient.addOrUpdateThreadNetwork(
|
|
1106
1120
|
{
|
|
1107
|
-
operationalDataset: Bytes.fromHex(this
|
|
1108
|
-
breadcrumb: this
|
|
1121
|
+
operationalDataset: Bytes.fromHex(this.commissioningOptions.threadNetwork.operationalDataset),
|
|
1122
|
+
breadcrumb: this.lastBreadcrumb++,
|
|
1109
1123
|
},
|
|
1110
1124
|
{ useExtendedFailSafeMessageResponseTimeout: true },
|
|
1111
1125
|
);
|
|
@@ -1116,7 +1130,7 @@ export class ControllerCommissioningFlow {
|
|
|
1116
1130
|
throw new CommissioningError(`Commissionee did not return network index`);
|
|
1117
1131
|
}
|
|
1118
1132
|
logger.debug(
|
|
1119
|
-
`Commissionee added Thread network ${this
|
|
1133
|
+
`Commissionee added Thread network ${this.commissioningOptions.threadNetwork.networkName} with network index ${networkIndex}`,
|
|
1120
1134
|
);
|
|
1121
1135
|
|
|
1122
1136
|
const updatedNetworks = await networkCommissioningClusterClient.getNetworksAttribute();
|
|
@@ -1127,19 +1141,19 @@ export class ControllerCommissioningFlow {
|
|
|
1127
1141
|
if (connected) {
|
|
1128
1142
|
logger.debug(
|
|
1129
1143
|
`Commissionee is already connected to Thread network ${
|
|
1130
|
-
this
|
|
1144
|
+
this.commissioningOptions.threadNetwork.networkName
|
|
1131
1145
|
} (networkId ${Bytes.toHex(networkId)})`,
|
|
1132
1146
|
);
|
|
1133
1147
|
return {
|
|
1134
1148
|
code: CommissioningStepResultCode.Success,
|
|
1135
|
-
breadcrumb: this
|
|
1149
|
+
breadcrumb: this.lastBreadcrumb,
|
|
1136
1150
|
};
|
|
1137
1151
|
}
|
|
1138
1152
|
|
|
1139
1153
|
const connectResult = await networkCommissioningClusterClient.connectNetwork(
|
|
1140
1154
|
{
|
|
1141
1155
|
networkId: networkId,
|
|
1142
|
-
breadcrumb: this
|
|
1156
|
+
breadcrumb: this.lastBreadcrumb++,
|
|
1143
1157
|
},
|
|
1144
1158
|
{ useExtendedFailSafeMessageResponseTimeout: true },
|
|
1145
1159
|
);
|
|
@@ -1151,13 +1165,13 @@ export class ControllerCommissioningFlow {
|
|
|
1151
1165
|
}
|
|
1152
1166
|
logger.debug(
|
|
1153
1167
|
`Commissionee successfully connected to Thread network ${
|
|
1154
|
-
this
|
|
1168
|
+
this.commissioningOptions.threadNetwork.networkName
|
|
1155
1169
|
} (networkId ${Bytes.toHex(networkId)})`,
|
|
1156
1170
|
);
|
|
1157
1171
|
|
|
1158
1172
|
return {
|
|
1159
1173
|
code: CommissioningStepResultCode.Success,
|
|
1160
|
-
breadcrumb: this
|
|
1174
|
+
breadcrumb: this.lastBreadcrumb,
|
|
1161
1175
|
};
|
|
1162
1176
|
}
|
|
1163
1177
|
|
|
@@ -1170,7 +1184,7 @@ export class ControllerCommissioningFlow {
|
|
|
1170
1184
|
* (CASE)”) session with the Commissionee over the operational network.
|
|
1171
1185
|
*/
|
|
1172
1186
|
async #reconnectWithDevice() {
|
|
1173
|
-
const isConcurrentFlow = this
|
|
1187
|
+
const isConcurrentFlow = this.collectedCommissioningData.supportsConcurrentConnection !== false;
|
|
1174
1188
|
|
|
1175
1189
|
logger.debug(`Reconnecting with device with ${isConcurrentFlow ? "concurrent" : "non-concurrent"} flow ...`);
|
|
1176
1190
|
|
|
@@ -1201,8 +1215,8 @@ export class ControllerCommissioningFlow {
|
|
|
1201
1215
|
reArmFailsafeInterval.start();
|
|
1202
1216
|
}
|
|
1203
1217
|
|
|
1204
|
-
const transitionResult = await this
|
|
1205
|
-
this
|
|
1218
|
+
const transitionResult = await this.transitionToCase(
|
|
1219
|
+
this.interactionClient.address,
|
|
1206
1220
|
// Assume concurrent connections are supported if not know (which should not be the case when we came here)
|
|
1207
1221
|
isConcurrentFlow,
|
|
1208
1222
|
);
|
|
@@ -1213,18 +1227,18 @@ export class ControllerCommissioningFlow {
|
|
|
1213
1227
|
logger.debug("CASE commissioning handled externally, terminating commissioning flow");
|
|
1214
1228
|
return {
|
|
1215
1229
|
code: CommissioningStepResultCode.Stop,
|
|
1216
|
-
breadcrumb: this
|
|
1230
|
+
breadcrumb: this.lastBreadcrumb,
|
|
1217
1231
|
};
|
|
1218
1232
|
}
|
|
1219
1233
|
|
|
1220
|
-
this
|
|
1234
|
+
this.interactionClient = transitionResult;
|
|
1221
1235
|
this.#clusterClients.clear();
|
|
1222
1236
|
|
|
1223
1237
|
logger.debug("Successfully reconnected with device ...");
|
|
1224
1238
|
|
|
1225
1239
|
return {
|
|
1226
1240
|
code: CommissioningStepResultCode.Success,
|
|
1227
|
-
breadcrumb: this
|
|
1241
|
+
breadcrumb: this.lastBreadcrumb,
|
|
1228
1242
|
};
|
|
1229
1243
|
}
|
|
1230
1244
|
|
|
@@ -1247,7 +1261,7 @@ export class ControllerCommissioningFlow {
|
|
|
1247
1261
|
|
|
1248
1262
|
return {
|
|
1249
1263
|
code: CommissioningStepResultCode.Success,
|
|
1250
|
-
breadcrumb: this
|
|
1264
|
+
breadcrumb: this.lastBreadcrumb,
|
|
1251
1265
|
};
|
|
1252
1266
|
}
|
|
1253
1267
|
}
|