zigbee-herdsman-converters 14.0.413 → 14.0.417

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.
@@ -423,9 +423,12 @@ const converters = {
423
423
  // This is for occupancy sensor that send motion start AND stop messages
424
424
  cluster: 'msOccupancySensing',
425
425
  type: ['attributeReport', 'readResponse'],
426
+ options: [exposes.options.no_occupancy_since()],
426
427
  convert: (model, msg, publish, options, meta) => {
427
428
  if (msg.data.hasOwnProperty('occupancy')) {
428
- return {occupancy: (msg.data.occupancy % 2) > 0};
429
+ const payload = {occupancy: (msg.data.occupancy % 2) > 0};
430
+ utils.noOccupancySince(msg.endpoint, payload, options, publish);
431
+ return payload;
429
432
  }
430
433
  },
431
434
  },
@@ -449,32 +452,19 @@ const converters = {
449
452
  options.occupancy_timeout : 90;
450
453
 
451
454
  // Stop existing timers because motion is detected and set a new one.
452
- globalStore.getValue(msg.endpoint, 'timers', []).forEach((t) => clearTimeout(t));
453
- globalStore.putValue(msg.endpoint, 'timers', []);
455
+ clearTimeout(globalStore.getValue(msg.endpoint, 'occupancy_timer', null));
454
456
 
455
457
  if (timeout !== 0) {
456
458
  const timer = setTimeout(() => {
457
459
  publish({occupancy: false});
458
460
  }, timeout * 1000);
459
461
 
460
- globalStore.getValue(msg.endpoint, 'timers').push(timer);
462
+ globalStore.putValue(msg.endpoint, 'occupancy_timer', timer);
461
463
  }
462
464
 
463
- // No occupancy since
464
- if (options && options.no_occupancy_since) {
465
- options.no_occupancy_since.forEach((since) => {
466
- const timer = setTimeout(() => {
467
- publish({no_occupancy_since: since});
468
- }, since * 1000);
469
- globalStore.getValue(msg.endpoint, 'timers').push(timer);
470
- });
471
- }
472
-
473
- if (options && options.no_occupancy_since) {
474
- return {occupancy: true, no_occupancy_since: 0};
475
- } else {
476
- return {occupancy: true};
477
- }
465
+ const payload = {occupancy: true};
466
+ utils.noOccupancySince(msg.endpoint, payload, options, publish);
467
+ return payload;
478
468
  },
479
469
  },
