zigbee-herdsman-converters 14.0.673 → 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
  ],
@@ -66,6 +66,14 @@ module.exports = [
66
66
  extend: extend.ledvance.light_onoff_brightness_colortemp_color({colorTempRange: [153, 370]}),
67
67
  ota: ota.ledvance,
68
68
  },
69
+ {
70
+ zigbeeModel: ['PAR16 RGBW T'],
71
+ model: '4058075729186',
72
+ vendor: 'LEDVANCE',
73
+ description: 'SMART+ Spot PAR16 28 GU10 Multicolor',
74
+ extend: extend.ledvance.light_onoff_brightness_colortemp_color({colorTempRange: [153, 370]}),
75
+ ota: ota.ledvance,
76
+ },
69
77
  {
70
78
  zigbeeModel: ['PAR16S TW'],
71
79
  model: 'AC33905',
@@ -170,6 +178,14 @@ module.exports = [
170
178
  extend: extend.ledvance.light_onoff_brightness_colortemp({colorTempRange: [153, 370]}),
171
179
  ota: ota.ledvance,
172
180
  },
181
+ {
182
+ zigbeeModel: ['P40 TW T'],
183
+ model: '4058075729124',
184
+ vendor: 'LEDVANCE',
185
+ description: 'SMART+ CL P40 E14 Tunable white',
186
+ extend: extend.ledvance.light_onoff_brightness_colortemp({colorTempRange: [153, 370]}),
187
+ ota: ota.ledvance,
188
+ },
173
189
  {
174
190
  zigbeeModel: ['CLA60 RGBW JP'],
175
191
  model: 'SMARTZBA60RGBW',
@@ -255,6 +271,19 @@ module.exports = [
255
271
  await reporting.onOff(endpoint);
256
272
  },
257
273
  },
274
+ {
275
+ zigbeeModel: ['PLUG UK T'],
276
+ model: '4058075729285',
277
+ vendor: 'LEDVANCE',
278
+ description: 'SMART+ Plug UK',
279
+ extend: extend.switch(),
280
+ ota: ota.ledvance,
281
+ configure: async (device, coordinatorEndpoint, logger) => {
282
+ const endpoint = device.getEndpoint(1);
283
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
284
+ await reporting.onOff(endpoint);
285
+ },
286
+ },
258
287
  {
259
288
  zigbeeModel: ['PLUG OUTDOOR EU T'],
260
289
  model: '4058075729308',
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
  ];
@@ -742,6 +742,13 @@ module.exports = [
742
742
  description: 'Hue White and Color Ambiance BR30 with bluetooth',
743
743
  extend: hueExtend.light_onoff_brightness_colortemp_color(),
744
744
  },
745
+ {
746
+ zigbeeModel: ['LCB002'],
747
+ model: '046677577957',
748
+ vendor: 'Philips',
749
+ description: 'Hue White and Color Ambiance BR30 with bluetooth',
750
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
751
+ },
745
752
  {
746
753
  zigbeeModel: ['LWB004'],
747
754
  model: '433714',
@@ -2448,6 +2455,13 @@ module.exports = [
2448
2455
  description: 'Hue Play gradient lightstrip 65',
2449
2456
  extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
2450
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
+ },
2451
2465
  {
2452
2466
  zigbeeModel: ['929003099301'],
2453
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';
@@ -146,5 +150,6 @@ module.exports = [
146
150
  fromZigbee: [fz.battery, fz.temperature, fz.humidity],
147
151
  toZigbee: [],
148
152
  exposes: [e.battery(), e.temperature(), e.humidity(), e.battery_voltage()],
153
+ ota: ota.zigbeeOTA,
149
154
  },
150
155
  ];
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
  {
@@ -1399,7 +1466,8 @@ module.exports = [
1399
1466
  fingerprint: [{modelID: 'TS0215A', manufacturerName: '_TZ3000_4fsgukof'},
1400
1467
  {modelID: 'TS0215A', manufacturerName: '_TZ3000_wr2ucaj9'},
1401
1468
  {modelID: 'TS0215A', manufacturerName: '_TZ3000_zsh6uat3'},
1402
- {modelID: 'TS0215A', manufacturerName: '_TZ3000_tj4pwzzm'}],
1469
+ {modelID: 'TS0215A', manufacturerName: '_TZ3000_tj4pwzzm'},
1470
+ {modelID: 'TS0215A', manufacturerName: '_TZ3000_2izubafb'}],
1403
1471
  model: 'TS0215A_sos',
1404
1472
  vendor: 'TuYa',
1405
1473
  description: 'SOS button',
@@ -3335,8 +3403,7 @@ module.exports = [
3335
3403
  exposes: [e.illuminance_lux(), e.brightness_state()],
3336
3404
  },
3337
3405
  {
3338
- fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_kltffuzl'}, {modelID: 'TS0601', manufacturerName: '_TZE200_fwoorn8y'},
3339
- {modelID: 'TS0601', manufacturerName: '_TZE200_pay2byax'}],
3406
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_kltffuzl'}, {modelID: 'TS0601', manufacturerName: '_TZE200_fwoorn8y'}],
3340
3407
  model: 'TM001-ZA/TM081',
3341
3408
  vendor: 'TuYa',
3342
3409
  description: 'Door and window sensor',
@@ -3418,18 +3485,7 @@ module.exports = [
3418
3485
  ],
3419
3486
  },
3420
3487
  {
3421
- fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_qoy0ekbd'},
3422
- {modelID: 'TS0601', manufacturerName: '_TZE200_znbl8dj5'}],
3423
- model: 'CX-0726',
3424
- vendor: 'TuYa',
3425
- description: 'Temperature & humidity LCD sensor',
3426
- fromZigbee: [fz.tuya_temperature_humidity_sensor, fz.ignore_tuya_set_time],
3427
- toZigbee: [],
3428
- onEvent: tuya.onEventSetLocalTime,
3429
- exposes: [e.temperature(), e.humidity(), e.battery()],
3430
- },
3431
- {
3432
- fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_3towulqd'}, {modelID: 'TS0601', manufacturerName: '_TZE200_1ibpyhdc'}],
3488
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_3towulqd', '_TZE200_1ibpyhdc', '_TZE200_bh3n6gk8']),
3433
3489
  model: 'ZG-204ZL',
3434
3490
  vendor: 'TuYa',
3435
3491
  description: 'Luminance motion sensor',
@@ -3550,4 +3606,112 @@ module.exports = [
3550
3606
  .withDescription('Turns the onboard LED on or off'),
3551
3607
  ],
3552
3608
  },
3609
+ {
3610
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_qoy0ekbd', '_TZE200_znbl8dj5', '_TZE200_a8sdabtg']),
3611
+ model: 'ZG-227ZL',
3612
+ vendor: 'TuYa',
3613
+ description: 'Temperature & humidity LCD sensor',
3614
+ fromZigbee: [tuya.fzDataPoints],
3615
+ toZigbee: [tuya.tzDataPoints],
3616
+ configure: tuya.configureMagicPacket,
3617
+ exposes: [e.temperature(), e.humidity(), tuya.exposes.temperatureUnit(), tuya.exposes.temperatureCalibration(),
3618
+ tuya.exposes.humidityCalibration(), e.battery()],
3619
+ meta: {
3620
+ tuyaDatapoints: [
3621
+ [1, 'temperature', tuya.valueConverter.divideBy10],
3622
+ [2, 'humidity', tuya.valueConverter.raw],
3623
+ [4, 'battery', tuya.valueConverter.raw],
3624
+ [9, 'temperature_unit', tuya.valueConverter.temperatureUnit],
3625
+ [23, 'temperature_calibration', tuya.valueConverter.divideBy10],
3626
+ [24, 'humidity_calibration', tuya.valueConverter.raw],
3627
+ ],
3628
+ },
3629
+ },
3630
+ {
3631
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_n8dljorx', '_TZE200_pay2byax']),
3632
+ model: 'ZG-102ZL',
3633
+ vendor: 'TuYa',
3634
+ description: 'Luminance door sensor',
3635
+ fromZigbee: [tuya.fzDataPoints],
3636
+ toZigbee: [tuya.tzDataPoints],
3637
+ configure: tuya.configureMagicPacket,
3638
+ exposes: [e.contact(), e.illuminance().withUnit('lx'), e.battery()],
3639
+ meta: {
3640
+ tuyaDatapoints: [
3641
+ [1, 'contact', tuya.valueConverter.inverse],
3642
+ [101, 'illuminance', tuya.valueConverter.raw],
3643
+ [2, 'battery', tuya.valueConverter.raw],
3644
+ ],
3645
+ },
3646
+ },
3647
+ {
3648
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_8isdky6j']),
3649
+ model: 'ZG-225Z',
3650
+ vendor: 'TuYa',
3651
+ description: 'Gas sensor',
3652
+ fromZigbee: [tuya.fzDataPoints],
3653
+ toZigbee: [tuya.tzDataPoints],
3654
+ configure: tuya.configureMagicPacket,
3655
+ exposes: [e.gas(), tuya.exposes.gasValue()],
3656
+ meta: {
3657
+ tuyaDatapoints: [
3658
+ [1, 'gas', tuya.valueConverter.true0ElseFalse],
3659
+ [2, 'gas_value', tuya.valueConverter.raw],
3660
+ ],
3661
+ },
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
+ },
3553
3717
  ];
