zigbee-herdsman-converters 14.0.607 → 14.0.610

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.
@@ -1540,14 +1540,15 @@ const converters = {
1540
1540
  // HomeAssistant etc. work the other way round.
1541
1541
  // For zigbee-herdsman-converters: open = 100, close = 0
1542
1542
  // ubisys J1 will report 255 if lift or tilt positions are not known, so skip that.
1543
- const invert = model.meta && model.meta.coverInverted ? !options.invert_cover : options.invert_cover;
1543
+ const metaInvert = model.meta && model.meta.coverInverted;
1544
+ const invert = metaInvert ? !options.invert_cover : options.invert_cover;
1544
1545
  const coverStateFromTilt = model.meta && model.meta.coverStateFromTilt;
1545
1546
  if (msg.data.hasOwnProperty('currentPositionLiftPercentage') && msg.data['currentPositionLiftPercentage'] <= 100) {
1546
1547
  const value = msg.data['currentPositionLiftPercentage'];
1547
1548
  result[postfixWithEndpointName('position', msg, model, meta)] = invert ? value : 100 - value;
1548
1549
  if (!coverStateFromTilt) {
1549
1550
  result[postfixWithEndpointName('state', msg, model, meta)] =
1550
- invert ? (value === 100 ? 'CLOSE' : 'OPEN') : (value === 0 ? 'CLOSE' : 'OPEN');
1551
+ metaInvert ? (value === 0 ? 'CLOSE' : 'OPEN') : (value === 100 ? 'CLOSE' : 'OPEN');
1551
1552
  }
1552
1553
  }
1553
1554
  if (msg.data.hasOwnProperty('currentPositionTiltPercentage') && msg.data['currentPositionTiltPercentage'] <= 100) {
@@ -1555,7 +1556,7 @@ const converters = {
1555
1556
  result[postfixWithEndpointName('tilt', msg, model, meta)] = invert ? value : 100 - value;
1556
1557
  if (coverStateFromTilt) {
1557
1558
  result[postfixWithEndpointName('state', msg, model, meta)] =
1558
- invert ? (value === 100 ? 'OPEN' : 'CLOSE') : (value === 0 ? 'OPEN' : 'CLOSE');
1559
+ metaInvert ? (value === 100 ? 'OPEN' : 'CLOSE') : (value === 0 ? 'OPEN' : 'CLOSE');
1559
1560
  }
1560
1561
  }
1561
1562
  return result;
@@ -167,4 +167,12 @@ module.exports = [
167
167
  extend: extend.ledvance.light_onoff_brightness_colortemp_color({colorTempRange: [153, 370]}),
168
168
  ota: ota.ledvance,
169
169
  },
170
+ {
171
+ zigbeeModel: ['CLA 60 DIM'],
172
+ model: '4058075728981',
173
+ vendor: 'LEDVANCE',
174
+ description: 'SMART+ Classic A E27 dimmable white',
175
+ extend: extend.ledvance.light_onoff_brightness(),
176
+ ota: ota.ledvance,
177
+ },
170
178
  ];
package/devices/lidl.js CHANGED
@@ -366,6 +366,7 @@ module.exports = [
366
366
  {modelID: 'TS011F', manufacturerName: '_TZ3000_wamqdr3f'}, // FR
367
367
  {modelID: 'TS011F', manufacturerName: '_TZ3000_00mk2xzy'}, // BS
368
368
  {modelID: 'TS011F', manufacturerName: '_TZ3000_upjrsxh1'}, // DK
369
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_ynmowqk2'}, // FR
369
370
  {manufacturerName: '_TZ3000_00mk2xzy'}, // BS
370
371
  ],
371
372
  model: 'HG06337',
package/devices/moes.js CHANGED
@@ -8,10 +8,78 @@ const extend = require('../lib/extend');
8
8
  const e = exposes.presets;
9
9
  const ea = exposes.access;
10
10
  const zosung = require('../lib/zosung');
11
+ const utils = require('../lib/utils');
11
12
  const fzZosung = zosung.fzZosung;
12
13
  const tzZosung = zosung.tzZosung;
13
14
  const ez = zosung.presetsZosung;
14
15
 
16
+ const fzLocal = {
17
+ ZSEUD: {
18
+ cluster: 'manuSpecificTuya',
19
+ type: ['commandDataResponse', 'commandDataReport'],
20
+ convert: async (model, msg, publish, options, meta) => {
21
+ const result = {};
22
+ for (const dpValue of msg.data.dpValues) {
23
+ const dp = dpValue.dp;
24
+ const value = tuya.getDataValue(dpValue);
25
+ switch (dp) {
26
+ case 1:
27
+ result.state_l1 = value ? 'ON' : 'OFF';
28
+ break;
29
+ case 2:
30
+ result.brightness_l1 = utils.mapNumberRange(value, 0, 1000, 0, 254);
31
+ break;
32
+ case 7:
33
+ result.state_l2 = value ? 'ON' : 'OFF';
34
+ break;
35
+ case 8:
36
+ result.brightness_l2 = utils.mapNumberRange(value, 0, 1000, 0, 254);
37
+ break;
38
+ default:
39
+ meta.logger.warn(`zigbee-herdsman-converters:ZSEUD: NOT RECOGNIZED DP #${dp} with data ${JSON.stringify(dpValue)}`);
40
+ }
41
+ }
42
+ return result;
43
+ },
44
+ },
45
+ };
46
+
47
+ const tzLocal = {
48
+ ZSEUD_state: {
49
+ key: ['state'],
50
+ convertSet: async (entity, key, value, meta) => {
51
+ const lookup = {l1: 1, l2: 7};
52
+ const dp = lookup[meta.endpoint_name];
53
+ await tuya.sendDataPointBool(entity, dp, value === 'ON');
54
+ },
55
+ },
56
+ ZSEUD_brightness: {
57
+ key: ['brightness'],
58
+ convertSet: async (entity, key, value, meta) => {
59
+ const lookup = {l1: 2, l2: 8};
60
+ const dp = lookup[meta.endpoint_name];
61
+
62
+ if (key == 'brightness') {
63
+ // upscale to 1000
64
+ if (value >= 0 && value <= 254) {
65
+ const newValue = utils.mapNumberRange(value, 0, 254, 0, 1000);
66
+ // Always use same transid as tuya_dimmer_state (https://github.com/Koenkk/zigbee2mqtt/issues/6366)
67
+ if (meta.state[`state_${meta.endpoint_name}`] === 'ON') {
68
+ await tuya.sendDataPointValue(entity, dp, newValue, 'dataRequest', 1);
69
+ } else {
70
+ await tuya.sendDataPoints(entity, [tuya.dpValueFromBool(dp-1, true), tuya.dpValueFromIntValue(dp, newValue)],
71
+ 'dataRequest', 1);
72
+ }
73
+ } else {
74
+ throw new Error('Dimmer brightness is out of range 0..254');
75
+ }
76
+ } else {
77
+ meta.logger.warn(`ZSEUD TZ unsupported key=${key} value=${value}`);
78
+ }
79
+ },
80
+ },
81
+ };
82
+
15
83
  module.exports = [
16
84
  {
17
85
  fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_cymsnfvf'},
@@ -205,9 +273,14 @@ module.exports = [
205
273
  exposes: [e.switch().withEndpoint('l1').setAccess('state', ea.STATE_SET),
206
274
  e.switch().withEndpoint('l2').setAccess('state', ea.STATE_SET),
207
275
  e.switch().withEndpoint('l3').setAccess('state', ea.STATE_SET),
208
- e.switch().withEndpoint('l4').setAccess('state', ea.STATE_SET)],
209
- fromZigbee: [fz.ignore_basic_report, fz.tuya_switch],
210
- toZigbee: [tz.tuya_switch_state],
276
+ e.switch().withEndpoint('l4').setAccess('state', ea.STATE_SET),
277
+ exposes.enum('indicate_light', ea.STATE_SET, Object.values(tuya.moesSwitch.indicateLight))
278
+ .withDescription('Indicator light status'),
279
+ exposes.enum('power_on_behavior', ea.STATE_SET, Object.values(tuya.moesSwitch.powerOnBehavior))
280
+ .withDescription('Controls the behavior when the device is powered on')],
281
+ fromZigbee: [fz.ignore_basic_report, fz.tuya_switch, fz.moes_switch],
282
+ toZigbee: [tz.tuya_switch_state, tz.moes_switch],
283
+ onEvent: tuya.onEventSetLocalTime,
211
284
  meta: {multiEndpoint: true},
212
285
  endpoint: (device) => {
213
286
  // Endpoint selection is made in tuya_switch_state
@@ -285,8 +358,25 @@ module.exports = [
285
358
  exposes: [e.light_brightness().setAccess('state', ea.STATE_SET).setAccess('brightness', ea.STATE_SET)],
286
359
  },
287
360
  {
288
- fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_e3oitdyu'},
289
- {modelID: 'TS0601', manufacturerName: '_TZE200_fjjbhx9d'}],
361
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_fjjbhx9d'}],
362
+ model: 'ZS-EUD',
363
+ vendor: 'Moes',
364
+ description: '2 gang light dimmer switch',
365
+ fromZigbee: [fzLocal.ZSEUD, fz.ignore_basic_report],
366
+ toZigbee: [tzLocal.ZSEUD_brightness, tzLocal.ZSEUD_state],
367
+ meta: {turnsOffAtBrightness1: true, multiEndpoint: true},
368
+ configure: async (device, coordinatorEndpoint, logger) => {
369
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
370
+ if (device.getEndpoint(2)) await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
371
+ },
372
+ exposes: [e.light_brightness().withEndpoint('l1').setAccess('state', ea.STATE_SET).setAccess('brightness', ea.STATE_SET),
373
+ e.light_brightness().withEndpoint('l2').setAccess('state', ea.STATE_SET).setAccess('brightness', ea.STATE_SET)],
374
+ endpoint: (device) => {
375
+ return {'l1': 1, 'l2': 1};
376
+ },
377
+ },
378
+ {
379
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_e3oitdyu'}],
290
380
  model: 'MS-105B',
291
381
  vendor: 'Moes',
292
382
  description: 'Smart dimmer module (2 gang)',
@@ -343,7 +433,10 @@ module.exports = [
343
433
  exposes.enum('calibration', ea.STATE_SET, ['OFF', 'ON']), exposes.enum('motor_reversal', ea.STATE_SET, ['OFF', 'ON'])],
344
434
  },
345
435
  {
346
- fingerprint: [{modelID: 'TS1201', manufacturerName: '_TZ3290_j37rooaxrcdcqo5n'}],
436
+ fingerprint: [
437
+ {modelID: 'TS1201', manufacturerName: '_TZ3290_j37rooaxrcdcqo5n'},
438
+ {modelID: 'TS1201', manufacturerName: '_TZ3290_ot6ewjvmejq5ekhl'},
439
+ ],
347
440
  model: 'UFO-R11',
348
441
  vendor: 'Moes',
349
442
  description: 'Universal smart IR remote control',
package/devices/niko.js CHANGED
@@ -61,9 +61,8 @@ const local = {
61
61
  if (!operationModeLookup.hasOwnProperty(value)) {
62
62
  throw new Error(`operation_mode was called with an invalid value (${value})`);
63
63
  } else {
64
- const operationModeProperty = `operation_mode${meta.endpoint_name ? `_${meta.endpoint_name}` : ''}`;
65
64
  await entity.write('manuSpecificNiko1', {'switchOperationMode': operationModeLookup[value]});
66
- return {state: {[operationModeProperty]: value.toLowerCase()}};
65
+ return {state: {operation_mode: value.toLowerCase()}};
67
66
  }
68
67
  },
69
68
  convertGet: async (entity, key, meta) => {
package/devices/onesti.js CHANGED
@@ -8,7 +8,7 @@ const constants = require('../lib/constants');
8
8
 
9
9
  module.exports = [
10
10
  {
11
- zigbeeModel: ['easyCodeTouch_v1', 'EasyCodeTouch'],
11
+ zigbeeModel: ['easyCodeTouch_v1', 'EasyCodeTouch', 'EasyFingerTouch'],
12
12
  model: 'easyCodeTouch_v1',
13
13
  vendor: 'Onesti Products AS',
14
14
  description: 'Zigbee module for EasyAccess code touch series',
@@ -21,6 +21,8 @@ module.exports = [
21
21
  await reporting.lockState(endpoint);
22
22
  await reporting.batteryPercentageRemaining(endpoint);
23
23
  await endpoint.read('closuresDoorLock', ['lockState', 'soundVolume']);
24
+ device.powerSource = 'Battery';
25
+ device.save();
24
26
  },
25
27
  exposes: [e.lock(), e.battery(), e.sound_volume(),
26
28
  e.lock_action_source_name(), e.lock_action_user(),
@@ -59,15 +59,30 @@ const fzPerenio = {
59
59
  type: ['attributeReport', 'readResponse'],
60
60
  convert: (model, msg, publish, options, meta) => {
61
61
  const result = {};
62
+ if (msg.data.hasOwnProperty(2)) {
63
+ result['rms_current'] = msg.data[2];
64
+ }
62
65
  if (msg.data.hasOwnProperty(3)) {
63
66
  result['rms_voltage'] = msg.data[3];
64
67
  }
68
+ if (msg.data.hasOwnProperty(4)) {
69
+ result['voltage_min'] = msg.data[4];
70
+ }
71
+ if (msg.data.hasOwnProperty(5)) {
72
+ result['voltage_max'] = msg.data[5];
73
+ }
65
74
  if (msg.data.hasOwnProperty(10)) {
66
75
  result['active_power'] = msg.data[10];
67
76
  }
77
+ if (msg.data.hasOwnProperty(11)) {
78
+ result['power_max'] = msg.data[11];
79
+ }
68
80
  if (msg.data.hasOwnProperty(14)) {
69
81
  result['consumed_energy'] = msg.data[14];
70
82
  }
83
+ if (msg.data.hasOwnProperty(15)) {
84
+ result['consumed_energy_limit'] = msg.data[15];
85
+ }
71
86
  if (msg.data.hasOwnProperty(24)) {
72
87
  result['rssi'] = msg.data[24];
73
88
  }
@@ -84,6 +99,7 @@ const fzPerenio = {
84
99
  result['alarm_voltage_min'] = false;
85
100
  result['alarm_voltage_max'] = false;
86
101
  result['alarm_power_max'] = false;
102
+ result['alarm_consumed_energy'] = false;
87
103
  } else {
88
104
  if (msg.data[1] & 1) {
89
105
  result['alarm_voltage_min'] = true;
@@ -94,6 +110,9 @@ const fzPerenio = {
94
110
  if (msg.data[1] & 4) {
95
111
  result['alarm_power_max'] = true;
96
112
  }
113
+ if (msg.data[1] & 8) {
114
+ result['alarm_consumed_energy'] = true;
115
+ }
97
116
  }
98
117
  }
99
118
  return result;
@@ -135,15 +154,51 @@ const tzPerenio = {
135
154
  },
136
155
  },
137
156
  alarms_reset: {
138
- key: ['alarm_voltage_min', 'alarm_voltage_max', 'alarm_power_max'],
157
+ key: ['alarm_voltage_min', 'alarm_voltage_max', 'alarm_power_max', 'alarm_consumed_energy'],
139
158
  convertSet: async (entity, key, val, meta) => {
140
159
  await entity.write(64635, {1: {value: 0, type: 0x20}}, {manufacturerCode: 0x007B});
141
- return {state: {alarm_voltage_min: false, alarm_voltage_max: false, alarm_power_max: false}};
160
+ return {state: {alarm_voltage_min: false, alarm_voltage_max: false, alarm_power_max: false, alarm_consumed_energy: false}};
142
161
  },
143
162
  convertGet: async (entity, key, meta) => {
144
163
  await entity.read(64635, [1]);
145
164
  },
146
165
  },
166
+ alarms_limits: {
167
+ key: ['voltage_min', 'voltage_max', 'power_max', 'consumed_energy_limit'],
168
+ convertSet: async (entity, key, val, meta) => {
169
+ switch (key) {
170
+ case 'voltage_min':
171
+ await entity.write(64635, {4: {value: val, type: 0x21}}, {manufacturerCode: 0x007B});
172
+ break;
173
+ case 'voltage_max':
174
+ await entity.write(64635, {5: {value: val, type: 0x21}}, {manufacturerCode: 0x007B});
175
+ break;
176
+ case 'power_max':
177
+ await entity.write(64635, {11: {value: val, type: 0x21}}, {manufacturerCode: 0x007B});
178
+ break;
179
+ case 'consumed_energy_limit':
180
+ await entity.write(64635, {15: {value: val, type: 0x21}}, {manufacturerCode: 0x007B});
181
+ break;
182
+ }
183
+ return {state: {[key]: val}};
184
+ },
185
+ convertGet: async (entity, key, meta) => {
186
+ switch (key) {
187
+ case 'voltage_min':
188
+ await entity.read(64635, [4]);
189
+ break;
190
+ case 'voltage_max':
191
+ await entity.read(64635, [5]);
192
+ break;
193
+ case 'power_max':
194
+ await entity.read(64635, [11]);
195
+ break;
196
+ case 'consumed_energy_limit':
197
+ await entity.read(64635, [15]);
198
+ break;
199
+ }
200
+ },
201
+ },
147
202
  on_off_mod: {
148
203
  key: ['state', 'on_time', 'off_wait_time'],
149
204
  convertSet: async (entity, key, value, meta) => {
@@ -291,8 +346,8 @@ module.exports = [
291
346
  model: 'PEHPL0X',
292
347
  vendor: 'Perenio',
293
348
  description: 'Power link',
294
- fromZigbee: [fz.on_off, fzPerenio.smart_plug],
295
- toZigbee: [tzPerenio.on_off_mod, tzPerenio.default_state, tzPerenio.alarms_reset],
349
+ fromZigbee: [fz.on_off, fzPerenio.smart_plug, fz.metering],
350
+ toZigbee: [tzPerenio.on_off_mod, tzPerenio.default_state, tzPerenio.alarms_reset, tzPerenio.alarms_limits],
296
351
  configure: async (device, coordinatorEndpoint, logger) => {
297
352
  const endpoint = device.getEndpoint(1);
298
353
  await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 64635]);
@@ -303,7 +358,26 @@ module.exports = [
303
358
  reportableChange: 0,
304
359
  }];
305
360
  await endpoint.configureReporting('genOnOff', payload);
306
- await endpoint.read(64635, [0, 1]);
361
+ await endpoint.configureReporting(64635, [{
362
+ attribute: {ID: 0x000a, type: 0x21},
363
+ minimumReportInterval: 5,
364
+ maximumReportInterval: 60,
365
+ reportableChange: 0,
366
+ }]);
367
+ await endpoint.configureReporting(64635, [{
368
+ attribute: {ID: 0x000e, type: 0x23},
369
+ minimumReportInterval: 5,
370
+ maximumReportInterval: 60,
371
+ reportableChange: 0,
372
+ }]);
373
+ await endpoint.configureReporting(64635, [{
374
+ attribute: {ID: 0x0003, type: 0x21},
375
+ minimumReportInterval: 5,
376
+ maximumReportInterval: 5,
377
+ reportableChange: 0,
378
+ }]);
379
+ await endpoint.read(64635, [0, 1, 2, 3]);
380
+ await endpoint.read(64635, [4, 5, 11, 15]);
307
381
  },
308
382
  exposes: [
309
383
  e.switch(),
@@ -317,6 +391,17 @@ module.exports = [
317
391
  .withDescription('Indicates if the alarm is triggered on the voltage rise above the limit, allows to reset alarms'),
318
392
  exposes.binary('alarm_power_max', ea.ALL, true, false)
319
393
  .withDescription('Indicates if the alarm is triggered on the active power rise above the limit, allows to reset alarms'),
394
+ exposes.binary('alarm_consumed_energy', ea.ALL, true, false)
395
+ .withDescription(
396
+ 'Indicates if the alarm is triggered when the consumption energy limit is reached, allows to reset alarms'),
397
+ exposes.numeric('voltage_min', ea.ALL).withValueMin(0).withValueMax(253)
398
+ .withDescription('Minimum allowable voltage limit for alarms.'),
399
+ exposes.numeric('voltage_max', ea.ALL).withValueMin(0).withValueMax(253)
400
+ .withDescription('Maximum allowable voltage limit for alarms.'),
401
+ exposes.numeric('power_max', ea.ALL).withValueMin(0).withValueMax(65534)
402
+ .withDescription('Maximum allowable power limit for alarms.'),
403
+ exposes.numeric('consumed_energy_limit', ea.ALL).withValueMin(0).withValueMax(65534)
404
+ .withDescription('Limit of electric energy consumption in kW*h. 0 value represents no limit'),
320
405
  exposes.numeric('rssi', ea.STATE).withUnit('dB')
321
406
  .withDescription('RSSI seen by the device').withValueMin(-128).withValueMax(127),
322
407
  ],
@@ -0,0 +1,113 @@
1
+ const fz = require('../converters/fromZigbee');
2
+ const exposes = require('../lib/exposes');
3
+ const tuya = require('../lib/tuya');
4
+ const e = exposes.presets;
5
+ const ea = exposes.access;
6
+
7
+ const dataPoints = {
8
+ valve_state_auto_shutdown: 2,
9
+ water_flow: 3,
10
+ shutdown_timer: 11,
11
+ remaining_watering_time: 101,
12
+ valve_state: 102,
13
+ last_watering_duration: 107,
14
+ battery: 110,
15
+ };
16
+
17
+ const fzLocal = {
18
+ watering_timer: {
19
+ cluster: 'manuSpecificTuya',
20
+ type: ['commandDataReport'],
21
+ convert: (model, msg, publish, options, meta) => {
22
+ const result = {};
23
+ for (const dpValue of msg.data.dpValues) {
24
+ const dp = dpValue.dp; // First we get the data point ID
25
+ const value = tuya.getDataValue(dpValue); // This function will take care of converting the data to proper JS type
26
+ switch (dp) {
27
+ case dataPoints.water_flow: {
28
+ result.water_flow = value;
29
+ break;
30
+ }
31
+ case dataPoints.remaining_watering_time: {
32
+ result.remaining_watering_time = value;
33
+ break;
34
+ }
35
+ case dataPoints.last_watering_duration: {
36
+ result.last_watering_duration = value;
37
+ break;
38
+ }
39
+
40
+ case dataPoints.valve_state: {
41
+ result.valve_state = value;
42
+ break;
43
+ }
44
+
45
+ case dataPoints.shutdown_timer: {
46
+ result.shutdown_timer = value;
47
+ break;
48
+ }
49
+ case dataPoints.valve_state_auto_shutdown: {
50
+ result.valve_state_auto_shutdown = value;
51
+ result.valve_state = value;
52
+ break;
53
+ }
54
+
55
+ case dataPoints.battery: {
56
+ result.battery = value;
57
+ break;
58
+ }
59
+ default: {
60
+ meta.logger.debug(`>>> UNKNOWN DP #${dp} with data "${JSON.stringify(dpValue)}"`);
61
+ }
62
+ }
63
+ }
64
+ return result;
65
+ },
66
+ },
67
+ };
68
+
69
+ const tzLocal = {
70
+ valve_state: {
71
+ key: ['valve_state'],
72
+ convertSet: async (entity, key, value, meta) => {
73
+ await tuya.sendDataPointValue(entity, dataPoints.valve_state, value);
74
+ },
75
+ },
76
+ shutdown_timer: {
77
+ key: ['shutdown_timer'],
78
+ convertSet: async (entity, key, value, meta) => {
79
+ await tuya.sendDataPointValue(entity, dataPoints.shutdown_timer, value);
80
+ },
81
+ },
82
+ valve_state_auto_shutdown: {
83
+ key: ['valve_state_auto_shutdown'],
84
+ convertSet: async (entity, key, value, meta) => {
85
+ await tuya.sendDataPointValue(entity, dataPoints.valve_state_auto_shutdown, value);
86
+ },
87
+ },
88
+ };
89
+
90
+ module.exports = [
91
+ {
92
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_arge1ptm'}],
93
+ model: 'QT-05M',
94
+ vendor: 'QOTO',
95
+ description: 'Solar powered garden watering timer',
96
+ fromZigbee: [fz.ignore_basic_report, fz.ignore_tuya_set_time, fz.ignore_onoff_report, fzLocal.watering_timer],
97
+ toZigbee: [tzLocal.valve_state, tzLocal.shutdown_timer, tzLocal.valve_state_auto_shutdown],
98
+ exposes: [
99
+ exposes.numeric('water_flow', ea.STATE).withUnit('%').withValueMin(0).withDescription('Current water flow in %.'),
100
+ exposes.numeric('last_watering_duration', ea.STATE).withUnit('sec').withValueMin(0)
101
+ .withDescription('Last watering duration in seconds.'),
102
+ exposes.numeric('remaining_watering_time', ea.STATE).withUnit('sec').withValueMin(0)
103
+ .withDescription('Remaning watering time (for auto shutdown). Updates every minute, and every 10s in the last minute.'),
104
+ exposes.numeric('valve_state', ea.STATE_SET).withValueMin(0).withValueMax(100).withValueStep(5).withUnit('%')
105
+ .withDescription('Set valve to %.'),
106
+ exposes.numeric('shutdown_timer', ea.STATE_SET).withValueMin(0).withValueMax(14400).withUnit('sec')
107
+ .withDescription('Auto shutdown in seconds.'),
108
+ exposes.numeric('valve_state_auto_shutdown', ea.STATE_SET).withValueMin(0).withValueMax(100).withValueStep(5).withUnit('%')
109
+ .withDescription('Set valve to % with auto shutdown.'),
110
+ e.battery(),
111
+ ],
112
+ },
113
+ ];
package/devices/tuya.js CHANGED
@@ -20,15 +20,13 @@ const TS011Fplugs = ['_TZ3000_5f43h46b', '_TZ3000_cphmq0q7', '_TZ3000_dpo1ysak',
20
20
  '_TZ3000_rdtixbnu', '_TZ3000_typdpbpg', '_TZ3000_kx0pris5', '_TZ3000_amdymr7l', '_TZ3000_z1pnpsdo', '_TZ3000_ksw8qtmt',
21
21
  '_TZ3000_1h2x4akh', '_TZ3000_9vo5icau', '_TZ3000_cehuw1lw', '_TZ3000_ko6v90pg', '_TZ3000_f1bapcit', '_TZ3000_cjrngdr3',
22
22
  '_TZ3000_zloso4jk', '_TZ3000_r6buo8ba', '_TZ3000_iksasdbv', '_TZ3000_idrffznf', '_TZ3000_okaz9tjs', '_TZ3210_q7oryllx',
23
- '_TZ3000_ss98ec5d', '_TZ3000_gznh2xla'];
23
+ '_TZ3000_ss98ec5d', '_TZ3000_gznh2xla', '_TZ3000_hdopuwv6'];
24
24
 
25
25
  const tzLocal = {
26
26
  hpsz: {
27
27
  key: ['led_state'],
28
28
  convertSet: async (entity, key, value, meta) => {
29
- const ledState = value.toUpperCase() === 'ON' ? true : false;
30
- await tuya.sendDataPointBool(entity, tuya.dataPoints.HPSZLEDState, ledState);
31
- return {led_state: value};
29
+ await tuya.sendDataPointBool(entity, tuya.dataPoints.HPSZLEDState, value);
32
30
  },
33
31
  },
34
32
  TS0504B_color: {
@@ -803,6 +801,7 @@ module.exports = [
803
801
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_remypqqm'},
804
802
  {modelID: 'TS0505B', manufacturerName: '_TZ3000_kohbva1f'},
805
803
  {modelID: 'TS0505B', manufacturerName: '_TZ3000_luit1t00'},
804
+ {modelID: 'TS0505B', manufacturerName: '_TZ3210_r5afgmkl'},
806
805
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_wslkvrau'},
807
806
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_0rn9qhnu'},
808
807
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_ejctepku'},
@@ -828,6 +827,7 @@ module.exports = [
828
827
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_cuqkfz2q'},
829
828
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_6amjviba'},
830
829
  {modelID: 'TS0505B', manufacturerName: '_TZ3000_xr5m6kfg'},
830
+ {modelID: 'TS0505B', manufacturerName: '_TZ3210_xr5m6kfg'},
831
831
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_bf175wi4'}],
832
832
  model: 'TS0505B',
833
833
  vendor: 'TuYa',
@@ -888,7 +888,8 @@ module.exports = [
888
888
  {modelID: 'TS0501B', manufacturerName: '_TZ3210_nehayyhx'},
889
889
  {modelID: 'TS0501B', manufacturerName: '_TZ3210_wuheofsg'},
890
890
  {modelID: 'TS0501B', manufacturerName: '_TZ3210_e5t9bfdv'},
891
- {modelID: 'TS0501B', manufacturerName: '_TZ3210_19qb27da'}],
891
+ {modelID: 'TS0501B', manufacturerName: '_TZ3210_19qb27da'},
892
+ {modelID: 'TS0501B', manufacturerName: '_TZ3210_4zinq6io'}],
892
893
  model: 'TS0501B',
893
894
  description: 'Zigbee light',
894
895
  vendor: 'TuYa',
@@ -1466,7 +1467,7 @@ module.exports = [
1466
1467
  },
1467
1468
  },
1468
1469
  {
1469
- fingerprint: [{modelID: 'TS004F', manufacturerName: '_TZ3000_xabckq1v'}],
1470
+ fingerprint: [{modelID: 'TS004F', manufacturerName: '_TZ3000_xabckq1v'}, {modelID: 'TS004F', manufacturerName: '_TZ3000_czuyt8lz'}],
1470
1471
  model: 'TS004F',
1471
1472
  vendor: 'TuYa',
1472
1473
  description: 'Wireless switch with 4 buttons',
@@ -3133,7 +3134,7 @@ module.exports = [
3133
3134
  .withDescription('Shows the presence duration in minutes'),
3134
3135
  exposes.numeric('duration_of_absence', ea.STATE).withUnit('minutes')
3135
3136
  .withDescription('Shows the duration of the absence in minutes'),
3136
- exposes.enum('led_state', ea.STATE_SET, ['on', 'off'])
3137
+ exposes.binary('led_state', ea.STATE_SET, true, false)
3137
3138
  .withDescription('Turns the onboard LED on or off'),
3138
3139
  ],
3139
3140
  },
package/devices/woox.js CHANGED
@@ -34,6 +34,7 @@ const fzLocal = {
34
34
  case 14: {
35
35
  const batteryLevels = {0: 'low', 1: 'middle', 2: 'high'};
36
36
  result.battery_level = batteryLevels[value];
37
+ result.battery_low = value === 0;
37
38
  break;
38
39
  }
39
40
  case 16:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.607",
3
+ "version": "14.0.610",
4
4
  "description": "Collection of device converters to be used with zigbee-herdsman",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -38,7 +38,7 @@
38
38
  "buffer-crc32": "^0.2.13",
39
39
  "https-proxy-agent": "^5.0.1",
40
40
  "tar-stream": "^2.2.0",
41
- "zigbee-herdsman": "^0.14.48"
41
+ "zigbee-herdsman": "^0.14.51"
42
42
  },
43
43
  "devDependencies": {
44
44
  "eslint": "*",