zwave-js 8.7.7 → 8.8.0

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 (107) hide show
  1. package/build/CommandClass.js +1 -0
  2. package/build/CommandClass.js.map +1 -1
  3. package/build/Controller.d.ts +1 -0
  4. package/build/Controller.d.ts.map +1 -1
  5. package/build/Controller.js +4 -1
  6. package/build/Controller.js.map +1 -1
  7. package/build/Node.d.ts +1 -1
  8. package/build/Node.d.ts.map +1 -1
  9. package/build/Node.js.map +1 -1
  10. package/build/Utils.d.ts +1 -0
  11. package/build/Utils.d.ts.map +1 -1
  12. package/build/Utils.js +7 -1
  13. package/build/Utils.js.map +1 -1
  14. package/build/lib/commandclass/API.d.ts +15 -3
  15. package/build/lib/commandclass/API.d.ts.map +1 -1
  16. package/build/lib/commandclass/API.js +50 -0
  17. package/build/lib/commandclass/API.js.map +1 -1
  18. package/build/lib/commandclass/CommandClass.d.ts +0 -6
  19. package/build/lib/commandclass/CommandClass.d.ts.map +1 -1
  20. package/build/lib/commandclass/CommandClass.js +0 -12
  21. package/build/lib/commandclass/CommandClass.js.map +1 -1
  22. package/build/lib/commandclass/Security2CC.d.ts +1 -10
  23. package/build/lib/commandclass/Security2CC.d.ts.map +1 -1
  24. package/build/lib/commandclass/Security2CC.js +16 -48
  25. package/build/lib/commandclass/Security2CC.js.map +1 -1
  26. package/build/lib/commandclass/SecurityCC.d.ts +2 -9
  27. package/build/lib/commandclass/SecurityCC.d.ts.map +1 -1
  28. package/build/lib/commandclass/SecurityCC.js +9 -53
  29. package/build/lib/commandclass/SecurityCC.js.map +1 -1
  30. package/build/lib/commandclass/WakeUpCC.d.ts.map +1 -1
  31. package/build/lib/commandclass/WakeUpCC.js +1 -0
  32. package/build/lib/commandclass/WakeUpCC.js.map +1 -1
  33. package/build/lib/controller/BridgeApplicationCommandRequest.d.ts +2 -6
  34. package/build/lib/controller/BridgeApplicationCommandRequest.d.ts.map +1 -1
  35. package/build/lib/controller/BridgeApplicationCommandRequest.js +9 -19
  36. package/build/lib/controller/BridgeApplicationCommandRequest.js.map +1 -1
  37. package/build/lib/controller/Controller.d.ts +12 -2
  38. package/build/lib/controller/Controller.d.ts.map +1 -1
  39. package/build/lib/controller/Controller.js +14 -6
  40. package/build/lib/controller/Controller.js.map +1 -1
  41. package/build/lib/controller/Inclusion.d.ts +1 -1
  42. package/build/lib/controller/SendDataBridgeMessages.d.ts +5 -3
  43. package/build/lib/controller/SendDataBridgeMessages.d.ts.map +1 -1
  44. package/build/lib/controller/SendDataBridgeMessages.js +21 -8
  45. package/build/lib/controller/SendDataBridgeMessages.js.map +1 -1
  46. package/build/lib/controller/SendDataMessages.d.ts +5 -3
  47. package/build/lib/controller/SendDataMessages.d.ts.map +1 -1
  48. package/build/lib/controller/SendDataMessages.js +21 -9
  49. package/build/lib/controller/SendDataMessages.js.map +1 -1
  50. package/build/lib/controller/SendDataShared.d.ts +72 -2
  51. package/build/lib/controller/SendDataShared.d.ts.map +1 -1
  52. package/build/lib/controller/SendDataShared.js +195 -1
  53. package/build/lib/controller/SendDataShared.js.map +1 -1
  54. package/build/lib/driver/CommandQueueMachine.d.ts +7 -3
  55. package/build/lib/driver/CommandQueueMachine.d.ts.map +1 -1
  56. package/build/lib/driver/CommandQueueMachine.js +66 -29
  57. package/build/lib/driver/CommandQueueMachine.js.map +1 -1
  58. package/build/lib/driver/Driver.d.ts +16 -12
  59. package/build/lib/driver/Driver.d.ts.map +1 -1
  60. package/build/lib/driver/Driver.js +178 -163
  61. package/build/lib/driver/Driver.js.map +1 -1
  62. package/build/lib/driver/MessageGenerators.d.ts +26 -0
  63. package/build/lib/driver/MessageGenerators.d.ts.map +1 -0
  64. package/build/lib/driver/MessageGenerators.js +242 -0
  65. package/build/lib/driver/MessageGenerators.js.map +1 -0
  66. package/build/lib/driver/SendThreadMachine.d.ts +24 -53
  67. package/build/lib/driver/SendThreadMachine.d.ts.map +1 -1
  68. package/build/lib/driver/SendThreadMachine.js +160 -618
  69. package/build/lib/driver/SendThreadMachine.js.map +1 -1
  70. package/build/lib/driver/StateMachineShared.d.ts +2 -0
  71. package/build/lib/driver/StateMachineShared.d.ts.map +1 -1
  72. package/build/lib/driver/StateMachineShared.js +21 -10
  73. package/build/lib/driver/StateMachineShared.js.map +1 -1
  74. package/build/lib/driver/Transaction.d.ts +35 -3
  75. package/build/lib/driver/Transaction.d.ts.map +1 -1
  76. package/build/lib/driver/Transaction.js +20 -15
  77. package/build/lib/driver/Transaction.js.map +1 -1
  78. package/build/lib/driver/TransactionMachine.d.ts +30 -0
  79. package/build/lib/driver/TransactionMachine.d.ts.map +1 -0
  80. package/build/lib/driver/TransactionMachine.js +247 -0
  81. package/build/lib/driver/TransactionMachine.js.map +1 -0
  82. package/build/lib/driver/ZWaveOptions.d.ts +0 -2
  83. package/build/lib/driver/ZWaveOptions.d.ts.map +1 -1
  84. package/build/lib/message/Constants.d.ts +8 -9
  85. package/build/lib/message/Constants.d.ts.map +1 -1
  86. package/build/lib/message/Constants.js +9 -12
  87. package/build/lib/message/Constants.js.map +1 -1
  88. package/build/lib/message/Message.d.ts +5 -1
  89. package/build/lib/message/Message.d.ts.map +1 -1
  90. package/build/lib/message/Message.js +11 -0
  91. package/build/lib/message/Message.js.map +1 -1
  92. package/build/lib/node/HealthCheck.d.ts +8 -0
  93. package/build/lib/node/HealthCheck.d.ts.map +1 -0
  94. package/build/lib/node/HealthCheck.js +83 -0
  95. package/build/lib/node/HealthCheck.js.map +1 -0
  96. package/build/lib/node/Node.d.ts +11 -3
  97. package/build/lib/node/Node.d.ts.map +1 -1
  98. package/build/lib/node/Node.js +283 -7
  99. package/build/lib/node/Node.js.map +1 -1
  100. package/build/lib/node/Types.d.ts +132 -1
  101. package/build/lib/node/Types.d.ts.map +1 -1
  102. package/build/lib/node/Types.js.map +1 -1
  103. package/build/lib/serialapi/misc/GetBackgroundRSSIMessages.d.ts +14 -0
  104. package/build/lib/serialapi/misc/GetBackgroundRSSIMessages.d.ts.map +1 -0
  105. package/build/lib/serialapi/misc/GetBackgroundRSSIMessages.js +46 -0
  106. package/build/lib/serialapi/misc/GetBackgroundRSSIMessages.js.map +1 -0
  107. package/package.json +14 -14
