zwave-js 13.2.0 → 13.3.1

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 (48) hide show
  1. package/bin/mock-server.js +2 -0
  2. package/build/lib/controller/Controller.d.ts +119 -9
  3. package/build/lib/controller/Controller.d.ts.map +1 -1
  4. package/build/lib/controller/Controller.js +1187 -81
  5. package/build/lib/controller/Controller.js.map +1 -1
  6. package/build/lib/controller/Inclusion.d.ts +44 -0
  7. package/build/lib/controller/Inclusion.d.ts.map +1 -1
  8. package/build/lib/controller/Inclusion.js +42 -1
  9. package/build/lib/controller/Inclusion.js.map +1 -1
  10. package/build/lib/driver/Driver.d.ts +16 -1
  11. package/build/lib/driver/Driver.d.ts.map +1 -1
  12. package/build/lib/driver/Driver.js +290 -97
  13. package/build/lib/driver/Driver.js.map +1 -1
  14. package/build/lib/driver/NetworkCache.d.ts +3 -0
  15. package/build/lib/driver/NetworkCache.d.ts.map +1 -1
  16. package/build/lib/driver/NetworkCache.js +37 -9
  17. package/build/lib/driver/NetworkCache.js.map +1 -1
  18. package/build/lib/driver/ZWaveOptions.d.ts +10 -3
  19. package/build/lib/driver/ZWaveOptions.d.ts.map +1 -1
  20. package/build/lib/driver/ZWaveOptions.js.map +1 -1
  21. package/build/lib/node/Node.d.ts +4 -3
  22. package/build/lib/node/Node.d.ts.map +1 -1
  23. package/build/lib/node/Node.js +130 -34
  24. package/build/lib/node/Node.js.map +1 -1
  25. package/build/lib/serialapi/application/ApplicationUpdateRequest.d.ts +5 -0
  26. package/build/lib/serialapi/application/ApplicationUpdateRequest.d.ts.map +1 -1
  27. package/build/lib/serialapi/application/ApplicationUpdateRequest.js +24 -1
  28. package/build/lib/serialapi/application/ApplicationUpdateRequest.js.map +1 -1
  29. package/build/lib/serialapi/capability/GetControllerCapabilitiesMessages.d.ts +2 -0
  30. package/build/lib/serialapi/capability/GetControllerCapabilitiesMessages.d.ts.map +1 -1
  31. package/build/lib/serialapi/capability/GetControllerCapabilitiesMessages.js +6 -0
  32. package/build/lib/serialapi/capability/GetControllerCapabilitiesMessages.js.map +1 -1
  33. package/build/lib/serialapi/capability/GetSerialApiInitDataMessages.d.ts +2 -9
  34. package/build/lib/serialapi/capability/GetSerialApiInitDataMessages.d.ts.map +1 -1
  35. package/build/lib/serialapi/capability/GetSerialApiInitDataMessages.js.map +1 -1
  36. package/build/lib/serialapi/capability/SerialAPISetupMessages.d.ts +27 -1
  37. package/build/lib/serialapi/capability/SerialAPISetupMessages.d.ts.map +1 -1
  38. package/build/lib/serialapi/capability/SerialAPISetupMessages.js +96 -1
  39. package/build/lib/serialapi/capability/SerialAPISetupMessages.js.map +1 -1
  40. package/build/lib/serialapi/network-mgmt/SetLearnModeMessages.d.ts +47 -0
  41. package/build/lib/serialapi/network-mgmt/SetLearnModeMessages.d.ts.map +1 -0
  42. package/build/lib/serialapi/network-mgmt/SetLearnModeMessages.js +137 -0
  43. package/build/lib/serialapi/network-mgmt/SetLearnModeMessages.js.map +1 -0
  44. package/build/lib/serialapi/nvm/ExtendedNVMOperationsMessages.d.ts +60 -0
  45. package/build/lib/serialapi/nvm/ExtendedNVMOperationsMessages.d.ts.map +1 -0
  46. package/build/lib/serialapi/nvm/ExtendedNVMOperationsMessages.js +201 -0
  47. package/build/lib/serialapi/nvm/ExtendedNVMOperationsMessages.js.map +1 -0
  48. package/package.json +9 -9
