@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
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type {BuffaloZcl} from "../buffaloZcl";
|
|
2
|
+
import {isAnalogDataType} from "../utils";
|
|
3
|
+
import {ZclStatusError} from "../zclStatusError";
|
|
4
|
+
import {BuffaloZclDataType, DataType, Direction} from "./enums";
|
|
2
5
|
import {Status} from "./status";
|
|
3
|
-
import type {
|
|
6
|
+
import type {Command, StructuredSelector} from "./tstype";
|
|
4
7
|
|
|
5
8
|
export type FoundationCommandName =
|
|
6
9
|
| "read"
|
|
@@ -27,316 +30,800 @@ export type FoundationCommandName =
|
|
|
27
30
|
| "discoverExt"
|
|
28
31
|
| "discoverExtRsp";
|
|
29
32
|
|
|
30
|
-
export interface FoundationDefinition
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
export interface FoundationDefinition<
|
|
34
|
+
// biome-ignore lint/suspicious/noExplicitAny: TODO: currently low level ZCL payloads are typed `any` which makes a mess
|
|
35
|
+
T extends Record<string, any> | Record<string, any>[] = Record<string, any> | Record<string, any>[],
|
|
36
|
+
> extends Pick<Command, "ID" | "name" | "response"> {
|
|
37
|
+
parse: (buffalo: BuffaloZcl) => T;
|
|
38
|
+
write: (buffalo: BuffaloZcl, payload: T) => void;
|
|
35
39
|
}
|
|
36
40
|
|
|
37
|
-
export const Foundation
|
|
41
|
+
export const Foundation = {
|
|
38
42
|
/** Read Attributes */
|
|
39
43
|
read: {
|
|
44
|
+
name: "read",
|
|
40
45
|
ID: 0x00,
|
|
41
|
-
parseStrategy: "repetitive",
|
|
42
|
-
parameters: [{name: "attrId", type: DataType.DATA16}],
|
|
43
46
|
response: 0x01, // readRsp
|
|
47
|
+
parse(buffalo) {
|
|
48
|
+
const payload: {attrId: number}[] = [];
|
|
49
|
+
|
|
50
|
+
do {
|
|
51
|
+
const attrId = buffalo.readUInt16();
|
|
52
|
+
|
|
53
|
+
payload.push({attrId});
|
|
54
|
+
} while (buffalo.isMore());
|
|
55
|
+
|
|
56
|
+
return payload;
|
|
57
|
+
},
|
|
58
|
+
write(buffalo, payload) {
|
|
59
|
+
if (!Array.isArray(payload)) {
|
|
60
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
for (const entry of payload) {
|
|
64
|
+
buffalo.writeUInt16(entry.attrId);
|
|
65
|
+
}
|
|
66
|
+
},
|
|
44
67
|
},
|
|
45
68
|
/** Read Attributes Response */
|
|
46
69
|
readRsp: {
|
|
70
|
+
name: "readRsp",
|
|
47
71
|
ID: 0x01,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
{
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
72
|
+
parse(buffalo) {
|
|
73
|
+
const payload: {attrId: number; status: number; dataType?: number; attrData?: unknown}[] = [];
|
|
74
|
+
|
|
75
|
+
do {
|
|
76
|
+
const attrId = buffalo.readUInt16();
|
|
77
|
+
const status = buffalo.readUInt8();
|
|
78
|
+
const rec: (typeof payload)[number] = {attrId, status};
|
|
79
|
+
|
|
80
|
+
if (status === Status.SUCCESS) {
|
|
81
|
+
const dataType = buffalo.readUInt8();
|
|
82
|
+
rec.dataType = dataType;
|
|
83
|
+
// [workaround] parse char str as Xiaomi struct for attribute 0xff01 (65281)
|
|
84
|
+
rec.attrData = buffalo.read(attrId === 0xff01 && dataType === DataType.CHAR_STR ? BuffaloZclDataType.MI_STRUCT : dataType, {});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
payload.push(rec);
|
|
88
|
+
} while (buffalo.isMore());
|
|
89
|
+
|
|
90
|
+
return payload;
|
|
91
|
+
},
|
|
92
|
+
write(buffalo, payload) {
|
|
93
|
+
if (!Array.isArray(payload)) {
|
|
94
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
for (const entry of payload) {
|
|
98
|
+
buffalo.writeUInt16(entry.attrId);
|
|
99
|
+
buffalo.writeUInt8(entry.status);
|
|
100
|
+
|
|
101
|
+
if (entry.status === Status.SUCCESS) {
|
|
102
|
+
buffalo.writeUInt8(entry.dataType);
|
|
103
|
+
buffalo.write(entry.dataType, entry.attrData, {});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
59
107
|
},
|
|
60
108
|
/** Write Attributes */
|
|
61
109
|
write: {
|
|
110
|
+
name: "write",
|
|
62
111
|
ID: 0x02,
|
|
63
|
-
parseStrategy: "repetitive",
|
|
64
|
-
parameters: [
|
|
65
|
-
{name: "attrId", type: DataType.DATA16},
|
|
66
|
-
{name: "dataType", type: DataType.DATA8},
|
|
67
|
-
{name: "attrData", type: BuffaloZclDataType.USE_DATA_TYPE},
|
|
68
|
-
],
|
|
69
112
|
response: 0x04, // writeRsp
|
|
113
|
+
parse(buffalo) {
|
|
114
|
+
const payload: {attrId: number; dataType: number; attrData: unknown}[] = [];
|
|
115
|
+
|
|
116
|
+
do {
|
|
117
|
+
const attrId = buffalo.readUInt16();
|
|
118
|
+
const dataType = buffalo.readUInt8();
|
|
119
|
+
const attrData = buffalo.read(dataType, {});
|
|
120
|
+
|
|
121
|
+
payload.push({attrId, dataType, attrData});
|
|
122
|
+
} while (buffalo.isMore());
|
|
123
|
+
|
|
124
|
+
return payload;
|
|
125
|
+
},
|
|
126
|
+
write(buffalo, payload) {
|
|
127
|
+
if (!Array.isArray(payload)) {
|
|
128
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
for (const entry of payload) {
|
|
132
|
+
buffalo.writeUInt16(entry.attrId);
|
|
133
|
+
buffalo.writeUInt8(entry.dataType);
|
|
134
|
+
buffalo.write(entry.dataType, entry.attrData, {});
|
|
135
|
+
}
|
|
136
|
+
},
|
|
70
137
|
},
|
|
71
138
|
/** Write Attributes Undivided */
|
|
72
139
|
writeUndiv: {
|
|
140
|
+
name: "writeUndiv",
|
|
73
141
|
ID: 0x03,
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
{
|
|
78
|
-
|
|
79
|
-
|
|
142
|
+
parse(buffalo) {
|
|
143
|
+
const payload: {attrId: number; dataType: number; attrData: unknown}[] = [];
|
|
144
|
+
|
|
145
|
+
do {
|
|
146
|
+
const attrId = buffalo.readUInt16();
|
|
147
|
+
const dataType = buffalo.readUInt8();
|
|
148
|
+
const attrData = buffalo.read(dataType, {});
|
|
149
|
+
|
|
150
|
+
payload.push({attrId, dataType, attrData});
|
|
151
|
+
} while (buffalo.isMore());
|
|
152
|
+
|
|
153
|
+
return payload;
|
|
154
|
+
},
|
|
155
|
+
write(buffalo, payload) {
|
|
156
|
+
if (!Array.isArray(payload)) {
|
|
157
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
for (const entry of payload) {
|
|
161
|
+
buffalo.writeUInt16(entry.attrId);
|
|
162
|
+
buffalo.writeUInt8(entry.dataType);
|
|
163
|
+
buffalo.write(entry.dataType, entry.attrData, {});
|
|
164
|
+
}
|
|
165
|
+
},
|
|
80
166
|
},
|
|
81
167
|
/** Write Attributes Response */
|
|
82
168
|
writeRsp: {
|
|
169
|
+
name: "writeRsp",
|
|
83
170
|
ID: 0x04,
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
171
|
+
/**
|
|
172
|
+
* Note that write attribute status records are not included for successfully written attributes, to save bandwidth.
|
|
173
|
+
* In the case of successful writing of all attributes, only a single write attribute status record SHALL be included in the command,
|
|
174
|
+
* with the status field set to SUCCESS and the attribute identifier field omitted.
|
|
175
|
+
*/
|
|
176
|
+
parse(buffalo) {
|
|
177
|
+
const firstStatus = buffalo.readUInt8();
|
|
178
|
+
|
|
179
|
+
if (firstStatus === Status.SUCCESS) {
|
|
180
|
+
return [{status: firstStatus}];
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const payload: {status: number; attrId?: number}[] = [];
|
|
184
|
+
const attrId = buffalo.readUInt16();
|
|
185
|
+
|
|
186
|
+
payload.push({status: firstStatus, attrId});
|
|
187
|
+
|
|
188
|
+
while (buffalo.isMore()) {
|
|
189
|
+
const status = buffalo.readUInt8();
|
|
190
|
+
const attrId = buffalo.readUInt16();
|
|
191
|
+
|
|
192
|
+
payload.push({status, attrId});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return payload;
|
|
196
|
+
},
|
|
197
|
+
write(buffalo, payload) {
|
|
198
|
+
if (!Array.isArray(payload)) {
|
|
199
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const nonSuccessPayload = payload.filter((entry) => entry.status !== Status.SUCCESS);
|
|
203
|
+
|
|
204
|
+
if (nonSuccessPayload.length === 0) {
|
|
205
|
+
buffalo.writeUInt8(Status.SUCCESS);
|
|
206
|
+
} else {
|
|
207
|
+
for (const entry of nonSuccessPayload) {
|
|
208
|
+
buffalo.writeUInt8(entry.status);
|
|
209
|
+
buffalo.writeUInt16(entry.attrId);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
},
|
|
93
213
|
},
|
|
94
214
|
/** Write Attributes No Response */
|
|
95
215
|
writeNoRsp: {
|
|
216
|
+
name: "writeNoRsp",
|
|
96
217
|
ID: 0x05,
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
{
|
|
101
|
-
|
|
102
|
-
|
|
218
|
+
parse(buffalo) {
|
|
219
|
+
const payload: {attrId: number; dataType: number; attrData: unknown}[] = [];
|
|
220
|
+
|
|
221
|
+
do {
|
|
222
|
+
const attrId = buffalo.readUInt16();
|
|
223
|
+
const dataType = buffalo.readUInt8();
|
|
224
|
+
const attrData = buffalo.read(dataType, {});
|
|
225
|
+
|
|
226
|
+
payload.push({attrId, dataType, attrData});
|
|
227
|
+
} while (buffalo.isMore());
|
|
228
|
+
|
|
229
|
+
return payload;
|
|
230
|
+
},
|
|
231
|
+
write(buffalo, payload) {
|
|
232
|
+
if (!Array.isArray(payload)) {
|
|
233
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
for (const entry of payload) {
|
|
237
|
+
buffalo.writeUInt16(entry.attrId);
|
|
238
|
+
buffalo.writeUInt8(entry.dataType);
|
|
239
|
+
buffalo.write(entry.dataType, entry.attrData, {});
|
|
240
|
+
}
|
|
241
|
+
},
|
|
103
242
|
},
|
|
104
243
|
/** Configure Reporting */
|
|
105
244
|
configReport: {
|
|
245
|
+
name: "configReport",
|
|
106
246
|
ID: 0x06,
|
|
107
|
-
parseStrategy: "repetitive",
|
|
108
|
-
parameters: [
|
|
109
|
-
{name: "direction", type: DataType.DATA8},
|
|
110
|
-
{name: "attrId", type: DataType.DATA16},
|
|
111
|
-
{
|
|
112
|
-
name: "dataType",
|
|
113
|
-
type: DataType.DATA8,
|
|
114
|
-
conditions: [{type: ParameterCondition.FIELD_EQUAL, field: "direction", value: Direction.CLIENT_TO_SERVER}],
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
name: "minRepIntval",
|
|
118
|
-
type: DataType.DATA16,
|
|
119
|
-
conditions: [{type: ParameterCondition.FIELD_EQUAL, field: "direction", value: Direction.CLIENT_TO_SERVER}],
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
name: "maxRepIntval",
|
|
123
|
-
type: DataType.DATA16,
|
|
124
|
-
conditions: [{type: ParameterCondition.FIELD_EQUAL, field: "direction", value: Direction.CLIENT_TO_SERVER}],
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
name: "repChange",
|
|
128
|
-
type: BuffaloZclDataType.USE_DATA_TYPE,
|
|
129
|
-
conditions: [
|
|
130
|
-
{type: ParameterCondition.FIELD_EQUAL, field: "direction", value: Direction.CLIENT_TO_SERVER},
|
|
131
|
-
{type: ParameterCondition.DATA_TYPE_CLASS_EQUAL, value: DataTypeClass.ANALOG},
|
|
132
|
-
],
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
name: "timeout",
|
|
136
|
-
type: DataType.DATA16,
|
|
137
|
-
conditions: [{type: ParameterCondition.FIELD_EQUAL, field: "direction", value: Direction.SERVER_TO_CLIENT}],
|
|
138
|
-
},
|
|
139
|
-
],
|
|
140
247
|
response: 0x07, // configReportRsp
|
|
248
|
+
parse(buffalo) {
|
|
249
|
+
const payload: {
|
|
250
|
+
direction: number;
|
|
251
|
+
attrId: number;
|
|
252
|
+
dataType?: number;
|
|
253
|
+
/**
|
|
254
|
+
* - If this value is set to 0x0000, then there is no minimum limit,
|
|
255
|
+
* unless one is imposed by the specification of the cluster using this reporting mechanism or by the application.
|
|
256
|
+
*/
|
|
257
|
+
minRepIntval?: number;
|
|
258
|
+
/**
|
|
259
|
+
* - If this value is set to 0xffff, then the device SHALL not issue reports for the specified attribute,
|
|
260
|
+
* and the configuration information for that attribute need not be maintained.
|
|
261
|
+
* - If this value is set to 0x0000, and the minimum reporting interval field does not equal 0xffff
|
|
262
|
+
* there SHALL be no periodic reporting, but change based reporting SHALL still be operational.
|
|
263
|
+
* - If this value is set to 0x0000 and the Minimum Reporting Interval Field equals 0xffff,
|
|
264
|
+
* then the device SHALL revert to its default reporting configuration.
|
|
265
|
+
* The reportable change field, if present, SHALL be set to zero.
|
|
266
|
+
*/
|
|
267
|
+
maxRepIntval?: number;
|
|
268
|
+
/**
|
|
269
|
+
* - If the Maximum Reporting Interval Field is set to 0xffff (terminate reporting configuration),
|
|
270
|
+
* or the Maximum Reporting Interval Field is set to 0x0000 and the Minimum Reporting Interval Field equals 0xffff,
|
|
271
|
+
* indicating a (default reporting configuration) then if this field is present,
|
|
272
|
+
* it SHALL be set to zero upon transmission and ignored upon reception.
|
|
273
|
+
*/
|
|
274
|
+
repChange?: number;
|
|
275
|
+
/**
|
|
276
|
+
* - If this value is set to 0x0000, reports of the attribute are not subject to timeout.
|
|
277
|
+
*/
|
|
278
|
+
timeout?: number;
|
|
279
|
+
}[] = [];
|
|
280
|
+
|
|
281
|
+
do {
|
|
282
|
+
const direction = buffalo.readUInt8();
|
|
283
|
+
const attrId = buffalo.readUInt16();
|
|
284
|
+
const rec: (typeof payload)[number] = {direction, attrId};
|
|
285
|
+
|
|
286
|
+
if (direction === Direction.CLIENT_TO_SERVER) {
|
|
287
|
+
const dataType = buffalo.readUInt8();
|
|
288
|
+
rec.dataType = dataType;
|
|
289
|
+
rec.minRepIntval = buffalo.readUInt16();
|
|
290
|
+
rec.maxRepIntval = buffalo.readUInt16();
|
|
291
|
+
|
|
292
|
+
if (isAnalogDataType(dataType)) {
|
|
293
|
+
rec.repChange = buffalo.read(dataType, {});
|
|
294
|
+
}
|
|
295
|
+
} else if (direction === Direction.SERVER_TO_CLIENT) {
|
|
296
|
+
rec.timeout = buffalo.readUInt16();
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
payload.push(rec);
|
|
300
|
+
} while (buffalo.isMore());
|
|
301
|
+
|
|
302
|
+
return payload;
|
|
303
|
+
},
|
|
304
|
+
write(buffalo, payload) {
|
|
305
|
+
if (!Array.isArray(payload)) {
|
|
306
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
for (const entry of payload) {
|
|
310
|
+
buffalo.writeUInt8(entry.direction);
|
|
311
|
+
buffalo.writeUInt16(entry.attrId);
|
|
312
|
+
|
|
313
|
+
if (entry.direction === Direction.CLIENT_TO_SERVER) {
|
|
314
|
+
buffalo.writeUInt8(entry.dataType);
|
|
315
|
+
buffalo.writeUInt16(entry.minRepIntval);
|
|
316
|
+
buffalo.writeUInt16(entry.maxRepIntval);
|
|
317
|
+
|
|
318
|
+
if (isAnalogDataType(entry.dataType)) {
|
|
319
|
+
buffalo.write(entry.dataType, entry.repChange, {});
|
|
320
|
+
}
|
|
321
|
+
} else if (entry.direction === Direction.SERVER_TO_CLIENT) {
|
|
322
|
+
buffalo.writeUInt16(entry.timeout);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
},
|
|
141
326
|
},
|
|
142
327
|
/** Configure Reporting Response */
|
|
143
328
|
configReportRsp: {
|
|
329
|
+
name: "configReportRsp",
|
|
144
330
|
ID: 0x07,
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
331
|
+
/**
|
|
332
|
+
* Note that attribute status records are not included for successfully configured attributes, to save bandwidth.
|
|
333
|
+
* In the case of successful configuration of all attributes, only a single attribute status record SHALL be included in the command,
|
|
334
|
+
* with the status field set to SUCCESS and the direction and attribute identifier fields omitted.
|
|
335
|
+
*/
|
|
336
|
+
parse(buffalo) {
|
|
337
|
+
const firstStatus = buffalo.readUInt8();
|
|
338
|
+
|
|
339
|
+
if (firstStatus === Status.SUCCESS) {
|
|
340
|
+
return [{status: firstStatus}];
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const payload: {status: number; direction?: number; attrId?: number}[] = [];
|
|
344
|
+
const direction = buffalo.readUInt8();
|
|
345
|
+
const attrId = buffalo.readUInt16();
|
|
346
|
+
|
|
347
|
+
payload.push({status: firstStatus, direction, attrId});
|
|
348
|
+
|
|
349
|
+
while (buffalo.isMore()) {
|
|
350
|
+
const status = buffalo.readUInt8();
|
|
351
|
+
const direction = buffalo.readUInt8();
|
|
352
|
+
const attrId = buffalo.readUInt16();
|
|
353
|
+
|
|
354
|
+
payload.push({status, direction, attrId});
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return payload;
|
|
358
|
+
},
|
|
359
|
+
write(buffalo, payload) {
|
|
360
|
+
if (!Array.isArray(payload)) {
|
|
361
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const nonSuccessPayload = payload.filter((entry) => entry.status !== Status.SUCCESS);
|
|
365
|
+
|
|
366
|
+
if (nonSuccessPayload.length === 0) {
|
|
367
|
+
buffalo.writeUInt8(Status.SUCCESS);
|
|
368
|
+
} else {
|
|
369
|
+
for (const entry of nonSuccessPayload) {
|
|
370
|
+
buffalo.writeUInt8(entry.status);
|
|
371
|
+
buffalo.writeUInt8(entry.direction);
|
|
372
|
+
buffalo.writeUInt16(entry.attrId);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
},
|
|
153
376
|
},
|
|
154
377
|
/** Read Reporting Configuration */
|
|
155
378
|
readReportConfig: {
|
|
379
|
+
name: "readReportConfig",
|
|
156
380
|
ID: 0x08,
|
|
157
|
-
parseStrategy: "repetitive",
|
|
158
|
-
parameters: [
|
|
159
|
-
{name: "direction", type: DataType.DATA8},
|
|
160
|
-
{name: "attrId", type: DataType.DATA16},
|
|
161
|
-
],
|
|
162
381
|
response: 0x09, // readReportConfigRsp
|
|
382
|
+
parse(buffalo) {
|
|
383
|
+
const payload: {direction: number; attrId: number}[] = [];
|
|
384
|
+
|
|
385
|
+
do {
|
|
386
|
+
const direction = buffalo.readUInt8();
|
|
387
|
+
const attrId = buffalo.readUInt16();
|
|
388
|
+
|
|
389
|
+
payload.push({direction, attrId});
|
|
390
|
+
} while (buffalo.isMore());
|
|
391
|
+
|
|
392
|
+
return payload;
|
|
393
|
+
},
|
|
394
|
+
write(buffalo, payload) {
|
|
395
|
+
if (!Array.isArray(payload)) {
|
|
396
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
for (const entry of payload) {
|
|
400
|
+
buffalo.writeUInt8(entry.direction);
|
|
401
|
+
buffalo.writeUInt16(entry.attrId);
|
|
402
|
+
}
|
|
403
|
+
},
|
|
163
404
|
},
|
|
164
405
|
/** Read Reporting Configuration Response */
|
|
165
406
|
readReportConfigRsp: {
|
|
407
|
+
name: "readReportConfigRsp",
|
|
166
408
|
ID: 0x09,
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
409
|
+
parse(buffalo) {
|
|
410
|
+
const payload: {
|
|
411
|
+
status: number;
|
|
412
|
+
direction: number;
|
|
413
|
+
attrId: number;
|
|
414
|
+
dataType?: number;
|
|
415
|
+
minRepIntval?: number;
|
|
416
|
+
maxRepIntval?: number;
|
|
417
|
+
repChange?: number;
|
|
418
|
+
timeout?: number;
|
|
419
|
+
}[] = [];
|
|
420
|
+
|
|
421
|
+
do {
|
|
422
|
+
const status = buffalo.readUInt8();
|
|
423
|
+
const direction = buffalo.readUInt8();
|
|
424
|
+
const attrId = buffalo.readUInt16();
|
|
425
|
+
const rec: (typeof payload)[number] = {status, direction, attrId};
|
|
426
|
+
|
|
427
|
+
if (status === Status.SUCCESS) {
|
|
428
|
+
if (direction === Direction.CLIENT_TO_SERVER) {
|
|
429
|
+
const dataType = buffalo.readUInt8();
|
|
430
|
+
rec.dataType = dataType;
|
|
431
|
+
rec.minRepIntval = buffalo.readUInt16();
|
|
432
|
+
rec.maxRepIntval = buffalo.readUInt16();
|
|
433
|
+
|
|
434
|
+
if (isAnalogDataType(dataType)) {
|
|
435
|
+
rec.repChange = buffalo.read(dataType, {});
|
|
436
|
+
}
|
|
437
|
+
} else if (direction === Direction.SERVER_TO_CLIENT) {
|
|
438
|
+
rec.timeout = buffalo.readUInt16();
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
payload.push(rec);
|
|
443
|
+
} while (buffalo.isMore());
|
|
444
|
+
|
|
445
|
+
return payload;
|
|
446
|
+
},
|
|
447
|
+
write(buffalo, payload) {
|
|
448
|
+
if (!Array.isArray(payload)) {
|
|
449
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
for (const entry of payload) {
|
|
453
|
+
buffalo.writeUInt8(entry.status);
|
|
454
|
+
buffalo.writeUInt8(entry.direction);
|
|
455
|
+
buffalo.writeUInt16(entry.attrId);
|
|
456
|
+
|
|
457
|
+
if (entry.status === Status.SUCCESS) {
|
|
458
|
+
if (entry.direction === Direction.CLIENT_TO_SERVER) {
|
|
459
|
+
buffalo.writeUInt8(entry.dataType);
|
|
460
|
+
buffalo.writeUInt16(entry.minRepIntval);
|
|
461
|
+
buffalo.writeUInt16(entry.maxRepIntval);
|
|
462
|
+
|
|
463
|
+
if (isAnalogDataType(entry.dataType)) {
|
|
464
|
+
buffalo.write(entry.dataType, entry.repChange, {});
|
|
465
|
+
}
|
|
466
|
+
} else if (entry.direction === Direction.SERVER_TO_CLIENT) {
|
|
467
|
+
buffalo.writeUInt16(entry.timeout);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
},
|
|
214
472
|
},
|
|
215
473
|
/** Report attributes */
|
|
216
474
|
report: {
|
|
475
|
+
name: "report",
|
|
217
476
|
ID: 0x0a,
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
{
|
|
222
|
-
|
|
223
|
-
|
|
477
|
+
parse(buffalo) {
|
|
478
|
+
const payload: {attrId: number; dataType: number; attrData: unknown}[] = [];
|
|
479
|
+
|
|
480
|
+
do {
|
|
481
|
+
const attrId = buffalo.readUInt16();
|
|
482
|
+
const dataType = buffalo.readUInt8();
|
|
483
|
+
// [workaround] parse char str as Xiaomi struct for attribute 0xff01 (65281)
|
|
484
|
+
const attrData = buffalo.read(attrId === 0xff01 && dataType === DataType.CHAR_STR ? BuffaloZclDataType.MI_STRUCT : dataType, {});
|
|
485
|
+
|
|
486
|
+
payload.push({attrId, dataType, attrData});
|
|
487
|
+
} while (buffalo.isMore());
|
|
488
|
+
|
|
489
|
+
return payload;
|
|
490
|
+
},
|
|
491
|
+
write(buffalo, payload) {
|
|
492
|
+
if (!Array.isArray(payload)) {
|
|
493
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
for (const entry of payload) {
|
|
497
|
+
buffalo.writeUInt16(entry.attrId);
|
|
498
|
+
buffalo.writeUInt8(entry.dataType);
|
|
499
|
+
buffalo.write(entry.dataType, entry.attrData, {});
|
|
500
|
+
}
|
|
501
|
+
},
|
|
224
502
|
},
|
|
225
503
|
/** Default Response */
|
|
226
504
|
defaultRsp: {
|
|
505
|
+
name: "defaultRsp",
|
|
227
506
|
ID: 0x0b,
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
507
|
+
parse(buffalo) {
|
|
508
|
+
const cmdId = buffalo.readUInt8();
|
|
509
|
+
const statusCode = buffalo.readUInt8();
|
|
510
|
+
|
|
511
|
+
return {cmdId, statusCode};
|
|
512
|
+
},
|
|
513
|
+
write(buffalo, payload) {
|
|
514
|
+
if (Array.isArray(payload)) {
|
|
515
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
buffalo.writeUInt8(payload.cmdId);
|
|
519
|
+
buffalo.writeUInt8(payload.statusCode);
|
|
520
|
+
},
|
|
233
521
|
},
|
|
234
522
|
/** Discover Attributes */
|
|
235
523
|
discover: {
|
|
524
|
+
name: "discover",
|
|
236
525
|
ID: 0x0c,
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
526
|
+
parse(buffalo) {
|
|
527
|
+
const startAttrId = buffalo.readUInt16();
|
|
528
|
+
const maxAttrIds = buffalo.readUInt8();
|
|
529
|
+
|
|
530
|
+
return {startAttrId, maxAttrIds};
|
|
531
|
+
},
|
|
532
|
+
write(buffalo, payload) {
|
|
533
|
+
if (Array.isArray(payload)) {
|
|
534
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
buffalo.writeUInt16(payload.startAttrId);
|
|
538
|
+
buffalo.writeUInt8(payload.maxAttrIds);
|
|
539
|
+
},
|
|
242
540
|
},
|
|
243
541
|
/** Discover Attributes Response */
|
|
244
542
|
discoverRsp: {
|
|
543
|
+
name: "discoverRsp",
|
|
245
544
|
ID: 0x0d,
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
{
|
|
250
|
-
|
|
545
|
+
parse(buffalo) {
|
|
546
|
+
const discComplete = buffalo.readUInt8();
|
|
547
|
+
const attrInfos: {attrId: number; dataType: number}[] = [];
|
|
548
|
+
const payload: {discComplete: number; attrInfos: typeof attrInfos} = {discComplete, attrInfos};
|
|
549
|
+
|
|
550
|
+
do {
|
|
551
|
+
const attrId = buffalo.readUInt16();
|
|
552
|
+
const dataType = buffalo.readUInt8();
|
|
553
|
+
|
|
554
|
+
attrInfos.push({attrId, dataType});
|
|
555
|
+
} while (buffalo.isMore());
|
|
556
|
+
|
|
557
|
+
return payload;
|
|
558
|
+
},
|
|
559
|
+
write(buffalo, payload) {
|
|
560
|
+
if (Array.isArray(payload)) {
|
|
561
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
buffalo.writeUInt8(payload.discComplete);
|
|
565
|
+
|
|
566
|
+
for (const entry of payload.attrInfos) {
|
|
567
|
+
buffalo.writeUInt16(entry.attrId);
|
|
568
|
+
buffalo.writeUInt8(entry.dataType);
|
|
569
|
+
}
|
|
570
|
+
},
|
|
251
571
|
},
|
|
252
572
|
/** Read Attributes Structured */
|
|
253
573
|
readStructured: {
|
|
574
|
+
name: "readStructured",
|
|
254
575
|
ID: 0x0e,
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
{
|
|
259
|
-
|
|
576
|
+
parse(buffalo) {
|
|
577
|
+
const payload: {attrId: number; selector: StructuredSelector}[] = [];
|
|
578
|
+
|
|
579
|
+
do {
|
|
580
|
+
const attrId = buffalo.readUInt16();
|
|
581
|
+
const selector = buffalo.readStructuredSelector();
|
|
582
|
+
|
|
583
|
+
payload.push({attrId, selector});
|
|
584
|
+
} while (buffalo.isMore());
|
|
585
|
+
|
|
586
|
+
return payload;
|
|
587
|
+
},
|
|
588
|
+
write(buffalo, payload) {
|
|
589
|
+
if (!Array.isArray(payload)) {
|
|
590
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
for (const entry of payload) {
|
|
594
|
+
buffalo.writeUInt16(entry.attrId);
|
|
595
|
+
buffalo.writeStructuredSelector(entry.selector);
|
|
596
|
+
}
|
|
597
|
+
},
|
|
260
598
|
},
|
|
261
599
|
/** Write Attributes Structured */
|
|
262
600
|
writeStructured: {
|
|
601
|
+
name: "writeStructured",
|
|
263
602
|
ID: 0x0f,
|
|
264
|
-
parseStrategy: "repetitive",
|
|
265
|
-
parameters: [
|
|
266
|
-
{name: "attrId", type: DataType.DATA16},
|
|
267
|
-
{name: "selector", type: BuffaloZclDataType.STRUCTURED_SELECTOR},
|
|
268
|
-
{name: "dataType", type: DataType.DATA8},
|
|
269
|
-
{name: "elementData", type: BuffaloZclDataType.USE_DATA_TYPE},
|
|
270
|
-
],
|
|
271
603
|
response: 0x10, // writeStructuredRsp
|
|
604
|
+
parse(buffalo) {
|
|
605
|
+
const payload: {attrId: number; selector: StructuredSelector; dataType: number; elementData: unknown}[] = [];
|
|
606
|
+
|
|
607
|
+
do {
|
|
608
|
+
const attrId = buffalo.readUInt16();
|
|
609
|
+
const selector = buffalo.readStructuredSelector();
|
|
610
|
+
const dataType = buffalo.readUInt8();
|
|
611
|
+
const elementData = buffalo.read(dataType, {});
|
|
612
|
+
|
|
613
|
+
payload.push({attrId, selector, dataType, elementData});
|
|
614
|
+
} while (buffalo.isMore());
|
|
615
|
+
|
|
616
|
+
return payload;
|
|
617
|
+
},
|
|
618
|
+
write(buffalo, payload) {
|
|
619
|
+
if (!Array.isArray(payload)) {
|
|
620
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
for (const entry of payload) {
|
|
624
|
+
buffalo.writeUInt16(entry.attrId);
|
|
625
|
+
buffalo.writeStructuredSelector(entry.selector);
|
|
626
|
+
buffalo.writeUInt8(entry.dataType);
|
|
627
|
+
buffalo.write(entry.dataType, entry.elementData, {});
|
|
628
|
+
}
|
|
629
|
+
},
|
|
272
630
|
},
|
|
273
631
|
/** Write Attributes Structured response */
|
|
274
632
|
writeStructuredRsp: {
|
|
633
|
+
name: "writeStructuredRsp",
|
|
275
634
|
ID: 0x10,
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
635
|
+
/**
|
|
636
|
+
* Note that write attribute status records are not included for successfully written attributes, to save bandwidth.
|
|
637
|
+
* In the case of successful writing of all attributes, only a single write attribute status record SHALL be included in the command,
|
|
638
|
+
* with the status field set to SUCCESS and the attribute identifier and selector fields omitted.
|
|
639
|
+
*/
|
|
640
|
+
parse(buffalo) {
|
|
641
|
+
const firstStatus = buffalo.readUInt8();
|
|
642
|
+
|
|
643
|
+
if (firstStatus === Status.SUCCESS) {
|
|
644
|
+
return [{status: firstStatus}];
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
const payload: {status: number; attrId?: number; selector?: StructuredSelector}[] = [];
|
|
648
|
+
const attrId = buffalo.readUInt16();
|
|
649
|
+
const selector = buffalo.readStructuredSelector();
|
|
650
|
+
|
|
651
|
+
payload.push({status: firstStatus, attrId, selector});
|
|
652
|
+
|
|
653
|
+
while (buffalo.isMore()) {
|
|
654
|
+
const status = buffalo.readUInt8();
|
|
655
|
+
const attrId = buffalo.readUInt16();
|
|
656
|
+
const selector = buffalo.readStructuredSelector();
|
|
657
|
+
|
|
658
|
+
payload.push({status, attrId, selector});
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
return payload;
|
|
662
|
+
},
|
|
663
|
+
write(buffalo, payload) {
|
|
664
|
+
if (!Array.isArray(payload)) {
|
|
665
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
const nonSuccessPayload = payload.filter((entry) => entry.status !== Status.SUCCESS);
|
|
669
|
+
|
|
670
|
+
if (nonSuccessPayload.length === 0) {
|
|
671
|
+
buffalo.writeUInt8(Status.SUCCESS);
|
|
672
|
+
} else {
|
|
673
|
+
for (const entry of nonSuccessPayload) {
|
|
674
|
+
buffalo.writeUInt8(entry.status);
|
|
675
|
+
buffalo.writeUInt16(entry.attrId);
|
|
676
|
+
buffalo.writeStructuredSelector(entry.selector);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
},
|
|
292
680
|
},
|
|
293
681
|
/** Discover Commands Received */
|
|
294
682
|
discoverCommands: {
|
|
683
|
+
name: "discoverCommands",
|
|
295
684
|
ID: 0x11,
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
685
|
+
parse(buffalo) {
|
|
686
|
+
const startCmdId = buffalo.readUInt8();
|
|
687
|
+
const maxCmdIds = buffalo.readUInt8();
|
|
688
|
+
|
|
689
|
+
return {startCmdId, maxCmdIds};
|
|
690
|
+
},
|
|
691
|
+
write(buffalo, payload) {
|
|
692
|
+
if (Array.isArray(payload)) {
|
|
693
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
buffalo.writeUInt8(payload.startCmdId);
|
|
697
|
+
buffalo.writeUInt8(payload.maxCmdIds);
|
|
698
|
+
},
|
|
301
699
|
},
|
|
302
700
|
/** Discover Commands Received Response */
|
|
303
701
|
discoverCommandsRsp: {
|
|
702
|
+
name: "discoverCommandsRsp",
|
|
304
703
|
ID: 0x12,
|
|
305
|
-
|
|
306
|
-
|
|
704
|
+
parse(buffalo) {
|
|
705
|
+
const discComplete = buffalo.readUInt8();
|
|
706
|
+
const commandIds: number[] = [];
|
|
707
|
+
const payload: {discComplete: number; commandIds: typeof commandIds} = {discComplete, commandIds};
|
|
708
|
+
|
|
709
|
+
do {
|
|
710
|
+
const commandId = buffalo.readUInt8();
|
|
711
|
+
|
|
712
|
+
commandIds.push(commandId);
|
|
713
|
+
} while (buffalo.isMore());
|
|
714
|
+
|
|
715
|
+
return payload;
|
|
716
|
+
},
|
|
717
|
+
write(buffalo, payload) {
|
|
718
|
+
if (Array.isArray(payload)) {
|
|
719
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
buffalo.writeUInt8(payload.discComplete);
|
|
723
|
+
|
|
724
|
+
for (const commandId of payload.commandIds) {
|
|
725
|
+
buffalo.writeUInt8(commandId);
|
|
726
|
+
}
|
|
727
|
+
},
|
|
307
728
|
},
|
|
308
729
|
/** Discover Commands Generated */
|
|
309
730
|
discoverCommandsGen: {
|
|
731
|
+
name: "discoverCommandsGen",
|
|
310
732
|
ID: 0x13,
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
733
|
+
parse(buffalo) {
|
|
734
|
+
const startCmdId = buffalo.readUInt8();
|
|
735
|
+
const maxCmdIds = buffalo.readUInt8();
|
|
736
|
+
|
|
737
|
+
return {startCmdId, maxCmdIds};
|
|
738
|
+
},
|
|
739
|
+
write(buffalo, payload) {
|
|
740
|
+
if (Array.isArray(payload)) {
|
|
741
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
buffalo.writeUInt8(payload.startCmdId);
|
|
745
|
+
buffalo.writeUInt8(payload.maxCmdIds);
|
|
746
|
+
},
|
|
316
747
|
},
|
|
317
748
|
/** Discover Commands Generated Response */
|
|
318
749
|
discoverCommandsGenRsp: {
|
|
750
|
+
name: "discoverCommandsGenRsp",
|
|
319
751
|
ID: 0x14,
|
|
320
|
-
|
|
321
|
-
|
|
752
|
+
parse(buffalo) {
|
|
753
|
+
const discComplete = buffalo.readUInt8();
|
|
754
|
+
const commandIds: number[] = [];
|
|
755
|
+
const payload: {discComplete: number; commandIds: typeof commandIds} = {discComplete, commandIds};
|
|
756
|
+
|
|
757
|
+
do {
|
|
758
|
+
const commandId = buffalo.readUInt8();
|
|
759
|
+
|
|
760
|
+
commandIds.push(commandId);
|
|
761
|
+
} while (buffalo.isMore());
|
|
762
|
+
|
|
763
|
+
return payload;
|
|
764
|
+
},
|
|
765
|
+
write(buffalo, payload) {
|
|
766
|
+
if (Array.isArray(payload)) {
|
|
767
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
buffalo.writeUInt8(payload.discComplete);
|
|
771
|
+
|
|
772
|
+
for (const commandId of payload.commandIds) {
|
|
773
|
+
buffalo.writeUInt8(commandId);
|
|
774
|
+
}
|
|
775
|
+
},
|
|
322
776
|
},
|
|
323
777
|
/** Discover Attributes Extended */
|
|
324
778
|
discoverExt: {
|
|
779
|
+
name: "discoverExt",
|
|
325
780
|
ID: 0x15,
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
781
|
+
parse(buffalo) {
|
|
782
|
+
const startAttrId = buffalo.readUInt16();
|
|
783
|
+
const maxAttrIds = buffalo.readUInt8();
|
|
784
|
+
|
|
785
|
+
return {startAttrId, maxAttrIds};
|
|
786
|
+
},
|
|
787
|
+
write(buffalo, payload) {
|
|
788
|
+
if (Array.isArray(payload)) {
|
|
789
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
buffalo.writeUInt16(payload.startAttrId);
|
|
793
|
+
buffalo.writeUInt8(payload.maxAttrIds);
|
|
794
|
+
},
|
|
331
795
|
},
|
|
332
796
|
/** Discover Attributes Extended Response */
|
|
333
797
|
discoverExtRsp: {
|
|
798
|
+
name: "discoverExtRsp",
|
|
334
799
|
ID: 0x16,
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
{
|
|
339
|
-
|
|
340
|
-
|
|
800
|
+
parse(buffalo) {
|
|
801
|
+
const discComplete = buffalo.readUInt8();
|
|
802
|
+
const attrInfos: {attrId: number; dataType: number; access: number}[] = [];
|
|
803
|
+
const payload: {discComplete: number; attrInfos: typeof attrInfos} = {discComplete, attrInfos};
|
|
804
|
+
|
|
805
|
+
do {
|
|
806
|
+
const attrId = buffalo.readUInt16();
|
|
807
|
+
const dataType = buffalo.readUInt8();
|
|
808
|
+
const access = buffalo.readUInt8();
|
|
809
|
+
|
|
810
|
+
attrInfos.push({attrId, dataType, access});
|
|
811
|
+
} while (buffalo.isMore());
|
|
812
|
+
|
|
813
|
+
return payload;
|
|
814
|
+
},
|
|
815
|
+
write(buffalo, payload) {
|
|
816
|
+
if (Array.isArray(payload)) {
|
|
817
|
+
throw new ZclStatusError(Status.MALFORMED_COMMAND);
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
buffalo.writeUInt8(payload.discComplete);
|
|
821
|
+
|
|
822
|
+
for (const entry of payload.attrInfos) {
|
|
823
|
+
buffalo.writeUInt16(entry.attrId);
|
|
824
|
+
buffalo.writeUInt8(entry.dataType);
|
|
825
|
+
buffalo.writeUInt8(entry.access);
|
|
826
|
+
}
|
|
827
|
+
},
|
|
341
828
|
},
|
|
342
|
-
}
|
|
829
|
+
} satisfies Readonly<Record<FoundationCommandName, Readonly<FoundationDefinition>>>;
|