zigbee-herdsman-converters 14.0.412 → 14.0.416

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);
461
- }
462
-
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
- });
462
+ globalStore.putValue(msg.endpoint, 'occupancy_timer', timer);
471
463
  }
472
464
 
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: {
@@ -2420,6 +2410,12 @@ const converters = {
2420
2410
  convert: (model, msg, publish, options, meta) => {
2421
2411
  const dpValue = tuya.firstDpValue(msg, meta, 'moes_switch');
2422
2412
  const dp = dpValue.dp;
2413
+
2414
+ // tuya_switch datapoints
2415
+ if (dp >= 1 && dp <= 4) {
2416
+ return null;
2417
+ }
2418
+
2423
2419
  const value = tuya.getDataValue(dpValue);
2424
2420
 
2425
2421
  switch (dp) {
@@ -2637,6 +2633,31 @@ const converters = {
2637
2633
  }
2638
2634
  },
2639
2635
  },
2636
+ ts011f_plug_indicator_mode: {
2637
+ cluster: 'genOnOff',
2638
+ type: ['attributeReport', 'readResponse'],
2639
+ convert: (model, msg, publish, options, meta) => {
2640
+ const property = 'tuyaBacklightMode'; // 0x8001 or 32769
2641
+ if (msg.data.hasOwnProperty(property)) {
2642
+ const value = msg.data[property];
2643
+ const lookup = {0: 'off', 1: 'off/on', 2: 'on/off', 3: 'on'};
2644
+ if (lookup.hasOwnProperty(value)) {
2645
+ return {indicator_mode: lookup[value]};
2646
+ }
2647
+ }
2648
+ },
2649
+ },
2650
+ ts011f_plug_child_mode: {
2651
+ cluster: 'genOnOff',
2652
+ type: ['attributeReport', 'readResponse'],
2653
+ convert: (model, msg, publish, options, meta) => {
2654
+ const property = (0x8000).toString(); // 32768
2655
+ if (msg.data.hasOwnProperty(property)) {
2656
+ const value = msg.data[property];
2657
+ return {child_lock: value ? 'LOCK' : 'UNLOCK'};
2658
+ }
2659
+ },
2660
+ },
2640
2661
  WSZ01_on_off_action: {
2641
2662
  cluster: 65029,
2642
2663
  type: 'raw',
@@ -5330,8 +5351,11 @@ const converters = {
5330
5351
  if (index == 1) {
5331
5352
  payload.voltage = value;
5332
5353
  payload.battery = batteryVoltageToPercentage(value, '3V_2100');
5333
- } else if (index === 3) payload.temperature = calibrateAndPrecisionRoundOptions(value, options, 'temperature'); // 0x03
5334
- else if (index === 5) {
5354
+ } else if (index === 3) {
5355
+ if (!['WXCJKG11LM', 'WXCJKG12LM', 'WXCJKG13LM'].includes(model.model)) {
5356
+ payload.temperature = calibrateAndPrecisionRoundOptions(value, options, 'temperature'); // 0x03
5357
+ }
5358
+ } else if (index === 5) {
5335
5359
  if (['JT-BZ-01AQ/A', 'RTCZCGQ11LM'].includes(model.model)) payload.power_outage_count = value;
5336
5360
  } else if (index === 100) {
5337
5361
  if (['QBKG20LM', 'QBKG31LM', 'QBKG39LM', 'QBKG41LM', 'QBCZ15LM'].includes(model.model)) {
@@ -5339,7 +5363,7 @@ const converters = {
5339
5363
  payload[`state_${mapping}`] = value === 1 ? 'ON' : 'OFF';
5340
5364
  } else if (['WXKG14LM', 'WXKG16LM', 'WXKG17LM'].includes(model.model)) {
5341
5365
  payload.click_mode = {1: 'fast', 2: 'multi'}[value];
5342
- } else if (['WXCJKG11LM ', 'WXCJKG12LM', 'WXCJKG13LM'].includes(model.model)) {
5366
+ } else if (['WXCJKG11LM', 'WXCJKG12LM', 'WXCJKG13LM'].includes(model.model)) {
5343
5367
  // We don't know what the value means for these devices.
5344
5368
  // https://github.com/Koenkk/zigbee2mqtt/issues/11126
5345
5369
  } else {
@@ -8301,79 +8325,89 @@ const converters = {
8301
8325
  return {action};
8302
8326
  },
8303
8327
  },
8304
- ZMAM02: {
8328
+ ZMAM02_cover: {
8305
8329
  cluster: 'manuSpecificTuya',
8306
- type: ['commandDataResponse', 'commandDataReport', 'commandSetDataresponse'],
8330
+ type: ['commandDataReport', 'commandDataResponse'],
8331
+ options: [exposes.options.invert_cover()],
8307
8332
  convert: (model, msg, publish, options, meta) => {
8308
- const result = {};
8309
- // let value = tuya.getDataValue(dpValue);
8310
- // let result = null;
8311
- for (const dpValue of msg.data.dpValues) {
8312
- const value = tuya.getDataValue(dpValue);
8313
- switch (dpValue.dp) {
8314
- case tuya.dataPoints.AM02Control:
8315
- result.control = tuya.ZMAM02.AM02Control[value];
8316
- break;
8317
- case tuya.dataPoints.AM02PercentControl:
8318
- 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.`);
8319
8366
  break;
8320
- case tuya.dataPoints.AM02ControlBackMode:
8321
- 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.`);
8322
8380
  break;
8323
- case tuya.dataPoints.AM02MotorWorkingMode:
8324
- switch (value) {
8325
- case 0: // continuous 1
8326
- result.motor_working_mode = 'continuous';
8327
- break;
8328
- case 1: // intermittently
8329
- result.motor_working_mode = 'intermittently';
8330
- break;
8331
- default:
8332
- meta.logger.warn('zigbee-herdsman-converters:ZM_AM_02: ' +
8333
- `Mode ${value} is not recognized.`);
8334
- break;
8335
- }
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.`);
8336
8392
  break;
8337
- case tuya.dataPoints.AM02Border:
8338
- switch (value) {
8339
- case 0: // up
8340
- result.border = 'up';
8341
- break;
8342
- case 1: // down
8343
- result.border = 'down';
8344
- break;
8345
- case 2: // down_delete
8346
- result.border = 'down_delete';
8347
- break;
8348
- default:
8349
- 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: ' +
8350
8403
  `Mode ${value} is not recognized.`);
8351
- break;
8352
- }
8353
- break;
8354
- case tuya.dataPoints.AM02PercentState:
8355
- result.percent_state = value;
8356
8404
  break;
8357
- case tuya.dataPoints.AM02Mode:
8358
- switch (value) {
8359
- case 0: // morning
8360
- result.mode = 'morning';
8361
- break;
8362
- case 1: // night
8363
- result.mode = 'night';
8364
- break;
8365
- default:
8366
- meta.logger.warn('zigbee-herdsman-converters:ZM_AM_02: ' +
8367
- `Mode ${value} is not recognized.`);
8368
- break;
8369
- }
8370
- break;
8371
- default:
8372
- meta.logger.warn(`fromZigbee.Zemismart Shader Konverter (Zm_AM02): NOT RECOGNIZED ` +
8373
- `DP #${dpValue.dp} with data ${JSON.stringify(dpValue)}`);
8374
8405
  }
8406
+ break;
8407
+ default: // Unknown code
8408
+ meta.logger.warn(`ZMAM02_cover: Unhandled DP #${dp} for ${meta.device.manufacturerName}:
8409
+ ${JSON.stringify(dpValue)}`);
8375
8410
  }
8376
- return result;
8377
8411
  },
8378
8412
  },
8379
8413
  // #endregion
@@ -3218,7 +3218,7 @@ const converters = {
3218
3218
  );
3219
3219
  break;
3220
3220
  case 'indicate_light':
3221
- await tuya.sendDataPointValue(
3221
+ await tuya.sendDataPointEnum(
3222
3222
  entity,
3223
3223
  tuya.dataPoints.moesSwitchIndicateLight,
3224
3224
  utils.getKey(tuya.moesSwitch.indicateLight, value),
@@ -5994,6 +5994,32 @@ const converters = {
5994
5994
  await entity.read('genOnOff', ['tuyaBacklightMode']);
5995
5995
  },
5996
5996
  },
5997
+ ts011f_plug_indicator_mode: {
5998
+ key: ['indicator_mode'],
5999
+ convertSet: async (entity, key, value, meta) => {
6000
+ if (typeof value === 'string') {
6001
+ value = value.toLowerCase();
6002
+ const lookup = {'off': 0, 'off/on': 1, 'on/off': 2, 'on': 3};
6003
+ utils.validateValue(value, Object.keys(lookup));
6004
+ value = lookup[value];
6005
+ }
6006
+
6007
+ if (typeof value === 'number' && value >= 0 && value <= 3) {
6008
+ await entity.write('genOnOff', {tuyaBacklightMode: value});
6009
+ } else {
6010
+ meta.logger.warn(`toZigbee.ts011f_plug_indicator_mode: Unsupported value ${value}`);
6011
+ }
6012
+ },
6013
+ convertGet: async (entity, key, meta) => {
6014
+ await entity.read('genOnOff', ['tuyaBacklightMode']);
6015
+ },
6016
+ },
6017
+ ts011f_plug_child_mode: {
6018
+ key: ['child_lock'],
6019
+ convertSet: async (entity, key, value, meta) => {
6020
+ await entity.write('genOnOff', {0x8000: {value: value === 'LOCK', type: 0x10}});
6021
+ },
6022
+ },
5997
6023
  hy_thermostat: {
5998
6024
  key: [
5999
6025
  'child_lock', 'current_heating_setpoint', 'local_temperature_calibration',
@@ -6898,30 +6924,56 @@ const converters = {
6898
6924
  }
6899
6925
  },
6900
6926
  },
6901
- ZMAM02: {
6902
- 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()],
6903
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
+ }
6904
6960
  switch (key) {
6905
- case 'control':
6906
- await tuya.sendDataPointEnum(entity, tuya.dataPoints.AM02Control, utils.getKey(tuya.ZMAM02.AM02Control, value));
6907
- break;
6908
- case 'percent_control':
6909
- await tuya.sendDataPointValue(entity, tuya.dataPoints.AM02PercentState, value);
6910
- break;
6911
6961
  case 'mode':
6912
- 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));
6913
6963
  break;
6914
- case 'control_back_mode':
6915
- 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));
6916
6966
  break;
6917
6967
  case 'border':
6918
- 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));
6919
6969
  break;
6920
6970
  case 'motor_working_mode':
6921
- 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));
6922
6976
  break;
