zigbee-herdsman-converters 14.0.409 → 14.0.413

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.
@@ -616,6 +616,25 @@ const converters = {
616
616
  return result;
617
617
  },
618
618
  },
619
+ meter_identification: {
620
+ cluster: 'haMeterIdentification',
621
+ type: ['readResponse'],
622
+ convert: (model, msg, publish, options, meta) => {
623
+ const result = {};
624
+ const elements = [
625
+ /* 0x000A*/ 'softwareRevision',
626
+ /* 0x000D*/ 'availablePower',
627
+ /* 0x000E*/ 'powerThreshold',
628
+ ];
629
+ for (const at of elements) {
630
+ const atSnake = at.split(/(?=[A-Z])/).join('_').toLowerCase();
631
+ if (msg.data[at]) {
632
+ result[atSnake] = msg.data[at];
633
+ }
634
+ }
635
+ return result;
636
+ },
637
+ },
619
638
  metering: {
620
639
  /**
621
640
  * When using this converter also add the following to the configure method of the device:
@@ -2395,6 +2414,32 @@ const converters = {
2395
2414
  }
2396
2415
  },
2397
2416
  },
2417
+ moes_switch: {
2418
+ cluster: 'manuSpecificTuya',
2419
+ type: ['commandDataResponse', 'commandDataReport'],
2420
+ convert: (model, msg, publish, options, meta) => {
2421
+ const dpValue = tuya.firstDpValue(msg, meta, 'moes_switch');
2422
+ const dp = dpValue.dp;
2423
+
2424
+ // tuya_switch datapoints
2425
+ if (dp >= 1 && dp <= 4) {
2426
+ return null;
2427
+ }
2428
+
2429
+ const value = tuya.getDataValue(dpValue);
2430
+
2431
+ switch (dp) {
2432
+ case tuya.dataPoints.moesSwitchPowerOnBehavior:
2433
+ return {power_on_behavior: tuya.moesSwitch.powerOnBehavior[value]};
2434
+ case tuya.dataPoints.moesSwitchIndicateLight:
2435
+ return {indicate_light: tuya.moesSwitch.indicateLight[value]};
2436
+ default:
2437
+ meta.logger.warn(`fromZigbee:moes_switch: NOT RECOGNIZED DP #${
2438
+ dp} with data ${JSON.stringify(dpValue)}`);
2439
+ break;
2440
+ }
2441
+ },
2442
+ },
2398
2443
  eurotronic_thermostat: {
2399
2444
  cluster: 'hvacThermostat',
2400
2445
  type: ['attributeReport', 'readResponse'],
@@ -2598,6 +2643,31 @@ const converters = {
2598
2643
  }
2599
2644
  },
2600
2645
  },
2646
+ ts011f_plug_indicator_mode: {
2647
+ cluster: 'genOnOff',
2648
+ type: ['attributeReport', 'readResponse'],
2649
+ convert: (model, msg, publish, options, meta) => {
2650
+ const property = 'tuyaBacklightMode'; // 0x8001 or 32769
2651
+ if (msg.data.hasOwnProperty(property)) {
2652
+ const value = msg.data[property];
2653
+ const lookup = {0: 'off', 1: 'off/on', 2: 'on/off', 3: 'on'};
2654
+ if (lookup.hasOwnProperty(value)) {
2655
+ return {indicator_mode: lookup[value]};
2656
+ }
2657
+ }
2658
+ },
2659
+ },
2660
+ ts011f_plug_child_mode: {
2661
+ cluster: 'genOnOff',
2662
+ type: ['attributeReport', 'readResponse'],
2663
+ convert: (model, msg, publish, options, meta) => {
2664
+ const property = (0x8000).toString(); // 32768
2665
+ if (msg.data.hasOwnProperty(property)) {
2666
+ const value = msg.data[property];
2667
+ return {child_lock: value ? 'LOCK' : 'UNLOCK'};
2668
+ }
2669
+ },
2670
+ },
2601
2671
  WSZ01_on_off_action: {
2602
2672
  cluster: 65029,
2603
2673
  type: 'raw',
@@ -5020,27 +5090,28 @@ const converters = {
5020
5090
  }
5021
5091
  },
5022
5092
  },
5023
- legrand_device_mode: {
5093
+ legrand_cluster_fc01: {
5024
5094
  cluster: 'manuSpecificLegrandDevices',
5025
5095
  type: ['readResponse'],
5026
5096
  convert: (model, msg, publish, options, meta) => {
5027
5097
  const payload = {};
5028
- const option0 = msg.data['0'];
5029
- // Beware that mode depends on device type
5030
- // contactor
5031
- if (option0 === 0x0003) payload.device_mode = 'switch';
5032
- else if (option0 === 0x0004) payload.device_mode = 'auto';
5033
- // dimmer
5034
- else if (option0 === 0x0101) payload.device_mode = 'dimmer_on';
5035
- else if (option0 === 0x0100) payload.device_mode = 'dimmer_off';
5036
- // pilot wire
5037
- else if (option0 === 0x0002) payload.device_mode = 'pilot_on';
5038
- else if (option0 === 0x0001) payload.device_mode = 'pilot_off';
5039
- // unknown case
5040
- else {
5041
- meta.logger.warn(`device_mode ${option0} not recognized, please fix me`);
5042
- payload.device_mode = 'unknown';
5098
+
5099
+ if (msg.data.hasOwnProperty('0')) {
5100
+ const option0 = msg.data['0'];
5101
+
5102
+ if (option0 === 0x0001) payload.device_mode = 'pilot_off';
5103
+ else if (option0 === 0x0002) payload.device_mode = 'pilot_on';
5104
+ else if (option0 === 0x0003) payload.device_mode = 'switch';
5105
+ else if (option0 === 0x0004) payload.device_mode = 'auto';
5106
+ else if (option0 === 0x0100) payload.device_mode = 'dimmer_off';
5107
+ else if (option0 === 0x0101) payload.device_mode = 'dimmer_on';
5108
+ else {
5109
+ meta.logger.warn(`device_mode ${option0} not recognized, please fix me`);
5110
+ payload.device_mode = 'unknown';
5111
+ }
5043
5112
  }
5113
+ if (msg.data.hasOwnProperty('1')) payload.permanent_led = msg.data['1'] === 0x00 ? 'OFF' : 'ON';
5114
+ if (msg.data.hasOwnProperty('2')) payload.led_when_on = msg.data['2'] === 0x00 ? 'OFF' : 'ON';
5044
5115
  return payload;
5045
5116
  },
5046
5117
  },
@@ -5168,8 +5239,16 @@ const converters = {
5168
5239
  aqara_opple: {
5169
5240
  cluster: 'aqaraOpple',
5170
5241
  type: ['attributeReport', 'readResponse'],
5171
- options: [exposes.options.precision('temperature'), exposes.options.calibration('temperature'),
5172
- exposes.options.precision('illuminance'), exposes.options.calibration('illuminance', 'percentual')],
5242
+ options: (definition) => {
5243
+ const result = [];
5244
+ if (definition.exposes.find((e) => e.name === 'temperature')) {
5245
+ result.push(exposes.options.precision('temperature'), exposes.options.calibration('temperature'));
5246
+ }
5247
+ if (definition.exposes.find((e) => e.name === 'illuminance')) {
5248
+ result.push(exposes.options.precision('illuminance'), exposes.options.calibration('illuminance', 'percentual'));
5249
+ }
5250
+ return result;
5251
+ },
5173
5252
  convert: (model, msg, publish, options, meta) => {
5174
5253
  const payload = {};
5175
5254
  if (msg.data.hasOwnProperty('247')) {
@@ -5282,8 +5361,11 @@ const converters = {
5282
5361
  if (index == 1) {
5283
5362
  payload.voltage = value;
5284
5363
  payload.battery = batteryVoltageToPercentage(value, '3V_2100');
5285
- } else if (index === 3) payload.temperature = calibrateAndPrecisionRoundOptions(value, options, 'temperature'); // 0x03
5286
- else if (index === 5) {
5364
+ } else if (index === 3) {
5365
+ if (!['WXCJKG11LM ', 'WXCJKG12LM', 'WXCJKG13LM'].includes(model.model)) {
5366
+ payload.temperature = calibrateAndPrecisionRoundOptions(value, options, 'temperature'); // 0x03
5367
+ }
5368
+ } else if (index === 5) {
5287
5369
  if (['JT-BZ-01AQ/A', 'RTCZCGQ11LM'].includes(model.model)) payload.power_outage_count = value;
5288
5370
  } else if (index === 100) {
5289
5371
  if (['QBKG20LM', 'QBKG31LM', 'QBKG39LM', 'QBKG41LM', 'QBCZ15LM'].includes(model.model)) {
@@ -5315,8 +5397,9 @@ const converters = {
5315
5397
  payload.presence_event = {0: 'enter', 1: 'leave', 2: 'left_enter', 3: 'right_leave', 4: 'right_enter',
5316
5398
  5: 'left_leave', 6: 'approach', 7: 'away', 255: null}[value];
5317
5399
  }
5318
- } else if (index ===103) payload.monitoring_mode = value === 1 ? 'left_right' : 'undirected'; // RTCZCGQ11LM
5319
- else if (index === 105) {
5400
+ } else if (index === 103) {
5401
+ if (['RTCZCGQ11LM'].includes(model.model)) payload.monitoring_mode = value === 1 ? 'left_right' : 'undirected';
5402
+ } else if (index === 105) {
5320
5403
  if (['RTCGQ13LM'].includes(model.model)) {
5321
5404
  payload.motion_sensitivity = {1: 'low', 2: 'medium', 3: 'high'}[value];
5322
5405
  } else if (['RTCZCGQ11LM'].includes(model.model)) {
@@ -2211,7 +2211,7 @@ const converters = {
2211
2211
  key: ['led_disabled_night'],
2212
2212
  convertSet: async (entity, key, value, meta) => {
2213
2213
  if (['ZNCZ04LM', 'ZNCZ15LM', 'QBCZ14LM', 'QBCZ15LM', 'QBKG19LM', 'QBKG20LM', 'QBKG25LM', 'QBKG26LM',
2214
- 'QBKG31LM', 'QBKG34LM', 'DLKZMK11LM'].includes(meta.mapped.model)) {
2214
+ 'QBKG31LM', 'QBKG34LM', 'DLKZMK11LM', 'SSM-U01'].includes(meta.mapped.model)) {
2215
2215
  await entity.write('aqaraOpple', {0x0203: {value: value ? 1 : 0, type: 0x10}}, manufacturerOptions.xiaomi);
2216
2216
  } else if (['ZNCZ11LM'].includes(meta.mapped.model)) {
2217
2217
  const payload = value ?
@@ -2226,7 +2226,7 @@ const converters = {
2226
2226
  },
2227
2227
  convertGet: async (entity, key, meta) => {
2228
2228
  if (['ZNCZ04LM', 'ZNCZ15LM', 'QBCZ15LM', 'QBCZ14LM', 'QBKG19LM', 'QBKG20LM', 'QBKG25LM', 'QBKG26LM',
2229
- 'QBKG31LM', 'QBKG34LM', 'DLKZMK11LM'].includes(meta.mapped.model)) {
2229
+ 'QBKG31LM', 'QBKG34LM', 'DLKZMK11LM', 'SSM-U01'].includes(meta.mapped.model)) {
2230
2230
  await entity.read('aqaraOpple', [0x0203], manufacturerOptions.xiaomi);
2231
2231
  } else {
2232
2232
  throw new Error('Not supported');
@@ -3206,6 +3206,30 @@ const converters = {
3206
3206
  await entity.read('genOnOff', ['moesStartUpOnOff']);
3207
3207
  },
3208
3208
  },
3209
+ moes_switch: {
3210
+ key: ['power_on_behavior', 'indicate_light'],
3211
+ convertSet: async (entity, key, value, meta) => {
3212
+ switch (key) {
3213
+ case 'power_on_behavior':
3214
+ await tuya.sendDataPointEnum(
3215
+ entity,
3216
+ tuya.dataPoints.moesSwitchPowerOnBehavior,
3217
+ utils.getKey(tuya.moesSwitch.powerOnBehavior, value),
3218
+ );
3219
+ break;
3220
+ case 'indicate_light':
3221
+ await tuya.sendDataPointEnum(
3222
+ entity,
3223
+ tuya.dataPoints.moesSwitchIndicateLight,
3224
+ utils.getKey(tuya.moesSwitch.indicateLight, value),
3225
+ );
3226
+ break;
3227
+ default:
3228
+ meta.logger.warn(`toZigbee.moes_switch: Unhandled Key ${key}`);
3229
+ break;
3230
+ }
3231
+ },
3232
+ },
3209
3233
  moes_thermostat_sensor: {
3210
3234
  key: ['sensor'],
3211
3235
  convertSet: async (entity, key, value, meta) => {
@@ -4499,6 +4523,10 @@ const converters = {
4499
4523
  const enableLedIfOn = value === 'ON' || (value === 'OFF' ? false : !!value);
4500
4524
  const payload = {1: {value: enableLedIfOn, type: 16}};
4501
4525
  await entity.write('manuSpecificLegrandDevices', payload, manufacturerOptions.legrand);
4526
+ return {state: {'permanent_led': value}};
4527
+ },
4528
+ convertGet: async (entity, key, meta) => {
4529
+ await entity.read('manuSpecificLegrandDevices', [0x0001], manufacturerOptions.legrand);
4502
4530
  },
4503
4531
  },
4504
4532
  legrand_settingEnableLedIfOn: {
@@ -4510,15 +4538,10 @@ const converters = {
4510
4538
  const enableLedIfOn = value === 'ON' || (value === 'OFF' ? false : !!value);
4511
4539
  const payload = {2: {value: enableLedIfOn, type: 16}};
4512
4540
  await entity.write('manuSpecificLegrandDevices', payload, manufacturerOptions.legrand);
4541
+ return {state: {'led_when_on': value}};
4513
4542
  },
4514
- },
4515
- legrand_settingEnableDimmer: {
4516
- key: ['dimmer_enabled'],
4517
- convertSet: async (entity, key, value, meta) => {
4518
- // enable the dimmer, requires a recent firmware on the device
4519
- const enableDimmer = value === 'ON' || (value === 'OFF' ? false : !!value);
4520
- const payload = {0: {value: enableDimmer ? 0x0101 : 0x0100, type: 9}};
4521
- await entity.write('manuSpecificLegrandDevices', payload, manufacturerOptions.legrand);
4543
+ convertGet: async (entity, key, meta) => {
4544
+ await entity.read('manuSpecificLegrandDevices', [0x0002], manufacturerOptions.legrand);
4522
4545
  },
4523
4546
  },
4524
4547
  legrand_deviceMode: {
@@ -5971,6 +5994,32 @@ const converters = {
5971
5994
  await entity.read('genOnOff', ['tuyaBacklightMode']);
5972
5995
  },
5973
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
+ },
5974
6023
  hy_thermostat: {
5975
6024
  key: [
5976
6025
  'child_lock', 'current_heating_setpoint', 'local_temperature_calibration',
@@ -12,12 +12,12 @@ module.exports = [
12
12
  model: 'K4003C/L4003C/N4003C/NT4003C',
13
13
  vendor: 'BTicino',
14
14
  description: 'Light switch with neutral',
15
- fromZigbee: [fz.identify, fz.on_off, fz.K4003C_binary_input],
15
+ fromZigbee: [fz.identify, fz.on_off, fz.K4003C_binary_input, fz.legrand_cluster_fc01],
16
16
  toZigbee: [tz.on_off, tz.legrand_settingAlwaysEnableLed, tz.legrand_settingEnableLedIfOn, tz.legrand_identify],
17
17
  exposes: [
18
18
  e.switch(), e.action(['identify', 'on', 'off']),
19
- exposes.binary('permanent_led', ea.STATE_SET, 'ON', 'OFF').withDescription('Enable or disable the permanent blue LED'),
20
- exposes.binary('led_when_on', ea.STATE_SET, 'ON', 'OFF').withDescription('Enables the LED when the light is on'),
19
+ exposes.binary('permanent_led', ea.ALL, 'ON', 'OFF').withDescription('Enable or disable the permanent blue LED'),
20
+ exposes.binary('led_when_on', ea.ALL, 'ON', 'OFF').withDescription('Enables the LED when the light is on'),
21
21
  ],
22
22
  configure: async (device, coordinatorEndpoint, logger) => {
23
23
  const endpoint = device.getEndpoint(1);
@@ -30,17 +30,17 @@ module.exports = [
30
30
  vendor: 'BTicino',
31
31
  description: 'Dimmer switch with neutral',
32
32
  extend: extend.light_onoff_brightness({noConfigure: true}),
33
- fromZigbee: [fz.brightness, fz.identify, fz.on_off, fz.lighting_ballast_configuration],
33
+ fromZigbee: [fz.brightness, fz.identify, fz.on_off, fz.lighting_ballast_configuration, fz.legrand_cluster_fc01],
34
34
  toZigbee: [tz.light_onoff_brightness, tz.legrand_settingAlwaysEnableLed, tz.legrand_settingEnableLedIfOn,
35
- tz.legrand_settingEnableDimmer, tz.legrand_identify, tz.ballast_config],
35
+ tz.legrand_deviceMode, tz.legrand_identify, tz.ballast_config],
36
36
  exposes: [e.light_brightness(),
37
37
  exposes.numeric('ballast_minimum_level', ea.ALL).withValueMin(1).withValueMax(254)
38
38
  .withDescription('Specifies the minimum brightness value'),
39
39
  exposes.numeric('ballast_maximum_level', ea.ALL).withValueMin(1).withValueMax(254)
40
40
  .withDescription('Specifies the maximum brightness value'),
41
- exposes.binary('dimmer_enabled', ea.STATE_SET, 'ON', 'OFF').withDescription('Allow the device to change brightness'),
42
- exposes.binary('permanent_led', ea.STATE_SET, 'ON', 'OFF').withDescription('Enable or disable the permanent blue LED'),
43
- exposes.binary('led_when_on', ea.STATE_SET, 'ON', 'OFF').withDescription('Enables the LED when the light is on')],
41
+ exposes.binary('device_mode', ea.ALL, 'dimmer_on', 'dimmer_off').withDescription('Allow the device to change brightness'),
42
+ exposes.binary('permanent_led', ea.ALL, 'ON', 'OFF').withDescription('Enable or disable the permanent blue LED'),
43
+ exposes.binary('led_when_on', ea.ALL, 'ON', 'OFF').withDescription('Enables the LED when the light is on')],
44
44
  configure: async (device, coordinatorEndpoint, logger) => {
45
45
  await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
46
46
  const endpoint = device.getEndpoint(1);
@@ -76,10 +76,10 @@ module.exports = [
76
76
  description: 'DIN power consumption module (same as Legrand 412015)',
77
77
  vendor: 'BTicino',
78
78
  extend: extend.switch(),
79
- fromZigbee: [fz.identify, fz.on_off, fz.electrical_measurement, fz.legrand_device_mode, fz.ignore_basic_report, fz.ignore_genOta],
79
+ fromZigbee: [fz.identify, fz.on_off, fz.electrical_measurement, fz.legrand_cluster_fc01, fz.ignore_basic_report, fz.ignore_genOta],
80
80
  toZigbee: [tz.legrand_deviceMode, tz.on_off, tz.legrand_identify, tz.electrical_measurement_power],
81
81
  exposes: [exposes.switch().withState('state', true, 'On/off (works only if device is in "switch" mode)'),
82
- e.power().withAccess(ea.STATE_GET), exposes.enum( 'device_mode', ea.ALL, ['switch', 'auto'])
82
+ e.power().withAccess(ea.STATE_GET), exposes.enum('device_mode', ea.ALL, ['switch', 'auto'])
83
83
  .withDescription('switch: allow on/off, auto will use wired action via C1/C2 on contactor for example with HC/HP')],
84
84
  configure: async (device, coordinatorEndpoint, logger) => {
85
85
  const endpoint = device.getEndpoint(1);
@@ -375,4 +375,25 @@ 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
+ },
378
399
  ];
@@ -65,7 +65,11 @@ const gledoptoExtend = {
65
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 = [
@@ -122,8 +126,11 @@ module.exports = [
122
126
  vendor: 'Gledopto',
123
127
  ota: ota.zigbeeOTA,
124
128
  description: 'Zigbee LED Controller WW/CW (pro)',
125
- extend: gledoptoExtend.light_onoff_brightness_colortemp(),
126
- configure: configureReadModelID,
129
+ extend: gledoptoExtend.light_onoff_brightness_colortemp({noConfigure: true}),
130
+ configure: async (device, coordinatorEndpoint, logger) => {
131
+ await extend.light_onoff_brightness_colortemp().configure(device, coordinatorEndpoint, logger);
132
+ await configureReadModelID(device, coordinatorEndpoint, logger);
133
+ },
127
134
  },
128
135
  {
129
136
  fingerprint: [
@@ -186,8 +193,11 @@ module.exports = [
186
193
  vendor: 'Gledopto',
187
194
  ota: ota.zigbeeOTA,
188
195
  description: 'Zigbee LED Controller RGBW (pro)',
189
- extend: gledoptoExtend.light_onoff_brightness_colortemp_color(),
190
- configure: configureReadModelID,
196
+ extend: gledoptoExtend.light_onoff_brightness_colortemp_color({noConfigure: true}),
197
+ configure: async (device, coordinatorEndpoint, logger) => {
198
+ await extend.light_onoff_brightness_colortemp_color().configure(device, coordinatorEndpoint, logger);
199
+ await configureReadModelID(device, coordinatorEndpoint, logger);
200
+ },
191
201
  },
192
202
  {
193
203
  fingerprint: [
@@ -245,8 +255,11 @@ module.exports = [
245
255
  vendor: 'Gledopto',
246
256
  ota: ota.zigbeeOTA,
247
257
  description: 'Zigbee LED Controller RGB (pro)',
248
- extend: gledoptoExtend.light_onoff_brightness_color(),
249
- configure: configureReadModelID,
258
+ extend: gledoptoExtend.light_onoff_brightness_color({noConfigure: true}),
259
+ configure: async (device, coordinatorEndpoint, logger) => {
260
+ await extend.light_onoff_brightness_color().configure(device, coordinatorEndpoint, logger);
261
+ await configureReadModelID(device, coordinatorEndpoint, logger);
262
+ },
250
263
  },
251
264
  {
252
265
  zigbeeModel: ['GL-C-008P'],
@@ -254,9 +267,12 @@ module.exports = [
254
267
  vendor: 'Gledopto',
255
268
  ota: ota.zigbeeOTA,
256
269
  description: 'Zigbee LED Controller RGB+CCT (pro)',
257
- extend: gledoptoExtend.light_onoff_brightness_colortemp_color({colorTempRange: [158, 495]}),
270
+ extend: gledoptoExtend.light_onoff_brightness_colortemp_color({colorTempRange: [158, 495], noConfigure: true}),
258
271
  meta: {disableDefaultResponse: true},
259
- configure: configureReadModelID,
272
+ configure: async (device, coordinatorEndpoint, logger) => {
273
+ await extend.light_onoff_brightness_colortemp_color().configure(device, coordinatorEndpoint, logger);
274
+ await configureReadModelID(device, coordinatorEndpoint, logger);
275
+ },
260
276
  },
261
277
  {
262
278
  zigbeeModel: ['GL-C-009'],
@@ -277,8 +293,11 @@ module.exports = [
277
293
  vendor: 'Gledopto',
278
294
  ota: ota.zigbeeOTA,
279
295
  description: 'Zigbee LED Controller W (pro)',
280
- extend: gledoptoExtend.light_onoff_brightness(),
281
- configure: configureReadModelID,
296
+ extend: gledoptoExtend.light_onoff_brightness({noConfigure: true}),
297
+ configure: async (device, coordinatorEndpoint, logger) => {
298
+ await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
299
+ await configureReadModelID(device, coordinatorEndpoint, logger);
300
+ },
282
301
  },
283
302
  {
284
303
  zigbeeModel: ['GL-C-009S'],
package/devices/jasco.js CHANGED
@@ -1,8 +1,10 @@
1
+ const fz = require('../converters/fromZigbee');
1
2
  const reporting = require('../lib/reporting');
2
3
  const extend = require('../lib/extend');
3
4
  const exposes = require('../lib/exposes');
4
5
  const e = exposes.presets;
5
6
 
7
+
6
8
  module.exports = [
7
9
  {
8
10
  zigbeeModel: ['35938'],
@@ -32,4 +34,20 @@ module.exports = [
32
34
  await reporting.instantaneousDemand(endpoint);
33
35
  },
34
36
  },
37
+ {
38
+ zigbeeModel: ['43095'],
39
+ model: '43095',
40
+ vendor: 'Jasco Products',
41
+ description: 'Zigbee smart plug-in switch with energy metering',
42
+ fromZigbee: [fz.command_on_state, fz.command_off_state, fz.metering],
43
+ extend: extend.switch(),
44
+ exposes: [e.switch(), e.power(), e.energy()],
45
+ configure: async (device, coordinatorEndpoint, logger) => {
46
+ const endpoint1 = device.getEndpoint(1);
47
+ await reporting.bind(endpoint1, coordinatorEndpoint, ['genOnOff', 'seMetering']);
48
+ await reporting.onOff(endpoint1);
49
+ await reporting.instantaneousDemand(endpoint1);
50
+ await reporting.readMeteringMultiplierDivisor(endpoint1);
51
+ },
52
+ },
35
53
  ];
@@ -36,10 +36,10 @@ module.exports = [
36
36
  description: 'Legrand (or Bticino) DIN contactor module',
37
37
  vendor: 'Legrand',
38
38
  extend: extend.switch(),
39
- fromZigbee: [fz.identify, fz.on_off, fz.electrical_measurement, fz.legrand_device_mode, fz.ignore_basic_report, fz.ignore_genOta],
39
+ fromZigbee: [fz.identify, fz.on_off, fz.electrical_measurement, fz.legrand_cluster_fc01, fz.ignore_basic_report, fz.ignore_genOta],
40
40
  toZigbee: [tz.legrand_deviceMode, tz.on_off, tz.legrand_identify, tz.electrical_measurement_power],
41
41
  exposes: [exposes.switch().withState('state', true, 'On/off (works only if device is in "switch" mode)'),
42
- e.power().withAccess(ea.STATE_GET), exposes.enum( 'device_mode', ea.ALL, ['switch', 'auto'])
42
+ e.power().withAccess(ea.STATE_GET), exposes.enum('device_mode', ea.ALL, ['switch', 'auto'])
43
43
  .withDescription('switch: allow on/off, auto will use wired action via C1/C2 on contactor for example with HC/HP')],
44
44
  configure: async (device, coordinatorEndpoint, logger) => {
45
45
  const endpoint = device.getEndpoint(1);
@@ -56,10 +56,10 @@ module.exports = [
56
56
  description: 'Legrand (or Bticino) DIN smart relay for light control (note: Legrand 412170 may be similar to Bticino FC80RC)',
57
57
  vendor: 'Legrand',
58
58
  extend: extend.switch(),
59
- fromZigbee: [fz.identify, fz.on_off, fz.electrical_measurement, fz.legrand_device_mode, fz.ignore_basic_report, fz.ignore_genOta],
59
+ fromZigbee: [fz.identify, fz.on_off, fz.electrical_measurement, fz.legrand_cluster_fc01, fz.ignore_basic_report, fz.ignore_genOta],
60
60
  toZigbee: [tz.legrand_deviceMode, tz.on_off, tz.legrand_identify, tz.electrical_measurement_power],
61
61
  exposes: [exposes.switch().withState('state', true, 'On/off (works only if device is in "switch" mode)'),
62
- e.power().withAccess(ea.STATE_GET), exposes.enum( 'device_mode', ea.ALL, ['switch', 'auto'])
62
+ e.power().withAccess(ea.STATE_GET), exposes.enum('device_mode', ea.ALL, ['switch', 'auto'])
63
63
  .withDescription('switch: allow on/off, auto will use wired action via C1/C2 on teleruptor with buttons')],
64
64
  configure: async (device, coordinatorEndpoint, logger) => {
65
65
  const endpoint = device.getEndpoint(1);
@@ -171,20 +171,19 @@ module.exports = [
171
171
  zigbeeModel: [' Dimmer switch w/o neutral\u0000\u0000\u0000\u0000\u0000'],
172
172
  model: '067771',
173
173
  vendor: 'Legrand',
174
- // led blink RED when battery is low
175
174
  description: 'Wired switch without neutral',
176
175
  extend: extend.light_onoff_brightness({noConfigure: true}),
177
- fromZigbee: [fz.brightness, fz.identify, fz.on_off, fz.lighting_ballast_configuration],
176
+ fromZigbee: [fz.brightness, fz.identify, fz.on_off, fz.lighting_ballast_configuration, fz.legrand_cluster_fc01],
178
177
  toZigbee: [tz.light_onoff_brightness, tz.legrand_settingAlwaysEnableLed, tz.legrand_settingEnableLedIfOn,
179
- tz.legrand_settingEnableDimmer, tz.legrand_identify, tz.ballast_config],
178
+ tz.legrand_deviceMode, tz.legrand_identify, tz.ballast_config],
180
179
  exposes: [e.light_brightness(),
181
180
  exposes.numeric('ballast_minimum_level', ea.ALL).withValueMin(1).withValueMax(254)
182
181
  .withDescription('Specifies the minimum brightness value'),
183
182
  exposes.numeric('ballast_maximum_level', ea.ALL).withValueMin(1).withValueMax(254)
184
183
  .withDescription('Specifies the maximum brightness value'),
185
- exposes.binary('dimmer_enabled', ea.STATE_SET, 'ON', 'OFF').withDescription('Allow the device to change brightness'),
186
- exposes.binary('permanent_led', ea.STATE_SET, 'ON', 'OFF').withDescription('Enable or disable the permanent blue LED'),
187
- exposes.binary('led_when_on', ea.STATE_SET, 'ON', 'OFF').withDescription('Enables the LED when the light is on')],
184
+ exposes.binary('device_mode', ea.ALL, 'dimmer_on', 'dimmer_off').withDescription('Allow the device to change brightness'),
185
+ exposes.binary('permanent_led', ea.ALL, 'ON', 'OFF').withDescription('Enable or disable the permanent blue LED'),
186
+ exposes.binary('led_when_on', ea.ALL, 'ON', 'OFF').withDescription('Enables the LED when the light is on')],
188
187
  configure: async (device, coordinatorEndpoint, logger) => {
189
188
  await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
190
189
  const endpoint = device.getEndpoint(1);
@@ -306,9 +305,9 @@ module.exports = [
306
305
  model: '064882',
307
306
  vendor: 'Legrand',
308
307
  description: 'Cable outlet with pilot wire and consumption measurement',
309
- fromZigbee: [fz.legrand_device_mode, fz.legrand_cable_outlet_mode, fz.on_off, fz.electrical_measurement],
308
+ fromZigbee: [fz.legrand_cluster_fc01, fz.legrand_cable_outlet_mode, fz.on_off, fz.electrical_measurement],
310
309
  toZigbee: [tz.legrand_deviceMode, tz.legrand_cableOutletMode, tz.on_off, tz.electrical_measurement_power],
311
- exposes: [exposes.enum('device_mode', ea.ALL, ['pilot_off', 'pilot_on']),
310
+ exposes: [exposes.binary('device_mode', ea.ALL, 'pilot_on', 'pilot_off'),
312
311
  exposes.enum('cable_outlet_mode', ea.ALL, ['comfort', 'comfort-1', 'comfort-2', 'eco', 'frost_protection', 'off']),
313
312
  exposes.switch().withState('state', true, 'Works only when the pilot wire is deactivated'),
314
313
  e.power().withAccess(ea.STATE_GET)],
@@ -320,4 +319,26 @@ module.exports = [
320
319
  await reporting.activePower(endpoint);
321
320
  },
322
321
  },
322
+ {
323
+ zigbeeModel: [' NLIS - Double light switch\u0000\u0000\u0000\u0000'],
324
+ model: '067772',
325
+ vendor: 'Legrand',
326
+ description: 'Double wired switch with neutral',
327
+ fromZigbee: [fz.on_off, fz.legrand_cluster_fc01],
328
+ toZigbee: [tz.on_off, tz.legrand_settingAlwaysEnableLed, tz.legrand_settingEnableLedIfOn],
329
+ exposes: [e.switch().withEndpoint('left'),
330
+ e.switch().withEndpoint('right'),
331
+ exposes.binary('permanent_led', ea.ALL, 'ON', 'OFF').withDescription('Enable or disable the permanent blue LED'),
332
+ exposes.binary('led_when_on', ea.ALL, 'ON', 'OFF').withDescription('Enables the LED when the light is on')],
333
+ meta: {multiEndpoint: true},
334
+ configure: async (device, coordinatorEndpoint, logger) => {
335
+ const endpointLeft = device.getEndpoint(1);
336
+ await reporting.bind(endpointLeft, coordinatorEndpoint, ['genOnOff']);
337
+ const endpointRight = device.getEndpoint(2);
338
+ await reporting.bind(endpointRight, coordinatorEndpoint, ['genOnOff']);
339
+ },
340
+ endpoint: (device) => {
341
+ return {left: 1, right: 2};
342
+ },
343
+ },
323
344
  ];