zigbee-herdsman-converters 14.0.608 → 14.0.611

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.
@@ -4633,22 +4633,22 @@ const converters = {
4633
4633
  }
4634
4634
  },
4635
4635
  },
4636
- legrand_settingAlwaysEnableLed: {
4636
+ legrand_settingEnableLedInDark: {
4637
4637
  // connected power outlet is on attribute 2 and not 1
4638
- key: ['led_when_off'],
4638
+ key: ['led_in_dark'],
4639
4639
  convertSet: async (entity, key, value, meta) => {
4640
4640
  // enable or disable the LED (blue) when permitJoin=false (LED off)
4641
4641
  const enableLedIfOn = value === 'ON' || (value === 'OFF' ? false : !!value);
4642
4642
  const payload = {1: {value: enableLedIfOn, type: 16}};
4643
4643
  await entity.write('manuSpecificLegrandDevices', payload, manufacturerOptions.legrand);
4644
- return {state: {'led_when_off': value}};
4644
+ return {state: {'led_in_dark': value}};
4645
4645
  },
4646
4646
  convertGet: async (entity, key, meta) => {
4647
4647
  await entity.read('manuSpecificLegrandDevices', [0x0001], manufacturerOptions.legrand);
4648
4648
  },
4649
4649
  },
4650
4650
  legrand_settingEnableLedIfOn: {
4651
- key: ['led_when_on'],
4651
+ key: ['led_if_on'],
4652
4652
  convertSet: async (entity, key, value, meta) => {
4653
4653
  // enable the LED when the light object is "doing something"
4654
4654
  // on the light switch, the LED is on when the light is on,
@@ -4656,7 +4656,7 @@ const converters = {
4656
4656
  const enableLedIfOn = value === 'ON' || (value === 'OFF' ? false : !!value);
4657
4657
  const payload = {2: {value: enableLedIfOn, type: 16}};
4658
4658
  await entity.write('manuSpecificLegrandDevices', payload, manufacturerOptions.legrand);
4659
- return {state: {'led_when_on': value}};
4659
+ return {state: {'led_if_on': value}};
4660
4660
  },
4661
4661
  convertGet: async (entity, key, meta) => {
4662
4662
  await entity.read('manuSpecificLegrandDevices', [0x0002], manufacturerOptions.legrand);
@@ -13,11 +13,12 @@ module.exports = [
13
13
  vendor: 'BTicino',
14
14
  description: 'Light switch with neutral',
15
15
  fromZigbee: [fz.identify, fz.on_off, fz.K4003C_binary_input, fz.legrand_cluster_fc01],
16
- toZigbee: [tz.on_off, tz.legrand_settingAlwaysEnableLed, tz.legrand_settingEnableLedIfOn, tz.legrand_identify],
16
+ toZigbee: [tz.on_off, tz.legrand_settingEnableLedInDark, tz.legrand_settingEnableLedIfOn, tz.legrand_identify],
17
17
  exposes: [
18
18
  e.switch(), e.action(['identify', 'on', 'off']),
19
- exposes.binary('led_when_off', ea.ALL, 'ON', 'OFF').withDescription('Enables the LED when the light is off'),
20
- exposes.binary('led_when_on', ea.ALL, 'ON', 'OFF').withDescription('Enables the LED when the light is on'),
19
+ exposes.binary('led_in_dark', ea.ALL, 'ON', 'OFF').withDescription(`Enables the LED when the light is turned off, allowing to
20
+ see the switch in the dark`),
21
+ exposes.binary('led_if_on', ea.ALL, 'ON', 'OFF').withDescription('Enables the LED when the light is turned on'),
21
22
  ],
22
23
  configure: async (device, coordinatorEndpoint, logger) => {
23
24
  const endpoint = device.getEndpoint(1);
@@ -31,7 +32,7 @@ module.exports = [
31
32
  description: 'Dimmer switch with neutral',
32
33
  extend: extend.light_onoff_brightness({noConfigure: true}),
33
34
  fromZigbee: [fz.brightness, fz.identify, fz.on_off, fz.lighting_ballast_configuration, fz.legrand_cluster_fc01],
34
- toZigbee: [tz.light_onoff_brightness, tz.legrand_settingAlwaysEnableLed, tz.legrand_settingEnableLedIfOn,
35
+ toZigbee: [tz.light_onoff_brightness, tz.legrand_settingEnableLedInDark, tz.legrand_settingEnableLedIfOn,
35
36
  tz.legrand_deviceMode, tz.legrand_identify, tz.ballast_config],
36
37
  exposes: [e.light_brightness(),
37
38
  exposes.numeric('ballast_minimum_level', ea.ALL).withValueMin(1).withValueMax(254)
@@ -39,8 +40,9 @@ module.exports = [
39
40
  exposes.numeric('ballast_maximum_level', ea.ALL).withValueMin(1).withValueMax(254)
40
41
  .withDescription('Specifies the maximum brightness value'),
41
42
  exposes.binary('device_mode', ea.ALL, 'dimmer_on', 'dimmer_off').withDescription('Allow the device to change brightness'),
42
- exposes.binary('led_when_off', ea.ALL, 'ON', 'OFF').withDescription('Enables the LED when the light is off'),
43
- exposes.binary('led_when_on', ea.ALL, 'ON', 'OFF').withDescription('Enables the LED when the light is on')],
43
+ exposes.binary('led_in_dark', ea.ALL, 'ON', 'OFF').withDescription(`Enables the LED when the light is turned off, allowing to
44
+ see the switch in the dark`),
45
+ exposes.binary('led_if_on', ea.ALL, 'ON', 'OFF').withDescription('Enables the LED when the light is turned on')],
44
46
  configure: async (device, coordinatorEndpoint, logger) => {
45
47
  await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
46
48
  const endpoint = device.getEndpoint(1);
@@ -62,7 +64,7 @@ module.exports = [
62
64
  fromZigbee: [fz.identify, fz.ignore_basic_report, fz.ignore_zclversion_read, fz.bticino_4027C_binary_input_moving,
63
65
  fz.cover_position_tilt],
64
66
  toZigbee: [tz.bticino_4027C_cover_state, tz.bticino_4027C_cover_position, tz.legrand_identify,
65
- tz.legrand_settingAlwaysEnableLed],
67
+ tz.legrand_settingEnableLedInDark],
66
68
  exposes: [e.cover_position()],
67
69
  meta: {coverInverted: true},
68
70
  configure: async (device, coordinatorEndpoint, logger) => {
@@ -95,7 +97,7 @@ module.exports = [
95
97
  vendor: 'BTicino',
96
98
  description: 'Power socket with power consumption monitoring',
97
99
  fromZigbee: [fz.identify, fz.on_off, fz.electrical_measurement],
98
- toZigbee: [tz.on_off, tz.legrand_settingAlwaysEnableLed, tz.legrand_identify],
100
+ toZigbee: [tz.on_off, tz.legrand_settingEnableLedInDark, tz.legrand_identify],
99
101
  exposes: [e.switch(), e.action(['identify']), e.power(), e.voltage(), e.current()],
100
102
  configure: async (device, coordinatorEndpoint, logger) => {
101
103
  const endpoint = device.getEndpoint(1);
@@ -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
  ];
@@ -106,7 +106,7 @@ module.exports = [
106
106
  fz.identify, fz.ignore_basic_report,
107
107
  // support binary report on moving state (supposed)
108
108
  fz.legrand_binary_input_moving, fz.cover_position_tilt],
109
- toZigbee: [tz.cover_state, tz.cover_position_tilt, tz.legrand_identify, tz.legrand_settingAlwaysEnableLed],
109
+ toZigbee: [tz.cover_state, tz.cover_position_tilt, tz.legrand_identify, tz.legrand_settingEnableLedInDark],
110
110
  configure: async (device, coordinatorEndpoint, logger) => {
111
111
  const endpoint = device.getEndpoint(1);
112
112
  await reporting.bind(endpoint, coordinatorEndpoint, ['genBinaryInput', 'closuresWindowCovering', 'genIdentify']);
@@ -175,7 +175,7 @@ module.exports = [
175
175
  description: 'Wired switch without neutral',
176
176
  extend: extend.light_onoff_brightness({noConfigure: true}),
177
177
  fromZigbee: [fz.brightness, fz.identify, fz.on_off, fz.lighting_ballast_configuration, fz.legrand_cluster_fc01],
178
- toZigbee: [tz.light_onoff_brightness, tz.legrand_settingAlwaysEnableLed, tz.legrand_settingEnableLedIfOn,
178
+ toZigbee: [tz.light_onoff_brightness, tz.legrand_settingEnableLedInDark, tz.legrand_settingEnableLedIfOn,
179
179
  tz.legrand_deviceMode, tz.legrand_identify, tz.ballast_config],
180
180
  exposes: [e.light_brightness(),
181
181
  exposes.numeric('ballast_minimum_level', ea.ALL).withValueMin(1).withValueMax(254)
@@ -183,8 +183,9 @@ module.exports = [
183
183
  exposes.numeric('ballast_maximum_level', ea.ALL).withValueMin(1).withValueMax(254)
184
184
  .withDescription('Specifies the maximum brightness value'),
185
185
  exposes.binary('device_mode', ea.ALL, 'dimmer_on', 'dimmer_off').withDescription('Allow the device to change brightness'),
186
- exposes.binary('led_when_off', ea.ALL, 'ON', 'OFF').withDescription('Enable the LED when the light is off'),
187
- exposes.binary('led_when_on', ea.ALL, 'ON', 'OFF').withDescription('Enables the LED when the light is on')],
186
+ exposes.binary('led_in_dark', ea.ALL, 'ON', 'OFF').withDescription(`Enables the LED when the light is turned off, allowing to
187
+ see the switch in the dark`),
188
+ exposes.binary('led_if_on', ea.ALL, 'ON', 'OFF').withDescription('Enables the LED when the light is turned on')],
188
189
  configure: async (device, coordinatorEndpoint, logger) => {
189
190
  await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
190
191
  const endpoint = device.getEndpoint(1);
@@ -201,8 +202,9 @@ module.exports = [
201
202
  ota: ota.zigbeeOTA,
202
203
  description: 'Power socket with power consumption monitoring',
203
204
  fromZigbee: [fz.identify, fz.on_off, fz.electrical_measurement],
204
- toZigbee: [tz.on_off, tz.legrand_settingAlwaysEnableLed, tz.legrand_identify],
205
- exposes: [e.switch(), e.action(['identify']), e.power()],
205
+ toZigbee: [tz.on_off, tz.legrand_settingEnableLedInDark, tz.legrand_identify, tz.legrand_settingEnableLedIfOn],
206
+ exposes: [e.switch(), e.action(['identify']), e.power(),
207
+ exposes.binary('led_if_on', ea.ALL, 'ON', 'OFF').withDescription('Enables the LED when the device is turned on')],
206
208
  configure: async (device, coordinatorEndpoint, logger) => {
207
209
  const endpoint = device.getEndpoint(1);
208
210
  await reporting.bind(endpoint, coordinatorEndpoint, ['genIdentify', 'genOnOff', 'haElectricalMeasurement']);
@@ -256,7 +258,7 @@ module.exports = [
256
258
  vendor: 'Legrand',
257
259
  description: 'DIN power consumption module',
258
260
  fromZigbee: [fz.identify, fz.metering, fz.electrical_measurement, fz.ignore_basic_report, fz.ignore_genOta, fz.legrand_power_alarm],
259
- toZigbee: [tz.legrand_settingAlwaysEnableLed, tz.legrand_identify, tz.electrical_measurement_power, tz.legrand_powerAlarm],
261
+ toZigbee: [tz.legrand_settingEnableLedInDark, tz.legrand_identify, tz.electrical_measurement_power, tz.legrand_powerAlarm],
260
262
  exposes: [e.power().withAccess(ea.STATE_GET), exposes.binary('power_alarm_active', ea.STATE, true, false),
261
263
  exposes.binary('power_alarm', ea.ALL, true, false).withDescription('Enable/disable the power alarm')],
262
264
  configure: async (device, coordinatorEndpoint, logger) => {
@@ -344,11 +346,12 @@ module.exports = [
344
346
  vendor: 'Legrand',
345
347
  description: 'Double wired switch with neutral',
346
348
  fromZigbee: [fz.on_off, fz.legrand_binary_input_on_off, fz.legrand_cluster_fc01],
347
- toZigbee: [tz.on_off, tz.legrand_settingAlwaysEnableLed, tz.legrand_settingEnableLedIfOn],
349
+ toZigbee: [tz.on_off, tz.legrand_settingEnableLedInDark, tz.legrand_settingEnableLedIfOn],
348
350
  exposes: [e.switch().withEndpoint('left'),
349
351
  e.switch().withEndpoint('right'),
350
- exposes.binary('led_when_off', ea.ALL, 'ON', 'OFF').withDescription('Enable the LED when the light is off'),
351
- exposes.binary('led_when_on', ea.ALL, 'ON', 'OFF').withDescription('Enables the LED when the light is on')],
352
+ exposes.binary('led_in_dark', ea.ALL, 'ON', 'OFF').withDescription(`Enables the LED when the light is turned off, allowing to
353
+ see the switch in the dark`),
354
+ exposes.binary('led_if_on', ea.ALL, 'ON', 'OFF').withDescription('Enables the LED when the light is turned on')],
352
355
  meta: {multiEndpoint: true},
353
356
  configure: async (device, coordinatorEndpoint, logger) => {
354
357
  const endpointLeft = device.getEndpoint(2);
@@ -368,7 +371,7 @@ module.exports = [
368
371
  ota: ota.zigbeeOTA,
369
372
  description: 'Outlet with power consumption monitoring',
370
373
  fromZigbee: [fz.identify, fz.on_off, fz.electrical_measurement],
371
- toZigbee: [tz.on_off, tz.legrand_settingAlwaysEnableLed, tz.legrand_identify],
374
+ toZigbee: [tz.on_off, tz.legrand_settingEnableLedInDark, tz.legrand_identify],
372
375
  exposes: [e.switch(), e.action(['identify']), e.power()],
373
376
  configure: async (device, coordinatorEndpoint, logger) => {
374
377
  const endpoint = device.getEndpoint(1);
package/devices/lidl.js CHANGED
@@ -378,6 +378,28 @@ module.exports = [
378
378
  await reporting.onOff(endpoint);
379
379
  },
380
380
  },
381
+ {
382
+ fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_ynmowqk2'}],
383
+ model: 'HG08673-FR',
384
+ vendor: 'Lidl',
385
+ description: 'Silvercrest smart plug FR with power monitoring',
386
+ fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering, fz.ignore_basic_report, fz.tuya_switch_power_outage_memory],
387
+ toZigbee: [tz.on_off, tz.tuya_switch_power_outage_memory],
388
+ exposes: [e.switch(), e.power(), e.current(), e.voltage().withAccess(ea.STATE),
389
+ e.energy(), exposes.enum('power_outage_memory', ea.ALL, ['on', 'off', 'restore'])
390
+ .withDescription('Recover state after power outage')],
391
+ configure: async (device, coordinatorEndpoint, logger) => {
392
+ const endpoint = device.getEndpoint(1);
393
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement']);
394
+ endpoint.saveClusterAttributeKeyValue('seMetering', {divisor: 100, multiplier: 1});
395
+ endpoint.saveClusterAttributeKeyValue('haElectricalMeasurement', {
396
+ acVoltageMultiplier: 1, acVoltageDivisor: 1, acCurrentMultiplier: 1, acCurrentDivisor: 1000, acPowerMultiplier: 1,
397
+ acPowerDivisor: 1,
398
+ });
399
+ },
400
+ options: [exposes.options.measurement_poll_interval()],
401
+ onEvent: tuya.onEventMeasurementPoll,
402
+ },
381
403
  {
382
404
  fingerprint: [{modelID: 'TS004F', manufacturerName: '_TZ3000_rco1yzb1'}],
383
405
  model: 'HG08164',
@@ -62,4 +62,21 @@ module.exports = [
62
62
  device.save();
63
63
  },
64
64
  },
65
+ {
66
+ fingerprint: [{modelID: 'TS0501', manufacturerName: '_TZ3210_lzqq3u4r'},
67
+ {modelID: 'TS0501', manufacturerName: '_TZ3210_4whigl8i'}],
68
+ model: 'SSWF01G',
69
+ description: 'AC fan controller',
70
+ vendor: 'Mercator',
71
+ fromZigbee: [fz.on_off, fz.fan],
72
+ toZigbee: [tz.fan_mode, tz.on_off],
73
+ exposes: [e.switch(), e.fan().withModes(['off', 'low', 'medium', 'high', 'on'])],
74
+ configure: async (device, coordinatorEndpoint, logger) => {
75
+ const endpoint = device.getEndpoint(1);
76
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genBasic', 'genOta', 'genTime', 'genGroups', 'genScenes']);
77
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genIdentify', 'manuSpecificTuya', 'hvacFanCtrl']);
78
+ await reporting.onOff(endpoint);
79
+ await reporting.fanMode(endpoint);
80
+ },
81
+ },
65
82
  ];
package/devices/moes.js CHANGED
@@ -273,9 +273,14 @@ module.exports = [
273
273
  exposes: [e.switch().withEndpoint('l1').setAccess('state', ea.STATE_SET),
274
274
  e.switch().withEndpoint('l2').setAccess('state', ea.STATE_SET),
275
275
  e.switch().withEndpoint('l3').setAccess('state', ea.STATE_SET),
276
- e.switch().withEndpoint('l4').setAccess('state', ea.STATE_SET)],
277
- fromZigbee: [fz.ignore_basic_report, fz.tuya_switch],
278
- 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,
279
284
  meta: {multiEndpoint: true},
280
285
  endpoint: (device) => {
281
286
  // Endpoint selection is made in tuya_switch_state
@@ -428,7 +433,10 @@ module.exports = [
428
433
  exposes.enum('calibration', ea.STATE_SET, ['OFF', 'ON']), exposes.enum('motor_reversal', ea.STATE_SET, ['OFF', 'ON'])],
429
434
  },
430
435
  {
431
- fingerprint: [{modelID: 'TS1201', manufacturerName: '_TZ3290_j37rooaxrcdcqo5n'}],
436
+ fingerprint: [
437
+ {modelID: 'TS1201', manufacturerName: '_TZ3290_j37rooaxrcdcqo5n'},
438
+ {modelID: 'TS1201', manufacturerName: '_TZ3290_ot6ewjvmejq5ekhl'},
439
+ ],
432
440
  model: 'UFO-R11',
433
441
  vendor: 'Moes',
434
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
+ ];
@@ -41,7 +41,7 @@ module.exports = [
41
41
  },
42
42
  },
43
43
  {
44
- zigbeeModel: ['LIGHTIFY RT Tunable White'],
44
+ zigbeeModel: ['LIGHTIFY RT Tunable White', 'RT TW'],
45
45
  model: '73742',
46
46
  vendor: 'Sylvania',
47
47
  description: 'LIGHTIFY LED adjustable white RT 5/6',
package/devices/tuya.js CHANGED
@@ -20,7 +20,7 @@ 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', '_TZ3000_gvn91tmx'];
24
24
 
25
25
  const tzLocal = {
26
26
  hpsz: {
@@ -801,6 +801,7 @@ module.exports = [
801
801
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_remypqqm'},
802
802
  {modelID: 'TS0505B', manufacturerName: '_TZ3000_kohbva1f'},
803
803
  {modelID: 'TS0505B', manufacturerName: '_TZ3000_luit1t00'},
804
+ {modelID: 'TS0505B', manufacturerName: '_TZ3210_r5afgmkl'},
804
805
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_wslkvrau'},
805
806
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_0rn9qhnu'},
806
807
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_ejctepku'},
@@ -818,6 +819,7 @@ module.exports = [
818
819
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_mzdax7ha'},
819
820
  {modelID: 'TS0505B', manufacturerName: '_TZB210_tmi0rihb'},
820
821
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_a4s41wm4'},
822
+ {modelID: 'TS0505B', manufacturerName: '_TZ3210_ijczzg9h'},
821
823
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_qxenlrin'},
822
824
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_iwbaamgh'},
823
825
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_klv2wul0'},
@@ -826,6 +828,7 @@ module.exports = [
826
828
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_cuqkfz2q'},
827
829
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_6amjviba'},
828
830
  {modelID: 'TS0505B', manufacturerName: '_TZ3000_xr5m6kfg'},
831
+ {modelID: 'TS0505B', manufacturerName: '_TZ3210_xr5m6kfg'},
829
832
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_bf175wi4'}],
830
833
  model: 'TS0505B',
831
834
  vendor: 'TuYa',
@@ -887,7 +890,8 @@ module.exports = [
887
890
  {modelID: 'TS0501B', manufacturerName: '_TZ3210_wuheofsg'},
888
891
  {modelID: 'TS0501B', manufacturerName: '_TZ3210_e5t9bfdv'},
889
892
  {modelID: 'TS0501B', manufacturerName: '_TZ3210_19qb27da'},
890
- {modelID: 'TS0501B', manufacturerName: '_TZ3210_4zinq6io'}],
893
+ {modelID: 'TS0501B', manufacturerName: '_TZ3210_4zinq6io'},
894
+ {modelID: 'TS0501B', manufacturerName: '_TZ3210_93gnbdgz'}],
891
895
  model: 'TS0501B',
892
896
  description: 'Zigbee light',
893
897
  vendor: 'TuYa',
@@ -1465,7 +1469,7 @@ module.exports = [
1465
1469
  },
1466
1470
  },
1467
1471
  {
1468
- fingerprint: [{modelID: 'TS004F', manufacturerName: '_TZ3000_xabckq1v'}],
1472
+ fingerprint: [{modelID: 'TS004F', manufacturerName: '_TZ3000_xabckq1v'}, {modelID: 'TS004F', manufacturerName: '_TZ3000_czuyt8lz'}],
1469
1473
  model: 'TS004F',
1470
1474
  vendor: 'TuYa',
1471
1475
  description: 'Wireless switch with 4 buttons',
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.608",
3
+ "version": "14.0.611",
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.53"
42
42
  },
43
43
  "devDependencies": {
44
44
  "eslint": "*",