zigbee-herdsman-converters 14.0.404 → 14.0.408

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.
@@ -2522,8 +2522,8 @@ const converters = {
2522
2522
  return {battpercentage: value};
2523
2523
  case tuya.dataPoints.neoAOMelody: // 0x21 [5] Melody
2524
2524
  return {melody: value};
2525
- case tuya.dataPoints.neoAOVolume: // 0x5 [0]/[1]/[2] Volume 0-max, 2-low
2526
- return {volume: {2: 'low', 1: 'medium', 0: 'high'}[value]};
2525
+ case tuya.dataPoints.neoAOVolume: // 0x5 [0]/[1]/[2] Volume 0-low, 2-max
2526
+ return {volume: {0: 'low', 1: 'medium', 2: 'high'}[value]};
2527
2527
  default: // Unknown code
2528
2528
  meta.logger.warn(`Unhandled DP #${dp}: ${JSON.stringify(msg.data)}`);
2529
2529
  }
@@ -3211,6 +3211,10 @@ const converters = {
3211
3211
  result[postfixWithEndpointName('pi_heating_demand', msg, model)] =
3212
3212
  precisionRound(msg.data['pIHeatingDemand'], 0);
3213
3213
  }
3214
+ if (msg.data.hasOwnProperty('danfossWindowOpenFeatureEnable')) {
3215
+ result[postfixWithEndpointName('window_open_feature', msg, model)] =
3216
+ (msg.data['danfossWindowOpenFeatureEnable'] === 1);
3217
+ }
3214
3218
  if (msg.data.hasOwnProperty('danfossWindowOpenInternal')) {
3215
3219
  result[postfixWithEndpointName('window_open_internal', msg, model)] =
3216
3220
  constants.danfossWindowOpen.hasOwnProperty(msg.data['danfossWindowOpenInternal']) ?
@@ -5029,6 +5033,9 @@ const converters = {
5029
5033
  // dimmer
5030
5034
  else if (option0 === 0x0101) payload.device_mode = 'dimmer_on';
5031
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';
5032
5039
  // unknown case
5033
5040
  else {
5034
5041
  meta.logger.warn(`device_mode ${option0} not recognized, please fix me`);
@@ -5037,6 +5044,26 @@ const converters = {
5037
5044
  return payload;
5038
5045
  },
5039
5046
  },
5047
+ legrand_cable_outlet_mode: {
5048
+ cluster: '64576',
5049
+ type: ['readResponse'],
5050
+ convert: (model, msg, publish, options, meta) => {
5051
+ const payload = {};
5052
+ const mode = msg.data['0'];
5053
+
5054
+ if (mode === 0x00) payload.cable_outlet_mode = 'comfort';
5055
+ else if (mode === 0x01) payload.cable_outlet_mode = 'comfort-1';
5056
+ else if (mode === 0x02) payload.cable_outlet_mode = 'comfort-2';
5057
+ else if (mode === 0x03) payload.cable_outlet_mode = 'eco';
5058
+ else if (mode === 0x04) payload.cable_outlet_mode = 'frost_protection';
5059
+ else if (mode === 0x05) payload.cable_outlet_mode = 'off';
5060
+ else {
5061
+ meta.logger.warn(`Bad mode : ${mode}`);
5062
+ payload.cable_outlet_mode = 'unknown';
5063
+ }
5064
+ return payload;
5065
+ },
5066
+ },
5040
5067
  legrand_power_alarm: {
5041
5068
  cluster: 'haElectricalMeasurement',
5042
5069
  type: ['attributeReport', 'readResponse'],
@@ -5257,13 +5284,16 @@ const converters = {
5257
5284
  payload.battery = batteryVoltageToPercentage(value, '3V_2100');
5258
5285
  } else if (index === 3) payload.temperature = calibrateAndPrecisionRoundOptions(value, options, 'temperature'); // 0x03
5259
5286
  else if (index === 5) {
5260
- if (['JT-BZ-01AQ/A'].includes(model.model)) payload.power_outage_count = value;
5287
+ if (['JT-BZ-01AQ/A', 'RTCZCGQ11LM'].includes(model.model)) payload.power_outage_count = value;
5261
5288
  } else if (index === 100) {
5262
5289
  if (['QBKG20LM', 'QBKG31LM', 'QBKG39LM', 'QBKG41LM', 'QBCZ15LM'].includes(model.model)) {
5263
5290
  const mapping = model.model === 'QBCZ15LM' ? 'relay' : 'left';
5264
5291
  payload[`state_${mapping}`] = value === 1 ? 'ON' : 'OFF';
5265
5292
  } else if (['WXKG14LM', 'WXKG16LM', 'WXKG17LM'].includes(model.model)) {
5266
5293
  payload.click_mode = {1: 'fast', 2: 'multi'}[value];
5294
+ } else if (['WXCJKG11LM ', 'WXCJKG12LM', 'WXCJKG13LM'].includes(model.model)) {
5295
+ // We don't know what the value means for these devices.
5296
+ // https://github.com/Koenkk/zigbee2mqtt/issues/11126
5267
5297
  } else {
5268
5298
  payload.state = value === 1 ? 'ON' : 'OFF';
5269
5299
  }
@@ -5281,9 +5311,18 @@ const converters = {
5281
5311
  } else if (index ===102 ) {
5282
5312
  if (['QBKG25LM', 'QBKG34LM'].includes(model.model)) {
5283
5313
  payload.state_right = value === 1 ? 'ON' : 'OFF';
5314
+ } else if (['RTCZCGQ11LM'].includes(model.model)) {
5315
+ payload.presence_event = {0: 'enter', 1: 'leave', 2: 'left_enter', 3: 'right_leave', 4: 'right_enter',
5316
+ 5: 'left_leave', 6: 'approach', 7: 'away', 255: null}[value];
5317
+ }
5318
+ } else if (index ===103) payload.monitoring_mode = value === 1 ? 'left_right' : 'undirected'; // RTCZCGQ11LM
5319
+ else if (index === 105) {
5320
+ if (['RTCGQ13LM'].includes(model.model)) {
5321
+ payload.motion_sensitivity = {1: 'low', 2: 'medium', 3: 'high'}[value];
5322
+ } else if (['RTCZCGQ11LM'].includes(model.model)) {
5323
+ payload.approach_distance = {0: 'far', 1: 'medium', 2: 'near'}[value];
5284
5324
  }
5285
- } else if (index === 105) payload.motion_sensitivity = {1: 'low', 2: 'medium', 3: 'high'}[value]; // RTCGQ13LM
5286
- else if (index === 149) {
5325
+ } else if (index === 149) {
5287
5326
  payload.energy = precisionRound(value, 2); // 0x95
5288
5327
  // Consumption is deprecated
5289
5328
  payload.consumption = payload.energy;
@@ -5322,6 +5361,15 @@ const converters = {
5322
5361
  if (msg.data.hasOwnProperty('313')) payload.state = msg.data['313'] === 1 ? 'preparation' : 'work'; // JT-BZ-01AQ/A
5323
5362
  if (msg.data.hasOwnProperty('314')) payload.gas = msg.data['314'] === 1; // JT-BZ-01AQ/A
5324
5363
  if (msg.data.hasOwnProperty('315')) payload.gas_density = msg.data['315']; // JT-BZ-01AQ/A
5364
+ if (msg.data.hasOwnProperty('322')) payload.presence = msg.data['322'] === 1; // RTCZCGQ11LM
5365
+ if (msg.data.hasOwnProperty('323')) {
5366
+ payload.presence_event = {0: 'enter', 1: 'leave', 2: 'left_enter', 3: 'right_leave', 4: 'right_enter',
5367
+ 5: 'left_leave', 6: 'approach', 7: 'away'}[msg.data['323']]; // RTCZCGQ11LM
5368
+ }
5369
+ // RTCZCGQ11LM
5370
+ if (msg.data.hasOwnProperty('324')) payload.monitoring_mode = msg.data['324'] === 1 ? 'left_right' : 'undirected';
5371
+ // RTCZCGQ11LM
5372
+ if (msg.data.hasOwnProperty('326')) payload.approach_distance = {0: 'far', 1: 'medium', 2: 'near'}[msg.data['326']];
5325
5373
  if (msg.data.hasOwnProperty('331')) payload.linkage_alarm = msg.data['331'] === 1; // JT-BZ-01AQ/A
5326
5374
  if (msg.data.hasOwnProperty('512')) {
5327
5375
  if (['ZNCZ15LM', 'QBCZ14LM', 'QBCZ15LM'].includes(model.model)) {
@@ -8194,7 +8242,7 @@ const converters = {
8194
8242
  cluster: 'genOnOff',
8195
8243
  type: 'raw',
8196
8244
  convert: (model, msg, publish, options, meta) => {
8197
- if (hasAlreadyProcessedMessage(msg, msg.data[2])) return;
8245
+ if (hasAlreadyProcessedMessage(msg, msg.data[1])) return;
8198
8246
  let action;
8199
8247
  if (msg.data[2] == 253) {
8200
8248
  action = {0: 'single', 1: 'double', 2: 'hold'}[msg.data[3]];
@@ -54,6 +54,14 @@ const converters = {
54
54
  meta.logger.info(`Wrote '${JSON.stringify(value.payload)}' to '${value.cluster}'`);
55
55
  },
56
56
  },
57
+ command: {
58
+ key: ['command'],
59
+ convertSet: async (entity, key, value, meta) => {
60
+ const options = utils.getOptions(meta.mapped, entity);
61
+ await entity.command(value.cluster, value.command, (value.hasOwnProperty('payload') ? value.payload : {}), options);
62
+ meta.logger.info(`Invoked '${value.cluster}.${value.command}' with payload '${JSON.stringify(value.payload)}'`);
63
+ },
64
+ },
57
65
  factory_reset: {
58
66
  key: ['reset'],
59
67
  convertSet: async (entity, key, value, meta) => {
@@ -2006,6 +2014,36 @@ const converters = {
2006
2014
  await entity.read('aqaraOpple', [0x010c], manufacturerOptions.xiaomi);
2007
2015
  },
2008
2016
  },
2017
+ RTCZCGQ11LM_presence: {
2018
+ key: ['presence'],
2019
+ convertGet: async (entity, key, meta) => {
2020
+ await entity.read('aqaraOpple', [0x0142], manufacturerOptions.xiaomi);
2021
+ },
2022
+ },
2023
+ RTCZCGQ11LM_monitoring_mode: {
2024
+ key: ['monitoring_mode'],
2025
+ convertSet: async (entity, key, value, meta) => {
2026
+ value = value.toLowerCase();
2027
+ const lookup = {'undirected': 0, 'left_right': 1};
2028
+ await entity.write('aqaraOpple', {0x0144: {value: lookup[value], type: 0x20}}, manufacturerOptions.xiaomi);
2029
+ return {state: {monitoring_mode: value}};
2030
+ },
2031
+ convertGet: async (entity, key, meta) => {
2032
+ await entity.read('aqaraOpple', [0x0144], manufacturerOptions.xiaomi);
2033
+ },
2034
+ },
2035
+ RTCZCGQ11LM_approach_distance: {
2036
+ key: ['approach_distance'],
2037
+ convertSet: async (entity, key, value, meta) => {
2038
+ value = value.toLowerCase();
2039
+ const lookup = {'far': 0, 'medium': 1, 'near': 2};
2040
+ await entity.write('aqaraOpple', {0x0146: {value: lookup[value], type: 0x20}}, manufacturerOptions.xiaomi);
2041
+ return {state: {approach_distance: value}};
2042
+ },
2043
+ convertGet: async (entity, key, meta) => {
2044
+ await entity.read('aqaraOpple', [0x0146], manufacturerOptions.xiaomi);
2045
+ },
2046
+ },
2009
2047
  ZigUP_lock: {
2010
2048
  key: ['led'],
2011
2049
  convertSet: async (entity, key, value, meta) => {
@@ -2040,7 +2078,7 @@ const converters = {
2040
2078
  convertSet: async (entity, key, value, meta) => {
2041
2079
  if (['ZNCZ04LM', 'ZNCZ15LM', 'QBCZ14LM', 'QBCZ15LM', 'SSM-U01', 'SSM-U02', 'DLKZMK11LM', 'DLKZMK12LM',
2042
2080
  'WS-EUK01', 'WS-EUK02', 'WS-EUK03', 'WS-EUK04', 'QBKG19LM', 'QBKG20LM', 'QBKG25LM', 'QBKG26LM',
2043
- 'QBKG31LM', 'QBKG34LM', 'QBKG38LM', 'QBKG39LM', 'QBKG40LM', 'QBKG41LM'].includes(meta.mapped.model)) {
2081
+ 'QBKG31LM', 'QBKG34LM', 'QBKG38LM', 'QBKG39LM', 'QBKG40LM', 'QBKG41LM', 'ZNDDMK11LM'].includes(meta.mapped.model)) {
2044
2082
  await entity.write('aqaraOpple', {0x0201: {value: value ? 1 : 0, type: 0x10}}, manufacturerOptions.xiaomi);
2045
2083
  } else if (['ZNCZ02LM', 'QBCZ11LM'].includes(meta.mapped.model)) {
2046
2084
  const payload = value ?
@@ -2063,7 +2101,7 @@ const converters = {
2063
2101
  convertGet: async (entity, key, meta) => {
2064
2102
  if (['ZNCZ04LM', 'ZNCZ15LM', 'QBCZ14LM', 'QBCZ15LM', 'SSM-U01', 'SSM-U02', 'DLKZMK11LM', 'DLKZMK12LM',
2065
2103
  'WS-EUK01', 'WS-EUK02', 'WS-EUK03', 'WS-EUK04', 'QBKG19LM', 'QBKG20LM', 'QBKG25LM', 'QBKG26LM',
2066
- 'QBKG31LM', 'QBKG34LM', 'QBKG38LM', 'QBKG39LM', 'QBKG40LM', 'QBKG41LM'].includes(meta.mapped.model)) {
2104
+ 'QBKG31LM', 'QBKG34LM', 'QBKG38LM', 'QBKG39LM', 'QBKG40LM', 'QBKG41LM', 'ZNDDMK11LM'].includes(meta.mapped.model)) {
2067
2105
  await entity.read('aqaraOpple', [0x0201]);
2068
2106
  } else if (['ZNCZ02LM', 'QBCZ11LM', 'ZNCZ11LM'].includes(meta.mapped.model)) {
2069
2107
  await entity.read('aqaraOpple', [0xFFF0]);
@@ -2714,6 +2752,16 @@ const converters = {
2714
2752
  await entity.read('hvacThermostat', ['danfossTriggerTime'], manufacturerOptions.danfoss);
2715
2753
  },
2716
2754
  },
2755
+ danfoss_window_open_feature: {
2756
+ key: ['window_open_feature'],
2757
+ convertSet: async (entity, key, value, meta) => {
2758
+ await entity.write('hvacThermostat', {'danfossWindowOpenFeatureEnable': value}, manufacturerOptions.danfoss);
2759
+ return {readAfterWriteTime: 200, state: {'window_open_feature': value}};
2760
+ },
2761
+ convertGet: async (entity, key, meta) => {
2762
+ await entity.read('hvacThermostat', ['danfossWindowOpenFeatureEnable'], manufacturerOptions.danfoss);
2763
+ },
2764
+ },
2717
2765
  danfoss_window_open_internal: {
2718
2766
  key: ['window_open_internal'],
2719
2767
  convertGet: async (entity, key, meta) => {
@@ -4490,6 +4538,9 @@ const converters = {
4490
4538
  // contactor
4491
4539
  'switch': 0x0003,
4492
4540
  'auto': 0x0004,
4541
+ // pilot wire
4542
+ 'pilot_on': 0x0002,
4543
+ 'pilot_off': 0x0001,
4493
4544
  };
4494
4545
 
4495
4546
  value = value.toLowerCase();
@@ -4502,6 +4553,15 @@ const converters = {
4502
4553
  await entity.read('manuSpecificLegrandDevices', [0x0000, 0x0001, 0x0002], manufacturerOptions.legrand);
4503
4554
  },
4504
4555
  },
4556
+ legrand_cableOutletMode: {
4557
+ key: ['cable_outlet_mode'],
4558
+ convertSet: async (entity, key, value, meta) => {
4559
+ meta.logger.warn('Feature under development !');
4560
+ },
4561
+ convertGet: async (entity, key, meta) => {
4562
+ await entity.read(64576, [0x0000], manufacturerOptions.legrand);
4563
+ },
4564
+ },
4505
4565
  legrand_powerAlarm: {
4506
4566
  key: ['power_alarm'],
4507
4567
  convertSet: async (entity, key, value, meta) => {
@@ -6709,7 +6769,7 @@ const converters = {
6709
6769
  await tuya.sendDataPoints(entity, [
6710
6770
  tuya.dpValueFromEnum(tuya.dataPoints.silvercrestChangeMode, tuya.silvercrestModes.white),
6711
6771
  tuya.dpValueFromIntValue(tuya.dataPoints.dimmerLevel, newValue),
6712
- ], 'dataRequest', 1);
6772
+ ], 'dataRequest');
6713
6773
 
6714
6774
  return {state: (key == 'white_brightness') ? {white_brightness: value} : {brightness: value}};
6715
6775
  } else if (key == 'color_temp') {
@@ -6736,7 +6796,7 @@ const converters = {
6736
6796
  await tuya.sendDataPoints(entity, [
6737
6797
  tuya.dpValueFromEnum(tuya.dataPoints.silvercrestChangeMode, tuya.silvercrestModes.white),
6738
6798
  tuya.dpValueFromIntValue(tuya.dataPoints.silvercrestSetColorTemp, data),
6739
- ], 'dataRequest', 1);
6799
+ ], 'dataRequest');
6740
6800
 
6741
6801
  return {state: {color_temp: value}};
6742
6802
  } else if (key == 'color' || (separateWhite && (key == 'brightness'))) {
@@ -6815,13 +6875,7 @@ const converters = {
6815
6875
  tuya.dpValueFromStringBuffer(tuya.dataPoints.silvercrestSetColor, data),
6816
6876
  ];
6817
6877
 
6818
- if (separateWhite && meta.state.white_brightness != undefined) {
6819
- // restore white state
6820
- const newValue = utils.mapNumberRange(meta.state.white_brightness, 0, 255, 0, 1000);
6821
- commands.push(tuya.dpValueFromEnum(tuya.dataPoints.silvercrestChangeMode, tuya.silvercrestModes.white));
6822
- commands.push(tuya.dpValueFromIntValue(tuya.dataPoints.dimmerLevel, newValue));
6823
- }
6824
- await tuya.sendDataPoints(entity, commands, 'dataRequest', 1);
6878
+ await tuya.sendDataPoints(entity, commands, 'dataRequest');
6825
6879
 
6826
6880
  return {state: newState};
6827
6881
  }
package/devices/acova.js CHANGED
@@ -3,33 +3,64 @@ const fz = require('../converters/fromZigbee');
3
3
  const tz = require('../converters/toZigbee');
4
4
  const reporting = require('../lib/reporting');
5
5
 
6
- module.exports = [{
7
- zigbeeModel: ['PERCALE2 D1.00P1.01Z1.00'],
8
- model: 'PERCALE2',
9
- vendor: 'Acova',
10
- description: 'Percale 2 heater',
11
- fromZigbee: [fz.thermostat, fz.hvac_user_interface],
12
- toZigbee: [
13
- tz.thermostat_local_temperature,
14
- tz.thermostat_system_mode,
15
- tz.thermostat_occupied_heating_setpoint,
16
- tz.thermostat_unoccupied_heating_setpoint,
17
- tz.thermostat_occupied_cooling_setpoint,
18
- tz.thermostat_running_state,
19
- ],
20
- exposes: [
21
- exposes.climate()
22
- .withSetpoint('occupied_heating_setpoint', 7, 28, 0.5)
23
- .withLocalTemperature()
24
- .withSystemMode(['off', 'heat', 'auto'])
25
- .withRunningState(['idle', 'heat']),
26
- ],
27
- configure: async (device, coordinatorEndpoint, logger) => {
28
- const endpoint = device.getEndpoint(1);
29
- await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'hvacThermostat']);
30
- await reporting.thermostatTemperature(endpoint);
31
- await reporting.thermostatRunningState(endpoint);
32
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
33
- await reporting.thermostatUnoccupiedHeatingSetpoint(endpoint);
6
+ module.exports = [
7
+ {
8
+ zigbeeModel: ['PERCALE2 D1.00P1.01Z1.00'],
9
+ model: 'PERCALE2',
10
+ vendor: 'Acova',
11
+ description: 'Percale 2 heater',
12
+ fromZigbee: [fz.thermostat, fz.hvac_user_interface],
13
+ toZigbee: [
14
+ tz.thermostat_local_temperature,
15
+ tz.thermostat_system_mode,
16
+ tz.thermostat_occupied_heating_setpoint,
17
+ tz.thermostat_unoccupied_heating_setpoint,
18
+ tz.thermostat_occupied_cooling_setpoint,
19
+ tz.thermostat_running_state,
20
+ ],
21
+ exposes: [
22
+ exposes.climate()
23
+ .withSetpoint('occupied_heating_setpoint', 7, 28, 0.5)
24
+ .withLocalTemperature()
25
+ .withSystemMode(['off', 'heat', 'auto'])
26
+ .withRunningState(['idle', 'heat']),
27
+ ],
28
+ configure: async (device, coordinatorEndpoint, logger) => {
29
+ const endpoint = device.getEndpoint(1);
30
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'hvacThermostat']);
31
+ await reporting.thermostatTemperature(endpoint);
32
+ await reporting.thermostatRunningState(endpoint);
33
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
34
+ await reporting.thermostatUnoccupiedHeatingSetpoint(endpoint);
35
+ },
34
36
  },
35
- }];
37
+ {
38
+ zigbeeModel: ['ALCANTARA2 D1.00P1.02Z1.00\u0000\u0000\u0000\u0000\u0000\u0000'],
39
+ model: 'ALCANTARA2',
40
+ vendor: 'Acova',
41
+ description: 'Alcantara 2 heater',
42
+ fromZigbee: [fz.thermostat, fz.hvac_user_interface],
43
+ toZigbee: [
44
+ tz.thermostat_local_temperature,
45
+ tz.thermostat_system_mode,
46
+ tz.thermostat_occupied_heating_setpoint,
47
+ tz.thermostat_unoccupied_heating_setpoint,
48
+ tz.thermostat_running_state,
49
+ ],
50
+ exposes: [
51
+ exposes.climate()
52
+ .withSetpoint('occupied_heating_setpoint', 7, 28, 0.5)
53
+ .withLocalTemperature()
54
+ .withSystemMode(['off', 'heat', 'auto'])
55
+ .withRunningState(['idle', 'heat']),
56
+ ],
57
+ configure: async (device, coordinatorEndpoint, logger) => {
58
+ const endpoint = device.getEndpoint(1);
59
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'hvacThermostat']);
60
+ await reporting.thermostatTemperature(endpoint);
61
+ await reporting.thermostatRunningState(endpoint);
62
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
63
+ await reporting.thermostatUnoccupiedHeatingSetpoint(endpoint);
64
+ },
65
+ },
66
+ ];
@@ -22,7 +22,8 @@ module.exports = [
22
22
  tz.danfoss_window_open_internal, tz.danfoss_window_open_external, tz.danfoss_load_estimate,
23
23
  tz.danfoss_viewing_direction, tz.danfoss_external_measured_room_sensor, tz.danfoss_radiator_covered,
24
24
  tz.thermostat_keypad_lockout, tz.thermostat_system_mode, tz.danfoss_load_balancing_enable, tz.danfoss_load_room_mean,
25
- tz.thermostat_weekly_schedule, tz.thermostat_clear_weekly_schedule, tz.thermostat_programming_operation_mode],
25
+ tz.thermostat_weekly_schedule, tz.thermostat_clear_weekly_schedule, tz.thermostat_programming_operation_mode,
26
+ tz.danfoss_window_open_feature],
26
27
  exposes: [e.battery(), e.keypad_lockout(), e.programming_operation_mode(),
27
28
  exposes.binary('mounted_mode_active', ea.STATE_GET, true, false)
28
29
  .withDescription('Is the unit in mounting mode. This is set to `false` for mounted (already on ' +
@@ -53,6 +54,8 @@ module.exports = [
53
54
  exposes.binary('radiator_covered', ea.ALL, true, false)
54
55
  .withDescription('Set if the TRV should solely rely on external_measured_room_sensor or operate in offset mode. ' +
55
56
  '`false` = Auto Offset Mode or `true` = Room Sensor Mode'),
57
+ exposes.binary('window_open_feature', ea.ALL, true, false)
58
+ .withDescription('Whether or not the window open feature is enabled'),
56
59
  exposes.numeric('window_open_internal', ea.STATE_GET).withValueMin(0).withValueMax(4)
57
60
  .withDescription('0=Quarantine, 1=Windows are closed, 2=Hold - Windows are maybe about to open, ' +
58
61
  '3=Open window detected, 4=In window open state from external but detected closed locally'),
@@ -114,6 +117,7 @@ module.exports = [
114
117
  }], options);
115
118
 
116
119
  await endpoint.read('hvacThermostat', [
120
+ 'danfossWindowOpenFeatureEnable',
117
121
  'danfossWindowOpenExternal',
118
122
  'danfossDayOfWeek',
119
123
  'danfossTriggerTime',
@@ -62,6 +62,12 @@ const gledoptoExtend = {
62
62
  }),
63
63
  };
64
64
 
65
+ const configureReadModelID = async (device, coordinatorEndpoint, logger) => {
66
+ // https://github.com/Koenkk/zigbee-herdsman-converters/issues/3016#issuecomment-1027726604
67
+ const endpoint = device.endpoints[0];
68
+ await endpoint.read('genBasic', ['modelId']);
69
+ };
70
+
65
71
  module.exports = [
66
72
  {
67
73
  fingerprint: [
@@ -117,6 +123,7 @@ module.exports = [
117
123
  ota: ota.zigbeeOTA,
118
124
  description: 'Zigbee LED Controller WW/CW (pro)',
119
125
  extend: gledoptoExtend.light_onoff_brightness_colortemp(),
126
+ configure: configureReadModelID,
120
127
  },
121
128
  {
122
129
  fingerprint: [
@@ -180,6 +187,7 @@ module.exports = [
180
187
  ota: ota.zigbeeOTA,
181
188
  description: 'Zigbee LED Controller RGBW (pro)',
182
189
  extend: gledoptoExtend.light_onoff_brightness_colortemp_color(),
190
+ configure: configureReadModelID,
183
191
  },
184
192
  {
185
193
  fingerprint: [
@@ -231,6 +239,15 @@ module.exports = [
231
239
  extend: gledoptoExtend.light_onoff_brightness_colortemp_color(),
232
240
  meta: {disableDefaultResponse: true},
233
241
  },
242
+ {
243
+ zigbeeModel: ['GL-C-003P'],
244
+ model: 'GL-C-003P',
245
+ vendor: 'Gledopto',
246
+ ota: ota.zigbeeOTA,
247
+ description: 'Zigbee LED Controller RGB (pro)',
248
+ extend: gledoptoExtend.light_onoff_brightness_color(),
249
+ configure: configureReadModelID,
250
+ },
234
251
  {
235
252
  zigbeeModel: ['GL-C-008P'],
236
253
  model: 'GL-C-008P',
@@ -239,6 +256,7 @@ module.exports = [
239
256
  description: 'Zigbee LED Controller RGB+CCT (pro)',
240
257
  extend: gledoptoExtend.light_onoff_brightness_colortemp_color({colorTempRange: [158, 495]}),
241
258
  meta: {disableDefaultResponse: true},
259
+ configure: configureReadModelID,
242
260
  },
243
261
  {
244
262
  zigbeeModel: ['GL-C-009'],
@@ -260,6 +278,7 @@ module.exports = [
260
278
  ota: ota.zigbeeOTA,
261
279
  description: 'Zigbee LED Controller W (pro)',
262
280
  extend: gledoptoExtend.light_onoff_brightness(),
281
+ configure: configureReadModelID,
263
282
  },
264
283
  {
265
284
  zigbeeModel: ['GL-C-009S'],
@@ -36,7 +36,7 @@ module.exports = [
36
36
  exposes: [e.lock(), e.battery()],
37
37
  },
38
38
  {
39
- zigbeeModel: ['SMARTCODE_DEADBOLT_10_W3'],
39
+ zigbeeModel: ['SMARTCODE_DEADBOLT_10_W3', 'SMARTCODE_DEADBOLT_10T_W3'],
40
40
  model: '99140-031',
41
41
  vendor: 'Kwikset',
42
42
  description: 'SmartCode traditional electronic deadbolt',
@@ -6,6 +6,7 @@ const extend = require('../lib/extend');
6
6
  const e = exposes.presets;
7
7
  const ea = exposes.access;
8
8
  const ota = require('../lib/ota');
9
+ const utils = require('../lib/utils');
9
10
 
10
11
  const readInitialBatteryState = async (type, data, device) => {
11
12
  if (['deviceAnnounce'].includes(type)) {
@@ -20,7 +21,9 @@ const fzLocal = {
20
21
  cluster: 'genOnOff',
21
22
  type: 'commandOff',
22
23
  convert: (model, msg, publish, options, meta) => {
23
- return {action: 'off'};
24
+ const payload = {action: utils.postfixWithEndpointName('off', msg, model)};
25
+ utils.addActionGroup(payload, msg, model);
26
+ return payload;
24
27
  },
25
28
  },
26
29
  };
@@ -297,4 +300,24 @@ module.exports = [
297
300
  toZigbee: [],
298
301
  exposes: [e.action(['press_once', 'press_twice'])],
299
302
  },
303
+ {
304
+ zigbeeModel: [' Cable outlet\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000' +
305
+ '\u0000\u0000'],
306
+ model: '064882',
307
+ vendor: 'Legrand',
308
+ 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],
310
+ 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']),
312
+ exposes.enum('cable_outlet_mode', ea.ALL, ['comfort', 'comfort-1', 'comfort-2', 'eco', 'frost_protection', 'off']),
313
+ exposes.switch().withState('state', true, 'Works only when the pilot wire is deactivated'),
314
+ e.power().withAccess(ea.STATE_GET)],
315
+ configure: async (device, coordinatorEndpoint, logger) => {
316
+ const endpoint = device.getEndpoint(1);
317
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 64576]);
318
+ await reporting.onOff(endpoint);
319
+ await reporting.readEletricalMeasurementMultiplierDivisors(endpoint);
320
+ await reporting.activePower(endpoint);
321
+ },
322
+ },
300
323
  ];
@@ -87,6 +87,14 @@ module.exports = [
87
87
  extend: extend.light_onoff_brightness_colortemp_color(),
88
88
  toZigbee: extend.light_onoff_brightness_colortemp_color().toZigbee.concat([tz.tint_scene]),
89
89
  },
90
+ {
91
+ fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3210_mntza0sw'}],
92
+ model: '404062',
93
+ vendor: 'Müller Licht',
94
+ description: 'Kea RGB+CCT',
95
+ extend: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
96
+ toZigbee: extend.light_onoff_brightness_colortemp_color().toZigbee.concat([tz.tint_scene]),
97
+ },
90
98
  {
91
99
  zigbeeModel: ['ZBT-Remote-ALL-RGBW'],
92
100
  model: 'MLI-404011',