zigbee-herdsman-converters 14.0.390 → 14.0.394

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.
@@ -699,6 +699,8 @@ const converters = {
699
699
  */
700
700
  cluster: 'haElectricalMeasurement',
701
701
  type: ['attributeReport', 'readResponse'],
702
+ options: [exposes.options.calibration('power', 'percentual'), exposes.options.calibration('current', 'percentual'),
703
+ exposes.options.calibration('voltage', 'percentual')],
702
704
  convert: (model, msg, publish, options, meta) => {
703
705
  const getFactor = (key) => {
704
706
  const multiplier = msg.endpoint.getClusterAttributeValue('haElectricalMeasurement', `${key}Multiplier`);
@@ -724,7 +726,8 @@ const converters = {
724
726
  if (msg.data.hasOwnProperty(entry.key)) {
725
727
  const factor = getFactor(entry.factor);
726
728
  const property = postfixWithEndpointName(entry.name, msg, model);
727
- payload[property] = precisionRound(msg.data[entry.key] * factor, 2);
729
+ const value = msg.data[entry.key] * factor;
730
+ payload[property] = calibrateAndPrecisionRoundOptions(value, options, entry.name);
728
731
  }
729
732
  }
730
733
  return payload;
@@ -1860,6 +1863,36 @@ const converters = {
1860
1863
  }
1861
1864
  },
1862
1865
  },
1866
+ tuya_illuminance_sensor: {
1867
+ cluster: `manuSpecificTuya`,
1868
+ type: [`commandDataReport`, `commandDataResponse`],
1869
+ options: [exposes.options.precision('illuminance_lux'),
1870
+ exposes.options.calibration('illuminance_lux', 'percentual')],
1871
+ convert: (() => {
1872
+ const brightnessState = {
1873
+ 0: 'low',
1874
+ 1: 'middle',
1875
+ 2: 'high',
1876
+ 3: 'strong',
1877
+ };
1878
+ return (model, msg, publish, options, meta) => {
1879
+ const dpValue = tuya.firstDpValue(msg, meta, `tuya_illuminance_sensor`);
1880
+ const dp = dpValue.dp;
1881
+ const value = tuya.getDataValue(dpValue);
1882
+ switch (dp) {
1883
+ case tuya.dataPoints.state:
1884
+ return {brightness_state: brightnessState[value]};
1885
+ case tuya.dataPoints.tIlluminanceLux:
1886
+ return {illuminance_lux: calibrateAndPrecisionRoundOptions(value, options, 'illuminance_lux')};
1887
+ default:
1888
+ meta.logger.warn(
1889
+ `zigbee-herdsman-converters:tuya_illuminance_sensor: NOT RECOGNIZED ` +
1890
+ `DP #${dp} with data ${JSON.stringify(dpValue)}`,
1891
+ );
1892
+ }
1893
+ };
1894
+ })(),
1895
+ },
1863
1896
  ts0201_temperature_humidity_alarm: {
1864
1897
  cluster: 'manuSpecificTuya_2',
1865
1898
  type: ['attributeReport', 'readResponse'],
@@ -2468,6 +2501,30 @@ const converters = {
2468
2501
  }
2469
2502
  },
2470
2503
  },
2504
+ neo_alarm: {
2505
+ cluster: 'manuSpecificTuya',
2506
+ type: ['commandDataReport', 'commandDataResponse'],
2507
+ convert: (model, msg, publish, options, meta) => {
2508
+ const dpValue = tuya.firstDpValue(msg, meta, 'neo_alarm');
2509
+ const dp = dpValue.dp;
2510
+ const value = tuya.getDataValue(dpValue);
2511
+
2512
+ switch (dp) {
2513
+ case tuya.dataPoints.neoAOAlarm: // 0x13 [TRUE,FALSE]
2514
+ return {alarm: value};
2515
+ case tuya.dataPoints.neoAODuration: // 0x7 [0,0,0,10] duration alarm in second
2516
+ return {duration: value};
2517
+ case tuya.dataPoints.neoAOBattPerc: // 0x15 [0,0,0,100] battery percentage
2518
+ return {battpercentage: value};
2519
+ case tuya.dataPoints.neoAOMelody: // 0x21 [5] Melody
2520
+ return {melody: value};
2521
+ case tuya.dataPoints.neoAOVolume: // 0x5 [0]/[1]/[2] Volume 0-max, 2-low
2522
+ return {volume: {2: 'low', 1: 'medium', 0: 'high'}[value]};
2523
+ default: // Unknown code
2524
+ meta.logger.warn(`Unhandled DP #${dp}: ${JSON.stringify(msg.data)}`);
2525
+ }
2526
+ },
2527
+ },
2471
2528
  terncy_contact: {
2472
2529
  cluster: 'genBinaryInput',
2473
2530
  type: 'attributeReport',
@@ -5238,6 +5295,7 @@ const converters = {
5238
5295
  payload.gas_sensitivity = {1: '15%LEL', 2: '10%LEL'}[msg.data['268']];
5239
5296
  }
5240
5297
  }
5298
+ if (msg.data.hasOwnProperty('293')) payload.click_mode = {1: 'fast', 2: 'multi'}[msg.data['293']];
5241
5299
  if (msg.data.hasOwnProperty('294')) payload.mute = msg.data['294'] === 1; // JT-BZ-01AQ/A
