zigbee-herdsman-converters 14.0.323 → 14.0.327

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.
@@ -1969,7 +1969,7 @@ const converters = {
1969
1969
  convertSet: async (entity, key, value, meta) => {
1970
1970
  if (['ZNCZ04LM', 'QBKG25LM', 'SSM-U01', 'SSM-U02', 'DLKZMK11LM', 'DLKZMK12LM', 'QBKG39LM', 'QBKG41LM', 'ZNCZ15LM',
1971
1971
  'WS-EUK01', 'WS-EUK02', 'WS-EUK03', 'WS-EUK04', 'QBKG31LM', 'QBCZ15LM', 'QBKG20LM', 'QBKG38LM',
1972
- 'QBKG34LM', 'QBCZ14LM', 'QBKG19LM'].includes(meta.mapped.model)) {
1972
+ 'QBKG34LM', 'QBCZ14LM', 'QBKG19LM', 'QBKG40LM', 'QBKG41LM'].includes(meta.mapped.model)) {
1973
1973
  await entity.write('aqaraOpple', {0x0201: {value: value ? 1 : 0, type: 0x10}}, manufacturerOptions.xiaomi);
1974
1974
  } else if (['ZNCZ02LM', 'QBCZ11LM'].includes(meta.mapped.model)) {
1975
1975
  const payload = value ?
@@ -1992,7 +1992,7 @@ const converters = {
1992
1992
  convertGet: async (entity, key, meta) => {
1993
1993
  if (['ZNCZ04LM', 'QBKG25LM', 'SSM-U01', 'SSM-U02', 'DLKZMK11LM', 'DLKZMK12LM', 'QBKG39LM', 'QBKG41LM', 'ZNCZ15LM',
1994
1994
  'WS-EUK02', 'WS-EUK01', 'QBKG31LM', 'QBCZ15LM', 'QBCZ14LM', 'QBKG20LM', 'QBKG34LM', 'QBKG19LM',
1995
- 'QBKG38LM'].includes(meta.mapped.model)) {
1995
+ 'QBKG38LM', 'QBKG40LM', 'QBKG41LM'].includes(meta.mapped.model)) {
1996
1996
  await entity.read('aqaraOpple', [0x0201]);
1997
1997
  } else if (['ZNCZ02LM', 'QBCZ11LM', 'ZNCZ11LM'].includes(meta.mapped.model)) {
1998
1998
  await entity.read('aqaraOpple', [0xFFF0]);
@@ -466,6 +466,20 @@ module.exports = [
466
466
  description: 'Zigbee 12W Downlight RGB+CCT (pro)',
467
467
  extend: gledoptoExtend.light_onoff_brightness_colortemp_color(),
468
468
  },
469
+ {
470
+ zigbeeModel: ['GL-D-006P'],
471
+ model: 'GL-D-006P',
472
+ vendor: 'Gledopto',
473
+ description: 'Zigbee 6W anti-glare downlight RGB+CCT (pro)',
474
+ extend: gledoptoExtend.light_onoff_brightness_colortemp_color({colorTempRange: [158, 495]}),
475
+ },
476
+ {
477
+ zigbeeModel: ['GL-D-007P'],
478
+ model: 'GL-D-007P',
479
+ vendor: 'Gledopto',
480
+ description: 'Zigbee 12W anti-glare downlight RGB+CCT (pro)',
481
+ extend: gledoptoExtend.light_onoff_brightness_colortemp_color({colorTempRange: [158, 495]}),
482
+ },
469
483
  {
470
484
  zigbeeModel: ['GL-FL-004TZ'],
471
485
  model: 'GL-FL-004TZ',
package/devices/ikea.js CHANGED
@@ -760,7 +760,7 @@ module.exports = [
760
760
  extend: tradfriExtend.light_onoff_brightness_colortemp_color(),
761
761
  },
762
762
  {
763
- zigbeeModel: ['TRADFRI bulb E14 CWS 470lm'],
763
+ zigbeeModel: ['TRADFRI bulb E14 CWS 470lm', 'TRADFRI bulb E12 CWS 450lm'],
764
764
  model: 'LED1925G6',
765
765
  vendor: 'IKEA',
766
766
  description: 'TRADFRI LED bulb E14 470 lumen, opal, dimmable, white spectrum, color spectrum',
package/devices/lidl.js CHANGED
@@ -6,6 +6,356 @@ const extend = require('../lib/extend');
6
6
  const e = exposes.presets;
7
7
  const ea = exposes.access;
8
8
  const tuya = require('../lib/tuya');
9
+ const globalStore = require('../lib/store');
10
+
11
+ const tuyaLocal = {
12
+ dataPoints: {
13
+ zsHeatingSetpoint: 16,
14
+ zsChildLock: 40,
15
+ zsTempCalibration: 104,
16
+ zsLocalTemp: 24,
17
+ zsBatteryVoltage: 35,
18
+ zsComfortTemp: 101,
19
+ zsEcoTemp: 102,
20
+ zsHeatingSetpointAuto: 105,
21
+ zsOpenwindowTemp: 116,
22
+ zsOpenwindowTime: 117,
23
+ zsErrorStatus: 45,
24
+ zsMode: 2,
25
+ zsAwaySetting: 103,
26
+ zsBinaryOne: 106,
27
+ zsBinaryTwo: 107,
28
+ zsScheduleMonday: 109,
29
+ zsScheduleTuesday: 110,
30
+ zsScheduleWednesday: 111,
31
+ zsScheduleThursday: 112,
32
+ zsScheduleFriday: 113,
33
+ zsScheduleSaturday: 114,
34
+ zsScheduleSunday: 115,
35
+ },
36
+ };
37
+
38
+ const fzLocal = {
39
+ zs_thermostat: {
40
+ cluster: 'manuSpecificTuya',
41
+ type: ['commandGetData', 'commandSetDataResponse'],
42
+ convert: (model, msg, publish, options, meta) => {
43
+ const dp = msg.data.dp;
44
+ const value = tuya.getDataValue(msg.data.datatype, msg.data.data);
45
+ const ret = {};
46
+ const daysMap = {1: 'monday', 2: 'tuesday', 3: 'wednesday', 4: 'thursday', 5: 'friday', 6: 'saturday', 7: 'sunday'};
47
+ const day = daysMap[value[0]];
48
+
49
+ switch (dp) {
50
+ case tuyaLocal.dataPoints.zsChildLock:
51
+ return {child_lock: value ? 'LOCK' : 'UNLOCK'};
52
+
53
+ case tuyaLocal.dataPoints.zsHeatingSetpoint:
54
+ if (value==0) ret.system_mode='off';
55
+ if (value==60) {
56
+ ret.system_mode='heat';
57
+ ret.preset = 'boost';
58
+ }
59
+
60
+ ret.current_heating_setpoint= (value / 2).toFixed(1);
61
+ if (value>0 && value<60) globalStore.putValue(msg.endpoint, 'current_heating_setpoint', ret.current_heating_setpoint);
62
+ return ret;
63
+ case tuyaLocal.dataPoints.zsHeatingSetpointAuto:
64
+ return {current_heating_setpoint_auto: (value / 2).toFixed(1)};
65
+
66
+ case tuyaLocal.dataPoints.zsOpenwindowTemp:
67
+ return {detectwindow_temperature: (value / 2).toFixed(1)};
68
+
69
+ case tuyaLocal.dataPoints.zsOpenwindowTime:
70
+ return {detectwindow_timeminute: value};
71
+
72
+ case tuyaLocal.dataPoints.zsLocalTemp:
73
+ return {local_temperature: (value / 10).toFixed(1)};
74
+
75
+ case tuyaLocal.dataPoints.zsBatteryVoltage:
76
+ return {voltage: Math.round(value * 10)};
77
+
78
+ case tuyaLocal.dataPoints.zsTempCalibration:
79
+ return {local_temperature_calibration: value > 55 ?
80
+ ((value - 0x100000000)/10).toFixed(1): (value/ 10).toFixed(1)};
81
+
82
+ case tuyaLocal.dataPoints.zsBinaryOne:
83
+ return {binary_one: value ? 'ON' : 'OFF'};
84
+
85
+ case tuyaLocal.dataPoints.zsBinaryTwo:
86
+ return {binary_two: value ? 'ON' : 'OFF'};
87
+
88
+ case tuyaLocal.dataPoints.zsComfortTemp:
89
+ return {comfort_temperature: (value / 2).toFixed(1)};
90
+
91
+ case tuyaLocal.dataPoints.zsEcoTemp:
92
+ return {eco_temperature: (value / 2).toFixed(1)};
93
+
94
+ case tuyaLocal.dataPoints.zsAwayTemp:
95
+ return {away_preset_temperature: (value / 2).toFixed(1)};
96
+
97
+ case tuyaLocal.dataPoints.zsMode:
98
+ switch (value) {
99
+ case 1: // manual
100
+ return {system_mode: 'heat', away_mode: 'OFF', preset: 'manual'};
101
+ case 2: // away
102
+ return {system_mode: 'auto', away_mode: 'ON', preset: 'holiday'};
103
+ case 0: // auto
104
+ return {system_mode: 'auto', away_mode: 'OFF', preset: 'schedule'};
105
+ default:
106
+ meta.logger.warn('zigbee-herdsman-converters:zsThermostat: ' +
107
+ `preset ${value} is not recognized.`);
108
+ break;
109
+ }
110
+ break;
111
+ case tuyaLocal.dataPoints.zsScheduleMonday:
112
+ case tuyaLocal.dataPoints.zsScheduleTuesday:
113
+ case tuyaLocal.dataPoints.zsScheduleWednesday:
114
+ case tuyaLocal.dataPoints.zsScheduleThursday:
115
+ case tuyaLocal.dataPoints.zsScheduleFriday:
116
+ case tuyaLocal.dataPoints.zsScheduleSaturday:
117
+ case tuyaLocal.dataPoints.zsScheduleSunday:
118
+ for (let i = 1; i <= 9; i++) {
119
+ const tempId = ((i-1) * 2) +1;
120
+ const timeId = ((i-1) * 2) +2;
121
+ ret[`${day}_temp_${i}`] = (value[tempId] / 2).toFixed(1);
122
+ if (i!=9) {
123
+ ret[`${day}_hour_${i}`] = Math.floor(value[timeId] / 4).toString().padStart(2, '0');
124
+ ret[`${day}_minute_${i}`] = ((value[timeId] % 4) *15).toString().padStart(2, '0');
125
+ }
126
+ }
127
+ return ret;
128
+ case tuyaLocal.dataPoints.zsAwaySetting:
129
+ ret.away_preset_year = value[0];
130
+ ret.away_preset_month = value[1];
131
+ ret.away_preset_day = value[2];
132
+ ret.away_preset_hour = value[3];
133
+ ret.away_preset_minute = value[4];
134
+ ret.away_preset_temperature = (value[5] / 2).toFixed(1);
135
+ ret.away_preset_days = (value[6]<<8)+value[7];
136
+ return ret;
137
+ default:
138
+ meta.logger.warn(`zigbee-herdsman-converters:zsThermostat: Unrecognized DP #${dp} with data ${JSON.stringify(msg.data)}`);
139
+ }
140
+ },
141
+ },
142
+ };
143
+ const tzLocal = {
144
+ zs_thermostat_child_lock: {
145
+ key: ['child_lock'],
146
+ convertSet: async (entity, key, value, meta) => {
147
+ await tuya.sendDataPointBool(entity, tuyaLocal.dataPoints.zsChildLock, value === 'LOCK');
148
+ },
149
+ },
150
+ zs_thermostat_binary_one: {
151
+ key: ['binary_one'],
152
+ convertSet: async (entity, key, value, meta) => {
153
+ await tuya.sendDataPointBool(entity, tuyaLocal.dataPoints.zsBinaryOne, value === 'ON');
154
+ },
155
+ },
156
+ zs_thermostat_binary_two: {
157
+ key: ['binary_two'],
158
+ convertSet: async (entity, key, value, meta) => {
159
+ await tuya.sendDataPointBool(entity, tuyaLocal.dataPoints.zsBinaryTwo, value === 'ON');
160
+ },
161
+ },
162
+ zs_thermostat_current_heating_setpoint: {
163
+ key: ['current_heating_setpoint'],
164
+ convertSet: async (entity, key, value, meta) => {
165
+ let temp = Math.round(value * 2);
166
+ if (temp<=0) temp = 1;
167
+ if (temp>=60) temp = 59;
168
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsHeatingSetpoint, temp);
169
+ },
170
+ },
171
+ zs_thermostat_current_heating_setpoint_auto: {
172
+ key: ['current_heating_setpoint_auto'],
173
+ convertSet: async (entity, key, value, meta) => {
174
+ let temp = Math.round(value * 2);
175
+ if (temp<=0) temp = 1;
176
+ if (temp>=60) temp = 59;
177
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsHeatingSetpointAuto, temp);
178
+ },
179
+ },
180
+ zs_thermostat_comfort_temp: {
181
+ key: ['comfort_temperature'],
182
+ convertSet: async (entity, key, value, meta) => {
183
+ meta.logger.debug(JSON.stringify(entity));
184
+ const temp = Math.round(value * 2);
185
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsComfortTemp, temp);
186
+ },
187
+ },
188
+ zs_thermostat_openwindow_temp: {
189
+ key: ['detectwindow_temperature'],
190
+ convertSet: async (entity, key, value, meta) => {
191
+ let temp = Math.round(value * 2);
192
+ if (temp<=0) temp = 1;
193
+ if (temp>=60) temp = 59;
194
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsOpenwindowTemp, temp);
195
+ },
196
+ },
197
+ zs_thermostat_openwindow_time: {
198
+ key: ['detectwindow_timeminute'],
199
+ convertSet: async (entity, key, value, meta) => {
200
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsOpenwindowTime, value);
201
+ },
202
+ },
203
+ zs_thermostat_eco_temp: {
204
+ key: ['eco_temperature'],
205
+ convertSet: async (entity, key, value, meta) => {
206
+ const temp = Math.round(value * 2);
207
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsEcoTemp, temp);
208
+ },
209
+ },
210
+ zs_thermostat_preset_mode: {
211
+ key: ['preset'],
212
+ convertSet: async (entity, key, value, meta) => {
213
+ const lookup = {'schedule': 0, 'manual': 1, 'holiday': 2};
214
+ if (value == 'boost') {
215
+ await tuya.sendDataPointEnum(entity, tuyaLocal.dataPoints.zsMode, lookup['manual']);
216
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsHeatingSetpoint, 60);
217
+ } else {
218
+ await tuya.sendDataPointEnum(entity, tuyaLocal.dataPoints.zsMode, lookup[value]);
219
+ if (value == 'manual') {
220
+ const temp = globalStore.getValue(entity, 'current_heating_setpoint');
221
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsHeatingSetpoint, temp ? Math.round(temp * 2) : 43 );
222
+ }
223
+ }
224
+ },
225
+ },
226
+ zs_thermostat_system_mode: {
227
+ key: ['system_mode'],
228
+ convertSet: async (entity, key, value, meta) => {
229
+ if (value == 'off') {
230
+ await tuya.sendDataPointEnum(entity, tuyaLocal.dataPoints.zsMode, 1);
231
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsHeatingSetpoint, 0);
232
+ } else if (value == 'auto') {
233
+ await tuya.sendDataPointEnum(entity, tuyaLocal.dataPoints.zsMode, 0);
234
+ } else if (value == 'heat') {
235
+ // manual
236
+ const temp = globalStore.getValue(entity, 'current_heating_setpoint');
237
+ await tuya.sendDataPointEnum(entity, tuyaLocal.dataPoints.zsMode, 1);
238
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsHeatingSetpoint, temp ? Math.round(temp * 2) : 43 );
239
+ }
240
+ },
241
+ },
242
+ zs_thermostat_local_temperature_calibration: {
243
+ key: ['local_temperature_calibration'],
244
+ convertSet: async (entity, key, value, meta) => {
245
+ if (value > 0) value = value*10;
246
+ if (value < 0) value = value*10 + 0x100000000;
247
+ await tuya.sendDataPointValue(entity, tuyaLocal.dataPoints.zsTempCalibration, value);
248
+ },
249
+ },
250
+ zs_thermostat_away_setting: {
251
+ key: ['away_setting'],
252
+ convertSet: async (entity, key, value, meta) => {
253
+ const result = [];
254
+ const daysInMonth = new Date(2000+result[0], result[1], 0).getDate();
255
+
256
+ for (const attrName of ['away_preset_year',
257
+ 'away_preset_month',
258
+ 'away_preset_day',
259
+ 'away_preset_hour',
260
+ 'away_preset_minute',
261
+ 'away_preset_temperature',
262
+ 'away_preset_days']) {
263
+ let v = 0;
264
+ if (value.hasOwnProperty(attrName)) {
265
+ v = value[attrName];
266
+ } else if (meta.state.hasOwnProperty(attrName)) {
267
+ v = meta.state[attrName];
268
+ }
269
+ switch (attrName) {
270
+ case 'away_preset_year':
271
+ if (v<17 || v>99) v = 17;
272
+ result.push(Math.round(v));
273
+ break;
274
+ case 'away_preset_month':
275
+ if (v<1 || v>12) v = 1;
276
+ result.push(Math.round(v));
277
+ break;
278
+ case 'away_preset_day':
279
+ if (v<1) {
280
+ v = 1;
281
+ } else if (v>daysInMonth) {
282
+ v = daysInMonth;
283
+ }
284
+ result.push(Math.round(v));
285
+ break;
286
+ case 'away_preset_hour':
287
+ if (v<0 || v>23) v = 0;
288
+ result.push(Math.round(v));
289
+ break;
290
+ case 'away_preset_minute':
291
+ if (v<0 || v>59) v = 0;
292
+ result.push(Math.round(v));
293
+ break;
294
+ case 'away_preset_temperature':
295
+ if (v<0.5 || v>29.5) v = 17;
296
+ result.push(Math.round(v * 2));
297
+ break;
298
+ case 'away_preset_days':
299
+ if (v<1 || v>9999) v = 1;
300
+ result.push((v & 0xff00)>>8);
301
+ result.push((v & 0x00ff));
302
+ break;
303
+ }
304
+ }
305
+
306
+ await tuya.sendDataPointRaw(entity, tuyaLocal.dataPoints.zsAwaySetting, result);
307
+ },
308
+ },
309
+ zs_thermostat_local_schedule: {
310
+ key: ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'],
311
+ convertSet: async (entity, key, value, meta) => {
312
+ const daysMap = {'monday': 1, 'tuesday': 2, 'wednesday': 3, 'thursday': 4, 'friday': 5, 'saturday': 6, 'sunday': 7};
313
+ const day = daysMap[key];
314
+ const results = [];
315
+ results.push(day);
316
+ for (let i = 1; i <= 9; i++) {
317
+ // temperature
318
+ const attrName = `${key}_temp_${i}`;
319
+ let v = 17;
320
+ if (value.hasOwnProperty(attrName)) {
321
+ v = value[attrName];
322
+ } else if (meta.state.hasOwnProperty(attrName)) {
323
+ v = meta.state[attrName];
324
+ }
325
+ if (v<0.5 || v>29.5) v = 17;
326
+ results.push(Math.round(v * 2));
327
+ if (i!=9) {
328
+ // hour
329
+ let attrName = `${key}_hour_${i}`;
330
+ let h = 0;
331
+ if (value.hasOwnProperty(attrName)) {
332
+ h = value[attrName];
333
+ } else if (meta.state.hasOwnProperty(attrName)) {
334
+ h = meta.state[attrName];
335
+ }
336
+ // minute
337
+ attrName = `${key}_minute_${i}`;
338
+ let m = 0;
339
+ if (value.hasOwnProperty(attrName)) {
340
+ m = value[attrName];
341
+ } else if (meta.state.hasOwnProperty(attrName)) {
342
+ m = meta.state[attrName];
343
+ }
344
+ let rt = h*4 + m/15;
345
+ if (rt<1) {
346
+ rt =1;
347
+ } else if (rt>96) {
348
+ rt = 96;
349
+ }
350
+ results.push(Math.round(rt));
351
+ }
352
+ }
353
+ if (value > 0) value = value*10;
354
+ if (value < 0) value = value*10 + 0x100000000;
355
+ await tuya.sendDataPointRaw(entity, (109+day-1), results);
356
+ },
357
+ },
358
+ };
9
359
 