@@ -2970,7 +2970,10 @@ protocol version: ${this.protocolVersion}`;
2970
2970
  }
2971
2971
  async handleZWavePlusGet(command) {
2972
2972
  const endpoint = this.getEndpoint(command.endpointIndex) ?? this;
2973
- await endpoint.commandClasses["Z-Wave Plus Info"]
2973
+ // We are being queried, so the device may actually not support the CC, just control it.
2974
+ // Using the commandClasses property would throw in that case
2975
+ await endpoint
2976
+ .createAPI(core_1.CommandClasses["Z-Wave Plus Info"], false)
2974
2977
  .withOptions({
2975
2978
  // Answer with the same encapsulation as asked, but omit
2976
2979
  // Supervision as it shouldn't be used for Get-Report flows
@@ -4052,6 +4055,9 @@ protocol version: ${this.protocolVersion}`;
4052
4055
  return this._firmwareUpdateInProgress;
4053
4056
  }
4054
4057
  }
4058
+ // Stores the CRC of the previously transferred firmware image.
4059
+ // Allows detecting whether resuming is supported and where to continue in a multi-file transfer.
4060
+ _previousFirmwareCRC;
4055
4061
  _abortFirmwareUpdate;
4056
4062
  /** Is used to remember fragment requests that came in before they were able to be handled */
4057
4063
  _firmwareUpdatePrematureRequest;
@@ -4064,6 +4070,8 @@ protocol version: ${this.protocolVersion}`;
4064
4070
  const supportsActivation = this.getValue(FirmwareUpdateMetaDataCC_1.FirmwareUpdateMetaDataCCValues.supportsActivation.id);
4065
4071
  const continuesToFunction = this.getValue(FirmwareUpdateMetaDataCC_1.FirmwareUpdateMetaDataCCValues.continuesToFunction.id);
4066
4072
  const additionalFirmwareIDs = this.getValue(FirmwareUpdateMetaDataCC_1.FirmwareUpdateMetaDataCCValues.additionalFirmwareIDs.id);
4073
+ const supportsResuming = this.getValue(FirmwareUpdateMetaDataCC_1.FirmwareUpdateMetaDataCCValues.supportsResuming.id);
4074
+ const supportsNonSecureTransfer = this.getValue(FirmwareUpdateMetaDataCC_1.FirmwareUpdateMetaDataCCValues.supportsNonSecureTransfer.id);
4067
4075
  // Ensure all information was queried
4068
4076
  if (!firmwareUpgradable
4069
4077
  || !(0, typeguards_1.isArray)(additionalFirmwareIDs)) {
@@ -4076,6 +4084,8 @@ protocol version: ${this.protocolVersion}`;
4076
4084
  .map((_, i) => i),
4077
4085
  continuesToFunction,
4078
4086
  supportsActivation,
4087
+ supportsResuming,
4088
+ supportsNonSecureTransfer,
4079
4089
  };
4080
4090
  }
4081
4091
  /**
@@ -4100,6 +4110,8 @@ protocol version: ${this.protocolVersion}`;
4100
4110
  .fill(0).map((_, i) => i),
4101
4111
  continuesToFunction: meta.continuesToFunction,
4102
4112
  supportsActivation: meta.supportsActivation,
4113
+ supportsResuming: meta.supportsResuming,
4114
+ supportsNonSecureTransfer: meta.supportsNonSecureTransfer,
4103
4115
  };
4104
4116
  }
4105
4117
  /**
@@ -4113,7 +4125,7 @@ protocol version: ${this.protocolVersion}`;
4113
4125
  *
4114
4126
  * @returns Whether all of the given updates were successful.
4115
4127
  */
4116
- async updateFirmware(updates) {
4128
+ async updateFirmware(updates, options = {}) {
4117
4129
  if (updates.length === 0) {
4118
4130
  throw new core_1.ZWaveError(`At least one update must be provided`, core_1.ZWaveErrorCodes.Argument_Invalid);
4119
4131
  }
@@ -4170,7 +4182,8 @@ protocol version: ${this.protocolVersion}`;
4170
4182
  this._firmwareUpdatePrematureRequest = undefined;
4171
4183
  };
4172
4184
  // Prepare the firmware update
4173
- let fragmentSize;
4185
+ let fragmentSizeSecure;
4186
+ let fragmentSizeNonSecure;
4174
4187
  let meta;
4175
4188
  try {
4176
4189
  const prepareResult = await this.prepareFirmwareUpdateInternal(updates.map((u) => u.firmwareTarget ?? 0), abortContext);
@@ -4186,7 +4199,8 @@ protocol version: ${this.protocolVersion}`;
4186
4199
  return result;
4187
4200
  }
4188
4201
  // If the firmware update was not aborted, prepareResult is definitely defined
4189
- ({ fragmentSize, ...meta } = prepareResult);
4202
+ ({ fragmentSizeSecure, fragmentSizeNonSecure, ...meta } =
4203
+ prepareResult);
4190
4204
  }