@@ -38,10 +38,12 @@ const WakeUpCC_1 = require("../commandclass/WakeUpCC");
38
38
  const ZWavePlusCC_1 = require("../commandclass/ZWavePlusCC");
39
39
  const ApplicationUpdateRequest_1 = require("../controller/ApplicationUpdateRequest");
40
40
  const GetNodeProtocolInfoMessages_1 = require("../controller/GetNodeProtocolInfoMessages");
41
+ const SendDataShared_1 = require("../controller/SendDataShared");
41
42
  const StateMachineShared_1 = require("../driver/StateMachineShared");
42
43
  const Constants_1 = require("../message/Constants");
43
44
  const DeviceClass_1 = require("./DeviceClass");
44
45
  const Endpoint_1 = require("./Endpoint");
46
+ const HealthCheck_1 = require("./HealthCheck");
45
47
  const NodeReadyMachine_1 = require("./NodeReadyMachine");
46
48
  const NodeStatistics_1 = require("./NodeStatistics");
47
49
  const NodeStatusMachine_1 = require("./NodeStatusMachine");
@@ -843,14 +845,18 @@ let ZWaveNode = class ZWaveNode extends Endpoint_1.Endpoint {
843
845
  * **WARNING:** Take care NOT to call this method when the node is already being interviewed.
844
846
  * Otherwise the node information may become inconsistent.
845
847
  */
846
- async refreshInfo() {
848
+ async refreshInfo(options = {}) {
847
849
  // It does not make sense to re-interview the controller. All important information is queried
848
850
  // directly via the serial API
849
851
  if (this.isControllerNode())
850
852
  return;
853
+ const { resetSecurityClasses = false } = options;
851
854
  // preserve the node name and location, since they might not be stored on the node
852
855
  const name = this.name;
853
856
  const location = this.location;
857
+ // Force a new detection of security classes if desired
858
+ if (resetSecurityClasses)
859
+ this.securityClasses.clear();
854
860
  this._interviewAttempts = 0;
855
861
  this.interviewStage = Types_1.InterviewStage.None;
856
862
  this._ready = false;
@@ -1787,8 +1793,11 @@ protocol version: ${this._protocolVersion}`;
1787
1793
  // the shared SPAN, since it did the same
1788
1794
  secMan.storeRemoteEI(this.nodeId, command.receiverEI);
1789
1795
  }
1790
- // Tell the driver to re-send the current message if necessary
1791
- this.driver.resendS2EncapsulatedCommand();
1796
+ this.driver.controllerLog.logNode(this.id, {
1797
+ message: `received S2 nonce, not sure what to do with it`,
1798
+ level: "warn",
1799
+ direction: "inbound",
1800
+ });
1792
1801
  }
1793
1802
  async handleHail(_command) {
1794
1803
  // treat this as a sign that the node is awake
@@ -2959,7 +2968,7 @@ protocol version: ${this._protocolVersion}`;
2959
2968
  *
2960
2969
  * **Note:** Depending on the number of test frames, this may take a while
2961
2970
  */
2962
- async testPowerlevel(testNodeId, powerlevel, testFrameCount, onProgress) {
2971
+ async testPowerlevel(testNodeId, powerlevel, healthCheckTestFrameCount, onProgress) {
2963
2972
  const api = this.commandClasses.Powerlevel;
2964
2973
  // Keep sleeping nodes awake
2965
2974
  const wasKeptAwake = this.keepAwake;
@@ -2971,10 +2980,10 @@ protocol version: ${this._protocolVersion}`;
2971
2980
  return value;
2972
2981
  };
2973
2982
  // Start the process
2974
- await api.startNodeTest(testNodeId, powerlevel, testFrameCount);
2983
+ await api.startNodeTest(testNodeId, powerlevel, healthCheckTestFrameCount);
2975
2984
  // Each frame will take a few ms to be sent, let's assume 5 per second
2976
2985
  // to estimate how long the test will take
2977
- const expectedDurationMs = Math.round((testFrameCount / 5) * 1000);
2986
+ const expectedDurationMs = Math.round((healthCheckTestFrameCount / 5) * 1000);
2978
2987
  // Poll the status of the test regularly
2979
2988
  const pollFrequencyMs = expectedDurationMs >= 60000
2980
2989
  ? 10000
@@ -3011,9 +3020,276 @@ protocol version: ${this._protocolVersion}`;
3011
3020
  }
3012
3021
  else if (onProgress) {
3013
3022
  // Notify the caller of the test progress
3014
- onProgress(status.acknowledgedFrames, testFrameCount);
3023
+ onProgress(status.acknowledgedFrames, healthCheckTestFrameCount);
3024
+ }
3025
+ }
3026
+ }
3027
+ /**
3028
+ * Checks the health of connection between the controller and this node and returns the results.
3029
+ */
3030
+ async checkLifelineHealth(rounds = 5, onProgress) {
3031
+ if (rounds > 10 || rounds < 1) {
3032
+ throw new core_1.ZWaveError("The number of health check rounds must be between 1 and 10!", core_1.ZWaveErrorCodes.Argument_Invalid);
3033
+ }
3034
+ // No. of pings per round
3035
+ const start = Date.now();
3036
+ /** Computes a health rating from a health check result */
3037
+ const computeRating = (result) => {
3038
+ var _a, _b, _c;
3039
+ const failedPings = Math.max((_a = result.failedPingsController) !== null && _a !== void 0 ? _a : 0, result.failedPingsNode);
3040
+ const numNeighbors = result.numNeighbors;
3041
+ const minPowerlevel = (_b = result.minPowerlevel) !== null && _b !== void 0 ? _b : PowerlevelCC_1.Powerlevel["-6 dBm"];
3042
+ const snrMargin = (_c = result.snrMargin) !== null && _c !== void 0 ? _c : 17;
3043
+ const latency = result.latency;
3044
+ if (failedPings === 10)
3045
+ return 0;
3046
+ if (failedPings > 2)
3047
+ return 1;
3048
+ if (failedPings === 2 || latency > 1000)
3049
+ return 2;
3050
+ if (failedPings === 1 || latency > 500)
3051
+ return 3;
3052
+ if (latency > 250)
3053
+ return 4;
3054
+ if (latency > 100)
3055
+ return 5;
3056
+ if (minPowerlevel < PowerlevelCC_1.Powerlevel["-6 dBm"] || snrMargin < 17) {
3057
+ // Lower powerlevel reductions (= higher power) have lower numeric values
3058
+ return numNeighbors > 2 ? 7 : 6;
3059
+ }
3060
+ if (numNeighbors <= 2)
3061
+ return 8;
3062
+ if (latency > 50)
3063
+ return 9;
3064
+ return 10;
3065
+ };
3066
+ this.driver.controllerLog.logNode(this.id, `Starting lifeline health check (${rounds} round${rounds !== 1 ? "s" : ""})...`);
3067
+ const results = [];
3068
+ for (let round = 1; round <= rounds; round++) {
3069
+ // Determine the number of repeating neighbors
3070
+ const numNeighbors = (await this.driver.controller.getNodeNeighbors(this.nodeId, true)).length;
3071
+ // Ping the node 10x, measuring the RSSI
3072
+ let txReport;
3073
+ let routeChanges;
3074
+ let rssi;
3075
+ let channel;
3076
+ let snrMargin;
3077
+ let failedPingsNode = 0;
3078
+ let latency = 0;
3079
+ const pingAPI = this.commandClasses["No Operation"].withOptions({
3080
+ onTXReport: (report) => {
3081
+ txReport = report;
3082
+ },
3083
+ });
3084
+ for (let i = 1; i <= HealthCheck_1.healthCheckTestFrameCount; i++) {
3085
+ const start = Date.now();
3086
+ const pingResult = await pingAPI.send().then(() => true, () => false);
3087
+ const rtt = Date.now() - start;
3088
+ latency = Math.max(latency, txReport ? txReport.txTicks * 10 : rtt);
3089
+ if (!pingResult) {
3090
+ failedPingsNode++;
3091
+ }
3092
+ else if (txReport) {
3093
+ routeChanges !== null && routeChanges !== void 0 ? routeChanges : (routeChanges = 0);
3094
+ if (txReport.routingAttempts > 1) {
3095
+ routeChanges++;
3096
+ }
3097
+ rssi = txReport.ackRSSI;
3098
+ channel = txReport.ackChannelNo;
3099
+ }
3100
+ }
3101
+ // If possible, compute the SNR margin from the test results
3102
+ if (rssi != undefined &&
3103
+ rssi < SendDataShared_1.RssiError.NoSignalDetected &&
3104
+ channel != undefined) {
3105
+ const backgroundRSSI = await this.driver.controller.getBackgroundRSSI();
3106
+ if (`rssiChannel${channel}` in backgroundRSSI) {
3107
+ snrMargin =
3108
+ rssi - backgroundRSSI[`rssiChannel${channel}`];
3109
+ }
3110
+ }
3111
+ const ret = {
3112
+ latency,
3113
+ failedPingsNode,
3114
+ numNeighbors,
3115
+ routeChanges,
3116
+ snrMargin,
3117
+ rating: 0,
3118
+ };
3119
+ // Now instruct the node to ping the controller, figuring out the minimum powerlevel
3120
+ if (this.supportsCC(core_1.CommandClasses.Powerlevel)) {
3121
+ // Do a binary search and find the highest reduction in powerlevel for which there are no errors
3122
+ let failedPingsController = 0;
3123
+ const executor = async (powerlevel) => {
3124
+ this.driver.controllerLog.logNode(this.id, `Sending ${HealthCheck_1.healthCheckTestFrameCount} pings to controller at ${(0, shared_1.getEnumMemberName)(PowerlevelCC_1.Powerlevel, powerlevel)}...`);
3125
+ const result = await this.testPowerlevel(this.driver.controller.ownNodeId, powerlevel, HealthCheck_1.healthCheckTestFrameCount);
3126
+ failedPingsController = HealthCheck_1.healthCheckTestFrameCount - result;
3127
+ this.driver.controllerLog.logNode(this.id, `At ${(0, shared_1.getEnumMemberName)(PowerlevelCC_1.Powerlevel, powerlevel)}, ${result}/${HealthCheck_1.healthCheckTestFrameCount} pings were acknowledged...`);
3128
+ return failedPingsController === 0;
3129
+ };
3130
+ try {
3131
+ const powerlevel = await (0, shared_1.discreteBinarySearch)(PowerlevelCC_1.Powerlevel["Normal Power"], // minimum reduction
3132
+ PowerlevelCC_1.Powerlevel["-9 dBm"], // maximum reduction
3133
+ executor);
3134
+ if (powerlevel == undefined) {
3135
+ // There were still failures at normal power, report it
3136
+ ret.minPowerlevel = PowerlevelCC_1.Powerlevel["Normal Power"];
3137
+ ret.failedPingsController = failedPingsController;
3138
+ }
3139
+ else {
3140
+ ret.minPowerlevel = powerlevel;
3141
+ }
3142
+ }
3143
+ catch (e) {
3144
+ if ((0, core_1.isZWaveError)(e) &&
3145
+ e.code === core_1.ZWaveErrorCodes.Controller_CallbackNOK) {
3146
+ // The node is dead, treat this as a failure
3147
+ ret.minPowerlevel = PowerlevelCC_1.Powerlevel["Normal Power"];
3148
+ ret.failedPingsController = HealthCheck_1.healthCheckTestFrameCount;
3149
+ }
3150
+ else {
3151
+ throw e;
3152
+ }
3153
+ }
3015
3154
  }
3155
+ ret.rating = computeRating(ret);
3156
+ results.push(ret);
3157
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(round, rounds, ret.rating);
3016
3158
  }
3159
+ const duration = Date.now() - start;
3160
+ const rating = Math.min(...results.map((r) => r.rating));
3161
+ const summary = { results, rating };
3162
+ this.driver.controllerLog.logNode(this.id, `Lifeline health check complete in ${duration} ms
3163
+ ${(0, HealthCheck_1.formatLifelineHealthCheckSummary)(summary)}`);
3164
+ return summary;
3165
+ }
3166
+ /**
3167
+ * Checks the health of connection between this node and the target node and returns the results.
3168
+ */
3169
+ async checkRouteHealth(targetNodeId, rounds = 5, onProgress) {
3170
+ if (rounds > 10 || rounds < 1) {
3171
+ throw new core_1.ZWaveError("The number of health check rounds must be between 1 and 10!", core_1.ZWaveErrorCodes.Argument_Invalid);
3172
+ }
3173
+ const otherNode = this.driver.controller.nodes.getOrThrow(targetNodeId);
3174
+ if (!this.supportsCC(core_1.CommandClasses.Powerlevel) &&
3175
+ !otherNode.supportsCC(core_1.CommandClasses.Powerlevel)) {
3176
+ throw new core_1.ZWaveError("For a route health check, at least one of the nodes must support Powerlevel CC!", core_1.ZWaveErrorCodes.CC_NotSupported);
3177
+ }
3178
+ // No. of pings per round
3179
+ const healthCheckTestFrameCount = 10;
3180
+ const start = Date.now();
3181
+ /** Computes a health rating from a health check result */
3182
+ const computeRating = (result) => {
3183
+ var _a, _b, _c, _d;
3184
+ const failedPings = Math.max((_a = result.failedPingsToSource) !== null && _a !== void 0 ? _a : 0, (_b = result.failedPingsToTarget) !== null && _b !== void 0 ? _b : 0);
3185
+ const numNeighbors = result.numNeighbors;
3186
+ const minPowerlevel = Math.max((_c = result.minPowerlevelSource) !== null && _c !== void 0 ? _c : PowerlevelCC_1.Powerlevel["-6 dBm"], (_d = result.minPowerlevelTarget) !== null && _d !== void 0 ? _d : PowerlevelCC_1.Powerlevel["-6 dBm"]);
3187
+ if (failedPings === 10)
3188
+ return 0;
3189
+ if (failedPings > 2)
3190
+ return 1;
3191
+ if (failedPings === 2)
3192
+ return 2;
3193
+ if (failedPings === 1)
3194
+ return 3;
3195
+ if (minPowerlevel < PowerlevelCC_1.Powerlevel["-6 dBm"]) {
3196
+ // Lower powerlevel reductions (= higher power) have lower numeric values
3197
+ return numNeighbors > 2 ? 7 : 6;
3198
+ }
3199
+ if (numNeighbors <= 2)
3200
+ return 8;
3201
+ return 10;
3202
+ };
3203
+ this.driver.controllerLog.logNode(this.id, `Starting route health check to node ${targetNodeId} (${rounds} round${rounds !== 1 ? "s" : ""})...`);
3204
+ const results = [];
3205
+ for (let round = 1; round <= rounds; round++) {
3206
+ // Determine the minimum number of repeating neighbors between the
3207
+ // source and target node
3208
+ const numNeighbors = Math.min((await this.driver.controller.getNodeNeighbors(this.nodeId, true)).length, (await this.driver.controller.getNodeNeighbors(targetNodeId, true)).length);
3209
+ let failedPings = 0;
3210
+ let failedPingsToSource;
3211
+ let minPowerlevelSource;
3212
+ let failedPingsToTarget;
3213
+ let minPowerlevelTarget;
3214
+ const executor = (node, otherNode) => async (powerlevel) => {
3215
+ this.driver.controllerLog.logNode(node.id, `Sending ${healthCheckTestFrameCount} pings to node ${otherNode.id} at ${(0, shared_1.getEnumMemberName)(PowerlevelCC_1.Powerlevel, powerlevel)}...`);
3216
+ const result = await node.testPowerlevel(otherNode.id, powerlevel, healthCheckTestFrameCount);
3217
+ failedPings = healthCheckTestFrameCount - result;
3218
+ this.driver.controllerLog.logNode(node.id, `At ${(0, shared_1.getEnumMemberName)(PowerlevelCC_1.Powerlevel, powerlevel)}, ${result}/${healthCheckTestFrameCount} pings were acknowledged by node ${otherNode.id}...`);
3219
+ return failedPings === 0;
3220
+ };
3221
+ // Now instruct this node to ping the other one, figuring out the minimum powerlevel
3222
+ if (this.supportsCC(core_1.CommandClasses.Powerlevel)) {
3223
+ try {
3224
+ const powerlevel = await (0, shared_1.discreteBinarySearch)(PowerlevelCC_1.Powerlevel["Normal Power"], // minimum reduction
3225
+ PowerlevelCC_1.Powerlevel["-9 dBm"], // maximum reduction
3226
+ executor(this, otherNode));
3227
+ if (powerlevel == undefined) {
3228
+ // There were still failures at normal power, report it
3229
+ minPowerlevelSource = PowerlevelCC_1.Powerlevel["Normal Power"];
3230
+ failedPingsToTarget = failedPings;
3231
+ }
3232
+ else {
3233
+ minPowerlevelSource = powerlevel;
3234
+ }
3235
+ }
3236
+ catch (e) {
3237
+ if ((0, core_1.isZWaveError)(e) &&
3238
+ e.code === core_1.ZWaveErrorCodes.Controller_CallbackNOK) {
3239
+ // The node is dead, treat this as a failure
3240
+ minPowerlevelSource = PowerlevelCC_1.Powerlevel["Normal Power"];
3241
+ failedPingsToTarget = healthCheckTestFrameCount;
3242
+ }
3243
+ else {
3244
+ throw e;
3245
+ }
3246
+ }
3247
+ }
3248
+ // And do the same with the other node
3249
+ if (otherNode.supportsCC(core_1.CommandClasses.Powerlevel)) {
3250
+ try {
3251
+ const powerlevel = await (0, shared_1.discreteBinarySearch)(PowerlevelCC_1.Powerlevel["Normal Power"], // minimum reduction
3252
+ PowerlevelCC_1.Powerlevel["-9 dBm"], // maximum reduction
3253
+ executor(otherNode, this));
3254
+ if (powerlevel == undefined) {
3255
+ // There were still failures at normal power, report it
3256
+ minPowerlevelTarget = PowerlevelCC_1.Powerlevel["Normal Power"];
3257
+ failedPingsToSource = failedPings;
3258
+ }
3259
+ else {
3260
+ minPowerlevelTarget = powerlevel;
3261
+ }
3262
+ }
3263
+ catch (e) {
3264
+ if ((0, core_1.isZWaveError)(e) &&
3265
+ e.code === core_1.ZWaveErrorCodes.Controller_CallbackNOK) {
3266
+ // The node is dead, treat this as a failure
3267
+ minPowerlevelTarget = PowerlevelCC_1.Powerlevel["Normal Power"];
3268
+ failedPingsToSource = healthCheckTestFrameCount;
3269
+ }
3270
+ else {
3271
+ throw e;
3272
+ }
3273
+ }
3274
+ }
3275
+ const ret = {
3276
+ numNeighbors,
3277
+ failedPingsToSource,
3278
+ failedPingsToTarget,
3279
+ minPowerlevelSource,
3280
+ minPowerlevelTarget,
3281
+ rating: 0,
3282
+ };
3283
+ ret.rating = computeRating(ret);
3284
+ results.push(ret);
3285
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(round, rounds, ret.rating);
3286
+ }
3287
+ const duration = Date.now() - start;
3288
+ const rating = Math.min(...results.map((r) => r.rating));
3289
+ const summary = { results, rating };
3290
+ this.driver.controllerLog.logNode(this.id, `Route health check to node ${otherNode.id} complete in ${duration} ms
3291
+ ${(0, HealthCheck_1.formatRouteHealthCheckSummary)(this.id, otherNode.id, summary)}`);
3292
+ return summary;
3017
3293
  }
3018
3294
  };
3019
3295
  ZWaveNode = __decorate([