5242
5300
  if (msg.data.hasOwnProperty('295')) payload.test = msg.data['295'] === 1; // JT-BZ-01AQ/A
5243
5301
  if (msg.data.hasOwnProperty('313')) payload.state = msg.data['313'] === 1 ? 'preparation' : 'work'; // JT-BZ-01AQ/A
@@ -7664,7 +7722,7 @@ const converters = {
7664
7722
  result = {tumble_switch: {false: 'OFF', true: 'ON'}[value]};
7665
7723
  break;
7666
7724
  case tuya.dataPoints.trsfFallDownStatus:
7667
- result = {fall_down_status: {0: false, 1: true}[value]};
7725
+ result = {fall_down_status: tuya.tuyaRadar.fallDown[value]};
7668
7726
  break;
7669
7727
  case tuya.dataPoints.trsfStaticDwellAlarm:
7670
7728
  result = {static_dwell_alarm: value};
@@ -7703,6 +7761,31 @@ const converters = {
7703
7761
  return result;
7704
7762
  },
7705
7763
  },
7764
+ matsee_garage_door_opener: {
7765
+ cluster: 'manuSpecificTuya',
7766
+ type: ['commandDataReport', 'raw'],
7767
+ convert: (model, msg, publish, options, meta) => {
7768
+ const result = {};
7769
+ for (const dpValue of msg.data.dpValues) {
7770
+ const value = tuya.getDataValue(dpValue);
7771
+ switch (dpValue.dp) {
7772
+ case tuya.dataPoints.garageDoorTrigger:
7773
+ result.action = 'trigger';
7774
+ break;
7775
+ case tuya.dataPoints.garageDoorContact:
7776
+ result.garage_door_contact = Boolean(!value);
7777
+ break;
7778
+ case tuya.dataPoints.garageDoorStatus:
7779
+ // This reports a garage door status (open, closed), but it is very naive and misleading
7780
+ break;
7781
+ default:
7782
+ meta.logger.debug(`zigbee-herdsman-converters:matsee_garage_door_opener: NOT RECOGNIZED ` +
7783
+ `DP #${dpValue.dp} with data ${JSON.stringify(dpValue)}`);
7784
+ }
7785
+ }
7786
+ return result;
7787
+ },
7788
+ },
7706
7789
  moes_thermostat_tv: {
7707
7790
  cluster: 'manuSpecificTuya',
7708
7791
  type: ['commandDataResponse', 'commandDataReport', 'raw'],
@@ -1270,7 +1270,7 @@ const converters = {
1270
1270
  convertSet: async (entity, key, value, meta) => {
1271
1271
  let result;
1272
1272
  if (meta.options.thermostat_unit === 'fahrenheit') {
1273
- result = utils.normalizeCelsiusVersionOfFahrenheit(value) * 100;
1273
+ result = Math.round(utils.normalizeCelsiusVersionOfFahrenheit(value) * 100);
1274
1274
  } else {
1275
1275
  result = (Math.round((value * 2).toFixed(1)) / 2).toFixed(1) * 100;
1276
1276
  }
@@ -1287,7 +1287,7 @@ const converters = {
1287
1287
  convertSet: async (entity, key, value, meta) => {
1288
1288
  let result;
1289
1289
  if (meta.options.thermostat_unit === 'fahrenheit') {
1290
- result = utils.normalizeCelsiusVersionOfFahrenheit(value) * 100;
1290
+ result = Math.round(utils.normalizeCelsiusVersionOfFahrenheit(value) * 100);
1291
1291
  } else {
1292
1292
  result = (Math.round((value * 2).toFixed(1)) / 2).toFixed(1) * 100;
1293
1293
  }
@@ -1304,7 +1304,7 @@ const converters = {
1304
1304
  convertSet: async (entity, key, value, meta) => {
1305
1305
  let result;
1306
1306
  if (meta.options.thermostat_unit === 'fahrenheit') {
1307
- result = utils.normalizeCelsiusVersionOfFahrenheit(value) * 100;
1307
+ result = Math.round(utils.normalizeCelsiusVersionOfFahrenheit(value) * 100);
1308
1308
  } else {
1309
1309
  result = (Math.round((value * 2).toFixed(1)) / 2).toFixed(1) * 100;
1310
1310
  }
@@ -1321,7 +1321,7 @@ const converters = {
1321
1321
  convertSet: async (entity, key, value, meta) => {
1322
1322
  let result;
1323
1323
  if (meta.options.thermostat_unit === 'fahrenheit') {
1324
- result = utils.normalizeCelsiusVersionOfFahrenheit(value) * 100;
1324
+ result = Math.round(utils.normalizeCelsiusVersionOfFahrenheit(value) * 100);
1325
1325
  } else {
1326
1326
  result = (Math.round((value * 2).toFixed(1)) / 2).toFixed(1) * 100;
1327
1327
  }
@@ -1356,7 +1356,7 @@ const converters = {
1356
1356
  convertSet: async (entity, key, value, meta) => {
1357
1357
  let result;
1358
1358
  if (meta.options.thermostat_unit === 'fahrenheit') {
1359
- result = utils.normalizeCelsiusVersionOfFahrenheit(value) * 100;
1359
+ result = Math.round(utils.normalizeCelsiusVersionOfFahrenheit(value) * 100);
1360
1360
  } else {
1361
1361
  result = (Math.round((value * 2).toFixed(1)) / 2).toFixed(1) * 100;
1362
1362
  }
@@ -1372,7 +1372,7 @@ const converters = {
1372
1372
  convertSet: async (entity, key, value, meta) => {
1373
1373
  let result;
1374
1374
  if (meta.options.thermostat_unit === 'fahrenheit') {
1375
- result = utils.normalizeCelsiusVersionOfFahrenheit(value) * 100;
1375
+ result = Math.round(utils.normalizeCelsiusVersionOfFahrenheit(value) * 100);
1376
1376
  } else {
1377
1377
  result = (Math.round((value * 2).toFixed(1)) / 2).toFixed(1) * 100;
1378
1378
  }
@@ -2333,6 +2333,12 @@ const converters = {
2333
2333
  tuya.sendDataPointRaw(entity, tuya.dataPoints.lidlTimer, tuya.convertDecimalValueTo4ByteHexArray(value));
2334
2334
  },
2335
2335
  },
2336
+ matsee_garage_door_opener: {
2337
+ key: ['trigger'],
2338
+ convertSet: (entity, key, value, meta) => {
2339
+ tuya.sendDataPointBool(entity, tuya.dataPoints.action, true);
2340
+ },
2341
+ },
2336
2342
  SPZ01_power_outage_memory: {
2337
2343
  key: ['power_outage_memory'],
2338
2344
  convertSet: async (entity, key, value, meta) => {
@@ -5074,6 +5080,32 @@ const converters = {
5074
5080
  }
5075
5081
  },
5076
5082
  },
5083
+ neo_alarm: {
5084
+ key: [
5085
+ 'alarm', 'melody', 'volume', 'duration',
5086
+ ],
5087
+ convertSet: async (entity, key, value, meta) => {
5088
+ switch (key) {
5089
+ case 'alarm':
5090
+ await tuya.sendDataPointBool(entity, tuya.dataPoints.neoAOAlarm, value);
5091
+ break;
5092
+ case 'melody':
5093
+ await tuya.sendDataPointEnum(entity, tuya.dataPoints.neoAOMelody, parseInt(value, 10));
5094
+ break;
5095
+ case 'volume':
5096
+ await tuya.sendDataPointEnum(
5097
+ entity,
5098
+ tuya.dataPoints.neoAOVolume,
5099
+ {'low': 2, 'medium': 1, 'high': 0}[value]);
5100
+ break;
5101
+ case 'duration':
5102
+ await tuya.sendDataPointValue(entity, tuya.dataPoints.neoAODuration, value);
5103
+ break;
5104
+ default: // Unknown key
5105
+ throw new Error(`Unhandled key ${key}`);
5106
+ }
5107
+ },
5108
+ },
5077
5109
  nous_lcd_temperature_humidity_sensor: {
5078
5110
  key: ['min_temperature', 'max_temperature', 'temperature_sensitivity', 'temperature_unit_convert'],
5079
5111
  convertSet: async (entity, key, value, meta) => {
@@ -6548,6 +6580,9 @@ const converters = {
6548
6580
  await entity.write('aqaraOpple', {0x0125: {value: lookupState[value], type: 0x20}}, manufacturerOptions.xiaomi);
6549
6581
  return {state: {click_mode: value}};
6550
6582
  },
6583
+ convertGet: async (entity, key, meta) => {
6584
+ await entity.read('aqaraOpple', [0x125], manufacturerOptions.xiaomi);
6585
+ },
6551
6586
  },
6552
6587
  tuya_light_wz5: {
6553
6588
  key: ['color', 'color_temp', 'brightness', 'white_brightness'],
@@ -100,4 +100,17 @@ module.exports = [
100
100
  await reporting.onOff(endpoint);
101
101
  },
102
102
  },
103
+ {
104
+ zigbeeModel: ['43096'],
105
+ model: '43096',
106
+ vendor: 'Enbrighten',
107
+ description: 'Zigbee plug-in smart dimmer with dual controlled outlets',
108
+ extend: extend.light_onoff_brightness({noConfigure: true}),
109
+ configure: async (device, coordinatorEndpoint, logger) => {
110
+ await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
111
+ const endpoint = device.getEndpoint(1);
112
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
113
+ await reporting.onOff(endpoint);
114
+ },
115
+ },
103
116
  ];
package/devices/ikea.js CHANGED
@@ -64,6 +64,12 @@ const tradfriExtend = {
64
64
  ota: ota.tradfri,
65
65
  onEvent: bulbOnEvent,
66
66
  }),
67
+ light_onoff_brightness_color: (options = {}) => ({
68
+ ...extend.light_onoff_brightness_color(options),
69
+ exposes: extend.light_onoff_brightness_color(options).exposes.concat(e.power_on_behavior()),
70
+ ota: ota.tradfri,
71
+ onEvent: bulbOnEvent,
72
+ }),
67
73
  };
68
74
 
69
75
  const manufacturerOptions = {manufacturerCode: herdsman.Zcl.ManufacturerCode.IKEA_OF_SWEDEN};
@@ -369,7 +375,7 @@ module.exports = [
369
375
  model: 'LED1624G9',
370
376
  vendor: 'IKEA',
371
377
  description: 'TRADFRI LED bulb E14/E26/E27 600 lumen, dimmable, color, opal white',
372
- extend: tradfriExtend.light_onoff_brightness_colortemp_color({colorTempRange: [250, 454]}),
378
+ extend: tradfriExtend.light_onoff_brightness_color(),
373
379
  meta: {supportsHueAndSaturation: false},
374
380
  },
375
381
  {
@@ -5,6 +5,7 @@ const reporting = require('../lib/reporting');
5
5
  const extend = require('../lib/extend');
6
6
  const e = exposes.presets;
7
7
  const ea = exposes.access;
8
+ const ota = require('../lib/ota');
8
9
 
9
10
  const readInitialBatteryState = async (type, data, device) => {
10
11
  if (['deviceAnnounce'].includes(type)) {
@@ -63,6 +64,7 @@ module.exports = [
63
64
  fromZigbee: [fz.identify, fz.ignore_basic_report, fz.command_cover_open, fz.command_cover_close, fz.command_cover_stop, fz.battery,
64
65
  fz.legrand_binary_input_moving],
65
66
  toZigbee: [],
67
+ ota: ota.zigbeeOTA,
66
68
  exposes: [e.battery(), e.action(['identify', 'open', 'close', 'stop', 'moving', 'stopped'])],
67
69
  configure: async (device, coordinatorEndpoint, logger) => {
68
70
  const endpoint = device.getEndpoint(1);
@@ -182,6 +184,7 @@ module.exports = [
182
184
  zigbeeModel: [' Connected outlet\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000'],
183
185
  model: '067775/741811',
184
186
  vendor: 'Legrand',
187
+ ota: ota.zigbeeOTA,
185
188
  description: 'Power socket with power consumption monitoring',
186
189
  fromZigbee: [fz.identify, fz.on_off, fz.electrical_measurement],
187
190
  toZigbee: [tz.on_off, tz.legrand_settingAlwaysEnableLed, tz.legrand_identify],
@@ -200,6 +203,7 @@ module.exports = [
200
203
  vendor: 'Legrand',
201
204
  description: 'Wired micromodule switch',
202
205
  extend: extend.switch(),
206
+ ota: ota.zigbeeOTA,
203
207
  fromZigbee: [fz.identify, fz.on_off],
204
208
  toZigbee: [tz.on_off, tz.legrand_identify],
205
209
  configure: async (device, coordinatorEndpoint, logger) => {
package/devices/lg.js ADDED
@@ -0,0 +1,18 @@
1
+ const extend = require('../lib/extend');
2
+
3
+ module.exports = [
4
+ {
5
+ zigbeeModel: ['B1027EB0Z01'],
6
+ model: 'B1027EB0Z01',
7
+ vendor: 'LG Electronics',
8
+ description: 'Smart bulb 1',
9
+ extend: extend.light_onoff_brightness(),
10
+ },
11
+ {
12
+ zigbeeModel: ['B1027EB0Z02'],
13
+ model: 'B1027EB0Z02',
14
+ vendor: 'LG Electronics',
15
+ description: 'Smart bulb 2',
16
+ extend: extend.light_onoff_brightness(),
17
+ },
18
+ ];
@@ -0,0 +1,31 @@
1
+ const fz = require('../converters/fromZigbee');
2
+ const exposes = require('../lib/exposes');
3
+ const reporting = require('../lib/reporting');
4
+ const extend = require('../lib/extend');
5
+ const e = exposes.presets;
6
+ const ea = exposes.access;
7
+
8
+
9
+ module.exports = [
10
+ {
11
+ zigbeeModel: ['SZ1000'],
12
+ model: 'ZB250',
13
+ vendor: 'Micro Matic Norge AS',
14
+ description: 'Zigbee dimmer for LED',
15
+ fromZigbee: extend.light_onoff_brightness().fromZigbee.concat([fz.electrical_measurement, fz.metering]),
16
+ toZigbee: extend.light_onoff_brightness().toZigbee,
17
+ configure: async (device, coordinatorEndpoint, logger) => {
18
+ await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
19
+ const endpoint = device.getEndpoint(1);
20
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl', 'haElectricalMeasurement', 'seMetering']);
21
+ await reporting.brightness(endpoint);
22
+ await reporting.readEletricalMeasurementMultiplierDivisors(endpoint);
23
+ await reporting.rmsVoltage(endpoint, {min: 10, change: 20}); // Voltage - Min change of 2V
24
+ await reporting.rmsCurrent(endpoint, {min: 10, change: 10}); // A - z2m displays only the first decimals, change of 10 / 0,01A
25
+ await reporting.activePower(endpoint, {min: 10, change: 15}); // W - Min change of 1,5W
26
+ await reporting.currentSummDelivered(endpoint, {min: 300}); // Report KWH every 5min
27
+ },
28
+ exposes: [e.light_brightness(), e.power(), e.current(), e.voltage().withAccess(ea.STATE), e.energy()],
29
+ },
30
+ ];
31
+
package/devices/neo.js CHANGED
@@ -34,6 +34,29 @@ module.exports = [
34
34
  await endpoint.command('manuSpecificTuya', 'mcuVersionRequest', {'seq': 0x0002});
35
35
  },
36
36
  },
37
+ {
38
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_t1blo2bj'}],
39
+ zigbeeModel: ['1blo2bj'],
40
+ model: 'NAS-AB02B2',
41
+ vendor: 'Neo',
42
+ description: 'Alarm',
43
+ fromZigbee: [fz.neo_alarm, fz.ignore_basic_report],
44
+ toZigbee: [tz.neo_alarm],
45
+ exposes: [
46
+ e.battery_low(),
47
+ exposes.binary('alarm', ea.STATE_SET, true, false),
48
+ exposes.enum('melody', ea.STATE_SET, Array.from(Array(18).keys()).map((x)=>(x+1).toString())),
49
+ exposes.numeric('duration', ea.STATE_SET).withUnit('second').withValueMin(0).withValueMax(1800),
50
+ exposes.enum('volume', ea.STATE_SET, ['low', 'medium', 'high']),
51
+ exposes.numeric('battpercentage', ea.STATE).withUnit('%'),
52
+ ],
53
+ onEvent: tuya.onEventSetLocalTime,
54
+ configure: async (device, coordinatorEndpoint, logger) => {
55
+ const endpoint = device.getEndpoint(1);
56
+ await endpoint.command('manuSpecificTuya', 'dataQuery', {});
57
+ await endpoint.command('manuSpecificTuya', 'mcuVersionRequest', {'seq': 0x0002});
58
+ },
59
+ },
37
60
  {
38
61
  fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_7hfcudw5'}],
39
62
  model: 'NAS-PD07',
@@ -29,6 +29,13 @@ const hueExtend = {
29
29
  };
30
30
 
31
31
  module.exports = [
32
+ {
33
+ zigbeeModel: ['929003055801'],
34
+ model: '929003055801',
35
+ vendor: 'Philips',
36
+ description: 'Hue white ambiance bathroom ceiling light Adore with Bluetooth',
37
+ extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
38
+ },
32
39
  {
33
40
  zigbeeModel: ['929003056901'],
34
41
  model: '929003056901',
@@ -66,7 +73,7 @@ module.exports = [
66
73
  ota: ota.zigbeeOTA,
67
74
  },
68
75
  {
69
- zigbeeModel: ['915005996401'],
76
+ zigbeeModel: ['915005996401', '915005996501'],
70
77
  model: '915005996401',
71
78
  vendor: 'Philips',
72
79
  description: 'Hue white ambiance ceiling light Enrave S with Bluetooth',
@@ -261,7 +268,7 @@ module.exports = [
261
268
  ota: ota.zigbeeOTA,
262
269
  },
263
270
  {
264
- zigbeeModel: ['LLC012', 'LLC011'],
271
+ zigbeeModel: ['LLC012', 'LLC011', 'LLC013'],
265
272
  model: '7299760PH',
266
273
  vendor: 'Philips',
267
274
  description: 'Hue Bloom',
@@ -494,6 +501,15 @@ module.exports = [
494
501
  extend: hueExtend.light_onoff_brightness(),
495
502
  ota: ota.zigbeeOTA,
496
503
  },
504
+ {
505
+ zigbeeModel: ['1746630V7'],
506
+ model: '1746630V7',
507
+ vendor: 'Philips',
508
+ description: 'Amarant linear outdoor light',
509
+ meta: {turnsOffAtBrightness1: true},
510
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
511
+ ota: ota.zigbeeOTA,
512
+ },
497
513
  {
498
514
  zigbeeModel: ['LCC001'],
499
515
  model: '4090531P7',
@@ -1194,12 +1210,12 @@ module.exports = [
1194
1210
  ota: ota.zigbeeOTA,
1195
1211
  },
1196
1212
  {
1197
- zigbeeModel: ['3261031P6'],
1213
+ zigbeeModel: ['3261031P6', '929003055001'],
1198
1214
  model: '3261031P6',
1199
1215
  vendor: 'Philips',
1200
1216
  description: 'Hue Being white',
1201
1217
  meta: {turnsOffAtBrightness1: true},
1202
- extend: hueExtend.light_onoff_brightness_colortemp(),
1218
+ extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
1203
1219
  ota: ota.zigbeeOTA,
1204
1220
  },
1205
1221
  {
@@ -2619,4 +2635,21 @@ module.exports = [
2619
2635
  extend: hueExtend.light_onoff_brightness(),
2620
2636
  ota: ota.zigbeeOTA,
2621
2637
  },
2638
+ {
2639
+ zigbeeModel: ['915005997501'],
2640
+ model: '915005997501',
2641
+ vendor: 'Philips',
2642
+ description: 'Hue Bluetooth white & color ambiance ceiling lamp Infuse large',
2643
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
2644
+ ota: ota.zigbeeOTA,
2645
+ },
2646
+ {
2647
+ zigbeeModel: ['929003045001_01', '929003045001_02', '929003045001_03'],
2648
+ model: '9290019533',
2649
+ vendor: 'Philips',
2650
+ description: 'Hue white ambiance GU10 with Bluetooth',
2651
+ meta: {turnsOffAtBrightness1: true},
2652
+ extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
2653
+ ota: ota.zigbeeOTA,
2654
+ },
2622
2655
  ];
@@ -0,0 +1,20 @@
1
+ const reporting = require('zigbee-herdsman-converters/lib/reporting');
2
+ const extend = require('zigbee-herdsman-converters/lib/extend');
3
+
4
+ module.exports = [
5
+ {
6
+ zigbeeModel: ['12501'],
7
+ model: '12501',
8
+ vendor: 'Scan Products',
9
+ description: 'Zigbee push dimmer',
10
+ fromZigbee: extend.light_onoff_brightness().fromZigbee,
11
+ toZigbee: extend.light_onoff_brightness().toZigbee,
12
+ extend: extend.light_onoff_brightness({noConfigure: true}),
13
+ configure: async (device, coordinatorEndpoint, logger) => {
14
+ await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
15
+ const endpoint = device.getEndpoint(1);
16
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
17
+ await reporting.onOff(endpoint);
18
+ },
19
+ },
20
+ ];
@@ -37,6 +37,22 @@ module.exports = [
37
37
  endpoint.saveClusterAttributeKeyValue('seMetering', {divisor: 1000000, multiplier: 1});
38
38
  },
39
39
  },
40
+ {
41
+ zigbeeModel: ['SZ-ESW02'],
42
+ model: 'SZ-ESW02',
43
+ vendor: 'Sercomm',
44
+ description: 'Telstra smart plug 2',
45
+ fromZigbee: [fz.on_off, fz.metering],
46
+ exposes: [e.switch(), e.power()],
47
+ toZigbee: [tz.on_off],
48
+ configure: async (device, coordinatorEndpoint, logger) => {
49
+ const endpoint = device.getEndpoint(1);
50
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'seMetering']);
51
+ await reporting.onOff(endpoint);
52
+ await reporting.instantaneousDemand(endpoint);
53
+ endpoint.saveClusterAttributeKeyValue('seMetering', {divisor: 1000000, multiplier: 1});
54
+ },
55
+ },
40
56
  {
41
57
  zigbeeModel: ['XHS2-SE'],
42
58
  model: 'XHS2-SE',
package/devices/tuya.js CHANGED
@@ -206,7 +206,8 @@ module.exports = [
206
206
  {modelID: 'TS0501B', manufacturerName: '_TZ3210_4whigl8i'},
207
207
  {modelID: 'TS0501B', manufacturerName: '_TZ3210_9q49basr'},
208
208
  {modelID: 'TS0501B', manufacturerName: '_TZ3210_grnwgegn'},
209
- {modelID: 'TS0501B', manufacturerName: '_TZ3210_wuheofsg'}],
209
+ {modelID: 'TS0501B', manufacturerName: '_TZ3210_wuheofsg'},
210
+ {modelID: 'TS0501B', manufacturerName: '_TZ3210_e5t9bfdv'}],
210
211
  model: 'TS0501B',
211
212
  description: 'Zigbee light',
212
213
  vendor: 'TuYa',
@@ -839,6 +840,7 @@ module.exports = [
839
840
  {modelID: 'TS0601', manufacturerName: '_TZE200_sbordckq'},
840
841
  {modelID: 'TS0601', manufacturerName: '_TZE200_fctwhugx'},
841
842
  {modelID: 'TS0601', manufacturerName: '_TZE200_zah67ekd'},
843
+ {modelID: 'TS0601', manufacturerName: '_TZE200_hsgrhjpf'},
842
844
  // Window pushers:
843
845
  {modelID: 'TS0601', manufacturerName: '_TZE200_g5wdnuow'},
844
846
  // Tubular motors:
@@ -1663,6 +1665,21 @@ module.exports = [
1663
1665
  e.energy(), exposes.enum('power_outage_memory', ea.STATE_SET, ['on', 'off', 'restore'])
1664
1666
  .withDescription('Recover state after power outage')],
1665
1667
  },
1668
+ {
1669
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_nklqjk62'}],
1670
+ model: 'PJ-ZGD01',
1671
+ vendor: 'TuYa',
1672
+ description: 'Garage door opener',
1673
+ fromZigbee: [fz.matsee_garage_door_opener, fz.ignore_basic_report],
1674
+ toZigbee: [tz.matsee_garage_door_opener, tz.tuya_data_point_test],
1675
+ whiteLabel: [{vendor: 'MatSee Plus', model: 'PJ-ZGD01'}],
1676
+ configure: async (device, coordinatorEndpoint, logger) => {
1677
+ const endpoint = device.getEndpoint(1);
1678
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genBasic']);
1679
+ },
1680
+ exposes: [exposes.binary('trigger', ea.STATE_SET, true, false).withDescription('Trigger the door movement'),
1681
+ e.action(), exposes.binary('garage_door_contact', ea.STATE, true, false)],
1682
+ },
1666
1683
  {
1667
1684
  fingerprint: [{modelID: 'TS0201', manufacturerName: '_TZ3000_qaaysllp'}],
1668
1685
  model: 'LCZ030',
@@ -1755,7 +1772,8 @@ module.exports = [
1755
1772
  .withDescription('fall sensitivity of the radar'),
1756
1773
  exposes.numeric('tumble_alarm_time', ea.STATE_SET).withValueMin(1).withValueMax(5).withValueStep(1)
1757
1774
  .withUnit('min').withDescription('tumble alarm time'),
1758
- exposes.binary('fall_down_status', ea.STATE).withDescription('fall down status'),
1775
+ exposes.enum('fall_down_status', ea.STATE, Object.values(tuya.tuyaRadar.fallDown))
1776
+ .withDescription('fall down status'),
1759
1777
  exposes.text('static_dwell_alarm', ea.STATE).withDescription('static dwell alarm'),
1760
1778
  ],
1761
1779
  configure: async (device, coordinatorEndpoint, logger) => {
@@ -1902,4 +1920,13 @@ module.exports = [
1902
1920
  toZigbee: [],
1903
1921
  exposes: [e.contact(), e.battery(), e.vibration()],
1904
1922
  },
1923
+ {
1924
+ fingerprint: [{modelID: `TS0601`, manufacturerName: `_TZE200_yi4jtqq1`}],
1925
+ model: `XFY-CGQ-ZIGB`,
1926
+ vendor: `TuYa`,
1927
+ description: `Illuminance sensor`,
1928
+ fromZigbee: [fz.tuya_illuminance_sensor],
1929
+ toZigbee: [],
1930
+ exposes: [e.illuminance_lux(), e.brightness_state()],
1931
+ },
1905
1932
  ];
@@ -0,0 +1,12 @@
1
+ const extend = require('../lib/extend');
2
+
3
+ module.exports = [
4
+ {
5
+ fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3210_dn5higyl'}],
6
+ model: 'TH008L10RGBCCT',
7
+ vendor: 'UR Lighting',
8
+ description: '10W RGB+CCT downlight',
9
+ meta: {applyRedFix: true, enhancedHue: false},
10
+ extend: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
11
+ },
12
+ ];
@@ -22,6 +22,21 @@ module.exports = [
22
22
  return {'l1': 1, 'l2': 2, 'l3': 3, 'l4': 4, 'l5': 5};
23
23
  },
24
24
  },
25
+ {
26
+ fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_cfnprab5'}],
27
+ model: 'SM-0306E-2W',
28
+ vendor: 'UseeLink',
29
+ description: '4 gang switch, with USB',
30
+ exposes: [e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'), e.switch().withEndpoint('l3'),
31
+ e.switch().withEndpoint('l4'), e.switch().withEndpoint('l5')],
32
+ extend: extend.switch(),
33
+ meta: {multiEndpoint: true},
34
+ configure: async (device, coordinatorEndpoint, logger) => {
35
+ for (const ID of [1, 2, 3, 4, 5]) {
36
+ await reporting.bind(device.getEndpoint(ID), coordinatorEndpoint, ['genOnOff']);
37
+ }
38
+ },
39
+ },
25
40
  {
26
41
  fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_tvuarksa'}],
27
42
  model: 'SM-AZ713',
package/devices/xiaomi.js CHANGED
@@ -1448,6 +1448,7 @@ module.exports = [
1448
1448
  await reporting.onOff(endpoint);
1449
1449
  await reporting.deviceTemperature(endpoint);
1450
1450
  device.powerSource = 'Mains (single phase)';
1451
+ device.type = 'Router';
1451
1452
  device.save();
1452
1453
  },
1453
1454
  },
@@ -1837,7 +1838,7 @@ module.exports = [
1837
1838
  fromZigbee: [fz.xiaomi_multistate_action, fz.aqara_opple],
1838
1839
  toZigbee: [tz.xiaomi_switch_click_mode],
1839
1840
  exposes: [e.battery(), e.battery_voltage(), e.action(['single', 'double', 'hold']),
1840
- exposes.enum('click_mode', ea.SET, ['fast', 'multi'])
1841
+ exposes.enum('click_mode', ea.ALL, ['fast', 'multi'])
1841
1842
  .withDescription('Click mode, fast: only supports single click which will be send immediately after clicking.' +
1842
1843
  'multi: supports more events like double and hold')],
1843
1844
  configure: async (device, coordinatorEndpoint, logger) => {
@@ -1853,7 +1854,7 @@ module.exports = [
1853
1854
  exposes: [e.battery(), e.battery_voltage(),
1854
1855
  e.action(['single_left', 'single_right', 'single_both', 'double_left', 'double_right', 'hold_left', 'hold_right']),
1855
1856
  // eslint-disable-next-line max-len
1856
- exposes.enum('click_mode', ea.SET, ['fast', 'multi']).withDescription('Click mode, fast: only supports single click which will be send immediately after clicking, multi: supports more events like double and hold'),
1857
+ exposes.enum('click_mode', ea.ALL, ['fast', 'multi']).withDescription('Click mode, fast: only supports single click which will be send immediately after clicking, multi: supports more events like double and hold'),
1857
1858
  ],
1858
1859
  fromZigbee: [fz.xiaomi_multistate_action, fz.aqara_opple],
1859
1860
  toZigbee: [tz.xiaomi_switch_click_mode],
@@ -1864,4 +1865,23 @@ module.exports = [
1864
1865
  await endpoint1.write('aqaraOpple', {0x0125: {value: 0x02, type: 0x20}}, {manufacturerCode: 0x115f});
1865
1866
  },
1866
1867
  },
1868
+ {
1869
+ zigbeeModel: ['lumi.remote.b18ac1'],
1870
+ model: 'WXKG14LM',
1871
+ vendor: 'Xiaomi',
1872
+ description: 'Aqara wireless remote switch H1 (single rocker)',
1873
+ fromZigbee: [fz.xiaomi_multistate_action, fz.aqara_opple],
1874
+ toZigbee: [tz.xiaomi_switch_click_mode, tz.aqara_opple_operation_mode],
1875
+ exposes: [e.battery(), e.battery_voltage(), e.action(['single', 'double', 'triple', 'hold']),
1876
+ exposes.enum('click_mode', ea.ALL, ['fast', 'multi'])
1877
+ .withDescription('Click mode, fast: only supports single click which will be send immediately after clicking.' +
1878
+ 'multi: supports more events like double and hold'),
1879
+ exposes.enum('operation_mode', ea.ALL, ['command', 'event'])
1880
+ .withDescription('Operation mode, select "command" to enable bindings (wake up the device before changing modes!)')],
1881
+ configure: async (device, coordinatorEndpoint, logger) => {
1882
+ const endpoint1 = device.getEndpoint(1);
1883
+ await endpoint1.write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
1884
+ await endpoint1.read('aqaraOpple', [0x0125], {manufacturerCode: 0x115f});
1885
+ },
1886
+ },
1867
1887
  ];
package/lib/exposes.js CHANGED
@@ -543,6 +543,7 @@ module.exports = {
543
543
  humidity: () => new Numeric('humidity', access.STATE).withUnit('%').withDescription('Measured relative humidity'),
544
544
  illuminance: () => new Numeric('illuminance', access.STATE).withDescription('Raw measured illuminance'),
545
545
  illuminance_lux: () => new Numeric('illuminance_lux', access.STATE).withUnit('lx').withDescription('Measured illuminance in lux'),
546
+ brightness_state: () => new Enum('brightness_state', access.STATE, ['low', 'middle', 'high', 'strong']).withDescription('Brightness state'),
546
547
  keypad_lockout: () => new Enum('keypad_lockout', access.ALL, ['unlock', 'lock1', 'lock2']).withDescription('Enables/disables physical input on the device'),
547
548
  led_disabled_night: () => new Binary('led_disabled_night', access.ALL, true, false).withDescription('Enable/disable the LED at night'),
548
549
  light_brightness: () => new Light().withBrightness(),
package/lib/tuya.js CHANGED
@@ -314,6 +314,12 @@ const dataPoints = {
314
314
  neoHumidityAlarm: 114,
315
315
  neoUnknown3: 115,
316
316
  neoVolume: 116,
317
+ // Neo AlarmOnly
318
+ neoAOBattPerc: 15,
319
+ neoAOMelody: 21,
320
+ neoAODuration: 7,
321
+ neoAOAlarm: 13,
322
+ neoAOVolume: 5,
317
323
  // Saswell TRV
318
324
  saswellHeating: 3,
319
325
  saswellWindowDetection: 8,
@@ -537,6 +543,7 @@ const dataPoints = {
537
543
  // TUYA / HUMIDITY/ILLUMINANCE/TEMPERATURE SENSOR
538
544
  thitBatteryPercentage: 3,
539
545
  thitIlluminanceLux: 7,
546
+ tIlluminanceLux: 2,
540
547
  thitHumidity: 9,
541
548
  thitTemperature: 8,
542
549
  // TUYA SMART VIBRATION SENSOR
@@ -564,6 +571,10 @@ const dataPoints = {
564
571
  AM02Border: 16,
565
572
  AM02MotorWorkingMode: 20,
566
573
  AM02AddRemoter: 101,
574
+ // Matsee Tuya Garage Door Opener
575
+ garageDoorTrigger: 1,
576
+ garageDoorContact: 3,
577
+ garageDoorStatus: 12,
567
578
  };
568
579
 
569
580
  const thermostatWeekFormat = {
@@ -643,6 +654,11 @@ const tuyaRadar = {
643
654
  1: 'moving_forward',
644
655
  2: 'moving_backward',
645
656
  },
657
+ fallDown: {
658
+ 0: 'none',
659
+ 1: 'maybe_fall',
660
+ 2: 'fall',
661
+ },
646
662
  };
647
663
 
648
664
  // Motion sensor lookups
package/lib/utils.js CHANGED
@@ -72,12 +72,12 @@ function hasAlreadyProcessedMessage(msg, ID=null, key=null) {
72
72
  return false;
73
73
  }
74
74
 
75
- const defaultPrecision = {temperature: 2, humidity: 2, pressure: 1, pm25: 0};
75
+ const defaultPrecision = {temperature: 2, humidity: 2, pressure: 1, pm25: 0, power: 2, voltage: 2, current: 2};
76
76
  function calibrateAndPrecisionRoundOptions(number, options, type) {
77
77
  // Calibrate
78
78
  const calibrateKey = `${type}_calibration`;
79
79
  let calibrationOffset = options && options.hasOwnProperty(calibrateKey) ? options[calibrateKey] : 0;
80
- if (type == 'illuminance' || type === 'illuminance_lux') {
80
+ if (['illuminance', 'illuminance_lux', 'power', 'current', 'voltage'].includes(type)) {
81
81
  // linear calibration because measured value is zero based
82
82
  // +/- percent
83
83
  calibrationOffset = Math.round(number * calibrationOffset / 100);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.390",
3
+ "version": "14.0.394",
4
4
  "lockfileVersion": 1,
5
5
  "requires": true,
6
6
  "dependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.390",
3
+ "version": "14.0.394",
4
4
  "description": "Collection of device converters to be used with zigbee-herdsman",
5
5
  "main": "index.js",
6
6
  "files": [