10
360
  module.exports = [
11
361
  {
@@ -301,4 +651,57 @@ module.exports = [
301
651
  await reporting.onOff(endpoint);
302
652
  },
303
653
  },
654
+ {
655
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_chyvmhay'}],
656
+ model: '368308_2010',
657
+ vendor: 'Lidl',
658
+ description: 'Silvercrest rdiator valve with thermostat',
659
+ fromZigbee: [fz.ignore_tuya_set_time, fzLocal.zs_thermostat, fz.tuya_data_point_dump],
660
+ toZigbee: [tzLocal.zs_thermostat_current_heating_setpoint, tzLocal.zs_thermostat_child_lock,
661
+ tzLocal.zs_thermostat_comfort_temp, tzLocal.zs_thermostat_eco_temp, tzLocal.zs_thermostat_preset_mode,
662
+ tzLocal.zs_thermostat_system_mode, tzLocal.zs_thermostat_local_temperature_calibration,
663
+ tzLocal.zs_thermostat_current_heating_setpoint_auto, tzLocal.zs_thermostat_openwindow_time,
664
+ tzLocal.zs_thermostat_openwindow_temp, tzLocal.zs_thermostat_binary_one, tzLocal.zs_thermostat_binary_two,
665
+ tzLocal.zs_thermostat_away_setting, tzLocal.zs_thermostat_local_schedule],
666
+ onEvent: tuya.onEventSetLocalTime,
667
+ configure: async (device, coordinatorEndpoint, logger) => {
668
+ const endpoint = device.getEndpoint(1);
669
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genBasic']);
670
+ },
671
+ exposes: [
672
+ e.child_lock(), e.comfort_temperature(), e.eco_temperature(), e.battery_voltage(),
673
+ exposes.numeric('current_heating_setpoint_auto', ea.STATE_SET).withValueMin(0.5).withValueMax(29.5)
674
+ .withValueStep(0.5).withUnit('°C').withDescription('Temperature setpoint automatic'),
675
+ exposes.climate().withSetpoint('current_heating_setpoint', 0.5, 29.5, 0.5, ea.STATE_SET)
676
+ .withLocalTemperature(ea.STATE).withLocalTemperatureCalibration(-20, 20, 1, ea.STATE_SET)
677
+ .withSystemMode(['off', 'heat', 'auto'], ea.STATE_SET)
678
+ .withPreset(['schedule', 'manual', 'holiday', 'boost']),
679
+ exposes.numeric('detectwindow_temperature', ea.STATE_SET).withUnit('°C').withDescription('Open window detection temperature'),
680
+ exposes.numeric('detectwindow_timeminute', ea.STATE_SET).withUnit('min').withDescription('Open window time in minute'),
681
+ exposes.binary('binary_one', ea.STATE_SET, 'ON', 'OFF').withDescription('Unknown binary one'),
682
+ exposes.binary('binary_two', ea.STATE_SET, 'ON', 'OFF').withDescription('Unknown binary two'),
683
+ exposes.binary('away_mode', ea.STATE, 'ON', 'OFF').withDescription('Away mode'),
684
+ exposes.composite('away_setting', 'away_setting').withFeature(e.away_preset_days()).setAccess('away_preset_days', ea.ALL)
685
+ .withFeature(e.away_preset_temperature()).setAccess('away_preset_temperature', ea.ALL)
686
+ .withFeature(exposes.numeric('away_preset_year', ea.ALL).withUnit('year').withDescription('Start away year 20xx'))
687
+ .withFeature(exposes.numeric('away_preset_month', ea.ALL).withUnit('month').withDescription('Start away month'))
688
+ .withFeature(exposes.numeric('away_preset_day', ea.ALL).withUnit('day').withDescription('Start away day'))
689
+ .withFeature(exposes.numeric('away_preset_hour', ea.ALL).withUnit('hour').withDescription('Start away hours'))
690
+ .withFeature(exposes.numeric('away_preset_minute', ea.ALL).withUnit('min').withDescription('Start away minutes')),
691
+ ...['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'].map((day) => {
692
+ const expose = exposes.composite(day, day);
693
+ [1, 2, 3, 4, 5, 6, 7, 8, 9].forEach((i) => {
694
+ expose.withFeature(exposes.numeric(`${day}_temp_${i}`, ea.ALL).withValueMin(0.5)
695
+ .withValueMax(29.5).withValueStep(0.5).withUnit('°C').withDescription(`Temperature ${i}`));
696
+ expose.withFeature(exposes.enum(`${day}_hour_${i}`, ea.STATE_SET,
697
+ ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09',
698
+ '10', '11', '12', '13', '14', '15', '16', '17', '18', '19',
699
+ '20', '21', '22', '23', '24']).withDescription(`Hour TO for temp ${i}`));
700
+ expose.withFeature(exposes.enum(`${day}_minute_${i}`, ea.STATE_SET, ['00', '15', '30', '45'])
701
+ .withDescription(`Minute TO for temp ${i}`));
702
+ });
703
+ return expose;
704
+ }),
705
+ ],
706
+ },
304
707
  ];
