zigbee-herdsman-converters 14.0.566 → 14.0.569
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/devices/adeo.js +7 -0
- package/devices/ctm.js +961 -0
- package/devices/evology.js +24 -0
- package/devices/heiman.js +2 -1
- package/devices/hive.js +3 -2
- package/devices/ledvance.js +8 -0
- package/devices/tuya.js +1 -0
- package/devices/ubisys.js +25 -12
- package/lib/utils.js +2 -2
- package/package.json +1 -1
package/devices/adeo.js
CHANGED
|
@@ -29,6 +29,13 @@ module.exports = [
|
|
|
29
29
|
description: 'ENKI LEXMAN E27 LED white filament 1055 lumen',
|
|
30
30
|
extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
|
|
31
31
|
},
|
|
32
|
+
{
|
|
33
|
+
zigbeeModel: ['ZBEK-9'],
|
|
34
|
+
model: 'IA-CDZFB2AA007NA-MZN-02',
|
|
35
|
+
vendor: 'ADEO',
|
|
36
|
+
description: 'ENKI LEXMAN E27 LED white',
|
|
37
|
+
extend: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 454]}),
|
|
38
|
+
},
|
|
32
39
|
{
|
|
33
40
|
zigbeeModel: ['ZBEK-4'],
|
|
34
41
|
model: 'IM-CDZDGAAA0005KA_MAN',
|
package/devices/ctm.js
ADDED
|
@@ -0,0 +1,961 @@
|
|
|
1
|
+
const fz = require('../converters/fromZigbee');
|
|
2
|
+
const tz = require('../converters/toZigbee');
|
|
3
|
+
const exposes = require('../lib/exposes');
|
|
4
|
+
const reporting = require('../lib/reporting');
|
|
5
|
+
const constants = require('../lib/constants');
|
|
6
|
+
const utils = require('../lib/utils');
|
|
7
|
+
const e = exposes.presets;
|
|
8
|
+
const ea = exposes.access;
|
|
9
|
+
|
|
10
|
+
const dataType = {
|
|
11
|
+
boolean: 16,
|
|
12
|
+
uint8: 32,
|
|
13
|
+
uint16: 33,
|
|
14
|
+
int8: 40,
|
|
15
|
+
int16: 41,
|
|
16
|
+
enum8: 48,
|
|
17
|
+
charStr: 66,
|
|
18
|
+
ieeeAddr: 240,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const fzLocal = {
|
|
22
|
+
ctm_device_mode: {
|
|
23
|
+
cluster: 'genOnOff',
|
|
24
|
+
type: ['attributeReport', 'readResponse'],
|
|
25
|
+
convert: (model, msg, publish, options, meta) => {
|
|
26
|
+
const result = {};
|
|
27
|
+
const data = msg.data;
|
|
28
|
+
if (data.hasOwnProperty(0x2200)) {
|
|
29
|
+
const deviceModeLookup = {0: 'astro_clock', 1: 'timer', 2: 'daily_timer', 3: 'weekly_timer'};
|
|
30
|
+
result.device_mode = deviceModeLookup[data[0x2200]];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return result;
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
ctm_device_enabled: {
|
|
37
|
+
cluster: 'genOnOff',
|
|
38
|
+
type: ['attributeReport', 'readResponse'],
|
|
39
|
+
convert: (model, msg, publish, options, meta) => {
|
|
40
|
+
const result = {};
|
|
41
|
+
const data = msg.data;
|
|
42
|
+
if (data.hasOwnProperty(0x2201)) {
|
|
43
|
+
result.device_enabled = data[0x2201] ? 'ON' : 'OFF';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return result;
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
ctm_child_lock: {
|
|
50
|
+
cluster: 'genOnOff',
|
|
51
|
+
type: ['attributeReport', 'readResponse'],
|
|
52
|
+
convert: (model, msg, publish, options, meta) => {
|
|
53
|
+
const result = {};
|
|
54
|
+
const data = msg.data;
|
|
55
|
+
if (data.hasOwnProperty(0x2202)) {
|
|
56
|
+
result.child_lock = data[0x2202] ? 'locked' : 'unlocked';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return result;
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
ctm_current_flag: {
|
|
63
|
+
cluster: 'genOnOff',
|
|
64
|
+
type: ['attributeReport', 'readResponse'],
|
|
65
|
+
convert: (model, msg, publish, options, meta) => {
|
|
66
|
+
const result = {};
|
|
67
|
+
const data = msg.data;
|
|
68
|
+
if (data.hasOwnProperty(0x5000)) {
|
|
69
|
+
result.current_flag = data[0x5000];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return result;
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
ctm_temperature_offset: {
|
|
76
|
+
cluster: 'msTemperatureMeasurement',
|
|
77
|
+
type: ['attributeReport', 'readResponse'],
|
|
78
|
+
convert: (model, msg, publish, options, meta) => {
|
|
79
|
+
const result = {};
|
|
80
|
+
const data = msg.data;
|
|
81
|
+
if (data.hasOwnProperty(0x0400)) {
|
|
82
|
+
result.temperature_offset = data[0x0400];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return result;
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
ctm_thermostat: {
|
|
89
|
+
cluster: 'hvacThermostat',
|
|
90
|
+
type: ['attributeReport', 'readResponse'],
|
|
91
|
+
convert: (model, msg, publish, options, meta) => {
|
|
92
|
+
const result = {};
|
|
93
|
+
const data = msg.data;
|
|
94
|
+
if (data.hasOwnProperty(0x0401)) { // Load
|
|
95
|
+
result.load = data[0x0401];
|
|
96
|
+
}
|
|
97
|
+
if (data.hasOwnProperty(0x0402)) { // Display text
|
|
98
|
+
result.display_text = data[0x0402];
|
|
99
|
+
}
|
|
100
|
+
if (data.hasOwnProperty(0x0403)) { // Sensor
|
|
101
|
+
const sensorModeLookup = {
|
|
102
|
+
0: 'air', 1: 'floor', 2: 'external', 3: 'regulator', 4: 'mv_air', 5: 'mv_external', 6: 'mv_regulator'};
|
|
103
|
+
result.sensor = sensorModeLookup[data[0x0403]];
|
|
104
|
+
}
|
|
105
|
+
if (data.hasOwnProperty(0x0405)) { // Regulator mode
|
|
106
|
+
result.regulator_mode = data[0x0405] ? 'regulator' : 'thermostat';
|
|
107
|
+
}
|
|
108
|
+
if (data.hasOwnProperty(0x0406)) { // Power status
|
|
109
|
+
result.power_status = data[0x0406] ? 'ON' : 'OFF';
|
|
110
|
+
}
|
|
111
|
+
if (data.hasOwnProperty(0x0408)) { // Mean power
|
|
112
|
+
result.mean_power = data[0x0408];
|
|
113
|
+
}
|
|
114
|
+
if (data.hasOwnProperty(0x0409)) { // Floor temp
|
|
115
|
+
result.floor_temp = utils.precisionRound(data[0x0409], 2) /100;
|
|
116
|
+
}
|
|
117
|
+
if (data.hasOwnProperty(0x0411)) { // Night switching
|
|
118
|
+
result.night_switching = data[0x0411] ? 'ON' : 'OFF';
|
|
119
|
+
}
|
|
120
|
+
if (data.hasOwnProperty(0x0412)) { // Frost guard
|
|
121
|
+
result.frost_guard = data[0x0412] ? 'ON' : 'OFF';
|
|
122
|
+
}
|
|
123
|
+
if (data.hasOwnProperty(0x0413)) { // Child lock
|
|
124
|
+
result.child_lock = data[0x0413] ? 'LOCK' : 'UNLOCK';
|
|
125
|
+
}
|
|
126
|
+
if (data.hasOwnProperty(0x0414)) { // Max floor temp
|
|
127
|
+
result.max_floor_temp = data[0x0414];
|
|
128
|
+
}
|
|
129
|
+
if (data.hasOwnProperty(0x0415)) { // Heating
|
|
130
|
+
result.heating = data[0x0415] ? 'heating' : 'idle';
|
|
131
|
+
}
|
|
132
|
+
if (data.hasOwnProperty(0x0420)) { // Regulator setpoint
|
|
133
|
+
result.regulator_setpoint = data[0x0420];
|
|
134
|
+
}
|
|
135
|
+
if (data.hasOwnProperty(0x0421)) { // Regulation mode
|
|
136
|
+
const regulationModeLookup = {0: 'thermostat', 1: 'regulator', 2: 'zzilent'};
|
|
137
|
+
result.regulation_mode= regulationModeLookup[data[0x0421]];
|
|
138
|
+
}
|
|
139
|
+
if (data.hasOwnProperty(0x0422)) { // Operation mode
|
|
140
|
+
const presetLookup = {0: 'off', 1: 'away', 2: 'sleep', 3: 'home'};
|
|
141
|
+
const systemModeLookup = {0: 'off', 1: 'off', 2: 'off', 3: 'heat'};
|
|
142
|
+
result.preset = presetLookup[data[0x0422]];
|
|
143
|
+
result.system_mode = systemModeLookup[data[0x0422]];
|
|
144
|
+
}
|
|
145
|
+
if (data.hasOwnProperty(0x0423)) { // Maximum floor temp guard
|
|
146
|
+
result.max_floor_guard = data[0x0423] ? 'ON' : 'OFF';
|
|
147
|
+
}
|
|
148
|
+
if (data.hasOwnProperty(0x0424)) { // Weekly timer enabled
|
|
149
|
+
result.weekly_timer = data[0x0424] ? 'ON' : 'OFF';
|
|
150
|
+
}
|
|
151
|
+
if (data.hasOwnProperty(0x0425)) { // Frost guard setpoint
|
|
152
|
+
result.frost_guard_setpoint = data[0x0425];
|
|
153
|
+
}
|
|
154
|
+
if (data.hasOwnProperty(0x0426)) { // External temperature
|
|
155
|
+
result.external_temp = utils.precisionRound(data[0x0426], 2) /100;
|
|
156
|
+
}
|
|
157
|
+
if (data.hasOwnProperty(0x0428)) { // Exteral sensor source
|
|
158
|
+
result.exteral_sensor_source = data[0x0428];
|
|
159
|
+
}
|
|
160
|
+
if (data.hasOwnProperty(0x0429)) { // Current air temperature
|
|
161
|
+
result.air_temp = utils.precisionRound(data[0x0429], 2) /100;
|
|
162
|
+
}
|
|
163
|
+
if (data.hasOwnProperty(0x0424)) { // Floor Sensor Error
|
|
164
|
+
result.floor_sensor_error = data[0x042B] ? 'error' : 'ok';
|
|
165
|
+
}
|
|
166
|
+
if (data.hasOwnProperty(0x0424)) { // External Air Sensor Error
|
|
167
|
+
result.exteral_sensor_error = data[0x042C] ? 'error' : 'ok';
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return result;
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
ctm_group_config: {
|
|
174
|
+
cluster: '65191', // 0xFEA7 ctmGroupConfig
|
|
175
|
+
type: ['attributeReport', 'readResponse'],
|
|
176
|
+
convert: (model, msg, publish, options, meta) => {
|
|
177
|
+
const result = {};
|
|
178
|
+
const data = msg.data;
|
|
179
|
+
if (data.hasOwnProperty(0x0000)) {
|
|
180
|
+
result.group_id = data[0x0000];
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return result;
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
ctm_sove_guard: {
|
|
187
|
+
cluster: '65481', // 0xFFC9 ctmSoveGuard
|
|
188
|
+
type: ['attributeReport', 'readResponse'],
|
|
189
|
+
convert: (model, msg, publish, options, meta) => {
|
|
190
|
+
const result = {};
|
|
191
|
+
const data = msg.data;
|
|
192
|
+
if (data.hasOwnProperty(0x0001)) { // Alarm status
|
|
193
|
+
const alarmStatusLookup = {
|
|
194
|
+
0: 'ok', 1: 'tamper', 2: 'high_temperatur', 3: 'timer', 4: 'battery_alarm', 5: 'error', 0xFF: 'unknown'};
|
|
195
|
+
result.alarm_status = alarmStatusLookup[data[0x0001]];
|
|
196
|
+
}
|
|
197
|
+
if (data.hasOwnProperty(0x0002)) { // Change battery
|
|
198
|
+
result.battery_low = data[0x0002] ? true : false;
|
|
199
|
+
}
|
|
200
|
+
if (data.hasOwnProperty(0x0003)) { // Stove temperature
|
|
201
|
+
result.stove_temperature = data[0x0003];
|
|
202
|
+
}
|
|
203
|
+
if (data.hasOwnProperty(0x0004)) { // Ambient temperature
|
|
204
|
+
result.ambient_temperature = data[0x0004];
|
|
205
|
+
}
|
|
206
|
+
if (data.hasOwnProperty(0x0005)) { // Active
|
|
207
|
+
result.active = data[0x0005] ? true : false;
|
|
208
|
+
}
|
|
209
|
+
if (data.hasOwnProperty(0x0006)) { // Runtime
|
|
210
|
+
result.runtime = data[0x0006];
|
|
211
|
+
}
|
|
212
|
+
if (data.hasOwnProperty(0x0007)) { // Runtime timeout
|
|
213
|
+
result.runtime_timeout = data[0x0007];
|
|
214
|
+
}
|
|
215
|
+
if (data.hasOwnProperty(0x0008)) { // Reset reason
|
|
216
|
+
const resetReasonLookup = {
|
|
217
|
+
0: 'unknown', 1: 'power_on', 2: 'external', 3: 'brown_out', 4: 'watchdog', 5: 'program_interface',
|
|
218
|
+
6: 'software', 0xFF: 'unknown'};
|
|
219
|
+
result.reset_reason = resetReasonLookup[data[0x0008]];
|
|
220
|
+
}
|
|
221
|
+
if (data.hasOwnProperty(0x0009)) { // Dip switch
|
|
222
|
+
result.dip_switch = data[0x0009];
|
|
223
|
+
}
|
|
224
|
+
if (data.hasOwnProperty(0x000A)) { // Software version
|
|
225
|
+
result.sw_version = data[0x000A];
|
|
226
|
+
}
|
|
227
|
+
if (data.hasOwnProperty(0x000B)) { // Hardware version
|
|
228
|
+
result.hw_version = data[0x000B];
|
|
229
|
+
}
|
|
230
|
+
if (data.hasOwnProperty(0x000C)) { // Bootloader version
|
|
231
|
+
result.bootloader_version = data[0x000C];
|
|
232
|
+
}
|
|
233
|
+
if (data.hasOwnProperty(0x000D)) { // Model
|
|
234
|
+
const modelLookup = {0: 'unknown', 1: '1_8', 2: 'infinity', 3: 'hybrid', 4: 'tak', 0xFF: 'unknown'};
|
|
235
|
+
result.model = modelLookup[data[0x000D]];
|
|
236
|
+
}
|
|
237
|
+
if (data.hasOwnProperty(0x0010)) { // Relay address
|
|
238
|
+
result.relay_address = data[0x0010];
|
|
239
|
+
}
|
|
240
|
+
if (data.hasOwnProperty(0x0100)) { // Relay current flag
|
|
241
|
+
const currentFlagLookup = {0: 'false', 1: 'true', 0xFF: 'unknown'};
|
|
242
|
+
result.current_flag = currentFlagLookup[data[0x0100]];
|
|
243
|
+
}
|
|
244
|
+
if (data.hasOwnProperty(0x0101)) { // Relay current
|
|
245
|
+
result.relay_current = data[0x0101];
|
|
246
|
+
}
|
|
247
|
+
if (data.hasOwnProperty(0x0102)) { // Relay status
|
|
248
|
+
const relayStatusLookup = {0: 'off', 1: 'on', 2: 'not_present', 0xFF: 'unknown'};
|
|
249
|
+
result.relay_status = relayStatusLookup[data[0x0102]];
|
|
250
|
+
}
|
|
251
|
+
if (data.hasOwnProperty(0x0103)) { // Relay external button
|
|
252
|
+
const relayStatusLookup = {0: 'not_clicked', 1: 'clicked', 0xFF: 'unknown'};
|
|
253
|
+
result.external_button = relayStatusLookup[data[0x0103]];
|
|
254
|
+
}
|
|
255
|
+
if (data.hasOwnProperty(0x0104)) { // Relay alarm
|
|
256
|
+
const relayAlarmLookup = {0: 'ok', 1: 'no_communication', 2: 'over_current', 3: 'over_temperature', 0xFF: 'unknown'};
|
|
257
|
+
result.relay_alarm = relayAlarmLookup[data[0x0104]];
|
|
258
|
+
}
|
|
259
|
+
if (data.hasOwnProperty(0x0105)) { // Alarm status (from relay)
|
|
260
|
+
const relayAlarmStatusLookup = {
|
|
261
|
+
0: 'ok', 1: 'tamper', 2: 'high_temperatur', 3: 'timer', 4: 'battery_alarm', 5: 'error', 0xFF: 'unknown'};
|
|
262
|
+
result.relay_alarm_status = relayAlarmStatusLookup[data[0x0105]];
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return result;
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
ctm_water_leak_alarm: {
|
|
269
|
+
cluster: 'ssIasZone',
|
|
270
|
+
type: ['commandStatusChangeNotification', 'attributeReport'],
|
|
271
|
+
convert: (model, msg, publish, options, meta) => {
|
|
272
|
+
const zoneStatus = msg.data.zonestatus;
|
|
273
|
+
return {
|
|
274
|
+
active_water_leak: (zoneStatus & 1) > 0,
|
|
275
|
+
water_leak: (zoneStatus & 1<<1) > 0,
|
|
276
|
+
battery_low: (zoneStatus & 1<<3) > 0,
|
|
277
|
+
};
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
const tzLocal = {
|
|
284
|
+
ballast_power_on_level: {
|
|
285
|
+
key: ['ballast_power_on_level'],
|
|
286
|
+
convertSet: async (entity, key, value, meta) => {
|
|
287
|
+
await entity.write('lightingBallastCfg', {'powerOnLevel': value});
|
|
288
|
+
},
|
|
289
|
+
convertGet: async (entity, key, meta) => {
|
|
290
|
+
await entity.read('lightingBallastCfg', ['powerOnLevel']);
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
ctm_device_mode: {
|
|
294
|
+
key: ['device_mode'],
|
|
295
|
+
convertGet: async (entity, key, meta) => {
|
|
296
|
+
await entity.read('genOnOff', [0x2200]);
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
ctm_device_enabled: {
|
|
300
|
+
key: ['device_enabled'],
|
|
301
|
+
convertSet: async (entity, key, value, meta) => {
|
|
302
|
+
await entity.write('genOnOff', {0x2201: {value: {'OFF': 0, 'ON': 1}[value], type: dataType.boolean}});
|
|
303
|
+
},
|
|
304
|
+
convertGet: async (entity, key, meta) => {
|
|
305
|
+
await entity.read('genOnOff', [0x2201]);
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
ctm_child_lock: {
|
|
309
|
+
key: ['child_lock'],
|
|
310
|
+
convertGet: async (entity, key, meta) => {
|
|
311
|
+
await entity.read('genOnOff', [0x2202]);
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
ctm_current_flag: {
|
|
315
|
+
key: ['current_flag'],
|
|
316
|
+
convertGet: async (entity, key, meta) => {
|
|
317
|
+
await entity.read('genOnOff', [0x5000], {manufacturerCode: 0x1337});
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
ctm_temperature_offset: {
|
|
321
|
+
key: ['temperature_offset'],
|
|
322
|
+
convertSet: async (entity, key, value, meta) => {
|
|
323
|
+
await entity.write('msTemperatureMeasurement',
|
|
324
|
+
{0x0400: {value: value, type: dataType.int8}}, {manufacturerCode: 0x1337, sendWhen: 'active'});
|
|
325
|
+
},
|
|
326
|
+
convertGet: async (entity, key, meta) => {
|
|
327
|
+
await entity.read('msTemperatureMeasurement', [0x0400], {manufacturerCode: 0x1337, sendWhen: 'active'});
|
|
328
|
+
await entity.read('msTemperatureMeasurement', ['measuredValue'], {sendWhen: 'active'});
|
|
329
|
+
},
|
|
330
|
+
},
|
|
331
|
+
ctm_thermostat: {
|
|
332
|
+
key: ['load', 'display_text', 'sensor', 'regulator_mode', 'power_status', 'system_mode', 'night_switching', 'frost_guard',
|
|
333
|
+
'max_floor_temp', 'regulator_setpoint', 'regulation_mode', 'max_floor_guard', 'weekly_timer', 'exteral_sensor_source',
|
|
334
|
+
],
|
|
335
|
+
convertSet: async (entity, key, value, meta) => {
|
|
336
|
+
switch (key) {
|
|
337
|
+
case 'load':
|
|
338
|
+
await entity.write('hvacThermostat', {0x0401: {value: value, type: dataType.uint16}});
|
|
339
|
+
break;
|
|
340
|
+
case 'display_text':
|
|
341
|
+
await entity.write('hvacThermostat', {0x0402: {value: value, type: dataType.charStr}});
|
|
342
|
+
break;
|
|
343
|
+
case 'sensor':
|
|
344
|
+
await entity.write('hvacThermostat', {0x0403: {
|
|
345
|
+
value: {'air': 0, 'floor': 1, 'external': 2, 'regulator': 3, 'mv_air': 4, 'mv_external': 5, 'mv_regulator': 6}[value],
|
|
346
|
+
type: dataType.enum8}});
|
|
347
|
+
break;
|
|
348
|
+
case 'regulator_mode':
|
|
349
|
+
await entity.write('hvacThermostat', {0x0405: {value: {'thermostat': 0, 'regulator': 1}[value], type: dataType.boolean}});
|
|
350
|
+
break;
|
|
351
|
+
case 'power_status':
|
|
352
|
+
await entity.write('hvacThermostat', {0x0406: {value: {'OFF': 0, 'ON': 1}[value], type: dataType.boolean}});
|
|
353
|
+
break;
|
|
354
|
+
case 'system_mode':
|
|
355
|
+
if (value === 'off') {
|
|
356
|
+
await entity.write('hvacThermostat', {0x0406: {value: 0, type: dataType.boolean}});
|
|
357
|
+
} else if (value === 'heat') {
|
|
358
|
+
await entity.write('hvacThermostat', {0x0422: {value: 3, type: dataType.uint8}});
|
|
359
|
+
}
|
|
360
|
+
break;
|
|
361
|
+
case 'night_switching':
|
|
362
|
+
await entity.write('hvacThermostat', {0x0411: {value: {'OFF': 0, 'ON': 1}[value], type: dataType.boolean}});
|
|
363
|
+
break;
|
|
364
|
+
case 'frost_guard':
|
|
365
|
+
await entity.write('hvacThermostat', {0x0412: {value: {'OFF': 0, 'ON': 1}[value], type: dataType.boolean}});
|
|
366
|
+
break;
|
|
367
|
+
case 'max_floor_temp':
|
|
368
|
+
await entity.write('hvacThermostat', {0x0414: {value: value, type: dataType.uint8}});
|
|
369
|
+
break;
|
|
370
|
+
case 'regulator_setpoint':
|
|
371
|
+
await entity.write('hvacThermostat', {0x0420: {value: value, type: dataType.uint8}});
|
|
372
|
+
break;
|
|
373
|
+
case 'regulation_mode':
|
|
374
|
+
await entity.write('hvacThermostat', {0x0421: {
|
|
375
|
+
value: {'thermostat': 0, 'regulator': 1, 'zzilent': 2}[value],
|
|
376
|
+
type: dataType.uint8}});
|
|
377
|
+
break;
|
|
378
|
+
case 'max_floor_guard':
|
|
379
|
+
await entity.write('hvacThermostat', {0x0423: {value: {'OFF': 0, 'ON': 1}[value], type: dataType.boolean}});
|
|
380
|
+
break;
|
|
381
|
+
case 'weekly_timer':
|
|
382
|
+
await entity.write('hvacThermostat', {0x0424: {value: {'OFF': 0, 'ON': 1}[value], type: dataType.boolean}});
|
|
383
|
+
break;
|
|
384
|
+
case 'exteral_sensor_source':
|
|
385
|
+
await entity.write('hvacThermostat', {0x0428: {value: value, type: dataType.uint16}});
|
|
386
|
+
break;
|
|
387
|
+
|
|
388
|
+
default: // Unknown key
|
|
389
|
+
throw new Error(`Unhandled key tzLocal.ctm_thermostat.convertSet ${key}`);
|
|
390
|
+
}
|
|
391
|
+
},
|
|
392
|
+
convertGet: async (entity, key, meta) => {
|
|
393
|
+
switch (key) {
|
|
394
|
+
case 'load':
|
|
395
|
+
await entity.read('hvacThermostat', [0x0401]);
|
|
396
|
+
break;
|
|
397
|
+
case 'display_text':
|
|
398
|
+
await entity.read('hvacThermostat', [0x0402]);
|
|
399
|
+
break;
|
|
400
|
+
case 'sensor':
|
|
401
|
+
await entity.read('hvacThermostat', [0x0403]);
|
|
402
|
+
break;
|
|
403
|
+
case 'regulator_mode':
|
|
404
|
+
await entity.read('hvacThermostat', [0x0405]);
|
|
405
|
+
break;
|
|
406
|
+
case 'power_status':
|
|
407
|
+
await entity.read('hvacThermostat', [0x0406]);
|
|
408
|
+
break;
|
|
409
|
+
case 'night_switching':
|
|
410
|
+
await entity.read('hvacThermostat', [0x0411]);
|
|
411
|
+
break;
|
|
412
|
+
case 'frost_guard':
|
|
413
|
+
await entity.read('hvacThermostat', [0x0412]);
|
|
414
|
+
break;
|
|
415
|
+
case 'max_floor_temp':
|
|
416
|
+
await entity.read('hvacThermostat', [0x0414]);
|
|
417
|
+
break;
|
|
418
|
+
case 'regulator_setpoint':
|
|
419
|
+
await entity.read('hvacThermostat', [0x0420]);
|
|
420
|
+
break;
|
|
421
|
+
case 'regulation_mode':
|
|
422
|
+
await entity.read('hvacThermostat', [0x0421]);
|
|
423
|
+
break;
|
|
424
|
+
case 'system_mode':
|
|
425
|
+
await entity.read('hvacThermostat', [0x0422]);
|
|
426
|
+
break;
|
|
427
|
+
case 'max_floor_guard':
|
|
428
|
+
await entity.read('hvacThermostat', [0x0423]);
|
|
429
|
+
break;
|
|
430
|
+
case 'weekly_timer':
|
|
431
|
+
await entity.read('hvacThermostat', [0x0424]);
|
|
432
|
+
break;
|
|
433
|
+
case 'exteral_sensor_source':
|
|
434
|
+
await entity.read('hvacThermostat', [0x0428]);
|
|
435
|
+
break;
|
|
436
|
+
|
|
437
|
+
default: // Unknown key
|
|
438
|
+
throw new Error(`Unhandled key tzLocal.ctm_thermostat.convertGet ${key}`);
|
|
439
|
+
}
|
|
440
|
+
},
|
|
441
|
+
},
|
|
442
|
+
ctm_thermostat_preset: {
|
|
443
|
+
key: ['preset'],
|
|
444
|
+
convertSet: async (entity, key, value, meta) => {
|
|
445
|
+
const presetLookup = {'off': 0, 'away': 1, 'sleep': 2, 'home': 3};
|
|
446
|
+
await entity.write('hvacThermostat', {0x0422: {value: presetLookup[value], type: dataType.uint8}});
|
|
447
|
+
},
|
|
448
|
+
},
|
|
449
|
+
ctm_thermostat_child_lock: {
|
|
450
|
+
key: ['child_lock'],
|
|
451
|
+
convertSet: async (entity, key, value, meta) => {
|
|
452
|
+
await entity.write('hvacThermostat', {0x0413: {value: {'UNLOCK': 0, 'LOCK': 1}[value], type: dataType.boolean}});
|
|
453
|
+
},
|
|
454
|
+
},
|
|
455
|
+
ctm_thermostat_gets: {
|
|
456
|
+
key: ['mean_power', 'floor_temp', 'heating', 'frost_guard_setpoint', 'external_temp',
|
|
457
|
+
'air_temp', 'floor_sensor_error', 'exteral_sensor_error',
|
|
458
|
+
],
|
|
459
|
+
convertGet: async (entity, key, meta) => {
|
|
460
|
+
switch (key) {
|
|
461
|
+
case 'mean_power':
|
|
462
|
+
await entity.read('hvacThermostat', [0x0408]);
|
|
463
|
+
break;
|
|
464
|
+
case 'floor_temp':
|
|
465
|
+
await entity.read('hvacThermostat', [0x0409]);
|
|
466
|
+
break;
|
|
467
|
+
case 'heating':
|
|
468
|
+
await entity.read('hvacThermostat', [0x0415]);
|
|
469
|
+
break;
|
|
470
|
+
case 'frost_guard_setpoint':
|
|
471
|
+
await entity.read('hvacThermostat', [0x0425]);
|
|
472
|
+
break;
|
|
473
|
+
case 'external_temp':
|
|
474
|
+
await entity.read('hvacThermostat', [0x0426]);
|
|
475
|
+
break;
|
|
476
|
+
case 'air_temp':
|
|
477
|
+
await entity.read('hvacThermostat', [0x0429]);
|
|
478
|
+
break;
|
|
479
|
+
case 'floor_sensor_error':
|
|
480
|
+
await entity.read('hvacThermostat', [0x042B]);
|
|
481
|
+
break;
|
|
482
|
+
case 'exteral_sensor_error':
|
|
483
|
+
await entity.read('hvacThermostat', [0x042C]);
|
|
484
|
+
break;
|
|
485
|
+
|
|
486
|
+
default: // Unknown key
|
|
487
|
+
throw new Error(`Unhandled key tzLocal.ctm_thermostat.convertGet ${key}`);
|
|
488
|
+
}
|
|
489
|
+
},
|
|
490
|
+
},
|
|
491
|
+
ctm_group_config: {
|
|
492
|
+
key: ['group_id'],
|
|
493
|
+
convertGet: async (entity, key, meta) => {
|
|
494
|
+
await entity.read(0xFEA7, [0x0000], {manufacturerCode: 0x1337, sendWhen: 'active'});
|
|
495
|
+
},
|
|
496
|
+
},
|
|
497
|
+
ctm_sove_guard: {
|
|
498
|
+
key: [
|
|
499
|
+
'alarm_status', 'change_battery', 'stove_temperature', 'ambient_temperature', 'active', 'runtime', 'runtime_timeout',
|
|
500
|
+
'reset_reason', 'dip_switch', 'sw_version', 'hw_version', 'bootloader_version', 'model', 'relay_address',
|
|
501
|
+
'current_flag', 'relay_current', 'relay_status', 'external_button', 'relay_alarm', 'relay_alarm_status',
|
|
502
|
+
],
|
|
503
|
+
convertGet: async (entity, key, meta) => {
|
|
504
|
+
switch (key) {
|
|
505
|
+
case 'alarm_status':
|
|
506
|
+
await entity.read(0xFFC9, [0x0001], {manufacturerCode: 0x1337});
|
|
507
|
+
break;
|
|
508
|
+
case 'battery_low':
|
|
509
|
+
await entity.read(0xFFC9, [0x0002], {manufacturerCode: 0x1337});
|
|
510
|
+
break;
|
|
511
|
+
case 'stove_temperature':
|
|
512
|
+
await entity.read(0xFFC9, [0x0003], {manufacturerCode: 0x1337});
|
|
513
|
+
break;
|
|
514
|
+
case 'ambient_temperature':
|
|
515
|
+
await entity.read(0xFFC9, [0x0004], {manufacturerCode: 0x1337});
|
|
516
|
+
break;
|
|
517
|
+
case 'active':
|
|
518
|
+
await entity.read(0xFFC9, [0x0005], {manufacturerCode: 0x1337});
|
|
519
|
+
break;
|
|
520
|
+
case 'runtime':
|
|
521
|
+
await entity.read(0xFFC9, [0x0006], {manufacturerCode: 0x1337});
|
|
522
|
+
break;
|
|
523
|
+
case 'runtime_timeout':
|
|
524
|
+
await entity.read(0xFFC9, [0x0007], {manufacturerCode: 0x1337});
|
|
525
|
+
break;
|
|
526
|
+
case 'reset_reason':
|
|
527
|
+
await entity.read(0xFFC9, [0x0008], {manufacturerCode: 0x1337});
|
|
528
|
+
break;
|
|
529
|
+
case 'dip_switch':
|
|
530
|
+
await entity.read(0xFFC9, [0x0009], {manufacturerCode: 0x1337});
|
|
531
|
+
break;
|
|
532
|
+
case 'sw_version':
|
|
533
|
+
await entity.read(0xFFC9, [0x000A], {manufacturerCode: 0x1337});
|
|
534
|
+
break;
|
|
535
|
+
case 'hw_version':
|
|
536
|
+
await entity.read(0xFFC9, [0x000B], {manufacturerCode: 0x1337});
|
|
537
|
+
break;
|
|
538
|
+
case 'bootloader_version':
|
|
539
|
+
await entity.read(0xFFC9, [0x000C], {manufacturerCode: 0x1337});
|
|
540
|
+
break;
|
|
541
|
+
case 'model':
|
|
542
|
+
await entity.read(0xFFC9, [0x000D], {manufacturerCode: 0x1337});
|
|
543
|
+
break;
|
|
544
|
+
case 'relay_address':
|
|
545
|
+
await entity.read(0xFFC9, [0x0010], {manufacturerCode: 0x1337});
|
|
546
|
+
break;
|
|
547
|
+
case 'current_flag':
|
|
548
|
+
await entity.read(0xFFC9, [0x0100], {manufacturerCode: 0x1337});
|
|
549
|
+
break;
|
|
550
|
+
case 'relay_current':
|
|
551
|
+
await entity.read(0xFFC9, [0x0101], {manufacturerCode: 0x1337});
|
|
552
|
+
break;
|
|
553
|
+
case 'relay_status':
|
|
554
|
+
await entity.read(0xFFC9, [0x0102], {manufacturerCode: 0x1337});
|
|
555
|
+
break;
|
|
556
|
+
case 'external_button':
|
|
557
|
+
await entity.read(0xFFC9, [0x0103], {manufacturerCode: 0x1337});
|
|
558
|
+
break;
|
|
559
|
+
case 'relay_alarm':
|
|
560
|
+
await entity.read(0xFFC9, [0x0104], {manufacturerCode: 0x1337});
|
|
561
|
+
break;
|
|
562
|
+
case 'relay_alarm_status':
|
|
563
|
+
await entity.read(0xFFC9, [0x0105], {manufacturerCode: 0x1337});
|
|
564
|
+
break;
|
|
565
|
+
|
|
566
|
+
default: // Unknown key
|
|
567
|
+
throw new Error(`Unhandled key tzLocal.ctm_sove_guard.convertGet ${key}`);
|
|
568
|
+
}
|
|
569
|
+
},
|
|
570
|
+
},
|
|
571
|
+
};
|
|
572
|
+
|
|
573
|
+
module.exports = [
|
|
574
|
+
{
|
|
575
|
+
zigbeeModel: ['mTouch Dim'],
|
|
576
|
+
model: 'mTouch_Dim',
|
|
577
|
+
vendor: 'CTM Lyng',
|
|
578
|
+
description: 'mTouch Dim OP, touch dimmer',
|
|
579
|
+
fromZigbee: [fz.on_off, fz.brightness, fz.lighting_ballast_configuration],
|
|
580
|
+
toZigbee: [tz.on_off, tz.light_onoff_brightness, tz.light_brightness_move, tz.ballast_config, tzLocal.ballast_power_on_level],
|
|
581
|
+
meta: {disableDefaultResponse: true},
|
|
582
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
583
|
+
const endpoint = device.getEndpoint(1);
|
|
584
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl', 'lightingBallastCfg']);
|
|
585
|
+
await endpoint.read('genOnOff', ['onOff']);
|
|
586
|
+
await reporting.onOff(endpoint);
|
|
587
|
+
await endpoint.read('genLevelCtrl', ['currentLevel']);
|
|
588
|
+
await reporting.brightness(endpoint);
|
|
589
|
+
await endpoint.read('lightingBallastCfg', ['minLevel', 'maxLevel', 'powerOnLevel']);
|
|
590
|
+
await endpoint.configureReporting('lightingBallastCfg', [{
|
|
591
|
+
attribute: 'minLevel',
|
|
592
|
+
minimumReportInterval: 0,
|
|
593
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
594
|
+
reportableChange: null}]);
|
|
595
|
+
await endpoint.configureReporting('lightingBallastCfg', [{
|
|
596
|
+
attribute: 'maxLevel',
|
|
597
|
+
minimumReportInterval: 0,
|
|
598
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
599
|
+
reportableChange: null}]);
|
|
600
|
+
await endpoint.configureReporting('lightingBallastCfg', [{
|
|
601
|
+
attribute: 'powerOnLevel',
|
|
602
|
+
minimumReportInterval: 0,
|
|
603
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
604
|
+
reportableChange: null}]);
|
|
605
|
+
},
|
|
606
|
+
exposes: [e.light_brightness(),
|
|
607
|
+
exposes.numeric('ballast_minimum_level', ea.ALL).withValueMin(1).withValueMax(99)
|
|
608
|
+
.withDescription('Specifies the minimum brightness value'),
|
|
609
|
+
exposes.numeric('ballast_maximum_level', ea.ALL).withValueMin(1).withValueMax(99)
|
|
610
|
+
.withDescription('Specifies the maximum brightness value'),
|
|
611
|
+
exposes.numeric('ballast_power_on_level', ea.ALL).withValueMin(1).withValueMax(99)
|
|
612
|
+
.withDescription('Specifies the initialisation light level. Can not be set lower than "ballast_minimum_level"')],
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
zigbeeModel: ['mTouch Bryter'],
|
|
616
|
+
model: 'mTouch_Bryter',
|
|
617
|
+
vendor: 'CTM Lyng',
|
|
618
|
+
description: 'mTouch Bryter OP, 3 channel switch',
|
|
619
|
+
fromZigbee: [fz.temperature, fz.battery, fz.command_recall, fz.command_on, fz.command_off, fz.command_toggle,
|
|
620
|
+
fz.command_move, fz.command_stop, fzLocal.ctm_group_config],
|
|
621
|
+
toZigbee: [],
|
|
622
|
+
meta: {battery: {voltageToPercentage: '3V_2500_3200'}},
|
|
623
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
624
|
+
const endpoint = device.getEndpoint(1);
|
|
625
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'msTemperatureMeasurement']);
|
|
626
|
+
await reporting.batteryVoltage(endpoint);
|
|
627
|
+
await endpoint.read('msTemperatureMeasurement', ['measuredValue']);
|
|
628
|
+
await reporting.temperature(endpoint, {min: constants.repInterval.MINUTES_10, max: constants.repInterval.HOUR, change: 100});
|
|
629
|
+
await endpoint.read(0xFEA7, [0x0000], {manufacturerCode: 0x1337});
|
|
630
|
+
},
|
|
631
|
+
exposes: [e.battery(), e.temperature(),
|
|
632
|
+
e.action(['recall_1', 'recall_2', 'recall_3', 'on', 'off', 'toggle',
|
|
633
|
+
'brightness_move_down', 'brightness_move_up', 'brightness_stop']),
|
|
634
|
+
exposes.numeric('group_id', ea.STATE)
|
|
635
|
+
.withDescription('The device sends commands with this group ID. Put dvices in this group to control them.')],
|
|
636
|
+
},
|
|
637
|
+
{
|
|
638
|
+
zigbeeModel: ['mTouch One'],
|
|
639
|
+
model: 'mTouch_One',
|
|
640
|
+
vendor: 'CTM Lyng',
|
|
641
|
+
description: 'mTouch One OP, touch thermostat',
|
|
642
|
+
fromZigbee: [fz.thermostat, fzLocal.ctm_thermostat],
|
|
643
|
+
toZigbee: [tz.thermostat_occupied_heating_setpoint, tz.thermostat_local_temperature, tzLocal.ctm_thermostat,
|
|
644
|
+
tzLocal.ctm_thermostat_preset, tzLocal.ctm_thermostat_child_lock, tzLocal.ctm_thermostat_gets],
|
|
645
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
646
|
+
const endpoint = device.getEndpoint(1);
|
|
647
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['hvacThermostat']);
|
|
648
|
+
await endpoint.read('hvacThermostat', ['localTemp', 'occupiedHeatingSetpoint']);
|
|
649
|
+
await reporting.thermostatTemperature(endpoint);
|
|
650
|
+
await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
|
|
651
|
+
await endpoint.read('hvacThermostat', [0x0401]);
|
|
652
|
+
await endpoint.read('hvacThermostat', [0x0402]);
|
|
653
|
+
// Regulator mode
|
|
654
|
+
await endpoint.read('hvacThermostat', [0x0405]);
|
|
655
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
656
|
+
attribute: {ID: 0x0405, type: dataType.boolean},
|
|
657
|
+
minimumReportInterval: 1,
|
|
658
|
+
maximumReportInterval: constants.repInterval.MAX,
|
|
659
|
+
reportableChange: null}]);
|
|
660
|
+
// Power consumption
|
|
661
|
+
await endpoint.read('hvacThermostat', [0x0408]);
|
|
662
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
663
|
+
attribute: {ID: 0x0408, type: dataType.uint16},
|
|
664
|
+
minimumReportInterval: 0,
|
|
665
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
666
|
+
reportableChange: 5}]);
|
|
667
|
+
// Floor temp sensor
|
|
668
|
+
await endpoint.read('hvacThermostat', [0x0409]);
|
|
669
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
670
|
+
attribute: {ID: 0x0409, type: dataType.int16},
|
|
671
|
+
minimumReportInterval: 0,
|
|
672
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
673
|
+
reportableChange: 10}]);
|
|
674
|
+
// Frost guard
|
|
675
|
+
await endpoint.read('hvacThermostat', [0x0412]);
|
|
676
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
677
|
+
attribute: {ID: 0x0412, type: dataType.boolean},
|
|
678
|
+
minimumReportInterval: 0,
|
|
679
|
+
maximumReportInterval: constants.repInterval.MAX,
|
|
680
|
+
reportableChange: null}]);
|
|
681
|
+
// Child lock active/inactive
|
|
682
|
+
await endpoint.read('hvacThermostat', [0x0413]);
|
|
683
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
684
|
+
attribute: {ID: 0x0413, type: dataType.boolean},
|
|
685
|
+
minimumReportInterval: 0,
|
|
686
|
+
maximumReportInterval: constants.repInterval.MAX,
|
|
687
|
+
reportableChange: null}]);
|
|
688
|
+
// Regulator setpoint
|
|
689
|
+
await endpoint.read('hvacThermostat', [0x0420]);
|
|
690
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
691
|
+
attribute: {ID: 0x0420, type: dataType.uint8},
|
|
692
|
+
minimumReportInterval: 0,
|
|
693
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
694
|
+
reportableChange: 1}]);
|
|
695
|
+
// Operation mode
|
|
696
|
+
await endpoint.read('hvacThermostat', [0x0422]);
|
|
697
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
698
|
+
attribute: {ID: 0x0422, type: dataType.uint8},
|
|
699
|
+
minimumReportInterval: 0,
|
|
700
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
701
|
+
reportableChange: 1}]);
|
|
702
|
+
// Air temp sensor
|
|
703
|
+
await endpoint.read('hvacThermostat', [0x0429]);
|
|
704
|
+
await endpoint.configureReporting('hvacThermostat', [{
|
|
705
|
+
attribute: {ID: 0x0429, type: dataType.int16},
|
|
706
|
+
minimumReportInterval: 0,
|
|
707
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
708
|
+
reportableChange: 10}]);
|
|
709
|
+
},
|
|
710
|
+
exposes: [e.child_lock(),
|
|
711
|
+
exposes.climate()
|
|
712
|
+
.withSetpoint('occupied_heating_setpoint', 5, 40, 1)
|
|
713
|
+
.withLocalTemperature()
|
|
714
|
+
.withSystemMode(['off', 'heat'])
|
|
715
|
+
.withPreset(['off', 'away', 'sleep', 'home']),
|
|
716
|
+
exposes.numeric('load', ea.ALL).withUnit('W')
|
|
717
|
+
.withDescription('Load in W when heating is on (between 0-3600 W). The thermostat uses the value as input to the ' +
|
|
718
|
+
'mean_power calculation.')
|
|
719
|
+
.withValueMin(0).withValueMax(3600),
|
|
720
|
+
exposes.text('display_text', ea.ALL)
|
|
721
|
+
.withDescription('Displayed text on thermostat display (zone). Max 19 characters'),
|
|
722
|
+
exposes.binary('regulator_mode', ea.ALL, 'regulator', 'thermostat')
|
|
723
|
+
.withDescription('Device in regulator or thermostat mode.'),
|
|
724
|
+
exposes.numeric('mean_power', ea.STATE_GET).withUnit('W')
|
|
725
|
+
.withDescription('Reports average power usage last 10 minutes'),
|
|
726
|
+
exposes.numeric('floor_temp', ea.STATE_GET).withUnit('°C')
|
|
727
|
+
.withDescription('Current temperature measured from the floor sensor'),
|
|
728
|
+
exposes.binary('frost_guard', ea.ALL, 'ON', 'OFF')
|
|
729
|
+
.withDescription('When frost guard is ON, it is activated when the thermostat is switched OFF with the ON/OFF button.' +
|
|
730
|
+
'At the same time, the display will fade and the text "Frostsikring x °C" appears in the display and remains until the ' +
|
|
731
|
+
'thermostat is switched on again.'),
|
|
732
|
+
exposes.numeric('regulator_setpoint', ea.ALL).withUnit('%')
|
|
733
|
+
.withDescription('Setpoint in %, use only when the thermostat is in regulator mode.')
|
|
734
|
+
.withValueMin(1).withValueMax(99),
|
|
735
|
+
exposes.numeric('air_temp', ea.STATE_GET).withUnit('°C')
|
|
736
|
+
.withDescription('Current temperature measured from the air sensor'),
|
|
737
|
+
],
|
|
738
|
+
},
|
|
739
|
+
{
|
|
740
|
+
zigbeeModel: ['mStikk Outlet'],
|
|
741
|
+
model: 'mStikk_Outlet',
|
|
742
|
+
vendor: 'CTM Lyng',
|
|
743
|
+
description: 'mStikk OP, wall socket',
|
|
744
|
+
fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering],
|
|
745
|
+
toZigbee: [tz.on_off],
|
|
746
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
747
|
+
const endpoint = device.getEndpoint(1);
|
|
748
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering']);
|
|
749
|
+
await endpoint.read('haElectricalMeasurement', ['acVoltageMultiplier', 'acVoltageDivisor']);
|
|
750
|
+
await endpoint.read('haElectricalMeasurement', ['acCurrentMultiplier', 'acCurrentDivisor']);
|
|
751
|
+
await endpoint.read('haElectricalMeasurement', ['acPowerMultiplier', 'acPowerDivisor']);
|
|
752
|
+
await reporting.readMeteringMultiplierDivisor(endpoint);
|
|
753
|
+
await endpoint.read('genOnOff', ['onOff']);
|
|
754
|
+
await reporting.onOff(endpoint);
|
|
755
|
+
await reporting.rmsVoltage(endpoint, {change: 100});
|
|
756
|
+
await reporting.rmsCurrent(endpoint);
|
|
757
|
+
await reporting.activePower(endpoint);
|
|
758
|
+
await reporting.currentSummDelivered(endpoint);
|
|
759
|
+
},
|
|
760
|
+
exposes: [e.power(), e.current(), e.voltage(), e.switch(), e.energy()],
|
|
761
|
+
},
|
|
762
|
+
{
|
|
763
|
+
zigbeeModel: ['mKomfy'],
|
|
764
|
+
model: 'mKomfy_Sensor',
|
|
765
|
+
vendor: 'CTM Lyng',
|
|
766
|
+
description: 'mKomfy, stove guard',
|
|
767
|
+
fromZigbee: [fz.temperature, fz.battery, fzLocal.ctm_sove_guard],
|
|
768
|
+
toZigbee: [],
|
|
769
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
770
|
+
const endpoint = device.getEndpoint(1);
|
|
771
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'msTemperatureMeasurement', 0xFFC9]);
|
|
772
|
+
await reporting.batteryPercentageRemaining(endpoint);
|
|
773
|
+
// await endpoint.read('msTemperatureMeasurement', ['measuredValue']);
|
|
774
|
+
await reporting.temperature(endpoint, {min: constants.repInterval.MINUTES_10, max: constants.repInterval.HOUR, change: 100});
|
|
775
|
+
// Alarm status
|
|
776
|
+
// await endpoint.read(0xFFC9, [0x0001], {manufacturerCode: 0x1337});
|
|
777
|
+
await endpoint.configureReporting(0xFFC9, [{
|
|
778
|
+
attribute: {ID: 0x0001, type: dataType.uint8},
|
|
779
|
+
minimumReportInterval: 0,
|
|
780
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
781
|
+
reportableChange: 0}], {manufacturerCode: 0x1337});
|
|
782
|
+
// Change battery
|
|
783
|
+
// await endpoint.read(0xFFC9, [0x0002], {manufacturerCode: 0x1337});
|
|
784
|
+
await endpoint.configureReporting(0xFFC9, [{
|
|
785
|
+
attribute: {ID: 0x0002, type: dataType.uint8},
|
|
786
|
+
minimumReportInterval: 0,
|
|
787
|
+
maximumReportInterval: constants.repInterval.MAX,
|
|
788
|
+
reportableChange: 0}], {manufacturerCode: 0x1337});
|
|
789
|
+
// Active
|
|
790
|
+
// await endpoint.read(0xFFC9, [0x0005], {manufacturerCode: 0x1337});
|
|
791
|
+
await endpoint.configureReporting(0xFFC9, [{
|
|
792
|
+
attribute: {ID: 0x0005, type: dataType.uint8},
|
|
793
|
+
minimumReportInterval: 0,
|
|
794
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
795
|
+
reportableChange: 0}], {manufacturerCode: 0x1337});
|
|
796
|
+
},
|
|
797
|
+
exposes: [e.battery(), e.battery_low(), e.temperature(),
|
|
798
|
+
exposes.enum('alarm_status', ea.STATE, ['ok', 'tamper', 'high_temperatur', 'timer', 'battery_alarm', 'error', 'unknown'])
|
|
799
|
+
.withDescription('Alarm status.'),
|
|
800
|
+
exposes.binary('active', ea.STATE, true, false)
|
|
801
|
+
.withDescription('Stove guard active/inactive (Stove in use)')],
|
|
802
|
+
},
|
|
803
|
+
{
|
|
804
|
+
zigbeeModel: ['mTouch Astro'],
|
|
805
|
+
model: 'mTouch_Astro',
|
|
806
|
+
vendor: 'CTM Lyng',
|
|
807
|
+
description: 'mTouch Astro OP, astro clock',
|
|
808
|
+
fromZigbee: [fz.on_off, fz.command_on, fz.command_off, fzLocal.ctm_device_mode, fzLocal.ctm_device_enabled,
|
|
809
|
+
fzLocal.ctm_child_lock, fzLocal.ctm_group_config],
|
|
810
|
+
toZigbee: [tz.on_off, tzLocal.ctm_device_enabled],
|
|
811
|
+
meta: {disableDefaultResponse: true},
|
|
812
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
813
|
+
const endpoint = device.getEndpoint(1);
|
|
814
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
|
|
815
|
+
await endpoint.read('genOnOff', ['onOff']);
|
|
816
|
+
await reporting.onOff(endpoint);
|
|
817
|
+
// Device mode
|
|
818
|
+
await endpoint.read('genOnOff', [0x2200]);
|
|
819
|
+
await endpoint.configureReporting('genOnOff', [{
|
|
820
|
+
attribute: {ID: 0x2200, type: dataType.uint8},
|
|
821
|
+
minimumReportInterval: 0,
|
|
822
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
823
|
+
reportableChange: 0}]);
|
|
824
|
+
await endpoint.read('genOnOff', [0x2201]);
|
|
825
|
+
await endpoint.configureReporting('genOnOff', [{
|
|
826
|
+
attribute: {ID: 0x2201, type: dataType.boolean},
|
|
827
|
+
minimumReportInterval: 0,
|
|
828
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
829
|
+
reportableChange: null}]);
|
|
830
|
+
await endpoint.read('genOnOff', [0x2202]);
|
|
831
|
+
await endpoint.configureReporting('genOnOff', [{
|
|
832
|
+
attribute: {ID: 0x2202, type: dataType.boolean},
|
|
833
|
+
minimumReportInterval: 0,
|
|
834
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
835
|
+
reportableChange: null}]);
|
|
836
|
+
await endpoint.read(0xFEA7, [0x0000], {manufacturerCode: 0x1337});
|
|
837
|
+
},
|
|
838
|
+
exposes: [e.switch(), e.action(['on', 'off']),
|
|
839
|
+
exposes.enum('device_mode', ea.STATE, ['astro_clock', 'timer', 'daily_timer', 'weekly_timer'])
|
|
840
|
+
.withDescription('Device mode.'),
|
|
841
|
+
exposes.binary('device_enabled', ea.ALL, 'ON', 'OFF')
|
|
842
|
+
.withDescription('Turn the device on or off'),
|
|
843
|
+
exposes.binary('child_lock', ea.STATE, 'locked', 'unlocked')
|
|
844
|
+
.withDescription('Physical input on the device enabled/disabled'),
|
|
845
|
+
exposes.numeric('group_id', ea.STATE)
|
|
846
|
+
.withDescription('The device sends commands with this group ID. Put dvices in this group to control them.'),
|
|
847
|
+
],
|
|
848
|
+
},
|
|
849
|
+
{
|
|
850
|
+
zigbeeModel: ['AX Water Sensor'],
|
|
851
|
+
model: 'AX_Water_Sensor',
|
|
852
|
+
vendor: 'CTM Lyng',
|
|
853
|
+
description: 'AX Water Sensor, water leakage detector',
|
|
854
|
+
fromZigbee: [fz.battery, fz.ias_enroll, fzLocal.ctm_water_leak_alarm],
|
|
855
|
+
toZigbee: [],
|
|
856
|
+
meta: {battery: {voltageToPercentage: '3V_2500_3200'}},
|
|
857
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
858
|
+
const endpoint = device.getEndpoint(1);
|
|
859
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'ssIasZone']);
|
|
860
|
+
await reporting.batteryVoltage(endpoint);
|
|
861
|
+
await endpoint.read('ssIasZone', ['iasCieAddr', 'zoneState', 'zoneId']);
|
|
862
|
+
},
|
|
863
|
+
exposes: [e.battery(), e.battery_low(), e.water_leak(),
|
|
864
|
+
exposes.binary('active_water_leak', ea.STATE, true, false)
|
|
865
|
+
.withDescription('Indicates whether there is an active water leak'),
|
|
866
|
+
],
|
|
867
|
+
},
|
|
868
|
+
{
|
|
869
|
+
zigbeeModel: ['AX Valve Controller'],
|
|
870
|
+
model: 'AX_Valve_Controller',
|
|
871
|
+
vendor: 'CTM Lyng',
|
|
872
|
+
description: 'AX Valve Controller, water shutoff valve controller',
|
|
873
|
+
fromZigbee: [fz.on_off, fz.ias_enroll, fzLocal.ctm_water_leak_alarm],
|
|
874
|
+
toZigbee: [tz.on_off],
|
|
875
|
+
meta: {disableDefaultResponse: true},
|
|
876
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
877
|
+
const endpoint = device.getEndpoint(1);
|
|
878
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'ssIasZone']);
|
|
879
|
+
await endpoint.read('genOnOff', ['onOff']);
|
|
880
|
+
await reporting.onOff(endpoint);
|
|
881
|
+
await endpoint.read('ssIasZone', ['iasCieAddr', 'zoneState', 'zoneId']);
|
|
882
|
+
},
|
|
883
|
+
exposes: [e.switch(), e.water_leak(),
|
|
884
|
+
exposes.binary('active_water_leak', ea.STATE, true, false)
|
|
885
|
+
.withDescription('Indicates whether there is an active water leak'),
|
|
886
|
+
],
|
|
887
|
+
},
|
|
888
|
+
{
|
|
889
|
+
zigbeeModel: ['Mikrofon'],
|
|
890
|
+
model: 'mSwitch_Mic',
|
|
891
|
+
vendor: 'CTM Lyng',
|
|
892
|
+
description: 'Mikrofon, alarm detection microphone',
|
|
893
|
+
fromZigbee: [fz.temperature, fz.battery, fz.command_on, fz.command_off, fz.ias_enroll, fz.ias_smoke_alarm_1,
|
|
894
|
+
fzLocal.ctm_group_config],
|
|
895
|
+
toZigbee: [],
|
|
896
|
+
meta: {battery: {voltageToPercentage: '3V_2500_3200'}},
|
|
897
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
898
|
+
const endpoint = device.getEndpoint(1);
|
|
899
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'ssIasZone', 'msTemperatureMeasurement']);
|
|
900
|
+
await reporting.batteryVoltage(endpoint);
|
|
901
|
+
await endpoint.read('ssIasZone', ['iasCieAddr', 'zoneState', 'zoneId']);
|
|
902
|
+
await endpoint.read('msTemperatureMeasurement', ['measuredValue']);
|
|
903
|
+
await reporting.temperature(endpoint, {min: constants.repInterval.MINUTES_10, max: constants.repInterval.HOUR, change: 100});
|
|
904
|
+
await endpoint.read(0xFEA7, [0x0000], {manufacturerCode: 0x1337});
|
|
905
|
+
},
|
|
906
|
+
exposes: [e.temperature(), e.battery(), e.battery_low(), e.smoke(),
|
|
907
|
+
e.action(['on', 'off']),
|
|
908
|
+
exposes.numeric('group_id', ea.STATE)
|
|
909
|
+
.withDescription('The device sends commands with this group ID. Put dvices in this group to control them.'),
|
|
910
|
+
],
|
|
911
|
+
},
|
|
912
|
+
{
|
|
913
|
+
zigbeeModel: ['Air Sensor'],
|
|
914
|
+
model: 'mTouch_Air_Sensor',
|
|
915
|
+
vendor: 'CTM Lyng',
|
|
916
|
+
description: 'Air Sensor, temperature & humidity sensor',
|
|
917
|
+
fromZigbee: [fz.battery, fz.temperature, fz.humidity],
|
|
918
|
+
toZigbee: [],
|
|
919
|
+
meta: {battery: {voltageToPercentage: '3V_2500_3200'}},
|
|
920
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
921
|
+
const endpoint = device.getEndpoint(1);
|
|
922
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'msTemperatureMeasurement', 'msRelativeHumidity']);
|
|
923
|
+
await reporting.batteryVoltage(endpoint);
|
|
924
|
+
await endpoint.read('msTemperatureMeasurement', ['measuredValue']);
|
|
925
|
+
await reporting.temperature(endpoint);
|
|
926
|
+
await endpoint.read('msRelativeHumidity', ['measuredValue']);
|
|
927
|
+
await reporting.humidity(endpoint);
|
|
928
|
+
},
|
|
929
|
+
exposes: [e.battery(), e.temperature(), e.humidity()],
|
|
930
|
+
},
|
|
931
|
+
{
|
|
932
|
+
zigbeeModel: ['MBD-S'],
|
|
933
|
+
model: 'MBD-S',
|
|
934
|
+
vendor: 'CTM Lyng',
|
|
935
|
+
description: 'MBD-S, motion detector with 16A relay',
|
|
936
|
+
fromZigbee: [fz.on_off, fz.illuminance, fz.occupancy, fzLocal.ctm_device_enabled],
|
|
937
|
+
toZigbee: [tz.on_off, tzLocal.ctm_device_enabled],
|
|
938
|
+
meta: {disableDefaultResponse: true},
|
|
939
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
940
|
+
const endpoint = device.getEndpoint(1);
|
|
941
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'msIlluminanceMeasurement', 'msOccupancySensing']);
|
|
942
|
+
await endpoint.read('genOnOff', ['onOff']);
|
|
943
|
+
await reporting.onOff(endpoint);
|
|
944
|
+
await endpoint.read('msIlluminanceMeasurement', ['measuredValue']);
|
|
945
|
+
await reporting.illuminance(endpoint);
|
|
946
|
+
await endpoint.read('msOccupancySensing', ['occupancy']);
|
|
947
|
+
await reporting.occupancy(endpoint);
|
|
948
|
+
// Device enabled
|
|
949
|
+
await endpoint.read('genOnOff', [0x2201]);
|
|
950
|
+
await endpoint.configureReporting('genOnOff', [{
|
|
951
|
+
attribute: {ID: 0x2201, type: dataType.boolean},
|
|
952
|
+
minimumReportInterval: 0,
|
|
953
|
+
maximumReportInterval: constants.repInterval.HOUR,
|
|
954
|
+
reportableChange: null}]);
|
|
955
|
+
},
|
|
956
|
+
exposes: [e.switch(), e.illuminance(), e.illuminance_lux(), e.occupancy(),
|
|
957
|
+
exposes.binary('device_enabled', ea.ALL, 'ON', 'OFF')
|
|
958
|
+
.withDescription('Turn the device on or off'),
|
|
959
|
+
],
|
|
960
|
+
},
|
|
961
|
+
];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const fz = require('../converters/fromZigbee');
|
|
2
|
+
const tz = require('../converters/toZigbee');
|
|
3
|
+
const reporting = require('../lib/reporting');
|
|
4
|
+
const exposes = require('../lib/exposes');
|
|
5
|
+
const e = exposes.presets;
|
|
6
|
+
|
|
7
|
+
module.exports = [
|
|
8
|
+
{
|
|
9
|
+
zigbeeModel: ['PSE03-V1.1.0'],
|
|
10
|
+
model: 'PSE03-V1.1.0',
|
|
11
|
+
vendor: 'EVOLOGY',
|
|
12
|
+
description: 'Sound and flash siren',
|
|
13
|
+
fromZigbee: [fz.ignore_basic_report, fz.ias_wd, fz.ias_enroll, fz.ias_siren],
|
|
14
|
+
toZigbee: [tz.warning],
|
|
15
|
+
meta: {disableDefaultResponse: true},
|
|
16
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
17
|
+
const endpoint = device.getEndpoint(1);
|
|
18
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'ssIasZone', 'ssIasWd', 'genBasic']);
|
|
19
|
+
await endpoint.read('ssIasZone', ['zoneState', 'iasCieAddr', 'zoneId', 'zoneStatus']);
|
|
20
|
+
await endpoint.read('ssIasWd', ['maxDuration']);
|
|
21
|
+
},
|
|
22
|
+
exposes: [e.warning().removeFeature('strobe_level').removeFeature('strobe').removeFeature('strobe_duty_cycle')],
|
|
23
|
+
},
|
|
24
|
+
];
|
package/devices/heiman.js
CHANGED
|
@@ -256,7 +256,8 @@ module.exports = [
|
|
|
256
256
|
exposes: [e.carbon_monoxide(), e.battery_low(), e.battery()],
|
|
257
257
|
},
|
|
258
258
|
{
|
|
259
|
-
fingerprint: [{modelID: 'TS0216', manufacturerName: '_TYZB01_8scntis1'}
|
|
259
|
+
fingerprint: [{modelID: 'TS0216', manufacturerName: '_TYZB01_8scntis1'},
|
|
260
|
+
{modelID: 'TS0216', manufacturerName: '_TYZB01_4obovpbi'}],
|
|
260
261
|
zigbeeModel: ['WarningDevice', 'WarningDevice-EF-3.0', 'SRHMP-I1'],
|
|
261
262
|
model: 'HS2WD-E',
|
|
262
263
|
vendor: 'HEIMAN',
|
package/devices/hive.js
CHANGED
|
@@ -91,7 +91,7 @@ module.exports = [
|
|
|
91
91
|
model: '1613V',
|
|
92
92
|
vendor: 'Hive',
|
|
93
93
|
description: 'Active plug',
|
|
94
|
-
fromZigbee: [fz.on_off, fz.metering
|
|
94
|
+
fromZigbee: [fz.on_off, fz.metering],
|
|
95
95
|
toZigbee: [tz.on_off],
|
|
96
96
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
97
97
|
const endpoint = device.getEndpoint(9);
|
|
@@ -99,8 +99,9 @@ module.exports = [
|
|
|
99
99
|
await reporting.onOff(endpoint);
|
|
100
100
|
await reporting.readMeteringMultiplierDivisor(endpoint);
|
|
101
101
|
await reporting.instantaneousDemand(endpoint);
|
|
102
|
+
await reporting.currentSummDelivered(endpoint);
|
|
102
103
|
},
|
|
103
|
-
exposes: [e.switch(), e.power(), e.energy()
|
|
104
|
+
exposes: [e.switch(), e.power(), e.energy()],
|
|
104
105
|
},
|
|
105
106
|
{
|
|
106
107
|
zigbeeModel: ['TWBulb01US'],
|
package/devices/ledvance.js
CHANGED
|
@@ -159,4 +159,12 @@ module.exports = [
|
|
|
159
159
|
extend: extend.ledvance.light_onoff_brightness_colortemp_color({colorTempRange: [153, 526]}),
|
|
160
160
|
ota: ota.ledvance,
|
|
161
161
|
},
|
|
162
|
+
{
|
|
163
|
+
zigbeeModel: ['A60S RGBW'],
|
|
164
|
+
model: '4058075208391',
|
|
165
|
+
vendor: 'LEDVANCE',
|
|
166
|
+
description: 'SMART+ lamp E27 RGBW',
|
|
167
|
+
extend: extend.ledvance.light_onoff_brightness_colortemp_color({colorTempRange: [153, 370]}),
|
|
168
|
+
ota: ota.ledvance,
|
|
169
|
+
},
|
|
162
170
|
];
|
package/devices/tuya.js
CHANGED
|
@@ -406,6 +406,7 @@ module.exports = [
|
|
|
406
406
|
{modelID: 'TS0001', manufacturerName: '_TZ3000_qsp2pwtf'}],
|
|
407
407
|
model: 'WHD02',
|
|
408
408
|
vendor: 'TuYa',
|
|
409
|
+
whiteLabel: [{vendor: 'TuYa', model: 'iHSW02'}],
|
|
409
410
|
description: 'Wall switch module',
|
|
410
411
|
toZigbee: extend.switch().toZigbee.concat([tz.moes_power_on_behavior, tz.tuya_switch_type]),
|
|
411
412
|
fromZigbee: extend.switch().fromZigbee.concat([fz.moes_power_on_behavior, fz.tuya_switch_type]),
|
package/devices/ubisys.js
CHANGED
|
@@ -74,6 +74,22 @@ const ubisys = {
|
|
|
74
74
|
}
|
|
75
75
|
},
|
|
76
76
|
},
|
|
77
|
+
configure_device_setup: {
|
|
78
|
+
cluster: 'manuSpecificUbisysDeviceSetup',
|
|
79
|
+
type: ['attributeReport', 'readResponse'],
|
|
80
|
+
convert: (model, msg, publish, options, meta) => {
|
|
81
|
+
const result = {};
|
|
82
|
+
if (msg.data.hasOwnProperty('input_configurations')) {
|
|
83
|
+
result['input_configurations'] = msg.data['input_configurations'];
|
|
84
|
+
}
|
|
85
|
+
if (msg.data.hasOwnProperty('inputActions')) {
|
|
86
|
+
result['input_actions'] = msg.data['inputActions'].map(function(el) {
|
|
87
|
+
return Object.values(el);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return {configure_device_setup: result};
|
|
91
|
+
},
|
|
92
|
+
},
|
|
77
93
|
},
|
|
78
94
|
tz: {
|
|
79
95
|
configure_j1: {
|
|
@@ -482,13 +498,9 @@ const ubisys = {
|
|
|
482
498
|
},
|
|
483
499
|
|
|
484
500
|
convertGet: async (entity, key, meta) => {
|
|
485
|
-
const log = (dataRead) => {
|
|
486
|
-
meta.logger.warn(
|
|
487
|
-
`ubisys: Device setup read for '${meta.options.friendly_name}': ${JSON.stringify(utils.toSnakeCase(dataRead))}`);
|
|
488
|
-
};
|
|
489
501
|
const devMgmtEp = meta.device.getEndpoint(232);
|
|
490
|
-
|
|
491
|
-
|
|
502
|
+
await devMgmtEp.read('manuSpecificUbisysDeviceSetup', ['inputConfigurations', 'inputActions'],
|
|
503
|
+
manufacturerOptions.ubisysNull);
|
|
492
504
|
},
|
|
493
505
|
},
|
|
494
506
|
},
|
|
@@ -507,7 +519,7 @@ module.exports = [
|
|
|
507
519
|
]),
|
|
508
520
|
e.power_on_behavior()],
|
|
509
521
|
fromZigbee: [fz.on_off, fz.metering, fz.command_toggle, fz.command_on, fz.command_off, fz.command_recall, fz.command_move,
|
|
510
|
-
fz.command_stop, fz.power_on_behavior],
|
|
522
|
+
fz.command_stop, fz.power_on_behavior, ubisys.fz.configure_device_setup],
|
|
511
523
|
toZigbee: [tz.on_off, tz.metering_power, ubisys.tz.configure_device_setup, tz.power_on_behavior],
|
|
512
524
|
endpoint: (device) => {
|
|
513
525
|
return {'l1': 1, 's1': 2, 'meter': 3};
|
|
@@ -549,7 +561,7 @@ module.exports = [
|
|
|
549
561
|
]),
|
|
550
562
|
e.power_on_behavior()],
|
|
551
563
|
fromZigbee: [fz.on_off, fz.metering, fz.command_toggle, fz.command_on, fz.command_off, fz.command_recall, fz.command_move,
|
|
552
|
-
fz.command_stop, fz.power_on_behavior],
|
|
564
|
+
fz.command_stop, fz.power_on_behavior, ubisys.fz.configure_device_setup],
|
|
553
565
|
toZigbee: [tz.on_off, tz.metering_power, ubisys.tz.configure_device_setup, tz.power_on_behavior],
|
|
554
566
|
endpoint: (device) => {
|
|
555
567
|
return {'l1': 1, 's1': 2, 'meter': 4};
|
|
@@ -592,7 +604,7 @@ module.exports = [
|
|
|
592
604
|
'brightness_stop_s2']),
|
|
593
605
|
e.power_on_behavior().withEndpoint('l1'), e.power_on_behavior().withEndpoint('l2')],
|
|
594
606
|
fromZigbee: [fz.on_off, fz.metering, fz.command_toggle, fz.command_on, fz.command_off, fz.command_recall, fz.command_move,
|
|
595
|
-
fz.command_stop, fz.power_on_behavior],
|
|
607
|
+
fz.command_stop, fz.power_on_behavior, ubisys.fz.configure_device_setup],
|
|
596
608
|
toZigbee: [tz.on_off, tz.metering_power, ubisys.tz.configure_device_setup, tz.power_on_behavior],
|
|
597
609
|
endpoint: (device) => {
|
|
598
610
|
return {'l1': 1, 'l2': 2, 's1': 3, 's2': 4, 'meter': 5};
|
|
@@ -638,7 +650,7 @@ module.exports = [
|
|
|
638
650
|
description: 'Universal dimmer D1',
|
|
639
651
|
fromZigbee: [fz.on_off, fz.brightness, fz.metering, fz.command_toggle, fz.command_on, fz.command_off, fz.command_recall,
|
|
640
652
|
fz.command_move, fz.command_stop, fz.lighting_ballast_configuration, fz.level_config, ubisys.fz.dimmer_setup,
|
|
641
|
-
ubisys.fz.dimmer_setup_genLevelCtrl],
|
|
653
|
+
ubisys.fz.dimmer_setup_genLevelCtrl, ubisys.fz.configure_device_setup],
|
|
642
654
|
toZigbee: [tz.light_onoff_brightness, tz.ballast_config, tz.level_config, ubisys.tz.dimmer_setup,
|
|
643
655
|
ubisys.tz.dimmer_setup_genLevelCtrl, ubisys.tz.configure_device_setup, tz.ignore_transition, tz.light_brightness_move,
|
|
644
656
|
tz.light_brightness_step],
|
|
@@ -702,7 +714,7 @@ module.exports = [
|
|
|
702
714
|
model: 'J1',
|
|
703
715
|
vendor: 'Ubisys',
|
|
704
716
|
description: 'Shutter control J1',
|
|
705
|
-
fromZigbee: [fz.cover_position_tilt, fz.metering],
|
|
717
|
+
fromZigbee: [fz.cover_position_tilt, fz.metering, ubisys.fz.configure_device_setup],
|
|
706
718
|
toZigbee: [tz.cover_state, tz.cover_position_tilt, tz.metering_power,
|
|
707
719
|
ubisys.tz.configure_j1, ubisys.tz.configure_device_setup],
|
|
708
720
|
exposes: [e.cover_position_tilt(),
|
|
@@ -739,7 +751,8 @@ module.exports = [
|
|
|
739
751
|
model: 'C4',
|
|
740
752
|
vendor: 'Ubisys',
|
|
741
753
|
description: 'Control unit C4',
|
|
742
|
-
fromZigbee: [fz.legacy.ubisys_c4_scenes, fz.legacy.ubisys_c4_onoff, fz.legacy.ubisys_c4_level, fz.legacy.ubisys_c4_cover
|
|
754
|
+
fromZigbee: [fz.legacy.ubisys_c4_scenes, fz.legacy.ubisys_c4_onoff, fz.legacy.ubisys_c4_level, fz.legacy.ubisys_c4_cover,
|
|
755
|
+
ubisys.fz.configure_device_setup],
|
|
743
756
|
toZigbee: [ubisys.tz.configure_device_setup],
|
|
744
757
|
exposes: [e.action([
|
|
745
758
|
'1_scene_*', '1_on', '1_off', '1_toggle', '1_level_move_down', '1_level_move_up',
|
package/lib/utils.js
CHANGED
|
@@ -75,12 +75,12 @@ function hasAlreadyProcessedMessage(msg, ID=null, key=null) {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
const defaultPrecision = {temperature: 2, humidity: 2, pressure: 1, pm25: 0, power: 2, current: 2, current_phase_b: 2, current_phase_c: 2,
|
|
78
|
-
voltage: 2, voltage_phase_b: 2, voltage_phase_c: 2};
|
|
78
|
+
voltage: 2, voltage_phase_b: 2, voltage_phase_c: 2, power_phase_b: 2, power_phase_c: 2};
|
|
79
79
|
function calibrateAndPrecisionRoundOptions(number, options, type) {
|
|
80
80
|
// Calibrate
|
|
81
81
|
const calibrateKey = `${type}_calibration`;
|
|
82
82
|
let calibrationOffset = options && options.hasOwnProperty(calibrateKey) ? options[calibrateKey] : 0;
|
|
83
|
-
if (
|
|
83
|
+
if (type.startsWith('current') || type.startsWith('voltage') || type.startsWith('power') || type.startsWith('illuminance')) {
|
|
84
84
|
// linear calibration because measured value is zero based
|
|
85
85
|
// +/- percent
|
|
86
86
|
calibrationOffset = Math.round(number * calibrationOffset / 100);
|