@willieee802/zigbee-herdsman 0.49.3 → 0.50.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/.github/dependabot.yml +0 -3
- package/.github/workflows/ci.yml +1 -2
- package/.github/workflows/release-please.yml +1 -1
- package/.github/workflows/typedoc.yaml +3 -3
- package/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +143 -0
- package/biome.json +1 -1
- package/dist/adapter/adapter.d.ts +14 -1
- package/dist/adapter/adapter.d.ts.map +1 -1
- package/dist/adapter/adapter.js +17 -0
- package/dist/adapter/adapter.js.map +1 -1
- package/dist/adapter/adapterDiscovery.d.ts.map +1 -1
- package/dist/adapter/adapterDiscovery.js.map +1 -1
- package/dist/adapter/deconz/adapter/deconzAdapter.d.ts +1 -3
- package/dist/adapter/deconz/adapter/deconzAdapter.d.ts.map +1 -1
- package/dist/adapter/deconz/adapter/deconzAdapter.js +14 -29
- package/dist/adapter/deconz/adapter/deconzAdapter.js.map +1 -1
- package/dist/adapter/deconz/driver/constants.d.ts +1 -1
- package/dist/adapter/deconz/driver/constants.d.ts.map +1 -1
- package/dist/adapter/ember/adapter/emberAdapter.d.ts +1 -1
- package/dist/adapter/ember/adapter/emberAdapter.d.ts.map +1 -1
- package/dist/adapter/ember/adapter/emberAdapter.js +19 -10
- package/dist/adapter/ember/adapter/emberAdapter.js.map +1 -1
- package/dist/adapter/ember/adapter/oneWaitress.d.ts +2 -0
- package/dist/adapter/ember/adapter/oneWaitress.d.ts.map +1 -1
- package/dist/adapter/ember/adapter/oneWaitress.js +13 -5
- package/dist/adapter/ember/adapter/oneWaitress.js.map +1 -1
- package/dist/adapter/ezsp/adapter/ezspAdapter.d.ts +1 -3
- package/dist/adapter/ezsp/adapter/ezspAdapter.d.ts.map +1 -1
- package/dist/adapter/ezsp/adapter/ezspAdapter.js +17 -30
- package/dist/adapter/ezsp/adapter/ezspAdapter.js.map +1 -1
- package/dist/adapter/ezsp/driver/index.d.ts +1 -1
- package/dist/adapter/ezsp/driver/index.d.ts.map +1 -1
- package/dist/adapter/ezsp/driver/index.js +1 -1
- package/dist/adapter/ezsp/driver/index.js.map +1 -1
- package/dist/adapter/ezsp/driver/types/index.d.ts +1 -1
- package/dist/adapter/ezsp/driver/types/index.d.ts.map +1 -1
- package/dist/adapter/ezsp/driver/types/index.js +3 -3
- package/dist/adapter/ezsp/driver/types/index.js.map +1 -1
- package/dist/adapter/serialPort.d.ts.map +1 -1
- package/dist/adapter/serialPort.js +7 -0
- package/dist/adapter/serialPort.js.map +1 -1
- package/dist/adapter/z-stack/adapter/adapter-backup.js +1 -1
- package/dist/adapter/z-stack/adapter/adapter-backup.js.map +1 -1
- package/dist/adapter/z-stack/adapter/adapter-nv-memory.js +1 -1
- package/dist/adapter/z-stack/adapter/adapter-nv-memory.js.map +1 -1
- package/dist/adapter/z-stack/adapter/manager.d.ts.map +1 -1
- package/dist/adapter/z-stack/adapter/manager.js +12 -2
- package/dist/adapter/z-stack/adapter/manager.js.map +1 -1
- package/dist/adapter/z-stack/adapter/tstype.d.ts.map +1 -1
- package/dist/adapter/z-stack/adapter/zStackAdapter.d.ts +1 -3
- package/dist/adapter/z-stack/adapter/zStackAdapter.d.ts.map +1 -1
- package/dist/adapter/z-stack/adapter/zStackAdapter.js +20 -34
- package/dist/adapter/z-stack/adapter/zStackAdapter.js.map +1 -1
- package/dist/adapter/z-stack/constants/index.d.ts +1 -1
- package/dist/adapter/z-stack/constants/index.d.ts.map +1 -1
- package/dist/adapter/z-stack/constants/index.js +1 -1
- package/dist/adapter/z-stack/constants/index.js.map +1 -1
- package/dist/adapter/z-stack/unpi/constants.d.ts +1 -1
- package/dist/adapter/z-stack/unpi/constants.d.ts.map +1 -1
- package/dist/adapter/z-stack/unpi/constants.js +1 -1
- package/dist/adapter/z-stack/unpi/constants.js.map +1 -1
- package/dist/adapter/zboss/adapter/zbossAdapter.d.ts +7 -8
- package/dist/adapter/zboss/adapter/zbossAdapter.d.ts.map +1 -1
- package/dist/adapter/zboss/adapter/zbossAdapter.js +12 -30
- package/dist/adapter/zboss/adapter/zbossAdapter.js.map +1 -1
- package/dist/adapter/zboss/driver.d.ts.map +1 -1
- package/dist/adapter/zboss/driver.js +8 -1
- package/dist/adapter/zboss/driver.js.map +1 -1
- package/dist/adapter/zboss/uart.d.ts.map +1 -1
- package/dist/adapter/zboss/uart.js +14 -2
- package/dist/adapter/zboss/uart.js.map +1 -1
- package/dist/adapter/zigate/adapter/zigateAdapter.d.ts +1 -3
- package/dist/adapter/zigate/adapter/zigateAdapter.d.ts.map +1 -1
- package/dist/adapter/zigate/adapter/zigateAdapter.js +8 -29
- package/dist/adapter/zigate/adapter/zigateAdapter.js.map +1 -1
- package/dist/adapter/zoh/adapter/zohAdapter.d.ts +1 -3
- package/dist/adapter/zoh/adapter/zohAdapter.d.ts.map +1 -1
- package/dist/adapter/zoh/adapter/zohAdapter.js +18 -33
- package/dist/adapter/zoh/adapter/zohAdapter.js.map +1 -1
- package/dist/controller/controller.d.ts.map +1 -1
- package/dist/controller/controller.js +10 -2
- package/dist/controller/controller.js.map +1 -1
- package/dist/controller/greenPower.d.ts.map +1 -1
- package/dist/controller/greenPower.js +15 -9
- package/dist/controller/greenPower.js.map +1 -1
- package/dist/controller/helpers/ota.d.ts +4 -4
- package/dist/controller/helpers/ota.d.ts.map +1 -1
- package/dist/controller/helpers/ota.js +28 -9
- package/dist/controller/helpers/ota.js.map +1 -1
- package/dist/controller/helpers/zclFrameConverter.d.ts.map +1 -1
- package/dist/controller/helpers/zclFrameConverter.js +17 -16
- package/dist/controller/helpers/zclFrameConverter.js.map +1 -1
- package/dist/controller/model/device.d.ts +14 -4
- package/dist/controller/model/device.d.ts.map +1 -1
- package/dist/controller/model/device.js +167 -85
- package/dist/controller/model/device.js.map +1 -1
- package/dist/controller/model/endpoint.d.ts +7 -3
- package/dist/controller/model/endpoint.d.ts.map +1 -1
- package/dist/controller/model/endpoint.js +34 -21
- package/dist/controller/model/endpoint.js.map +1 -1
- package/dist/controller/model/group.d.ts +0 -1
- package/dist/controller/model/group.d.ts.map +1 -1
- package/dist/controller/model/group.js +14 -19
- package/dist/controller/model/group.js.map +1 -1
- package/dist/controller/touchlink.js +3 -3
- package/dist/controller/touchlink.js.map +1 -1
- package/dist/utils/timeService.js +2 -2
- package/dist/utils/timeService.js.map +1 -1
- package/dist/zspec/zcl/buffaloZcl.d.ts +3 -3
- package/dist/zspec/zcl/buffaloZcl.d.ts.map +1 -1
- package/dist/zspec/zcl/buffaloZcl.js +198 -96
- package/dist/zspec/zcl/buffaloZcl.js.map +1 -1
- package/dist/zspec/zcl/definition/cluster.d.ts +2 -2
- package/dist/zspec/zcl/definition/cluster.d.ts.map +1 -1
- package/dist/zspec/zcl/definition/cluster.js +2699 -2808
- package/dist/zspec/zcl/definition/cluster.js.map +1 -1
- package/dist/zspec/zcl/definition/clusters-types.d.ts +63 -1109
- package/dist/zspec/zcl/definition/clusters-types.d.ts.map +1 -1
- package/dist/zspec/zcl/definition/enums.d.ts +0 -1
- package/dist/zspec/zcl/definition/enums.d.ts.map +1 -1
- package/dist/zspec/zcl/definition/enums.js +0 -1
- package/dist/zspec/zcl/definition/enums.js.map +1 -1
- package/dist/zspec/zcl/definition/foundation.d.ts +306 -7
- package/dist/zspec/zcl/definition/foundation.d.ts.map +1 -1
- package/dist/zspec/zcl/definition/foundation.js +552 -207
- package/dist/zspec/zcl/definition/foundation.js.map +1 -1
- package/dist/zspec/zcl/definition/status.d.ts +21 -10
- package/dist/zspec/zcl/definition/status.d.ts.map +1 -1
- package/dist/zspec/zcl/definition/status.js +11 -0
- package/dist/zspec/zcl/definition/status.js.map +1 -1
- package/dist/zspec/zcl/definition/tstype.d.ts +57 -48
- package/dist/zspec/zcl/definition/tstype.d.ts.map +1 -1
- package/dist/zspec/zcl/utils.d.ts +7 -4
- package/dist/zspec/zcl/utils.d.ts.map +1 -1
- package/dist/zspec/zcl/utils.js +133 -240
- package/dist/zspec/zcl/utils.js.map +1 -1
- package/dist/zspec/zcl/zclFrame.d.ts +4 -4
- package/dist/zspec/zcl/zclFrame.d.ts.map +1 -1
- package/dist/zspec/zcl/zclFrame.js +19 -103
- package/dist/zspec/zcl/zclFrame.js.map +1 -1
- package/dist/zspec/zcl/zclStatusError.d.ts +1 -1
- package/dist/zspec/zcl/zclStatusError.d.ts.map +1 -1
- package/dist/zspec/zcl/zclStatusError.js +2 -2
- package/dist/zspec/zcl/zclStatusError.js.map +1 -1
- package/package.json +1 -1
- package/scripts/clusters-typegen.ts +44 -139
- package/src/adapter/adapter.ts +38 -3
- package/src/adapter/adapterDiscovery.ts +2 -1
- package/src/adapter/deconz/adapter/deconzAdapter.ts +24 -51
- package/src/adapter/deconz/driver/constants.ts +1 -1
- package/src/adapter/ember/adapter/emberAdapter.ts +23 -10
- package/src/adapter/ember/adapter/oneWaitress.ts +16 -6
- package/src/adapter/ezsp/adapter/ezspAdapter.ts +27 -48
- package/src/adapter/ezsp/driver/index.ts +1 -1
- package/src/adapter/ezsp/driver/types/index.ts +99 -99
- package/src/adapter/serialPort.ts +9 -0
- package/src/adapter/z-stack/adapter/adapter-backup.ts +1 -1
- package/src/adapter/z-stack/adapter/adapter-nv-memory.ts +1 -1
- package/src/adapter/z-stack/adapter/manager.ts +16 -2
- package/src/adapter/z-stack/adapter/tstype.ts +1 -0
- package/src/adapter/z-stack/adapter/zStackAdapter.ts +34 -81
- package/src/adapter/z-stack/constants/index.ts +1 -1
- package/src/adapter/z-stack/unpi/constants.ts +1 -1
- package/src/adapter/zboss/adapter/zbossAdapter.ts +23 -54
- package/src/adapter/zboss/driver.ts +8 -1
- package/src/adapter/zboss/uart.ts +14 -1
- package/src/adapter/zigate/adapter/zigateAdapter.ts +17 -48
- package/src/adapter/zoh/adapter/zohAdapter.ts +27 -50
- package/src/controller/controller.ts +12 -2
- package/src/controller/greenPower.ts +16 -9
- package/src/controller/helpers/ota.ts +37 -11
- package/src/controller/helpers/zclFrameConverter.ts +20 -17
- package/src/controller/model/device.ts +204 -97
- package/src/controller/model/endpoint.ts +36 -24
- package/src/controller/model/group.ts +14 -20
- package/src/controller/touchlink.ts +3 -3
- package/src/utils/timeService.ts +2 -2
- package/src/zspec/zcl/buffaloZcl.ts +226 -100
- package/src/zspec/zcl/definition/cluster.ts +2713 -2822
- package/src/zspec/zcl/definition/clusters-types.ts +80 -1135
- package/src/zspec/zcl/definition/enums.ts +0 -1
- package/src/zspec/zcl/definition/foundation.ts +703 -216
- package/src/zspec/zcl/definition/status.ts +22 -11
- package/src/zspec/zcl/definition/tstype.ts +59 -58
- package/src/zspec/zcl/utils.ts +137 -264
- package/src/zspec/zcl/zclFrame.ts +25 -130
- package/src/zspec/zcl/zclStatusError.ts +2 -2
- package/test/adapter/ember/emberAdapter.test.ts +191 -4
- package/test/adapter/ezsp/uart.test.ts +10 -10
- package/test/adapter/z-stack/adapter.test.ts +88 -32
- package/test/adapter/zoh/zohAdapter.test.ts +4 -4
- package/test/controller.test.ts +822 -248
- package/test/device-ota.test.ts +141 -16
- package/test/device.test.ts +731 -0
- package/test/requests.bench.ts +2 -0
- package/test/zcl.test.ts +70 -95
- package/test/zspec/zcl/buffalo.test.ts +251 -11
- package/test/zspec/zcl/foundation.test.ts +990 -0
- package/test/zspec/zcl/frame.test.ts +84 -69
- package/test/zspec/zcl/utils.test.ts +105 -81
- package/tsconfig.json +0 -1
- package/scripts/check-clusters-changes.ts +0 -328
- package/scripts/clusters-changes.log +0 -584
- package/scripts/utils.ts +0 -88
- package/scripts/zap-update-clusters-report.json +0 -303
- package/scripts/zap-update-clusters.ts +0 -1520
- package/scripts/zap-update-types.ts +0 -707
- package/scripts/zap-xml-clusters-overrides-data.ts +0 -52
- package/scripts/zap-xml-clusters-overrides.ts +0 -400
- package/scripts/zap-xml-types.ts +0 -146
|
@@ -59,7 +59,7 @@ export class AdapterBackup {
|
|
|
59
59
|
|
|
60
60
|
/* get adapter ieee address */
|
|
61
61
|
const ieeeAddressResponse = await this.znp.requestWithReply(Subsystem.SYS, "getExtAddr", {});
|
|
62
|
-
if (!ieeeAddressResponse.payload.extaddress
|
|
62
|
+
if (!ieeeAddressResponse.payload.extaddress?.startsWith("0x")) {
|
|
63
63
|
throw new Error("Failed to read adapter IEEE address");
|
|
64
64
|
}
|
|
65
65
|
const ieeeAddress = Buffer.from(ieeeAddressResponse.payload.extaddress.split("0x")[1], "hex");
|
|
@@ -151,7 +151,7 @@ export class AdapterNvMemory {
|
|
|
151
151
|
public async updateItem(id: NvItemsIds, data: Buffer, autoInit = true): Promise<void> {
|
|
152
152
|
this.checkMemoryAlignmentSetup();
|
|
153
153
|
const current = await this.readItem(id);
|
|
154
|
-
if (!current
|
|
154
|
+
if (!current?.equals(data)) {
|
|
155
155
|
await this.writeItem(id, data, 0, autoInit);
|
|
156
156
|
}
|
|
157
157
|
}
|
|
@@ -150,7 +150,11 @@ export class ZnpAdapterManager {
|
|
|
150
150
|
/* exception for some adapters which may actually use 0xdddddddddddddddd as EPID (backward compatibility) */
|
|
151
151
|
/* v8 ignore next */
|
|
152
152
|
this.nwkOptions.hasDefaultExtendedPanId) &&
|
|
153
|
-
|
|
153
|
+
/* On Z-Stack 3.x, the preconfigured (transport) key in NVRAM may retain a default
|
|
154
|
+
* firmware value that does not match the configured network key, even though the
|
|
155
|
+
* active and alternate keys are correct. Only require preconfiguredKey match on
|
|
156
|
+
* Z-Stack 1.2 where it serves as the active key (see lines 128-133 above). */
|
|
157
|
+
(this.options.version !== ZnpVersion.ZStack12 || this.nwkOptions.networkKey.equals(preconfiguredKey.key)) &&
|
|
154
158
|
this.nwkOptions.networkKey.equals(activeKeyInfo.key) &&
|
|
155
159
|
this.nwkOptions.networkKey.equals(alternateKeyInfo.key);
|
|
156
160
|
|
|
@@ -178,7 +182,7 @@ export class ZnpAdapterManager {
|
|
|
178
182
|
};
|
|
179
183
|
|
|
180
184
|
/* Determine startup strategy */
|
|
181
|
-
if (!hasConfigured
|
|
185
|
+
if (!hasConfigured?.isConfigured() || !nib) {
|
|
182
186
|
/* Adapter is not configured or not commissioned */
|
|
183
187
|
logger.debug("(stage-1) adapter is not configured / not commissioned", NS);
|
|
184
188
|
if (configMatchesBackup) {
|
|
@@ -199,6 +203,16 @@ export class ZnpAdapterManager {
|
|
|
199
203
|
logger.debug("(stage-1) adapter is configured", NS);
|
|
200
204
|
|
|
201
205
|
if (configMatchesAdapter) {
|
|
206
|
+
/* Warn if preconfigured key doesn't match (Z-Stack 3.x only, non-fatal) */
|
|
207
|
+
if (this.options.version !== ZnpVersion.ZStack12 && !this.nwkOptions.networkKey.equals(preconfiguredKey.key)) {
|
|
208
|
+
logger.warning(
|
|
209
|
+
"Adapter preconfigured (transport) key does not match configured network key " +
|
|
210
|
+
`(preconfigured=${preconfiguredKey.key.toString("hex")}, configured=${this.nwkOptions.networkKey.toString("hex")}). ` +
|
|
211
|
+
"This is typically harmless on Z-Stack 3.x adapters where only the active key matters.",
|
|
212
|
+
NS,
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
202
216
|
/* Warn if EPID is reversed (backward-compat) */
|
|
203
217
|
if (isExtendedPanIdReversed) {
|
|
204
218
|
logger.debug("(stage-2) extended pan id is reversed", NS);
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
|
-
|
|
3
2
|
import debounce from "debounce";
|
|
4
|
-
|
|
5
3
|
import type * as Models from "../../../models";
|
|
6
4
|
import {Queue, Waitress, wait} from "../../../utils";
|
|
7
5
|
import {logger} from "../../../utils/logger";
|
|
@@ -11,7 +9,7 @@ import type {Eui64} from "../../../zspec/tstypes";
|
|
|
11
9
|
import * as Zcl from "../../../zspec/zcl";
|
|
12
10
|
import * as Zdo from "../../../zspec/zdo";
|
|
13
11
|
import type * as ZdoTypes from "../../../zspec/zdo/definition/tstypes";
|
|
14
|
-
import Adapter from "../../adapter";
|
|
12
|
+
import Adapter, {type ClusterWaitressMatcher, type ZclWaitressPayload} from "../../adapter";
|
|
15
13
|
import type * as Events from "../../events";
|
|
16
14
|
import type {AdapterOptions, CoordinatorVersion, NetworkOptions, NetworkParameters, SerialPortOptions, StartResult} from "../../tstype";
|
|
17
15
|
import * as Constants from "../constants";
|
|
@@ -31,16 +29,6 @@ const {ZnpCommandStatus, AddressMode} = Constants.COMMON;
|
|
|
31
29
|
|
|
32
30
|
const DataConfirmTimeout = 9999; // Not an actual code
|
|
33
31
|
|
|
34
|
-
interface WaitressMatcher {
|
|
35
|
-
address?: number | string;
|
|
36
|
-
endpoint: number;
|
|
37
|
-
transactionSequenceNumber?: number;
|
|
38
|
-
frameType: Zcl.FrameType;
|
|
39
|
-
clusterID: number;
|
|
40
|
-
commandIdentifier: number;
|
|
41
|
-
direction: number;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
32
|
class DataConfirmError extends Error {
|
|
45
33
|
public code: number;
|
|
46
34
|
constructor(code: number) {
|
|
@@ -72,7 +60,7 @@ export class ZStackAdapter extends Adapter {
|
|
|
72
60
|
private supportsLED?: boolean;
|
|
73
61
|
private interpanLock: boolean;
|
|
74
62
|
private interpanEndpointRegistered: boolean;
|
|
75
|
-
private waitress: Waitress<
|
|
63
|
+
private waitress: Waitress<ZclWaitressPayload, ClusterWaitressMatcher>;
|
|
76
64
|
private konnextConfig: KonnextConfig;
|
|
77
65
|
|
|
78
66
|
public constructor(networkOptions: NetworkOptions, serialPortOptions: SerialPortOptions, backupPath: string, adapterOptions: AdapterOptions, konnextConfig: KonnextConfig) {
|
|
@@ -88,7 +76,7 @@ export class ZStackAdapter extends Adapter {
|
|
|
88
76
|
this.interpanLock = false;
|
|
89
77
|
this.interpanEndpointRegistered = false;
|
|
90
78
|
this.closing = false;
|
|
91
|
-
this.waitress = new Waitress
|
|
79
|
+
this.waitress = new Waitress(Adapter.zclWaitressValidator, Adapter.clusterWaitressTimeoutFormatter);
|
|
92
80
|
|
|
93
81
|
this.znp.on("received", this.onZnpRecieved.bind(this));
|
|
94
82
|
this.znp.on("close", this.onZnpClose.bind(this));
|
|
@@ -530,22 +518,20 @@ export class ZStackAdapter extends Adapter {
|
|
|
530
518
|
response = this.waitForInternal(
|
|
531
519
|
networkAddress,
|
|
532
520
|
endpoint,
|
|
533
|
-
zclFrame.header.frameControl.frameType,
|
|
534
|
-
Zcl.Direction.SERVER_TO_CLIENT,
|
|
535
521
|
zclFrame.header.transactionSequenceNumber,
|
|
536
522
|
zclFrame.cluster.ID,
|
|
537
523
|
command.response,
|
|
524
|
+
undefined,
|
|
538
525
|
timeout,
|
|
539
526
|
);
|
|
540
527
|
} else if (!zclFrame.header.frameControl.disableDefaultResponse) {
|
|
541
528
|
response = this.waitForInternal(
|
|
542
529
|
networkAddress,
|
|
543
530
|
endpoint,
|
|
544
|
-
Zcl.FrameType.GLOBAL,
|
|
545
|
-
Zcl.Direction.SERVER_TO_CLIENT,
|
|
546
531
|
zclFrame.header.transactionSequenceNumber,
|
|
547
532
|
zclFrame.cluster.ID,
|
|
548
533
|
Zcl.Foundation.defaultRsp.ID,
|
|
534
|
+
undefined,
|
|
549
535
|
timeout,
|
|
550
536
|
);
|
|
551
537
|
}
|
|
@@ -978,7 +964,11 @@ export class ZStackAdapter extends Adapter {
|
|
|
978
964
|
wasBroadcast: object.payload.wasbroadcast === 1,
|
|
979
965
|
destinationEndpoint: object.payload.dstendpoint,
|
|
980
966
|
};
|
|
981
|
-
|
|
967
|
+
|
|
968
|
+
if (payload.header !== undefined) {
|
|
969
|
+
this.waitress.resolve(payload as ZclWaitressPayload);
|
|
970
|
+
}
|
|
971
|
+
|
|
982
972
|
this.emit("zclPayload", payload);
|
|
983
973
|
}
|
|
984
974
|
})
|
|
@@ -999,7 +989,10 @@ export class ZStackAdapter extends Adapter {
|
|
|
999
989
|
destinationEndpoint: object.payload.dstendpoint,
|
|
1000
990
|
};
|
|
1001
991
|
|
|
1002
|
-
|
|
992
|
+
if (payload.header !== undefined) {
|
|
993
|
+
this.waitress.resolve(payload as ZclWaitressPayload);
|
|
994
|
+
}
|
|
995
|
+
|
|
1003
996
|
this.emit("zclPayload", payload);
|
|
1004
997
|
}
|
|
1005
998
|
}
|
|
@@ -1077,16 +1070,7 @@ export class ZStackAdapter extends Adapter {
|
|
|
1077
1070
|
let response: ReturnType<typeof this.waitForInternal> | undefined;
|
|
1078
1071
|
|
|
1079
1072
|
if (!disableResponse && command.response !== undefined) {
|
|
1080
|
-
response = this.waitForInternal(
|
|
1081
|
-
undefined,
|
|
1082
|
-
0xfe,
|
|
1083
|
-
zclFrame.header.frameControl.frameType,
|
|
1084
|
-
Zcl.Direction.SERVER_TO_CLIENT,
|
|
1085
|
-
undefined,
|
|
1086
|
-
zclFrame.cluster.ID,
|
|
1087
|
-
command.response,
|
|
1088
|
-
timeout,
|
|
1089
|
-
);
|
|
1073
|
+
response = this.waitForInternal(undefined, 0xfe, undefined, zclFrame.cluster.ID, command.response, undefined, timeout);
|
|
1090
1074
|
}
|
|
1091
1075
|
|
|
1092
1076
|
try {
|
|
@@ -1125,22 +1109,13 @@ export class ZStackAdapter extends Adapter {
|
|
|
1125
1109
|
private waitForInternal(
|
|
1126
1110
|
networkAddress: number | undefined,
|
|
1127
1111
|
endpoint: number,
|
|
1128
|
-
frameType: Zcl.FrameType,
|
|
1129
|
-
direction: Zcl.Direction,
|
|
1130
1112
|
transactionSequenceNumber: number | undefined,
|
|
1131
|
-
|
|
1132
|
-
|
|
1113
|
+
clusterId: number,
|
|
1114
|
+
commandId: number,
|
|
1115
|
+
defaultRspCommandId: number | undefined,
|
|
1133
1116
|
timeout: number,
|
|
1134
1117
|
): {start: () => {promise: Promise<Events.ZclPayload>}; cancel: () => void} {
|
|
1135
|
-
const payload = {
|
|
1136
|
-
address: networkAddress,
|
|
1137
|
-
endpoint,
|
|
1138
|
-
clusterID,
|
|
1139
|
-
commandIdentifier,
|
|
1140
|
-
frameType,
|
|
1141
|
-
direction,
|
|
1142
|
-
transactionSequenceNumber,
|
|
1143
|
-
};
|
|
1118
|
+
const payload = {address: networkAddress, endpoint, clusterId, commandId, defaultRspCommandId, transactionSequenceNumber};
|
|
1144
1119
|
|
|
1145
1120
|
const waiter = this.waitress.waitFor(payload, timeout);
|
|
1146
1121
|
const cancel = (): void => this.waitress.remove(waiter.ID);
|
|
@@ -1148,25 +1123,17 @@ export class ZStackAdapter extends Adapter {
|
|
|
1148
1123
|
}
|
|
1149
1124
|
|
|
1150
1125
|
public waitFor(
|
|
1151
|
-
networkAddress: number
|
|
1126
|
+
networkAddress: number,
|
|
1152
1127
|
endpoint: number,
|
|
1153
|
-
|
|
1154
|
-
|
|
1128
|
+
_frameType: Zcl.FrameType,
|
|
1129
|
+
_direction: Zcl.Direction,
|
|
1155
1130
|
transactionSequenceNumber: number | undefined,
|
|
1156
|
-
|
|
1157
|
-
|
|
1131
|
+
clusterId: number,
|
|
1132
|
+
commandId: number,
|
|
1133
|
+
defaultRspCommandId: number | undefined,
|
|
1158
1134
|
timeout: number,
|
|
1159
1135
|
): {promise: Promise<Events.ZclPayload>; cancel: () => void} {
|
|
1160
|
-
const waiter = this.waitForInternal(
|
|
1161
|
-
networkAddress,
|
|
1162
|
-
endpoint,
|
|
1163
|
-
frameType,
|
|
1164
|
-
direction,
|
|
1165
|
-
transactionSequenceNumber,
|
|
1166
|
-
clusterID,
|
|
1167
|
-
commandIdentifier,
|
|
1168
|
-
timeout,
|
|
1169
|
-
);
|
|
1136
|
+
const waiter = this.waitForInternal(networkAddress, endpoint, transactionSequenceNumber, clusterId, commandId, defaultRspCommandId, timeout);
|
|
1170
1137
|
|
|
1171
1138
|
return {cancel: waiter.cancel, promise: waiter.start().promise};
|
|
1172
1139
|
}
|
|
@@ -1186,6 +1153,13 @@ export class ZStackAdapter extends Adapter {
|
|
|
1186
1153
|
const transactionID = this.nextTransactionID();
|
|
1187
1154
|
const response = this.znp.waitFor(Type.AREQ, Subsystem.AF, "dataConfirm", undefined, transactionID, undefined, timeout);
|
|
1188
1155
|
|
|
1156
|
+
let options = 0;
|
|
1157
|
+
|
|
1158
|
+
// Zigbee Direct cluster, enable APS layer encryption
|
|
1159
|
+
if (clusterID === Zcl.Clusters.zigbeeDirectConfiguration.ID) {
|
|
1160
|
+
options |= Constants.AF.options.EN_SECURITY;
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1189
1163
|
await this.znp.request(
|
|
1190
1164
|
Subsystem.AF,
|
|
1191
1165
|
"dataRequest",
|
|
@@ -1195,7 +1169,7 @@ export class ZStackAdapter extends Adapter {
|
|
|
1195
1169
|
srcendpoint: sourceEndpoint,
|
|
1196
1170
|
clusterid: clusterID,
|
|
1197
1171
|
transid: transactionID,
|
|
1198
|
-
options
|
|
1172
|
+
options,
|
|
1199
1173
|
radius: radius,
|
|
1200
1174
|
len: data.length,
|
|
1201
1175
|
data: data,
|
|
@@ -1301,27 +1275,6 @@ export class ZStackAdapter extends Adapter {
|
|
|
1301
1275
|
return typeof address === "number" ? `0x${address.toString(16).padStart(16, "0")}` : address.toString();
|
|
1302
1276
|
}
|
|
1303
1277
|
|
|
1304
|
-
private waitressTimeoutFormatter(matcher: WaitressMatcher, timeout: number): string {
|
|
1305
|
-
return (
|
|
1306
|
-
`Timeout - ${matcher.address} - ${matcher.endpoint}` +
|
|
1307
|
-
` - ${matcher.transactionSequenceNumber} - ${matcher.clusterID}` +
|
|
1308
|
-
` - ${matcher.commandIdentifier} after ${timeout}ms`
|
|
1309
|
-
);
|
|
1310
|
-
}
|
|
1311
|
-
|
|
1312
|
-
private waitressValidator(payload: Events.ZclPayload, matcher: WaitressMatcher): boolean {
|
|
1313
|
-
return Boolean(
|
|
1314
|
-
payload.header &&
|
|
1315
|
-
(!matcher.address || payload.address === matcher.address) &&
|
|
1316
|
-
payload.endpoint === matcher.endpoint &&
|
|
1317
|
-
(matcher.transactionSequenceNumber === undefined || payload.header.transactionSequenceNumber === matcher.transactionSequenceNumber) &&
|
|
1318
|
-
payload.clusterID === matcher.clusterID &&
|
|
1319
|
-
matcher.frameType === payload.header.frameControl.frameType &&
|
|
1320
|
-
matcher.commandIdentifier === payload.header.commandIdentifier &&
|
|
1321
|
-
matcher.direction === payload.header.frameControl.direction,
|
|
1322
|
-
);
|
|
1323
|
-
}
|
|
1324
|
-
|
|
1325
1278
|
private checkInterpanLock(): void {
|
|
1326
1279
|
if (this.interpanLock) {
|
|
1327
1280
|
throw new Error("Cannot execute command, in Inter-PAN mode");
|
|
@@ -30,4 +30,4 @@ const PositionCmd1 = 3;
|
|
|
30
30
|
const MinMessageLength = 5;
|
|
31
31
|
const MaxDataSize = 250;
|
|
32
32
|
|
|
33
|
-
export {
|
|
33
|
+
export {DataStart, MaxDataSize, MinMessageLength, PositionCmd0, PositionCmd1, PositionDataLength, SOF, Subsystem, Type};
|
|
@@ -8,35 +8,23 @@ import * as ZSpec from "../../../zspec";
|
|
|
8
8
|
import * as Zcl from "../../../zspec/zcl";
|
|
9
9
|
import * as Zdo from "../../../zspec/zdo";
|
|
10
10
|
import type * as ZdoTypes from "../../../zspec/zdo/definition/tstypes";
|
|
11
|
-
import {Adapter, type
|
|
11
|
+
import {Adapter, type ClusterWaitressMatcher, type ZclWaitressPayload} from "../../adapter";
|
|
12
12
|
import {WORKAROUND_JOIN_MANUF_IEEE_PREFIX_TO_CODE} from "../../const";
|
|
13
13
|
import type {ZclPayload} from "../../events";
|
|
14
|
+
import type {AdapterOptions, CoordinatorVersion, NetworkOptions, NetworkParameters, SerialPortOptions, StartResult} from "../../tstype";
|
|
14
15
|
import {ZBOSSDriver} from "../driver";
|
|
15
16
|
import {CommandId, DeviceUpdateStatus} from "../enums";
|
|
16
17
|
import {FrameType, type ZBOSSFrame} from "../frame";
|
|
17
18
|
|
|
18
19
|
const NS = "zh:zboss";
|
|
19
20
|
|
|
20
|
-
interface WaitressMatcher {
|
|
21
|
-
address: number | string;
|
|
22
|
-
endpoint: number;
|
|
23
|
-
transactionSequenceNumber?: number;
|
|
24
|
-
clusterID: number;
|
|
25
|
-
commandIdentifier: number;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
21
|
export class ZBOSSAdapter extends Adapter {
|
|
29
22
|
private queue: Queue;
|
|
30
23
|
private readonly driver: ZBOSSDriver;
|
|
31
|
-
private waitress: Waitress<
|
|
24
|
+
private waitress: Waitress<ZclWaitressPayload, ClusterWaitressMatcher>;
|
|
32
25
|
private currentManufacturerCode: Zcl.ManufacturerCode;
|
|
33
26
|
|
|
34
|
-
constructor(
|
|
35
|
-
networkOptions: TsType.NetworkOptions,
|
|
36
|
-
serialPortOptions: TsType.SerialPortOptions,
|
|
37
|
-
backupPath: string,
|
|
38
|
-
adapterOptions: TsType.AdapterOptions,
|
|
39
|
-
) {
|
|
27
|
+
constructor(networkOptions: NetworkOptions, serialPortOptions: SerialPortOptions, backupPath: string, adapterOptions: AdapterOptions) {
|
|
40
28
|
super(networkOptions, serialPortOptions, backupPath, adapterOptions);
|
|
41
29
|
this.hasZdoMessageOverhead = false;
|
|
42
30
|
this.manufacturerID = Zcl.ManufacturerCode.NORDIC_SEMICONDUCTOR_ASA;
|
|
@@ -45,7 +33,7 @@ export class ZBOSSAdapter extends Adapter {
|
|
|
45
33
|
logger.debug(`Adapter concurrent: ${concurrent}`, NS);
|
|
46
34
|
this.queue = new Queue(concurrent);
|
|
47
35
|
|
|
48
|
-
this.waitress = new Waitress
|
|
36
|
+
this.waitress = new Waitress(Adapter.zclWaitressValidator, Adapter.clusterWaitressTimeoutFormatter);
|
|
49
37
|
this.driver = new ZBOSSDriver(serialPortOptions, networkOptions);
|
|
50
38
|
this.driver.on("frame", this.processMessage.bind(this));
|
|
51
39
|
}
|
|
@@ -107,7 +95,10 @@ export class ZBOSSAdapter extends Adapter {
|
|
|
107
95
|
destinationEndpoint: frame.payload.dstEndpoint,
|
|
108
96
|
};
|
|
109
97
|
|
|
110
|
-
|
|
98
|
+
if (payload.header !== undefined) {
|
|
99
|
+
this.waitress.resolve(payload as ZclWaitressPayload);
|
|
100
|
+
}
|
|
101
|
+
|
|
111
102
|
this.emit("zclPayload", payload);
|
|
112
103
|
break;
|
|
113
104
|
}
|
|
@@ -115,7 +106,7 @@ export class ZBOSSAdapter extends Adapter {
|
|
|
115
106
|
}
|
|
116
107
|
}
|
|
117
108
|
|
|
118
|
-
public async start(): Promise<
|
|
109
|
+
public async start(): Promise<StartResult> {
|
|
119
110
|
logger.info("ZBOSS Adapter starting", NS);
|
|
120
111
|
|
|
121
112
|
await this.driver.connect();
|
|
@@ -133,8 +124,8 @@ export class ZBOSSAdapter extends Adapter {
|
|
|
133
124
|
return await Promise.resolve(this.driver.netInfo.ieeeAddr);
|
|
134
125
|
}
|
|
135
126
|
|
|
136
|
-
public async getCoordinatorVersion(): Promise<
|
|
137
|
-
return await this.queue.execute<
|
|
127
|
+
public async getCoordinatorVersion(): Promise<CoordinatorVersion> {
|
|
128
|
+
return await this.queue.execute<CoordinatorVersion>(async () => {
|
|
138
129
|
const ver = await this.driver.execCommand(CommandId.GET_MODULE_VERSION, {});
|
|
139
130
|
const cver = await this.driver.execCommand(CommandId.GET_COORDINATOR_VERSION, {});
|
|
140
131
|
const ver2str = (version: number): string => {
|
|
@@ -169,7 +160,7 @@ export class ZBOSSAdapter extends Adapter {
|
|
|
169
160
|
return await Promise.reject(new Error("This adapter does not support backup"));
|
|
170
161
|
}
|
|
171
162
|
|
|
172
|
-
public async getNetworkParameters(): Promise<
|
|
163
|
+
public async getNetworkParameters(): Promise<NetworkParameters> {
|
|
173
164
|
return await this.queue.execute(async () => {
|
|
174
165
|
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
|
|
175
166
|
const channel = this.driver.netInfo!.network.channel;
|
|
@@ -362,6 +353,7 @@ export class ZBOSSAdapter extends Adapter {
|
|
|
362
353
|
zclFrame.cluster.ID,
|
|
363
354
|
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
|
|
364
355
|
command.response!,
|
|
356
|
+
undefined,
|
|
365
357
|
timeout,
|
|
366
358
|
);
|
|
367
359
|
} else if (!zclFrame.header.frameControl.disableDefaultResponse) {
|
|
@@ -371,6 +363,7 @@ export class ZBOSSAdapter extends Adapter {
|
|
|
371
363
|
zclFrame.header.transactionSequenceNumber,
|
|
372
364
|
zclFrame.cluster.ID,
|
|
373
365
|
Zcl.Foundation.defaultRsp.ID,
|
|
366
|
+
undefined,
|
|
374
367
|
timeout,
|
|
375
368
|
);
|
|
376
369
|
}
|
|
@@ -480,18 +473,13 @@ export class ZBOSSAdapter extends Adapter {
|
|
|
480
473
|
networkAddress: number,
|
|
481
474
|
endpoint: number,
|
|
482
475
|
transactionSequenceNumber: number | undefined,
|
|
483
|
-
|
|
484
|
-
|
|
476
|
+
clusterId: number,
|
|
477
|
+
commandId: number,
|
|
478
|
+
defaultRspCommandId: number | undefined,
|
|
485
479
|
timeout: number,
|
|
486
480
|
): {start: () => {promise: Promise<ZclPayload>}; cancel: () => void} {
|
|
487
481
|
const waiter = this.waitress.waitFor(
|
|
488
|
-
{
|
|
489
|
-
address: networkAddress,
|
|
490
|
-
endpoint,
|
|
491
|
-
clusterID,
|
|
492
|
-
commandIdentifier,
|
|
493
|
-
transactionSequenceNumber,
|
|
494
|
-
},
|
|
482
|
+
{address: networkAddress, endpoint, clusterId, commandId, defaultRspCommandId, transactionSequenceNumber},
|
|
495
483
|
timeout,
|
|
496
484
|
);
|
|
497
485
|
const cancel = (): void => this.waitress.remove(waiter.ID);
|
|
@@ -504,32 +492,13 @@ export class ZBOSSAdapter extends Adapter {
|
|
|
504
492
|
_frameType: Zcl.FrameType,
|
|
505
493
|
_direction: Zcl.Direction,
|
|
506
494
|
transactionSequenceNumber: number | undefined,
|
|
507
|
-
|
|
508
|
-
|
|
495
|
+
clusterId: number,
|
|
496
|
+
commandId: number,
|
|
497
|
+
defaultRspCommandId: number | undefined,
|
|
509
498
|
timeout: number,
|
|
510
499
|
): {promise: Promise<ZclPayload>; cancel: () => void} {
|
|
511
|
-
const waiter = this.waitForInternal(networkAddress, endpoint, transactionSequenceNumber,
|
|
500
|
+
const waiter = this.waitForInternal(networkAddress, endpoint, transactionSequenceNumber, clusterId, commandId, defaultRspCommandId, timeout);
|
|
512
501
|
|
|
513
502
|
return {cancel: waiter.cancel, promise: waiter.start().promise};
|
|
514
503
|
}
|
|
515
|
-
|
|
516
|
-
private waitressTimeoutFormatter(matcher: WaitressMatcher, timeout: number): string {
|
|
517
|
-
return (
|
|
518
|
-
`Timeout - ${matcher.address} - ${matcher.endpoint}` +
|
|
519
|
-
` - ${matcher.transactionSequenceNumber} - ${matcher.clusterID}` +
|
|
520
|
-
` - ${matcher.commandIdentifier} after ${timeout}ms`
|
|
521
|
-
);
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
private waitressValidator(payload: ZclPayload, matcher: WaitressMatcher): boolean {
|
|
525
|
-
return (
|
|
526
|
-
(payload.header &&
|
|
527
|
-
(!matcher.address || payload.address === matcher.address) &&
|
|
528
|
-
payload.endpoint === matcher.endpoint &&
|
|
529
|
-
(matcher.transactionSequenceNumber === undefined || payload.header.transactionSequenceNumber === matcher.transactionSequenceNumber) &&
|
|
530
|
-
payload.clusterID === matcher.clusterID &&
|
|
531
|
-
matcher.commandIdentifier === payload.header.commandIdentifier) ||
|
|
532
|
-
false
|
|
533
|
-
);
|
|
534
|
-
}
|
|
535
504
|
}
|
|
@@ -8,6 +8,7 @@ import {Waitress} from "../../utils";
|
|
|
8
8
|
import {AsyncMutex} from "../../utils/async-mutex";
|
|
9
9
|
import {logger} from "../../utils/logger";
|
|
10
10
|
import type * as ZSpec from "../../zspec";
|
|
11
|
+
import * as Zcl from "../../zspec/zcl";
|
|
11
12
|
import * as Zdo from "../../zspec/zdo";
|
|
12
13
|
import type {TsType} from "..";
|
|
13
14
|
import {ZDO_REQ_CLUSTER_ID_TO_ZBOSS_COMMAND_ID} from "./commands";
|
|
@@ -307,6 +308,12 @@ export class ZBOSSDriver extends EventEmitter {
|
|
|
307
308
|
}
|
|
308
309
|
|
|
309
310
|
public async request(ieee: string, profileID: number, clusterID: number, dstEp: number, srcEp: number, data: Buffer): Promise<ZBOSSFrame> {
|
|
311
|
+
// Default APS options
|
|
312
|
+
let txOptions = 0x02; // ROUTE DISCOVERY
|
|
313
|
+
// Zigbee Direct cluster, enable APS layer encryption
|
|
314
|
+
if (clusterID === Zcl.Clusters.zigbeeDirectConfiguration.ID) {
|
|
315
|
+
txOptions |= 0x01;
|
|
316
|
+
}
|
|
310
317
|
const payload = {
|
|
311
318
|
paramLength: 21,
|
|
312
319
|
dataLength: data.length,
|
|
@@ -317,7 +324,7 @@ export class ZBOSSDriver extends EventEmitter {
|
|
|
317
324
|
srcEndpoint: srcEp,
|
|
318
325
|
radius: 3,
|
|
319
326
|
dstAddrMode: 3, // ADDRESS MODE ieee
|
|
320
|
-
txOptions
|
|
327
|
+
txOptions,
|
|
321
328
|
useAlias: 0,
|
|
322
329
|
aliasAddr: 0,
|
|
323
330
|
aliasSequence: 0,
|
|
@@ -208,7 +208,20 @@ export class ZBOSSUart extends EventEmitter {
|
|
|
208
208
|
}
|
|
209
209
|
|
|
210
210
|
private async onPackage(data: Buffer): Promise<void> {
|
|
211
|
-
|
|
211
|
+
// Do not drop frames while `inReset` is set.
|
|
212
|
+
//
|
|
213
|
+
// `inReset` is set by `reset()` and only cleared by `onPortClose`
|
|
214
|
+
// (after a 3s wait + reopen). On some NCP transports the underlying
|
|
215
|
+
// port does not reliably close around `esp_restart()` (e.g. ESP32-C6
|
|
216
|
+
// USB-Serial-JTAG re-attaches the same CDC descriptor essentially
|
|
217
|
+
// instantly), so `onPortClose` never fires, `inReset` never clears,
|
|
218
|
+
// and the device's tsn-matching NCP_RESET response plus the
|
|
219
|
+
// post-reboot boot-ready frame both get silently dropped here.
|
|
220
|
+
// `Driver.execCommand(NCP_RESET, ...)` already uses an undefined-tsn
|
|
221
|
+
// waitress matcher, so either frame would resolve the pending
|
|
222
|
+
// promise if it reached the `"frame"` emitter. The CRC8/CRC16 checks below
|
|
223
|
+
// reject any garbage (ROM banner ASCII, partial frames, electrical
|
|
224
|
+
// noise) that legitimately arrives during the reset window.
|
|
212
225
|
const len = data.readUInt16LE(0);
|
|
213
226
|
const pType = data.readUInt8(2);
|
|
214
227
|
const pFlags = data.readUInt8(3);
|
|
@@ -8,7 +8,7 @@ import type {BroadcastAddress} from "../../../zspec/enums";
|
|
|
8
8
|
import * as Zcl from "../../../zspec/zcl";
|
|
9
9
|
import * as Zdo from "../../../zspec/zdo";
|
|
10
10
|
import type * as ZdoTypes from "../../../zspec/zdo/definition/tstypes";
|
|
11
|
-
import Adapter from "../../adapter";
|
|
11
|
+
import Adapter, {type ClusterWaitressMatcher, type ZclWaitressPayload} from "../../adapter";
|
|
12
12
|
import type * as Events from "../../events";
|
|
13
13
|
import type * as TsType from "../../tstype";
|
|
14
14
|
import type {RawAPSDataRequestPayload} from "../driver/commandType";
|
|
@@ -19,20 +19,11 @@ import {patchZdoBuffaloBE} from "./patchZdoBuffaloBE";
|
|
|
19
19
|
|
|
20
20
|
const NS = "zh:zigate";
|
|
21
21
|
const default_bind_group = 901; // https://github.com/Koenkk/zigbee-herdsman-converters/blob/master/lib/constants.js#L3
|
|
22
|
-
interface WaitressMatcher {
|
|
23
|
-
address?: number | string;
|
|
24
|
-
endpoint: number;
|
|
25
|
-
transactionSequenceNumber?: number;
|
|
26
|
-
frameType: Zcl.FrameType;
|
|
27
|
-
clusterID: number;
|
|
28
|
-
commandIdentifier: number;
|
|
29
|
-
direction: number;
|
|
30
|
-
}
|
|
31
22
|
|
|
32
23
|
export class ZiGateAdapter extends Adapter {
|
|
33
24
|
private driver: Driver;
|
|
34
25
|
private joinPermitted: boolean;
|
|
35
|
-
private waitress: Waitress<
|
|
26
|
+
private waitress: Waitress<ZclWaitressPayload, ClusterWaitressMatcher>;
|
|
36
27
|
private closing: boolean;
|
|
37
28
|
private queue: Queue;
|
|
38
29
|
|
|
@@ -54,7 +45,7 @@ export class ZiGateAdapter extends Adapter {
|
|
|
54
45
|
this.queue = new Queue(concurrent);
|
|
55
46
|
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
|
|
56
47
|
this.driver = new Driver(serialPortOptions.path!, serialPortOptions);
|
|
57
|
-
this.waitress = new Waitress
|
|
48
|
+
this.waitress = new Waitress(Adapter.zclWaitressValidator, Adapter.clusterWaitressTimeoutFormatter);
|
|
58
49
|
|
|
59
50
|
this.driver.on("received", this.dataListener.bind(this));
|
|
60
51
|
this.driver.on("LeaveIndication", this.leaveIndicationListener.bind(this));
|
|
@@ -357,6 +348,7 @@ export class ZiGateAdapter extends Adapter {
|
|
|
357
348
|
zclFrame.header.transactionSequenceNumber,
|
|
358
349
|
zclFrame.cluster.ID,
|
|
359
350
|
command.response,
|
|
351
|
+
undefined,
|
|
360
352
|
timeout,
|
|
361
353
|
);
|
|
362
354
|
} else if (!zclFrame.header.frameControl.disableDefaultResponse) {
|
|
@@ -368,6 +360,7 @@ export class ZiGateAdapter extends Adapter {
|
|
|
368
360
|
zclFrame.header.transactionSequenceNumber,
|
|
369
361
|
zclFrame.cluster.ID,
|
|
370
362
|
Zcl.Foundation.defaultRsp.ID,
|
|
363
|
+
undefined,
|
|
371
364
|
timeout,
|
|
372
365
|
);
|
|
373
366
|
}
|
|
@@ -518,24 +511,17 @@ export class ZiGateAdapter extends Adapter {
|
|
|
518
511
|
}
|
|
519
512
|
|
|
520
513
|
public waitFor(
|
|
521
|
-
networkAddress: number
|
|
514
|
+
networkAddress: number,
|
|
522
515
|
endpoint: number,
|
|
523
|
-
|
|
524
|
-
|
|
516
|
+
_frameType: Zcl.FrameType,
|
|
517
|
+
_direction: Zcl.Direction,
|
|
525
518
|
transactionSequenceNumber: number | undefined,
|
|
526
|
-
|
|
527
|
-
|
|
519
|
+
clusterId: number,
|
|
520
|
+
commandId: number,
|
|
521
|
+
defaultRspCommandId: number | undefined,
|
|
528
522
|
timeout: number,
|
|
529
523
|
): {promise: Promise<Events.ZclPayload>; cancel: () => void} {
|
|
530
|
-
const payload = {
|
|
531
|
-
address: networkAddress,
|
|
532
|
-
endpoint,
|
|
533
|
-
clusterID,
|
|
534
|
-
commandIdentifier,
|
|
535
|
-
frameType,
|
|
536
|
-
direction,
|
|
537
|
-
transactionSequenceNumber,
|
|
538
|
-
};
|
|
524
|
+
const payload = {address: networkAddress, endpoint, clusterId, commandId, defaultRspCommandId, transactionSequenceNumber};
|
|
539
525
|
const waiter = this.waitress.waitFor(payload, timeout);
|
|
540
526
|
const cancel = (): void => this.waitress.remove(waiter.ID);
|
|
541
527
|
return {promise: waiter.start().promise, cancel};
|
|
@@ -591,7 +577,11 @@ export class ZiGateAdapter extends Adapter {
|
|
|
591
577
|
wasBroadcast: false, // TODO
|
|
592
578
|
destinationEndpoint: <number>ziGateObject.payload.destinationEndpoint,
|
|
593
579
|
};
|
|
594
|
-
|
|
580
|
+
|
|
581
|
+
if (payload.header !== undefined) {
|
|
582
|
+
this.waitress.resolve(payload as ZclWaitressPayload);
|
|
583
|
+
}
|
|
584
|
+
|
|
595
585
|
this.emit("zclPayload", payload);
|
|
596
586
|
}
|
|
597
587
|
|
|
@@ -604,27 +594,6 @@ export class ZiGateAdapter extends Adapter {
|
|
|
604
594
|
this.emit("deviceLeave", payload);
|
|
605
595
|
}
|
|
606
596
|
|
|
607
|
-
private waitressTimeoutFormatter(matcher: WaitressMatcher, timeout: number): string {
|
|
608
|
-
return (
|
|
609
|
-
`Timeout - ${matcher.address} - ${matcher.endpoint}` +
|
|
610
|
-
` - ${matcher.transactionSequenceNumber} - ${matcher.clusterID}` +
|
|
611
|
-
` - ${matcher.commandIdentifier} after ${timeout}ms`
|
|
612
|
-
);
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
private waitressValidator(payload: Events.ZclPayload, matcher: WaitressMatcher): boolean {
|
|
616
|
-
return Boolean(
|
|
617
|
-
payload.header &&
|
|
618
|
-
(!matcher.address || payload.address === matcher.address) &&
|
|
619
|
-
matcher.endpoint === payload.endpoint &&
|
|
620
|
-
(matcher.transactionSequenceNumber === undefined || payload.header.transactionSequenceNumber === matcher.transactionSequenceNumber) &&
|
|
621
|
-
matcher.clusterID === payload.clusterID &&
|
|
622
|
-
matcher.frameType === payload.header.frameControl.frameType &&
|
|
623
|
-
matcher.commandIdentifier === payload.header.commandIdentifier &&
|
|
624
|
-
matcher.direction === payload.header.frameControl.direction,
|
|
625
|
-
);
|
|
626
|
-
}
|
|
627
|
-
|
|
628
597
|
private onZiGateClose(): void {
|
|
629
598
|
if (!this.closing) {
|
|
630
599
|
this.emit("disconnected");
|