zigbee-herdsman-converters 14.0.674 → 14.0.675

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.
@@ -638,7 +638,8 @@ module.exports = [
638
638
  ['electricity', 'gas', 'water', 'kamstrup-kmp', 'linky', 'IEC62056-21', 'DSMR-2.3', 'DSMR-4.0'])
639
639
  .withDescription('Operating mode/probe'),
640
640
  exposes.numeric('current_summation', ea.SET)
641
- .withDescription('Current summation value sent to the display. e.g. 570 = 0,570 kWh').withValueMin(0).withValueMax(10000),
641
+ .withDescription('Current summation value sent to the display. e.g. 570 = 0,570 kWh').withValueMin(0)
642
+ .withValueMax(268435455),
642
643
  exposes.binary('check_meter', ea.STATE, true, false)
643
644
  .withDescription('Is true if communication problem with meter is experienced'),
644
645
  ],
package/devices/lidl.js CHANGED
@@ -395,10 +395,13 @@ module.exports = [
395
395
  },
396
396
  },
397
397
  {
398
- fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_ynmowqk2'}],
399
- model: 'HG08673-FR',
398
+ fingerprint: [
399
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_j1v25l17'}, // EU
400
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_ynmowqk2'}, // FR
401
+ ],
402
+ model: 'HG08673',
400
403
  vendor: 'Lidl',
401
- description: 'Silvercrest smart plug FR with power monitoring',
404
+ description: 'Silvercrest smart plug with power monitoring (EU, FR)',
402
405
  ota: ota.zigbeeOTA,
403
406
  fromZigbee: [fz.on_off, fzLocal.electrical_measurement_skip_duplicate, fzLocal.metering_skip_duplicate, fz.ignore_basic_report,
404
407
  fz.tuya_switch_power_outage_memory, fz.ts011f_plug_indicator_mode, fz.ts011f_plug_child_mode],
@@ -259,7 +259,7 @@ module.exports = [
259
259
  exposes.numeric('calibration_time', ea.STATE).withUnit('S').withDescription('Calibration time')],
260
260
  },