4191
4205
  catch {
4192
4206
  restore(false);
@@ -4198,33 +4212,84 @@ protocol version: ${this.protocolVersion}`;
4198
4212
  };
4199
4213
  return result;
4200
4214
  }
4215
+ // The resume and non-secure transfer features may not be supported by the node
4216
+ // If not, disable them, even though the application requested them
4217
+ if (!meta.supportsResuming)
4218
+ options.resume = false;
4219
+ const securityClass = this.getHighestSecurityClass();
4220
+ const isSecure = securityClass === core_1.SecurityClass.S0_Legacy
4221
+ || (0, core_1.securityClassIsS2)(securityClass);
4222
+ if (!isSecure) {
4223
+ // The nonSecureTransfer option is only relevant for secure devices
4224
+ options.nonSecureTransfer = false;
4225
+ }
4226
+ else if (!meta.supportsNonSecureTransfer) {
4227
+ options.nonSecureTransfer = false;
4228
+ }
4201
4229
  // Throttle the progress emitter so applications can handle the load of events
4202
4230
  const notifyProgress = (0, shared_1.throttle)((progress) => this.emit("firmware update progress", this, progress), 250, true);
4231
+ // If resuming is supported and desired, try to figure out with which file to continue
4232
+ const updatesWithChecksum = updates.map((u) => ({
4233
+ ...u,
4234
+ checksum: (0, core_1.CRC16_CCITT)(u.data),
4235
+ }));
4236
+ let skipFinishedFiles = -1;
4237
+ let shouldResume = options.resume
4238
+ && this._previousFirmwareCRC != undefined;
4239
+ if (shouldResume) {
4240
+ skipFinishedFiles = updatesWithChecksum.findIndex((u) => u.checksum === this._previousFirmwareCRC);
4241
+ if (skipFinishedFiles === -1)
4242
+ shouldResume = false;
4243
+ }
4203
4244
  // Perform all firmware updates in sequence
4204
4245
  let updateResult;
4205
4246
  let conservativeWaitTime;
4206
- const totalFragments = updates.reduce((total, update) => total + Math.ceil(update.data.length / fragmentSize), 0);
4207
- let sentFragmentsOfPreviousFiles = 0;
4208
- for (let i = 0; i < updates.length; i++) {
4209
- this.driver.controllerLog.logNode(this.id, `Updating firmware (part ${i + 1} / ${updates.length})...`);
4210
- const { firmwareTarget: target = 0, data } = updates[i];
4247
+ const totalBytes = updatesWithChecksum.reduce((total, update) => total + update.data.length, 0);
4248
+ let sentBytesOfPreviousFiles = 0;
4249
+ for (let i = 0; i < updatesWithChecksum.length; i++) {
4250
+ const { firmwareTarget: target = 0, data, checksum } = updatesWithChecksum[i];
4251
+ if (i < skipFinishedFiles) {
4252
+ // If we are resuming, skip this file since it was already done before
4253
+ this.driver.controllerLog.logNode(this.id, `Skipping already completed firmware update (part ${i + 1} / ${updatesWithChecksum.length})...`);
4254
+ sentBytesOfPreviousFiles += data.length;
4255
+ continue;
4256
+ }
4257
+ this.driver.controllerLog.logNode(this.id, `Updating firmware (part ${i + 1} / ${updatesWithChecksum.length})...`);
4258
+ // For determining the initial fragment size, assume the node respects our choice.
4259
+ // If the node is not secure, these two values are identical anyways.
4260
+ let fragmentSize = options.nonSecureTransfer
4261
+ ? fragmentSizeNonSecure
4262
+ : fragmentSizeSecure;
4211
4263
  // Tell the node to start requesting fragments
4212
- await this.beginFirmwareUpdateInternal(data, target, meta, fragmentSize);
4264
+ const { resume, nonSecureTransfer } = await this
4265
+ .beginFirmwareUpdateInternal(data, target, meta, fragmentSize, checksum, shouldResume, options.nonSecureTransfer);
4266
+ // If the node did not accept non-secure transfer, revisit our choice of fragment size
4267
+ if (options.nonSecureTransfer && !nonSecureTransfer) {
4268
+ fragmentSize = fragmentSizeSecure;
4269
+ }
4270
+ // Remember the checksum, so we can resume if necessary
4271
+ this._previousFirmwareCRC = checksum;
4272
+ if (shouldResume) {
4273
+ this.driver.controllerLog.logNode(this.id, `Node ${resume ? "accepted" : "did not accept"} resuming the update...`);
4274
+ }
4275
+ if (nonSecureTransfer) {
4276
+ this.driver.controllerLog.logNode(this.id, `Firmware will be transferred without encryption...`);
4277
+ }
4213
4278
  // And handle them
4214
- updateResult = await this.doFirmwareUpdateInternal(data, fragmentSize, abortContext, (fragment, total) => {
4279
+ updateResult = await this.doFirmwareUpdateInternal(data, fragmentSize, nonSecureTransfer, abortContext, (fragment, total) => {
4215
4280
  const progress = {
4216
4281
  currentFile: i + 1,
4217
- totalFiles: updates.length,
4282
+ totalFiles: updatesWithChecksum.length,
4218
4283
  sentFragments: fragment,
4219
4284
  totalFragments: total,
4220
- progress: (0, math_1.roundTo)(((sentFragmentsOfPreviousFiles + fragment)
4221
- / totalFragments)
4222
- * 100, 2),
4285
+ progress: (0, math_1.roundTo)(((sentBytesOfPreviousFiles
4286
+ + Math.min(fragment * fragmentSize, data.length))
4287
+ / totalBytes) * 100, 2),
4223
4288
  };
4224
4289
  notifyProgress(progress);
4225
4290
  // When this file is done, add the fragments to the total, so we can compute the total progress correctly
4226
4291
  if (fragment === total) {
4227
- sentFragmentsOfPreviousFiles += fragment;
4292
+ sentBytesOfPreviousFiles += data.length;
4228
4293
  }
4229
4294
  });
4230
4295
  // If we wait, wait a bit longer than the device told us, so it is actually ready to use
@@ -4232,7 +4297,7 @@ protocol version: ${this.protocolVersion}`;
4232
4297
  .getConservativeWaitTimeAfterFirmwareUpdate(updateResult.waitTime);
4233
4298
  if (!updateResult.success) {
4234
4299
  this.driver.controllerLog.logNode(this.id, {
4235
- message: `Firmware update (part ${i + 1} / ${updates.length}) failed with status ${(0, shared_1.getEnumMemberName)(cc_1.FirmwareUpdateStatus, updateResult.status)}`,
4300
+ message: `Firmware update (part ${i + 1} / ${updatesWithChecksum.length}) failed with status ${(0, shared_1.getEnumMemberName)(cc_1.FirmwareUpdateStatus, updateResult.status)}`,
4236
4301
  direction: "inbound",
4237
4302
  });
4238
4303
  const result = {
@@ -4244,16 +4309,20 @@ protocol version: ${this.protocolVersion}`;
4244
4309
  restore(false);
4245
4310
  return result;
4246
4311
  }
4247
- else if (i < updates.length - 1) {
4312
+ else if (i < updatesWithChecksum.length - 1) {
4248
4313
  // Update succeeded, but we're not done yet
4249
4314
  this.driver.controllerLog.logNode(this.id, {
4250
- message: `Firmware update (part ${i + 1} / ${updates.length}) succeeded with status ${(0, shared_1.getEnumMemberName)(cc_1.FirmwareUpdateStatus, updateResult.status)}`,
4315
+ message: `Firmware update (part ${i + 1} / ${updatesWithChecksum.length}) succeeded with status ${(0, shared_1.getEnumMemberName)(cc_1.FirmwareUpdateStatus, updateResult.status)}`,
4251
4316
  direction: "inbound",
4252
4317
  });
4253
4318
  this.driver.controllerLog.logNode(this.id, `Continuing with next part in ${conservativeWaitTime} seconds...`);
4319
+ // If we've resumed the previous file, there's no need to resume the next one too
4320
+ shouldResume = false;
4254
4321
  await (0, async_1.wait)(conservativeWaitTime * 1000, true);
4255
4322
  }
4256
4323
  }
4324
+ // We're done. No need to resume this update
4325
+ this._previousFirmwareCRC = undefined;
4257
4326
  const result = {
4258
4327
  ...updateResult,
4259
4328
  waitTime: conservativeWaitTime,
@@ -4294,21 +4363,32 @@ protocol version: ${this.protocolVersion}`;
4294
4363
  const fcc = new FirmwareUpdateMetaDataCC_1.FirmwareUpdateMetaDataCC(this.driver, {
4295
4364
  nodeId: this.id,
4296
4365
  });
4297
- const maxNetPayloadSize = this.driver.computeNetCCPayloadSize(fcc)
4366
+ const maxGrossPayloadSizeSecure = this.driver.computeNetCCPayloadSize(fcc);
4367
+ const maxGrossPayloadSizeNonSecure = this.driver
4368
+ .computeNetCCPayloadSize(fcc, true);
4369
+ const maxNetPayloadSizeSecure = maxGrossPayloadSizeSecure
4370
+ - 2 // report number
4371
+ - (fcc.version >= 2 ? 2 : 0); // checksum
4372
+ const maxNetPayloadSizeNonSecure = maxGrossPayloadSizeNonSecure
4298
4373
  - 2 // report number
4299
4374
  - (fcc.version >= 2 ? 2 : 0); // checksum
4300
4375
  // Use the smallest allowed payload
4301
- const fragmentSize = Math.min(maxNetPayloadSize, meta.maxFragmentSize ?? Number.POSITIVE_INFINITY);
4376
+ const fragmentSizeSecure = Math.min(maxNetPayloadSizeSecure, meta.maxFragmentSize ?? Number.POSITIVE_INFINITY);
4377
+ const fragmentSizeNonSecure = Math.min(maxNetPayloadSizeNonSecure, meta.maxFragmentSize ?? Number.POSITIVE_INFINITY);
4302
4378
  if (abortContext.abort) {
4303
4379
  abortContext.abortPromise.resolve(true);
4304
4380
  return;
4305
4381
  }
4306
4382
  else {
4307
- return { ...meta, fragmentSize };
4383
+ return {
4384
+ ...meta,
4385
+ fragmentSizeSecure,
4386
+ fragmentSizeNonSecure,
4387
+ };
4308
4388
  }
4309
4389
  }
4310
- /** Kicks off a firmware update of a single target */
4311
- async beginFirmwareUpdateInternal(data, target, meta, fragmentSize) {
4390
+ /** Kicks off a firmware update of a single target. Returns whether the node accepted resuming and non-secure transfer */
4391
+ async beginFirmwareUpdateInternal(data, target, meta, fragmentSize, checksum, resume, nonSecureTransfer) {
4312
4392
  const api = this.commandClasses["Firmware Update Meta Data"];
4313
4393
  // ================================
4314
4394
  // STEP 3:
@@ -4319,16 +4399,18 @@ protocol version: ${this.protocolVersion}`;
4319
4399
  });
4320
4400
  // Request the node to start the upgrade
4321
4401
  // TODO: Should manufacturer id and firmware id be provided externally?
4322
- const requestUpdateStatus = await api.requestUpdate({
4402
+ const result = await api.requestUpdate({
4323
4403
  manufacturerId: meta.manufacturerId,
4324
4404
  firmwareId: target == 0
4325
4405
  ? meta.firmwareId
4326
4406
  : meta.additionalFirmwareIDs[target - 1],
4327
4407
  firmwareTarget: target,
4328
4408
  fragmentSize,
4329
- checksum: (0, core_1.CRC16_CCITT)(data),
4409
+ checksum,
4410
+ resume,
4411
+ nonSecureTransfer,
4330
4412
  });
4331
- switch (requestUpdateStatus) {
4413
+ switch (result.status) {
4332
4414
  case cc_1.FirmwareUpdateRequestStatus.Error_AuthenticationExpected:
4333
4415
  throw new core_1.ZWaveError(`Failed to start the update: A manual authentication event (e.g. button push) was expected!`, core_1.ZWaveErrorCodes.FirmwareUpdateCC_FailedToStart);
4334
4416
  case cc_1.FirmwareUpdateRequestStatus.Error_BatteryLow:
@@ -4349,9 +4431,13 @@ protocol version: ${this.protocolVersion}`;
4349
4431
  // Keep the node awake until the update is done.
4350
4432
  this.keepAwake = true;
4351
4433
  }
4434
+ return {
4435
+ resume: !!result.resume,
4436
+ nonSecureTransfer: !!result.nonSecureTransfer,
4437
+ };
4352
4438
  }
4353
4439
  /** Performs the firmware update of a single target */
4354
- async doFirmwareUpdateInternal(data, fragmentSize, abortContext, onProgress) {
4440
+ async doFirmwareUpdateInternal(data, fragmentSize, nonSecureTransfer, abortContext, onProgress) {
4355
4441
  const numFragments = Math.ceil(data.length / fragmentSize);
4356
4442
  // Make sure we're not responding to an outdated request immediately
4357
4443
  this._firmwareUpdatePrematureRequest = undefined;
@@ -4395,7 +4481,7 @@ protocol version: ${this.protocolVersion}`;
4395
4481
  message: `Received Firmware Update Get for an out-of-bounds fragment. Forcing the node to abort...`,
4396
4482
  direction: "inbound",
4397
4483
  });
4398
- await this.sendCorruptedFirmwareUpdateReport(fragmentRequest.reportNumber, (0, node_crypto_1.randomBytes)(fragmentSize));
4484
+ await this.sendCorruptedFirmwareUpdateReport(fragmentRequest.reportNumber, (0, node_crypto_1.randomBytes)(fragmentSize), nonSecureTransfer);
4399
4485
  // This will cause the node to abort the process, wait for that
4400
4486
  break update;
4401
4487
  }
@@ -4407,7 +4493,7 @@ protocol version: ${this.protocolVersion}`;
4407
4493
  }
4408
4494
  const fragment = data.subarray((num - 1) * fragmentSize, num * fragmentSize);
4409
4495
  if (abortContext.abort) {
4410
- await this.sendCorruptedFirmwareUpdateReport(fragmentRequest.reportNumber, (0, node_crypto_1.randomBytes)(fragment.length));
4496
+ await this.sendCorruptedFirmwareUpdateReport(fragmentRequest.reportNumber, (0, node_crypto_1.randomBytes)(fragment.length), nonSecureTransfer);
4411
4497
  // This will cause the node to abort the process, wait for that
4412
4498
  break update;
4413
4499
  }
@@ -4426,7 +4512,12 @@ protocol version: ${this.protocolVersion}`;
4426
4512
  });
4427
4513
  const isLast = num === numFragments;
4428
4514
  try {
4429
- await this.commandClasses["Firmware Update Meta Data"].sendFirmwareFragment(num, isLast, fragment);
4515
+ await this.commandClasses["Firmware Update Meta Data"]
4516
+ .withOptions({
4517
+ // Only encapsulate if the transfer is secure
4518
+ autoEncapsulate: !nonSecureTransfer,
4519
+ })
4520
+ .sendFirmwareFragment(num, isLast, fragment);
4430
4521
  onProgress(num, numFragments);
4431
4522
  // If that was the last one wait for status report from the node and restart interview
4432
4523
  if (isLast) {
@@ -4485,9 +4576,14 @@ protocol version: ${this.protocolVersion}`;
4485
4576
  return;
4486
4577
  await this._abortFirmwareUpdate();
4487
4578
  }
4488
- async sendCorruptedFirmwareUpdateReport(reportNum, fragment) {
4579
+ async sendCorruptedFirmwareUpdateReport(reportNum, fragment, nonSecureTransfer = false) {
4489
4580
  try {
4490
- await this.commandClasses["Firmware Update Meta Data"].sendFirmwareFragment(reportNum, true, fragment);
4581
+ await this.commandClasses["Firmware Update Meta Data"]
4582
+ .withOptions({
4583
+ // Only encapsulate if the transfer is secure
4584
+ autoEncapsulate: !nonSecureTransfer,
4585
+ })
4586
+ .sendFirmwareFragment(reportNum, true, fragment);
4491
4587
  }
4492
4588
  catch {
4493
4589
  // ignore
@@ -5742,7 +5838,7 @@ ${(0, HealthCheck_1.formatRouteHealthCheckSummary)(this.id, otherNode.id, summar
5742
5838
  continue;
5743
5839
  ret.endpoints ??= {};
5744
5840
  const endpointDump = endpoint.createEndpointDump();
5745
- collectValues(index, (ccId) => endpointDump.commandClasses[(0, core_1.getCCName)(ccId)]?.values);
5841
+ collectValues(endpoint.index, (ccId) => endpointDump.commandClasses[(0, core_1.getCCName)(ccId)]?.values);
5746
5842
  ret.endpoints[endpoint.index] = endpointDump;
5747
5843
  }
5748
5844
  if (this.deviceConfig) {