6923
- default: // Unknown Key
6924
- meta.logger.warn(`toZigbee.ZMAM02: Unhandled Key ${key}`);
6925
6977
  }
6926
6978
  },
6927
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',
@@ -375,4 +375,44 @@ module.exports = [
375
375
  },
376
376
  exposes: [e.battery(), e.illuminance(), e.temperature(), e.humidity(), e.pressure()],
377
377
  },
378
+ {
379
+ zigbeeModel: ['EFEKTA_eFlower_Pro'],
380
+ model: 'EFEKTA_eFlower_Pro',
381
+ vendor: 'Custom devices (DiY)',
382
+ description: '[Plant Wattering Sensor with e-ink display 2.13](https://efektalab.com/eFlowerPro)',
383
+ fromZigbee: [fz.temperature, fz.humidity, fz.illuminance, fz.soil_moisture, fz.battery],
384
+ toZigbee: [tz.factory_reset],
385
+ configure: async (device, coordinatorEndpoint, logger) => {
386
+ const firstEndpoint = device.getEndpoint(1);
387
+ await reporting.bind(firstEndpoint, coordinatorEndpoint, [
388
+ 'genPowerCfg', 'msTemperatureMeasurement', 'msRelativeHumidity', 'msIlluminanceMeasurement', 'msSoilMoisture']);
389
+ const overides = {min: 0, max: 21600, change: 0};
390
+ await reporting.batteryVoltage(firstEndpoint, overides);
391
+ await reporting.batteryPercentageRemaining(firstEndpoint, overides);
392
+ await reporting.temperature(firstEndpoint, overides);
393
+ await reporting.humidity(firstEndpoint, overides);
394
+ await reporting.illuminance(firstEndpoint, overides);
395
+ await reporting.soil_moisture(firstEndpoint, overides);
396
+ },
397
+ exposes: [e.soil_moisture(), e.battery(), e.illuminance(), e.temperature(), e.humidity()],
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
+ },
378
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};
@@ -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',
@@ -62,10 +62,14 @@ const gledoptoExtend = {
62
62
  }),
