zigbee-herdsman-converters 25.91.0 → 25.93.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/CHANGELOG.md +50 -0
- package/dist/converters/fromZigbee.js +2 -2
- package/dist/converters/fromZigbee.js.map +1 -1
- package/dist/devices/dresden_elektronik.d.ts.map +1 -1
- package/dist/devices/dresden_elektronik.js +16 -6
- package/dist/devices/dresden_elektronik.js.map +1 -1
- package/dist/devices/ezviz.d.ts +3 -0
- package/dist/devices/ezviz.d.ts.map +1 -0
- package/dist/devices/ezviz.js +47 -0
- package/dist/devices/ezviz.js.map +1 -0
- package/dist/devices/gewiss.d.ts.map +1 -1
- package/dist/devices/gewiss.js +2 -1
- package/dist/devices/gewiss.js.map +1 -1
- package/dist/devices/gledopto.js +1 -1
- package/dist/devices/gledopto.js.map +1 -1
- package/dist/devices/heiman.d.ts.map +1 -1
- package/dist/devices/heiman.js +948 -256
- package/dist/devices/heiman.js.map +1 -1
- package/dist/devices/index.d.ts.map +1 -1
- package/dist/devices/index.js +2 -0
- package/dist/devices/index.js.map +1 -1
- package/dist/devices/inovelli.js +1 -1
- package/dist/devices/inovelli.js.map +1 -1
- package/dist/devices/ledvance.d.ts.map +1 -1
- package/dist/devices/ledvance.js +14 -20
- package/dist/devices/ledvance.js.map +1 -1
- package/dist/devices/lightsolutions.d.ts.map +1 -1
- package/dist/devices/lightsolutions.js +7 -0
- package/dist/devices/lightsolutions.js.map +1 -1
- package/dist/devices/lumi.d.ts.map +1 -1
- package/dist/devices/lumi.js +28 -34
- package/dist/devices/lumi.js.map +1 -1
- package/dist/devices/moes.d.ts.map +1 -1
- package/dist/devices/moes.js +98 -0
- package/dist/devices/moes.js.map +1 -1
- package/dist/devices/muller_licht.d.ts.map +1 -1
- package/dist/devices/muller_licht.js +7 -0
- package/dist/devices/muller_licht.js.map +1 -1
- package/dist/devices/philips.d.ts.map +1 -1
- package/dist/devices/philips.js +31 -13
- package/dist/devices/philips.js.map +1 -1
- package/dist/devices/sonoff.d.ts.map +1 -1
- package/dist/devices/sonoff.js +45 -53
- package/dist/devices/sonoff.js.map +1 -1
- package/dist/devices/tuya.d.ts.map +1 -1
- package/dist/devices/tuya.js +479 -17
- package/dist/devices/tuya.js.map +1 -1
- package/dist/lib/lumi.d.ts +2 -0
- package/dist/lib/lumi.d.ts.map +1 -1
- package/dist/lib/lumi.js +137 -0
- package/dist/lib/lumi.js.map +1 -1
- package/dist/lib/modernExtend.d.ts.map +1 -1
- package/dist/lib/modernExtend.js +3 -3
- package/dist/lib/modernExtend.js.map +1 -1
- package/dist/models-index.json +1 -1
- package/package.json +3 -3
package/dist/devices/heiman.js
CHANGED
|
@@ -43,218 +43,748 @@ const heiman_1 = require("../lib/heiman");
|
|
|
43
43
|
const m = __importStar(require("../lib/modernExtend"));
|
|
44
44
|
const reporting = __importStar(require("../lib/reporting"));
|
|
45
45
|
const tuya = __importStar(require("../lib/tuya"));
|
|
46
|
+
const utils = __importStar(require("../lib/utils"));
|
|
46
47
|
const e = exposes.presets;
|
|
47
48
|
const ea = exposes.access;
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
result.fall_status = ["normal", "fall_warning", "fall_alarm"][bit4to5] || "unknown";
|
|
63
|
-
}
|
|
64
|
-
return result;
|
|
49
|
+
const defaultResponseOptions = { disableDefaultResponse: false };
|
|
50
|
+
const iasWarningMode = { stop: 0, burglar: 1, fire: 2, emergency: 3, police_panic: 4, fire_panic: 5, emergency_panic: 6 };
|
|
51
|
+
const heimanExtend = {
|
|
52
|
+
heimanClusterRadar: () => m.deviceAddCustomCluster("heimanClusterRadar", {
|
|
53
|
+
ID: 0xfc8b,
|
|
54
|
+
manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.HEIMAN_TECHNOLOGY_CO_LTD,
|
|
55
|
+
attributes: {
|
|
56
|
+
enableIndicator: { ID: 0xf001, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true }, // 0: off, 1: enable
|
|
57
|
+
sensitivity: { ID: 0xf002, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true },
|
|
58
|
+
enableSubRegionIsolation: { ID: 0xf006, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true },
|
|
59
|
+
installationMethod: { ID: 0xf007, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true },
|
|
60
|
+
cellMountedTable: { ID: 0xf008, type: zigbee_herdsman_1.Zcl.DataType.OCTET_STR, write: true }, // string
|
|
61
|
+
wallMountedTable: { ID: 0xf009, type: zigbee_herdsman_1.Zcl.DataType.OCTET_STR, write: true }, // string
|
|
62
|
+
subRegionIsolationTable: { ID: 0xf00a, type: zigbee_herdsman_1.Zcl.DataType.OCTET_STR, write: true }, // string
|
|
65
63
|
},
|
|
64
|
+
commands: {},
|
|
65
|
+
commandsResponse: {},
|
|
66
|
+
}),
|
|
67
|
+
heimanClusterSpecial: () => m.deviceAddCustomCluster("heimanClusterSpecial", {
|
|
68
|
+
ID: 0xfc90,
|
|
69
|
+
manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.HEIMAN_TECHNOLOGY_CO_LTD,
|
|
70
|
+
attributes: {
|
|
71
|
+
// Sensor 0x0000~0x0FFF
|
|
72
|
+
sensorPreheatingState: { ID: 0x0000, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, write: true },
|
|
73
|
+
sensorSelfCheckState: { ID: 0x0001, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, write: true },
|
|
74
|
+
sensorFaultState: { ID: 0x0002, type: zigbee_herdsman_1.Zcl.DataType.BITMAP16, write: true },
|
|
75
|
+
sensorPollutionLevel: { ID: 0x0003, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true },
|
|
76
|
+
sensorSensitivityLevel: { ID: 0x0004, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, write: true },
|
|
77
|
+
sensorPrealarmThreshold: { ID: 0x0005, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, write: true },
|
|
78
|
+
sensorLifeState: { ID: 0x0006, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, write: true },
|
|
79
|
+
sensorLifeTime: { ID: 0x0007, type: zigbee_herdsman_1.Zcl.DataType.UINT16, write: true },
|
|
80
|
+
deviceMuteControl: { ID: 0x0008, type: zigbee_herdsman_1.Zcl.DataType.BITMAP32, write: true },
|
|
81
|
+
deviceMuteState: { ID: 0x0009, type: zigbee_herdsman_1.Zcl.DataType.BITMAP16, write: true },
|
|
82
|
+
deviceCascadeControlEnable: { ID: 0x000a, type: zigbee_herdsman_1.Zcl.DataType.BITMAP8, write: true },
|
|
83
|
+
deviceSoundToneType: { ID: 0x000b, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, write: true },
|
|
84
|
+
deviceSoundControl: { ID: 0x000c, type: zigbee_herdsman_1.Zcl.DataType.ARRAY, write: true },
|
|
85
|
+
deviceBlinkControl: { ID: 0x000d, type: zigbee_herdsman_1.Zcl.DataType.ARRAY, write: true },
|
|
86
|
+
smokeAdValue: { ID: 0x000e, type: zigbee_herdsman_1.Zcl.DataType.UINT16, write: true },
|
|
87
|
+
smokeAlarmType: { ID: 0x000f, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, write: true },
|
|
88
|
+
smokeWaterMistState: { ID: 0x0010, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, write: true },
|
|
89
|
+
smokeSensorData: { ID: 0x0011, type: zigbee_herdsman_1.Zcl.DataType.ARRAY, write: true },
|
|
90
|
+
deviceCascadeState: { ID: 0x0012, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, write: true },
|
|
91
|
+
sensorPrealarmState: { ID: 0x0013, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, write: true },
|
|
92
|
+
smokeConcentrationLevel: { ID: 0x0016, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
|
|
93
|
+
smokeChamberContaminationLevel: { ID: 0x0017, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
|
|
94
|
+
smokeConcentationUnit: { ID: 0x0018, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
|
|
95
|
+
// Light/Switch 0x1000~0x1FFF
|
|
96
|
+
indicatorLightControl: { ID: 0x1000, type: zigbee_herdsman_1.Zcl.DataType.BITMAP8, write: true },
|
|
97
|
+
indicatorLightNotDisturbStartTime: { ID: 0x1001, type: zigbee_herdsman_1.Zcl.DataType.UINT16, write: true },
|
|
98
|
+
indicatorLightNotDisturbEndTime: { ID: 0x1002, type: zigbee_herdsman_1.Zcl.DataType.UINT16, write: true },
|
|
99
|
+
indicatorLightNotDisturbEnable: { ID: 0x1003, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true },
|
|
100
|
+
indicatorLightLevelControlOf1: { ID: 0x1004, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true },
|
|
101
|
+
indicatorLightLevelControlOf2: { ID: 0x1005, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true },
|
|
102
|
+
indicatorLightLevelControlOf3: { ID: 0x1006, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true },
|
|
103
|
+
interconnectable: { ID: 0x1007, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true },
|
|
104
|
+
smokeUnit: { ID: 0x1008, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
|
|
105
|
+
rebootedCount: { ID: 0x1009, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
|
|
106
|
+
rejoinedCount: { ID: 0x100a, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
|
|
107
|
+
reportedPackages: { ID: 0x100b, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
|
|
108
|
+
},
|
|
109
|
+
commands: {},
|
|
110
|
+
commandsResponse: {},
|
|
111
|
+
}),
|
|
112
|
+
heimanClusterIasZone: () => m.deviceAddCustomCluster("ssIasZone", {
|
|
113
|
+
ID: zigbee_herdsman_1.Zcl.Clusters.ssIasZone.ID,
|
|
114
|
+
attributes: {},
|
|
115
|
+
commands: {
|
|
116
|
+
initiateTestMode: {
|
|
117
|
+
ID: 0x02,
|
|
118
|
+
parameters: [
|
|
119
|
+
{ name: "testModeDuration", type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
|
|
120
|
+
{ name: "sensitivityLevel", type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
|
|
121
|
+
],
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
commandsResponse: {},
|
|
125
|
+
}),
|
|
126
|
+
// ModernExtend define
|
|
127
|
+
heimanClusterRadarActiveIndicatorExtend: () => {
|
|
128
|
+
const clusterName = "heimanClusterRadar";
|
|
129
|
+
const exposes = utils.exposeEndpoints(e.binary("enable_indicator", ea.ALL, true, false).withDescription("active green indicator"));
|
|
130
|
+
const fromZigbee = [
|
|
131
|
+
{
|
|
132
|
+
cluster: clusterName,
|
|
133
|
+
type: ["attributeReport", "readResponse"],
|
|
134
|
+
convert: (model, msg, publish, options, meta) => {
|
|
135
|
+
if (msg.data.enableIndicator === undefined) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const state = !!msg.data["enableIndicator"];
|
|
139
|
+
return { enable_indicator: state };
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
];
|
|
143
|
+
const toZigbee = [
|
|
144
|
+
{
|
|
145
|
+
key: ["enable_indicator"],
|
|
146
|
+
convertGet: async (entity, key, meta) => {
|
|
147
|
+
await entity.read(clusterName, ["enableIndicator"], defaultResponseOptions);
|
|
148
|
+
},
|
|
149
|
+
convertSet: async (entity, key, value, meta) => {
|
|
150
|
+
// const state = (value as Record<string, unknown>) || {};
|
|
151
|
+
const state = value ? 1 : 0;
|
|
152
|
+
await entity.write(clusterName, { enableIndicator: state }, defaultResponseOptions);
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
];
|
|
156
|
+
return { exposes: exposes, fromZigbee, toZigbee, isModernExtend: true };
|
|
66
157
|
},
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
158
|
+
heimanClusterRadarSubRegionEnableExtend: () => {
|
|
159
|
+
const clusterName = "heimanClusterRadar";
|
|
160
|
+
const exposes = utils.exposeEndpoints(e.binary("enable_sub_region_isolation", ea.ALL, true, false).withDescription("active green indicator"));
|
|
161
|
+
const fromZigbee = [
|
|
162
|
+
{
|
|
163
|
+
cluster: clusterName,
|
|
164
|
+
type: ["attributeReport", "readResponse"],
|
|
165
|
+
convert: (model, msg, publish, options, meta) => {
|
|
166
|
+
if (msg.data.enableSubRegionIsolation === undefined) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const state = !!msg.data["enableSubRegionIsolation"];
|
|
170
|
+
return { enable_sub_region_isolation: state };
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
];
|
|
174
|
+
const toZigbee = [
|
|
175
|
+
{
|
|
176
|
+
key: ["enable_sub_region_isolation"],
|
|
177
|
+
convertGet: async (entity, key, meta) => {
|
|
178
|
+
await entity.read(clusterName, ["enableSubRegionIsolation"], defaultResponseOptions);
|
|
179
|
+
},
|
|
180
|
+
convertSet: async (entity, key, value, meta) => {
|
|
181
|
+
const state = value ? 1 : 0;
|
|
182
|
+
await entity.write(clusterName, { enableSubRegionIsolation: state }, defaultResponseOptions);
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
];
|
|
186
|
+
return {
|
|
187
|
+
exposes: exposes,
|
|
188
|
+
fromZigbee,
|
|
189
|
+
toZigbee,
|
|
190
|
+
isModernExtend: true,
|
|
191
|
+
};
|
|
192
|
+
},
|
|
193
|
+
heimanClusterRadarSensitivityExtend: () => {
|
|
194
|
+
const clusterName = "heimanClusterRadar";
|
|
195
|
+
const exposes = utils.exposeEndpoints(e
|
|
196
|
+
.numeric("sensitivity", ea.ALL)
|
|
197
|
+
.withUnit("%")
|
|
198
|
+
.withValueMin(0)
|
|
199
|
+
.withValueMax(100)
|
|
200
|
+
.withDescription("Sensitivity of the radar sensor in range of 0 ~ 100%"));
|
|
201
|
+
const fromZigbee = [
|
|
202
|
+
{
|
|
203
|
+
cluster: clusterName,
|
|
204
|
+
type: ["attributeReport", "readResponse"],
|
|
205
|
+
convert: (model, msg, publish, options, meta) => {
|
|
206
|
+
let attrData = null;
|
|
207
|
+
if (msg.data.sensitivity === undefined) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
attrData = msg.data["sensitivity"];
|
|
211
|
+
return { sensitivity: attrData };
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
];
|
|
215
|
+
const toZigbee = [
|
|
216
|
+
{
|
|
217
|
+
key: ["sensitivity"],
|
|
218
|
+
convertGet: async (entity, key, meta) => {
|
|
219
|
+
await entity.read(clusterName, ["sensitivity"], defaultResponseOptions);
|
|
220
|
+
},
|
|
221
|
+
convertSet: async (entity, key, value, meta) => {
|
|
222
|
+
const state = Number(value);
|
|
223
|
+
await entity.write(clusterName, { sensitivity: state }, defaultResponseOptions);
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
];
|
|
227
|
+
return {
|
|
228
|
+
exposes: exposes,
|
|
229
|
+
fromZigbee,
|
|
230
|
+
toZigbee,
|
|
231
|
+
isModernExtend: true,
|
|
232
|
+
};
|
|
233
|
+
},
|
|
234
|
+
heimanClusterRadarCellMountedTableExtend: () => {
|
|
235
|
+
const clusterName = "heimanClusterRadar";
|
|
236
|
+
const exposes = utils.exposeEndpoints(e
|
|
237
|
+
.text("cell_mounted_table", ea.ALL)
|
|
238
|
+
.withDescription("Ceiling installation area coordinate table. Format: 'X1,X2,Y1,Y2,height'. Value range: -2000≤X1≤0, 0≤X2≤2000 -2500≤Y1≤0, 0≤Y2≤2500 2300≤height≤3000 Unit:mm"));
|
|
239
|
+
const fromZigbee = [
|
|
240
|
+
{
|
|
241
|
+
cluster: clusterName,
|
|
242
|
+
type: ["attributeReport", "readResponse"],
|
|
243
|
+
convert: (model, msg, publish, options, meta) => {
|
|
244
|
+
const result = {};
|
|
245
|
+
const value = msg.data["cellMountedTable"];
|
|
84
246
|
if (Buffer.isBuffer(value) && value.length >= 5) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
throw new Error(`Invalid cell_mounted_table data length: expected 10 bytes, got ${value.length}.`);
|
|
89
|
-
}
|
|
90
|
-
const coordinates = [
|
|
91
|
-
value.readInt16LE(0), // x1
|
|
92
|
-
value.readInt16LE(2), // y1
|
|
93
|
-
value.readInt16LE(4), // x2
|
|
94
|
-
value.readInt16LE(6), // y2
|
|
95
|
-
value.readInt16LE(8), // height
|
|
96
|
-
];
|
|
97
|
-
result.cell_mounted_table = coordinates.join(",");
|
|
98
|
-
}
|
|
99
|
-
else if (key === "wall_mounted_table") {
|
|
100
|
-
if (value.length !== 8) {
|
|
101
|
-
throw new Error(`Invalid wall_mounted_table data length: expected 8 bytes, got ${value.length}.`);
|
|
102
|
-
}
|
|
103
|
-
const coordinates = [
|
|
104
|
-
value.readInt16LE(0), // x1
|
|
105
|
-
value.readInt16LE(2), // y1
|
|
106
|
-
value.readInt16LE(4), // x2
|
|
107
|
-
value.readInt16LE(6), // height
|
|
108
|
-
];
|
|
109
|
-
result.wall_mounted_table = coordinates.join(",");
|
|
110
|
-
}
|
|
111
|
-
else if (key === "sub_region_isolation_table") {
|
|
112
|
-
if (value.length !== 12) {
|
|
113
|
-
throw new Error(`Invalid sub_region_isolation_table data length: expected 12 bytes, got ${value.length}.`);
|
|
114
|
-
}
|
|
115
|
-
const coordinates = [
|
|
116
|
-
value.readInt16LE(0), // x1
|
|
117
|
-
value.readInt16LE(2), // y1
|
|
118
|
-
value.readInt16LE(4), // x2
|
|
119
|
-
value.readInt16LE(6), // y2
|
|
120
|
-
value.readInt16LE(8), // z1
|
|
121
|
-
value.readInt16LE(10), // z2
|
|
122
|
-
];
|
|
123
|
-
result.sub_region_isolation_table = coordinates.join(",");
|
|
124
|
-
}
|
|
247
|
+
console.log(value);
|
|
248
|
+
if (value.length !== 10) {
|
|
249
|
+
throw new Error(`Invalid cell_mounted_table data length: expected 10 bytes, got ${value.length}.`);
|
|
125
250
|
}
|
|
126
|
-
|
|
127
|
-
|
|
251
|
+
const coordinates = [
|
|
252
|
+
value.readInt16LE(0), // x1
|
|
253
|
+
value.readInt16LE(2), // y1
|
|
254
|
+
value.readInt16LE(4), // x2
|
|
255
|
+
value.readInt16LE(6), // y2
|
|
256
|
+
value.readInt16LE(8), // height
|
|
257
|
+
];
|
|
258
|
+
result.cell_mounted_table = coordinates.join(",");
|
|
259
|
+
console.log(result);
|
|
260
|
+
}
|
|
261
|
+
return result;
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
];
|
|
265
|
+
const toZigbee = [
|
|
266
|
+
{
|
|
267
|
+
key: ["cell_mounted_table"],
|
|
268
|
+
convertGet: async (entity, key, meta) => {
|
|
269
|
+
await entity.read(clusterName, ["cellMountedTable"], defaultResponseOptions);
|
|
270
|
+
},
|
|
271
|
+
convertSet: async (entity, key, value, meta) => {
|
|
272
|
+
if (key === "cell_mounted_table" && value !== "") {
|
|
273
|
+
const coordinates = value.split(",").map((v) => Number.parseInt(v, 10));
|
|
274
|
+
if (coordinates.length !== 5) {
|
|
275
|
+
throw new Error("cell_mounted_table must be a string with 5 comma-separated values (e.g., '-2000,2000,-2500,2500,2300')");
|
|
276
|
+
}
|
|
277
|
+
// Range check
|
|
278
|
+
if (coordinates[0] < -2000 ||
|
|
279
|
+
coordinates[0] > 0 || // X1
|
|
280
|
+
coordinates[1] < 0 ||
|
|
281
|
+
coordinates[1] > 2000 || // X2
|
|
282
|
+
coordinates[2] < -2500 ||
|
|
283
|
+
coordinates[2] > 0 || // Y1
|
|
284
|
+
coordinates[3] < 0 ||
|
|
285
|
+
coordinates[3] > 2500 || // Y2
|
|
286
|
+
coordinates[4] < 2300 ||
|
|
287
|
+
coordinates[4] > 3000 // height
|
|
288
|
+
) {
|
|
289
|
+
throw new Error("Values out of range for Cell Mounted Table.");
|
|
290
|
+
}
|
|
291
|
+
const buffer = Buffer.alloc(10); // 10 bytes + 1 byte
|
|
292
|
+
buffer.writeInt16LE(coordinates[0], 0); // x1
|
|
293
|
+
buffer.writeInt16LE(coordinates[1], 2); // x2
|
|
294
|
+
buffer.writeInt16LE(coordinates[2], 4); // y1
|
|
295
|
+
buffer.writeInt16LE(coordinates[3], 6); // y2
|
|
296
|
+
buffer.writeInt16LE(coordinates[4], 8); // height
|
|
297
|
+
await entity.write(clusterName, { cellMountedTable: buffer }, defaultResponseOptions);
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
];
|
|
302
|
+
return {
|
|
303
|
+
exposes: exposes,
|
|
304
|
+
fromZigbee,
|
|
305
|
+
toZigbee,
|
|
306
|
+
isModernExtend: true,
|
|
307
|
+
};
|
|
308
|
+
},
|
|
309
|
+
heimanClusterRadarWallMountedTableExtend: () => {
|
|
310
|
+
const clusterName = "heimanClusterRadar";
|
|
311
|
+
const exposes = utils.exposeEndpoints(e
|
|
312
|
+
.text("wall_mounted_table", ea.ALL)
|
|
313
|
+
.withDescription("Wall-mounted installation area coordinate table. Format: 'X1,X2,Y2,height' Value range: -2000≤X1≤0, 0≤X2≤2000 200≤Y2≤4000 1500≤height≤1600 Unit:mm."));
|
|
314
|
+
const fromZigbee = [
|
|
315
|
+
{
|
|
316
|
+
cluster: clusterName,
|
|
317
|
+
type: ["attributeReport", "readResponse"],
|
|
318
|
+
convert: (model, msg, publish, options, meta) => {
|
|
319
|
+
const result = {};
|
|
320
|
+
const value = msg.data["wallMountedTable"];
|
|
321
|
+
if (Buffer.isBuffer(value) && value.length >= 5) {
|
|
322
|
+
if (value.length !== 8) {
|
|
323
|
+
throw new Error(`Invalid wall_mounted_table data length: expected 8 bytes, got ${value.length}.`);
|
|
128
324
|
}
|
|
325
|
+
const coordinates = [
|
|
326
|
+
value.readInt16LE(0), // x1
|
|
327
|
+
value.readInt16LE(2), // y1
|
|
328
|
+
value.readInt16LE(4), // x2
|
|
329
|
+
value.readInt16LE(6), // height
|
|
330
|
+
];
|
|
331
|
+
result.wall_mounted_table = coordinates.join(",");
|
|
129
332
|
}
|
|
130
|
-
|
|
131
|
-
|
|
333
|
+
return result;
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
];
|
|
337
|
+
const toZigbee = [
|
|
338
|
+
{
|
|
339
|
+
key: ["wall_mounted_table"],
|
|
340
|
+
convertGet: async (entity, key, meta) => {
|
|
341
|
+
await entity.read(clusterName, ["wallMountedTable"], defaultResponseOptions);
|
|
342
|
+
},
|
|
343
|
+
convertSet: async (entity, key, value, meta) => {
|
|
344
|
+
if (key === "wall_mounted_table" && value !== "") {
|
|
345
|
+
const coordinates = value.split(",").map((v) => Number.parseInt(v, 10));
|
|
346
|
+
if (coordinates.length !== 4) {
|
|
347
|
+
throw new Error("wall_mounted_table must be a string with 4 comma-separated values (e.g., '-2000,2000,4000,1600')");
|
|
348
|
+
}
|
|
349
|
+
if (coordinates[0] < -2000 ||
|
|
350
|
+
coordinates[0] > 0 || // X1
|
|
351
|
+
coordinates[1] < 0 ||
|
|
352
|
+
coordinates[1] > 2000 || // X2
|
|
353
|
+
coordinates[2] < 200 ||
|
|
354
|
+
coordinates[2] > 4000 || // Y2
|
|
355
|
+
coordinates[3] < 1500 ||
|
|
356
|
+
coordinates[3] > 1600 // height
|
|
357
|
+
) {
|
|
358
|
+
throw new Error("Values out of range for Wall Mounted Table.");
|
|
359
|
+
}
|
|
360
|
+
const buffer = Buffer.alloc(8); // 8 bytes + 1 byte
|
|
361
|
+
buffer.writeInt16LE(coordinates[0], 0); // x1
|
|
362
|
+
buffer.writeInt16LE(coordinates[1], 2); // x2
|
|
363
|
+
buffer.writeInt16LE(coordinates[2], 4); // y2
|
|
364
|
+
buffer.writeInt16LE(coordinates[3], 6); // height
|
|
365
|
+
await entity.write(clusterName, { wallMountedTable: buffer }, defaultResponseOptions);
|
|
132
366
|
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
|
|
367
|
+
},
|
|
368
|
+
},
|
|
369
|
+
];
|
|
370
|
+
return {
|
|
371
|
+
exposes: exposes,
|
|
372
|
+
fromZigbee,
|
|
373
|
+
toZigbee,
|
|
374
|
+
isModernExtend: true,
|
|
375
|
+
};
|
|
137
376
|
},
|
|
138
|
-
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
"
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
377
|
+
heimanClusterRadarSubRegionIsolationTableExtend: () => {
|
|
378
|
+
const clusterName = "heimanClusterRadar";
|
|
379
|
+
const exposes = utils.exposeEndpoints(e
|
|
380
|
+
.text("sub_region_isolation_table", ea.ALL)
|
|
381
|
+
.withDescription("Undetectable area coordinate table. Format: 'x1,x2,y1,y2,z1,z2'. Ranges: X1≤x1≤x2≤X2 When wall-mounted: 200≤y1≤y2≤Y2 0≤z1≤z2≤2300 Ceiling installation: Y1≤y1≤y2≤Y2 0≤z1≤z2≤height Unit:mm"));
|
|
382
|
+
const fromZigbee = [
|
|
383
|
+
{
|
|
384
|
+
cluster: clusterName,
|
|
385
|
+
type: ["attributeReport", "readResponse"],
|
|
386
|
+
convert: (model, msg, publish, options, meta) => {
|
|
387
|
+
const result = {};
|
|
388
|
+
const value = msg.data["subRegionIsolationTable"];
|
|
389
|
+
if (Buffer.isBuffer(value) && value.length >= 5) {
|
|
390
|
+
if (value.length !== 12) {
|
|
391
|
+
throw new Error(`Invalid sub_region_isolation_table data length: expected 12 bytes, got ${value.length}.`);
|
|
392
|
+
}
|
|
393
|
+
const coordinates = [
|
|
394
|
+
value.readInt16LE(0), // x1
|
|
395
|
+
value.readInt16LE(2), // y1
|
|
396
|
+
value.readInt16LE(4), // x2
|
|
397
|
+
value.readInt16LE(6), // y2
|
|
398
|
+
value.readInt16LE(8), // z1
|
|
399
|
+
value.readInt16LE(10), // z2
|
|
400
|
+
];
|
|
401
|
+
result.sub_region_isolation_table = coordinates.join(",");
|
|
402
|
+
}
|
|
403
|
+
return result;
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
];
|
|
407
|
+
const toZigbee = [
|
|
408
|
+
{
|
|
409
|
+
key: ["sub_region_isolation_table"],
|
|
410
|
+
convertGet: async (entity, key, meta) => {
|
|
411
|
+
await entity.read(clusterName, ["subRegionIsolationTable"], defaultResponseOptions);
|
|
412
|
+
},
|
|
413
|
+
convertSet: async (entity, key, value, meta) => {
|
|
414
|
+
if (key === "sub_region_isolation_table" && value !== "") {
|
|
415
|
+
const coordinates = value.split(",").map((v) => Number.parseInt(v, 10));
|
|
416
|
+
if (coordinates.length !== 6) {
|
|
417
|
+
throw new Error("sub_region_isolation_table must be a string with 6 comma-separated values (e.g., '-2000,2000,-2500,2500,2300,3000')");
|
|
418
|
+
}
|
|
419
|
+
if (coordinates[0] < -2000 ||
|
|
420
|
+
coordinates[0] > 2000 || // X1
|
|
421
|
+
coordinates[1] < -2000 ||
|
|
422
|
+
coordinates[1] > 2000 // X2
|
|
423
|
+
) {
|
|
424
|
+
throw new Error("Values out of range for Sub-Region Isolation Table.");
|
|
425
|
+
}
|
|
426
|
+
const buffer = Buffer.alloc(12); // 12 bytes + 1 byte
|
|
427
|
+
buffer.writeInt16LE(coordinates[0], 0); // x1
|
|
428
|
+
buffer.writeInt16LE(coordinates[1], 2); // x2
|
|
429
|
+
buffer.writeInt16LE(coordinates[2], 4); // y1
|
|
430
|
+
buffer.writeInt16LE(coordinates[3], 6); // y2
|
|
431
|
+
buffer.writeInt16LE(coordinates[4], 8); // z1
|
|
432
|
+
buffer.writeInt16LE(coordinates[5], 10); // z2
|
|
433
|
+
await entity.write(clusterName, { subRegionIsolationTable: buffer }, defaultResponseOptions);
|
|
434
|
+
}
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
];
|
|
438
|
+
return {
|
|
439
|
+
exposes: exposes,
|
|
440
|
+
fromZigbee,
|
|
441
|
+
toZigbee,
|
|
442
|
+
isModernExtend: true,
|
|
443
|
+
};
|
|
444
|
+
},
|
|
445
|
+
heimanClusterRadarSenseExtend: () => {
|
|
446
|
+
const clusterName = "msOccupancySensing";
|
|
447
|
+
const exposes = [
|
|
448
|
+
e.binary("occupancy", ea.STATE, true, false).withDescription("Indicates if someone is present"),
|
|
449
|
+
e.enum("sensor_status", ea.STATE, ["none", "activity", "unknown"]).withDescription("Sensor activity status"),
|
|
450
|
+
e.enum("fall_status", ea.STATE, ["normal", "fall_warning", "fall_alarm", "unknown"]).withDescription("Fall detection status"),
|
|
451
|
+
];
|
|
452
|
+
const fromZigbee = [
|
|
453
|
+
{
|
|
454
|
+
cluster: clusterName,
|
|
455
|
+
type: ["attributeReport", "readResponse"],
|
|
456
|
+
convert: (model, msg, publish, options, meta) => {
|
|
457
|
+
const result = {};
|
|
458
|
+
if (Object.hasOwn(msg.data, "occupancy")) {
|
|
459
|
+
const occupancy = msg.data.occupancy;
|
|
460
|
+
const bit0 = occupancy & 0x01; // Bit 0: Occupancy (0: no one, 1: someone)
|
|
461
|
+
const bit1to3 = (occupancy >> 1) & 0x07; // Bits 1-3: Sensor status
|
|
462
|
+
const bit4to5 = (occupancy >> 4) & 0x03; // Bits 4-5: Fall status
|
|
463
|
+
// Interprete bitmap
|
|
464
|
+
result.occupancy = bit0 === 1;
|
|
465
|
+
result.sensor_status = ["none", "activity"][bit1to3] || "unknown";
|
|
466
|
+
result.fall_status = ["normal", "fall_warning", "fall_alarm"][bit4to5] || "unknown";
|
|
467
|
+
}
|
|
468
|
+
return result;
|
|
469
|
+
},
|
|
470
|
+
},
|
|
471
|
+
];
|
|
472
|
+
return {
|
|
473
|
+
exposes: exposes,
|
|
474
|
+
fromZigbee,
|
|
475
|
+
isModernExtend: true,
|
|
476
|
+
};
|
|
477
|
+
},
|
|
478
|
+
heimanClusterLegacyIlluminanceExtend: () => {
|
|
479
|
+
const clusterName = "msIlluminanceMeasurement";
|
|
480
|
+
const exposes = utils.exposeEndpoints(e.numeric("ambient_light", ea.STATE_GET).withUnit("Lx").withDescription("ambient illuminance in lux"));
|
|
481
|
+
const fromZigbee = [
|
|
482
|
+
{
|
|
483
|
+
cluster: clusterName,
|
|
484
|
+
type: ["attributeReport", "readResponse"],
|
|
485
|
+
convert: (model, msg, publish, options, meta) => {
|
|
486
|
+
let attrData = null;
|
|
487
|
+
if (msg.data.measuredValue === undefined) {
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
attrData = msg.data["measuredValue"];
|
|
491
|
+
return { ambient_light: attrData };
|
|
492
|
+
},
|
|
493
|
+
},
|
|
494
|
+
];
|
|
495
|
+
const toZigbee = [
|
|
496
|
+
{
|
|
497
|
+
key: ["ambient_light"],
|
|
498
|
+
convertGet: async (entity, key, meta) => {
|
|
499
|
+
await entity.read(clusterName, ["measuredValue"], defaultResponseOptions);
|
|
500
|
+
},
|
|
501
|
+
},
|
|
502
|
+
];
|
|
503
|
+
return {
|
|
504
|
+
exposes: exposes,
|
|
505
|
+
fromZigbee,
|
|
506
|
+
toZigbee,
|
|
507
|
+
isModernExtend: true,
|
|
508
|
+
};
|
|
509
|
+
},
|
|
510
|
+
heimanClusterSensorFaultState: () => {
|
|
511
|
+
const clusterName = "heimanClusterSpecial";
|
|
512
|
+
const faultStateBitMap = {
|
|
513
|
+
0: "fault", // bit0
|
|
514
|
+
1: "sensor_open_circuit_fault", // bit1
|
|
515
|
+
2: "sensor_short_circuit_fault", // bit2
|
|
516
|
+
3: "sensor_pollution_fault", // bit3
|
|
517
|
+
};
|
|
518
|
+
const exposes = utils.exposeEndpoints(e.text("fault_state", ea.STATE_GET).withDescription("Device fault status (normal or fault types)."));
|
|
519
|
+
const fromZigbee = [
|
|
520
|
+
{
|
|
521
|
+
cluster: clusterName,
|
|
522
|
+
type: ["attributeReport", "readResponse"],
|
|
523
|
+
convert: (model, msg, publish, options, meta) => {
|
|
524
|
+
let attrData = null;
|
|
525
|
+
let attrValue = 0;
|
|
526
|
+
if (msg.data.sensorFaultState === undefined) {
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
attrData = msg.data["sensorFaultState"];
|
|
530
|
+
attrValue = Number(attrData);
|
|
531
|
+
const activeFaults = [];
|
|
532
|
+
for (const [bit, faultDesc] of Object.entries(faultStateBitMap)) {
|
|
533
|
+
const bitNum = Number(bit);
|
|
534
|
+
const isFault = (attrValue & (1 << bitNum)) !== 0;
|
|
535
|
+
if (isFault) {
|
|
536
|
+
activeFaults.push(faultDesc);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
const faultResult = activeFaults.length > 0 ? activeFaults.join(" | ") : "normal";
|
|
540
|
+
return { fault_state: faultResult };
|
|
541
|
+
},
|
|
542
|
+
},
|
|
543
|
+
];
|
|
544
|
+
const toZigbee = [
|
|
545
|
+
{
|
|
546
|
+
key: ["fault_state"],
|
|
547
|
+
convertGet: async (entity, key, meta) => {
|
|
548
|
+
await entity.read(clusterName, ["sensorFaultState"], defaultResponseOptions);
|
|
549
|
+
},
|
|
550
|
+
},
|
|
551
|
+
];
|
|
552
|
+
return {
|
|
553
|
+
exposes: exposes,
|
|
554
|
+
fromZigbee,
|
|
555
|
+
toZigbee,
|
|
556
|
+
isModernExtend: true,
|
|
557
|
+
};
|
|
558
|
+
},
|
|
559
|
+
heimanClusterDeviceMuteState: () => {
|
|
560
|
+
const clusterName = "heimanClusterSpecial";
|
|
561
|
+
const muteStateBitMap = {
|
|
562
|
+
0: "mute", // bit0
|
|
563
|
+
1: "alarm_mute", // bit1
|
|
564
|
+
2: "fault_mute", // bit2
|
|
565
|
+
3: "low_battery_mute", // bit3
|
|
566
|
+
};
|
|
567
|
+
const exposes = utils.exposeEndpoints(e.text("muted", ea.STATE_GET).withDescription("Device mute status (normal or mute types)."));
|
|
568
|
+
const fromZigbee = [
|
|
569
|
+
{
|
|
570
|
+
cluster: clusterName,
|
|
571
|
+
type: ["attributeReport", "readResponse"],
|
|
572
|
+
convert: (model, msg, publish, options, meta) => {
|
|
573
|
+
let attrData = null;
|
|
574
|
+
let attrValue = 0;
|
|
575
|
+
if (msg.data.deviceMuteState === undefined) {
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
attrData = msg.data["deviceMuteState"];
|
|
579
|
+
attrValue = Number(attrData);
|
|
580
|
+
const activeMutes = [];
|
|
581
|
+
for (const [bit, muteDesc] of Object.entries(muteStateBitMap)) {
|
|
582
|
+
const bitNum = Number(bit);
|
|
583
|
+
const isFault = (attrValue & (1 << bitNum)) !== 0;
|
|
584
|
+
if (isFault) {
|
|
585
|
+
activeMutes.push(muteDesc);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
const muteResult = activeMutes.length > 0 ? activeMutes.join(" | ") : "normal";
|
|
589
|
+
return { Muted: muteResult };
|
|
590
|
+
},
|
|
591
|
+
},
|
|
592
|
+
];
|
|
593
|
+
const toZigbee = [
|
|
594
|
+
{
|
|
595
|
+
key: ["muted"],
|
|
596
|
+
convertGet: async (entity, key, meta) => {
|
|
597
|
+
await entity.read(clusterName, ["deviceMuteState"], defaultResponseOptions);
|
|
598
|
+
},
|
|
599
|
+
},
|
|
600
|
+
];
|
|
601
|
+
return {
|
|
602
|
+
exposes: exposes,
|
|
603
|
+
fromZigbee,
|
|
604
|
+
toZigbee,
|
|
605
|
+
isModernExtend: true,
|
|
606
|
+
};
|
|
607
|
+
},
|
|
608
|
+
heimanClusterIndicatorLight: () => {
|
|
609
|
+
const clusterName = "heimanClusterSpecial";
|
|
610
|
+
const exposes = utils.exposeEndpoints(e.binary("heartbeat_indicator", ea.ALL, true, false).withDescription("active green indicator"));
|
|
611
|
+
const fromZigbee = [
|
|
612
|
+
{
|
|
613
|
+
cluster: clusterName,
|
|
614
|
+
type: ["attributeReport", "readResponse"],
|
|
615
|
+
convert: (model, msg, publish, options, meta) => {
|
|
616
|
+
if (msg.data.indicatorLightLevelControlOf1 === undefined) {
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
const state = !!msg.data["indicatorLightLevelControlOf1"];
|
|
620
|
+
return { heartbeat_indicator: state };
|
|
621
|
+
},
|
|
622
|
+
},
|
|
623
|
+
];
|
|
624
|
+
const toZigbee = [
|
|
625
|
+
{
|
|
626
|
+
key: ["heartbeat_indicator"],
|
|
627
|
+
convertGet: async (entity, key, meta) => {
|
|
628
|
+
await entity.read(clusterName, ["indicatorLightLevelControlOf1"], defaultResponseOptions);
|
|
629
|
+
},
|
|
630
|
+
convertSet: async (entity, key, value, meta) => {
|
|
631
|
+
// const state = (value as Record<string, unknown>) || {};
|
|
632
|
+
const state = value ? 1 : 0;
|
|
633
|
+
await entity.write(clusterName, { indicatorLightLevelControlOf1: state }, defaultResponseOptions);
|
|
634
|
+
},
|
|
635
|
+
},
|
|
636
|
+
];
|
|
637
|
+
return {
|
|
638
|
+
exposes: exposes,
|
|
639
|
+
fromZigbee,
|
|
640
|
+
toZigbee,
|
|
641
|
+
isModernExtend: true,
|
|
642
|
+
};
|
|
643
|
+
},
|
|
644
|
+
heimanClusterSensorInterconnectable: () => {
|
|
645
|
+
const clusterName = "heimanClusterSpecial";
|
|
646
|
+
const exposes = utils.exposeEndpoints(e.binary("interconnectable", ea.STATE_GET, true, false).withDescription("used for interconnection automation."));
|
|
647
|
+
const fromZigbee = [
|
|
648
|
+
{
|
|
649
|
+
cluster: clusterName,
|
|
650
|
+
type: ["attributeReport", "readResponse"],
|
|
651
|
+
convert: (model, msg, publish, options, meta) => {
|
|
652
|
+
if (msg.data.interconnectable === undefined) {
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
const state = !!msg.data["interconnectable"];
|
|
656
|
+
return { interconnectable: state };
|
|
657
|
+
},
|
|
658
|
+
},
|
|
659
|
+
];
|
|
660
|
+
const toZigbee = [
|
|
661
|
+
{
|
|
662
|
+
key: ["interconnectable"],
|
|
663
|
+
convertGet: async (entity, key, meta) => {
|
|
664
|
+
await entity.read(clusterName, ["interconnectable"], defaultResponseOptions);
|
|
665
|
+
},
|
|
666
|
+
},
|
|
667
|
+
];
|
|
668
|
+
return {
|
|
669
|
+
exposes: exposes,
|
|
670
|
+
fromZigbee,
|
|
671
|
+
toZigbee,
|
|
672
|
+
isModernExtend: true,
|
|
673
|
+
};
|
|
674
|
+
},
|
|
675
|
+
iasZoneInitiateTestMode: () => {
|
|
676
|
+
const exposes = utils.exposeEndpoints(e.enum("trigger_selftest", ea.SET, ["test"]).withDescription("Trigger smoke alarm self-check test."));
|
|
677
|
+
const toZigbee = [
|
|
678
|
+
{
|
|
679
|
+
key: ["trigger_selftest"],
|
|
680
|
+
convertSet: async (entity, key, value, meta) => {
|
|
681
|
+
const testMode = {
|
|
682
|
+
testModeDuration: 0x01,
|
|
683
|
+
currentZoneSensitivityLevel: 0x01,
|
|
684
|
+
};
|
|
685
|
+
await entity.command("ssIasZone", "initTestMode", testMode);
|
|
686
|
+
return { state: { [key]: value } };
|
|
687
|
+
},
|
|
688
|
+
},
|
|
689
|
+
];
|
|
690
|
+
return {
|
|
691
|
+
exposes: exposes,
|
|
692
|
+
fromZigbee: [],
|
|
693
|
+
toZigbee,
|
|
694
|
+
isModernExtend: true,
|
|
695
|
+
};
|
|
696
|
+
},
|
|
697
|
+
iasWarningDeviceControl: (args) => {
|
|
698
|
+
const defaultModes = Object.keys(iasWarningMode);
|
|
699
|
+
const displayModes = args?.warningMode ?? defaultModes;
|
|
700
|
+
const invalidModes = displayModes.filter((m) => !defaultModes.includes(m));
|
|
701
|
+
if (invalidModes.length > 0) {
|
|
702
|
+
throw new Error(`Invalid alarm mode: ${invalidModes.join(", ")},
|
|
703
|
+
Legal values: ${defaultModes.join(", ")}`);
|
|
704
|
+
}
|
|
705
|
+
// biome-ignore lint/correctness/noUnusedVariables: In the future use.
|
|
706
|
+
const level = { low: 0, medium: 1, high: 2, very_high: 3 };
|
|
707
|
+
// biome-ignore lint/correctness/noUnusedVariables: In the future use.
|
|
708
|
+
const strobeLevel = { low: 0, medium: 1, high: 2, very_high: 3 };
|
|
709
|
+
const exposes = utils.exposeEndpoints(e
|
|
710
|
+
.composite("warning_control", "warning_control", ea.SET)
|
|
711
|
+
.withDescription("Make the device trigger an alarm.")
|
|
712
|
+
.withFeature(e.enum("mode", ea.SET, displayModes).withDescription("Mode of the warning (sound effect)"))
|
|
713
|
+
.withFeature(e.numeric("duration", ea.SET).withUnit("s").withDescription("Duration in seconds of the alarm")));
|
|
714
|
+
const toZigbee = [
|
|
715
|
+
{
|
|
716
|
+
key: ["warning_control"],
|
|
717
|
+
convertSet: async (entity, key, value, meta) => {
|
|
718
|
+
const warningModeKey = "mode";
|
|
719
|
+
const warningDurationKey = "duration";
|
|
720
|
+
const warningModeStr = value[warningModeKey];
|
|
721
|
+
const warningDurationValue = Number(value[warningDurationKey]);
|
|
722
|
+
const warningModeValue = iasWarningMode[warningModeStr];
|
|
723
|
+
if (warningModeValue === undefined) {
|
|
724
|
+
throw new Error(`Invalid warning mode: ${invalidModes.join(", ")}, Valid modes:${defaultModes.join(", ")}`);
|
|
725
|
+
}
|
|
726
|
+
if (Number.isNaN(warningDurationValue) || warningDurationValue < 0) {
|
|
727
|
+
throw new Error(`Invalid duration: ${warningDurationValue}. Must be a non-negative number.`);
|
|
728
|
+
}
|
|
729
|
+
const values = {
|
|
730
|
+
mode: warningModeValue,
|
|
731
|
+
level: warningModeValue ? 1 : 0,
|
|
732
|
+
strobe: false,
|
|
733
|
+
duration: warningDurationValue,
|
|
734
|
+
strobeDutyCycle: 0,
|
|
735
|
+
strobeLevel: 0,
|
|
736
|
+
};
|
|
737
|
+
if (Array.isArray(meta.mapped))
|
|
738
|
+
throw new Error("Not supported for groups");
|
|
739
|
+
const info = (values.mode << 4) + ((values.strobe ? 1 : 0) << 2) + values.level;
|
|
740
|
+
await entity.command("ssIasWd", "startWarning", {
|
|
741
|
+
startwarninginfo: info,
|
|
742
|
+
warningduration: values.duration,
|
|
743
|
+
strobedutycycle: values.strobeDutyCycle,
|
|
744
|
+
strobelevel: values.strobeLevel,
|
|
745
|
+
}, utils.getOptions(meta.mapped, entity));
|
|
746
|
+
},
|
|
747
|
+
},
|
|
748
|
+
];
|
|
749
|
+
return {
|
|
750
|
+
exposes: exposes,
|
|
751
|
+
fromZigbee: [],
|
|
752
|
+
toZigbee,
|
|
753
|
+
isModernExtend: true,
|
|
754
|
+
};
|
|
755
|
+
},
|
|
756
|
+
iasWarningDeviceMute: () => {
|
|
757
|
+
const exposes = utils.exposeEndpoints(e.enum("temporary_mute", ea.SET, ["mute"]).withDescription("temporarily mute smoke alarm but please ensure there is no real fire."));
|
|
758
|
+
const toZigbee = [
|
|
759
|
+
{
|
|
760
|
+
key: ["temporary_mute"],
|
|
761
|
+
convertSet: async (entity, key, value, meta) => {
|
|
762
|
+
const values = {
|
|
763
|
+
mode: 0,
|
|
764
|
+
level: 0,
|
|
765
|
+
strobe: false,
|
|
766
|
+
duration: 0,
|
|
767
|
+
strobeDutyCycle: 0,
|
|
768
|
+
strobeLevel: 0,
|
|
769
|
+
};
|
|
770
|
+
if (Array.isArray(meta.mapped))
|
|
771
|
+
throw new Error("Not supported for groups");
|
|
772
|
+
const info = (values.mode << 4) + ((values.strobe ? 1 : 0) << 2) + values.level;
|
|
773
|
+
await entity.command("ssIasWd", "startWarning", {
|
|
774
|
+
startwarninginfo: info,
|
|
775
|
+
warningduration: values.duration,
|
|
776
|
+
strobedutycycle: values.strobeDutyCycle,
|
|
777
|
+
strobelevel: values.strobeLevel,
|
|
778
|
+
}, utils.getOptions(meta.mapped, entity));
|
|
779
|
+
},
|
|
780
|
+
},
|
|
781
|
+
];
|
|
782
|
+
return {
|
|
783
|
+
exposes: exposes,
|
|
784
|
+
fromZigbee: [],
|
|
785
|
+
toZigbee,
|
|
786
|
+
isModernExtend: true,
|
|
787
|
+
};
|
|
258
788
|
},
|
|
259
789
|
};
|
|
260
790
|
exports.definitions = [
|
|
@@ -480,7 +1010,7 @@ exports.definitions = [
|
|
|
480
1010
|
},
|
|
481
1011
|
{
|
|
482
1012
|
zigbeeModel: ["DOOR_TPV13", "DOOR_TPV12"],
|
|
483
|
-
model: "
|
|
1013
|
+
model: "Heiman-M1",
|
|
484
1014
|
vendor: "Heiman",
|
|
485
1015
|
description: "Door sensor",
|
|
486
1016
|
fromZigbee: [fz.ias_contact_alarm_1],
|
|
@@ -488,7 +1018,7 @@ exports.definitions = [
|
|
|
488
1018
|
exposes: [e.contact(), e.battery_low(), e.tamper()],
|
|
489
1019
|
},
|
|
490
1020
|
{
|
|
491
|
-
zigbeeModel: ["WaterSensor-N", "WaterSensor-EM", "WaterSensor-N-3.0", "WaterSensor-EF-3.0", "
|
|
1021
|
+
zigbeeModel: ["WaterSensor-N", "WaterSensor-EM", "WaterSensor-N-3.0", "WaterSensor-EF-3.0", "WATER_TPV13"],
|
|
492
1022
|
model: "HS1WL/HS3WL",
|
|
493
1023
|
vendor: "Heiman",
|
|
494
1024
|
description: "Water leakage sensor",
|
|
@@ -502,6 +1032,22 @@ exports.definitions = [
|
|
|
502
1032
|
},
|
|
503
1033
|
exposes: [e.water_leak(), e.battery_low(), e.tamper(), e.battery()],
|
|
504
1034
|
},
|
|
1035
|
+
{
|
|
1036
|
+
zigbeeModel: ["WaterSensor2-EF-3.0"],
|
|
1037
|
+
model: "HS2WL",
|
|
1038
|
+
vendor: "Heiman",
|
|
1039
|
+
description: "Water leakage sensor",
|
|
1040
|
+
fromZigbee: [],
|
|
1041
|
+
toZigbee: [],
|
|
1042
|
+
extend: [m.iasZoneAlarm({ zoneType: "water_leak", zoneAttributes: ["alarm_1"] }), m.temperature(), m.battery({ lowStatus: true })],
|
|
1043
|
+
configure: async (device, coordinatorEndpoint) => {
|
|
1044
|
+
const endpoint = device.getEndpoint(1);
|
|
1045
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ["genPowerCfg", "msTemperatureMeasurement"]);
|
|
1046
|
+
await reporting.batteryPercentageRemaining(endpoint);
|
|
1047
|
+
await endpoint.read("genPowerCfg", ["batteryPercentageRemaining"]);
|
|
1048
|
+
await endpoint.read("msTemperatureMeasurement", ["measuredValue"]);
|
|
1049
|
+
},
|
|
1050
|
+
},
|
|
505
1051
|
{
|
|
506
1052
|
fingerprint: [{ modelID: "RC-N", manufacturerName: "HEIMAN" }],
|
|
507
1053
|
model: "HS1RC-N",
|
|
@@ -849,7 +1395,7 @@ exports.definitions = [
|
|
|
849
1395
|
await heiman.configureReporting.tvocMeasuredValue(endpoint);
|
|
850
1396
|
await heiman.configureReporting.aqiMeasuredValue(endpoint);
|
|
851
1397
|
await endpoint.read("genPowerCfg", ["batteryPercentageRemaining"]);
|
|
852
|
-
// Seems that it is bug in
|
|
1398
|
+
// Seems that it is bug in Heiman, device does not asks for the time with binding
|
|
853
1399
|
// So, we need to write time during configure
|
|
854
1400
|
const time = Math.round((Date.now() - constants.OneJanuary2000) / 1000);
|
|
855
1401
|
// Time-master + synchronised
|
|
@@ -1077,67 +1623,86 @@ exports.definitions = [
|
|
|
1077
1623
|
vendor: "Heiman",
|
|
1078
1624
|
description: "Fall Detection Sensor",
|
|
1079
1625
|
extend: [
|
|
1080
|
-
m.
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
},
|
|
1104
|
-
commands: {},
|
|
1105
|
-
commandsResponse: {},
|
|
1626
|
+
// m.occupancy(),
|
|
1627
|
+
heimanExtend.heimanClusterRadar(),
|
|
1628
|
+
heimanExtend.heimanClusterRadarActiveIndicatorExtend(),
|
|
1629
|
+
heimanExtend.heimanClusterRadarSubRegionEnableExtend(),
|
|
1630
|
+
heimanExtend.heimanClusterRadarSenseExtend(),
|
|
1631
|
+
heimanExtend.heimanClusterRadarCellMountedTableExtend(),
|
|
1632
|
+
heimanExtend.heimanClusterRadarWallMountedTableExtend(),
|
|
1633
|
+
heimanExtend.heimanClusterRadarSubRegionIsolationTableExtend(),
|
|
1634
|
+
m.enumLookup({
|
|
1635
|
+
name: "sensitivity",
|
|
1636
|
+
lookup: { Off: 0, LowSensitivity: 1, HighSensitivity: 2 },
|
|
1637
|
+
cluster: "heimanClusterRadar",
|
|
1638
|
+
attribute: { ID: 0xf002, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
|
|
1639
|
+
description: "0: Off, 1: Low sensitivity, 2: High sensitivity",
|
|
1640
|
+
access: "ALL",
|
|
1641
|
+
}),
|
|
1642
|
+
m.enumLookup({
|
|
1643
|
+
name: "installation_method",
|
|
1644
|
+
lookup: { WallMounted: 0, Ceiling: 1, RotateCeiling45: 2 },
|
|
1645
|
+
cluster: "heimanClusterRadar",
|
|
1646
|
+
attribute: { ID: 0xf007, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
|
|
1647
|
+
description: "0: Wall-mounted, 1: Ceiling, 2: Rotate ceiling 45°",
|
|
1648
|
+
access: "ALL",
|
|
1106
1649
|
}),
|
|
1107
1650
|
],
|
|
1108
|
-
fromZigbee: [fz.identify
|
|
1109
|
-
toZigbee: [
|
|
1651
|
+
fromZigbee: [fz.identify],
|
|
1652
|
+
toZigbee: [],
|
|
1110
1653
|
ota: true,
|
|
1111
|
-
exposes: [
|
|
1112
|
-
e.binary("occupancy", ea.STATE, true, false).withDescription("Indicates if someone is present"),
|
|
1113
|
-
e.enum("sensor_status", ea.STATE, ["none", "activity", "unknown"]).withDescription("Sensor activity status"),
|
|
1114
|
-
e.enum("fall_status", ea.STATE, ["normal", "fall_warning", "fall_alarm", "unknown"]).withDescription("Fall detection status"),
|
|
1115
|
-
e.enum("enable_indicator", ea.ALL, [0, 1]).withDescription("0: Off, 1: Enable"),
|
|
1116
|
-
e.enum("sensitivity", ea.ALL, [0, 1, 2]).withDescription("0: Off, 1: Low sensitivity, 2: High sensitivity"),
|
|
1117
|
-
e.enum("enable_sub_region_isolation", ea.ALL, [0, 1]).withDescription("0: Disable, 1: Enable"),
|
|
1118
|
-
e.enum("installation_method", ea.ALL, [0, 1, 2]).withDescription("0: Wall-mounted, 1: Ceiling, 2: Rotate ceiling 45°"),
|
|
1119
|
-
exposes
|
|
1120
|
-
.text("cell_mounted_table", ea.ALL)
|
|
1121
|
-
.withDescription("Ceiling installation area coordinate table. Format: 'X1,X2,Y1,Y2,height'. Value range: -2000≤X1≤0, 0≤X2≤2000 -2500≤Y1≤0, 0≤Y2≤2500 2300≤height≤3000 Unit:mm"),
|
|
1122
|
-
exposes
|
|
1123
|
-
.text("wall_mounted_table", ea.ALL)
|
|
1124
|
-
.withDescription("Wall-mounted installation area coordinate table. Format: 'X1,X2,Y2,height' Value range: -2000≤X1≤0, 0≤X2≤2000 200≤Y2≤4000 1500≤height≤1600 Unit:mm."),
|
|
1125
|
-
exposes
|
|
1126
|
-
.text("sub_region_isolation_table", ea.ALL)
|
|
1127
|
-
.withDescription("Undetectable area coordinate table. Format: 'x1,x2,y1,y2,z1,z2'. Ranges: X1≤x1≤x2≤X2 When wall-mounted: 200≤y1≤y2≤Y2 0≤z1≤z2≤2300 Ceiling installation: Y1≤y1≤y2≤Y2 0≤z1≤z2≤height Unit:mm"),
|
|
1128
|
-
],
|
|
1654
|
+
exposes: [],
|
|
1129
1655
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1130
1656
|
const endpoint = device.getEndpoint(1);
|
|
1131
|
-
await reporting.bind(endpoint, coordinatorEndpoint, ["msOccupancySensing", "
|
|
1657
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ["msOccupancySensing", "heimanClusterRadar"]);
|
|
1132
1658
|
await reporting.occupancy(endpoint);
|
|
1133
|
-
await endpoint.read("
|
|
1134
|
-
"
|
|
1135
|
-
"
|
|
1136
|
-
"
|
|
1659
|
+
await endpoint.read("heimanClusterRadar", [
|
|
1660
|
+
"cellMountedTable",
|
|
1661
|
+
"wallMountedTable",
|
|
1662
|
+
"subRegionIsolationTable",
|
|
1137
1663
|
]);
|
|
1138
1664
|
},
|
|
1139
1665
|
endpoint: (device) => ({ default: 1 }),
|
|
1140
1666
|
},
|
|
1667
|
+
{
|
|
1668
|
+
zigbeeModel: ["HS8OS-EF1-3.0"],
|
|
1669
|
+
model: "HS8OS-EF1-3.0",
|
|
1670
|
+
vendor: "Heiman",
|
|
1671
|
+
description: "Human presence sensor",
|
|
1672
|
+
extend: [
|
|
1673
|
+
m.occupancy(),
|
|
1674
|
+
heimanExtend.heimanClusterRadar(),
|
|
1675
|
+
heimanExtend.heimanClusterRadarActiveIndicatorExtend(),
|
|
1676
|
+
heimanExtend.heimanClusterRadarSensitivityExtend(),
|
|
1677
|
+
heimanExtend.heimanClusterLegacyIlluminanceExtend(),
|
|
1678
|
+
m.numeric({
|
|
1679
|
+
name: "radar_delay_time",
|
|
1680
|
+
cluster: 0x0406,
|
|
1681
|
+
attribute: { ID: 0x0020, type: 0x21 },
|
|
1682
|
+
description: "Occupied to unoccupied delay",
|
|
1683
|
+
valueMin: 60,
|
|
1684
|
+
valueMax: 3600,
|
|
1685
|
+
access: "ALL",
|
|
1686
|
+
}),
|
|
1687
|
+
],
|
|
1688
|
+
fromZigbee: [],
|
|
1689
|
+
toZigbee: [],
|
|
1690
|
+
ota: true,
|
|
1691
|
+
exposes: [],
|
|
1692
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1693
|
+
const endpoint = device.getEndpoint(1);
|
|
1694
|
+
await reporting.bind(endpoint, coordinatorEndpoint, [
|
|
1695
|
+
"msOccupancySensing",
|
|
1696
|
+
"msIlluminanceMeasurement",
|
|
1697
|
+
"heimanClusterRadar",
|
|
1698
|
+
"haDiagnostic",
|
|
1699
|
+
]);
|
|
1700
|
+
await endpoint.read("msIlluminanceMeasurement", ["measuredValue"]);
|
|
1701
|
+
await endpoint.read("msOccupancySensing", ["ultrasonicOToUDelay"]);
|
|
1702
|
+
await endpoint.read("heimanClusterRadar", [0xf001, 0xf002], { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.HEIMAN_TECHNOLOGY_CO_LTD });
|
|
1703
|
+
},
|
|
1704
|
+
endpoint: (device) => ({ default: 1 }),
|
|
1705
|
+
},
|
|
1141
1706
|
{
|
|
1142
1707
|
fingerprint: [{ modelID: "HS2AQ-EF-3.0", manufacturerName: "HEIMAN" }],
|
|
1143
1708
|
model: "HS2AQ-EF-3.0",
|
|
@@ -1215,5 +1780,132 @@ exports.definitions = [
|
|
|
1215
1780
|
},
|
|
1216
1781
|
exposes: [e.temperature(), e.pm25(), e.hcho(), e.aqi(), e.pm10()],
|
|
1217
1782
|
},
|
|
1783
|
+
{
|
|
1784
|
+
zigbeeModel: ["HS1SA-EF-3.0"],
|
|
1785
|
+
model: "HS1SA-E",
|
|
1786
|
+
vendor: "Heiman",
|
|
1787
|
+
description: "Smoke detector",
|
|
1788
|
+
fromZigbee: [fz.ias_smoke_alarm_1, fz.battery],
|
|
1789
|
+
toZigbee: [tz.warning],
|
|
1790
|
+
configure: async (device, coordinatorEndpoint) => {
|
|
1791
|
+
const endpoint = device.getEndpoint(1);
|
|
1792
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ["genPowerCfg", 0xfc90]);
|
|
1793
|
+
await reporting.batteryPercentageRemaining(endpoint);
|
|
1794
|
+
await endpoint.read("ssIasZone", ["zoneStatus", "zoneState", "iasCieAddr", "zoneId"]);
|
|
1795
|
+
await endpoint.read("heimanClusterSpecial", [0x0002, 0x009, 0x1004, 0x1007, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b], {
|
|
1796
|
+
manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.HEIMAN_TECHNOLOGY_CO_LTD,
|
|
1797
|
+
});
|
|
1798
|
+
},
|
|
1799
|
+
exposes: [],
|
|
1800
|
+
extend: [
|
|
1801
|
+
m.battery(),
|
|
1802
|
+
m.temperature(),
|
|
1803
|
+
m.iasZoneAlarm({ zoneType: "smoke", zoneAttributes: ["alarm_1", "battery_low", "test"] }),
|
|
1804
|
+
heimanExtend.heimanClusterSpecial(),
|
|
1805
|
+
heimanExtend.heimanClusterSensorFaultState(),
|
|
1806
|
+
heimanExtend.heimanClusterDeviceMuteState(),
|
|
1807
|
+
heimanExtend.iasZoneInitiateTestMode(),
|
|
1808
|
+
heimanExtend.iasWarningDeviceMute(),
|
|
1809
|
+
heimanExtend.heimanClusterIndicatorLight(),
|
|
1810
|
+
heimanExtend.heimanClusterSensorInterconnectable(),
|
|
1811
|
+
m.numeric({
|
|
1812
|
+
name: "smoke_level",
|
|
1813
|
+
unit: "",
|
|
1814
|
+
scale: 0.1,
|
|
1815
|
+
valueMin: 0,
|
|
1816
|
+
valueMax: 20,
|
|
1817
|
+
cluster: "heimanClusterSpecial",
|
|
1818
|
+
attribute: { ID: 0x0016, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
|
|
1819
|
+
description: "smoke level",
|
|
1820
|
+
access: "STATE_GET",
|
|
1821
|
+
}),
|
|
1822
|
+
m.enumLookup({
|
|
1823
|
+
name: "smoke_unit",
|
|
1824
|
+
lookup: { "dB/m": 0, "%ft OBS": 1 },
|
|
1825
|
+
cluster: "heimanClusterSpecial",
|
|
1826
|
+
attribute: { ID: 0x0018, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
|
|
1827
|
+
description: "smoke level unit",
|
|
1828
|
+
access: "STATE_GET",
|
|
1829
|
+
}),
|
|
1830
|
+
m.enumLookup({
|
|
1831
|
+
name: "chamber_contamination",
|
|
1832
|
+
lookup: { normal: 0, light_contamination: 1, medium_contamication: 2, critical_contamication: 3 },
|
|
1833
|
+
cluster: "heimanClusterSpecial",
|
|
1834
|
+
attribute: { ID: 0x0017, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
|
|
1835
|
+
description: "it indicates that how serious the smoke chamber get contaminated.",
|
|
1836
|
+
access: "STATE_GET",
|
|
1837
|
+
}),
|
|
1838
|
+
m.enumLookup({
|
|
1839
|
+
name: "siren_for_automation_only",
|
|
1840
|
+
lookup: { stop: 0, smoke_siren: 1, co_siren: 2 },
|
|
1841
|
+
cluster: "heimanClusterSpecial",
|
|
1842
|
+
attribute: { ID: 0x0012, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
|
|
1843
|
+
description: "siren effect",
|
|
1844
|
+
access: "ALL",
|
|
1845
|
+
}),
|
|
1846
|
+
m.numeric({
|
|
1847
|
+
name: "reported_packages",
|
|
1848
|
+
unit: "",
|
|
1849
|
+
valueMin: 0,
|
|
1850
|
+
valueMax: 60000,
|
|
1851
|
+
cluster: "heimanClusterSpecial",
|
|
1852
|
+
attribute: { ID: 0x001b, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
|
|
1853
|
+
description: "for diagnostic purpose, how many zigbee packages has the reported in a day.",
|
|
1854
|
+
access: "STATE_GET",
|
|
1855
|
+
}),
|
|
1856
|
+
m.numeric({
|
|
1857
|
+
name: "rejoin_count",
|
|
1858
|
+
unit: "",
|
|
1859
|
+
valueMin: 0,
|
|
1860
|
+
valueMax: 60000,
|
|
1861
|
+
cluster: "heimanClusterSpecial",
|
|
1862
|
+
attribute: { ID: 0x001a, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
|
|
1863
|
+
description: "for diagnostic purpose, how many times has the product rejoined to zigbee network.",
|
|
1864
|
+
access: "STATE_GET",
|
|
1865
|
+
}),
|
|
1866
|
+
m.numeric({
|
|
1867
|
+
name: "reboot_count",
|
|
1868
|
+
unit: "",
|
|
1869
|
+
valueMin: 0,
|
|
1870
|
+
valueMax: 60000,
|
|
1871
|
+
cluster: "heimanClusterSpecial",
|
|
1872
|
+
attribute: { ID: 0x0019, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
|
|
1873
|
+
description: "for diagnostic purpose, how many times has the product rebooted.",
|
|
1874
|
+
access: "STATE_GET",
|
|
1875
|
+
}),
|
|
1876
|
+
],
|
|
1877
|
+
ota: true,
|
|
1878
|
+
},
|
|
1879
|
+
{
|
|
1880
|
+
zigbeeModel: ["WarningDevice-EFA1-3.0"],
|
|
1881
|
+
model: "HS2WD-EF",
|
|
1882
|
+
vendor: "Heiman",
|
|
1883
|
+
description: "Smart siren",
|
|
1884
|
+
fromZigbee: [fz.battery, fz.ias_wd],
|
|
1885
|
+
toZigbee: [tz.warning, tz.ias_max_duration],
|
|
1886
|
+
meta: { disableDefaultResponse: true },
|
|
1887
|
+
configure: async (device, coordinatorEndpoint) => {
|
|
1888
|
+
const endpoint = device.getEndpoint(1);
|
|
1889
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ["genPowerCfg"]);
|
|
1890
|
+
await reporting.batteryPercentageRemaining(endpoint);
|
|
1891
|
+
await endpoint.read("ssIasWd", ["maxDuration"]);
|
|
1892
|
+
},
|
|
1893
|
+
exposes: [
|
|
1894
|
+
e.battery(),
|
|
1895
|
+
e
|
|
1896
|
+
.numeric("max_duration", ea.ALL)
|
|
1897
|
+
.withUnit("s")
|
|
1898
|
+
.withValueMin(0)
|
|
1899
|
+
.withValueMax(1800)
|
|
1900
|
+
.withDescription("Max duration of Siren")
|
|
1901
|
+
.withCategory("config"),
|
|
1902
|
+
e
|
|
1903
|
+
.warning()
|
|
1904
|
+
.removeFeature("strobe_level")
|
|
1905
|
+
.removeFeature("mode")
|
|
1906
|
+
.withFeature(e.enum("mode", ea.SET, ["stop", "burglar", "fire", "emergency"]).withDescription("Mode of the warning(sound effect)")),
|
|
1907
|
+
],
|
|
1908
|
+
ota: true,
|
|
1909
|
+
},
|
|
1218
1910
|
];
|
|
1219
1911
|
//# sourceMappingURL=heiman.js.map
|