zwave-js 15.24.3 → 15.25.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/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/driver/Driver.d.ts +9 -1
- package/build/cjs/lib/driver/Driver.js +216 -130
- package/build/cjs/lib/driver/Driver.js.map +3 -3
- package/build/cjs/lib/driver/PartialCCSessionManager.d.ts +69 -0
- package/build/cjs/lib/driver/PartialCCSessionManager.js +161 -0
- package/build/cjs/lib/driver/PartialCCSessionManager.js.map +7 -0
- package/build/cjs/lib/driver/ZWaveOptions.d.ts +5 -0
- package/build/cjs/lib/driver/ZWaveOptions.js.map +2 -2
- package/build/cjs/lib/node/Node.d.ts +0 -1
- package/build/cjs/lib/node/Node.js +45 -12
- package/build/cjs/lib/node/Node.js.map +2 -2
- package/build/cjs/lib/node/_Types.d.ts +5 -3
- package/build/cjs/lib/node/_Types.js +1 -0
- package/build/cjs/lib/node/_Types.js.map +2 -2
- package/build/cjs/lib/node/mixins/90_InterviewProgress.d.ts +94 -0
- package/build/cjs/lib/node/mixins/90_InterviewProgress.js +280 -0
- package/build/cjs/lib/node/mixins/90_InterviewProgress.js.map +7 -0
- package/build/cjs/lib/node/mixins/index.d.ts +2 -2
- package/build/cjs/lib/node/mixins/index.js +2 -2
- package/build/cjs/lib/node/mixins/index.js.map +2 -2
- package/build/esm/lib/_version.d.ts +1 -1
- package/build/esm/lib/_version.js +1 -1
- package/build/esm/lib/driver/Driver.d.ts +9 -1
- package/build/esm/lib/driver/Driver.d.ts.map +1 -1
- package/build/esm/lib/driver/Driver.js +260 -149
- package/build/esm/lib/driver/Driver.js.map +1 -1
- package/build/esm/lib/driver/PartialCCSessionManager.d.ts +69 -0
- package/build/esm/lib/driver/PartialCCSessionManager.d.ts.map +1 -0
- package/build/esm/lib/driver/PartialCCSessionManager.js +169 -0
- package/build/esm/lib/driver/PartialCCSessionManager.js.map +1 -0
- package/build/esm/lib/driver/ZWaveOptions.d.ts +5 -0
- package/build/esm/lib/driver/ZWaveOptions.d.ts.map +1 -1
- package/build/esm/lib/driver/ZWaveOptions.js.map +1 -1
- package/build/esm/lib/node/Node.d.ts +0 -1
- package/build/esm/lib/node/Node.d.ts.map +1 -1
- package/build/esm/lib/node/Node.js +102 -21
- package/build/esm/lib/node/Node.js.map +1 -1
- package/build/esm/lib/node/_Types.d.ts +5 -3
- package/build/esm/lib/node/_Types.d.ts.map +1 -1
- package/build/esm/lib/node/_Types.js +2 -1
- package/build/esm/lib/node/_Types.js.map +1 -1
- package/build/esm/lib/node/mixins/90_InterviewProgress.d.ts +94 -0
- package/build/esm/lib/node/mixins/90_InterviewProgress.d.ts.map +1 -0
- package/build/esm/lib/node/mixins/90_InterviewProgress.js +283 -0
- package/build/esm/lib/node/mixins/90_InterviewProgress.js.map +1 -0
- package/build/esm/lib/node/mixins/index.d.ts +2 -2
- package/build/esm/lib/node/mixins/index.d.ts.map +1 -1
- package/build/esm/lib/node/mixins/index.js +2 -2
- package/build/esm/lib/node/mixins/index.js.map +1 -1
- package/package.json +9 -9
|
@@ -22,7 +22,7 @@ __export(version_exports, {
|
|
|
22
22
|
PACKAGE_VERSION: () => PACKAGE_VERSION
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(version_exports);
|
|
25
|
-
const PACKAGE_VERSION = "15.
|
|
25
|
+
const PACKAGE_VERSION = "15.25.0";
|
|
26
26
|
const PACKAGE_NAME = "zwave-js";
|
|
27
27
|
// Annotate the CommonJS export names for ESM import in node:
|
|
28
28
|
0 && (module.exports = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/_version.ts"],
|
|
4
|
-
"sourcesContent": ["// This file is auto-generated by the codegen maintenance script\nexport const PACKAGE_VERSION = \"15.
|
|
4
|
+
"sourcesContent": ["// This file is auto-generated by the codegen maintenance script\nexport const PACKAGE_VERSION = \"15.25.0\";\nexport const PACKAGE_NAME = \"zwave-js\";\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;;;;;;AACO,MAAM,kBAAkB;AACxB,MAAM,eAAe;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -416,8 +416,16 @@ export declare class Driver extends TypedEventTarget<DriverEventCallbacks> imple
|
|
|
416
416
|
private isMissingNodeACK;
|
|
417
417
|
private shouldRequestWakeupOnDemand;
|
|
418
418
|
private partialCCSessions;
|
|
419
|
-
|
|
419
|
+
/**
|
|
420
|
+
* Determines the request a new partial CC session is the response to, if any.
|
|
421
|
+
* This is used to re-request the response when segments are missing.
|
|
422
|
+
*/
|
|
423
|
+
private findPartialCCSessionRequest;
|
|
424
|
+
/** Re-requests the response a partial CC session belongs to because segments are missing */
|
|
425
|
+
private rerequestPartialCCSession;
|
|
420
426
|
private assemblePartialCCs;
|
|
427
|
+
/** Refreshes the timeouts of awaited messages which a partial message may belong to */
|
|
428
|
+
private refreshAwaitedMessageTimers;
|
|
421
429
|
private handleTransportServiceCommand;
|
|
422
430
|
private handleUnsolicitedMessage;
|
|
423
431
|
private handleSerialAPIStartedUnexpectedly;
|
|
@@ -62,6 +62,7 @@ var import_DriverMode = require("./DriverMode.js");
|
|
|
62
62
|
var import_EndDeviceCLI = require("./EndDeviceCLI.js");
|
|
63
63
|
var import_MessageGenerators = require("./MessageGenerators.js");
|
|
64
64
|
var import_NetworkCache = require("./NetworkCache.js");
|
|
65
|
+
var import_PartialCCSessionManager = require("./PartialCCSessionManager.js");
|
|
65
66
|
var import_Queue = require("./Queue.js");
|
|
66
67
|
var import_SerialAPICommandMachine = require("./SerialAPICommandMachine.js");
|
|
67
68
|
var import_StateMachineShared = require("./StateMachineShared.js");
|
|
@@ -117,7 +118,8 @@ const defaultOptions = {
|
|
|
117
118
|
sendDataJammed: 5,
|
|
118
119
|
nodeInterview: 5,
|
|
119
120
|
smartStartInclusion: 5,
|
|
120
|
-
firmwareUpdateOTW: 3
|
|
121
|
+
firmwareUpdateOTW: 3,
|
|
122
|
+
partialReports: 2
|
|
121
123
|
},
|
|
122
124
|
disableOptimisticValueUpdate: false,
|
|
123
125
|
features: {
|
|
@@ -210,6 +212,9 @@ function checkOptions(options) {
|
|
|
210
212
|
if (options.attempts.firmwareUpdateOTW < 1 || options.attempts.firmwareUpdateOTW > 5) {
|
|
211
213
|
throw new import_core.ZWaveError(`The OTW firmware update attempts must be between 1 and 5!`, import_core.ZWaveErrorCodes.Driver_InvalidOptions);
|
|
212
214
|
}
|
|
215
|
+
if (options.attempts.partialReports < 0 || options.attempts.partialReports > 3) {
|
|
216
|
+
throw new import_core.ZWaveError(`The partial reports attempts must be between 0 and 3!`, import_core.ZWaveErrorCodes.Driver_InvalidOptions);
|
|
217
|
+
}
|
|
213
218
|
if (options.inclusionUserCallbacks) {
|
|
214
219
|
if (!(0, import_typeguards.isObject)(options.inclusionUserCallbacks)) {
|
|
215
220
|
throw new import_core.ZWaveError(`The inclusionUserCallbacks must be an object!`, import_core.ZWaveErrorCodes.Driver_InvalidOptions);
|
|
@@ -2218,6 +2223,7 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
2218
2223
|
]) {
|
|
2219
2224
|
timeout?.clear();
|
|
2220
2225
|
}
|
|
2226
|
+
this.partialCCSessions.clear();
|
|
2221
2227
|
}
|
|
2222
2228
|
async handleSerialData(serial) {
|
|
2223
2229
|
try {
|
|
@@ -2346,7 +2352,6 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
2346
2352
|
if (!this._controller && (0, import_serialapi.containsCC)(msg))
|
|
2347
2353
|
return;
|
|
2348
2354
|
if (msg) {
|
|
2349
|
-
let wasMessageLogged = false;
|
|
2350
2355
|
if ((0, import_serialapi.isCommandRequest)(msg) && (0, import_serialapi.containsCC)(msg)) {
|
|
2351
2356
|
if (msg.command instanceof import_cc.SecurityCCCommandEncapsulationNonceGet) {
|
|
2352
2357
|
const node = this.tryGetNode(msg);
|
|
@@ -2359,29 +2364,35 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
2359
2364
|
secondaryTags: ["partial"],
|
|
2360
2365
|
direction: "inbound"
|
|
2361
2366
|
});
|
|
2362
|
-
|
|
2363
|
-
|
|
2367
|
+
const reassembled = await this.handleTransportServiceCommand(msg.command);
|
|
2368
|
+
if (!reassembled) {
|
|
2369
|
+
this.refreshAwaitedMessageTimers(msg);
|
|
2370
|
+
return;
|
|
2371
|
+
}
|
|
2372
|
+
msg.command = reassembled;
|
|
2373
|
+
}
|
|
2374
|
+
if (this.isSecurityLevelTooLow(msg.command)) {
|
|
2375
|
+
this.driverLog.logMessage(msg, {
|
|
2376
|
+
direction: "inbound",
|
|
2377
|
+
secondaryTags: ["discarded"]
|
|
2364
2378
|
});
|
|
2379
|
+
return;
|
|
2365
2380
|
}
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
entry.timeout?.refresh();
|
|
2370
|
-
}
|
|
2371
|
-
}
|
|
2381
|
+
const completeMsg = await this.assemblePartialCCs(msg);
|
|
2382
|
+
if (!completeMsg) {
|
|
2383
|
+
this.refreshAwaitedMessageTimers(msg);
|
|
2372
2384
|
return;
|
|
2373
2385
|
}
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
}
|
|
2386
|
+
msg = completeMsg;
|
|
2387
|
+
if (this.shouldDiscardCC(completeMsg.command)) {
|
|
2388
|
+
this.driverLog.logMessage(msg, {
|
|
2389
|
+
direction: "inbound",
|
|
2390
|
+
secondaryTags: ["discarded"]
|
|
2391
|
+
});
|
|
2381
2392
|
return;
|
|
2382
2393
|
}
|
|
2383
2394
|
try {
|
|
2384
|
-
this.persistCCValues(
|
|
2395
|
+
this.persistCCValues(completeMsg.command);
|
|
2385
2396
|
} catch (e) {
|
|
2386
2397
|
if ((0, import_core.isZWaveError)(e) && e.code === import_core.ZWaveErrorCodes.PacketFormat_InvalidPayload) {
|
|
2387
2398
|
this.driverLog.print(`dropping CC with invalid values${typeof e.context === "string" ? ` (Reason: ${e.context})` : ""}`, "warn");
|
|
@@ -2390,19 +2401,13 @@ class Driver extends import_shared.TypedEventTarget {
|
|
|
2390
2401
|
throw e;
|
|
2391
2402
|
}
|
|
2392
2403
|
}
|
|
2393
|
-
if ((0, import_cc.isTransportServiceEncapsulation)(msg.command)) {
|
|
2394
|
-
msg.command = msg.command.encapsulated;
|
|
2395
|
-
wasMessageLogged = false;
|
|
2396
|
-
}
|
|
2397
2404
|
}
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
this.driverLog.print(`Logging a message failed: ${(0, import_shared.getErrorMessage)(e)}`);
|
|
2405
|
-
}
|
|
2405
|
+
try {
|
|
2406
|
+
this.driverLog.logMessage(msg, {
|
|
2407
|
+
direction: "inbound"
|
|
2408
|
+
});
|
|
2409
|
+
} catch (e) {
|
|
2410
|
+
this.driverLog.print(`Logging a message failed: ${(0, import_shared.getErrorMessage)(e)}`);
|
|
2406
2411
|
}
|
|
2407
2412
|
void this.handleUnsolicitedMessage(msg);
|
|
2408
2413
|
}
|
|
@@ -2766,71 +2771,111 @@ ${(0, import_shared.buffer2hex)(data)}`, "warn");
|
|
|
2766
2771
|
shouldRequestWakeupOnDemand(node) {
|
|
2767
2772
|
return !!node.supportsWakeUpOnDemand && node.status === import_Types2.NodeStatus.Asleep && this.hasPendingTransactions((t) => t.requestWakeUpOnDemand && t.message.getNodeId() === node.id);
|
|
2768
2773
|
}
|
|
2769
|
-
partialCCSessions =
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2774
|
+
partialCCSessions = new import_PartialCCSessionManager.PartialCCSessionManager({
|
|
2775
|
+
getSegmentTimeout: /* @__PURE__ */ __name(() => this._options.timeouts.report, "getSegmentTimeout"),
|
|
2776
|
+
getMaxReRequestAttempts: /* @__PURE__ */ __name(() => this._options.attempts.partialReports, "getMaxReRequestAttempts"),
|
|
2777
|
+
findRequestCC: /* @__PURE__ */ __name((command) => this.findPartialCCSessionRequest(command), "findRequestCC"),
|
|
2778
|
+
rerequestSession: /* @__PURE__ */ __name((session) => this.rerequestPartialCCSession(session), "rerequestSession"),
|
|
2779
|
+
onSessionLost: /* @__PURE__ */ __name((session) => {
|
|
2780
|
+
this.controllerLog.logNode(session.nodeId, {
|
|
2781
|
+
message: `Dropping incomplete partial CC session`,
|
|
2782
|
+
level: "warn",
|
|
2783
|
+
direction: "inbound"
|
|
2778
2784
|
});
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2785
|
+
}, "onSessionLost")
|
|
2786
|
+
});
|
|
2787
|
+
/**
|
|
2788
|
+
* Determines the request a new partial CC session is the response to, if any.
|
|
2789
|
+
* This is used to re-request the response when segments are missing.
|
|
2790
|
+
*/
|
|
2791
|
+
findPartialCCSessionRequest(command) {
|
|
2792
|
+
const currentMessage = this.queue.currentTransaction?.getCurrentMessage();
|
|
2793
|
+
if (!currentMessage || !(0, import_serialapi.containsCC)(currentMessage) || currentMessage.getNodeId() !== command.nodeId || !currentMessage.expectsNodeUpdate(this)) {
|
|
2794
|
+
return;
|
|
2786
2795
|
}
|
|
2796
|
+
const request = (0, import_cc.getInnermostCommandClass)(currentMessage.command);
|
|
2797
|
+
if (!request.isExpectedCCResponse(this, (0, import_cc.getInnermostCommandClass)(command))) {
|
|
2798
|
+
return;
|
|
2799
|
+
}
|
|
2800
|
+
return request;
|
|
2801
|
+
}
|
|
2802
|
+
/** Re-requests the response a partial CC session belongs to because segments are missing */
|
|
2803
|
+
rerequestPartialCCSession(session) {
|
|
2804
|
+
this.refreshAwaitedMessageTimers(session.lastSegmentMsg);
|
|
2805
|
+
this.controllerLog.logNode(session.nodeId, {
|
|
2806
|
+
message: `Some expected reports were not received, requesting the response again...`,
|
|
2807
|
+
level: "warn",
|
|
2808
|
+
direction: "outbound"
|
|
2809
|
+
});
|
|
2810
|
+
void this.sendCommand(session.requestCC, {
|
|
2811
|
+
priority: import_core.MessagePriority.Immediate,
|
|
2812
|
+
maxSendAttempts: 1,
|
|
2813
|
+
ignoreNodeUpdate: true
|
|
2814
|
+
}).catch(import_shared.noop);
|
|
2787
2815
|
}
|
|
2788
2816
|
/**
|
|
2789
|
-
* Assembles partial CCs
|
|
2790
|
-
*
|
|
2817
|
+
* Assembles partial CCs in a message body. Returns the message containing the complete
|
|
2818
|
+
* command to continue handling. This is not necessarily the passed message, since responses
|
|
2819
|
+
* may be split into multiple messages.
|
|
2820
|
+
* If the message contains a partial CC and more segments are expected, this returns `undefined`.
|
|
2791
2821
|
*/
|
|
2792
2822
|
async assemblePartialCCs(msg) {
|
|
2793
2823
|
let command = msg.command;
|
|
2794
2824
|
while (true) {
|
|
2795
|
-
const
|
|
2796
|
-
if (
|
|
2797
|
-
if (
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2825
|
+
const update = this.partialCCSessions.handleCommand(command, msg);
|
|
2826
|
+
if (update?.type === "segment") {
|
|
2827
|
+
if (update.duplicate) {
|
|
2828
|
+
this.controllerLog.logNode(command.nodeId, {
|
|
2829
|
+
message: `Ignoring duplicate partial CC segment:`,
|
|
2830
|
+
level: "debug",
|
|
2831
|
+
direction: "inbound"
|
|
2832
|
+
});
|
|
2833
|
+
}
|
|
2834
|
+
this.driverLog.logMessage(msg, {
|
|
2835
|
+
secondaryTags: ["partial"],
|
|
2836
|
+
direction: "inbound"
|
|
2837
|
+
});
|
|
2838
|
+
return void 0;
|
|
2839
|
+
} else if (update?.type === "complete") {
|
|
2840
|
+
if (update.partials.length > 0) {
|
|
2841
|
+
this.driverLog.logMessage(msg, {
|
|
2842
|
+
secondaryTags: ["partial"],
|
|
2843
|
+
direction: "inbound"
|
|
2844
|
+
});
|
|
2845
|
+
}
|
|
2846
|
+
try {
|
|
2847
|
+
await update.command.mergePartialCCs(update.partials, {
|
|
2848
|
+
...this.getCCParsingContext(),
|
|
2849
|
+
sourceNodeId: update.command.nodeId,
|
|
2850
|
+
frameType: update.finalMsg.frameType
|
|
2851
|
+
});
|
|
2852
|
+
assertValidCCs(update.finalMsg);
|
|
2853
|
+
if (update.partials.length > 0) {
|
|
2854
|
+
this.controllerLog.logNode(update.command.nodeId, {
|
|
2855
|
+
message: `Assembled partial CC from ${update.partials.length + 1} segments`,
|
|
2856
|
+
level: "debug",
|
|
2802
2857
|
direction: "inbound"
|
|
2803
2858
|
});
|
|
2804
2859
|
}
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
case import_core.ZWaveErrorCodes.Deserialization_NotImplemented:
|
|
2819
|
-
case import_core.ZWaveErrorCodes.CC_NotImplemented:
|
|
2820
|
-
this.driverLog.print(`Dropping message because it could not be deserialized: ${e.message}`, "warn");
|
|
2821
|
-
return false;
|
|
2822
|
-
case import_core.ZWaveErrorCodes.PacketFormat_InvalidPayload:
|
|
2823
|
-
this.driverLog.print(`Could not assemble partial CCs because the payload is invalid. Dropping them.`, "warn");
|
|
2824
|
-
return false;
|
|
2825
|
-
case import_core.ZWaveErrorCodes.Driver_NotReady:
|
|
2826
|
-
this.driverLog.print(`Could not assemble partial CCs because the driver is not ready yet. Dropping them`, "warn");
|
|
2827
|
-
return false;
|
|
2828
|
-
}
|
|
2860
|
+
} catch (e) {
|
|
2861
|
+
if ((0, import_core.isZWaveError)(e)) {
|
|
2862
|
+
switch (e.code) {
|
|
2863
|
+
case import_core.ZWaveErrorCodes.Deserialization_NotImplemented:
|
|
2864
|
+
case import_core.ZWaveErrorCodes.CC_NotImplemented:
|
|
2865
|
+
this.driverLog.print(`Dropping message because it could not be deserialized: ${e.message}`, "warn");
|
|
2866
|
+
return void 0;
|
|
2867
|
+
case import_core.ZWaveErrorCodes.PacketFormat_InvalidPayload:
|
|
2868
|
+
this.driverLog.print(`Could not assemble partial CCs because the payload is invalid. Dropping them.`, "warn");
|
|
2869
|
+
return void 0;
|
|
2870
|
+
case import_core.ZWaveErrorCodes.Driver_NotReady:
|
|
2871
|
+
this.driverLog.print(`Could not assemble partial CCs because the driver is not ready yet. Dropping them`, "warn");
|
|
2872
|
+
return void 0;
|
|
2829
2873
|
}
|
|
2830
|
-
throw e;
|
|
2831
2874
|
}
|
|
2875
|
+
throw e;
|
|
2832
2876
|
}
|
|
2833
|
-
|
|
2877
|
+
msg = update.finalMsg;
|
|
2878
|
+
command = update.command;
|
|
2834
2879
|
}
|
|
2835
2880
|
if ((0, import_cc.isEncapsulatingCommandClass)(command)) {
|
|
2836
2881
|
command = command.encapsulated;
|
|
@@ -2838,19 +2883,40 @@ ${(0, import_shared.buffer2hex)(data)}`, "warn");
|
|
|
2838
2883
|
break;
|
|
2839
2884
|
}
|
|
2840
2885
|
}
|
|
2841
|
-
return
|
|
2886
|
+
return msg;
|
|
2887
|
+
}
|
|
2888
|
+
/** Refreshes the timeouts of awaited messages which a partial message may belong to */
|
|
2889
|
+
refreshAwaitedMessageTimers(msg) {
|
|
2890
|
+
for (const entry of this.awaitedMessages) {
|
|
2891
|
+
if (entry.refreshPredicate?.(msg)) {
|
|
2892
|
+
entry.timeout?.refresh();
|
|
2893
|
+
}
|
|
2894
|
+
}
|
|
2842
2895
|
}
|
|
2843
|
-
/**
|
|
2896
|
+
/**
|
|
2897
|
+
* Is called when a Transport Service command is received.
|
|
2898
|
+
* When the command completes a datagram, the reassembled command is returned.
|
|
2899
|
+
*/
|
|
2844
2900
|
async handleTransportServiceCommand(command) {
|
|
2845
2901
|
const nodeSessions = this.ensureNodeSessions(command.nodeId);
|
|
2846
2902
|
const missingSegmentTimeout = import_cc.TransportServiceTimeouts.requestMissingSegmentR2;
|
|
2847
|
-
const
|
|
2848
|
-
const
|
|
2903
|
+
const sendSegmentComplete = /* @__PURE__ */ __name(() => {
|
|
2904
|
+
const cc = new import_cc.TransportServiceCCSegmentComplete({
|
|
2905
|
+
nodeId: command.nodeId,
|
|
2906
|
+
sessionId: command.sessionId
|
|
2907
|
+
});
|
|
2908
|
+
void this.sendCommand(cc, {
|
|
2909
|
+
maxSendAttempts: 1,
|
|
2910
|
+
priority: import_core.MessagePriority.Immediate
|
|
2911
|
+
}).catch(import_shared.noop);
|
|
2912
|
+
}, "sendSegmentComplete");
|
|
2913
|
+
const advanceTransportServiceSession = /* @__PURE__ */ __name((session2, input) => {
|
|
2914
|
+
const machine = session2.machine;
|
|
2849
2915
|
const transition = machine.next(input);
|
|
2850
2916
|
if (transition) {
|
|
2851
2917
|
machine.transition(transition.newState);
|
|
2852
2918
|
if (machine.state.value === "receive") {
|
|
2853
|
-
startMissingSegmentTimeout(
|
|
2919
|
+
startMissingSegmentTimeout(session2);
|
|
2854
2920
|
} else if (machine.state.value === "requestMissing") {
|
|
2855
2921
|
this.controllerLog.logNode(command.nodeId, {
|
|
2856
2922
|
message: `Transport Service RX session #${command.sessionId}: Segment with offset ${machine.state.offset} missing - requesting it...`,
|
|
@@ -2862,11 +2928,10 @@ ${(0, import_shared.buffer2hex)(data)}`, "warn");
|
|
|
2862
2928
|
sessionId: command.sessionId,
|
|
2863
2929
|
datagramOffset: machine.state.offset
|
|
2864
2930
|
});
|
|
2865
|
-
|
|
2931
|
+
this.sendCommand(cc, {
|
|
2866
2932
|
maxSendAttempts: 1,
|
|
2867
2933
|
priority: import_core.MessagePriority.Immediate
|
|
2868
|
-
}).catch(import_shared.noop);
|
|
2869
|
-
startMissingSegmentTimeout(session);
|
|
2934
|
+
}).catch(import_shared.noop).finally(() => startMissingSegmentTimeout(session2));
|
|
2870
2935
|
} else if (machine.state.value === "failure") {
|
|
2871
2936
|
this.controllerLog.logNode(command.nodeId, {
|
|
2872
2937
|
message: `Transport Service RX session #${command.sessionId} failed`,
|
|
@@ -2874,42 +2939,39 @@ ${(0, import_shared.buffer2hex)(data)}`, "warn");
|
|
|
2874
2939
|
direction: "none"
|
|
2875
2940
|
});
|
|
2876
2941
|
nodeSessions.transportService.delete(command.sessionId);
|
|
2877
|
-
if (
|
|
2878
|
-
clearTimeout(
|
|
2942
|
+
if (session2.timeout) {
|
|
2943
|
+
clearTimeout(session2.timeout);
|
|
2879
2944
|
}
|
|
2945
|
+
} else if (machine.state.value === "success") {
|
|
2946
|
+
this.controllerLog.logNode(command.nodeId, {
|
|
2947
|
+
message: `Transport Service RX session #${command.sessionId} complete`,
|
|
2948
|
+
level: "debug",
|
|
2949
|
+
direction: "inbound"
|
|
2950
|
+
});
|
|
2951
|
+
if (session2.timeout) {
|
|
2952
|
+
clearTimeout(session2.timeout);
|
|
2953
|
+
}
|
|
2954
|
+
sendSegmentComplete();
|
|
2955
|
+
return "completed";
|
|
2880
2956
|
}
|
|
2881
|
-
}
|
|
2882
|
-
|
|
2883
|
-
this.controllerLog.logNode(command.nodeId, {
|
|
2884
|
-
message: `Transport Service RX session #${command.sessionId} complete`,
|
|
2885
|
-
level: "debug",
|
|
2886
|
-
direction: "inbound"
|
|
2887
|
-
});
|
|
2888
|
-
if (session.timeout) {
|
|
2889
|
-
clearTimeout(session.timeout);
|
|
2890
|
-
}
|
|
2891
|
-
const cc = new import_cc.TransportServiceCCSegmentComplete({
|
|
2892
|
-
nodeId: command.nodeId,
|
|
2893
|
-
sessionId: command.sessionId
|
|
2894
|
-
});
|
|
2895
|
-
await this.sendCommand(cc, {
|
|
2896
|
-
maxSendAttempts: 1,
|
|
2897
|
-
priority: import_core.MessagePriority.Immediate
|
|
2898
|
-
}).catch(import_shared.noop);
|
|
2957
|
+
} else if (machine.state.value === "success") {
|
|
2958
|
+
sendSegmentComplete();
|
|
2899
2959
|
}
|
|
2900
2960
|
}, "advanceTransportServiceSession");
|
|
2901
|
-
function startMissingSegmentTimeout(
|
|
2902
|
-
if (
|
|
2903
|
-
clearTimeout(
|
|
2961
|
+
function startMissingSegmentTimeout(session2) {
|
|
2962
|
+
if (session2.timeout) {
|
|
2963
|
+
clearTimeout(session2.timeout);
|
|
2904
2964
|
}
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2965
|
+
session2.timeout = setTimeout(() => {
|
|
2966
|
+
session2.timeout = void 0;
|
|
2967
|
+
advanceTransportServiceSession(session2, {
|
|
2908
2968
|
value: "timeout"
|
|
2909
2969
|
});
|
|
2910
2970
|
}, missingSegmentTimeout);
|
|
2911
2971
|
}
|
|
2912
2972
|
__name(startMissingSegmentTimeout, "startMissingSegmentTimeout");
|
|
2973
|
+
let session;
|
|
2974
|
+
let datagramOffset;
|
|
2913
2975
|
if (command instanceof import_cc.TransportServiceCCFirstSegment) {
|
|
2914
2976
|
nodeSessions.transportService.clear();
|
|
2915
2977
|
this.controllerLog.logNode(command.nodeId, {
|
|
@@ -2918,21 +2980,15 @@ ${(0, import_shared.buffer2hex)(data)}`, "warn");
|
|
|
2918
2980
|
direction: "inbound"
|
|
2919
2981
|
});
|
|
2920
2982
|
const machine = (0, import_TransportServiceMachine.createTransportServiceRXMachine)(command.datagramSize, command.partialDatagram.length);
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2983
|
+
session = {
|
|
2984
|
+
machine,
|
|
2985
|
+
datagram: new import_shared.Bytes(command.datagramSize)
|
|
2924
2986
|
};
|
|
2925
2987
|
nodeSessions.transportService.set(command.sessionId, session);
|
|
2926
|
-
|
|
2988
|
+
datagramOffset = 0;
|
|
2927
2989
|
} else {
|
|
2928
|
-
|
|
2929
|
-
if (
|
|
2930
|
-
await advanceTransportServiceSession(transportSession, {
|
|
2931
|
-
value: "segment",
|
|
2932
|
-
offset: command.datagramOffset,
|
|
2933
|
-
length: command.partialDatagram.length
|
|
2934
|
-
});
|
|
2935
|
-
} else {
|
|
2990
|
+
session = nodeSessions.transportService.get(command.sessionId);
|
|
2991
|
+
if (!session) {
|
|
2936
2992
|
const cc = new import_cc.TransportServiceCCSegmentWait({
|
|
2937
2993
|
nodeId: command.nodeId,
|
|
2938
2994
|
pendingSegments: 0
|
|
@@ -2941,7 +2997,36 @@ ${(0, import_shared.buffer2hex)(data)}`, "warn");
|
|
|
2941
2997
|
maxSendAttempts: 1,
|
|
2942
2998
|
priority: import_core.MessagePriority.Immediate
|
|
2943
2999
|
}).catch(import_shared.noop);
|
|
3000
|
+
return;
|
|
2944
3001
|
}
|
|
3002
|
+
datagramOffset = command.datagramOffset;
|
|
3003
|
+
}
|
|
3004
|
+
if (datagramOffset + command.partialDatagram.length > session.datagram.length) {
|
|
3005
|
+
this.controllerLog.logNode(command.nodeId, {
|
|
3006
|
+
message: `Transport Service RX session #${command.sessionId}: Ignoring segment because it is incompatible with the datagram length`,
|
|
3007
|
+
level: "warn",
|
|
3008
|
+
direction: "inbound"
|
|
3009
|
+
});
|
|
3010
|
+
return;
|
|
3011
|
+
}
|
|
3012
|
+
session.datagram.set(command.partialDatagram, datagramOffset);
|
|
3013
|
+
const result = advanceTransportServiceSession(session, {
|
|
3014
|
+
value: "segment",
|
|
3015
|
+
offset: datagramOffset,
|
|
3016
|
+
length: command.partialDatagram.length
|
|
3017
|
+
});
|
|
3018
|
+
if (result !== "completed")
|
|
3019
|
+
return;
|
|
3020
|
+
try {
|
|
3021
|
+
return await import_cc.CommandClass.parse(session.datagram, {
|
|
3022
|
+
...this.getCCParsingContext(),
|
|
3023
|
+
sourceNodeId: command.nodeId,
|
|
3024
|
+
// Transport Service is only used for singlecast commands
|
|
3025
|
+
frameType: command.frameType ?? "singlecast"
|
|
3026
|
+
});
|
|
3027
|
+
} catch (e) {
|
|
3028
|
+
this.driverLog.print(`Dropping Transport Service datagram because the contained command could not be deserialized: ${(0, import_shared.getErrorMessage)(e)}`, "warn");
|
|
3029
|
+
return;
|
|
2945
3030
|
}
|
|
2946
3031
|
}
|
|
2947
3032
|
/**
|
|
@@ -3036,8 +3121,6 @@ ${handlers.length} left`);
|
|
|
3036
3121
|
this.controllerLog.logNode(cc.nodeId, `is unknown - discarding received command...`, "warn");
|
|
3037
3122
|
return true;
|
|
3038
3123
|
}
|
|
3039
|
-
if (cc instanceof import_cc.TransportServiceCC)
|
|
3040
|
-
return false;
|
|
3041
3124
|
if (cc instanceof import_cc.CRC16CCCommandEncapsulation) {
|
|
3042
3125
|
return this.isSecurityLevelTooLow(cc.encapsulated);
|
|
3043
3126
|
}
|
|
@@ -3093,7 +3176,7 @@ ${handlers.length} left`);
|
|
|
3093
3176
|
}
|
|
3094
3177
|
}
|
|
3095
3178
|
if (requiresSecurity && !isSecure) {
|
|
3096
|
-
this.controllerLog.logNode(cc.nodeId, `command was received at a lower security level than expected - discarding it
|
|
3179
|
+
this.controllerLog.logNode(cc.nodeId, `command was received at a lower security level than expected - discarding it:`, "warn");
|
|
3097
3180
|
return true;
|
|
3098
3181
|
}
|
|
3099
3182
|
return false;
|
|
@@ -4121,6 +4204,9 @@ ${handlers.length} left`);
|
|
|
4121
4204
|
if (!!options.reportTimeoutMs) {
|
|
4122
4205
|
msg.nodeUpdateTimeout = options.reportTimeoutMs;
|
|
4123
4206
|
}
|
|
4207
|
+
if (options.ignoreNodeUpdate) {
|
|
4208
|
+
msg.ignoreNodeUpdate = true;
|
|
4209
|
+
}
|
|
4124
4210
|
return msg;
|
|
4125
4211
|
}
|
|
4126
4212
|
/**
|