package/devices/xiaomi.js CHANGED
@@ -131,7 +131,7 @@ const fzLocal = {
131
131
  break;
132
132
  case 0x041502bc: { // feeding report
133
133
  const report = val.toString();
134
- result['feeding_source'] = {1: 'manual', 2: 'remote'}[parseInt(report.slice(0, 2))];
134
+ result['feeding_source'] = {0: 'schedule', 1: 'manual', 2: 'remote'}[parseInt(report.slice(0, 2))];
135
135
  result['feeding_size'] = parseInt(report.slice(3, 4));
136
136
  break;
137
137
  }
@@ -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'],
@@ -2582,7 +2583,7 @@ module.exports = [
2582
2583
  toZigbee: [tzLocal.aqara_feeder],
2583
2584
  exposes: [
2584
2585
  exposes.enum('feed', ea.STATE_SET, ['START']).withDescription('Start feeding'),
2585
- exposes.enum('feeding_source', ea.STATE, ['manual', 'remote']).withDescription('Feeding source'),
2586
+ exposes.enum('feeding_source', ea.STATE, ['schedule', 'manual', 'remote']).withDescription('Feeding source'),
2586
2587
  exposes.numeric('feeding_size', ea.STATE).withDescription('Feeding size').withUnit('portion'),
2587
2588
  exposes.numeric('portions_per_day', ea.STATE).withDescription('Portions per day'),
2588
2589
  exposes.numeric('weight_per_day', ea.STATE).withDescription('Weight per day').withUnit('g'),
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
 
@@ -1170,6 +1174,22 @@ const tuyaExposes = {
1170
1174
  errorStatus: () => exposes.numeric('error_status', ea.STATE).withDescription('Error status'),
1171
1175
  scheduleAllDays: (access, format) => ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']
1172
1176
  .map((day) => exposes.text(`schedule_${day}`, access).withDescription(`Schedule for ${day}, format: "${format}"`)),
1177
+ temperatureUnit: () => exposes.enum('temperature_unit', ea.STATE_SET, ['celsius', 'fahrenheit']).withDescription('Temperature unit'),
1178
+ temperatureCalibration: () => exposes.numeric('temperature_calibration', ea.STATE_SET).withValueMin(-2.0).withValueMax(2.0)
1179
+ .withValueStep(0.1).withUnit('°C').withDescription('Temperature calibration'),
1180
+ humidityCalibration: () => exposes.numeric('humidity_calibration', ea.STATE_SET).withValueMin(-30).withValueMax(30)
1181
+ .withValueStep(1).withUnit('%').withDescription('Humidity calibration'),
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()})`),
1173
1193
  };
1174
1194
 
1175
1195
  const skip = {
@@ -1255,7 +1275,9 @@ const valueConverter = {
1255
1275
  scale0_254to0_1000: valueConverterBasic.scale(0, 254, 0, 1000),
1256
1276
  scale0_1to0_1000: valueConverterBasic.scale(0, 1, 0, 1000),
1257
1277
  divideBy100: valueConverterBasic.divideBy(100),
1278
+ temperatureUnit: valueConverterBasic.lookup({'celsius': 0, 'fahrenheit': 1}),
1258
1279
  divideBy10: valueConverterBasic.divideBy(10),
1280
+ divideBy1000: valueConverterBasic.divideBy(1000),
1259
1281
  raw: valueConverterBasic.raw(),
1260
1282
  phaseVariant1: {
1261
1283
  from: (v) => {
@@ -1269,6 +1291,17 @@ const valueConverter = {
1269
1291
  return {voltage: (buf[1] | buf[0] << 8) / 10, current: (buf[4] | buf[3] << 8) / 1000, power: (buf[7] | buf[6] << 8)};
1270
1292
  },
1271
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
+ },
1272
1305
  threshold: {
1273
1306
  from: (v) => {
1274
1307
  const buffer = Buffer.from(v, 'base64');
@@ -1452,11 +1485,13 @@ const valueConverter = {
1452
1485
  return {system_mode: v === false ? 'heat' : 'off', heating_stop: v === false ? 'OFF' : 'ON'};
1453
1486
  },
1454
1487
  },
1488
+ inverse: {to: (v) => !v, from: (v) => !v},
1455
1489
  onOffNotStrict: {from: (v) => v ? 'ON' : 'OFF', to: (v) => v === 'ON'},
1456
1490
  };
1457
1491
 
1458
1492
  const tzDataPoints = {
1459
1493
  key: [
1494
+ 'temperature_unit', 'temperature_calibration', 'humidity_calibration',
1460
1495
  'state', 'brightness', 'min_brightness', 'max_brightness', 'power_on_behavior',
1461
1496
  'countdown', 'light_type', 'silence', 'self_test', 'child_lock', 'open_window', 'open_window_temperature', 'frost_protection',
1462
1497
  'system_mode', 'heating_stop', 'current_heating_setpoint', 'local_temperature_calibration', 'preset', 'boost_timeset_countdown',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.673",
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": [