zwave-js 8.6.0 → 8.7.2

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 (42) hide show
  1. package/build/Utils.d.ts +2 -2
  2. package/build/Utils.d.ts.map +1 -1
  3. package/build/Utils.js +3 -1
  4. package/build/Utils.js.map +1 -1
  5. package/build/lib/commandclass/AssociationCC.d.ts.map +1 -1
  6. package/build/lib/commandclass/AssociationCC.js +2 -4
  7. package/build/lib/commandclass/AssociationCC.js.map +1 -1
  8. package/build/lib/commandclass/ManufacturerProprietaryCC.d.ts.map +1 -1
  9. package/build/lib/commandclass/ManufacturerProprietaryCC.js +15 -8
  10. package/build/lib/commandclass/ManufacturerProprietaryCC.js.map +1 -1
  11. package/build/lib/commandclass/MultiChannelAssociationCC.d.ts.map +1 -1
  12. package/build/lib/commandclass/MultiChannelAssociationCC.js +2 -4
  13. package/build/lib/commandclass/MultiChannelAssociationCC.js.map +1 -1
  14. package/build/lib/controller/AddNodeToNetworkRequest.d.ts +36 -8
  15. package/build/lib/controller/AddNodeToNetworkRequest.d.ts.map +1 -1
  16. package/build/lib/controller/AddNodeToNetworkRequest.js +111 -41
  17. package/build/lib/controller/AddNodeToNetworkRequest.js.map +1 -1
  18. package/build/lib/controller/ApplicationUpdateRequest.d.ts +16 -4
  19. package/build/lib/controller/ApplicationUpdateRequest.d.ts.map +1 -1
  20. package/build/lib/controller/ApplicationUpdateRequest.js +56 -15
  21. package/build/lib/controller/ApplicationUpdateRequest.js.map +1 -1
  22. package/build/lib/controller/Controller.d.ts +65 -20
  23. package/build/lib/controller/Controller.d.ts.map +1 -1
  24. package/build/lib/controller/Controller.js +651 -265
  25. package/build/lib/controller/Controller.js.map +1 -1
  26. package/build/lib/controller/Inclusion.d.ts +31 -4
  27. package/build/lib/controller/Inclusion.d.ts.map +1 -1
  28. package/build/lib/controller/Inclusion.js +15 -3
  29. package/build/lib/controller/Inclusion.js.map +1 -1
  30. package/build/lib/controller/RemoveNodeFromNetworkRequest.d.ts +15 -9
  31. package/build/lib/controller/RemoveNodeFromNetworkRequest.d.ts.map +1 -1
  32. package/build/lib/controller/RemoveNodeFromNetworkRequest.js +70 -41
  33. package/build/lib/controller/RemoveNodeFromNetworkRequest.js.map +1 -1
  34. package/build/lib/driver/Driver.d.ts +5 -1
  35. package/build/lib/driver/Driver.d.ts.map +1 -1
  36. package/build/lib/driver/Driver.js +246 -59
  37. package/build/lib/driver/Driver.js.map +1 -1
  38. package/build/lib/node/Node.d.ts +6 -0
  39. package/build/lib/node/Node.d.ts.map +1 -1
  40. package/build/lib/node/Node.js +22 -9
  41. package/build/lib/node/Node.js.map +1 -1
  42. package/package.json +10 -10