261
261
  {
262
- fingerprint: [{modelID: 'TS110E', manufacturerName: '_TZ3210_zxbtub8r'}, {modelID: 'TS110E', manufacturerName: '_TZ3210_ngqk6jia'}],
262
+ fingerprint: [{modelID: 'TS110E', manufacturerName: '_TZ3210_zxbtub8r'}],
263
263
  model: 'TS110E_1gang',
264
264
  vendor: 'Lonsonho',
265
265
  description: 'Zigbee smart dimmer module 1 gang with neutral',
package/devices/owon.js CHANGED
@@ -7,6 +7,15 @@ const e = exposes.presets;
7
7
  const ea = exposes.access;
8
8
 
9
9
  const fzLocal = {
10
+ temperature: {
11
+ ...fz.temperature,
12
+ convert: (model, msg, publish, options, meta) => {
13
+ // https://github.com/Koenkk/zigbee2mqtt/issues/15173
14
+ if (msg.data.measuredValue < 32770) {
15
+ return fz.temperature.convert(model, msg, publish, options, meta);
16
+ }
17
+ },
18
+ },
10
19
  PC321_metering: {
11
20
  cluster: 'seMetering',
12
21
  type: ['attributeReport', 'readResponse'],
@@ -76,6 +85,7 @@ const fzLocal = {
76
85
  },
77
86
  },
78
87
  };
88
+
79
89
  module.exports = [
80
90
  {
81
91
  zigbeeModel: ['WSP404'],
@@ -177,7 +187,7 @@ module.exports = [
177
187
  model: 'THS317-ET',
178
188
  vendor: 'OWON',
179
189
  description: 'Temperature sensor',
180
- fromZigbee: [fz.temperature, fz.battery],
190
+ fromZigbee: [fzLocal.temperature, fz.battery],
181
191
  toZigbee: [],
182
192
  exposes: [e.battery(), e.temperature()],
183
193
  configure: async (device, coordinatorEndpoint, logger) => {
@@ -280,4 +290,19 @@ module.exports = [
280
290
  await endpoint2.read('msOccupancySensing', ['occupancy']);
281
291
  },
282
292
  },
293
+ {
294
+ zigbeeModel: ['PIR323-PTH'],
295
+ model: 'PIR323-PTH',
296
+ vendor: 'OWON',
297
+ description: 'Multi-sensor',
298
+ fromZigbee: [fz.battery, fz.ignore_basic_report, fz.ias_occupancy_alarm_1, fz.temperature, fz.humidity, fz.occupancy_timeout],
299
+ toZigbee: [],
300
+ exposes: [e.occupancy(), e.battery_low(), e.temperature(), e.humidity()],
301
+ configure: async (device, coordinatorEndpoint, logger) => {
302
+ const endpoint = device.getEndpoint(2);
303
+ await reporting.bind(endpoint, coordinatorEndpoint, ['msTemperatureMeasurement', 'msRelativeHumidity']);
304
+ device.powerSource = 'Battery';
305
+ device.save();
306
+ },
307
+ },
283
308
  ];
@@ -2455,6 +2455,13 @@ module.exports = [
2455
2455
  description: 'Hue Play gradient lightstrip 65',
2456
2456
  extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
2457
2457
  },
2458
+ {
2459
+ zigbeeModel: ['LCX003'],
2460
+ model: '929002422901',
2461
+ vendor: 'Philips',
2462
+ description: 'Hue Play gradient lightstrip 75',
2463
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
2464
+ },
2458
2465
  {
2459
2466
  zigbeeModel: ['929003099301'],
2460
2467
  model: '929003099301',
package/devices/sinope.js CHANGED
@@ -187,7 +187,7 @@ module.exports = [
187
187
  } catch (error) {/* Not all support this */}
188
188
 
189
189
  try {
190
- await endpoint.read('haElectricalMeasurement', ['acPowerMultiplier']);
190
+ await endpoint.read('haElectricalMeasurement', ['acPowerMultiplier', 'acPowerDivisor']);
191
191
  await reporting.activePower(endpoint, {min: 10, max: 305, change: 1}); // divider 1: 1W
192
192
  } catch (error) {
193
193
  endpoint.saveClusterAttributeKeyValue('haElectricalMeasurement', {'acPowerMultiplier': 1, 'acPowerDivisor': 1});
@@ -75,6 +75,7 @@ module.exports = [
75
75
  description: 'Wireless motion sensor',
76
76
  fromZigbee: [fz.ias_occupancy_alarm_1, fz.battery],
77
77
  toZigbee: [],
78
+ ota: ota.zigbeeOTA,
78
79
  exposes: [e.occupancy(), e.battery_low(), e.battery(), e.battery_voltage()],
79
80
  configure: async (device, coordinatorEndpoint, logger) => {
80
81
  device.powerSource = 'Battery';
@@ -88,6 +89,7 @@ module.exports = [
88
89
  description: 'Door sensor',
89
90
  fromZigbee: [fz.ias_contact_alarm_1, fz.battery],
90
91
  toZigbee: [],
92
+ ota: ota.zigbeeOTA,
91
93
  meta: {battery: {dontDividePercentage: true}},
92
94
  exposes: [e.contact(), e.battery_low(), e.battery(), e.battery_voltage()],
93
95
  configure: async (device, coordinatorEndpoint, logger) => {
@@ -115,6 +117,7 @@ module.exports = [
115
117
  fromZigbee: [fz.cover_position_tilt, fz.battery],
116
118
  toZigbee: [tz.cover_state, tz.cover_position_tilt],
117
119
  meta: {battery: {dontDividePercentage: false}},
120
+ ota: ota.zigbeeOTA,
118
121
  configure: async (device, coordinatorEndpoint, logger) => {
119
122
  const endpoint = device.getEndpoint(1);
120
123
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'closuresWindowCovering']);
@@ -132,6 +135,7 @@ module.exports = [
132
135
  description: 'Smart button',
133
136
  fromZigbee: [fz.battery, fz.itcmdr_clicks],
134
137
  toZigbee: [],
138
+ ota: ota.zigbeeOTA,
135
139
  exposes: [e.battery(), e.battery_low(), e.battery_voltage(), e.action(['single', 'double', 'long'])],
136
140
  configure: async (device, coordinatorEndpoint, logger) => {
137
141
  device.powerSource = 'Battery';
package/devices/tuya.js CHANGED
@@ -25,6 +25,50 @@ const TS011Fplugs = ['_TZ3000_5f43h46b', '_TZ3000_cphmq0q7', '_TZ3000_dpo1ysak',
25
25
  '_TZ3000_rdfh8cfs', '_TZ3000_yujkchbz', '_TZ3000_fgwhjm9j', '_TZ3000_qeuvnohg', '_TZ3000_rul9yxcc'];
26
26
 
27
27
  const tzLocal = {
28
+ TS110E_options: {
29
+ key: ['min_brightness', 'max_brightness', 'light_type'],
30
+ convertSet: async (entity, key, value, meta) => {
31
+ let payload = null;
32
+ if (key === 'min_brightness' || key == 'max_brightness') {
33
+ const id = key === 'min_brightness' ? 64515 : 64516;
34
+ payload = {[id]: {value: utils.mapNumberRange(value, 1, 255, 0, 1000), type: 0x21}};
35
+ } else if (key === 'light_type') {
36
+ const lookup = {led: 0, incandescent: 1, halogen: 2};
37
+ payload = {64514: {value: lookup[value], type: 0x20}};
38
+ }
39
+ await entity.write('genLevelCtrl', payload, utils.getOptions(meta.mapped, entity));
40
+ },
41
+ convertGet: async (entity, key, meta) => {
42
+ let id = null;
43
+ if (key === 'min_brightness') id = 64515;
44
+ if (key === 'max_brightness') id = 64516;
45
+ if (key === 'light_type') id = 64514;
46
+ await entity.read('genLevelCtrl', [id]);
47
+ },
48
+ },
49
+ TS110E_onoff_brightness: {
50
+ key: ['state', 'brightness'],
51
+ options: [],
52
+ convertSet: async (entity, key, value, meta) => {
53
+ const {message, state} = meta;
54
+ if (message.state === 'OFF' || (message.hasOwnProperty('state') && !message.hasOwnProperty('brightness'))) {
55
+ return await tz.on_off.convertSet(entity, key, value, meta);
56
+ } else if (message.hasOwnProperty('brightness')) {
57
+ // set brightness
58
+ if (state.state === 'OFF') {
59
+ await entity.command('genOnOff', 'on', {}, utils.getOptions(meta.mapped, entity));
60
+ }
61
+
62
+ const level = utils.mapNumberRange(message.brightness, 0, 254, 0, 1000);
63
+ await entity.command('genLevelCtrl', 'moveToLevelTuya', {level, transtime: 100}, utils.getOptions(meta.mapped, entity));
64
+ return {state: {state: 'ON', brightness: message.brightness}};
65
+ }
66
+ },
67
+ convertGet: async (entity, key, meta) => {
68
+ if (key === 'state') await tz.on_off.convertGet(entity, key, meta);
69
+ if (key === 'brightness') await entity.read('genLevelCtrl', [61440]);
70
+ },
71
+ },
28
72
  SA12IZL_silence_siren: {
29
73
  key: ['silence_siren'],
30
74
  convertSet: async (entity, key, value, meta) => {
@@ -291,6 +335,27 @@ const tzLocal = {
291
335
  };
292
336
 
293
337
  const fzLocal = {
338
+ TS110E: {
339
+ cluster: 'genLevelCtrl',
340
+ type: ['attributeReport', 'readResponse'],
341
+ convert: (model, msg, publish, options, meta) => {
342
+ const result = {};
343
+ if (msg.data.hasOwnProperty('64515')) {
344
+ result['min_brightness'] = utils.mapNumberRange(msg.data['64515'], 0, 1000, 1, 255);
345
+ }
346
+ if (msg.data.hasOwnProperty('64516')) {
347
+ result['max_brightness'] = utils.mapNumberRange(msg.data['64516'], 0, 1000, 1, 255);
348
+ }
349
+ if (msg.data.hasOwnProperty('64514')) {
350
+ const lookup = {0: 'led', 1: 'incandescent', 2: 'halogen'};
351
+ result['light_type'] = lookup[msg.data['64514']];
352
+ }
353
+ if (msg.data.hasOwnProperty('61440')) {
354
+ result['brightness'] = utils.mapNumberRange(msg.data['61440'], 0, 1000, 0, 254);
355
+ }
356
+ return result;
357
+ },
358
+ },
294
359
  SA12IZL: {
295
360
  cluster: 'manuSpecificTuya',
296
361
  type: ['commandDataResponse', 'commandDataReport'],
@@ -826,7 +891,9 @@ module.exports = [
826
891
  fromZigbee: extend.switch().fromZigbee.concat([fz.moes_power_on_behavior, fz.tuya_switch_type]),
827
892
  exposes: extend.switch().exposes.concat([e.power_on_behavior(), e.switch_type_2()]),
828
893
  configure: async (device, coordinatorEndpoint, logger) => {
829
- await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
894
+ const endpoint = device.getEndpoint(1);
895
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
896
+ await reporting.onOff(endpoint);
830
897
  },
831
898
  },
832
899
  {
@@ -3593,4 +3660,58 @@ module.exports = [
3593
3660
  ],
3594
3661
  },
3595
3662
  },
3663
+ {
3664
+ fingerprint: tuya.fingerprint('TS110E', ['_TZ3210_ngqk6jia']),
3665
+ model: 'TS110E',
3666
+ vendor: 'TuYa',
3667
+ description: '1 channel dimmer',
3668
+ whiteLabel: [{vendor: 'RTX', model: 'QS-Zigbee-D02-TRIAC-LN'}],
3669
+ fromZigbee: [fzLocal.TS110E, fz.moes_power_on_behavior, fz.on_off],
3670
+ toZigbee: [tzLocal.TS110E_onoff_brightness, tzLocal.TS110E_options, tz.moes_power_on_behavior, tz.light_brightness_move],
3671
+ exposes: [
3672
+ e.light_brightness().withMinBrightness().withMaxBrightness(),
3673
+ tuya.exposes.lightType().withAccess(ea.ALL), tuya.exposes.powerOnBehavior().withAccess(ea.ALL)],
3674
+ configure: async (device, coordinatorEndpoint, logger) => {
3675
+ const endpoint = device.getEndpoint(1);
3676
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
3677
+ await reporting.onOff(endpoint);
3678
+ },
3679
+ },
3680
+ {
3681
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_nslr42tt']),
3682
+ model: 'TS0601_3_phase_clamp_meter',
3683
+ vendor: 'TuYa',
3684
+ description: '3-phase clamp power meter',
3685
+ fromZigbee: [tuya.fzDataPoints],
3686
+ toZigbee: [tuya.tzDataPoints],
3687
+ configure: tuya.configureMagicPacket,
3688
+ whiteLabel: [{vendor: 'MatSeePlus', model: 'PC321-Z-TY'}],
3689
+ exposes: [
3690
+ e.ac_frequency(), e.temperature(), e.current(), e.power(), e.energy(),
3691
+ tuya.exposes.energyWithPhase('a'), tuya.exposes.energyWithPhase('b'), tuya.exposes.energyWithPhase('c'),
3692
+ tuya.exposes.voltageWithPhase('a'), tuya.exposes.voltageWithPhase('b'), tuya.exposes.voltageWithPhase('c'),
3693
+ tuya.exposes.powerWithPhase('a'), tuya.exposes.powerWithPhase('b'), tuya.exposes.powerWithPhase('c'),
3694
+ tuya.exposes.currentWithPhase('a'), tuya.exposes.currentWithPhase('b'), tuya.exposes.currentWithPhase('c'),
3695
+ tuya.exposes.powerFactorWithPhase('a'), tuya.exposes.powerFactorWithPhase('b'), tuya.exposes.powerFactorWithPhase('c'),
3696
+ ],
3697
+ meta: {
3698
+ tuyaDatapoints: [
3699
+ [132, 'ac_frequency', tuya.valueConverter.raw],
3700
+ [133, 'temperature', tuya.valueConverter.divideBy10],
3701
+ [1, 'energy', tuya.valueConverter.divideBy100],
3702
+ [101, 'energy_a', tuya.valueConverter.divideBy1000],
3703
+ [111, 'energy_b', tuya.valueConverter.divideBy1000],
3704
+ [121, 'energy_c', tuya.valueConverter.divideBy1000],
3705
+ [131, 'current', tuya.valueConverter.divideBy1000],
3706
+ [9, 'power', tuya.valueConverter.raw],
3707
+ [102, 'power_factor_a', tuya.valueConverter.raw],
3708
+ [112, 'power_factor_b', tuya.valueConverter.raw],
3709
+ [122, 'power_factor_c', tuya.valueConverter.raw],
3710
+ [6, null, tuya.valueConverter.phaseVariant2WithPhase('a')],
3711
+ [7, null, tuya.valueConverter.phaseVariant2WithPhase('b')],
3712
+ [8, null, tuya.valueConverter.phaseVariant2WithPhase('c')],
3713
+ [134, 'device_status', tuya.valueConverter.raw],
3714
+ ],
3715
+ },
3716
+ },
3596
3717
  ];
package/devices/xiaomi.js CHANGED
@@ -2572,6 +2572,7 @@ module.exports = [
2572
2572
  const endpoint = device.getEndpoint(1);
2573
2573
  await endpoint.read('aqaraOpple', [0x040a], {manufacturerCode: 0x115f});
2574
2574
  },
2575
+ ota: ota.zigbeeOTA,
2575
2576
  },
2576
2577
  {
2577
2578
  zigbeeModel: ['aqara.feeder.acn001'],
package/lib/tuya.js CHANGED
@@ -246,22 +246,26 @@ function convertDecimalValueTo2ByteHexArray(value) {
246
246
  async function onEventMeasurementPoll(type, data, device, options, electricalMeasurement=true, metering=false) {
247
247
  const endpoint = device.getEndpoint(1);
248
248
  if (type === 'stop') {
249
- clearInterval(globalStore.getValue(device, 'interval'));
250
- globalStore.clearValue(device, 'interval');
251
- } else if (!globalStore.hasValue(device, 'interval')) {
249
+ clearTimeout(globalStore.getValue(device, 'measurement_poll'));
250
+ globalStore.clearValue(device, 'measurement_poll');
251
+ } else if (!globalStore.hasValue(device, 'measurement_poll')) {
252
252
  const seconds = options && options.measurement_poll_interval ? options.measurement_poll_interval : 60;
253
253
  if (seconds === -1) return;
254
- const interval = setInterval(async () => {
255
- try {
256
- if (electricalMeasurement) {
257
- await endpoint.read('haElectricalMeasurement', ['rmsVoltage', 'rmsCurrent', 'activePower']);
258
- }
259
- if (metering) {
260
- await endpoint.read('seMetering', ['currentSummDelivered']);
261
- }
262
- } catch (error) {/* Do nothing*/}
263
- }, seconds*1000);
264
- globalStore.putValue(device, 'interval', interval);
254
+ const setTimer = () => {
255
+ const timer = setTimeout(async () => {
256
+ try {
257
+ if (electricalMeasurement) {
258
+ await endpoint.read('haElectricalMeasurement', ['rmsVoltage', 'rmsCurrent', 'activePower']);
259
+ }
260
+ if (metering) {
261
+ await endpoint.read('seMetering', ['currentSummDelivered']);
262
+ }
263
+ } catch (error) {/* Do nothing*/}
264
+ setTimer();
265
+ }, seconds * 1000);
266
+ globalStore.putValue(device, 'measurement_poll', timer);
267
+ };
268
+ setTimer();
265
269
  }
266
270
  }
267
271
 
@@ -1176,6 +1180,16 @@ const tuyaExposes = {
1176
1180
  humidityCalibration: () => exposes.numeric('humidity_calibration', ea.STATE_SET).withValueMin(-30).withValueMax(30)
1177
1181
  .withValueStep(1).withUnit('%').withDescription('Humidity calibration'),
1178
1182
  gasValue: () => exposes.numeric('gas_value', ea.STATE).withDescription('Measured gas concentration').withUnit('ppm'),
1183
+ energyWithPhase: (phase) => exposes.numeric(`energy_${phase}`, ea.STATE).withUnit('kWh')
1184
+ .withDescription(`Sum of consumed energy (phase ${phase.toUpperCase()})`),
1185
+ voltageWithPhase: (phase) => exposes.numeric(`voltage_${phase}`, ea.STATE).withUnit('V')
1186
+ .withDescription(`Measured electrical potential value (phase ${phase.toUpperCase()})`),
1187
+ powerWithPhase: (phase) => exposes.numeric(`power_${phase}`, ea.STATE).withUnit('W')
1188
+ .withDescription(`Instantaneous measured power (phase ${phase.toUpperCase()})`),
1189
+ currentWithPhase: (phase) => exposes.numeric(`current_${phase}`, ea.STATE).withUnit('A')
1190
+ .withDescription(`Instantaneous measured electrical current (phase ${phase.toUpperCase()})`),
1191
+ powerFactorWithPhase: (phase) => exposes.numeric(`power_factor_${phase}`, ea.STATE).withUnit('%')
1192
+ .withDescription(`Instantaneous measured power factor (phase ${phase.toUpperCase()})`),
1179
1193
  };
1180
1194
 
1181
1195
  const skip = {
@@ -1263,6 +1277,7 @@ const valueConverter = {
1263
1277
  divideBy100: valueConverterBasic.divideBy(100),
1264
1278
  temperatureUnit: valueConverterBasic.lookup({'celsius': 0, 'fahrenheit': 1}),
1265
1279
  divideBy10: valueConverterBasic.divideBy(10),
1280
+ divideBy1000: valueConverterBasic.divideBy(1000),
1266
1281
  raw: valueConverterBasic.raw(),
1267
1282
  phaseVariant1: {
1268
1283
  from: (v) => {
@@ -1276,6 +1291,17 @@ const valueConverter = {
1276
1291
  return {voltage: (buf[1] | buf[0] << 8) / 10, current: (buf[4] | buf[3] << 8) / 1000, power: (buf[7] | buf[6] << 8)};
1277
1292
  },
1278
1293
  },
1294
+ phaseVariant2WithPhase: (phase) => {
1295
+ return {
1296
+ from: (v) => {
1297
+ const buf = Buffer.from(v, 'base64');
1298
+ return {
1299
+ [`voltage_${phase}`]: (buf[1] | buf[0] << 8) / 10,
1300
+ [`current_${phase}`]: (buf[4] | buf[3] << 8) / 1000,
1301
+ [`power_${phase}`]: (buf[7] | buf[6] << 8)};
1302
+ },
1303
+ };
1304
+ },
1279
1305
  threshold: {
1280
1306
  from: (v) => {
1281
1307
  const buffer = Buffer.from(v, 'base64');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.674",
3
+ "version": "14.0.675",
4
4
  "description": "Collection of device converters to be used with zigbee-herdsman",
5
5
  "main": "index.js",
6
6
  "files": [