480
470
  occupancy_timeout: {
@@ -5362,7 +5352,7 @@ const converters = {
5362
5352
  payload.voltage = value;
5363
5353
  payload.battery = batteryVoltageToPercentage(value, '3V_2100');
5364
5354
  } else if (index === 3) {
5365
- if (!['WXCJKG11LM ', 'WXCJKG12LM', 'WXCJKG13LM'].includes(model.model)) {
5355
+ if (!['WXCJKG11LM', 'WXCJKG12LM', 'WXCJKG13LM'].includes(model.model)) {
5366
5356
  payload.temperature = calibrateAndPrecisionRoundOptions(value, options, 'temperature'); // 0x03
5367
5357
  }
5368
5358
  } else if (index === 5) {
@@ -5373,7 +5363,7 @@ const converters = {
5373
5363
  payload[`state_${mapping}`] = value === 1 ? 'ON' : 'OFF';
5374
5364
  } else if (['WXKG14LM', 'WXKG16LM', 'WXKG17LM'].includes(model.model)) {
5375
5365
  payload.click_mode = {1: 'fast', 2: 'multi'}[value];
5376
- } else if (['WXCJKG11LM ', 'WXCJKG12LM', 'WXCJKG13LM'].includes(model.model)) {
5366
+ } else if (['WXCJKG11LM', 'WXCJKG12LM', 'WXCJKG13LM'].includes(model.model)) {
5377
5367
  // We don't know what the value means for these devices.
5378
5368
  // https://github.com/Koenkk/zigbee2mqtt/issues/11126
5379
5369
  } else {
@@ -8335,79 +8325,89 @@ const converters = {
8335
8325
  return {action};
8336
8326
  },
8337
8327
  },
8338
- ZMAM02: {
8328
+ ZMAM02_cover: {
8339
8329
  cluster: 'manuSpecificTuya',
8340
- type: ['commandDataResponse', 'commandDataReport', 'commandSetDataresponse'],
8330
+ type: ['commandDataReport', 'commandDataResponse'],
8331
+ options: [exposes.options.invert_cover()],
8341
8332
  convert: (model, msg, publish, options, meta) => {
8342
- const result = {};
8343
- // let value = tuya.getDataValue(dpValue);
8344
- // let result = null;
8345
- for (const dpValue of msg.data.dpValues) {
8346
- const value = tuya.getDataValue(dpValue);
8347
- switch (dpValue.dp) {
8348
- case tuya.dataPoints.AM02Control:
8349
- result.control = tuya.ZMAM02.AM02Control[value];
8350
- break;
8351
- case tuya.dataPoints.AM02PercentControl:
8352
- result.percent_control = value;
8333
+ const dpValue = tuya.firstDpValue(msg, meta, 'ZMAM02_cover');
8334
+ const dp = dpValue.dp;
8335
+ const value = tuya.getDataValue(dpValue);
8336
+ switch (dp) {
8337
+ case tuya.dataPoints.coverPosition: // Started moving to position (triggered from Zigbee)
8338
+ case tuya.dataPoints.coverArrived: { // Arrived at position
8339
+ const running = dp === tuya.dataPoints.coverArrived ? false : true;
8340
+ const invert = tuya.isCoverInverted(meta.device.manufacturerName) ? !options.invert_cover : options.invert_cover;
8341
+ const position = invert ? 100 - (value & 0xFF) : (value & 0xFF);
8342
+ if (position > 0 && position <= 100) {
8343
+ return {running, position, state: 'OPEN'};
8344
+ } else if (position == 0) { // Report fully closed
8345
+ return {running, position, state: 'CLOSE'};
8346
+ } else {
8347
+ return {running}; // Not calibrated yet, no position is available
8348
+ }
8349
+ }
8350
+ case tuya.dataPoints.coverSpeed: // Cover is reporting its current speed setting
8351
+ return {motor_speed: value};
8352
+ case tuya.dataPoints.state: // Ignore the cover state, it's not reliable between different covers!
8353
+ case tuya.dataPoints.coverChange: // Ignore manual cover change, it's not reliable between different covers!
8354
+ break;
8355
+ case tuya.dataPoints.config: // Returned by configuration set; ignore
8356
+ break;
8357
+ case tuya.dataPoints.AM02MotorWorkingMode:
8358
+ switch (value) {
8359
+ case 0: // continuous 1
8360
+ return {motor_working_mode: 'continuous'};
8361
+ case 1: // intermittently
8362
+ return {motor_working_mode: 'intermittently'};
8363
+ default:
8364
+ meta.logger.warn('ZMAM02: ' +
8365
+ `Mode ${value} is not recognized.`);
8353
8366
  break;
8354
- case tuya.dataPoints.AM02ControlBackMode:
8355
- result.control_back_mode = tuya.ZMAM02.AM02Direction[value];
8367
+ }
8368
+ break;
8369
+ case tuya.dataPoints.AM02Border:
8370
+ switch (value) {
8371
+ case 0: // up
8372
+ return {border: 'up'};
8373
+ case 1: // down
8374
+ return {border: 'down'};
8375
+ case 2: // down_delete
8376
+ return {border: 'down_delete'};
8377
+ default:
8378
+ meta.logger.warn('zigbee-herdsman-converters:ZM_AM_02: ' +
8379
+ `Mode ${value} is not recognized.`);
8356
8380
  break;
8357
- case tuya.dataPoints.AM02MotorWorkingMode:
8358
- switch (value) {
8359
- case 0: // continuous 1
8360
- result.motor_working_mode = 'continuous';
8361
- break;
8362
- case 1: // intermittently
8363
- result.motor_working_mode = 'intermittently';
8364
- break;
8365
- default:
8366
- meta.logger.warn('zigbee-herdsman-converters:ZM_AM_02: ' +
8367
- `Mode ${value} is not recognized.`);
8368
- break;
8369
- }
8381
+ }
8382
+ break;
8383
+ case tuya.dataPoints.AM02Direction:
8384
+ switch (value) {
8385
+ case 0:
8386
+ return {motor_direction: 'forward'};
8387
+ case 1:
8388
+ return {motor_direction: 'back'};
8389
+ default:
8390
+ meta.logger.warn('ZMAM02: ' +
8391
+ `Mode ${value} is not recognized.`);
8370
8392
  break;
8371
- case tuya.dataPoints.AM02Border:
8372
- switch (value) {
8373
- case 0: // up
8374
- result.border = 'up';
8375
- break;
8376
- case 1: // down
8377
- result.border = 'down';
8378
- break;
8379
- case 2: // down_delete
8380
- result.border = 'down_delete';
8381
- break;
8382
- default:
8383
- meta.logger.warn('zigbee-herdsman-converters:ZM_AM_02: ' +
8393
+ }
8394
+ break;
8395
+ case tuya.dataPoints.AM02Mode:
8396
+ switch (value) {
8397
+ case 0: // morning
8398
+ return {mode: 'morning'};
8399
+ case 1: // night
8400
+ return {mode: 'night'};
8401
+ default:
8402
+ meta.logger.warn('zigbee-herdsman-converters:ZM_AM_02: ' +
8384
8403
  `Mode ${value} is not recognized.`);
8385
- break;
8386
- }
8387
- break;
8388
- case tuya.dataPoints.AM02PercentState:
8389
- result.percent_state = value;
8390
8404
  break;
8391
- case tuya.dataPoints.AM02Mode:
8392
- switch (value) {
8393
- case 0: // morning
8394
- result.mode = 'morning';
8395
- break;
8396
- case 1: // night
8397
- result.mode = 'night';
8398
- break;
8399
- default:
8400
- meta.logger.warn('zigbee-herdsman-converters:ZM_AM_02: ' +
8401
- `Mode ${value} is not recognized.`);
8402
- break;
8403
- }
8404
- break;
8405
- default:
8406
- meta.logger.warn(`fromZigbee.Zemismart Shader Konverter (Zm_AM02): NOT RECOGNIZED ` +
8407
- `DP #${dpValue.dp} with data ${JSON.stringify(dpValue)}`);
8408
8405
  }
8406
+ break;
8407
+ default: // Unknown code
8408
+ meta.logger.warn(`ZMAM02_cover: Unhandled DP #${dp} for ${meta.device.manufacturerName}:
8409
+ ${JSON.stringify(dpValue)}`);
8409
8410
  }
8410
- return result;
8411
8411
  },
8412
8412
  },
8413
8413
  // #endregion
@@ -6924,30 +6924,56 @@ const converters = {
6924
6924
  }
6925
6925
  },
6926
6926
  },
6927
- ZMAM02: {
6928
- key: ['control', 'percent_control', 'mode', 'control_back_mode', 'border', 'motor_working_mode'],
6927
+ ZMAM02_cover: {
6928
+ key: ['state', 'position', 'mode', 'motor_direction', 'border', 'motor_working_mode'],
6929
+ options: [exposes.options.invert_cover()],
6929
6930
  convertSet: async (entity, key, value, meta) => {
6931
+ if (key === 'position') {
6932
+ if (value >= 0 && value <= 100) {
6933
+ const invert = tuya.isCoverInverted(meta.device.manufacturerName) ?
6934
+ !meta.options.invert_cover : meta.options.invert_cover;
6935
+
6936
+ value = invert ? 100 - value : value;
6937
+ await tuya.sendDataPointValue(entity, tuya.dataPoints.coverPosition, value);
6938
+ } else {
6939
+ throw new Error('TuYa_cover_control: Curtain motor position is out of range');
6940
+ }
6941
+ } else if (key === 'state') {
6942
+ const stateEnums = tuya.getCoverStateEnums(meta.device.manufacturerName);
6943
+ meta.logger.debug(`ZMAM02: Using state enums for ${meta.device.manufacturerName}:
6944
+ ${JSON.stringify(stateEnums)}`);
6945
+ value = value.toLowerCase();
6946
+ switch (value) {
6947
+ case 'close':
6948
+ await tuya.sendDataPointEnum(entity, tuya.dataPoints.AM02Control, stateEnums.close);
6949
+ break;
6950
+ case 'open':
6951
+ await tuya.sendDataPointEnum(entity, tuya.dataPoints.AM02Control, stateEnums.open);
6952
+ break;
6953
+ case 'stop':
6954
+ await tuya.sendDataPointEnum(entity, tuya.dataPoints.AM02Control, stateEnums.stop);
6955
+ break;
6956
+ default:
6957
+ throw new Error('ZMAM02: Invalid command received');
6958
+ }
6959
+ }
6930
6960
  switch (key) {
6931
- case 'control':
6932
- await tuya.sendDataPointEnum(entity, tuya.dataPoints.AM02Control, utils.getKey(tuya.ZMAM02.AM02Control, value));
6933
- break;
6934
- case 'percent_control':
6935
- await tuya.sendDataPointValue(entity, tuya.dataPoints.AM02PercentState, value);
6936
- break;
6937
6961
  case 'mode':
6938
- await tuya.sendDataPointEnum(entity, tuya.dataPoints.AM02Mode, utils.getKey(tuya.ZMAM02.AM02Mode, value));
6962
+ await tuya.sendDataPointEnum(entity, tuya.dataPoints.AM02Mode, utils.getKey(tuya.ZMLookups.AM02Mode, value));
6939
6963
  break;
6940
- case 'control_back_mode':
6941
- await tuya.sendDataPointEnum(entity, tuya.dataPoints.AM02ControlBackMode, utils.getKey(tuya.ZMAM02.AM02Direction, value));
6964
+ case 'motor_direction':
6965
+ await tuya.sendDataPointEnum(entity, tuya.dataPoints.AM02Direction, utils.getKey(tuya.ZMLookups.AM02Direction, value));
6942
6966
  break;
6943
6967
  case 'border':
6944
- await tuya.sendDataPointEnum(entity, tuya.dataPoints.AM02Border, utils.getKey(tuya.ZMAM02.AM02Border, value));
6968
+ await tuya.sendDataPointEnum(entity, tuya.dataPoints.AM02Border, utils.getKey(tuya.ZMLookups.AM02Border, value));
6945
6969
  break;
6946
6970
  case 'motor_working_mode':
6947
- await tuya.sendDataPointEnum(entity, tuya.dataPoints.AM02MotorWorkingMode, utils.getKey(tuya.ZMAM02.AM02MotorMode, value));
6971
+ await tuya.sendDataPointEnum(
6972
+ entity,
6973
+ tuya.dataPoints.AM02MotorWorkingMode,
6974
+ utils.getKey(tuya.ZMLookups.AM02MotorWorkingMode,
6975
+ value));
6948
6976
  break;
6949
- default: // Unknown Key
6950
- meta.logger.warn(`toZigbee.ZMAM02: Unhandled Key ${key}`);
6951
6977
  }
6952
6978
  },
6953
6979
  },
package/devices/adeo.js CHANGED
@@ -6,6 +6,13 @@ const tz = require('../converters/toZigbee');
6
6
  const e = exposes.presets;
7
7
 
8
8
  module.exports = [
9
+ {
10
+ zigbeeModel: ['ZBEK-12'],
11
+ model: 'IA-CDZFB2AA007NA-MZN-01',
12
+ vendor: 'ADEO',
13
+ description: 'ENKI LEXMAN E27 LED white',
14
+ extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
15
+ },
9
16
  {
10
17
  zigbeeModel: ['LDSENK01F'],
11
18
  model: 'LDSENK01F',
@@ -396,4 +396,23 @@ module.exports = [
396
396
  },
397
397
  exposes: [e.soil_moisture(), e.battery(), e.illuminance(), e.temperature(), e.humidity()],
398
398
  },
399
+ {
400
+ zigbeeModel: ['EFEKTA_eTH102'],
401
+ model: 'EFEKTA_eTH102',
402
+ vendor: 'Custom devices (DiY)',
403
+ description: '[Mini digital thermometer & hygrometer with e-ink1.02](http://efektalab.com/eTH102)',
404
+ fromZigbee: [fz.temperature, fz.humidity, fz.battery],
405
+ toZigbee: [tz.factory_reset],
406
+ configure: async (device, coordinatorEndpoint, logger) => {
407
+ const endpoint = device.getEndpoint(1);
408
+ await reporting.bind(endpoint, coordinatorEndpoint, [
409
+ 'genPowerCfg', 'msTemperatureMeasurement', 'msRelativeHumidity']);
410
+ const overides = {min: 0, max: 21600, change: 0};
411
+ await reporting.batteryVoltage(endpoint, overides);
412
+ await reporting.batteryPercentageRemaining(endpoint, overides);
413
+ await reporting.temperature(endpoint, overides);
414
+ await reporting.humidity(endpoint, overides);
415
+ },
416
+ exposes: [e.battery(), e.temperature(), e.humidity()],
417
+ },
399
418
  ];
@@ -39,7 +39,8 @@ module.exports = [
39
39
  description: 'Power plug',
40
40
  fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering, fz.device_temperature],
41
41
  toZigbee: [tz.on_off],
42
- exposes: [e.switch(), e.power(), e.current(), e.voltage(), e.energy(), e.device_temperature()],
42
+ exposes: [e.switch(), e.power(), e.current(), e.voltage(), e.energy(), e.device_temperature(), e.ac_frequency()],
43
+ options: [exposes.options.precision(`ac_frequency`)],
43
44
  configure: async (device, coordinatorEndpoint, logger) => {
44
45
  const endpoint = device.getEndpoint(2);
45
46
  await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering', 'genDeviceTempCfg']);
@@ -52,6 +53,7 @@ module.exports = [
52
53
  await reporting.readMeteringMultiplierDivisor(endpoint);
53
54
  await reporting.currentSummDelivered(endpoint, {change: [0, 20]}); // Limit reports to once every 5m, or 0.02kWh
54
55
  await reporting.instantaneousDemand(endpoint, {min: constants.repInterval.MINUTES_5, change: 10});
56
+ await reporting.acFrequency(endpoint);
55
57
  },
56
58
  endpoint: (device) => {
57
59
  return {default: 2};
package/devices/ecodim.js CHANGED
@@ -40,7 +40,7 @@ module.exports = [
40
40
  ]},
41
41
  ],
42
42
  zigbeeModel: ['Dimmer-Switch-ZB3.0'],
43
- model: 'Eco-Dim.07',
43
+ model: 'Eco-Dim.07/Eco-Dim.10',
44
44
  vendor: 'EcoDim',
45
45
  description: 'Zigbee & Z-wave dimmer',
46
46
  extend: extend.light_onoff_brightness({noConfigure: true, disableEffect: true}),
@@ -6,7 +6,8 @@ const ea = exposes.access;
6
6
 
7
7
  module.exports = [
8
8
  {
9
- fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_wt9agwf3'}],
9
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_wt9agwf3'},
10
+ {modelID: 'TS0601', manufacturerName: '_TZE200_5uodvhgc'}],
10
11
  model: 'FK_V02',
11
12
  vendor: 'FrankEver',
12
13
  description: 'Zigbee smart water valve',
@@ -267,6 +267,7 @@ module.exports = [
267
267
  vendor: 'Gledopto',
268
268
  ota: ota.zigbeeOTA,
269
269
  description: 'Zigbee LED Controller RGB+CCT (pro)',
270
+ whiteLabel: [{vendor: 'Gledopto', model: 'GL-C-001P'}],
270
271
  extend: gledoptoExtend.light_onoff_brightness_colortemp_color({colorTempRange: [158, 495], noConfigure: true}),
271
272
  meta: {disableDefaultResponse: true},
272
273
  configure: async (device, coordinatorEndpoint, logger) => {
@@ -568,6 +569,14 @@ module.exports = [
568
569
  description: 'Zigbee 10W Floodlight RGB+CCT (pro)',
569
570
  extend: gledoptoExtend.light_onoff_brightness_colortemp_color(),
570
571
  },
572
+ {
573
+ zigbeeModel: ['GL-FL-001P'],
574
+ model: 'GL-FL-001P',
575
+ vendor: 'Gledopto',
576
+ ota: ota.zigbeeOTA,
577
+ description: 'Zigbee 10W Floodlight RGB+CCT 12V Low Voltage (pro)',
578
+ extend: gledoptoExtend.light_onoff_brightness_colortemp_color({colorTempRange: [158, 495]}),
579
+ },
571
580
  {
572
581
  zigbeeModel: ['GL-FL-005TZ'],
573
582
  model: 'GL-FL-005TZ',
package/devices/heiman.js CHANGED
@@ -398,7 +398,7 @@ module.exports = [
398
398
  exposes: [e.temperature(), e.humidity(), e.battery()],
399
399
  },
400
400
  {
401
- fingerprint: [{modelID: 'SOS-EM', manufacturerName: 'HEIMAN'}],
401
+ fingerprint: [{modelID: 'SOS-EM', manufacturerName: 'HEIMAN'}, {modelID: 'SOS-EF-3.0', manufacturerName: 'HEIMAN'}],
402
402
  model: 'HS1EB/HS1EB-E',
403
403
  vendor: 'HEIMAN',
404
404
  description: 'Smart emergency button',
package/devices/lixee.js CHANGED
@@ -295,19 +295,19 @@ const clustersDef = {
295
295
  const exposedData = [
296
296
  // Historique
297
297
  {cluster: clustersDef._0x0702, att: 'meterSerialNumber', reportable: false, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.text('ADCO', ea.STATE).withProperty('meter_serial_number').withDescription('Serial Number')},
298
- {cluster: clustersDef._0x0702, att: 'currentSummDelivered', reportable: true, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('BASE', ea.STATE).withUnit('kWh').withProperty('current_summ_delivered').withDescription('Base index')},
298
+ {cluster: clustersDef._0x0702, att: 'currentSummDelivered', reportable: true, report: {change: 100}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('BASE', ea.STATE).withUnit('kWh').withProperty('current_summ_delivered').withDescription('Base index')},
299
299
  {cluster: clustersDef._0xFF66, att: 'currentTarif', reportable: false, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.text('OPTARIF', ea.STATE).withProperty('current_tarif').withDescription('Tarif option')},
300
300
  {cluster: clustersDef._0x0B01, att: 'availablePower', reportable: false, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('ISOUSC', ea.STATE).withUnit('A').withProperty('available_power').withDescription('Subscribed intensity level')},
301
- {cluster: clustersDef._0x0702, att: 'currentTier1SummDelivered', reportable: false, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('HCHC', ea.STATE).withUnit('kWh').withProperty('current_tier1_summ_delivered').withDescription('HCHC index')},
302
- {cluster: clustersDef._0x0702, att: 'currentTier2SummDelivered', reportable: false, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('HCHP', ea.STATE).withUnit('kWh').withProperty('current_tier2_summ_delivered').withDescription('HCHP index')},
303
- {cluster: clustersDef._0x0702, att: 'currentTier1SummDelivered', reportable: false, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('EJPHN', ea.STATE).withUnit('kWh').withProperty('current_tier1_summ_delivered').withDescription('EJPHN index')},
304
- {cluster: clustersDef._0x0702, att: 'currentTier2SummDelivered', reportable: false, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('EJPHPM', ea.STATE).withUnit('kWh').withProperty('current_tier2_summ_delivered').withDescription('EJPHPM index')},
305
- {cluster: clustersDef._0x0702, att: 'currentTier1SummDelivered', reportable: false, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('BBRHCJB', ea.STATE).withUnit('kWh').withProperty('current_tier1_summ_delivered').withDescription('BBRHCJB index')},
306
- {cluster: clustersDef._0x0702, att: 'currentTier2SummDelivered', reportable: false, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('BBRHPJB', ea.STATE).withUnit('kWh').withProperty('current_tier2_summ_delivered').withDescription('BBRHPJB index')},
307
- {cluster: clustersDef._0x0702, att: 'currentTier3SummDelivered', reportable: false, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('BBRHCJW', ea.STATE).withUnit('kWh').withProperty('current_tier3_summ_delivered').withDescription('BBRHCJW index')},
308
- {cluster: clustersDef._0x0702, att: 'currentTier4SummDelivered', reportable: false, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('BBRHPJW', ea.STATE).withUnit('kWh').withProperty('current_tier4_summ_delivered').withDescription('BBRHPJW index')},
309
- {cluster: clustersDef._0x0702, att: 'currentTier5SummDelivered', reportable: false, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('BBRHCJR', ea.STATE).withUnit('kWh').withProperty('current_tier5_summ_delivered').withDescription('BBRHCJR index')},
310
- {cluster: clustersDef._0x0702, att: 'currentTier6SummDelivered', reportable: false, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('BBRHPJR', ea.STATE).withUnit('kWh').withProperty('current_tier6_summ_delivered').withDescription('BBRHPJR index')},
301
+ {cluster: clustersDef._0x0702, att: 'currentTier1SummDelivered', reportable: false, report: {change: 100, min: 60}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('HCHC', ea.STATE).withUnit('kWh').withProperty('current_tier1_summ_delivered').withDescription('HCHC index')},
302
+ {cluster: clustersDef._0x0702, att: 'currentTier2SummDelivered', reportable: false, report: {change: 100, min: 60}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('HCHP', ea.STATE).withUnit('kWh').withProperty('current_tier2_summ_delivered').withDescription('HCHP index')},
303
+ {cluster: clustersDef._0x0702, att: 'currentTier1SummDelivered', reportable: false, report: {change: 100, min: 60}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('EJPHN', ea.STATE).withUnit('kWh').withProperty('current_tier1_summ_delivered').withDescription('EJPHN index')},
304
+ {cluster: clustersDef._0x0702, att: 'currentTier2SummDelivered', reportable: false, report: {change: 100, min: 60}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('EJPHPM', ea.STATE).withUnit('kWh').withProperty('current_tier2_summ_delivered').withDescription('EJPHPM index')},
305
+ {cluster: clustersDef._0x0702, att: 'currentTier1SummDelivered', reportable: false, report: {change: 100, min: 60}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('BBRHCJB', ea.STATE).withUnit('kWh').withProperty('current_tier1_summ_delivered').withDescription('BBRHCJB index')},
306
+ {cluster: clustersDef._0x0702, att: 'currentTier2SummDelivered', reportable: false, report: {change: 100, min: 60}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('BBRHPJB', ea.STATE).withUnit('kWh').withProperty('current_tier2_summ_delivered').withDescription('BBRHPJB index')},
307
+ {cluster: clustersDef._0x0702, att: 'currentTier3SummDelivered', reportable: false, report: {change: 100, min: 60}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('BBRHCJW', ea.STATE).withUnit('kWh').withProperty('current_tier3_summ_delivered').withDescription('BBRHCJW index')},
308
+ {cluster: clustersDef._0x0702, att: 'currentTier4SummDelivered', reportable: false, report: {change: 100, min: 60}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('BBRHPJW', ea.STATE).withUnit('kWh').withProperty('current_tier4_summ_delivered').withDescription('BBRHPJW index')},
309
+ {cluster: clustersDef._0x0702, att: 'currentTier5SummDelivered', reportable: false, report: {change: 100, min: 60}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('BBRHCJR', ea.STATE).withUnit('kWh').withProperty('current_tier5_summ_delivered').withDescription('BBRHCJR index')},
310
+ {cluster: clustersDef._0x0702, att: 'currentTier6SummDelivered', reportable: false, report: {change: 100, min: 60}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('BBRHPJR', ea.STATE).withUnit('kWh').withProperty('current_tier6_summ_delivered').withDescription('BBRHPJR index')},
311
311
  {cluster: clustersDef._0x0B04, att: 'rmsCurrent', reportable: true, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('IINST', ea.STATE).withUnit('A').withProperty('rms_current').withDescription('RMS current')},
312
312
  {cluster: clustersDef._0x0B04, att: 'rmsCurrent', reportable: true, onlyProducer: false, linkyPhase: linkyPhaseDef.three, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('IINST1', ea.STATE).withUnit('A').withProperty('rms_current').withDescription('RMS current (phase 1)')},
313
313
  {cluster: clustersDef._0x0B04, att: 'rmsCurrentPhB', reportable: true, onlyProducer: false, linkyPhase: linkyPhaseDef.three, linkyMode: linkyModeDef.legacy, exposes: exposes.numeric('IINST2', ea.STATE).withUnit('A').withProperty('rms_current_ph_b').withDescription('RMS current (phase 2)')},
@@ -333,22 +333,22 @@ const exposedData = [
333
333
  {cluster: clustersDef._0xFF66, att: 'currentIndexTarif', reportable: false, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('NTARF', ea.STATE).withProperty('current_index_tarif').withDescription('Current tariff index number')},
334
334
  {cluster: clustersDef._0x0B01, att: 'softwareRevision', reportable: false, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('VTIC', ea.STATE).withProperty('software_revision').withDescription('Customer tele-information protocol version')},
335
335
  {cluster: clustersDef._0xFF66, att: 'currentDate', reportable: false, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.text('DATE', ea.STATE).withProperty('current_date').withDescription('Current date and time')},
336
- {cluster: clustersDef._0x0702, att: 'currentSummDelivered', reportable: true, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EAST', ea.STATE).withUnit('kWh').withProperty('current_summ_delivered').withDescription('Total active power delivered')},
337
- {cluster: clustersDef._0x0702, att: 'currentTier1SummDelivered', reportable: true, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASF01', ea.STATE).withUnit('kWh').withProperty('current_tier1_summ_delivered').withDescription('Total provider active power delivered (index 01)')},
338
- {cluster: clustersDef._0x0702, att: 'currentTier2SummDelivered', reportable: true, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASF02', ea.STATE).withUnit('kWh').withProperty('current_tier2_summ_delivered').withDescription('Total provider active power delivered (index 02)')},
339
- {cluster: clustersDef._0x0702, att: 'currentTier3SummDelivered', reportable: true, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASF03', ea.STATE).withUnit('kWh').withProperty('current_tier3_summ_delivered').withDescription('Total provider active power delivered (index 03)')},
340
- {cluster: clustersDef._0x0702, att: 'currentTier4SummDelivered', reportable: false, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASF04', ea.STATE).withUnit('kWh').withProperty('current_tier4_summ_delivered').withDescription('Total provider active power delivered (index 04)')},
341
- {cluster: clustersDef._0x0702, att: 'currentTier5SummDelivered', reportable: false, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASF05', ea.STATE).withUnit('kWh').withProperty('current_tier5_summ_delivered').withDescription('Total provider active power delivered (index 05)')},
342
- {cluster: clustersDef._0x0702, att: 'currentTier6SummDelivered', reportable: false, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASF06', ea.STATE).withUnit('kWh').withProperty('current_tier6_summ_delivered').withDescription('Total provider active power delivered (index 06)')},
343
- {cluster: clustersDef._0x0702, att: 'currentTier7SummDelivered', reportable: false, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASF07', ea.STATE).withUnit('kWh').withProperty('current_tier7_summ_delivered').withDescription('Total provider active power delivered (index 07)')},
344
- {cluster: clustersDef._0x0702, att: 'currentTier8SummDelivered', reportable: false, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASF08', ea.STATE).withUnit('kWh').withProperty('current_tier8_summ_delivered').withDescription('Total provider active power delivered (index 08)')},
345
- {cluster: clustersDef._0x0702, att: 'currentTier9SummDelivered', reportable: false, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASF09', ea.STATE).withUnit('kWh').withProperty('current_tier9_summ_delivered').withDescription('Total provider active power delivered (index 09)')},
346
- {cluster: clustersDef._0x0702, att: 'currentTier10SummDelivered', reportable: false, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASF10', ea.STATE).withUnit('kWh').withProperty('current_tier10_summ_delivered').withDescription('Total provider active power delivered (index 10)')},
347
- {cluster: clustersDef._0xFF66, att: 'activeEnerfyOutD01', reportable: true, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASD01', ea.STATE).withUnit('kWh').withProperty('active_enerfy_out_d01').withDescription('Active energy withdrawn Distributor (index 01)')},
348
- {cluster: clustersDef._0xFF66, att: 'activeEnerfyOutD02', reportable: false, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASD02', ea.STATE).withUnit('kWh').withProperty('active_enerfy_out_d02').withDescription('Active energy withdrawn Distributor (index 02)')},
349
- {cluster: clustersDef._0xFF66, att: 'activeEnerfyOutD03', reportable: false, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASD03', ea.STATE).withUnit('kWh').withProperty('active_enerfy_out_d03').withDescription('Active energy withdrawn Distributor (index 03)')},
350
- {cluster: clustersDef._0xFF66, att: 'activeEnerfyOutD04', reportable: false, reportChange: 100, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASD04', ea.STATE).withUnit('kWh').withProperty('active_enerfy_out_d04').withDescription('Active energy withdrawn Distributor (index 04)')},
351
- {cluster: clustersDef._0x0702, att: 'currentSummReceived', reportable: true, reportChange: 100, onlyProducer: true, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EAIT', ea.STATE).withUnit('kWh').withProperty('current_summ_received').withDescription('Total active power injected')},
336
+ {cluster: clustersDef._0x0702, att: 'currentSummDelivered', reportable: true, report: {change: 100}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EAST', ea.STATE).withUnit('kWh').withProperty('current_summ_delivered').withDescription('Total active power delivered')},
337
+ {cluster: clustersDef._0x0702, att: 'currentTier1SummDelivered', reportable: true, report: {change: 100, min: 60}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASF01', ea.STATE).withUnit('kWh').withProperty('current_tier1_summ_delivered').withDescription('Total provider active power delivered (index 01)')},
338
+ {cluster: clustersDef._0x0702, att: 'currentTier2SummDelivered', reportable: true, report: {change: 100, min: 60}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASF02', ea.STATE).withUnit('kWh').withProperty('current_tier2_summ_delivered').withDescription('Total provider active power delivered (index 02)')},
339
+ {cluster: clustersDef._0x0702, att: 'currentTier3SummDelivered', reportable: true, report: {change: 100, min: 60}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASF03', ea.STATE).withUnit('kWh').withProperty('current_tier3_summ_delivered').withDescription('Total provider active power delivered (index 03)')},
340
+ {cluster: clustersDef._0x0702, att: 'currentTier4SummDelivered', reportable: false, report: {change: 100, min: 60}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASF04', ea.STATE).withUnit('kWh').withProperty('current_tier4_summ_delivered').withDescription('Total provider active power delivered (index 04)')},
341
+ {cluster: clustersDef._0x0702, att: 'currentTier5SummDelivered', reportable: false, report: {change: 100, min: 60}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASF05', ea.STATE).withUnit('kWh').withProperty('current_tier5_summ_delivered').withDescription('Total provider active power delivered (index 05)')},
342
+ {cluster: clustersDef._0x0702, att: 'currentTier6SummDelivered', reportable: false, report: {change: 100, min: 60}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASF06', ea.STATE).withUnit('kWh').withProperty('current_tier6_summ_delivered').withDescription('Total provider active power delivered (index 06)')},
343
+ {cluster: clustersDef._0x0702, att: 'currentTier7SummDelivered', reportable: false, report: {change: 100, min: 60}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASF07', ea.STATE).withUnit('kWh').withProperty('current_tier7_summ_delivered').withDescription('Total provider active power delivered (index 07)')},
344
+ {cluster: clustersDef._0x0702, att: 'currentTier8SummDelivered', reportable: false, report: {change: 100, min: 60}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASF08', ea.STATE).withUnit('kWh').withProperty('current_tier8_summ_delivered').withDescription('Total provider active power delivered (index 08)')},
345
+ {cluster: clustersDef._0x0702, att: 'currentTier9SummDelivered', reportable: false, report: {change: 100, min: 60}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASF09', ea.STATE).withUnit('kWh').withProperty('current_tier9_summ_delivered').withDescription('Total provider active power delivered (index 09)')},
346
+ {cluster: clustersDef._0x0702, att: 'currentTier10SummDelivered', reportable: false, report: {change: 100, min: 60}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASF10', ea.STATE).withUnit('kWh').withProperty('current_tier10_summ_delivered').withDescription('Total provider active power delivered (index 10)')},
347
+ {cluster: clustersDef._0xFF66, att: 'activeEnerfyOutD01', reportable: true, report: {change: 100}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASD01', ea.STATE).withUnit('kWh').withProperty('active_enerfy_out_d01').withDescription('Active energy withdrawn Distributor (index 01)')},
348
+ {cluster: clustersDef._0xFF66, att: 'activeEnerfyOutD02', reportable: false, report: {change: 100}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASD02', ea.STATE).withUnit('kWh').withProperty('active_enerfy_out_d02').withDescription('Active energy withdrawn Distributor (index 02)')},
349
+ {cluster: clustersDef._0xFF66, att: 'activeEnerfyOutD03', reportable: false, report: {change: 100}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASD03', ea.STATE).withUnit('kWh').withProperty('active_enerfy_out_d03').withDescription('Active energy withdrawn Distributor (index 03)')},
350
+ {cluster: clustersDef._0xFF66, att: 'activeEnerfyOutD04', reportable: false, report: {change: 100}, onlyProducer: false, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EASD04', ea.STATE).withUnit('kWh').withProperty('active_enerfy_out_d04').withDescription('Active energy withdrawn Distributor (index 04)')},
351
+ {cluster: clustersDef._0x0702, att: 'currentSummReceived', reportable: true, report: {change: 100}, onlyProducer: true, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('EAIT', ea.STATE).withUnit('kWh').withProperty('current_summ_received').withDescription('Total active power injected')},
352
352
  {cluster: clustersDef._0x0B04, att: 'totalReactivePower', reportable: true, onlyProducer: true, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('ERQ1', ea.STATE).withUnit('VArh').withProperty('total_reactive_power').withDescription('Total reactive power (Q1)')},
353
353
  {cluster: clustersDef._0x0B04, att: 'reactivePower', reportable: true, onlyProducer: true, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('ERQ2', ea.STATE).withUnit('VArh').withProperty('reactive_power').withDescription('Total reactive power (Q2)')},
354
354
  {cluster: clustersDef._0x0B04, att: 'reactivePowerPhB', reportable: true, onlyProducer: true, linkyPhase: linkyPhaseDef.single, linkyMode: linkyModeDef.standard, exposes: exposes.numeric('ERQ3', ea.STATE).withUnit('VArh').withProperty('reactive_power_ph_b').withDescription('Total reactive power (Q3)')},
@@ -491,7 +491,12 @@ const definition = {
491
491
  // docs generation
492
492
  let exposes;
493
493
  if (device == null && options == null) {
494
- exposes = exposedData.map((e) => e.exposes);
494
+ exposes = exposedData.map((e) => e.exposes)
495
+ .filter((value, index, self) =>
496
+ index === self.findIndex((t) => (
497
+ t.property === value.property // Remove duplicates
498
+ )),
499
+ );
495
500
  } else {
496
501
  exposes = getCurrentConfig(device, options).map((e) => e.exposes);
497
502
  }
@@ -533,13 +538,19 @@ const definition = {
533
538
  });
534
539
 
535
540
  for (const e of suscribeNew) {
536
- let change = 1;
537
- if (e.hasOwnProperty('reportChange')) {
538
- change = e['reportChange'];
541
+ let params = {
542
+ att: e.att,
543
+ min: 0,
544
+ max: repInterval.MINUTES_15,
545
+ change: 1,
546
+ };
547
+ // Override reportings
548
+ if (e.hasOwnProperty('report')) {
549
+ params = {...params, ...e.report};
539
550
  }
540
551
  configReportings.push(endpoint
541
552
  .configureReporting(
542
- e.cluster, reporting.payload(e.att, 0, repInterval.MINUTES_15, change)),
553
+ e.cluster, reporting.payload(params.att, params.min, params.max, params.change)),
543
554
  );
544
555
  }
545
556
  (await Promise.allSettled(configReportings))
package/devices/moes.js CHANGED
@@ -119,9 +119,9 @@ module.exports = [
119
119
  vendor: 'Moes',
120
120
  description: 'Wall touch light switch (1 gang)',
121
121
  exposes: [e.switch().setAccess('state', ea.STATE_SET),
122
- exposes.enum('indicate_light', ea.STATE_SET, ['off', 'switch', 'position'])
122
+ exposes.enum('indicate_light', ea.STATE_SET, Object.values(tuya.moesSwitch.indicateLight))
123
123
  .withDescription('Indicator light status'),
124
- exposes.enum('power_on_behavior', ea.STATE_SET, ['off', 'on', 'previous'])
124
+ exposes.enum('power_on_behavior', ea.STATE_SET, Object.values(tuya.moesSwitch.powerOnBehavior))
125
125
  .withDescription('Controls the behavior when the device is powered on')],
126
126
  fromZigbee: [fz.tuya_switch, fz.moes_switch],
127
127
  toZigbee: [tz.tuya_switch_state, tz.moes_switch],
@@ -140,9 +140,9 @@ module.exports = [
140
140
  description: 'Wall touch light switch (2 gang)',
141
141
  exposes: [e.switch().withEndpoint('l1').setAccess('state', ea.STATE_SET),
142
142
  e.switch().withEndpoint('l2').setAccess('state', ea.STATE_SET),
143
- exposes.enum('indicate_light', ea.STATE_SET, ['off', 'switch', 'position'])
143
+ exposes.enum('indicate_light', ea.STATE_SET, Object.values(tuya.moesSwitch.indicateLight))
144
144
  .withDescription('Indicator light status'),
145
- exposes.enum('power_on_behavior', ea.STATE_SET, ['off', 'on', 'previous'])
145
+ exposes.enum('power_on_behavior', ea.STATE_SET, Object.values(tuya.moesSwitch.powerOnBehavior))
146
146
  .withDescription('Controls the behavior when the device is powered on')],
147
147
  fromZigbee: [fz.ignore_basic_report, fz.tuya_switch, fz.moes_switch],
148
148
  toZigbee: [tz.tuya_switch_state, tz.moes_switch],
@@ -168,9 +168,9 @@ module.exports = [
168
168
  exposes: [e.switch().withEndpoint('l1').setAccess('state', ea.STATE_SET),
169
169
  e.switch().withEndpoint('l2').setAccess('state', ea.STATE_SET),
170
170
  e.switch().withEndpoint('l3').setAccess('state', ea.STATE_SET),
171
- exposes.enum('indicate_light', ea.STATE_SET, ['off', 'switch', 'position'])
171
+ exposes.enum('indicate_light', ea.STATE_SET, Object.values(tuya.moesSwitch.indicateLight))
172
172
  .withDescription('Indicator light status'),
173
- exposes.enum('power_on_behavior', ea.STATE_SET, ['off', 'on', 'previous'])
173
+ exposes.enum('power_on_behavior', ea.STATE_SET, Object.values(tuya.moesSwitch.powerOnBehavior))
174
174
  .withDescription('Controls the behavior when the device is powered on')],
175
175
  fromZigbee: [fz.ignore_basic_report, fz.tuya_switch, fz.moes_switch],
176
176
  toZigbee: [tz.tuya_switch_state, tz.moes_switch],
@@ -90,7 +90,7 @@ module.exports = [
90
90
  },
91
91
  {
92
92
  zigbeeModel: ['500.45'],
93
- model: '798.15',
93
+ model: '500.45',
94
94
  vendor: 'Paulmann',
95
95
  description: 'SmartHome Zigbee Pendulum Light Aptare',
96
96
  extend: extend.light_onoff_brightness(),
@@ -45,6 +45,15 @@ module.exports = [
45
45
  extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
46
46
  ota: ota.zigbeeOTA,
47
47
  },
48
+ {
49
+ zigbeeModel: ['929003047401'],
50
+ model: '929003047401',
51
+ vendor: 'Philips',
52
+ description: 'Hue White and Color Ambiance GU10 (Centura)',
53
+ meta: {turnsOffAtBrightness1: true},
54
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
55
+ ota: ota.zigbeeOTA,
56
+ },
48
57
  {
49
58
  zigbeeModel: ['929003056901'],
50
59
  model: '929003056901',
@@ -1468,6 +1477,15 @@ module.exports = [
1468
1477
  extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 500]}),
1469
1478
  ota: ota.zigbeeOTA,
1470
1479
  },
1480
+ {
1481
+ zigbeeModel: ['929003054801'],
1482
+ model: '929003054801',
1483
+ vendor: 'Philips',
1484
+ description: 'Hue white ambiance suspension Amaze with Bluetooth',
1485
+ meta: {turnsOffAtBrightness1: true},
1486
+ extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
1487
+ ota: ota.zigbeeOTA,
1488
+ },
1471
1489
  {
1472
1490
  zigbeeModel: ['LWF001', 'LWF002', 'LWW001'],
1473
1491
  model: '9290011370B',
@@ -1,4 +1,7 @@
1
1
  const extend = require('../lib/extend');
2
+ const fz = require('../converters/fromZigbee');
3
+ const exposes = require('../lib/exposes');
4
+ const e = exposes.presets;
2
5
 
3
6
  module.exports = [
4
7
  {
@@ -29,4 +32,13 @@ module.exports = [
29
32
  description: 'GU10 white and colour spot',
30
33
  extend: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 555]}),
31
34
  },
35
+ {
36
+ zigbeeModel: ['PROLIGHT REMOTE CONTROL'],
37
+ model: 'PROLIGHT_REMOTE_CONTROL',
38
+ vendor: 'Prolight',
39
+ description: 'Remote control',
40
+ toZigbee: [],
41
+ fromZigbee: [fz.command_on, fz.command_off, fz.command_move_to_level],
42
+ exposes: [e.action(['on', 'off', 'brightness_move_up', 'brightness_move_down'])],
43
+ },
32
44
  ];
@@ -10,11 +10,12 @@ module.exports = [
10
10
  vendor: 'Titan Products',
11
11
  description: 'Room CO2, humidity & temperature sensor',
12
12
  fromZigbee: [fz.battery, fz.humidity, fz.temperature, fz.co2],
13
- exposes: [e.battery(), e.humidity(), e.temperature(), e.co2()],
13
+ exposes: [e.battery_voltage(), e.battery_low(), e.humidity(), e.temperature(), e.co2()],
14
14
  toZigbee: [],
15
15
  configure: async (device, coordinatorEndpoint, logger) => {
16
16
  const endpoint = device.getEndpoint(1);
17
17
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'msTemperatureMeasurement', 'msCO2']);
18
+ await endpoint.read('genPowerCfg', ['batteryVoltage']);
18
19
  await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['msRelativeHumidity']);
19
20
  },
20
21
  },
package/devices/tplink.js CHANGED
@@ -1,6 +1,6 @@
1
- const exposes = require('zigbee-herdsman-converters/lib/exposes');
2
- const fz = {...require('zigbee-herdsman-converters/converters/fromZigbee'), legacy: require('../lib/legacy').fromZigbee};
3
- const reporting = require('zigbee-herdsman-converters/lib/reporting');
1
+ const exposes = require('../lib/exposes');
2
+ const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/legacy').fromZigbee};
3
+ const reporting = require('../lib/reporting');
4
4
  const e = exposes.presets;
5
5
 
6
6
  module.exports = [
package/devices/tuya.js CHANGED
@@ -175,7 +175,8 @@ module.exports = [
175
175
  {modelID: 'TS0505B', manufacturerName: '_TZ3000_cmaky9gq'},
176
176
  {modelID: 'TS0505B', manufacturerName: '_TZ3000_tza2vjxx'},
177
177
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_k1pe6ibm'},
178
- {modelID: 'TS0505B', manufacturerName: '_TZ3210_bfwvfyx1'}],
178
+ {modelID: 'TS0505B', manufacturerName: '_TZ3210_bfwvfyx1'},
179
+ {modelID: 'TS0505B', manufacturerName: '_TZ3210_jd3z4yig'}],
179
180
  model: 'TS0505B',
180
181
  vendor: 'TuYa',
181
182
  description: 'Zigbee RGB+CCT light',
@@ -204,6 +205,7 @@ module.exports = [
204
205
  fingerprint: [{modelID: 'TS0504B', manufacturerName: '_TZ3000_ukuvyhaa'},
205
206
  {modelID: 'TS0504B', manufacturerName: '_TZ3210_bfvybixd'},
206
207
  {modelID: 'TS0504B', manufacturerName: '_TZ3210_sroezl0s'},
208
+ {modelID: 'TS0504B', manufacturerName: '_TZ3210_i2i0bsnv'},
207
209
  {modelID: 'TS0504B', manufacturerName: '_TZ3210_1elppmba'}],
208
210
  model: 'TS0504B',
209
211
  vendor: 'TuYa',
@@ -369,7 +371,8 @@ module.exports = [
369
371
  {vendor: 'BSEED', model: 'Zigbee Socket'}],
370
372
  },
371
373
  {
372
- fingerprint: [{modelID: 'isltm67\u0000', manufacturerName: '_TYST11_pisltm67'}],
374
+ fingerprint: [{modelID: 'isltm67\u0000', manufacturerName: '_TYST11_pisltm67'},
375
+ {modelID: 'TS0601', manufacturerName: '_TZE200_pisltm67'}],
373
376
  model: 'S-LUX-ZB',
374
377
  vendor: 'TuYa',
375
378
  description: 'Light sensor',
@@ -379,7 +382,13 @@ module.exports = [
379
382
  const endpoint = device.getEndpoint(1);
380
383
  await reporting.bind(endpoint, coordinatorEndpoint, ['genBasic']);
381
384
  },
382
- exposes: [e.battery(), e.illuminance_lux(), e.battery_low()],
385
+ exposes: (device, options) => {
386
+ if (device && device.manufacturerName === '_TZE200_pisltm67') {
387
+ return [e.illuminance_lux(), e.linkquality()];
388
+ } else {
389
+ return [e.battery(), e.illuminance_lux(), e.battery_low(), e.linkquality()];
390
+ }
391
+ },
383
392
  },
384
393
  {
385
394
  zigbeeModel: ['TS130F'],
package/devices/woox.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const exposes = require('../lib/exposes');
2
- const reporting = require('zigbee-herdsman-converters/lib/reporting');
2
+ const reporting = require('../lib/reporting');
3
3
  const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/legacy').fromZigbee};
4
4
  const tz = require('../converters/toZigbee');
5
5
  const tuya = require('../lib/tuya');
package/devices/xiaomi.js CHANGED
@@ -152,7 +152,7 @@ module.exports = [
152
152
  model: 'WXKG01LM',
153
153
  vendor: 'Xiaomi',
154
154
  description: 'MiJia wireless switch',
155
- meta: {battery: {voltageToPercentage: '3V_2100'}},
155
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
156
156
  fromZigbee: [fz.xiaomi_battery, fz.xiaomi_WXKG01LM_action, fz.legacy.WXKG01LM_click],
157
157
  exposes: [e.battery(), e.action(['single', 'double', 'triple', 'quadruple', 'hold', 'release', 'many']), e.battery_voltage()],
158
158
  toZigbee: [],
@@ -162,7 +162,7 @@ module.exports = [
162
162
  model: 'WXKG11LM',
163
163
  vendor: 'Xiaomi',
164
164
  description: 'Aqara wireless switch',
165
- meta: {battery: {voltageToPercentage: '3V_2100'}},
165
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
166
166
  exposes: [e.battery(), e.battery_voltage(), e.action(['single', 'double', 'triple', 'quadruple', 'hold', 'release'])],
167
167
  fromZigbee: [fz.xiaomi_multistate_action, fz.xiaomi_WXKG11LM_action, fz.xiaomi_battery,
168
168
  fz.legacy.WXKG11LM_click, fz.legacy.xiaomi_action_click_multistate],
@@ -173,7 +173,7 @@ module.exports = [
173
173
  model: 'WXKG12LM',
174
174
  vendor: 'Xiaomi',
175
175
  description: 'Aqara wireless switch (with gyroscope)',
176
- meta: {battery: {voltageToPercentage: '3V_2100'}},
176
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
177
177
  exposes: [e.battery(), e.action(['single', 'double', 'hold', 'release', 'shake']), e.battery_voltage()],
178
178
  fromZigbee: [fz.xiaomi_battery, fz.xiaomi_multistate_action, fz.legacy.WXKG12LM_action_click_multistate],
179
179
  toZigbee: [],
@@ -183,7 +183,7 @@ module.exports = [
183
183
  model: 'WXKG03LM_rev1',
184
184
  vendor: 'Xiaomi',
185
185
  description: 'Aqara single key wireless wall switch (2016 model)',
186
- meta: {battery: {voltageToPercentage: '3V_2100'}},
186
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
187
187
  exposes: [e.battery(), e.action(['single']), e.battery_voltage()],
188
188
  fromZigbee: [fz.xiaomi_on_off_action, fz.xiaomi_battery, fz.legacy.WXKG03LM_click],
189
189
  toZigbee: [],
@@ -194,7 +194,7 @@ module.exports = [
194
194
  model: 'WXKG03LM_rev2',
195
195
  vendor: 'Xiaomi',
196
196
  description: 'Aqara single key wireless wall switch (2018 model)',
197
- meta: {battery: {voltageToPercentage: '3V_2100'}},
197
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
198
198
  exposes: [e.battery(), e.action(['single', 'double', 'hold']), e.battery_voltage()],
199
199
  fromZigbee: [fz.xiaomi_on_off_action, fz.xiaomi_multistate_action, fz.xiaomi_battery,
200
200
  fz.legacy.WXKG03LM_click, fz.legacy.xiaomi_action_click_multistate],
@@ -212,7 +212,7 @@ module.exports = [
212
212
  e.action(['single', 'double', 'hold']),
213
213
  e.battery_voltage()],
214
214
  onEvent: preventReset,
215
- meta: {battery: {voltageToPercentage: '3V_2100'}},
215
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
216
216
  configure: async (device, coordinatorEndpoint, logger) => {
217
217
  try {
218
218
  const endpoint = device.endpoints[1];
@@ -227,7 +227,7 @@ module.exports = [
227
227
  model: 'WXKG02LM_rev1',
228
228
  vendor: 'Xiaomi',
229
229
  description: 'Aqara double key wireless wall switch (2016 model)',
230
- meta: {battery: {voltageToPercentage: '3V_2100'}},
230
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
231
231
  exposes: [e.battery(), e.action(['single_left', 'single_right', 'single_both']), e.battery_voltage()],
232
232
  fromZigbee: [fz.xiaomi_on_off_action, fz.xiaomi_battery, fz.legacy.WXKG02LM_click],
233
233
  toZigbee: [],
@@ -238,7 +238,7 @@ module.exports = [
238
238
  model: 'WXKG02LM_rev2',
239
239
  vendor: 'Xiaomi',
240
240
  description: 'Aqara double key wireless wall switch (2018 model)',
241
- meta: {battery: {voltageToPercentage: '3V_2100'}},
241
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
242
242
  exposes: [e.battery(), e.action(['single_left', 'single_right', 'single_both', 'double_left', 'double_right', 'double_both',
243
243
  'hold_left', 'hold_right', 'hold_both']), e.battery_voltage()],
244
244
  fromZigbee: [fz.xiaomi_on_off_action, fz.xiaomi_multistate_action, fz.xiaomi_battery,
@@ -534,7 +534,7 @@ module.exports = [
534
534
  model: 'WXKG07LM',
535
535
  vendor: 'Xiaomi',
536
536
  description: 'Aqara D1 double key wireless wall switch',
537
- meta: {battery: {voltageToPercentage: '3V_2100'}},
537
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
538
538
  fromZigbee: [fz.xiaomi_battery, fz.legacy.xiaomi_on_off_action, fz.legacy.xiaomi_multistate_action],
539
539
  toZigbee: [],
540
540
  endpoint: (device) => {
@@ -811,7 +811,7 @@ module.exports = [
811
811
  model: 'WSDCGQ01LM',
812
812
  vendor: 'Xiaomi',
813
813
  description: 'MiJia temperature & humidity sensor',
814
- meta: {battery: {voltageToPercentage: '3V_2100'}},
814
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
815
815
  fromZigbee: [fz.xiaomi_battery, fz.WSDCGQ01LM_WSDCGQ11LM_interval, fz.xiaomi_temperature, fz.humidity],
816
816
  toZigbee: [],
817
817
  exposes: [e.battery(), e.temperature(), e.humidity(), e.battery_voltage()],
@@ -821,7 +821,7 @@ module.exports = [
821
821
  model: 'WSDCGQ11LM',
822
822
  vendor: 'Xiaomi',
823
823
  description: 'Aqara temperature, humidity and pressure sensor',
824
- meta: {battery: {voltageToPercentage: '3V_2100'}},
824
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
825
825
  fromZigbee: [fz.xiaomi_battery, fz.xiaomi_temperature, fz.humidity, fz.pressure, fz.WSDCGQ01LM_WSDCGQ11LM_interval],
826
826
  toZigbee: [],
827
827
  exposes: [e.battery(), e.temperature(), e.humidity(), e.pressure(), e.battery_voltage()],
@@ -837,7 +837,7 @@ module.exports = [
837
837
  description: 'Aqara T1 temperature, humidity and pressure sensor',
838
838
  fromZigbee: [fz.xiaomi_battery, fz.temperature, fz.humidity, fz.pressure],
839
839
  toZigbee: [],
840
- meta: {battery: {voltageToPercentage: '3V_2100'}},
840
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
841
841
  configure: async (device, coordinatorEndpoint, logger) => {
842
842
  const endpoint = device.getEndpoint(1);
843
843
  const binds = ['msTemperatureMeasurement', 'msRelativeHumidity', 'msPressureMeasurement'];
@@ -850,7 +850,7 @@ module.exports = [
850
850
  model: 'RTCGQ01LM',
851
851
  vendor: 'Xiaomi',
852
852
  description: 'MiJia human body movement sensor',
853
- meta: {battery: {voltageToPercentage: '3V_2100'}},
853
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
854
854
  fromZigbee: [fz.xiaomi_battery, fz.occupancy_with_timeout],
855
855
  toZigbee: [],
856
856
  exposes: [e.battery(), e.occupancy(), e.battery_voltage()],
@@ -860,7 +860,7 @@ module.exports = [
860
860
  model: 'RTCGQ11LM',
861
861
  vendor: 'Xiaomi',
862
862
  description: 'Aqara human body movement and illuminance sensor',
863
- meta: {battery: {voltageToPercentage: '3V_2100'}},
863
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
864
864
  fromZigbee: [fz.xiaomi_battery, fz.occupancy_with_timeout, fz.RTCGQ11LM_illuminance, fz.RTCGQ11LM_interval],
865
865
  toZigbee: [],
866
866
  exposes: [e.battery(), e.occupancy(), e.temperature(), e.battery_voltage(), e.illuminance_lux().withProperty('illuminance'),
@@ -876,7 +876,7 @@ module.exports = [
876
876
  exposes: [e.occupancy(), e.illuminance().withUnit('lx').withDescription('Measured illuminance in lux'),
877
877
  exposes.numeric('detection_interval', ea.ALL).withValueMin(2).withValueMax(65535).withUnit('s')
878
878
  .withDescription('Time interval for detecting actions'), e.battery()],
879
- meta: {battery: {voltageToPercentage: '3V_2100'}},
879
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
880
880
  configure: async (device, coordinatorEndpoint, logger) => {
881
881
  const endpoint = device.getEndpoint(1);
882
882
  await endpoint.read('genPowerCfg', ['batteryVoltage']);
@@ -894,7 +894,7 @@ module.exports = [
894
894
  exposes: [e.occupancy(), exposes.enum('motion_sensitivity', ea.ALL, ['low', 'medium', 'high']),
895
895
  exposes.numeric('detection_interval', ea.ALL).withValueMin(2).withValueMax(65535).withUnit('s')
896
896
  .withDescription('Time interval for detecting actions'), e.battery()],
897
- meta: {battery: {voltageToPercentage: '3V_2100'}},
897
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
898
898
  configure: async (device, coordinatorEndpoint, logger) => {
899
899
  const endpoint = device.getEndpoint(1);
900
900
  await endpoint.read('genPowerCfg', ['batteryVoltage']);
@@ -932,7 +932,7 @@ module.exports = [
932
932
  model: 'MCCGQ01LM',
933
933
  vendor: 'Xiaomi',
934
934
  description: 'MiJia door & window contact sensor',
935
- meta: {battery: {voltageToPercentage: '3V_2100'}},
935
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
936
936
  fromZigbee: [fz.xiaomi_battery, fz.xiaomi_contact],
937
937
  toZigbee: [],
938
938
  exposes: [e.battery(), e.contact(), e.battery_voltage()],
@@ -942,7 +942,7 @@ module.exports = [
942
942
  model: 'MCCGQ11LM',
943
943
  vendor: 'Xiaomi',
944
944
  description: 'Aqara door & window contact sensor',
945
- meta: {battery: {voltageToPercentage: '3V_2100'}},
945
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
946
946
  fromZigbee: [fz.xiaomi_battery, fz.xiaomi_contact, fz.xiaomi_contact_interval],
947
947
  toZigbee: [],
948
948
  exposes: [e.battery(), e.contact(), e.temperature(), e.battery_voltage()],
@@ -956,7 +956,7 @@ module.exports = [
956
956
  model: 'SJCGQ11LM',
957
957
  vendor: 'Xiaomi',
958
958
  description: 'Aqara water leak sensor',
959
- meta: {battery: {voltageToPercentage: '3V_2100'}},
959
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
960
960
  fromZigbee: [fz.xiaomi_battery, fz.ias_water_leak_alarm_1, fz.SJCGQ11LM_temperature],
961
961
  toZigbee: [],
962
962
  exposes: [e.battery(), e.water_leak(), e.battery_low(), e.battery_voltage(), e.temperature()],
@@ -966,7 +966,7 @@ module.exports = [
966
966
  model: 'SJCGQ12LM',
967
967
  vendor: 'Xiaomi',
968
968
  description: 'Aqara T1 water leak sensor',
969
- meta: {battery: {voltageToPercentage: '3V_2100'}},
969
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
970
970
  fromZigbee: [fz.xiaomi_battery, fz.ias_water_leak_alarm_1],
971
971
  toZigbee: [],
972
972
  exposes: [e.battery(), e.water_leak(), e.battery_low(), e.tamper(), e.battery_voltage()],
@@ -977,7 +977,7 @@ module.exports = [
977
977
  model: 'MFKZQ01LM',
978
978
  vendor: 'Xiaomi',
979
979
  description: 'Mi/Aqara smart home cube',
980
- meta: {battery: {voltageToPercentage: '3V_2100'}},
980
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
981
981
  fromZigbee: [fz.xiaomi_battery, fz.MFKZQ01LM_action_multistate, fz.MFKZQ01LM_action_analog],
982
982
  exposes: [e.battery(), e.battery_voltage(), e.angle('action_angle'),
983
983
  e.cube_side('action_from_side'), e.cube_side('action_side'), e.cube_side('action_to_side'),
@@ -1135,7 +1135,7 @@ module.exports = [
1135
1135
  model: 'JTYJ-GD-01LM/BW',
1136
1136
  description: 'MiJia Honeywell smoke detector',
1137
1137
  vendor: 'Xiaomi',
1138
- meta: {battery: {voltageToPercentage: '3V_2100'}},
1138
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
1139
1139
  fromZigbee: [fz.xiaomi_battery, fz.JTYJGD01LMBW_smoke, fz.JTYJGD01LMBW_smoke_density],
1140
1140
  toZigbee: [tz.JTQJBF01LMBW_JTYJGD01LMBW_sensitivity, tz.JTQJBF01LMBW_JTYJGD01LMBW_selfest],
1141
1141
  exposes: [
@@ -1205,7 +1205,7 @@ module.exports = [
1205
1205
  model: 'DJT11LM',
1206
1206
  vendor: 'Xiaomi',
1207
1207
  description: 'Aqara vibration sensor',
1208
- meta: {battery: {voltageToPercentage: '3V_2100'}},
1208
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
1209
1209
  fromZigbee: [fz.xiaomi_battery, fz.DJT11LM_vibration],
1210
1210
  toZigbee: [tz.DJT11LM_vibration_sensitivity],
1211
1211
  exposes: [
@@ -1377,7 +1377,7 @@ module.exports = [
1377
1377
  ]), exposes.enum('operation_mode', ea.ALL, ['command', 'event'])
1378
1378
  .withDescription('Operation mode, select "command" to enable bindings (wake up the device before changing modes!)')],
1379
1379
  toZigbee: [tz.aqara_opple_operation_mode],
1380
- meta: {battery: {voltageToPercentage: '3V_2500'}},
1380
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
1381
1381
  configure: async (device, coordinatorEndpoint, logger) => {
1382
1382
  const endpoint = device.getEndpoint(1);
1383
1383
  await endpoint.write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f});
@@ -1399,7 +1399,7 @@ module.exports = [
1399
1399
  ]), exposes.enum('operation_mode', ea.ALL, ['command', 'event'])
1400
1400
  .withDescription('Operation mode, select "command" to enable bindings (wake up the device before changing modes!)')],
1401
1401
  toZigbee: [tz.aqara_opple_operation_mode],
1402
- meta: {battery: {voltageToPercentage: '3V_2500'}},
1402
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
1403
1403
  configure: async (device, coordinatorEndpoint, logger) => {
1404
1404
  const endpoint = device.getEndpoint(1);
1405
1405
  await endpoint.write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f});
@@ -1425,7 +1425,7 @@ module.exports = [
1425
1425
  ]), exposes.enum('operation_mode', ea.ALL, ['command', 'event'])
1426
1426
  .withDescription('Operation mode, select "command" to enable bindings (wake up the device before changing modes!)')],
1427
1427
  toZigbee: [tz.aqara_opple_operation_mode],
1428
- meta: {battery: {voltageToPercentage: '3V_2500'}},
1428
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
1429
1429
  configure: async (device, coordinatorEndpoint, logger) => {
1430
1430
  const endpoint = device.getEndpoint(1);
1431
1431
  await endpoint.write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f});
@@ -1441,7 +1441,7 @@ module.exports = [
1441
1441
  description: 'MiJia light intensity sensor',
1442
1442
  fromZigbee: [fz.battery, fz.illuminance],
1443
1443
  toZigbee: [],
1444
- meta: {battery: {voltageToPercentage: '3V_2500'}},
1444
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
1445
1445
  configure: async (device, coordinatorEndpoint, logger) => {
1446
1446
  const endpoint = device.getEndpoint(1);
1447
1447
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'msIlluminanceMeasurement']);
@@ -1592,7 +1592,7 @@ module.exports = [
1592
1592
  description: 'Aqara wireless remote switch H1 (double rocker)',
1593
1593
  fromZigbee: [fz.battery, fz.xiaomi_multistate_action, fz.aqara_opple, fz.command_toggle],
1594
1594
  toZigbee: [tz.xiaomi_switch_click_mode, tz.aqara_opple_operation_mode],
1595
- meta: {battery: {voltageToPercentage: '3V_2500'}, multiEndpoint: true},
1595
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}, multiEndpoint: true},
1596
1596
  exposes: [
1597
1597
  e.battery(), e.battery_voltage(), e.action([
1598
1598
  'single_left', 'single_right', 'single_both',
@@ -1679,7 +1679,7 @@ module.exports = [
1679
1679
  description: 'Aqara TVOC air quality monitor',
1680
1680
  fromZigbee: [fz.xiaomi_tvoc, fz.battery, fz.temperature, fz.humidity],
1681
1681
  toZigbee: [],
1682
- meta: {battery: {voltageToPercentage: '3V_2100'}},
1682
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
1683
1683
  exposes: [e.battery(), e.temperature(), e.humidity(), e.voc()],
1684
1684
  configure: async (device, coordinatorEndpoint, logger) => {
1685
1685
  const endpoint = device.getEndpoint(1);
@@ -1758,7 +1758,7 @@ module.exports = [
1758
1758
  model: 'WXKG13LM',
1759
1759
  vendor: 'Xiaomi',
1760
1760
  description: 'Aqara T1 wireless mini switch',
1761
- meta: {battery: {voltageToPercentage: '3V_2500'}},
1761
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
1762
1762
  fromZigbee: [fz.battery, fz.aqara_opple_multistate, fz.aqara_opple],
1763
1763
  toZigbee: [],
1764
1764
  exposes: [e.battery(), e.battery_voltage(), e.action(['single', 'double', 'triple', 'quintuple', 'hold', 'release', 'many'])],
@@ -1774,7 +1774,7 @@ module.exports = [
1774
1774
  description: 'Aqara T1 light intensity sensor',
1775
1775
  fromZigbee: [fz.battery, fz.illuminance, fz.aqara_opple],
1776
1776
  toZigbee: [tz.GZCGQ11LM_detection_period],
1777
- meta: {battery: {voltageToPercentage: '3V_2500'}},
1777
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
1778
1778
  exposes: [e.battery(), e.battery_voltage(), e.illuminance(), e.illuminance_lux(),
1779
1779
  exposes.numeric('detection_period', exposes.access.ALL).withValueMin(1).withValueMax(59).withUnit('s')
1780
1780
  .withDescription('Time interval in seconds to report after light changes')],
@@ -1813,7 +1813,7 @@ module.exports = [
1813
1813
  description: 'Aqara T1 door & window contact sensor',
1814
1814
  fromZigbee: [fz.xiaomi_contact, fz.battery],
1815
1815
  toZigbee: [],
1816
- meta: {battery: {voltageToPercentage: '3V_2100'}},
1816
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
1817
1817
  exposes: [e.contact(), e.battery(), e.battery_voltage()],
1818
1818
  configure: async (device, coordinatorEndpoint, logger) => {
1819
1819
  const endpoint = device.getEndpoint(1);
@@ -1842,7 +1842,7 @@ module.exports = [
1842
1842
  model: 'ZNXNKG02LM',
1843
1843
  vendor: 'Xiaomi',
1844
1844
  description: 'Aqara knob H1 (wireless)',
1845
- meta: {battery: {voltageToPercentage: '3V_2100'}},
1845
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
1846
1846
  exposes: [e.battery(), e.battery_voltage(),
1847
1847
  e.action(['single', 'double', 'hold', 'release', 'start_rotating', 'rotation', 'stop_rotating']),
1848
1848
  exposes.enum('operation_mode', ea.ALL, ['event', 'command']).withDescription('Button mode'),
@@ -1880,7 +1880,7 @@ module.exports = [
1880
1880
  model: 'WXKG17LM',
1881
1881
  vendor: 'Xiaomi',
1882
1882
  description: 'Aqara E1 double key wireless switch',
1883
- meta: {battery: {voltageToPercentage: '3V_2100'}},
1883
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
1884
1884
  exposes: [e.battery(), e.battery_voltage(),
1885
1885
  e.action(['single_left', 'single_right', 'single_both', 'double_left', 'double_right', 'hold_left', 'hold_right']),
1886
1886
  // eslint-disable-next-line max-len
@@ -126,17 +126,22 @@ module.exports = [
126
126
  },
127
127
  {
128
128
  fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_iossyxra'}],
129
- model: 'ZM-AM02',
129
+ model: 'ZM-AM02_cover',
130
130
  vendor: 'Zemismart',
131
131
  description: 'Zigbee/RF curtain converter',
132
- fromZigbee: [fz.ZMAM02],
133
- toZigbee: [tz.ZMAM02],
134
- exposes: [exposes.enum('motor_working_mode', ea.STATE_SET, Object.values(tuya.ZMAM02.AM02MotorMode)),
135
- exposes.enum('control', ea.STATE_SET, Object.values(tuya.ZMAM02.AM02Control)),
132
+ fromZigbee: [fz.ZMAM02_cover],
133
+ toZigbee: [tz.ZMAM02_cover],
134
+ exposes: [e.cover_position().setAccess('position', ea.STATE_SET),
135
+ exposes.composite('options', 'options')
136
+ .withFeature(exposes.numeric('motor_speed', ea.STATE_SET)
137
+ .withValueMin(0)
138
+ .withValueMax(255)
139
+ .withDescription('Motor speed')),
140
+ exposes.enum('motor_working_mode', ea.STATE_SET, Object.values(tuya.ZMLookups.AM02MotorWorkingMode)),
136
141
  exposes.numeric('percent_state', ea.STATE).withValueMin(0).withValueMax(100).withValueStep(1).withUnit('%'),
137
- exposes.enum('mode', ea.STATE_SET, Object.values(tuya.ZMAM02.AM02Mode)),
138
- exposes.enum('control_back_mode', ea.STATE_SET, Object.values(tuya.ZMAM02.AM02Direction)),
139
- exposes.enum('border', ea.STATE_SET, Object.values(tuya.ZMAM02.AM02Border)),
142
+ exposes.enum('mode', ea.STATE_SET, Object.values(tuya.ZMLookups.AM02Mode)),
143
+ exposes.enum('motor_direction', ea.STATE_SET, Object.values(tuya.ZMLookups.AM02Direction)),
144
+ exposes.enum('border', ea.STATE_SET, Object.values(tuya.ZMLookups.AM02Border)),
140
145
  // ---------------------------------------------------------------------------------
141
146
  // DP exists, but not used at the moment
142
147
  // exposes.numeric('percent_control', ea.STATE_SET).withValueMin(0).withValueMax(100).withValueStep(1).withUnit('%'),
package/lib/exposes.js CHANGED
@@ -484,7 +484,7 @@ module.exports = {
484
484
  precision: (name) => new Numeric(`${name}_precision`, access.SET).withValueMin(0).withValueMax(3).withDescription(`Number of digits after decimal point for ${name}, takes into effect on next report of device.`),
485
485
  invert_cover: () => new Binary(`invert_cover`, access.SET, true, false).withDescription(`Inverts the cover position, false: open=100,close=0, true: open=0,close=100 (default false).`),
486
486
  color_sync: () => new Binary(`color_sync`, access.SET, true, false).withDescription(`When enabled colors will be synced, e.g. if the light supports both color x/y and color temperature a conversion from color x/y to color temperature will be done when setting the x/y color (default true).`),
487
- thermostat_unit: () => new Enum('thermostat_unit', access.SET, ['celsius', 'fahrenheit']).withDescription('Controls the temperature unit of the themrostat (default celsius).'),
487
+ thermostat_unit: () => new Enum('thermostat_unit', access.SET, ['celsius', 'fahrenheit']).withDescription('Controls the temperature unit of the thermostat (default celsius).'),
488
488
  expose_pin: () => new Binary(`expose_pin`, access.SET, true, false).withDescription(`Expose pin of this lock in the published payload (default false).`),
489
489
  occupancy_timeout: () => new Numeric(`occupancy_timeout`, access.SET).withValueMin(0).withDescription('Time in seconds after which occupancy is cleared after detecting it (default 90 seconds).'),
490
490
  vibration_timeout: () => new Numeric(`vibration_timeout`, access.SET).withValueMin(0).withDescription('Time in seconds after which vibration is cleared after detecting it (default 90 seconds).'),
@@ -501,6 +501,7 @@ module.exports = {
501
501
  illuminance_below_threshold_check: () => new Binary(`illuminance_below_threshold_check`, access.SET, true, false).withDescription(`Set to false to also send messages when illuminance is above threshold in night mode (default true).`),
502
502
  },
503
503
  presets: {
504
+ ac_frequency: () => new Numeric('ac_frequency', access.STATE).withUnit('Hz').withDescription('Measured electrical AC frequency'),
504
505
  action: (values) => new Enum('action', access.STATE, values).withDescription('Triggered action (e.g. a button click)'),
505
506
  angle: (name) => new Numeric(name, access.STATE).withValueMin(-360).withValueMax(360),
506
507
  angle_axis: (name) => new Numeric(name, access.STATE).withValueMin(-90).withValueMax(90),
package/lib/reporting.js CHANGED
@@ -19,9 +19,10 @@ function payload(attribute, min, max, change, overrides) {
19
19
  }
20
20
 
21
21
  async function readEletricalMeasurementMultiplierDivisors(endpoint) {
22
- // Split into two chunks, some devices fail to respond when reading too much attributes at once.
22
+ // Split into three chunks, some devices fail to respond when reading too much attributes at once.
23
23
  await endpoint.read('haElectricalMeasurement', ['acVoltageMultiplier', 'acVoltageDivisor', 'acCurrentMultiplier']);
24
24
  await endpoint.read('haElectricalMeasurement', ['acCurrentDivisor', 'acPowerMultiplier', 'acPowerDivisor']);
25
+ await endpoint.read('haElectricalMeasurement', ['acFrequencyDivisor', 'acFrequencyMultiplier']);
25
26
  }
26
27
 
27
28
  async function readMeteringMultiplierDivisor(endpoint) {
@@ -199,4 +200,8 @@ module.exports = {
199
200
  const p = payload('measuredValue', 10, repInterval.HOUR, 100, overrides);
200
201
  await endpoint.configureReporting('msSoilMoisture', p);
201
202
  },
203
+ acFrequency: async (endpoint, overrides) => {
204
+ const p = payload('acFrequency', 5, repInterval.MINUTES_5, 10, overrides);
205
+ await endpoint.configureReporting('haElectricalMeasurement', p);
206
+ },
202
207
  };
package/lib/tuya.js CHANGED
@@ -565,7 +565,7 @@ const dataPoints = {
565
565
  AM02PercentControl: 2,
566
566
  AM02PercentState: 3,
567
567
  AM02Mode: 4,
568
- AM02ControlBackMode: 5,
568
+ AM02Direction: 5,
569
569
  AM02WorkState: 7,
570
570
  AM02CountdownLeft: 9,
571
571
  AM02TimeTotal: 10,
@@ -700,7 +700,7 @@ const tvThermostatPreset = {
700
700
  3: 'holiday',
701
701
  };
702
702
  // Zemismart ZM_AM02 Roller Shade Converter
703
- const ZMAM02 = {
703
+ const ZMLookups = {
704
704
  AM02Mode: {
705
705
  0: 'morning',
706
706
  1: 'night',
@@ -728,7 +728,7 @@ const ZMAM02 = {
728
728
  0: 'fully_open',
729
729
  1: 'fully_close',
730
730
  },
731
- AM02MotorMode: {
731
+ AM02MotorWorkingMode: {
732
732
  0: 'continuous',
733
733
  1: 'intermittently',
734
734
  },
@@ -744,6 +744,7 @@ const moesSwitch = {
744
744
  0: 'off',
745
745
  1: 'switch',
746
746
  2: 'position',
747
+ 3: 'freeze',
747
748
  },
748
749
  };
749
750
 
@@ -896,6 +897,6 @@ module.exports = {
896
897
  tvThermostatMode,
897
898
  tvThermostatPreset,
898
899
  tuyaRadar,
899
- ZMAM02,
900
+ ZMLookups,
900
901
  moesSwitch,
901
902
  };
package/lib/utils.js CHANGED
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ const globalStore = require('./store');
4
+
3
5
  function isLegacyEnabled(options) {
4
6
  return !options.hasOwnProperty('legacy') || options.legacy;
5
7
  }
@@ -158,6 +160,8 @@ function batteryVoltageToPercentage(voltage, option) {
158
160
  percentage = 0;
159
161
  }
160
162
  percentage = Math.round(percentage);
163
+ } else if (option === '3V_2850_3200') {
164
+ percentage = toPercentage(voltage, 2850, 3200);
161
165
  } else if (option === '4LR6AA1_5v') {
162
166
  percentage = toPercentage(voltage, 3000, 4200);
163
167
  } else {
@@ -384,7 +388,23 @@ function extendDevice(deviceConfigs, modelName, adjustments) {
384
388
  return {...baseDevice, ...adjustments};
385
389
  }
386
390
 
391
+ function noOccupancySince(endpoint, newPayload, options, publish) {
392
+ if (options && options.no_occupancy_since && newPayload.occupancy) {
393
+ globalStore.getValue(endpoint, 'no_occupancy_since_timers', []).forEach((t) => clearTimeout(t));
394
+ globalStore.putValue(endpoint, 'no_occupancy_since_timers', []);
395
+
396
+ newPayload.no_occupancy_since = 0;
397
+ options.no_occupancy_since.forEach((since) => {
398
+ const timer = setTimeout(() => {
399
+ publish({no_occupancy_since: since});
400
+ }, since * 1000);
401
+ globalStore.getValue(endpoint, 'no_occupancy_since_timers').push(timer);
402
+ });
403
+ }
404
+ }
405
+
387
406
  module.exports = {
407
+ noOccupancySince,
388
408
  getOptions,
389
409
  isLegacyEnabled,
390
410
  precisionRound,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.413",
3
+ "version": "14.0.417",
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.413",
3
+ "version": "14.0.417",
4
4
  "description": "Collection of device converters to be used with zigbee-herdsman",
5
5
  "main": "index.js",
6
6
  "files": [