@@ -56,6 +56,7 @@ const ApplicationUpdateRequest_1 = require("../controller/ApplicationUpdateReque
56
56
  const BridgeApplicationCommandRequest_1 = require("../controller/BridgeApplicationCommandRequest");
57
57
  const Controller_1 = require("../controller/Controller");
58
58
  const GetControllerVersionMessages_1 = require("../controller/GetControllerVersionMessages");
59
+ const Inclusion_1 = require("../controller/Inclusion");
59
60
  const SendDataBridgeMessages_1 = require("../controller/SendDataBridgeMessages");
60
61
  const SendDataMessages_1 = require("../controller/SendDataMessages");
61
62
  const SendDataShared_1 = require("../controller/SendDataShared");
@@ -232,6 +233,7 @@ class Driver extends shared_1.TypedEventEmitter {
232
233
  this._controllerLog = new Controller_2.ControllerLogger(this._logContainer);
233
234
  // Initialize the cache
234
235
  this.cacheDir = this.options.storage.cacheDir;
236
+ // TODO: Load provisioning list
235
237
  // Initialize config manager
236
238
  this.configManager = new config_1.ConfigManager({
237
239
  logContainer: this._logContainer,
@@ -452,7 +454,9 @@ class Driver extends shared_1.TypedEventEmitter {
452
454
  spOpenPromise.resolve();
453
455
  // Perform initialization sequence
454
456
  await this.writeHeader(serial_1.MessageHeaders.NAK);
455
- await this.trySoftReset();
457
+ // Per the specs, this should be followed by a soft-reset but we need to be able
458
+ // to handle sticks that don't support the soft reset command. Therefore we do it
459
+ // after opening the value DBs
456
460
  // Try to create the cache directory. This can fail, in which case we should expose a good error message
457
461
  try {
458
462
  await this.options.storage.driver.ensureDir(this.cacheDir);
@@ -534,6 +538,32 @@ class Driver extends shared_1.TypedEventEmitter {
534
538
  get allNodesReady() {
535
539
  return this._nodesReadyEventEmitted;
536
540
  }
541
+ async initValueDBs(homeId) {
542
+ // Always start the value and metadata databases
543
+ const options = {
544
+ ignoreReadErrors: true,
545
+ ...ThrottlePresets_1.throttlePresets[this.options.storage.throttle],
546
+ };
547
+ if (this.options.storage.lockDir) {
548
+ options.lockfileDirectory = this.options.storage.lockDir;
549
+ }
550
+ const valueDBFile = path_1.default.join(this.cacheDir, `${homeId.toString(16)}.values.jsonl`);
551
+ this._valueDB = new jsonl_db_1.JsonlDB(valueDBFile, {
552
+ ...options,
553
+ reviver: (key, value) => (0, core_1.deserializeCacheValue)(value),
554
+ serializer: (key, value) => (0, core_1.serializeCacheValue)(value),
555
+ });
556
+ await this._valueDB.open();
557
+ const metadataDBFile = path_1.default.join(this.cacheDir, `${homeId.toString(16)}.metadata.jsonl`);
558
+ this._metadataDB = new jsonl_db_1.JsonlDB(metadataDBFile, options);
559
+ await this._metadataDB.open();
560
+ if (process.env.NO_CACHE === "true") {
561
+ // Since value/metadata DBs are append-only, we need to clear them
562
+ // if the cache should be ignored
563
+ this._valueDB.clear();
564
+ this._metadataDB.clear();
565
+ }
566
+ }
537
567
  /**
538
568
  * Initializes the variables for controller and nodes,
539
569
  * adds event handlers and starts the interview process.
@@ -546,42 +576,56 @@ class Driver extends shared_1.TypedEventEmitter {
546
576
  .on("node added", this.onNodeAdded.bind(this))
547
577
  .on("node removed", this.onNodeRemoved.bind(this));
548
578
  }
549
- const initValueDBs = async () => {
550
- // Always start the value and metadata databases
551
- const options = {
552
- ignoreReadErrors: true,
553
- ...ThrottlePresets_1.throttlePresets[this.options.storage.throttle],
554
- };
555
- if (this.options.storage.lockDir) {
556
- options.lockfileDirectory = this.options.storage.lockDir;
557
- }
558
- const valueDBFile = path_1.default.join(this.cacheDir, `${this._controller.homeId.toString(16)}.values.jsonl`);
559
- this._valueDB = new jsonl_db_1.JsonlDB(valueDBFile, {
560
- ...options,
561
- reviver: (key, value) => (0, core_1.deserializeCacheValue)(value),
562
- serializer: (key, value) => (0, core_1.serializeCacheValue)(value),
563
- });
564
- await this._valueDB.open();
565
- const metadataDBFile = path_1.default.join(this.cacheDir, `${this._controller.homeId.toString(16)}.metadata.jsonl`);
566
- this._metadataDB = new jsonl_db_1.JsonlDB(metadataDBFile, options);
567
- await this._metadataDB.open();
568
- if (process.env.NO_CACHE === "true") {
569
- // Since value/metadata DBs are append-only, we need to clear them
570
- // if the cache should be ignored
571
- this._valueDB.clear();
572
- this._metadataDB.clear();
573
- }
574
- };
575
579
  if (!this.options.interview.skipInterview) {
580
+ // Determine controller IDs to open the Value DBs
581
+ // We need to do this first because some older controllers, especially the UZB1 and
582
+ // some 500-series sticks in virtualized environments don't respond after a soft reset
583
+ // No need to initialize databases if skipInterview is true, because it is only used in some
584
+ // Driver unit tests that don't need access to them
585
+ // Identify the controller and determine if it supports soft reset
586
+ await this.controller.identify();
587
+ if (this.options.enableSoftReset && !(await this.maySoftReset())) {
588
+ this.driverLog.print(`Soft reset is enabled through config, but this stick does not support it.`, "warn");
589
+ this.options.enableSoftReset = false;
590
+ }
591
+ if (this.options.enableSoftReset) {
592
+ try {
593
+ await this.softResetInternal(false);
594
+ }
595
+ catch (e) {
596
+ if ((0, core_1.isZWaveError)(e) &&
597
+ e.code === core_1.ZWaveErrorCodes.Driver_Failed) {
598
+ // Remember that soft reset is not supported by this stick
599
+ await this.rememberNoSoftReset();
600
+ // Then fail the driver
601
+ await this.destroy();
602
+ return;
603
+ }
604
+ }
605
+ }
606
+ // There are situations where a controller claims it has the ID 0,
607
+ // which isn't valid. In this case try again after having soft-reset the stick
608
+ if (this.controller.ownNodeId === 0 &&
609
+ this.options.enableSoftReset) {
610
+ this.driverLog.print(`Controller identification returned invalid node ID 0 - trying again...`, "warn");
611
+ await this.controller.identify();
612
+ }
613
+ if (this.controller.ownNodeId === 0) {
614
+ this.driverLog.print(`Controller identification returned invalid node ID 0`, "error");
615
+ await this.destroy();
616
+ return;
617
+ }
618
+ // now that we know the home ID, we can open the databases
619
+ await this.initValueDBs(this.controller.homeId);
576
620
  // Interview the controller.
577
- await this._controller.interview(initValueDBs, async () => {
621
+ await this._controller.interview(async () => {
578
622
  // Try to restore the network information from the cache
579
623
  if (process.env.NO_CACHE !== "true") {
580
624
  await this.restoreNetworkStructureFromCache();
581
625
  }
582
626
  });
583
- // No need to initialize databases if skipInterview is true, because it is only used in some
584
- // Driver unit tests that don't need access to them
627
+ // Auto-enable smart start inclusion
628
+ this._controller.autoProvisionSmartStart();
585
629
  }
586
630
  // Set up the S0 security manager. We can only do that after the controller
587
631
  // interview because we need to know the controller node id.
@@ -1058,6 +1102,76 @@ class Driver extends shared_1.TypedEventEmitter {
1058
1102
  throw new core_1.ZWaveError("Cannot retrieve the version of a CC that is not implemented", core_1.ZWaveErrorCodes.CC_NotSupported);
1059
1103
  }
1060
1104
  }
1105
+ async maySoftReset() {
1106
+ var _a;
1107
+ // If we've previously determined a stick not to support soft reset, don't bother trying again
1108
+ let supportsSoftReset;
1109
+ if (this._controllerInterviewed) {
1110
+ supportsSoftReset = this.controller.supportsSoftReset;
1111
+ }
1112
+ else {
1113
+ // The controller wasn't interviewed yet, read the json file manually
1114
+ const fs = this.options.storage.driver;
1115
+ const cacheFile = path_1.default.join(this.cacheDir, this.controller.homeId.toString(16) + ".json");
1116
+ // Read it if it exists
1117
+ let json;
1118
+ if (await fs.pathExists(cacheFile)) {
1119
+ try {
1120
+ json = JSON.parse(await fs.readFile(cacheFile, "utf8"));
1121
+ }
1122
+ catch { }
1123
+ }
1124
+ supportsSoftReset = (_a = json === null || json === void 0 ? void 0 : json.controller) === null || _a === void 0 ? void 0 : _a.supportsSoftReset;
1125
+ }
1126
+ if (supportsSoftReset === false)
1127
+ return false;
1128
+ // Blacklist some sticks that are known to not support soft reset
1129
+ const { manufacturerId, productType, productId } = this.controller;
1130
+ // Z-Wave.me UZB1
1131
+ if (manufacturerId === 0x0115 &&
1132
+ productType === 0x0000 &&
1133
+ productId === 0x0000) {
1134
+ return false;
1135
+ }
1136
+ // Z-Wave.me UZB
1137
+ if (manufacturerId === 0x0115 &&
1138
+ productType === 0x0400 &&
1139
+ productId === 0x0001) {
1140
+ return false;
1141
+ }
1142
+ return true;
1143
+ }
1144
+ async rememberNoSoftReset() {
1145
+ var _a;
1146
+ this.driverLog.print("Soft reset seems not to be supported by this stick, disabling it.", "warn");
1147
+ this.controller.supportsSoftReset = false;
1148
+ if (this._controllerInterviewed) {
1149
+ // We can use the normal method for this
1150
+ await this.saveNetworkToCacheInternal();
1151
+ }
1152
+ else {
1153
+ // saveNetworkToCache won't write anything, just edit the file "manually"
1154
+ // TODO: This is ugly, rework this when changing how the network data is saved
1155
+ const fs = this.options.storage.driver;
1156
+ await fs.ensureDir(this.cacheDir);
1157
+ const cacheFile = path_1.default.join(this.cacheDir, this.controller.homeId.toString(16) + ".json");
1158
+ // Read it if it exists
1159
+ let json;
1160
+ if (await fs.pathExists(cacheFile)) {
1161
+ try {
1162
+ json = JSON.parse(await fs.readFile(cacheFile, "utf8"));
1163
+ }
1164
+ catch { }
1165
+ }
1166
+ // Change the supportsSoftReset flag
1167
+ json !== null && json !== void 0 ? json : (json = {});
1168
+ (_a = json.controller) !== null && _a !== void 0 ? _a : (json.controller = {});
1169
+ json.controller.supportsSoftReset = false;
1170
+ // And save it again
1171
+ const jsonString = (0, shared_1.stringify)(json);
1172
+ await this.options.storage.driver.writeFile(cacheFile, jsonString, "utf8");
1173
+ }
1174
+ }
1061
1175
  /**
1062
1176
  * Soft-resets the controller if the feature is enabled
1063
1177
  */
@@ -1083,6 +1197,9 @@ class Driver extends shared_1.TypedEventEmitter {
1083
1197
  this.controllerLog.print(message, "error");
1084
1198
  throw new core_1.ZWaveError(message, core_1.ZWaveErrorCodes.Driver_FeatureDisabled);
1085
1199
  }
1200
+ return this.softResetInternal(true);
1201
+ }
1202
+ async softResetInternal(destroyOnError) {
1086
1203
  this.controllerLog.print("Performing soft reset...");
1087
1204
  try {
1088
1205
  this.isSoftResetting = true;
@@ -1095,7 +1212,14 @@ class Driver extends shared_1.TypedEventEmitter {
1095
1212
  this.controllerLog.print(`Soft reset failed: ${(0, shared_1.getErrorMessage)(e)}`, "error");
1096
1213
  }
1097
1214
  // Make sure we're able to communicate with the controller again
1098
- await this.ensureSerialAPI();
1215
+ if (!(await this.ensureSerialAPI())) {
1216
+ if (destroyOnError) {
1217
+ await this.destroy();
1218
+ }
1219
+ else {
1220
+ throw new core_1.ZWaveError("The Serial API did not respond after soft-reset", core_1.ZWaveErrorCodes.Driver_Failed);
1221
+ }
1222
+ }
1099
1223
  this.isSoftResetting = false;
1100
1224
  // And resume sending
1101
1225
  this.unpauseSendThread();
@@ -1109,7 +1233,7 @@ class Driver extends shared_1.TypedEventEmitter {
1109
1233
  if (waitResult) {
1110
1234
  // Serial API did start, maybe do something with the information?
1111
1235
  this.controllerLog.print("reconnected and restarted");
1112
- return;
1236
+ return true;
1113
1237
  }
1114
1238
  // If the controller disconnected the serial port during the soft reset, we need to re-open it
1115
1239
  if (!this.serial.isOpen) {
@@ -1122,7 +1246,7 @@ class Driver extends shared_1.TypedEventEmitter {
1122
1246
  if (waitResult) {
1123
1247
  // Serial API did start, maybe do something with the information?
1124
1248
  this.controllerLog.print("Serial API started");
1125
- return;
1249
+ return true;
1126
1250
  }
1127
1251
  this.controllerLog.print("Did not receive notification that Serial API has started, checking if it responds...");
1128
1252
  // We don't need to use any specific command here. However we're going to use this one in the interview
@@ -1144,21 +1268,15 @@ class Driver extends shared_1.TypedEventEmitter {
1144
1268
  };
1145
1269
  // Poll the controller with increasing backoff delay
1146
1270
  if (await pollController())
1147
- return;
1148
- this.controllerLog.print("Serial API did not respond, trying again in 2 seconds...");
1149
- await (0, async_1.wait)(2000, true);
1150
- if (await pollController())
1151
- return;
1152
- this.controllerLog.print("Serial API did not respond, trying again in 5 seconds...");
1153
- await (0, async_1.wait)(5000, true);
1154
- if (await pollController())
1155
- return;
1156
- this.controllerLog.print("Serial API did not respond, trying again in 10 seconds...");
1157
- await (0, async_1.wait)(10000, true);
1158
- if (await pollController())
1159
- return;
1271
+ return true;
1272
+ for (const backoff of [2, 5, 10, 15]) {
1273
+ this.controllerLog.print(`Serial API did not respond, trying again in ${backoff} seconds...`);
1274
+ await (0, async_1.wait)(backoff * 1000, true);
1275
+ if (await pollController())
1276
+ return true;
1277
+ }
1160
1278
  this.controllerLog.print("Serial API did not respond, giving up", "error");
1161
- await this.destroy();
1279
+ return false;
1162
1280
  }
1163
1281
  /**
1164
1282
  * Performs a hard reset on the controller. This wipes out all configuration!
@@ -1206,12 +1324,27 @@ class Driver extends shared_1.TypedEventEmitter {
1206
1324
  * Must be called under any circumstances.
1207
1325
  */
1208
1326
  async destroy() {
1209
- var _a, _b, _c;
1327
+ var _a, _b, _c, _d;
1210
1328
  // Ensure this is only called once and all subsequent calls block
1211
1329
  if (this._destroyPromise)
1212
1330
  return this._destroyPromise;
1213
1331
  this._destroyPromise = (0, deferred_promise_1.createDeferredPromise)();
1214
1332
  this.driverLog.print("destroying driver instance...");
1333
+ // Disable inclusion before shutting down
1334
+ try {
1335
+ switch ((_a = this._controller) === null || _a === void 0 ? void 0 : _a.inclusionState) {
1336
+ case Inclusion_1.InclusionState.SmartStart:
1337
+ case Inclusion_1.InclusionState.Including:
1338
+ await this._controller.stopInclusionNoCallback();
1339
+ break;
1340
+ case Inclusion_1.InclusionState.Excluding:
1341
+ await this._controller.stopExclusionNoCallback();
1342
+ break;
1343
+ }
1344
+ }
1345
+ catch {
1346
+ // ignore
1347
+ }
1215
1348
  // First stop the send thread machine and close the serial port, so nothing happens anymore
1216
1349
  if (this.sendThread.initialized)
1217
1350
  this.sendThread.stop();
@@ -1231,8 +1364,8 @@ class Driver extends shared_1.TypedEventEmitter {
1231
1364
  }
1232
1365
  try {
1233
1366
  // Attempt to close the value DBs
1234
- await ((_a = this._valueDB) === null || _a === void 0 ? void 0 : _a.close());
1235
- await ((_b = this._metadataDB) === null || _b === void 0 ? void 0 : _b.close());
1367
+ await ((_b = this._valueDB) === null || _b === void 0 ? void 0 : _b.close());
1368
+ await ((_c = this._metadataDB) === null || _c === void 0 ? void 0 : _c.close());
1236
1369
  }
1237
1370
  catch (e) {
1238
1371
  this.driverLog.print(`Closing the value DBs failed: ${(0, shared_1.getErrorMessage)(e)}`, "error");
@@ -1248,7 +1381,7 @@ class Driver extends shared_1.TypedEventEmitter {
1248
1381
  clearTimeout(timeout);
1249
1382
  }
1250
1383
  // Destroy all nodes
1251
- (_c = this._controller) === null || _c === void 0 ? void 0 : _c.nodes.forEach((n) => n.destroy());
1384
+ (_d = this._controller) === null || _d === void 0 ? void 0 : _d.nodes.forEach((n) => n.destroy());
1252
1385
  process.removeListener("exit", this._cleanupHandler);
1253
1386
  process.removeListener("SIGINT", this._cleanupHandler);
1254
1387
  process.removeListener("uncaughtException", this._cleanupHandler);
@@ -1461,7 +1594,7 @@ class Driver extends shared_1.TypedEventEmitter {
1461
1594
  throw e;
1462
1595
  }
1463
1596
  async handleSecurityS2DecodeError(e, msg) {
1464
- var _a;
1597
+ var _a, _b;
1465
1598
  if (!(0, core_1.isZWaveError)(e))
1466
1599
  return false;
1467
1600
  if ((e.code === core_1.ZWaveErrorCodes.Security2CC_NoSPAN ||
@@ -1493,13 +1626,42 @@ class Driver extends shared_1.TypedEventEmitter {
1493
1626
  ? "Message authentication failed"
1494
1627
  : "No SPAN is established yet";
1495
1628
  if (this.controller.bootstrappingS2NodeId === nodeId) {
1496
- // The node is currently being bootstrapped. Us not being able to decode the command means we need to abort the bootstrapping process
1497
- this.controllerLog.logNode(nodeId, {
1498
- message: `${message}, cannot decode command. Aborting the S2 bootstrapping process...`,
1499
- level: "error",
1500
- direction: "inbound",
1501
- });
1502
- this.controller.cancelSecureBootstrapS2(shared_2.KEXFailType.BootstrappingCanceled);
1629
+ // The node is currently being bootstrapped.
1630
+ if ((_b = this.securityManager2) === null || _b === void 0 ? void 0 : _b.tempKeys.has(nodeId)) {
1631
+ // The DSK has been verified, so we should be able to decode this command.
1632
+ // If this is the first attempt, we need to request a nonce first
1633
+ if (this.securityManager2.getSPANState(nodeId).type ===
1634
+ core_1.SPANState.None) {
1635
+ this.controllerLog.logNode(nodeId, {
1636
+ message: `${message}, cannot decode command. Requesting a nonce...`,
1637
+ level: "verbose",
1638
+ direction: "outbound",
1639
+ });
1640
+ // Send the node our nonce
1641
+ node.commandClasses["Security 2"]
1642
+ .sendNonce()
1643
+ .catch(() => {
1644
+ // Ignore errors
1645
+ });
1646
+ }
1647
+ else {
1648
+ // Us repeatedly not being able to decode the command means we need to abort the bootstrapping process
1649
+ // because the PIN is wrong
1650
+ this.controllerLog.logNode(nodeId, {
1651
+ message: `${message}, cannot decode command. Aborting the S2 bootstrapping process...`,
1652
+ level: "error",
1653
+ direction: "inbound",
1654
+ });
1655
+ this.controller.cancelSecureBootstrapS2(shared_2.KEXFailType.BootstrappingCanceled);
1656
+ }
1657
+ }
1658
+ else {
1659
+ this.controllerLog.logNode(nodeId, {
1660
+ message: `Ignoring KEXSet because the DSK has not been verified yet`,
1661
+ level: "verbose",
1662
+ direction: "inbound",
1663
+ });
1664
+ }
1503
1665
  }
1504
1666
  else if (!this.hasPendingTransactions(isS2NonceReport)) {
1505
1667
  this.controllerLog.logNode(nodeId, {
@@ -1999,6 +2161,31 @@ ${handlers.length} left`);
1999
2161
  return;
2000
2162
  }
2001
2163
  }
2164
+ else if (msg instanceof ApplicationUpdateRequest_1.ApplicationUpdateRequestSmartStartHomeIDReceived) {
2165
+ // the controller is in Smart Start learn mode and a node requests inclusion via Smart Start
2166
+ this.controllerLog.print("Received Smart Start inclusion request");
2167
+ if (this.controller.inclusionState !== Inclusion_1.InclusionState.Idle &&
2168
+ this.controller.inclusionState !== Inclusion_1.InclusionState.SmartStart) {
2169
+ this.controllerLog.print("Controller is busy and cannot handle this inclusion request right now...");
2170
+ return;
2171
+ }
2172
+ // Check if the node is on the provisioning list
2173
+ const provisioningEntry = this.controller.provisioningList.find((entry) => (0, core_1.nwiHomeIdFromDSK)((0, core_1.dskFromString)(entry.dsk)).equals(msg.nwiHomeId));
2174
+ if (!provisioningEntry) {
2175
+ this.controllerLog.print("NWI Home ID not found in provisioning list, ignoring request...");
2176
+ return;
2177
+ }
2178
+ this.controllerLog.print("NWI Home ID found in provisioning list, including node...");
2179
+ try {
2180
+ const result = await this.controller.beginInclusionSmartStart(provisioningEntry);
2181
+ if (!result) {
2182
+ this.controllerLog.print("Smart Start inclusion could not be started", "error");
2183
+ }
2184
+ }
2185
+ catch (e) {
2186
+ this.controllerLog.print(`Smart Start inclusion could not be started: ${(0, shared_1.getErrorMessage)(e)}`, "error");
2187
+ }
2188
+ }
2002
2189
  }
2003
2190
  else {
2004
2191
  // Check if we have a dynamic handler waiting for this message