@willieee802/zigbee-herdsman 0.49.4 → 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 -3
- package/dist/controller/model/device.d.ts.map +1 -1
- package/dist/controller/model/device.js +155 -68
- 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.js +4 -4
- 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 +192 -79
- package/src/controller/model/endpoint.ts +36 -24
- package/src/controller/model/group.ts +4 -4
- 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
|
@@ -2,7 +2,7 @@ import { Events as AdapterEvents } from '../../adapter';
|
|
|
2
2
|
import type { Eui64 } from "../../zspec/tstypes";
|
|
3
3
|
import * as Zcl from "../../zspec/zcl";
|
|
4
4
|
import type { TClusterCommandPayload, TPartialClusterAttributes } from "../../zspec/zcl/definition/clusters-types";
|
|
5
|
-
import type {
|
|
5
|
+
import type { Cluster, CustomClusters } from "../../zspec/zcl/definition/tstype";
|
|
6
6
|
import type { BindingTableEntry, LQITableEntry, RoutingTableEntry } from "../../zspec/zdo/definition/tstypes";
|
|
7
7
|
import type { ControllerEventMap } from "../controller";
|
|
8
8
|
import type { DeviceType, KeyValue, OtaDataSettings, OtaExtraMetas, OtaSource, OtaUpdateAvailableResult, ZigbeeOtaImageMeta } from "../tstype";
|
|
@@ -68,6 +68,7 @@ export declare class Device extends Entity<ControllerEventMap> {
|
|
|
68
68
|
get skipDefaultResponse(): boolean;
|
|
69
69
|
set skipDefaultResponse(skipDefaultResponse: boolean);
|
|
70
70
|
get customReadResponse(): CustomReadResponse | undefined;
|
|
71
|
+
/** If the set function returns true, the default read response behavior is skipped */
|
|
71
72
|
set customReadResponse(customReadResponse: CustomReadResponse | undefined);
|
|
72
73
|
get checkinInterval(): number | undefined;
|
|
73
74
|
set checkinInterval(checkinInterval: number | undefined);
|
|
@@ -83,6 +84,12 @@ export declare class Device extends Entity<ControllerEventMap> {
|
|
|
83
84
|
private static readonly deletedDevices;
|
|
84
85
|
private static readonly nwkToIeeeCache;
|
|
85
86
|
private constructor();
|
|
87
|
+
/**
|
|
88
|
+
* Reset transient data about the device.
|
|
89
|
+
* @param cache If true, reset some previously cached data.
|
|
90
|
+
* Should be set to true when device potentially changed its internal data to prevent mismatching state/config.
|
|
91
|
+
*/
|
|
92
|
+
resetTransient(cache: boolean): void;
|
|
86
93
|
createEndpoint(id: number): Endpoint;
|
|
87
94
|
changeIeeeAddress(ieeeAddr: string): void;
|
|
88
95
|
getEndpoint(id: number): Endpoint | undefined;
|
|
@@ -92,7 +99,7 @@ export declare class Device extends Entity<ControllerEventMap> {
|
|
|
92
99
|
updateLastSeen(): void;
|
|
93
100
|
private resetPendingRequestTimeout;
|
|
94
101
|
private hasPendingRequests;
|
|
95
|
-
onZclData(dataPayload: AdapterEvents.ZclPayload, frame: Zcl.Frame, endpoint: Endpoint): Promise<void>;
|
|
102
|
+
onZclData(dataPayload: AdapterEvents.ZclPayload, frame: Zcl.Frame, endpoint: Endpoint, defaultResponse: Zcl.Status | undefined): Promise<void>;
|
|
96
103
|
/**
|
|
97
104
|
* Reset runtime lookups.
|
|
98
105
|
*/
|
|
@@ -135,13 +142,17 @@ export declare class Device extends Entity<ControllerEventMap> {
|
|
|
135
142
|
*/
|
|
136
143
|
clearAllBindings(eui64List: Eui64[]): Promise<void>;
|
|
137
144
|
ping(disableRecovery?: boolean): Promise<void>;
|
|
138
|
-
addCustomCluster(name: string, cluster:
|
|
145
|
+
addCustomCluster(name: string, cluster: Cluster): void;
|
|
139
146
|
findMatchingOtaImage(source: OtaSource, current: TClusterCommandPayload<"genOta", "queryNextImageRequest">, extraMetas: OtaExtraMetas): Promise<ZigbeeOtaImageMeta | undefined>;
|
|
140
147
|
/**
|
|
141
148
|
* If `current` is undefined, will automatically notify and reply to query with `NO_IMAGE_AVAILABLE` (stops device from doing further requests).
|
|
142
149
|
*/
|
|
143
150
|
checkOta(source: OtaSource, current: TClusterCommandPayload<"genOta", "queryNextImageRequest"> | undefined, extraMetas: OtaExtraMetas, endpoint?: Endpoint | undefined): Promise<OtaUpdateAvailableResult>;
|
|
144
151
|
updateOta(source: Readonly<OtaSource> | undefined, requestPayload: TClusterCommandPayload<"genOta", "queryNextImageRequest"> | undefined, requestTsn: number | undefined, extraMetas: Readonly<OtaExtraMetas>, onProgress: (progress: number, remaining: number) => void, dataSettings: OtaDataSettings, endpoint?: Endpoint | undefined): Promise<[from: OtaUpdateAvailableResult["current"], to: OtaUpdateAvailableResult["current"] | undefined]>;
|
|
152
|
+
/**
|
|
153
|
+
* Abort running OTA if any. Send `ABORT` with next block response to device.
|
|
154
|
+
*/
|
|
155
|
+
abortOta(): void;
|
|
145
156
|
scheduleOta(source: OtaSource): void;
|
|
146
157
|
unscheduleOta(): void;
|
|
147
158
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device.d.ts","sourceRoot":"","sources":["../../../src/controller/model/device.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,MAAM,IAAI,aAAa,EAAC,MAAM,eAAe,CAAC;AAMtD,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,qBAAqB,CAAC;AAC/C,OAAO,KAAK,GAAG,MAAM,iBAAiB,CAAC;AACvC,OAAO,KAAK,EAAC,sBAAsB,
|
|
1
|
+
{"version":3,"file":"device.d.ts","sourceRoot":"","sources":["../../../src/controller/model/device.ts"],"names":[],"mappings":"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"}
|
|
@@ -61,6 +61,10 @@ const INTERVIEW_GENBASIC_ATTRIBUTES = [
|
|
|
61
61
|
"dateCode",
|
|
62
62
|
"swBuildId",
|
|
63
63
|
];
|
|
64
|
+
const GEN_BASIC_CLUSTER_ID = Zcl.Clusters.genBasic.ID;
|
|
65
|
+
const GEN_TIME_CLUSTER_ID = Zcl.Clusters.genTime.ID;
|
|
66
|
+
const GEN_POLL_CTRL_CLUSTER_ID = Zcl.Clusters.genPollCtrl.ID;
|
|
67
|
+
const GEN_OTA_CLUSTER_ID = Zcl.Clusters.genOta.ID;
|
|
64
68
|
var InterviewState;
|
|
65
69
|
(function (InterviewState) {
|
|
66
70
|
InterviewState["Pending"] = "PENDING";
|
|
@@ -90,6 +94,7 @@ class Device extends entity_1.default {
|
|
|
90
94
|
_gpSecurityKey;
|
|
91
95
|
#scheduledOta;
|
|
92
96
|
#otaInProgress = false;
|
|
97
|
+
#otaAbortController;
|
|
93
98
|
// Getters/setters
|
|
94
99
|
get ieeeAddr() {
|
|
95
100
|
return this._ieeeAddr;
|
|
@@ -209,6 +214,7 @@ class Device extends entity_1.default {
|
|
|
209
214
|
get customReadResponse() {
|
|
210
215
|
return this._customReadResponse;
|
|
211
216
|
}
|
|
217
|
+
/** If the set function returns true, the default read response behavior is skipped */
|
|
212
218
|
set customReadResponse(customReadResponse) {
|
|
213
219
|
this._customReadResponse = customReadResponse;
|
|
214
220
|
}
|
|
@@ -273,6 +279,19 @@ class Device extends entity_1.default {
|
|
|
273
279
|
this._gpSecurityKey = gpSecurityKey;
|
|
274
280
|
this.#scheduledOta = scheduledOta;
|
|
275
281
|
}
|
|
282
|
+
/**
|
|
283
|
+
* Reset transient data about the device.
|
|
284
|
+
* @param cache If true, reset some previously cached data.
|
|
285
|
+
* Should be set to true when device potentially changed its internal data to prevent mismatching state/config.
|
|
286
|
+
*/
|
|
287
|
+
resetTransient(cache) {
|
|
288
|
+
this._lastDefaultResponseSequenceNumber = undefined;
|
|
289
|
+
if (cache) {
|
|
290
|
+
// force retrieving this data again
|
|
291
|
+
this._checkinInterval = undefined;
|
|
292
|
+
this._pendingRequestTimeout = 0;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
276
295
|
createEndpoint(id) {
|
|
277
296
|
if (this.getEndpoint(id)) {
|
|
278
297
|
throw new Error(`Device '${this.ieeeAddr}' already has an endpoint '${id}'`);
|
|
@@ -318,62 +337,115 @@ class Device extends entity_1.default {
|
|
|
318
337
|
hasPendingRequests() {
|
|
319
338
|
return this.endpoints.find((e) => e.hasPendingRequests()) !== undefined;
|
|
320
339
|
}
|
|
321
|
-
async onZclData(dataPayload, frame, endpoint) {
|
|
340
|
+
async onZclData(dataPayload, frame, endpoint, defaultResponse) {
|
|
322
341
|
if (!Device.devices.get(this.databaseID)?.has(this.ieeeAddr)) {
|
|
323
342
|
// prevent race conditions where device gets deleted during processing
|
|
324
343
|
return;
|
|
325
344
|
}
|
|
326
|
-
if (
|
|
327
|
-
//
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
345
|
+
if (this.type === "GreenPower") {
|
|
346
|
+
// nothing below applies
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
const { header, command, cluster } = frame;
|
|
350
|
+
let sendDefaultResponse = !dataPayload.wasBroadcast && command.response === undefined;
|
|
351
|
+
let defaultResponseStatus = defaultResponse ?? Zcl.Status.SUCCESS;
|
|
352
|
+
if (header.isGlobal) {
|
|
353
|
+
// Response to read requests from device to coordinator
|
|
354
|
+
switch (command.name) {
|
|
355
|
+
case "read": {
|
|
356
|
+
// NOTE: `sendDefaultResponse` always false from `command.response === 0x01`
|
|
357
|
+
if (this._customReadResponse?.(frame, endpoint)) {
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
339
360
|
const response = {};
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
361
|
+
switch (dataPayload.clusterID) {
|
|
362
|
+
case GEN_TIME_CLUSTER_ID: {
|
|
363
|
+
// relax type to index by attr name, undefined results in non-success attr record
|
|
364
|
+
const timeAttrs = timeService.getTimeClusterAttributes();
|
|
365
|
+
for (const entry of frame.payload) {
|
|
366
|
+
// TODO: this.manufacturerID or frame.header.manufacturerCode
|
|
367
|
+
const name = Zcl.Utils.getClusterAttribute(cluster, entry.attrId, this.manufacturerID)?.name;
|
|
368
|
+
if (name === undefined) {
|
|
369
|
+
// UNSUPPORTED_ATTRIBUTE
|
|
370
|
+
response[entry.attrId] = { value: undefined, type: Zcl.DataType.NO_DATA };
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
response[name] = timeAttrs[name];
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
break;
|
|
377
|
+
}
|
|
378
|
+
// NOTE: can add more clusters here to use defaults from spec as needed
|
|
379
|
+
case GEN_BASIC_CLUSTER_ID: {
|
|
380
|
+
for (const entry of frame.payload) {
|
|
381
|
+
// TODO: this.manufacturerID or frame.header.manufacturerCode
|
|
382
|
+
const attr = Zcl.Utils.getClusterAttribute(cluster, entry.attrId, this.manufacturerID);
|
|
383
|
+
if (attr?.default === undefined) {
|
|
384
|
+
// UNSUPPORTED_ATTRIBUTE
|
|
385
|
+
response[entry.attrId] = { value: undefined, type: Zcl.DataType.NO_DATA };
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
response[attr.name] = attr.default;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
break;
|
|
392
|
+
}
|
|
393
|
+
default: {
|
|
394
|
+
for (const entry of frame.payload) {
|
|
395
|
+
// UNSUPPORTED_ATTRIBUTE
|
|
396
|
+
response[entry.attrId] = { value: undefined, type: Zcl.DataType.NO_DATA };
|
|
397
|
+
}
|
|
398
|
+
break;
|
|
344
399
|
}
|
|
345
400
|
}
|
|
346
401
|
try {
|
|
347
|
-
await endpoint.readResponse(
|
|
402
|
+
await endpoint.readResponse(cluster.ID, header.transactionSequenceNumber, response, {
|
|
348
403
|
srcEndpoint: dataPayload.destinationEndpoint,
|
|
349
404
|
});
|
|
350
405
|
}
|
|
351
406
|
catch (error) {
|
|
352
407
|
logger_1.logger.error(`Read response to ${this.ieeeAddr} failed (${error.message})`, NS);
|
|
408
|
+
// XXX: technically, if `readResponse` fails before reaching the network (internal to ZH), we should send a default response
|
|
409
|
+
// currently not possible due to implementation (no distinction as to "where" it failed)
|
|
353
410
|
}
|
|
411
|
+
break;
|
|
412
|
+
}
|
|
413
|
+
case "defaultRsp": {
|
|
414
|
+
sendDefaultResponse = false; // per spec
|
|
415
|
+
break;
|
|
354
416
|
}
|
|
355
417
|
}
|
|
356
418
|
}
|
|
357
|
-
else if (
|
|
358
|
-
switch (
|
|
419
|
+
else if (header.isSpecific) {
|
|
420
|
+
switch (cluster.name) {
|
|
359
421
|
case "ssIasZone": {
|
|
360
|
-
if (
|
|
422
|
+
if (command.name === "enrollReq") {
|
|
361
423
|
// Respond to enroll requests
|
|
362
424
|
logger_1.logger.debug(`IAS - '${this.ieeeAddr}' responding to enroll response`, NS);
|
|
363
|
-
|
|
425
|
+
try {
|
|
426
|
+
await endpoint.command("ssIasZone", "enrollRsp", { enrollrspcode: 0, zoneid: 23 }, { transactionSequenceNumber: header.transactionSequenceNumber, disableDefaultResponse: true });
|
|
427
|
+
sendDefaultResponse = false; // per spec, sending a specific response TODO: no "Effect on receipt" in spec, is this correct?
|
|
428
|
+
}
|
|
429
|
+
catch (error) {
|
|
430
|
+
logger_1.logger.error(`Handling of IAS zone enroll for ${this.ieeeAddr} failed (${error.message})`, NS);
|
|
431
|
+
defaultResponseStatus = Zcl.Status.FAILURE;
|
|
432
|
+
}
|
|
364
433
|
}
|
|
365
434
|
break;
|
|
366
435
|
}
|
|
367
436
|
case "genPollCtrl": {
|
|
368
|
-
if (
|
|
437
|
+
if (command.name === "checkin") {
|
|
438
|
+
let startedFastPolling = false;
|
|
369
439
|
// Handle check-in from sleeping end devices
|
|
370
440
|
try {
|
|
371
441
|
if (this.hasPendingRequests() || this._checkinInterval === undefined) {
|
|
372
442
|
logger_1.logger.debug(`check-in from ${this.ieeeAddr}: accepting fast-poll`, NS);
|
|
373
|
-
await endpoint.command(
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
443
|
+
await endpoint.command(cluster.name, "checkinRsp", { startFastPolling: 1, fastPollTimeout: 0 }, {
|
|
444
|
+
transactionSequenceNumber: header.transactionSequenceNumber,
|
|
445
|
+
disableDefaultResponse: true,
|
|
446
|
+
sendPolicy: "immediate",
|
|
447
|
+
});
|
|
448
|
+
startedFastPolling = true;
|
|
377
449
|
// This is a good time to read the checkin interval if we haven't stored it previously
|
|
378
450
|
if (this._checkinInterval === undefined) {
|
|
379
451
|
const pollPeriod = await endpoint.read("genPollCtrl", ["checkinInterval"], { sendPolicy: "immediate" });
|
|
@@ -382,21 +454,32 @@ class Device extends entity_1.default {
|
|
|
382
454
|
logger_1.logger.debug(`Request Queue (${this.ieeeAddr}): default expiration timeout set to ${this.pendingRequestTimeout}`, NS);
|
|
383
455
|
}
|
|
384
456
|
await Promise.all(this.endpoints.map(async (e) => await e.sendPendingRequests(true)));
|
|
385
|
-
// We *must* end fast-poll when we're done sending things. Otherwise
|
|
386
|
-
// we cause undue power-drain.
|
|
387
|
-
logger_1.logger.debug(`check-in from ${this.ieeeAddr}: stopping fast-poll`, NS);
|
|
388
|
-
await endpoint.command(frame.cluster.name, "fastPollStop", {}, { sendPolicy: "immediate" });
|
|
389
457
|
}
|
|
390
458
|
else {
|
|
391
459
|
logger_1.logger.debug(`check-in from ${this.ieeeAddr}: declining fast-poll`, NS);
|
|
392
|
-
await endpoint.command(
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
460
|
+
await endpoint.command(cluster.name, "checkinRsp", { startFastPolling: 0, fastPollTimeout: 0 }, {
|
|
461
|
+
transactionSequenceNumber: header.transactionSequenceNumber,
|
|
462
|
+
disableDefaultResponse: true,
|
|
463
|
+
sendPolicy: "immediate",
|
|
464
|
+
});
|
|
396
465
|
}
|
|
466
|
+
sendDefaultResponse = false; // per spec, sending a specific response
|
|
397
467
|
}
|
|
398
468
|
catch (error) {
|
|
399
469
|
logger_1.logger.error(`Handling of poll check-in from ${this.ieeeAddr} failed (${error.message})`, NS);
|
|
470
|
+
defaultResponseStatus = Zcl.Status.FAILURE;
|
|
471
|
+
}
|
|
472
|
+
finally {
|
|
473
|
+
if (startedFastPolling) {
|
|
474
|
+
// We *must* end fast-poll when we're done sending things. Otherwise we cause undue power-drain.
|
|
475
|
+
logger_1.logger.debug(`check-in from ${this.ieeeAddr}: stopping fast-poll`, NS);
|
|
476
|
+
try {
|
|
477
|
+
await endpoint.command(cluster.name, "fastPollStop", {}, { sendPolicy: "immediate" });
|
|
478
|
+
}
|
|
479
|
+
catch (error) {
|
|
480
|
+
logger_1.logger.error(`Failed to stop fast poll for ${this.ieeeAddr} (${error.message})`, NS);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
400
483
|
}
|
|
401
484
|
}
|
|
402
485
|
break;
|
|
@@ -404,34 +487,23 @@ class Device extends entity_1.default {
|
|
|
404
487
|
}
|
|
405
488
|
}
|
|
406
489
|
// Send a default response if necessary.
|
|
407
|
-
const isDefaultResponse = frame.header.isGlobal && frame.command.name === "defaultRsp";
|
|
408
|
-
const commandHasResponse = frame.command.response !== undefined;
|
|
409
|
-
const disableDefaultResponse = frame.header.frameControl.disableDefaultResponse;
|
|
410
490
|
/* v8 ignore next */
|
|
411
491
|
const disableTuyaDefaultResponse = this.manufacturerName?.startsWith("_TZ") && process.env.DISABLE_TUYA_DEFAULT_RESPONSE;
|
|
412
492
|
// Sometimes messages are received twice, prevent responding twice
|
|
413
|
-
const alreadyResponded = this._lastDefaultResponseSequenceNumber ===
|
|
414
|
-
if (this.
|
|
415
|
-
|
|
416
|
-
!disableDefaultResponse &&
|
|
417
|
-
!isDefaultResponse &&
|
|
418
|
-
!commandHasResponse &&
|
|
419
|
-
!this._skipDefaultResponse &&
|
|
493
|
+
const alreadyResponded = this._lastDefaultResponseSequenceNumber === header.transactionSequenceNumber;
|
|
494
|
+
if (!this._skipDefaultResponse &&
|
|
495
|
+
sendDefaultResponse &&
|
|
496
|
+
(!header.frameControl.disableDefaultResponse || defaultResponseStatus !== Zcl.Status.SUCCESS) &&
|
|
420
497
|
!alreadyResponded &&
|
|
421
498
|
!disableTuyaDefaultResponse) {
|
|
422
499
|
try {
|
|
423
|
-
this._lastDefaultResponseSequenceNumber =
|
|
424
|
-
|
|
425
|
-
// In https://github.com/Koenkk/zigbee2mqtt/issues/18096 a commandResponse (SERVER_TO_CLIENT)
|
|
426
|
-
// is send and the device expects a CLIENT_TO_SERVER back.
|
|
427
|
-
// Previously SERVER_TO_CLIENT was always used.
|
|
428
|
-
// Therefore for non-global commands we inverse the direction.
|
|
429
|
-
const direction = frame.header.isGlobal
|
|
500
|
+
this._lastDefaultResponseSequenceNumber = header.transactionSequenceNumber;
|
|
501
|
+
const direction = header.frameControl.direction === Zcl.Direction.CLIENT_TO_SERVER
|
|
430
502
|
? Zcl.Direction.SERVER_TO_CLIENT
|
|
431
|
-
:
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
503
|
+
: Zcl.Direction.CLIENT_TO_SERVER;
|
|
504
|
+
await endpoint.defaultResponse(command.ID, defaultResponseStatus, cluster.ID, header.transactionSequenceNumber, {
|
|
505
|
+
direction,
|
|
506
|
+
});
|
|
435
507
|
}
|
|
436
508
|
catch (error) {
|
|
437
509
|
logger_1.logger.debug(`Default response to ${this.ieeeAddr} failed (${error})`, NS);
|
|
@@ -462,7 +534,7 @@ class Device extends entity_1.default {
|
|
|
462
534
|
}
|
|
463
535
|
// default: no timeout (messages expire immediately after first send attempt)
|
|
464
536
|
let pendingRequestTimeout = 0;
|
|
465
|
-
if (endpoints.filter((e) => e.inputClusters.includes(
|
|
537
|
+
if (endpoints.filter((e) => e.inputClusters.includes(GEN_POLL_CTRL_CLUSTER_ID)).length > 0) {
|
|
466
538
|
// default for devices that support genPollCtrl cluster (RX off when idle): 1 day
|
|
467
539
|
pendingRequestTimeout = 86400000;
|
|
468
540
|
}
|
|
@@ -1097,31 +1169,35 @@ class Device extends entity_1.default {
|
|
|
1097
1169
|
// Zigbee does not have an official pinging mechanism. Use a read request
|
|
1098
1170
|
// of a mandatory basic cluster attribute to keep it as lightweight as
|
|
1099
1171
|
// possible.
|
|
1100
|
-
const endpoint = this.endpoints.find((ep) => ep.inputClusters.includes(
|
|
1172
|
+
const endpoint = this.endpoints.find((ep) => ep.inputClusters.includes(GEN_BASIC_CLUSTER_ID)) ?? this.endpoints[0];
|
|
1101
1173
|
await endpoint.read("genBasic", ["zclVersion"], { disableRecovery, sendPolicy: "immediate" });
|
|
1102
1174
|
}
|
|
1103
1175
|
addCustomCluster(name, cluster) {
|
|
1104
|
-
(0, node_assert_1.default)(
|
|
1176
|
+
(0, node_assert_1.default)(cluster.ID !== Zcl.Clusters.touchlink.ID && cluster.ID !== Zcl.Clusters.greenPower.ID, "Overriding of greenPower or touchlink cluster is not supported");
|
|
1105
1177
|
if (Zcl.Utils.isClusterName(name)) {
|
|
1106
|
-
const existingCluster = this._customClusters[name] ?? Zcl.Clusters[name];
|
|
1107
1178
|
// Extend existing cluster
|
|
1179
|
+
const existingCluster = this._customClusters[name] ?? Zcl.Clusters[name];
|
|
1108
1180
|
(0, node_assert_1.default)(existingCluster.ID === cluster.ID, `Custom cluster ID (${cluster.ID}) should match existing cluster ID (${existingCluster.ID})`);
|
|
1109
|
-
|
|
1181
|
+
const extendedCluster = {
|
|
1182
|
+
name: cluster.name,
|
|
1110
1183
|
ID: cluster.ID,
|
|
1111
1184
|
manufacturerCode: cluster.manufacturerCode,
|
|
1112
1185
|
attributes: { ...existingCluster.attributes, ...cluster.attributes },
|
|
1113
1186
|
commands: { ...existingCluster.commands, ...cluster.commands },
|
|
1114
1187
|
commandsResponse: { ...existingCluster.commandsResponse, ...cluster.commandsResponse },
|
|
1115
1188
|
};
|
|
1189
|
+
this._customClusters[name] = extendedCluster;
|
|
1190
|
+
}
|
|
1191
|
+
else {
|
|
1192
|
+
this._customClusters[name] = cluster;
|
|
1116
1193
|
}
|
|
1117
|
-
this._customClusters[name] = cluster;
|
|
1118
1194
|
}
|
|
1119
|
-
#waitForOtaCommand(endpointId, commandId,
|
|
1195
|
+
#waitForOtaCommand(endpointId, commandId, defaultRspCommandId, timeout) {
|
|
1120
1196
|
const adapter = entity_1.default.getAdapterByID(this.databaseID);
|
|
1121
1197
|
if (!adapter) {
|
|
1122
1198
|
throw new Error(`No adapter found for database ID ${this.databaseID}`);
|
|
1123
1199
|
}
|
|
1124
|
-
const waiter = adapter.waitFor(this.networkAddress, endpointId, Zcl.FrameType.SPECIFIC, Zcl.Direction.CLIENT_TO_SERVER,
|
|
1200
|
+
const waiter = adapter.waitFor(this.networkAddress, endpointId, Zcl.FrameType.SPECIFIC, Zcl.Direction.CLIENT_TO_SERVER, undefined, GEN_OTA_CLUSTER_ID, commandId, defaultRspCommandId, timeout);
|
|
1125
1201
|
const promise = new Promise((resolve, reject) => {
|
|
1126
1202
|
waiter.promise.then((payload) => {
|
|
1127
1203
|
try {
|
|
@@ -1163,10 +1239,11 @@ class Device extends entity_1.default {
|
|
|
1163
1239
|
}
|
|
1164
1240
|
async #notifyOta(endpoint) {
|
|
1165
1241
|
// Some devices (e.g. Insta) take a very long trying to discover the correct coordinator EP for OTA
|
|
1166
|
-
const queryNextImageRequest = this.#waitForOtaCommand(endpoint.ID, Zcl.Clusters.genOta.commands.queryNextImageRequest.ID,
|
|
1242
|
+
const queryNextImageRequest = this.#waitForOtaCommand(endpoint.ID, Zcl.Clusters.genOta.commands.queryNextImageRequest.ID, Zcl.Clusters.genOta.commandsResponse.imageNotify.ID, 60000);
|
|
1167
1243
|
try {
|
|
1168
1244
|
await endpoint.commandResponse("genOta", "imageNotify", { payloadType: 0, queryJitter: 100 }, { sendPolicy: "immediate" });
|
|
1169
1245
|
const response = await queryNextImageRequest.promise;
|
|
1246
|
+
(0, node_assert_1.default)(response.header.isSpecific);
|
|
1170
1247
|
return [response.payload, response.header.transactionSequenceNumber];
|
|
1171
1248
|
}
|
|
1172
1249
|
catch {
|
|
@@ -1304,10 +1381,14 @@ class Device extends entity_1.default {
|
|
|
1304
1381
|
const session = new ota_1.OtaSession(this.ieeeAddr, endpoint, image, onProgress, dataSettings, this.#waitForOtaCommand.bind(this));
|
|
1305
1382
|
let endResult;
|
|
1306
1383
|
try {
|
|
1307
|
-
|
|
1384
|
+
this.#otaAbortController = new AbortController();
|
|
1385
|
+
const runEnd = await session.run(this.#otaAbortController.signal);
|
|
1386
|
+
(0, node_assert_1.default)(runEnd.header.isSpecific);
|
|
1387
|
+
endResult = runEnd;
|
|
1308
1388
|
}
|
|
1309
1389
|
finally {
|
|
1310
1390
|
this.#otaInProgress = false;
|
|
1391
|
+
this.#otaAbortController = undefined;
|
|
1311
1392
|
}
|
|
1312
1393
|
logger_1.logger.debug(() => `Received upgrade end request for ${this.ieeeAddr}: ${JSON.stringify(endResult.payload)}`, NS);
|
|
1313
1394
|
if (endResult.payload.status === Zcl.Status.SUCCESS) {
|
|
@@ -1362,7 +1443,7 @@ class Device extends entity_1.default {
|
|
|
1362
1443
|
* response command with status of success and it SHALL wait for the client to reinitiate the upgrade process.
|
|
1363
1444
|
*/
|
|
1364
1445
|
try {
|
|
1365
|
-
await endpoint.defaultResponse(Zcl.Clusters.genOta.commands.upgradeEndRequest.ID, Zcl.Status.SUCCESS,
|
|
1446
|
+
await endpoint.defaultResponse(Zcl.Clusters.genOta.commands.upgradeEndRequest.ID, Zcl.Status.SUCCESS, GEN_OTA_CLUSTER_ID, endResult.header.transactionSequenceNumber);
|
|
1366
1447
|
}
|
|
1367
1448
|
catch (error) {
|
|
1368
1449
|
logger_1.logger.debug(() => `OTA upgrade end request default response for ${this.ieeeAddr} failed: ${error.message}`, NS);
|
|
@@ -1371,6 +1452,12 @@ class Device extends entity_1.default {
|
|
|
1371
1452
|
throw new Error(`OTA update of ${this.ieeeAddr} failed with reason: ${Zcl.Status[endResult.payload.status]}`);
|
|
1372
1453
|
}
|
|
1373
1454
|
}
|
|
1455
|
+
/**
|
|
1456
|
+
* Abort running OTA if any. Send `ABORT` with next block response to device.
|
|
1457
|
+
*/
|
|
1458
|
+
abortOta() {
|
|
1459
|
+
this.#otaAbortController?.abort();
|
|
1460
|
+
}
|
|
1374
1461
|
scheduleOta(source) {
|
|
1375
1462
|
(0, node_assert_1.default)(this.endpoints.some((e) => e.supportsOutputCluster("genOta")), `No endpoint found with OTA cluster support for ${this.ieeeAddr}`);
|
|
1376
1463
|
if (this.#scheduledOta) {
|