@@ -39,6 +39,6 @@ module.exports = [
39
39
  model: 'FUT038Z',
40
40
  description: 'RGBW LED controller',
41
41
  vendor: 'Miboxer',
42
- extend: extend.light_onoff_brightness_colortemp({disableColorTempStartup: true, colorTempRange: [153, 500]}),
42
+ extend: extend.light_onoff_brightness_colortemp_color({disableColorTempStartup: true, colorTempRange: [153, 500]}),
43
43
  },
44
44
  ];
@@ -38,6 +38,15 @@ module.exports = [
38
38
  extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 500]}),
39
39
  ota: ota.zigbeeOTA,
40
40
  },
41
+ {
42
+ zigbeeModel: ['929003054301'],
43
+ model: '929003054301',
44
+ vendor: 'Philips',
45
+ description: 'Hue White Ambiance Cher Pendant',
46
+ meta: {turnsOffAtBrightness1: true},
47
+ extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
48
+ ota: ota.zigbeeOTA,
49
+ },
41
50
  {
42
51
  zigbeeModel: ['5063131P7'],
43
52
  model: '5063131P7',
@@ -726,6 +735,15 @@ module.exports = [
726
735
  extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
727
736
  ota: ota.zigbeeOTA,
728
737
  },
738
+ {
739
+ zigbeeModel: ['LCA006'],
740
+ model: '9290024689',
741
+ vendor: 'Philips',
742
+ description: 'Hue white and color ambiance B22 1100lm',
743
+ meta: {turnsOffAtBrightness1: true},
744
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
745
+ ota: ota.zigbeeOTA,
746
+ },
729
747
  {
730
748
  zigbeeModel: ['LCA008'],
731
749
  model: '929002471601',
@@ -1067,6 +1085,15 @@ module.exports = [
1067
1085
  extend: hueExtend.light_onoff_brightness_colortemp_color(),
1068
1086
  ota: ota.zigbeeOTA,
1069
1087
  },
1088
+ {
1089
+ zigbeeModel: ['4090231P9'],
1090
+ model: '4090231P9',
1091
+ vendor: 'Philips',
1092
+ description: 'Hue Liane',
1093
+ meta: {turnsOffAtBrightness1: true},
1094
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
1095
+ ota: ota.zigbeeOTA,
1096
+ },
1070
1097
  {
1071
1098
  zigbeeModel: ['LTC001'],
1072
1099
  model: '3261030P7',
@@ -1237,6 +1264,15 @@ module.exports = [
1237
1264
  extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
1238
1265
  ota: ota.zigbeeOTA,
1239
1266
  },
1267
+ {
1268
+ zigbeeModel: ['929003099101'],
1269
+ model: '929003099101',
1270
+ vendor: 'Philips',
1271
+ description: 'Hue white ambiance Aurelle rectangle panel light',
1272
+ meta: {turnsOffAtBrightness1: true},
1273
+ extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
1274
+ ota: ota.zigbeeOTA,
1275
+ },
1240
1276
  {
1241
1277
  zigbeeModel: ['LTC016'],
1242
1278
  model: '3216431P5',
@@ -1789,6 +1825,39 @@ module.exports = [
1789
1825
  },
1790
1826
  ota: ota.zigbeeOTA,
1791
1827
  },
1828
+ {
1829
+ zigbeeModel: ['SML003'],
1830
+ model: '9290030675',
1831
+ vendor: 'Philips',
1832
+ description: 'Hue motion sensor',
1833
+ fromZigbee: [fz.battery, fz.occupancy, fz.temperature, fz.occupancy_timeout, fz.illuminance,
1834
+ fz.hue_motion_sensitivity, fz.hue_motion_led_indication],
1835
+ exposes: [e.temperature(), e.occupancy(), e.battery(), e.illuminance_lux(), e.illuminance(),
1836
+ exposes.enum('motion_sensitivity', ea.ALL, ['low', 'medium', 'high']),
1837
+ exposes.binary('led_indication', ea.ALL, true, false).withDescription('Blink green LED on motion detection'),
1838
+ exposes.numeric('occupancy_timeout', ea.ALL).withUnit('second').withValueMin(0).withValueMax(65535)],
1839
+ toZigbee: [tz.occupancy_timeout, tz.hue_motion_sensitivity, tz.hue_motion_led_indication],
1840
+ endpoint: (device) => {
1841
+ return {
1842
+ 'default': 2, // default
1843
+ 'ep1': 1,
1844
+ 'ep2': 2, // e.g. for write to msOccupancySensing
1845
+ };
1846
+ },
1847
+ configure: async (device, coordinatorEndpoint, logger) => {
1848
+ const endpoint = device.getEndpoint(2);
1849
+ const binds = ['genPowerCfg', 'msIlluminanceMeasurement', 'msTemperatureMeasurement', 'msOccupancySensing'];
1850
+ await reporting.bind(endpoint, coordinatorEndpoint, binds);
1851
+ await reporting.batteryPercentageRemaining(endpoint);
1852
+ await reporting.occupancy(endpoint);
1853
+ await reporting.temperature(endpoint);
1854
+ await reporting.illuminance(endpoint);
1855
+ // read occupancy_timeout and motion_sensitivity
1856
+ await endpoint.read('msOccupancySensing', ['pirOToUDelay']);
1857
+ await endpoint.read('msOccupancySensing', [48], {manufacturerCode: 4107});
1858
+ },
1859
+ ota: ota.zigbeeOTA,
1860
+ },
1792
1861
  {
1793
1862
  zigbeeModel: ['LOM001'],
1794
1863
  model: '929002240401',
@@ -2332,4 +2401,22 @@ module.exports = [
2332
2401
  extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
2333
2402
  ota: ota.zigbeeOTA,
2334
2403
  },
2404
+ {
2405
+ zigbeeModel: ['LTA005'],
2406
+ model: '8719514392830',
2407
+ vendor: 'Philips',
2408
+ description: 'Hue White Ambiance E27 filament screw globe',
2409
+ meta: {turnsOffAtBrightness1: true},
2410
+ extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [222, 454]}),
2411
+ ota: ota.zigbeeOTA,
2412
+ },
2413
+ {
2414
+ zigbeeModel: ['LWE007'],
2415
+ model: '9290030211',
2416
+ vendor: 'Philips',
2417
+ description: 'Hue white Candle bulb E14 bluetooth',
2418
+ meta: {turnsOffAtBrightness1: true},
2419
+ extend: hueExtend.light_onoff_brightness(),
2420
+ ota: ota.zigbeeOTA,
2421
+ },
2335
2422
  ];
@@ -70,7 +70,7 @@ module.exports = [
70
70
  exposes: [e.contact(), e.battery_low(), e.tamper(), e.temperature(), e.battery()],
71
71
  },
72
72
  {
73
- zigbeeModel: ['SZ-DWS08N', 'SZ-DWS08'],
73
+ zigbeeModel: ['SZ-DWS08N', 'SZ-DWS08', 'SZ-DWS08N-CZ3'],
74
74
  model: 'SZ-DWS08',
75
75
  vendor: 'Sercomm',
76
76
  description: 'Magnetic door & window contact sensor',
@@ -85,4 +85,16 @@ module.exports = [
85
85
  meta: {battery: {dontDividePercentage: true}},
86
86
  exposes: [e.contact(), e.battery_low(), e.battery(), e.battery_voltage()],
87
87
  },
88
+ {
89
+ zigbeeModel: ['3RSP019BZ'],
90
+ model: '3RSP019BZ',
91
+ vendor: 'Third Reality',
92
+ description: 'Zigbee / BLE smart plug',
93
+ extend: extend.switch(),
94
+ configure: async (device, coordinatorEndpoint, logger) => {
95
+ const endpoint = device.getEndpoint(1);
96
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
97
+ await reporting.onOff(endpoint);
98
+ },
99
+ },
88
100
  ];