zwave-js 15.2.0 → 15.3.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/cjs/index_browser.js.map +2 -2
- package/build/cjs/lib/_version.d.ts +1 -1
- package/build/cjs/lib/_version.js +1 -1
- package/build/cjs/lib/_version.js.map +1 -1
- package/build/cjs/lib/controller/Controller.js +5 -4
- package/build/cjs/lib/controller/Controller.js.map +2 -2
- package/build/cjs/lib/driver/Driver.d.ts +12 -2
- package/build/cjs/lib/driver/Driver.js +141 -108
- package/build/cjs/lib/driver/Driver.js.map +2 -2
- package/build/cjs/lib/driver/DriverMock.js +1 -1
- package/build/cjs/lib/driver/DriverMock.js.map +2 -2
- package/build/cjs/lib/driver/Queue.d.ts +1 -1
- package/build/cjs/lib/driver/Queue.js +1 -0
- package/build/cjs/lib/driver/Queue.js.map +2 -2
- package/build/cjs/lib/driver/mDNSDiscovery/node.d.ts +3 -0
- package/build/cjs/lib/driver/mDNSDiscovery/node.js +97 -0
- package/build/cjs/lib/driver/mDNSDiscovery/node.js.map +7 -0
- package/build/cjs/lib/driver/mDNSDiscovery/stub.d.ts +3 -0
- package/build/cjs/lib/driver/mDNSDiscovery/stub.js +33 -0
- package/build/cjs/lib/driver/mDNSDiscovery/stub.js.map +7 -0
- package/build/cjs/lib/driver/mDNSDiscovery.d.ts +1 -1
- package/build/cjs/lib/driver/mDNSDiscovery.js +2 -70
- package/build/cjs/lib/driver/mDNSDiscovery.js.map +3 -3
- package/build/cjs/lib/node/Node.js +3 -1
- package/build/cjs/lib/node/Node.js.map +2 -2
- package/build/cjs/lib/zniffer/Zniffer.js +3 -3
- package/build/cjs/lib/zniffer/Zniffer.js.map +2 -2
- package/build/cjs/package.json +30 -1
- package/build/esm/index_browser.d.ts.map +1 -1
- package/build/esm/index_browser.js +1 -0
- package/build/esm/index_browser.js.map +1 -1
- package/build/esm/lib/_version.d.ts +1 -1
- package/build/esm/lib/_version.js +1 -1
- package/build/esm/lib/controller/Controller.d.ts.map +1 -1
- package/build/esm/lib/controller/Controller.js +7 -7
- package/build/esm/lib/controller/Controller.js.map +1 -1
- package/build/esm/lib/driver/Driver.d.ts +12 -2
- package/build/esm/lib/driver/Driver.d.ts.map +1 -1
- package/build/esm/lib/driver/Driver.js +186 -146
- package/build/esm/lib/driver/Driver.js.map +1 -1
- package/build/esm/lib/driver/DriverMock.js +1 -1
- package/build/esm/lib/driver/DriverMock.js.map +1 -1
- package/build/esm/lib/driver/Queue.d.ts +1 -1
- package/build/esm/lib/driver/Queue.d.ts.map +1 -1
- package/build/esm/lib/driver/Queue.js +1 -0
- package/build/esm/lib/driver/Queue.js.map +1 -1
- package/build/esm/lib/driver/mDNSDiscovery/node.d.ts +3 -0
- package/build/esm/lib/driver/mDNSDiscovery/node.d.ts.map +1 -0
- package/build/esm/lib/driver/mDNSDiscovery/node.js +70 -0
- package/build/esm/lib/driver/mDNSDiscovery/node.js.map +1 -0
- package/build/esm/lib/driver/mDNSDiscovery/stub.d.ts +3 -0
- package/build/esm/lib/driver/mDNSDiscovery/stub.d.ts.map +1 -0
- package/build/esm/lib/driver/mDNSDiscovery/stub.js +5 -0
- package/build/esm/lib/driver/mDNSDiscovery/stub.js.map +1 -0
- package/build/esm/lib/driver/mDNSDiscovery.d.ts +1 -1
- package/build/esm/lib/driver/mDNSDiscovery.d.ts.map +1 -1
- package/build/esm/lib/driver/mDNSDiscovery.js +1 -69
- package/build/esm/lib/driver/mDNSDiscovery.js.map +1 -1
- package/build/esm/lib/node/Node.d.ts.map +1 -1
- package/build/esm/lib/node/Node.js +6 -2
- package/build/esm/lib/node/Node.js.map +1 -1
- package/build/esm/lib/zniffer/Zniffer.js +3 -3
- package/build/esm/lib/zniffer/Zniffer.js.map +1 -1
- package/build/esm/package.json +30 -1
- package/package.json +40 -11
|
@@ -64,11 +64,15 @@ export declare class Driver extends TypedEventTarget<DriverEventCallbacks> imple
|
|
|
64
64
|
private serialAPIQueue;
|
|
65
65
|
/** Gives access to the transaction queues, ordered by priority */
|
|
66
66
|
private get queues();
|
|
67
|
+
private initTransactionQueues;
|
|
68
|
+
private destroyTransactionQueues;
|
|
67
69
|
private _scheduler;
|
|
68
70
|
get scheduler(): TaskScheduler;
|
|
69
71
|
private queuePaused;
|
|
70
72
|
/** Used to immediately abort ongoing Serial API commands */
|
|
71
73
|
private abortSerialAPICommand;
|
|
74
|
+
private initSerialAPIQueue;
|
|
75
|
+
private destroySerialAPIQueue;
|
|
72
76
|
private _queuesBusyFlags;
|
|
73
77
|
private _queueIdle;
|
|
74
78
|
/** Whether the queue is currently idle */
|
|
@@ -359,6 +363,8 @@ export declare class Driver extends TypedEventTarget<DriverEventCallbacks> imple
|
|
|
359
363
|
*/
|
|
360
364
|
softReset(): Promise<void>;
|
|
361
365
|
private softResetInternal;
|
|
366
|
+
/** Soft-reset the Z-Wave module and restart the driver instance */
|
|
367
|
+
softResetAndRestart(): Promise<void>;
|
|
362
368
|
/**
|
|
363
369
|
* Checks whether recovering an unresponsive controller is enabled
|
|
364
370
|
* and whether the driver is in a state where it makes sense.
|
|
@@ -394,6 +400,10 @@ export declare class Driver extends TypedEventTarget<DriverEventCallbacks> imple
|
|
|
394
400
|
* Must be called under any circumstances.
|
|
395
401
|
*/
|
|
396
402
|
destroy(): Promise<void>;
|
|
403
|
+
/** Cleanly destroy the controller instance, but not the entire driver */
|
|
404
|
+
private destroyController;
|
|
405
|
+
private closeDatabases;
|
|
406
|
+
private clearAllTimeouts;
|
|
397
407
|
private handleSerialData;
|
|
398
408
|
/**
|
|
399
409
|
* Is called when the serial port has received a single-byte message or a complete message buffer
|
|
@@ -653,9 +663,9 @@ export declare class Driver extends TypedEventTarget<DriverEventCallbacks> imple
|
|
|
653
663
|
private enterBootloaderFromCLI;
|
|
654
664
|
private leaveBootloaderInternal;
|
|
655
665
|
/**
|
|
656
|
-
* Leaves the bootloader
|
|
666
|
+
* Leaves the bootloader by running the application.
|
|
657
667
|
*/
|
|
658
|
-
leaveBootloader(
|
|
668
|
+
leaveBootloader(): Promise<void>;
|
|
659
669
|
private serialport_onBootloaderData;
|
|
660
670
|
/**
|
|
661
671
|
* Waits until a specific chunk is received from the bootloader or a timeout has elapsed. Returns the received chunk.
|
|
@@ -305,24 +305,6 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
305
305
|
},
|
|
306
306
|
getSupportedCCVersion: /* @__PURE__ */ __name((cc, nodeId, endpointIndex) => this.getSupportedCCVersion(cc, nodeId, endpointIndex), "getSupportedCCVersion")
|
|
307
307
|
};
|
|
308
|
-
this.immediateQueue = new import_Queue.TransactionQueue({
|
|
309
|
-
name: "immediate",
|
|
310
|
-
mayStartNextTransaction: /* @__PURE__ */ __name((t) => {
|
|
311
|
-
if (this.controller.status === import_core.ControllerStatus.Unresponsive) {
|
|
312
|
-
return t.message instanceof import_serialapi.SoftResetRequest || t.message instanceof import_serialapi.GetControllerVersionRequest;
|
|
313
|
-
}
|
|
314
|
-
if (this.controller.status === import_core.ControllerStatus.Jammed) {
|
|
315
|
-
return t.message instanceof import_serialapi.SoftResetRequest;
|
|
316
|
-
}
|
|
317
|
-
return !this.queuePaused && this.controller.status === import_core.ControllerStatus.Ready;
|
|
318
|
-
}, "mayStartNextTransaction")
|
|
319
|
-
});
|
|
320
|
-
this.queue = new import_Queue.TransactionQueue({
|
|
321
|
-
name: "normal",
|
|
322
|
-
mayStartNextTransaction: /* @__PURE__ */ __name((t) => this.mayStartTransaction(t), "mayStartNextTransaction")
|
|
323
|
-
});
|
|
324
|
-
this.serialAPIQueue = new import_shared.AsyncQueue();
|
|
325
|
-
this._queueIdle = false;
|
|
326
308
|
this._scheduler = new import_Task.TaskScheduler();
|
|
327
309
|
}
|
|
328
310
|
serialFactory;
|
|
@@ -342,8 +324,10 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
342
324
|
getDeviceConfig: /* @__PURE__ */ __name((nodeId) => this.getDeviceConfig(nodeId), "getDeviceConfig"),
|
|
343
325
|
sdkVersion: this._controller?.sdkVersion,
|
|
344
326
|
requestStorage: this._requestStorage,
|
|
345
|
-
ownNodeId: this.
|
|
346
|
-
|
|
327
|
+
ownNodeId: this._controller?.ownNodeId ?? 0,
|
|
328
|
+
// Unspecified node ID
|
|
329
|
+
homeId: this._controller?.homeId ?? 1431655765,
|
|
330
|
+
// Invalid home ID
|
|
347
331
|
nodeIdType: this._controller?.nodeIdType ?? import_core.NodeIDType.Short
|
|
348
332
|
};
|
|
349
333
|
}
|
|
@@ -357,14 +341,51 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
357
341
|
// We have multiple queues to achieve multiple "layers" of communication priority:
|
|
358
342
|
// The default queue for most messages
|
|
359
343
|
queue;
|
|
344
|
+
// Is initialized in initTransactionQueues()
|
|
360
345
|
// An immediate queue for handling queries that need to be handled ASAP, e.g. Nonce Get
|
|
361
346
|
immediateQueue;
|
|
347
|
+
// Is initialized in initTransactionQueues()
|
|
362
348
|
// And all of them feed into the serial API queue, which contains commands that will be sent ASAP
|
|
363
349
|
serialAPIQueue;
|
|
350
|
+
// Is initialized in initControllerAndNodes()
|
|
364
351
|
/** Gives access to the transaction queues, ordered by priority */
|
|
365
352
|
get queues() {
|
|
366
353
|
return [this.immediateQueue, this.queue];
|
|
367
354
|
}
|
|
355
|
+
initTransactionQueues() {
|
|
356
|
+
this.immediateQueue = new import_Queue.TransactionQueue({
|
|
357
|
+
name: "immediate",
|
|
358
|
+
mayStartNextTransaction: /* @__PURE__ */ __name((t) => {
|
|
359
|
+
if (this.controller.status === import_core.ControllerStatus.Unresponsive) {
|
|
360
|
+
return t.message instanceof import_serialapi.SoftResetRequest || t.message instanceof import_serialapi.GetControllerVersionRequest;
|
|
361
|
+
}
|
|
362
|
+
if (this.controller.status === import_core.ControllerStatus.Jammed) {
|
|
363
|
+
return t.message instanceof import_serialapi.SoftResetRequest;
|
|
364
|
+
}
|
|
365
|
+
return !this.queuePaused && this.controller.status === import_core.ControllerStatus.Ready;
|
|
366
|
+
}, "mayStartNextTransaction")
|
|
367
|
+
});
|
|
368
|
+
this.queue = new import_Queue.TransactionQueue({
|
|
369
|
+
name: "normal",
|
|
370
|
+
mayStartNextTransaction: /* @__PURE__ */ __name((t) => this.mayStartTransaction(t), "mayStartNextTransaction")
|
|
371
|
+
});
|
|
372
|
+
this._queueIdle = false;
|
|
373
|
+
for (const queue of this.queues) {
|
|
374
|
+
void this.drainTransactionQueue(queue);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
async destroyTransactionQueues(reason, errorCode) {
|
|
378
|
+
for (const queue of this.queues) {
|
|
379
|
+
if (!queue)
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
if ((0, import_shared.getenv)("NODE_ENV") !== "test") {
|
|
383
|
+
await this.rejectTransactions((_t) => true, reason, errorCode ?? import_core.ZWaveErrorCodes.Driver_TaskRemoved);
|
|
384
|
+
}
|
|
385
|
+
for (const queue of this.queues) {
|
|
386
|
+
queue.abort();
|
|
387
|
+
}
|
|
388
|
+
}
|
|
368
389
|
_scheduler;
|
|
369
390
|
get scheduler() {
|
|
370
391
|
return this._scheduler;
|
|
@@ -372,9 +393,19 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
372
393
|
queuePaused = false;
|
|
373
394
|
/** Used to immediately abort ongoing Serial API commands */
|
|
374
395
|
abortSerialAPICommand;
|
|
396
|
+
initSerialAPIQueue() {
|
|
397
|
+
this.serialAPIQueue = new import_shared.AsyncQueue();
|
|
398
|
+
void this.drainSerialAPIQueue();
|
|
399
|
+
}
|
|
400
|
+
destroySerialAPIQueue(reason, errorCode) {
|
|
401
|
+
if (!this.serialAPIQueue)
|
|
402
|
+
return;
|
|
403
|
+
this.serialAPIQueue.abort();
|
|
404
|
+
this.abortSerialAPICommand?.reject(new import_core.ZWaveError(reason, errorCode ?? import_core.ZWaveErrorCodes.Driver_Destroyed));
|
|
405
|
+
}
|
|
375
406
|
// Keep track of which queues are currently busy
|
|
376
407
|
_queuesBusyFlags = 0;
|
|
377
|
-
_queueIdle;
|
|
408
|
+
_queueIdle = false;
|
|
378
409
|
/** Whether the queue is currently idle */
|
|
379
410
|
get queueIdle() {
|
|
380
411
|
return this._queueIdle;
|
|
@@ -668,7 +699,11 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
668
699
|
*/
|
|
669
700
|
static async enumerateSerialPorts({ local = true, remote = true } = {}) {
|
|
670
701
|
const ret = [];
|
|
671
|
-
const bindings = (
|
|
702
|
+
const bindings = (
|
|
703
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
704
|
+
// @ts-ignore - For some reason, VSCode does not like this import, although tsc is fine with it
|
|
705
|
+
(await import("#default_bindings/serial")).serial
|
|
706
|
+
);
|
|
672
707
|
if (local && typeof bindings.list === "function") {
|
|
673
708
|
for (const port of await bindings.list()) {
|
|
674
709
|
if (port.type === "custom")
|
|
@@ -742,10 +777,10 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
742
777
|
return Promise.resolve();
|
|
743
778
|
this._wasStarted = true;
|
|
744
779
|
this.bindings = {
|
|
745
|
-
fs: this._options.host?.fs ?? (await import("
|
|
746
|
-
serial: this._options.host?.serial ?? (await import("
|
|
747
|
-
db: this._options.host?.db ?? (await import("
|
|
748
|
-
log: this._options.host?.log ?? (await import("
|
|
780
|
+
fs: this._options.host?.fs ?? (await import("#default_bindings/fs")).fs,
|
|
781
|
+
serial: this._options.host?.serial ?? (await import("#default_bindings/serial")).serial,
|
|
782
|
+
db: this._options.host?.db ?? (await import("#default_bindings/db")).db,
|
|
783
|
+
log: this._options.host?.log ?? (await import("#default_bindings/log")).log
|
|
749
784
|
};
|
|
750
785
|
this._logContainer = this.bindings.log(this._options.logConfig);
|
|
751
786
|
this._driverLog = new import_Driver.DriverLogger(this, this._logContainer);
|
|
@@ -791,10 +826,6 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
791
826
|
this.driverLog.print("serial port opened");
|
|
792
827
|
this._isOpen = true;
|
|
793
828
|
spOpenPromise.resolve();
|
|
794
|
-
for (const queue of this.queues) {
|
|
795
|
-
void this.drainTransactionQueue(queue);
|
|
796
|
-
}
|
|
797
|
-
void this.drainSerialAPIQueue();
|
|
798
829
|
this._scheduler.start();
|
|
799
830
|
if (typeof this._options.testingHooks?.onSerialPortOpen === "function") {
|
|
800
831
|
await this._options.testingHooks.onSerialPortOpen(this.serial);
|
|
@@ -999,10 +1030,13 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
999
1030
|
* adds event handlers and starts the interview process.
|
|
1000
1031
|
*/
|
|
1001
1032
|
async initializeControllerAndNodes() {
|
|
1002
|
-
if (this._controller
|
|
1003
|
-
|
|
1004
|
-
this._controller.on("node found", this.onNodeFound.bind(this)).on("node added", this.onNodeAdded.bind(this)).on("node removed", this.onNodeRemoved.bind(this)).on("status changed", this.onControllerStatusChanged.bind(this)).on("network found", this.onNetworkFound.bind(this)).on("network joined", this.onNetworkJoined.bind(this)).on("network left", this.onNetworkLeft.bind(this));
|
|
1033
|
+
if (this._controller) {
|
|
1034
|
+
throw new import_core.ZWaveError("The controller was already initialized!", import_core.ZWaveErrorCodes.Driver_Failed);
|
|
1005
1035
|
}
|
|
1036
|
+
this._controller = new import_Controller.ZWaveController(this);
|
|
1037
|
+
this._controller.on("node found", this.onNodeFound.bind(this)).on("node added", this.onNodeAdded.bind(this)).on("node removed", this.onNodeRemoved.bind(this)).on("status changed", this.onControllerStatusChanged.bind(this)).on("network found", this.onNetworkFound.bind(this)).on("network joined", this.onNetworkJoined.bind(this)).on("network left", this.onNetworkLeft.bind(this));
|
|
1038
|
+
this.initTransactionQueues();
|
|
1039
|
+
this.initSerialAPIQueue();
|
|
1006
1040
|
if (!this._options.testingHooks?.skipControllerIdentification) {
|
|
1007
1041
|
const { nodeIds } = await this.controller.queryCapabilities();
|
|
1008
1042
|
await this.controller.queryAndConfigureRF();
|
|
@@ -1231,7 +1265,7 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
1231
1265
|
this.retryNodeInterviewTimeouts.get(node.id)?.clear();
|
|
1232
1266
|
this.retryNodeInterviewTimeouts.delete(node.id);
|
|
1233
1267
|
}
|
|
1234
|
-
this.rejectTransactions((t) => t.message.getNodeId() === node.id && (t.priority === import_core.MessagePriority.NodeQuery || t.tag === "interview"), "The interview was restarted", import_core.ZWaveErrorCodes.Controller_InterviewRestarted);
|
|
1268
|
+
await this.rejectTransactions((t) => t.message.getNodeId() === node.id && (t.priority === import_core.MessagePriority.NodeQuery || t.tag === "interview"), "The interview was restarted", import_core.ZWaveErrorCodes.Controller_InterviewRestarted);
|
|
1235
1269
|
const maxInterviewAttempts = this._options.attempts.nodeInterview;
|
|
1236
1270
|
try {
|
|
1237
1271
|
if (!await node.interviewInternal()) {
|
|
@@ -1296,7 +1330,7 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
1296
1330
|
onNodeWakeUp(node, oldStatus) {
|
|
1297
1331
|
this.controllerLog.logNode(node.id, `The node is ${oldStatus === import_Types.NodeStatus.Unknown ? "" : "now "}awake.`);
|
|
1298
1332
|
if (oldStatus === import_Types.NodeStatus.Asleep) {
|
|
1299
|
-
this.reduceQueues(({ message }) => {
|
|
1333
|
+
void this.reduceQueues(({ message }) => {
|
|
1300
1334
|
if (message.getNodeId() !== node.id)
|
|
1301
1335
|
return { type: "keep" };
|
|
1302
1336
|
if (messageIsPing(message)) {
|
|
@@ -1519,7 +1553,7 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
1519
1553
|
this.securityManager?.deleteAllNoncesForReceiver(node.id);
|
|
1520
1554
|
this.securityManager2?.deleteNonce(node.id);
|
|
1521
1555
|
this.securityManagerLR?.deleteNonce(node.id);
|
|
1522
|
-
this.rejectAllTransactionsForNode(node.id, "The node was removed from the network", import_core.ZWaveErrorCodes.Controller_NodeRemoved);
|
|
1556
|
+
void this.rejectAllTransactionsForNode(node.id, "The node was removed from the network", import_core.ZWaveErrorCodes.Controller_NodeRemoved);
|
|
1523
1557
|
const replaced = reason === import_Inclusion.RemoveNodeReason.Replaced || reason === import_Inclusion.RemoveNodeReason.ProxyReplaced;
|
|
1524
1558
|
if (!replaced) {
|
|
1525
1559
|
this.controller.removeNodeFromAllAssociations(node.id).catch((err) => {
|
|
@@ -1822,8 +1856,8 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
1822
1856
|
this.unpauseSendQueue();
|
|
1823
1857
|
}
|
|
1824
1858
|
}
|
|
1825
|
-
/**
|
|
1826
|
-
async softResetAndRestart(
|
|
1859
|
+
/** Soft-reset the Z-Wave module and restart the driver instance */
|
|
1860
|
+
async softResetAndRestart() {
|
|
1827
1861
|
this.controllerLog.print("Performing soft reset...");
|
|
1828
1862
|
try {
|
|
1829
1863
|
this.isSoftResetting = true;
|
|
@@ -1834,12 +1868,12 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
1834
1868
|
} catch (e) {
|
|
1835
1869
|
this.controllerLog.print(`Soft reset failed: ${(0, import_shared.getErrorMessage)(e)}`, "error");
|
|
1836
1870
|
}
|
|
1871
|
+
if (!await this.ensureSerialAPI()) {
|
|
1872
|
+
await this.destroyWithMessage("The Serial API did not respond after soft-reset");
|
|
1873
|
+
}
|
|
1837
1874
|
this.isSoftResetting = false;
|
|
1838
|
-
this.
|
|
1839
|
-
|
|
1840
|
-
process.nextTick(() => {
|
|
1841
|
-
this.emit("error", new import_core.ZWaveError(restartReason, import_core.ZWaveErrorCodes.Driver_Failed));
|
|
1842
|
-
});
|
|
1875
|
+
await this.destroyController();
|
|
1876
|
+
void this.initializeControllerAndNodes();
|
|
1843
1877
|
}
|
|
1844
1878
|
/**
|
|
1845
1879
|
* Checks whether recovering an unresponsive controller is enabled
|
|
@@ -1856,7 +1890,9 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
1856
1890
|
let waitResult = await this.waitForMessage((msg) => msg.functionType === import_serial.FunctionType.SerialAPIStarted, 1500).catch(() => false);
|
|
1857
1891
|
if (waitResult) {
|
|
1858
1892
|
this.controllerLog.print("reconnected and restarted");
|
|
1859
|
-
this.
|
|
1893
|
+
if (this._controller) {
|
|
1894
|
+
this._controller["_supportsLongRange"] = waitResult.supportsLongRange;
|
|
1895
|
+
}
|
|
1860
1896
|
return true;
|
|
1861
1897
|
}
|
|
1862
1898
|
if (!this.serial.isOpen) {
|
|
@@ -1873,7 +1909,9 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
1873
1909
|
}, this._options.timeouts.serialAPIStarted).catch(() => false);
|
|
1874
1910
|
if (waitResult) {
|
|
1875
1911
|
this.controllerLog.print("Serial API started");
|
|
1876
|
-
this.
|
|
1912
|
+
if (this._controller) {
|
|
1913
|
+
this._controller["_supportsLongRange"] = waitResult.supportsLongRange;
|
|
1914
|
+
}
|
|
1877
1915
|
return true;
|
|
1878
1916
|
}
|
|
1879
1917
|
this.controllerLog.print("Did not receive notification that Serial API has started, checking if it responds...");
|
|
@@ -1944,20 +1982,7 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
1944
1982
|
await this.scheduler.removeTasks(() => true, new import_core.ZWaveError("The controller is being hard-reset", import_core.ZWaveErrorCodes.Driver_TaskRemoved));
|
|
1945
1983
|
await this.controller.setControllerNIF();
|
|
1946
1984
|
await this.controller.hardReset();
|
|
1947
|
-
this.
|
|
1948
|
-
this.sendNodeToSleepTimers.forEach((timeout) => timeout.clear());
|
|
1949
|
-
this.sendNodeToSleepTimers.clear();
|
|
1950
|
-
for (const timer of this.retryNodeInterviewTimeouts.values()) {
|
|
1951
|
-
timer.clear();
|
|
1952
|
-
}
|
|
1953
|
-
this.retryNodeInterviewTimeouts.clear();
|
|
1954
|
-
for (const timer of this.autoRefreshNodeValueTimers.values()) {
|
|
1955
|
-
timer.clear();
|
|
1956
|
-
}
|
|
1957
|
-
this.autoRefreshNodeValueTimers.clear();
|
|
1958
|
-
this.pollBackgroundRSSITimer?.clear();
|
|
1959
|
-
this.pollBackgroundRSSITimer = void 0;
|
|
1960
|
-
this._controllerInterviewed = false;
|
|
1985
|
+
await this.destroyController();
|
|
1961
1986
|
void this.initializeControllerAndNodes();
|
|
1962
1987
|
if (oldPrivateKey) {
|
|
1963
1988
|
this.once("driver ready", () => {
|
|
@@ -2023,15 +2048,36 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
2023
2048
|
this._destroyPromise = (0, import_deferred_promise.createDeferredPromise)();
|
|
2024
2049
|
this.driverLog.print("destroying driver instance...");
|
|
2025
2050
|
await this._scheduler.stop();
|
|
2026
|
-
this.
|
|
2027
|
-
|
|
2028
|
-
queue.abort();
|
|
2029
|
-
}
|
|
2051
|
+
await this.destroyTransactionQueues("driver instance destroyed", import_core.ZWaveErrorCodes.Driver_Destroyed);
|
|
2052
|
+
this.destroySerialAPIQueue("driver instance destroyed", import_core.ZWaveErrorCodes.Driver_Destroyed);
|
|
2030
2053
|
if (this.serial != void 0) {
|
|
2031
2054
|
if (this.serial.isOpen)
|
|
2032
2055
|
await this.serial.close();
|
|
2033
2056
|
this.serial = void 0;
|
|
2034
2057
|
}
|
|
2058
|
+
await this.destroyController();
|
|
2059
|
+
this.driverLog.print(`driver instance destroyed`);
|
|
2060
|
+
this._logContainer.destroy();
|
|
2061
|
+
this._destroyPromise.resolve();
|
|
2062
|
+
}
|
|
2063
|
+
/** Cleanly destroy the controller instance, but not the entire driver */
|
|
2064
|
+
// FIXME: Too much overlap with destroy()
|
|
2065
|
+
async destroyController() {
|
|
2066
|
+
await this.scheduler.removeTasks(() => true, new import_core.ZWaveError("The controller instance is being destroyed", import_core.ZWaveErrorCodes.Driver_TaskRemoved));
|
|
2067
|
+
await this.destroyTransactionQueues("The controller instance is being destroyed", import_core.ZWaveErrorCodes.Driver_TaskRemoved);
|
|
2068
|
+
this.destroySerialAPIQueue("The controller instance is being destroyed", import_core.ZWaveErrorCodes.Driver_TaskRemoved);
|
|
2069
|
+
this.requestHandlers.clear();
|
|
2070
|
+
await this.closeDatabases();
|
|
2071
|
+
this.clearAllTimeouts();
|
|
2072
|
+
if (this._controller) {
|
|
2073
|
+
this._controller.destroy();
|
|
2074
|
+
this._controller = void 0;
|
|
2075
|
+
}
|
|
2076
|
+
this._controllerInterviewed = false;
|
|
2077
|
+
this._nodesReady.clear();
|
|
2078
|
+
this._nodesReadyEventEmitted = false;
|
|
2079
|
+
}
|
|
2080
|
+
async closeDatabases() {
|
|
2035
2081
|
try {
|
|
2036
2082
|
await this._valueDB?.close();
|
|
2037
2083
|
} catch (e) {
|
|
@@ -2047,6 +2093,8 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
2047
2093
|
} catch (e) {
|
|
2048
2094
|
this.driverLog.print(`Closing the network cache failed: ${(0, import_shared.getErrorMessage)(e)}`, "error");
|
|
2049
2095
|
}
|
|
2096
|
+
}
|
|
2097
|
+
clearAllTimeouts() {
|
|
2050
2098
|
for (const timeout of [
|
|
2051
2099
|
this._powerlevelTestNodeContext?.timeout
|
|
2052
2100
|
]) {
|
|
@@ -2067,13 +2115,6 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
2067
2115
|
]) {
|
|
2068
2116
|
timeout?.clear();
|
|
2069
2117
|
}
|
|
2070
|
-
if (this._controller) {
|
|
2071
|
-
this._controller.destroy();
|
|
2072
|
-
this._controller = void 0;
|
|
2073
|
-
}
|
|
2074
|
-
this.driverLog.print(`driver instance destroyed`);
|
|
2075
|
-
this._logContainer.destroy();
|
|
2076
|
-
this._destroyPromise.resolve();
|
|
2077
2118
|
}
|
|
2078
2119
|
async handleSerialData(serial) {
|
|
2079
2120
|
try {
|
|
@@ -2437,7 +2478,7 @@ ${(0, import_shared.buffer2hex)(data)}`, "warn");
|
|
|
2437
2478
|
reason: errorMsg
|
|
2438
2479
|
});
|
|
2439
2480
|
transaction.abort(error);
|
|
2440
|
-
this.rejectAllTransactionsForNode(node.id, errorMsg);
|
|
2481
|
+
void this.rejectAllTransactionsForNode(node.id, errorMsg);
|
|
2441
2482
|
return true;
|
|
2442
2483
|
}
|
|
2443
2484
|
}
|
|
@@ -2521,7 +2562,7 @@ ${(0, import_shared.buffer2hex)(data)}`, "warn");
|
|
|
2521
2562
|
reason: errorMsg
|
|
2522
2563
|
});
|
|
2523
2564
|
transaction.abort(error);
|
|
2524
|
-
this.rejectAllTransactionsForNode(node.id, errorMsg);
|
|
2565
|
+
void this.rejectAllTransactionsForNode(node.id, errorMsg);
|
|
2525
2566
|
handled = true;
|
|
2526
2567
|
}
|
|
2527
2568
|
if (this._recoveryPhase === 4) {
|
|
@@ -3578,8 +3619,6 @@ ${handlers.length} left`);
|
|
|
3578
3619
|
} else {
|
|
3579
3620
|
throw e;
|
|
3580
3621
|
}
|
|
3581
|
-
} else if ((0, import_serialapi.isTransmitReport)(e.context) && e.context.transmitStatus === import_core.TransmitStatus.NoAck) {
|
|
3582
|
-
waitDurationMs = 100;
|
|
3583
3622
|
} else if (e.code === import_core.ZWaveErrorCodes.Controller_MessageDropped) {
|
|
3584
3623
|
throw e;
|
|
3585
3624
|
}
|
|
@@ -3610,6 +3649,7 @@ ${handlers.length} left`);
|
|
|
3610
3649
|
async drainSerialAPIQueue() {
|
|
3611
3650
|
for await (const item of this.serialAPIQueue) {
|
|
3612
3651
|
const { msg, transactionSource, result } = item;
|
|
3652
|
+
this._currentSerialAPICommandPromise = result;
|
|
3613
3653
|
attempts: for (let attempt = 1; ; attempt++) {
|
|
3614
3654
|
try {
|
|
3615
3655
|
const ret = await this.executeSerialAPICommand(msg, transactionSource);
|
|
@@ -3638,7 +3678,10 @@ ${handlers.length} left`);
|
|
|
3638
3678
|
this.serialAPIQueue.add({
|
|
3639
3679
|
msg,
|
|
3640
3680
|
transactionSource,
|
|
3641
|
-
result
|
|
3681
|
+
result,
|
|
3682
|
+
[Symbol.dispose]: () => {
|
|
3683
|
+
result.reject(new import_core.ZWaveError("The message has been removed from the queue", import_core.ZWaveErrorCodes.Controller_MessageDropped, void 0, transactionSource));
|
|
3684
|
+
}
|
|
3642
3685
|
});
|
|
3643
3686
|
return result;
|
|
3644
3687
|
}
|
|
@@ -3830,7 +3873,7 @@ ${handlers.length} left`);
|
|
|
3830
3873
|
let expirationTimeout;
|
|
3831
3874
|
if (options.expire) {
|
|
3832
3875
|
expirationTimeout = (0, import_shared.setTimer)(() => {
|
|
3833
|
-
this.reduceQueues((t, _source) => {
|
|
3876
|
+
void this.reduceQueues((t, _source) => {
|
|
3834
3877
|
if (t === transaction) {
|
|
3835
3878
|
return {
|
|
3836
3879
|
type: "reject",
|
|
@@ -4217,7 +4260,7 @@ ${handlers.length} left`);
|
|
|
4217
4260
|
...requeue,
|
|
4218
4261
|
tag: "interview"
|
|
4219
4262
|
};
|
|
4220
|
-
this.reduceQueues((transaction, _source) => {
|
|
4263
|
+
void this.reduceQueues((transaction, _source) => {
|
|
4221
4264
|
const msg = transaction.message;
|
|
4222
4265
|
if (msg.getNodeId() !== nodeId)
|
|
4223
4266
|
return { type: "keep" };
|
|
@@ -4229,7 +4272,7 @@ ${handlers.length} left`);
|
|
|
4229
4272
|
* Rejects all pending transactions that match a predicate and removes them from the send queue
|
|
4230
4273
|
*/
|
|
4231
4274
|
rejectTransactions(predicate, errorMsg = `The message has been removed from the queue`, errorCode = import_core.ZWaveErrorCodes.Controller_MessageDropped) {
|
|
4232
|
-
this.reduceQueues((transaction, _source) => {
|
|
4275
|
+
return this.reduceQueues((transaction, _source) => {
|
|
4233
4276
|
if (predicate(transaction)) {
|
|
4234
4277
|
return {
|
|
4235
4278
|
type: "reject",
|
|
@@ -4246,7 +4289,7 @@ ${handlers.length} left`);
|
|
|
4246
4289
|
* Rejects all pending transactions for a node and removes them from the send queue
|
|
4247
4290
|
*/
|
|
4248
4291
|
rejectAllTransactionsForNode(nodeId, errorMsg = `The node is dead`, errorCode = import_core.ZWaveErrorCodes.Controller_MessageDropped) {
|
|
4249
|
-
this.rejectTransactions((t) => t.message.getNodeId() === nodeId, errorMsg, errorCode);
|
|
4292
|
+
return this.rejectTransactions((t) => t.message.getNodeId() === nodeId, errorMsg, errorCode);
|
|
4250
4293
|
}
|
|
4251
4294
|
/**
|
|
4252
4295
|
* Pauses the send queue, avoiding commands to be sent to the controller
|
|
@@ -4262,9 +4305,7 @@ ${handlers.length} left`);
|
|
|
4262
4305
|
this.triggerQueues();
|
|
4263
4306
|
}
|
|
4264
4307
|
reduceQueues(reducer) {
|
|
4265
|
-
|
|
4266
|
-
this.reduceQueue(queue, reducer);
|
|
4267
|
-
}
|
|
4308
|
+
return Promise.all(this.queues.map((queue) => this.reduceQueue(queue, reducer))).then(import_shared.noop);
|
|
4268
4309
|
}
|
|
4269
4310
|
reduceQueue(queue, reducer) {
|
|
4270
4311
|
const dropQueued = [];
|
|
@@ -4329,8 +4370,9 @@ ${handlers.length} left`);
|
|
|
4329
4370
|
t.setProgress({ state: import_core.TransactionState.Queued });
|
|
4330
4371
|
}
|
|
4331
4372
|
if ((0, import_serialapi.isSendData)(stopActive?.message)) {
|
|
4332
|
-
|
|
4373
|
+
return this.abortSendData();
|
|
4333
4374
|
}
|
|
4375
|
+
return Promise.resolve();
|
|
4334
4376
|
}
|
|
4335
4377
|
/** @internal */
|
|
4336
4378
|
resolvePendingPings(nodeId) {
|
|
@@ -4615,7 +4657,8 @@ ${handlers.length} left`);
|
|
|
4615
4657
|
} else if (this.controller.sdkVersionGte("6.50.0") && this.controller.supportedFunctionTypes?.includes(import_serial.FunctionType.FirmwareUpdateNVM)) {
|
|
4616
4658
|
const wasUpdated = await this.firmwareUpdateOTW500(data);
|
|
4617
4659
|
if (wasUpdated.success) {
|
|
4618
|
-
|
|
4660
|
+
this.driverLog.print("Activating new firmware and restarting driver...");
|
|
4661
|
+
await this.softResetAndRestart();
|
|
4619
4662
|
}
|
|
4620
4663
|
return wasUpdated;
|
|
4621
4664
|
}
|
|
@@ -4684,7 +4727,6 @@ ${handlers.length} left`);
|
|
|
4684
4727
|
}
|
|
4685
4728
|
async firmwareUpdateOTW700(data) {
|
|
4686
4729
|
this._otwFirmwareUpdateInProgress = true;
|
|
4687
|
-
let destroy = false;
|
|
4688
4730
|
try {
|
|
4689
4731
|
await this.enterBootloader();
|
|
4690
4732
|
this.controllerLog.print("Beginning firmware upload");
|
|
@@ -4734,7 +4776,6 @@ ${handlers.length} left`);
|
|
|
4734
4776
|
progress: (0, import_math.roundTo)(fragment / numFragments * 100, 2)
|
|
4735
4777
|
};
|
|
4736
4778
|
this.emit("firmware update progress", progress);
|
|
4737
|
-
destroy = true;
|
|
4738
4779
|
continue transfer;
|
|
4739
4780
|
}
|
|
4740
4781
|
case import_serial.XModemMessageHeaders.NAK:
|
|
@@ -4791,7 +4832,7 @@ ${handlers.length} left`);
|
|
|
4791
4832
|
this.emit("firmware update finished", result);
|
|
4792
4833
|
return result;
|
|
4793
4834
|
} finally {
|
|
4794
|
-
await this.leaveBootloader(
|
|
4835
|
+
await this.leaveBootloader();
|
|
4795
4836
|
this._otwFirmwareUpdateInProgress = false;
|
|
4796
4837
|
}
|
|
4797
4838
|
}
|
|
@@ -4824,12 +4865,10 @@ ${handlers.length} left`);
|
|
|
4824
4865
|
}
|
|
4825
4866
|
}
|
|
4826
4867
|
async enterBootloaderFromSerialAPI() {
|
|
4827
|
-
|
|
4828
|
-
this.
|
|
4829
|
-
|
|
4830
|
-
this.
|
|
4831
|
-
this.rejectTransactions((_t) => true, "The controller is entering bootloader mode.");
|
|
4832
|
-
const promise = this.writeSerial(import_shared.Bytes.from("01030027db", "hex"));
|
|
4868
|
+
const ctx = this.getEncodingContext();
|
|
4869
|
+
await this.destroyController();
|
|
4870
|
+
const msg = new import_serialapi.EnterBootloaderRequest();
|
|
4871
|
+
const promise = this.writeSerial(await msg.serialize(ctx));
|
|
4833
4872
|
this.serial.mode = import_serial.ZWaveSerialMode.Bootloader;
|
|
4834
4873
|
await promise;
|
|
4835
4874
|
}
|
|
@@ -4844,27 +4883,21 @@ ${handlers.length} left`);
|
|
|
4844
4883
|
return promise;
|
|
4845
4884
|
}
|
|
4846
4885
|
/**
|
|
4847
|
-
* Leaves the bootloader
|
|
4886
|
+
* Leaves the bootloader by running the application.
|
|
4848
4887
|
*/
|
|
4849
|
-
async leaveBootloader(
|
|
4888
|
+
async leaveBootloader() {
|
|
4850
4889
|
this.controllerLog.print("Leaving bootloader...");
|
|
4851
4890
|
await this.leaveBootloaderInternal();
|
|
4852
|
-
await (
|
|
4853
|
-
if (
|
|
4891
|
+
const isSerialAPI = await this.waitForMessage((msg) => msg.functionType === import_serial.FunctionType.SerialAPIStarted, 1e3).then(() => true).catch(() => false);
|
|
4892
|
+
if (isSerialAPI) {
|
|
4893
|
+
await this.initializeControllerAndNodes();
|
|
4894
|
+
return;
|
|
4895
|
+
} else if (this.mode === import_DriverMode.DriverMode.CLI) {
|
|
4854
4896
|
await this.ensureCLIReady();
|
|
4855
4897
|
return;
|
|
4856
4898
|
}
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
this.controllerLog.print(restartReason);
|
|
4860
|
-
await this.destroy();
|
|
4861
|
-
setImmediate(() => {
|
|
4862
|
-
this.emit("error", new import_core.ZWaveError(restartReason, import_core.ZWaveErrorCodes.Driver_Failed));
|
|
4863
|
-
});
|
|
4864
|
-
} else {
|
|
4865
|
-
this.unpauseSendQueue();
|
|
4866
|
-
await this.ensureSerialAPI();
|
|
4867
|
-
}
|
|
4899
|
+
this.unpauseSendQueue();
|
|
4900
|
+
await this.ensureSerialAPI();
|
|
4868
4901
|
}
|
|
4869
4902
|
serialport_onBootloaderData(data) {
|
|
4870
4903
|
switch (data.type) {
|