zwave-js 10.3.0 → 10.4.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.
- package/build/Controller.d.ts +1 -1
- package/build/Controller.d.ts.map +1 -1
- package/build/Controller.js +2 -1
- package/build/Controller.js.map +1 -1
- package/build/Controller_safe.d.ts +1 -1
- package/build/Controller_safe.d.ts.map +1 -1
- package/build/Controller_safe.js +2 -1
- package/build/Controller_safe.js.map +1 -1
- package/build/lib/controller/Controller.d.ts +65 -2
- package/build/lib/controller/Controller.d.ts.map +1 -1
- package/build/lib/controller/Controller.js +670 -21
- package/build/lib/controller/Controller.js.map +1 -1
- package/build/lib/controller/FirmwareUpdateService.d.ts +2 -1
- package/build/lib/controller/FirmwareUpdateService.d.ts.map +1 -1
- package/build/lib/controller/FirmwareUpdateService.js +47 -82
- package/build/lib/controller/FirmwareUpdateService.js.map +1 -1
- package/build/lib/controller/Inclusion.d.ts +9 -4
- package/build/lib/controller/Inclusion.d.ts.map +1 -1
- package/build/lib/controller/Inclusion.js.map +1 -1
- package/build/lib/controller/NodeInformationFrame.d.ts.map +1 -1
- package/build/lib/controller/NodeInformationFrame.js +3 -2
- package/build/lib/controller/NodeInformationFrame.js.map +1 -1
- package/build/lib/controller/_Types.d.ts +24 -2
- package/build/lib/controller/_Types.d.ts.map +1 -1
- package/build/lib/controller/_Types.js +13 -0
- package/build/lib/controller/_Types.js.map +1 -1
- package/build/lib/driver/Bootloader.d.ts +22 -0
- package/build/lib/driver/Bootloader.d.ts.map +1 -0
- package/build/lib/driver/Bootloader.js +52 -0
- package/build/lib/driver/Bootloader.js.map +1 -0
- package/build/lib/driver/CommandQueueMachine.d.ts +4 -4
- package/build/lib/driver/CommandQueueMachine.d.ts.map +1 -1
- package/build/lib/driver/Driver.d.ts +27 -3
- package/build/lib/driver/Driver.d.ts.map +1 -1
- package/build/lib/driver/Driver.js +178 -51
- package/build/lib/driver/Driver.js.map +1 -1
- package/build/lib/driver/DriverMock.d.ts +5 -1
- package/build/lib/driver/DriverMock.d.ts.map +1 -1
- package/build/lib/driver/DriverMock.js +5 -1
- package/build/lib/driver/DriverMock.js.map +1 -1
- package/build/lib/driver/MessageGenerators.d.ts +1 -1
- package/build/lib/driver/MessageGenerators.d.ts.map +1 -1
- package/build/lib/driver/SendThreadMachine.d.ts +7 -7
- package/build/lib/driver/SendThreadMachine.d.ts.map +1 -1
- package/build/lib/driver/SerialAPICommandMachine.d.ts +8 -8
- package/build/lib/driver/SerialAPICommandMachine.d.ts.map +1 -1
- package/build/lib/driver/SerialAPICommandMachine.js +7 -1
- package/build/lib/driver/SerialAPICommandMachine.js.map +1 -1
- package/build/lib/driver/StateMachineShared.d.ts +2 -2
- package/build/lib/driver/StateMachineShared.d.ts.map +1 -1
- package/build/lib/driver/TransactionMachine.d.ts +3 -3
- package/build/lib/driver/TransactionMachine.d.ts.map +1 -1
- package/build/lib/driver/TransportServiceMachine.d.ts +4 -4
- package/build/lib/driver/TransportServiceMachine.d.ts.map +1 -1
- package/build/lib/driver/ZWaveOptions.d.ts +12 -1
- package/build/lib/driver/ZWaveOptions.d.ts.map +1 -1
- package/build/lib/node/Node.d.ts +3 -3
- package/build/lib/node/Node.d.ts.map +1 -1
- package/build/lib/node/Node.js +65 -14
- package/build/lib/node/Node.js.map +1 -1
- package/build/lib/node/NodeReadyMachine.d.ts +3 -3
- package/build/lib/node/NodeReadyMachine.d.ts.map +1 -1
- package/build/lib/node/NodeStatusMachine.d.ts +3 -3
- package/build/lib/node/NodeStatusMachine.d.ts.map +1 -1
- package/build/lib/node/_Types.d.ts +21 -21
- package/build/lib/node/_Types.d.ts.map +1 -1
- package/build/lib/serialapi/application/ApplicationUpdateRequest.d.ts +14 -10
- package/build/lib/serialapi/application/ApplicationUpdateRequest.d.ts.map +1 -1
- package/build/lib/serialapi/application/ApplicationUpdateRequest.js +27 -16
- package/build/lib/serialapi/application/ApplicationUpdateRequest.js.map +1 -1
- package/build/lib/serialapi/network-mgmt/RequestNodeInfoMessages.d.ts +3 -0
- package/build/lib/serialapi/network-mgmt/RequestNodeInfoMessages.d.ts.map +1 -1
- package/build/lib/serialapi/network-mgmt/RequestNodeInfoMessages.js +12 -0
- package/build/lib/serialapi/network-mgmt/RequestNodeInfoMessages.js.map +1 -1
- package/build/lib/serialapi/nvm/FirmwareUpdateNVMMessages.d.ts +96 -0
- package/build/lib/serialapi/nvm/FirmwareUpdateNVMMessages.d.ts.map +1 -0
- package/build/lib/serialapi/nvm/FirmwareUpdateNVMMessages.js +326 -0
- package/build/lib/serialapi/nvm/FirmwareUpdateNVMMessages.js.map +1 -0
- package/build/lib/serialapi/nvm/GetNVMIdMessages.d.ts +1 -1
- package/build/lib/serialapi/nvm/GetNVMIdMessages.d.ts.map +1 -1
- package/build/lib/serialapi/transport/SendDataShared.d.ts +3 -3
- package/build/lib/serialapi/transport/SendDataShared.d.ts.map +1 -1
- package/package.json +15 -15
|
@@ -59,6 +59,7 @@ const SendDataShared_1 = require("../serialapi/transport/SendDataShared");
|
|
|
59
59
|
const deviceConfig_1 = require("../telemetry/deviceConfig");
|
|
60
60
|
const sentry_1 = require("../telemetry/sentry");
|
|
61
61
|
const statistics_1 = require("../telemetry/statistics");
|
|
62
|
+
const Bootloader_1 = require("./Bootloader");
|
|
62
63
|
const MessageGenerators_1 = require("./MessageGenerators");
|
|
63
64
|
const NetworkCache_1 = require("./NetworkCache");
|
|
64
65
|
const SendThreadMachine_1 = require("./SendThreadMachine");
|
|
@@ -195,6 +196,8 @@ class Driver extends shared_1.TypedEventEmitter {
|
|
|
195
196
|
this.awaitedMessages = [];
|
|
196
197
|
/** A map of awaited commands */
|
|
197
198
|
this.awaitedCommands = [];
|
|
199
|
+
/** A map of awaited chunks from the bootloader */
|
|
200
|
+
this.awaitedBootloaderChunks = [];
|
|
198
201
|
/** A map of Node ID -> ongoing sessions */
|
|
199
202
|
this.nodeSessions = new Map();
|
|
200
203
|
this._wasStarted = false;
|
|
@@ -457,6 +460,16 @@ class Driver extends shared_1.TypedEventEmitter {
|
|
|
457
460
|
return this._controller;
|
|
458
461
|
}
|
|
459
462
|
/** @internal */
|
|
463
|
+
get bootloader() {
|
|
464
|
+
if (this._bootloader == undefined) {
|
|
465
|
+
throw new core_1.ZWaveError("The controller is not in bootloader mode!", core_1.ZWaveErrorCodes.Driver_NotReady);
|
|
466
|
+
}
|
|
467
|
+
return this._bootloader;
|
|
468
|
+
}
|
|
469
|
+
isInBootloader() {
|
|
470
|
+
return this._bootloader != undefined;
|
|
471
|
+
}
|
|
472
|
+
/** @internal */
|
|
460
473
|
get securityManager() {
|
|
461
474
|
return this._securityManager;
|
|
462
475
|
}
|
|
@@ -608,6 +621,7 @@ class Driver extends shared_1.TypedEventEmitter {
|
|
|
608
621
|
}
|
|
609
622
|
this.serial
|
|
610
623
|
.on("data", this.serialport_onData.bind(this))
|
|
624
|
+
.on("bootloaderData", this.serialport_onBootloaderData.bind(this))
|
|
611
625
|
.on("error", (err) => {
|
|
612
626
|
if (this.isSoftResetting && !this.serial?.isOpen) {
|
|
613
627
|
// A disconnection while soft resetting is to be expected
|
|
@@ -650,6 +664,33 @@ class Driver extends shared_1.TypedEventEmitter {
|
|
|
650
664
|
// Per the specs, this should be followed by a soft-reset but we need to be able
|
|
651
665
|
// to handle sticks that don't support the soft reset command. Therefore we do it
|
|
652
666
|
// after opening the value DBs
|
|
667
|
+
if (!this.options.testingHooks?.skipBootloaderCheck) {
|
|
668
|
+
// After an incomplete firmware upgrade, we might be stuck in the bootloader
|
|
669
|
+
// Therefore wait a short amount of time to see if the serialport detects bootloader mode.
|
|
670
|
+
// If we are, the bootloader will reply with its menu.
|
|
671
|
+
await (0, async_1.wait)(1000);
|
|
672
|
+
if (this._bootloader) {
|
|
673
|
+
this.driverLog.print("Controller is in bootloader, attempting to recover...", "warn");
|
|
674
|
+
await this.leaveBootloaderInternal();
|
|
675
|
+
// Wait a short time again. If we're in bootloader mode again, we're stuck
|
|
676
|
+
await (0, async_1.wait)(1000);
|
|
677
|
+
if (this._bootloader) {
|
|
678
|
+
if (this.options.allowBootloaderOnly) {
|
|
679
|
+
this.driverLog.print("Failed to recover from bootloader. Staying in bootloader mode as requested.", "warn");
|
|
680
|
+
// Needed for the OTW feature to be available
|
|
681
|
+
this._controller = new Controller_1.ZWaveController(this, true);
|
|
682
|
+
this.emit("bootloader ready");
|
|
683
|
+
}
|
|
684
|
+
else {
|
|
685
|
+
const message = "Failed to recover from bootloader. Please flash a new firmware to continue...";
|
|
686
|
+
this.driverLog.print(message, "error");
|
|
687
|
+
this.emit("error", new core_1.ZWaveError(message, core_1.ZWaveErrorCodes.Driver_Failed));
|
|
688
|
+
void this.destroy();
|
|
689
|
+
}
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
}
|
|
653
694
|
// Try to create the cache directory. This can fail, in which case we should expose a good error message
|
|
654
695
|
try {
|
|
655
696
|
await this.options.storage.driver.ensureDir(this.cacheDir);
|
|
@@ -1538,6 +1579,11 @@ class Driver extends shared_1.TypedEventEmitter {
|
|
|
1538
1579
|
this.controllerLog.print(message, "error");
|
|
1539
1580
|
throw new core_1.ZWaveError(message, core_1.ZWaveErrorCodes.Driver_FeatureDisabled);
|
|
1540
1581
|
}
|
|
1582
|
+
if (this._controller?.isAnyOTAFirmwareUpdateInProgress()) {
|
|
1583
|
+
const message = `Failed to soft reset controller: A firmware update is in progress on this network.`;
|
|
1584
|
+
this.controllerLog.print(message, "error");
|
|
1585
|
+
throw new core_1.ZWaveError(message, core_1.ZWaveErrorCodes.FirmwareUpdateCC_NetworkBusy);
|
|
1586
|
+
}
|
|
1541
1587
|
return this.softResetInternal(true);
|
|
1542
1588
|
}
|
|
1543
1589
|
async softResetInternal(destroyOnError) {
|
|
@@ -1612,7 +1658,9 @@ class Driver extends shared_1.TypedEventEmitter {
|
|
|
1612
1658
|
}
|
|
1613
1659
|
// Wait the configured amount of time for the Serial API started command to be received
|
|
1614
1660
|
this.controllerLog.print("Waiting for the Serial API to start...");
|
|
1615
|
-
waitResult = await this.waitForMessage((msg) =>
|
|
1661
|
+
waitResult = await this.waitForMessage((msg) => {
|
|
1662
|
+
return msg.functionType === serial_1.FunctionType.SerialAPIStarted;
|
|
1663
|
+
}, this.options.timeouts.serialAPIStarted).catch(() => false);
|
|
1616
1664
|
if (waitResult) {
|
|
1617
1665
|
// Serial API did start, maybe do something with the information?
|
|
1618
1666
|
this.controllerLog.print("Serial API started");
|
|
@@ -1656,9 +1704,14 @@ class Driver extends shared_1.TypedEventEmitter {
|
|
|
1656
1704
|
*/
|
|
1657
1705
|
async hardReset() {
|
|
1658
1706
|
this.ensureReady(true);
|
|
1707
|
+
if (this.controller.isAnyOTAFirmwareUpdateInProgress()) {
|
|
1708
|
+
const message = `Failed to hard reset controller: A firmware update is in progress on this network.`;
|
|
1709
|
+
this.controllerLog.print(message, "error");
|
|
1710
|
+
throw new core_1.ZWaveError(message, core_1.ZWaveErrorCodes.FirmwareUpdateCC_NetworkBusy);
|
|
1711
|
+
}
|
|
1659
1712
|
// Update the controller NIF prior to hard resetting
|
|
1660
|
-
await this.
|
|
1661
|
-
await this.
|
|
1713
|
+
await this.controller.setControllerNIF();
|
|
1714
|
+
await this.controller.hardReset();
|
|
1662
1715
|
// Clean up
|
|
1663
1716
|
this.rejectTransactions(() => true, `The controller was hard-reset`);
|
|
1664
1717
|
this.sendNodeToSleepTimers.forEach((timeout) => clearTimeout(timeout));
|
|
@@ -1682,6 +1735,9 @@ class Driver extends shared_1.TypedEventEmitter {
|
|
|
1682
1735
|
if (includingController && !this._controllerInterviewed) {
|
|
1683
1736
|
throw new core_1.ZWaveError("The controller is not ready yet", core_1.ZWaveErrorCodes.Driver_NotReady);
|
|
1684
1737
|
}
|
|
1738
|
+
if (this._bootloader) {
|
|
1739
|
+
throw new core_1.ZWaveError("Cannot do this while in bootloader mode", core_1.ZWaveErrorCodes.Driver_NotReady);
|
|
1740
|
+
}
|
|
1685
1741
|
}
|
|
1686
1742
|
/** Indicates whether the driver is ready, i.e. the "driver ready" event was emitted */
|
|
1687
1743
|
get ready() {
|
|
@@ -1737,6 +1793,7 @@ class Driver extends shared_1.TypedEventEmitter {
|
|
|
1737
1793
|
this.statisticsTimeout,
|
|
1738
1794
|
...this.awaitedCommands.map((c) => c.timeout),
|
|
1739
1795
|
...this.awaitedMessages.map((m) => m.timeout),
|
|
1796
|
+
...this.awaitedBootloaderChunks.map((b) => b.timeout),
|
|
1740
1797
|
]) {
|
|
1741
1798
|
if (timeout)
|
|
1742
1799
|
clearTimeout(timeout);
|
|
@@ -2597,54 +2654,9 @@ ${handlers.length} left`);
|
|
|
2597
2654
|
return;
|
|
2598
2655
|
}
|
|
2599
2656
|
else if (msg instanceof ApplicationUpdateRequest_1.ApplicationUpdateRequest) {
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
this.controllerLog.logNode(node.id, {
|
|
2604
|
-
message: "Received updated node info",
|
|
2605
|
-
direction: "inbound",
|
|
2606
|
-
});
|
|
2607
|
-
node.updateNodeInfo(msg.nodeInformation);
|
|
2608
|
-
// Tell the send thread that we received a NIF from the node
|
|
2609
|
-
this.sendThread.send({ type: "NIF", nodeId: node.id });
|
|
2610
|
-
if (node.canSleep &&
|
|
2611
|
-
node.supportsCC(core_1.CommandClasses["Wake Up"])) {
|
|
2612
|
-
// In case this is a sleeping node and there are no messages in the queue, the node may go back to sleep very soon
|
|
2613
|
-
this.debounceSendNodeToSleep(node);
|
|
2614
|
-
}
|
|
2615
|
-
return;
|
|
2616
|
-
}
|
|
2617
|
-
}
|
|
2618
|
-
else if (msg instanceof ApplicationUpdateRequest_1.ApplicationUpdateRequestSmartStartHomeIDReceived) {
|
|
2619
|
-
// the controller is in Smart Start learn mode and a node requests inclusion via Smart Start
|
|
2620
|
-
this.controllerLog.print("Received Smart Start inclusion request");
|
|
2621
|
-
if (this.controller.inclusionState !== Inclusion_1.InclusionState.Idle &&
|
|
2622
|
-
this.controller.inclusionState !== Inclusion_1.InclusionState.SmartStart) {
|
|
2623
|
-
this.controllerLog.print("Controller is busy and cannot handle this inclusion request right now...");
|
|
2624
|
-
return;
|
|
2625
|
-
}
|
|
2626
|
-
// Check if the node is on the provisioning list
|
|
2627
|
-
const provisioningEntry = this.controller.provisioningList.find((entry) => (0, core_1.nwiHomeIdFromDSK)((0, core_1.dskFromString)(entry.dsk)).equals(msg.nwiHomeId));
|
|
2628
|
-
if (!provisioningEntry) {
|
|
2629
|
-
this.controllerLog.print("NWI Home ID not found in provisioning list, ignoring request...");
|
|
2630
|
-
return;
|
|
2631
|
-
}
|
|
2632
|
-
else if (provisioningEntry.status ===
|
|
2633
|
-
Inclusion_1.ProvisioningEntryStatus.Inactive) {
|
|
2634
|
-
this.controllerLog.print("The provisioning entry for this node is inactive, ignoring request...");
|
|
2635
|
-
return;
|
|
2636
|
-
}
|
|
2637
|
-
this.controllerLog.print("NWI Home ID found in provisioning list, including node...");
|
|
2638
|
-
try {
|
|
2639
|
-
const result = await this.controller.beginInclusionSmartStart(provisioningEntry);
|
|
2640
|
-
if (!result) {
|
|
2641
|
-
this.controllerLog.print("Smart Start inclusion could not be started", "error");
|
|
2642
|
-
}
|
|
2643
|
-
}
|
|
2644
|
-
catch (e) {
|
|
2645
|
-
this.controllerLog.print(`Smart Start inclusion could not be started: ${(0, shared_1.getErrorMessage)(e)}`, "error");
|
|
2646
|
-
}
|
|
2647
|
-
}
|
|
2657
|
+
// Make sure we're ready to handle this command
|
|
2658
|
+
this.ensureReady(true);
|
|
2659
|
+
return this.controller.handleApplicationUpdateRequest(msg);
|
|
2648
2660
|
}
|
|
2649
2661
|
else {
|
|
2650
2662
|
// TODO: This deserves a nicer formatting
|
|
@@ -3482,6 +3494,121 @@ ${handlers.length} left`);
|
|
|
3482
3494
|
}
|
|
3483
3495
|
return true;
|
|
3484
3496
|
}
|
|
3497
|
+
/** @internal */
|
|
3498
|
+
async enterBootloader() {
|
|
3499
|
+
this.controllerLog.print("Entering bootloader...");
|
|
3500
|
+
// await this.controller.toggleRF(false);
|
|
3501
|
+
await this.trySoftReset();
|
|
3502
|
+
this.pauseSendThread();
|
|
3503
|
+
// It would be nicer to not hardcode the command here, but since we're switching stream parsers
|
|
3504
|
+
// mid-command - thus ignoring the ACK, we can't really use the existing communication machinery
|
|
3505
|
+
const promise = this.writeSerial(Buffer.from("01030027db", "hex"));
|
|
3506
|
+
this.serial.mode = serial_1.ZWaveSerialMode.Bootloader;
|
|
3507
|
+
await promise;
|
|
3508
|
+
// Wait if the menu shows up
|
|
3509
|
+
this._enterBootloaderPromise = (0, deferred_promise_1.createDeferredPromise)();
|
|
3510
|
+
const success = await Promise.race([
|
|
3511
|
+
this._enterBootloaderPromise.then(() => true),
|
|
3512
|
+
(0, async_1.wait)(5000, true).then(() => false),
|
|
3513
|
+
]);
|
|
3514
|
+
if (success) {
|
|
3515
|
+
this.controllerLog.print("Entered bootloader");
|
|
3516
|
+
}
|
|
3517
|
+
else {
|
|
3518
|
+
throw new core_1.ZWaveError("Failed to enter bootloader", core_1.ZWaveErrorCodes.Controller_Timeout);
|
|
3519
|
+
}
|
|
3520
|
+
}
|
|
3521
|
+
leaveBootloaderInternal() {
|
|
3522
|
+
const promise = this.bootloader.runApplication();
|
|
3523
|
+
// Reset the known serial mode. We might end up in serial or bootloader mode afterwards.
|
|
3524
|
+
this.serial.mode = undefined;
|
|
3525
|
+
this._bootloader = undefined;
|
|
3526
|
+
return promise;
|
|
3527
|
+
}
|
|
3528
|
+
/**
|
|
3529
|
+
* @internal
|
|
3530
|
+
* Leaves the bootloader and destroys the driver instance if desired
|
|
3531
|
+
*/
|
|
3532
|
+
async leaveBootloader(destroy = false) {
|
|
3533
|
+
this.controllerLog.print("Leaving bootloader...");
|
|
3534
|
+
await this.leaveBootloaderInternal();
|
|
3535
|
+
// TODO: do we need to wait here?
|
|
3536
|
+
if (destroy) {
|
|
3537
|
+
const restartReason = "Restarting driver after OTW update...";
|
|
3538
|
+
this.controllerLog.print(restartReason);
|
|
3539
|
+
await this.destroy();
|
|
3540
|
+
// Let the async calling context finish before emitting the error
|
|
3541
|
+
process.nextTick(() => {
|
|
3542
|
+
this.emit("error", new core_1.ZWaveError(restartReason, core_1.ZWaveErrorCodes.Driver_Failed));
|
|
3543
|
+
});
|
|
3544
|
+
}
|
|
3545
|
+
else {
|
|
3546
|
+
this.unpauseSendThread();
|
|
3547
|
+
await this.ensureSerialAPI();
|
|
3548
|
+
}
|
|
3549
|
+
}
|
|
3550
|
+
serialport_onBootloaderData(data) {
|
|
3551
|
+
switch (data.type) {
|
|
3552
|
+
case serial_1.BootloaderChunkType.Message: {
|
|
3553
|
+
this.controllerLog.print(`[BOOTLOADER] ${data.message}`, "verbose");
|
|
3554
|
+
break;
|
|
3555
|
+
}
|
|
3556
|
+
case serial_1.BootloaderChunkType.FlowControl: {
|
|
3557
|
+
if (data.command === serial_1.XModemMessageHeaders.C) {
|
|
3558
|
+
this.controllerLog.print(`[BOOTLOADER] awaiting input...`, "verbose");
|
|
3559
|
+
}
|
|
3560
|
+
break;
|
|
3561
|
+
}
|
|
3562
|
+
}
|
|
3563
|
+
for (const entry of this.awaitedBootloaderChunks) {
|
|
3564
|
+
if (entry.predicate(data)) {
|
|
3565
|
+
// resolve the promise - this will remove the entry from the list
|
|
3566
|
+
entry.promise.resolve(data);
|
|
3567
|
+
return;
|
|
3568
|
+
}
|
|
3569
|
+
}
|
|
3570
|
+
if (!this._bootloader && data.type === serial_1.BootloaderChunkType.Menu) {
|
|
3571
|
+
// We just entered the bootloader
|
|
3572
|
+
this.controllerLog.print(`[BOOTLOADER] version ${data.version}`, "verbose");
|
|
3573
|
+
this._bootloader = new Bootloader_1.Bootloader(this.writeSerial.bind(this), data.version, data.options);
|
|
3574
|
+
if (this._enterBootloaderPromise) {
|
|
3575
|
+
this._enterBootloaderPromise.resolve();
|
|
3576
|
+
this._enterBootloaderPromise = undefined;
|
|
3577
|
+
}
|
|
3578
|
+
}
|
|
3579
|
+
}
|
|
3580
|
+
/**
|
|
3581
|
+
* Waits until a specific chunk is received from the bootloader or a timeout has elapsed. Returns the received chunk.
|
|
3582
|
+
* @param timeout The number of milliseconds to wait. If the timeout elapses, the returned promise will be rejected
|
|
3583
|
+
* @param predicate A predicate function to test all incoming chunks
|
|
3584
|
+
*/
|
|
3585
|
+
waitForBootloaderChunk(predicate, timeout) {
|
|
3586
|
+
return new Promise((resolve, reject) => {
|
|
3587
|
+
const entry = {
|
|
3588
|
+
predicate,
|
|
3589
|
+
promise: (0, deferred_promise_1.createDeferredPromise)(),
|
|
3590
|
+
timeout: undefined,
|
|
3591
|
+
};
|
|
3592
|
+
this.awaitedBootloaderChunks.push(entry);
|
|
3593
|
+
const removeEntry = () => {
|
|
3594
|
+
if (entry.timeout)
|
|
3595
|
+
clearTimeout(entry.timeout);
|
|
3596
|
+
const index = this.awaitedBootloaderChunks.indexOf(entry);
|
|
3597
|
+
if (index !== -1)
|
|
3598
|
+
this.awaitedBootloaderChunks.splice(index, 1);
|
|
3599
|
+
};
|
|
3600
|
+
// When the timeout elapses, remove the wait entry and reject the returned Promise
|
|
3601
|
+
entry.timeout = setTimeout(() => {
|
|
3602
|
+
removeEntry();
|
|
3603
|
+
reject(new core_1.ZWaveError(`Received no matching chunk within the provided timeout!`, core_1.ZWaveErrorCodes.Controller_Timeout));
|
|
3604
|
+
}, timeout);
|
|
3605
|
+
// When the promise is resolved, remove the wait entry and resolve the returned Promise
|
|
3606
|
+
void entry.promise.then((cc) => {
|
|
3607
|
+
removeEntry();
|
|
3608
|
+
resolve(cc);
|
|
3609
|
+
});
|
|
3610
|
+
});
|
|
3611
|
+
}
|
|
3485
3612
|
}
|
|
3486
3613
|
exports.Driver = Driver;
|
|
3487
3614
|
//# sourceMappingURL=Driver.js.map
|