@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
package/src/zspec/zcl/utils.ts
CHANGED
|
@@ -1,72 +1,10 @@
|
|
|
1
1
|
import {Clusters} from "./definition/cluster";
|
|
2
2
|
import {ZCL_TYPE_INVALID_BY_TYPE} from "./definition/datatypes";
|
|
3
|
-
import {DataType
|
|
3
|
+
import {DataType} from "./definition/enums";
|
|
4
4
|
import {Foundation, type FoundationCommandName, type FoundationDefinition} from "./definition/foundation";
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
DataType.DATA8,
|
|
9
|
-
DataType.DATA16,
|
|
10
|
-
DataType.DATA24,
|
|
11
|
-
DataType.DATA32,
|
|
12
|
-
DataType.DATA40,
|
|
13
|
-
DataType.DATA48,
|
|
14
|
-
DataType.DATA56,
|
|
15
|
-
DataType.DATA64,
|
|
16
|
-
DataType.BOOLEAN,
|
|
17
|
-
DataType.BITMAP8,
|
|
18
|
-
DataType.BITMAP16,
|
|
19
|
-
DataType.BITMAP24,
|
|
20
|
-
DataType.BITMAP32,
|
|
21
|
-
DataType.BITMAP40,
|
|
22
|
-
DataType.BITMAP48,
|
|
23
|
-
DataType.BITMAP56,
|
|
24
|
-
DataType.BITMAP64,
|
|
25
|
-
DataType.ENUM8,
|
|
26
|
-
DataType.ENUM16,
|
|
27
|
-
DataType.OCTET_STR,
|
|
28
|
-
DataType.CHAR_STR,
|
|
29
|
-
DataType.LONG_OCTET_STR,
|
|
30
|
-
DataType.LONG_CHAR_STR,
|
|
31
|
-
DataType.ARRAY,
|
|
32
|
-
DataType.STRUCT,
|
|
33
|
-
DataType.SET,
|
|
34
|
-
DataType.BAG,
|
|
35
|
-
DataType.CLUSTER_ID,
|
|
36
|
-
DataType.ATTR_ID,
|
|
37
|
-
DataType.BAC_OID,
|
|
38
|
-
DataType.IEEE_ADDR,
|
|
39
|
-
DataType.SEC_KEY,
|
|
40
|
-
];
|
|
41
|
-
const DATA_TYPE_CLASS_ANALOG = [
|
|
42
|
-
DataType.UINT8,
|
|
43
|
-
DataType.UINT16,
|
|
44
|
-
DataType.UINT24,
|
|
45
|
-
DataType.UINT32,
|
|
46
|
-
DataType.UINT40,
|
|
47
|
-
DataType.UINT48,
|
|
48
|
-
DataType.UINT56,
|
|
49
|
-
DataType.INT8,
|
|
50
|
-
DataType.INT16,
|
|
51
|
-
DataType.INT24,
|
|
52
|
-
DataType.INT32,
|
|
53
|
-
DataType.INT40,
|
|
54
|
-
DataType.INT48,
|
|
55
|
-
DataType.INT56,
|
|
56
|
-
DataType.SEMI_PREC,
|
|
57
|
-
DataType.SINGLE_PREC,
|
|
58
|
-
DataType.DOUBLE_PREC,
|
|
59
|
-
DataType.TOD,
|
|
60
|
-
DataType.DATE,
|
|
61
|
-
DataType.UTC,
|
|
62
|
-
];
|
|
63
|
-
|
|
64
|
-
const FOUNDATION_DISCOVER_RSP_IDS = [
|
|
65
|
-
Foundation.discoverRsp.ID,
|
|
66
|
-
Foundation.discoverCommandsRsp.ID,
|
|
67
|
-
Foundation.discoverCommandsGenRsp.ID,
|
|
68
|
-
Foundation.discoverExtRsp.ID,
|
|
69
|
-
];
|
|
5
|
+
import {Status} from "./definition/status";
|
|
6
|
+
import type {Attribute, Cluster, ClusterName, Command, CustomClusters, Parameter} from "./definition/tstype";
|
|
7
|
+
import {ZclStatusError} from "./zclStatusError";
|
|
70
8
|
|
|
71
9
|
/** Runtime fast lookup */
|
|
72
10
|
const ZCL_CLUSTERS_ID_TO_NAMES = (() => {
|
|
@@ -81,227 +19,166 @@ const ZCL_CLUSTERS_ID_TO_NAMES = (() => {
|
|
|
81
19
|
return map;
|
|
82
20
|
})();
|
|
83
21
|
|
|
84
|
-
export function
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
22
|
+
export function isAnalogDataType(dataType: DataType): boolean {
|
|
23
|
+
return (
|
|
24
|
+
dataType === DataType.UINT8 ||
|
|
25
|
+
dataType === DataType.UINT16 ||
|
|
26
|
+
dataType === DataType.UINT24 ||
|
|
27
|
+
dataType === DataType.UINT32 ||
|
|
28
|
+
dataType === DataType.UINT40 ||
|
|
29
|
+
dataType === DataType.UINT48 ||
|
|
30
|
+
dataType === DataType.UINT56 ||
|
|
31
|
+
dataType === DataType.INT8 ||
|
|
32
|
+
dataType === DataType.INT16 ||
|
|
33
|
+
dataType === DataType.INT24 ||
|
|
34
|
+
dataType === DataType.INT32 ||
|
|
35
|
+
dataType === DataType.INT40 ||
|
|
36
|
+
dataType === DataType.INT48 ||
|
|
37
|
+
dataType === DataType.INT56 ||
|
|
38
|
+
dataType === DataType.SEMI_PREC ||
|
|
39
|
+
dataType === DataType.SINGLE_PREC ||
|
|
40
|
+
dataType === DataType.DOUBLE_PREC ||
|
|
41
|
+
dataType === DataType.TOD ||
|
|
42
|
+
dataType === DataType.DATE ||
|
|
43
|
+
dataType === DataType.UTC
|
|
44
|
+
);
|
|
94
45
|
}
|
|
95
46
|
|
|
96
|
-
function
|
|
97
|
-
|
|
98
|
-
// below is twice faster than checking `Object.keys(customClusters).length`
|
|
99
|
-
for (const _k in customClusters) return true;
|
|
100
|
-
return false;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function findClusterNameByID(
|
|
104
|
-
id: number,
|
|
105
|
-
manufacturerCode: number | undefined,
|
|
106
|
-
clusters: typeof Clusters | CustomClusters,
|
|
107
|
-
zcl: boolean,
|
|
108
|
-
): [name: string | undefined, partialMatch: boolean] {
|
|
109
|
-
let name: string | undefined;
|
|
110
|
-
// if manufacturer code is given, consider partial match if didn't match against manufacturer code
|
|
111
|
-
let partialMatch = Boolean(manufacturerCode);
|
|
112
|
-
|
|
113
|
-
if (zcl) {
|
|
114
|
-
const zclName = ZCL_CLUSTERS_ID_TO_NAMES.get(id);
|
|
115
|
-
|
|
116
|
-
if (zclName) {
|
|
117
|
-
const cluster = clusters[zclName];
|
|
118
|
-
|
|
119
|
-
// priority on first match when matching only ID
|
|
120
|
-
if (name === undefined) {
|
|
121
|
-
name = zclName;
|
|
122
|
-
}
|
|
47
|
+
export function getCluster(key: string | number, manufacturerCode: number | undefined = undefined, customClusters: CustomClusters = {}): Cluster {
|
|
48
|
+
let cluster: Cluster | undefined;
|
|
123
49
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
name = zclName;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
} else {
|
|
132
|
-
for (const clusterName in clusters) {
|
|
133
|
-
const cluster = clusters[clusterName as ClusterName];
|
|
50
|
+
if (typeof key === "number") {
|
|
51
|
+
// custom clusters have priority over Zcl clusters, except in case of better match (see below)
|
|
52
|
+
for (const clusterName in customClusters) {
|
|
53
|
+
const foundCluster = customClusters[clusterName as ClusterName];
|
|
134
54
|
|
|
135
|
-
if (
|
|
55
|
+
if (foundCluster.ID === key) {
|
|
136
56
|
// priority on first match when matching only ID
|
|
137
|
-
if (
|
|
138
|
-
|
|
57
|
+
if (cluster === undefined) {
|
|
58
|
+
cluster = foundCluster;
|
|
139
59
|
}
|
|
140
60
|
|
|
141
|
-
if (manufacturerCode &&
|
|
142
|
-
|
|
143
|
-
partialMatch = false;
|
|
61
|
+
if (manufacturerCode && foundCluster.manufacturerCode === manufacturerCode) {
|
|
62
|
+
cluster = foundCluster;
|
|
144
63
|
break;
|
|
145
64
|
}
|
|
146
65
|
|
|
147
|
-
if (!
|
|
148
|
-
|
|
66
|
+
if (!foundCluster.manufacturerCode) {
|
|
67
|
+
cluster = foundCluster;
|
|
149
68
|
break;
|
|
150
69
|
}
|
|
151
70
|
}
|
|
152
71
|
}
|
|
153
|
-
}
|
|
154
72
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
function getClusterDefinition(
|
|
159
|
-
key: string | number,
|
|
160
|
-
manufacturerCode: number | undefined,
|
|
161
|
-
customClusters: CustomClusters,
|
|
162
|
-
): {name: string; cluster: ClusterDefinition} {
|
|
163
|
-
let name: string | undefined;
|
|
73
|
+
if (!cluster) {
|
|
74
|
+
const zclName = ZCL_CLUSTERS_ID_TO_NAMES.get(key);
|
|
164
75
|
|
|
165
|
-
|
|
166
|
-
|
|
76
|
+
if (zclName) {
|
|
77
|
+
const foundCluster = Clusters[zclName];
|
|
167
78
|
|
|
168
|
-
|
|
169
|
-
[name, partialMatch] = findClusterNameByID(key, manufacturerCode, customClusters, false);
|
|
79
|
+
// TODO: can remove all below once all manuf-specific moved to ZHC
|
|
170
80
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
[zclName, partialMatch] = findClusterNameByID(key, manufacturerCode, Clusters, true);
|
|
81
|
+
// priority on first match when matching only ID
|
|
82
|
+
if (cluster === undefined) {
|
|
83
|
+
cluster = foundCluster;
|
|
84
|
+
}
|
|
176
85
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
86
|
+
if (manufacturerCode && foundCluster.manufacturerCode === manufacturerCode) {
|
|
87
|
+
cluster = foundCluster;
|
|
88
|
+
} else if (foundCluster.manufacturerCode === undefined) {
|
|
89
|
+
cluster = foundCluster;
|
|
90
|
+
}
|
|
180
91
|
}
|
|
181
92
|
}
|
|
182
|
-
} else {
|
|
183
|
-
name = key;
|
|
184
|
-
}
|
|
185
93
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
: Clusters[name as ClusterName];
|
|
193
|
-
|
|
194
|
-
if (!cluster || cluster.ID === undefined) {
|
|
195
|
-
if (typeof key === "number") {
|
|
196
|
-
name = key.toString();
|
|
197
|
-
cluster = {attributes: {}, commands: {}, commandsResponse: {}, manufacturerCode: undefined, ID: key};
|
|
198
|
-
} else {
|
|
199
|
-
name = undefined;
|
|
94
|
+
// TODO: cluster.ID can't be undefined?
|
|
95
|
+
if (!cluster || cluster.ID === undefined) {
|
|
96
|
+
cluster = {name: `${key}`, ID: key, attributes: {}, commands: {}, commandsResponse: {}};
|
|
97
|
+
// XXX: align behavior with string key?
|
|
98
|
+
// throw new ZclStatusError(Status.UNSUPPORTED_CLUSTER, `${key}`);
|
|
200
99
|
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
if (!name) {
|
|
204
|
-
throw new Error(`Cluster with name '${key}' does not exist`);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
return {name, cluster};
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
function cloneClusterEntriesWithName<T extends Record<string, unknown>>(entries: Record<string, T>): Record<string, {name: string} & T> {
|
|
211
|
-
const clone: Record<string, {name: string} & T> = {};
|
|
100
|
+
} else {
|
|
101
|
+
cluster = key in customClusters ? customClusters[key] : Clusters[key as ClusterName];
|
|
212
102
|
|
|
213
|
-
|
|
214
|
-
|
|
103
|
+
// TODO: cluster.ID can't be undefined?
|
|
104
|
+
if (!cluster || cluster.ID === undefined) {
|
|
105
|
+
throw new ZclStatusError(Status.UNSUPPORTED_CLUSTER, key);
|
|
106
|
+
}
|
|
215
107
|
}
|
|
216
108
|
|
|
217
|
-
return
|
|
109
|
+
return cluster;
|
|
218
110
|
}
|
|
219
111
|
|
|
220
|
-
function
|
|
221
|
-
const attributes
|
|
222
|
-
const commands: Record<string, Command> = cloneClusterEntriesWithName(cluster.commands);
|
|
223
|
-
const commandsResponse: Record<string, Command> = cloneClusterEntriesWithName(cluster.commandsResponse);
|
|
112
|
+
export function getClusterAttribute(cluster: Cluster, key: number | string, manufacturerCode: number | undefined): Attribute | undefined {
|
|
113
|
+
const attributes = cluster.attributes;
|
|
224
114
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
let partialMatchAttr: Attribute | undefined;
|
|
115
|
+
if (typeof key === "number") {
|
|
116
|
+
let partialMatchAttr: Attribute | undefined;
|
|
228
117
|
|
|
229
|
-
|
|
230
|
-
|
|
118
|
+
for (const attrKey in attributes) {
|
|
119
|
+
const attr = attributes[attrKey];
|
|
231
120
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
121
|
+
if (attr.ID === key) {
|
|
122
|
+
if (manufacturerCode !== undefined && attr.manufacturerCode === manufacturerCode) {
|
|
123
|
+
return attr;
|
|
124
|
+
}
|
|
236
125
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
}
|
|
126
|
+
if (attr.manufacturerCode === undefined) {
|
|
127
|
+
partialMatchAttr = attr;
|
|
240
128
|
}
|
|
241
129
|
}
|
|
242
|
-
|
|
243
|
-
return partialMatchAttr;
|
|
244
130
|
}
|
|
245
131
|
|
|
246
|
-
return
|
|
247
|
-
}
|
|
132
|
+
return partialMatchAttr;
|
|
133
|
+
}
|
|
248
134
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
135
|
+
return attributes[key];
|
|
136
|
+
// XXX: align behavior with cmds?
|
|
137
|
+
// throw new ZclStatusError(Status.UNSUPPORTED_ATTRIBUTE, `${cluster.name}:${key}`);
|
|
138
|
+
}
|
|
253
139
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
const cmd = commands[
|
|
140
|
+
export function getClusterCommand(cluster: Cluster, key: number | string): Command {
|
|
141
|
+
const commands = cluster.commands;
|
|
142
|
+
|
|
143
|
+
if (typeof key === "number") {
|
|
144
|
+
for (const cmdKey in commands) {
|
|
145
|
+
const cmd = commands[cmdKey];
|
|
260
146
|
|
|
261
|
-
if (cmd) {
|
|
147
|
+
if (cmd.ID === key) {
|
|
262
148
|
return cmd;
|
|
263
149
|
}
|
|
264
150
|
}
|
|
151
|
+
} else {
|
|
152
|
+
const cmd = commands[key];
|
|
153
|
+
|
|
154
|
+
if (cmd) {
|
|
155
|
+
return cmd;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
265
158
|
|
|
266
|
-
|
|
267
|
-
|
|
159
|
+
throw new ZclStatusError(Status.UNSUP_COMMAND, `${cluster.name}:${key}`);
|
|
160
|
+
}
|
|
268
161
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
for (const cmdKey in commandsResponse) {
|
|
272
|
-
const cmd = commandsResponse[cmdKey];
|
|
162
|
+
export function getClusterCommandResponse(cluster: Cluster, key: number | string): Command {
|
|
163
|
+
const commandResponses = cluster.commandsResponse;
|
|
273
164
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
}
|
|
278
|
-
} else {
|
|
279
|
-
const cmd = commandsResponse[key];
|
|
165
|
+
if (typeof key === "number") {
|
|
166
|
+
for (const cmdKey in commandResponses) {
|
|
167
|
+
const cmd = commandResponses[cmdKey];
|
|
280
168
|
|
|
281
|
-
if (cmd) {
|
|
169
|
+
if (cmd.ID === key) {
|
|
282
170
|
return cmd;
|
|
283
171
|
}
|
|
284
172
|
}
|
|
173
|
+
} else {
|
|
174
|
+
const cmd = commandResponses[key];
|
|
285
175
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
ID: cluster.ID,
|
|
291
|
-
attributes,
|
|
292
|
-
manufacturerCode: cluster.manufacturerCode,
|
|
293
|
-
name,
|
|
294
|
-
commands,
|
|
295
|
-
commandsResponse,
|
|
296
|
-
getAttribute,
|
|
297
|
-
getCommand,
|
|
298
|
-
getCommandResponse,
|
|
299
|
-
};
|
|
300
|
-
}
|
|
176
|
+
if (cmd) {
|
|
177
|
+
return cmd;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
301
180
|
|
|
302
|
-
|
|
303
|
-
const {name, cluster} = getClusterDefinition(key, manufacturerCode, customClusters);
|
|
304
|
-
return createCluster(name, cluster, manufacturerCode);
|
|
181
|
+
throw new ZclStatusError(Status.UNSUP_COMMAND, `response ${cluster.name}:${key}`);
|
|
305
182
|
}
|
|
306
183
|
|
|
307
184
|
function getGlobalCommandNameById(id: number): FoundationCommandName {
|
|
@@ -311,28 +188,18 @@ function getGlobalCommandNameById(id: number): FoundationCommandName {
|
|
|
311
188
|
}
|
|
312
189
|
}
|
|
313
190
|
|
|
314
|
-
throw new
|
|
191
|
+
throw new ZclStatusError(Status.UNSUP_COMMAND, `foundation:${id}`);
|
|
315
192
|
}
|
|
316
193
|
|
|
317
|
-
export function getGlobalCommand(key: number | string):
|
|
194
|
+
export function getGlobalCommand(key: number | string): FoundationDefinition {
|
|
318
195
|
const name = typeof key === "number" ? getGlobalCommandNameById(key) : (key as FoundationCommandName);
|
|
319
196
|
const command = Foundation[name];
|
|
320
197
|
|
|
321
198
|
if (!command) {
|
|
322
|
-
throw new
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
const result: Command = {
|
|
326
|
-
ID: command.ID,
|
|
327
|
-
name,
|
|
328
|
-
parameters: command.parameters,
|
|
329
|
-
};
|
|
330
|
-
|
|
331
|
-
if (command.response !== undefined) {
|
|
332
|
-
result.response = command.response;
|
|
199
|
+
throw new ZclStatusError(Status.UNSUP_COMMAND, `foundation:${key}`);
|
|
333
200
|
}
|
|
334
201
|
|
|
335
|
-
return
|
|
202
|
+
return command;
|
|
336
203
|
}
|
|
337
204
|
|
|
338
205
|
export function isClusterName(name: string): name is ClusterName {
|
|
@@ -348,11 +215,17 @@ export function getFoundationCommand(id: number): FoundationDefinition {
|
|
|
348
215
|
}
|
|
349
216
|
}
|
|
350
217
|
|
|
351
|
-
throw new
|
|
218
|
+
throw new ZclStatusError(Status.UNSUP_COMMAND, `foundation:${id}`);
|
|
352
219
|
}
|
|
353
220
|
|
|
354
|
-
export function
|
|
355
|
-
|
|
221
|
+
export function getFoundationCommandByName(name: string): FoundationDefinition {
|
|
222
|
+
const command = Foundation[name as FoundationCommandName];
|
|
223
|
+
|
|
224
|
+
if (command === undefined) {
|
|
225
|
+
throw new ZclStatusError(Status.UNSUP_COMMAND, `foundation:${name}`);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return command;
|
|
356
229
|
}
|
|
357
230
|
|
|
358
231
|
/** Check if value is equal to either min, max, minRef or maxRef */
|
|
@@ -366,37 +239,37 @@ function isMinOrMax<T>(entry: Attribute | Parameter, value: T): boolean {
|
|
|
366
239
|
|
|
367
240
|
function processRestrictions<T>(entry: Attribute | Parameter, value: T): void {
|
|
368
241
|
if (entry.min !== undefined && (value as number) < entry.min) {
|
|
369
|
-
throw new
|
|
242
|
+
throw new ZclStatusError(Status.INVALID_VALUE, `${entry.name} requires min of ${entry.min}`);
|
|
370
243
|
}
|
|
371
244
|
|
|
372
245
|
if (entry.minExcl !== undefined && (value as number) <= entry.minExcl) {
|
|
373
|
-
throw new
|
|
246
|
+
throw new ZclStatusError(Status.INVALID_VALUE, `${entry.name} requires min exclusive of ${entry.minExcl}`);
|
|
374
247
|
}
|
|
375
248
|
|
|
376
249
|
if (entry.max !== undefined && (value as number) > entry.max) {
|
|
377
|
-
throw new
|
|
250
|
+
throw new ZclStatusError(Status.INVALID_VALUE, `${entry.name} requires max of ${entry.max}`);
|
|
378
251
|
}
|
|
379
252
|
|
|
380
253
|
if (entry.maxExcl !== undefined && (value as number) >= entry.maxExcl) {
|
|
381
|
-
throw new
|
|
254
|
+
throw new ZclStatusError(Status.INVALID_VALUE, `${entry.name} requires max exclusive of ${entry.maxExcl}`);
|
|
382
255
|
}
|
|
383
256
|
|
|
384
257
|
if (entry.length !== undefined && (value as string | unknown[] | Buffer).length !== entry.length) {
|
|
385
|
-
throw new
|
|
258
|
+
throw new ZclStatusError(Status.INVALID_VALUE, `${entry.name} requires length of ${entry.length}`);
|
|
386
259
|
}
|
|
387
260
|
|
|
388
261
|
if (entry.minLen !== undefined && (value as string | unknown[] | Buffer).length < entry.minLen) {
|
|
389
|
-
throw new
|
|
262
|
+
throw new ZclStatusError(Status.INVALID_VALUE, `${entry.name} requires min length of ${entry.minLen}`);
|
|
390
263
|
}
|
|
391
264
|
|
|
392
265
|
if (entry.maxLen !== undefined && (value as string | unknown[] | Buffer).length > entry.maxLen) {
|
|
393
|
-
throw new
|
|
266
|
+
throw new ZclStatusError(Status.INVALID_VALUE, `${entry.name} requires max length of ${entry.maxLen}`);
|
|
394
267
|
}
|
|
395
268
|
}
|
|
396
269
|
|
|
397
270
|
export function processAttributeWrite<T>(attribute: Attribute, value: T): T {
|
|
398
271
|
if (attribute.write !== true) {
|
|
399
|
-
throw new
|
|
272
|
+
throw new ZclStatusError(Status.NOT_AUTHORIZED, `${attribute.name} (${attribute.ID}) is not writable`);
|
|
400
273
|
}
|
|
401
274
|
|
|
402
275
|
if (value == null) {
|
|
@@ -413,7 +286,7 @@ export function processAttributeWrite<T>(attribute: Attribute, value: T): T {
|
|
|
413
286
|
const nonValue = ZCL_TYPE_INVALID_BY_TYPE[attribute.type];
|
|
414
287
|
|
|
415
288
|
if (nonValue === undefined) {
|
|
416
|
-
throw new
|
|
289
|
+
throw new ZclStatusError(Status.INVALID_FIELD, `${attribute.name} (${attribute.ID}) does not have a default nor a non-value`);
|
|
417
290
|
}
|
|
418
291
|
|
|
419
292
|
return nonValue as T;
|
|
@@ -429,7 +302,7 @@ export function processAttributeWrite<T>(attribute: Attribute, value: T): T {
|
|
|
429
302
|
|
|
430
303
|
export function processAttributePreRead(attribute: Attribute): void {
|
|
431
304
|
if (attribute.read === false) {
|
|
432
|
-
throw new
|
|
305
|
+
throw new ZclStatusError(Status.NOT_AUTHORIZED, `${attribute.name} (${attribute.ID}) is not readable`);
|
|
433
306
|
}
|
|
434
307
|
}
|
|
435
308
|
|
|
@@ -470,7 +343,7 @@ export function processParameterWrite<T>(parameter: Parameter, value: T): T {
|
|
|
470
343
|
const nonValue = ZCL_TYPE_INVALID_BY_TYPE[parameter.type];
|
|
471
344
|
|
|
472
345
|
if (nonValue === undefined) {
|
|
473
|
-
throw new
|
|
346
|
+
throw new ZclStatusError(Status.INVALID_FIELD, `${parameter.name} does not have a non-value`);
|
|
474
347
|
}
|
|
475
348
|
|
|
476
349
|
return nonValue as T;
|