63
63
  };
64
64
 
65
- const configureReadModelID = async (device) => {
65
+ const configureReadModelID = async (device, coordinatorEndpoint, logger) => {
66
66
  // https://github.com/Koenkk/zigbee-herdsman-converters/issues/3016#issuecomment-1027726604
67
67
  const endpoint = device.endpoints[0];
68
- await endpoint.read('genBasic', ['modelId']);
68
+ const oldModel = device.modelID;
69
+ const newModel = (await endpoint.read('genBasic', ['modelId'])).modelId;
70
+ if (oldModel != newModel) {
71
+ logger.info(`Detected Gledopto device mode change, from '${oldModel}' to '${newModel}'`);
72
+ }
69
73
  };
70
74
 
71
75
  module.exports = [
@@ -125,7 +129,7 @@ module.exports = [
125
129
  extend: gledoptoExtend.light_onoff_brightness_colortemp({noConfigure: true}),
126
130
  configure: async (device, coordinatorEndpoint, logger) => {
127
131
  await extend.light_onoff_brightness_colortemp().configure(device, coordinatorEndpoint, logger);
128
- await configureReadModelID(device);
132
+ await configureReadModelID(device, coordinatorEndpoint, logger);
129
133
  },
130
134
  },
131
135
  {
@@ -192,7 +196,7 @@ module.exports = [
192
196
  extend: gledoptoExtend.light_onoff_brightness_colortemp_color({noConfigure: true}),
193
197
  configure: async (device, coordinatorEndpoint, logger) => {
194
198
  await extend.light_onoff_brightness_colortemp_color().configure(device, coordinatorEndpoint, logger);
195
- await configureReadModelID(device);
199
+ await configureReadModelID(device, coordinatorEndpoint, logger);
196
200
  },
197
201
  },
198
202
  {
@@ -254,7 +258,7 @@ module.exports = [
254
258
  extend: gledoptoExtend.light_onoff_brightness_color({noConfigure: true}),
255
259
  configure: async (device, coordinatorEndpoint, logger) => {
256
260
  await extend.light_onoff_brightness_color().configure(device, coordinatorEndpoint, logger);
257
- await configureReadModelID(device);
261
+ await configureReadModelID(device, coordinatorEndpoint, logger);
258
262
  },
259
263
  },
260
264
  {
@@ -263,11 +267,12 @@ module.exports = [
263
267
  vendor: 'Gledopto',
264
268
  ota: ota.zigbeeOTA,
265
269
  description: 'Zigbee LED Controller RGB+CCT (pro)',
270
+ whiteLabel: [{vendor: 'Gledopto', model: 'GL-C-001P'}],
266
271
  extend: gledoptoExtend.light_onoff_brightness_colortemp_color({colorTempRange: [158, 495], noConfigure: true}),
267
272
  meta: {disableDefaultResponse: true},
268
273
  configure: async (device, coordinatorEndpoint, logger) => {
269
274
  await extend.light_onoff_brightness_colortemp_color().configure(device, coordinatorEndpoint, logger);
270
- await configureReadModelID(device);
275
+ await configureReadModelID(device, coordinatorEndpoint, logger);
271
276
  },
272
277
  },
273
278
  {
@@ -292,7 +297,7 @@ module.exports = [
292
297
  extend: gledoptoExtend.light_onoff_brightness({noConfigure: true}),
293
298
  configure: async (device, coordinatorEndpoint, logger) => {
294
299
  await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
295
- await configureReadModelID(device);
300
+ await configureReadModelID(device, coordinatorEndpoint, logger);
296
301
  },
297
302
  },
298
303
  {
@@ -564,6 +569,14 @@ module.exports = [
564
569
  description: 'Zigbee 10W Floodlight RGB+CCT (pro)',
565
570
  extend: gledoptoExtend.light_onoff_brightness_colortemp_color(),
566
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
+ },
567
580
  {
568
581
  zigbeeModel: ['GL-FL-005TZ'],
569
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',