zigbee-herdsman-converters 14.0.296 → 14.0.300

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.
@@ -3024,6 +3024,12 @@ const converters = {
3024
3024
  result[postfixWithEndpointName('running_state', msg, model)] = 'idle';
3025
3025
  }
3026
3026
  }
3027
+ if (msg.data.hasOwnProperty('danfossLoadBalancingEnable')) {
3028
+ result[postfixWithEndpointName('load_balancing_enable', msg, model)] = (msg.data['danfossLoadBalancingEnable'] === 1);
3029
+ }
3030
+ if (msg.data.hasOwnProperty('danfossLoadRoomMean')) {
3031
+ result[postfixWithEndpointName('load_room_mean', msg, model)] = msg.data['danfossLoadRoomMean'];
3032
+ }
3027
3033
  if (msg.data.hasOwnProperty('danfossLoadEstimate')) {
3028
3034
  result[postfixWithEndpointName('load_estimate', msg, model)] = msg.data['danfossLoadEstimate'];
3029
3035
  }
@@ -3532,6 +3538,121 @@ const converters = {
3532
3538
  }
3533
3539
  },
3534
3540
  },
3541
+ haozee_thermostat: {
3542
+ cluster: 'manuSpecificTuya',
3543
+ type: ['commandGetData', 'commandSetDataResponse'],
3544
+ convert: (model, msg, publish, options, meta) => {
3545
+ const dp = msg.data.dp; // First we get the data point ID
3546
+ const value = tuya.getDataValue(msg.data.datatype, msg.data.data);
3547
+ const presetLookup = {0: 'auto', 1: 'manual', 2: 'off', 3: 'on'};
3548
+ switch (dp) {
3549
+ case tuya.dataPoints.haozeeSystemMode:
3550
+ return {preset: presetLookup[value]};
3551
+ case tuya.dataPoints.haozeeHeatingSetpoint:
3552
+ return {current_heating_setpoint: (value / 10).toFixed(1)};
3553
+ case tuya.dataPoints.haozeeLocalTemp:
3554
+ return {local_temperature: (value / 10).toFixed(1)};
3555
+ case tuya.dataPoints.haozeeBoostHeatingCountdown:
3556
+ // quick heating countdown
3557
+ return {boost_heating_countdown: value};
3558
+ case tuya.dataPoints.haozeeWindowDetection:
3559
+ // window check
3560
+ return {window_detection: value ? 'ON' : 'OFF'};
3561
+ case tuya.dataPoints.haozeeWindowState:
3562
+ // window state
3563
+ return {window: value ? 'OPEN' : 'CLOSED'};
3564
+ case tuya.dataPoints.haozeeChildLock:
3565
+ return {child_lock: value ? 'LOCK' : 'UNLOCK'};
3566
+ case tuya.dataPoints.haozeeBattery:
3567
+ // battery
3568
+ return {battery: value};
3569
+ case tuya.dataPoints.haozeeFaultAlarm:
3570
+ return {error: value ? 'ON': 'OFF'};
3571
+ case tuya.dataPoints.haozeeScheduleMonday:
3572
+ // Monday
3573
+ return {
3574
+ 'monday_schedule': ' ' + value[1] + 'h:' + value[2] + 'm ' + value[4] / 10 + '°C' +
3575
+ ', ' + value[5] + 'h:' + value[6] + 'm ' + value[8] / 10 + '°C' +
3576
+ ', ' + value[9] + 'h:' + value[10] + 'm ' + value[12] / 10 + '°C' +
3577
+ ', ' + value[13] + 'h:' + value[14] + 'm ' + value[16] / 10 + '°C ',
3578
+ };
3579
+ case tuya.dataPoints.haozeeScheduleTuesday:
3580
+ // Tuesday
3581
+ return {
3582
+ 'tuesday_schedule': ' ' + value[1] + 'h:' + value[2] + 'm ' + value[4] / 10 + '°C' +
3583
+ ', ' + value[5] + 'h:' + value[6] + 'm ' + value[8] / 10 + '°C' +
3584
+ ', ' + value[9] + 'h:' + value[10] + 'm ' + value[12] / 10 + '°C' +
3585
+ ', ' + value[13] + 'h:' + value[14] + 'm ' + value[16] / 10 + '°C ',
3586
+ };
3587
+ case tuya.dataPoints.haozeeScheduleWednesday:
3588
+ // wednesday
3589
+ return {
3590
+ 'wednesday_schedule': ' ' + value[1] + 'h:' + value[2] + 'm ' + value[4] / 10 + '°C' +
3591
+ ', ' + value[5] + 'h:' + value[6] + 'm ' + value[8] / 10 + '°C' +
3592
+ ', ' + value[9] + 'h:' + value[10] + 'm ' + value[12] / 10 + '°C' +
3593
+ ', ' + value[13] + 'h:' + value[14] + 'm ' + value[16] / 10 + '°C ',
3594
+ };
3595
+ case tuya.dataPoints.haozeeScheduleThursday:
3596
+ // Thursday
3597
+ return {
3598
+ 'thursday_schedule': ' ' + value[1] + 'h:' + value[2] + 'm ' + value[4] / 10 + '°C' +
3599
+ ', ' + value[5] + 'h:' + value[6] + 'm ' + value[8] / 10 + '°C' +
3600
+ ', ' + value[9] + 'h:' + value[10] + 'm ' + value[12] / 10 + '°C' +
3601
+ ', ' + value[13] + 'h:' + value[14] + 'm ' + value[16] / 10 + '°C ',
3602
+ };
3603
+ case tuya.dataPoints.haozeeScheduleFriday:
3604
+ // Friday
3605
+ return {
3606
+ 'friday_schedule': ' ' + value[1] + 'h:' + value[2] + 'm ' + value[4] / 10 + '°C' +
3607
+ ', ' + value[5] + 'h:' + value[6] + 'm ' + value[8] / 10 + '°C' +
3608
+ ', ' + value[9] + 'h:' + value[10] + 'm ' + value[12] / 10 + '°C' +
3609
+ ', ' + value[13] + 'h:' + value[14] + 'm ' + value[16] / 10 + '°C ',
3610
+ };
3611
+ case tuya.dataPoints.haozeeScheduleSaturday:
3612
+ // Saturday
3613
+ return {
3614
+ 'saturday_schedule': ' ' + value[1] + 'h:' + value[2] + 'm ' + value[4] / 10 + '°C' +
3615
+ ', ' + value[5] + 'h:' + value[6] + 'm ' + value[8] / 10 + '°C' +
3616
+ ', ' + value[9] + 'h:' + value[10] + 'm ' + value[12] / 10 + '°C' +
3617
+ ', ' + value[13] + 'h:' + value[14] + 'm ' + value[16] / 10 + '°C ',
3618
+ };
3619
+ case tuya.dataPoints.haozeeScheduleSunday:
3620
+
3621
+ // Sunday
3622
+ return {
3623
+ 'sunday_schedule': ' ' + value[1] + 'h:' + value[2] + 'm ' + value[4] / 10 + '°C' +
3624
+ ', ' + value[5] + 'h:' + value[6] + 'm ' + value[8] / 10 + '°C' +
3625
+ ', ' + value[9] + 'h:' + value[10] + 'm ' + value[12] / 10 + '°C' +
3626
+ ', ' + value[13] + 'h:' + value[14] + 'm ' + value[16] / 10 + '°C ',
3627
+ };
3628
+
3629
+ case tuya.dataPoints.haozeeRunningState:
3630
+ // working status 0 - pause 1 -working
3631
+ return {'heating': value ? 'ON' : 'OFF'};
3632
+ case tuya.dataPoints.haozeeBoostHeating:
3633
+ // rapid heating -> boolean
3634
+ break;
3635
+ case tuya.dataPoints.haozeeTempCalibration:
3636
+ // temperature calibration
3637
+ break;
3638
+ case tuya.dataPoints.haozeeValvePosition:
3639
+ // valve position
3640
+ return {'position': value};
3641
+ case tuya.dataPoints.haozeeMinTemp:
3642
+ // lower limit temperature
3643
+ return {'min_temperature': ( value/10 ).toFixed(1)};
3644
+ case tuya.dataPoints.haozeeMaxTemp:
3645
+ // max limit temperature
3646
+ return {'max_temperature': ( value/10 ).toFixed(1)};
3647
+ case tuya.dataPoints.haozeeSoftVersion:
3648
+ // software
3649
+ break;
3650
+ default:
3651
+ meta.logger.warn(`zigbee-herdsman-converters:haozee: NOT RECOGNIZED DP #${
3652
+ dp} with data ${JSON.stringify(msg.data)}`);
3653
+ }
3654
+ },
3655
+ },
3535
3656
  tuya_air_quality: {
3536
3657
  cluster: 'manuSpecificTuya',
3537
3658
  type: ['commandSetDataResponse', 'commandGetData'],
@@ -1954,7 +1954,7 @@ const converters = {
1954
1954
  convertSet: async (entity, key, value, meta) => {
1955
1955
  if (['ZNCZ04LM', 'QBKG25LM', 'SSM-U01', 'SSM-U02', 'DLKZMK11LM', 'QBKG39LM', 'QBKG41LM', 'ZNCZ15LM',
1956
1956
  'WS-EUK01', 'WS-EUK02', 'WS-EUK03', 'WS-EUK04', 'QBKG31LM', 'QBCZ15LM', 'QBKG20LM', 'QBKG38LM',
1957
- 'QBKG34LM', 'QBCZ14LM'].includes(meta.mapped.model)) {
1957
+ 'QBKG34LM', 'QBCZ14LM', 'QBKG19LM'].includes(meta.mapped.model)) {
1958
1958
  await entity.write('aqaraOpple', {0x0201: {value: value ? 1 : 0, type: 0x10}}, manufacturerOptions.xiaomi);
1959
1959
  } else if (['ZNCZ02LM', 'QBCZ11LM'].includes(meta.mapped.model)) {
1960
1960
  const payload = value ?
@@ -1976,7 +1976,7 @@ const converters = {
1976
1976
  },
1977
1977
  convertGet: async (entity, key, meta) => {
1978
1978
  if (['ZNCZ04LM', 'QBKG25LM', 'SSM-U01', 'SSM-U02', 'DLKZMK11LM', 'QBKG39LM', 'QBKG41LM', 'ZNCZ15LM',
1979
- 'WS-EUK02', 'WS-EUK01', 'QBKG31LM', 'QBCZ15LM', 'QBCZ14LM', 'QBKG20LM', 'QBKG34LM',
1979
+ 'WS-EUK02', 'WS-EUK01', 'QBKG31LM', 'QBCZ15LM', 'QBCZ14LM', 'QBKG20LM', 'QBKG34LM', 'QBKG19LM',
1980
1980
  'QBKG38LM'].includes(meta.mapped.model)) {
1981
1981
  await entity.read('aqaraOpple', [0x0201]);
1982
1982
  } else if (['ZNCZ02LM', 'QBCZ11LM', 'ZNCZ11LM'].includes(meta.mapped.model)) {
@@ -2075,7 +2075,7 @@ const converters = {
2075
2075
  xiaomi_led_disabled_night: {
2076
2076
  key: ['led_disabled_night'],
2077
2077
  convertSet: async (entity, key, value, meta) => {
2078
- if (['ZNCZ04LM', 'ZNCZ15LM', 'QBCZ15LM', 'QBCZ14LM', 'QBKG20LM', 'QBKG25LM',
2078
+ if (['ZNCZ04LM', 'ZNCZ15LM', 'QBCZ15LM', 'QBCZ14LM', 'QBKG20LM', 'QBKG25LM', 'QBKG19LM',
2079
2079
  'QBKG34LM'].includes(meta.mapped.model)) {
2080
2080
  await entity.write('aqaraOpple', {0x0203: {value: value ? 1 : 0, type: 0x10}}, manufacturerOptions.xiaomi);
2081
2081
  } else if (['ZNCZ11LM'].includes(meta.mapped.model)) {
@@ -2090,7 +2090,7 @@ const converters = {
2090
2090
  return {state: {led_disabled_night: value}};
2091
2091
  },
2092
2092
  convertGet: async (entity, key, meta) => {
2093
- if (['ZNCZ04LM', 'ZNCZ15LM', 'QBCZ15LM', 'QBCZ14LM', 'QBKG20LM', 'QBKG25LM',
2093
+ if (['ZNCZ04LM', 'ZNCZ15LM', 'QBCZ15LM', 'QBCZ14LM', 'QBKG20LM', 'QBKG25LM', 'QBKG19LM',
2094
2094
  'QBKG34LM'].includes(meta.mapped.model)) {
2095
2095
  await entity.read('aqaraOpple', [0x0203], manufacturerOptions.xiaomi);
2096
2096
  } else {
@@ -2510,6 +2510,26 @@ const converters = {
2510
2510
  await entity.read('hvacThermostat', ['danfossWindowOpenExternal'], manufacturerOptions.danfoss);
2511
2511
  },
2512
2512
  },
2513
+ danfoss_load_balancing_enable: {
2514
+ key: ['load_balancing_enable'],
2515
+ convertSet: async (entity, key, value, meta) => {
2516
+ await entity.write('hvacThermostat', {'danfossLoadBalancingEnable': value}, manufacturerOptions.danfoss);
2517
+ return {readAfterWriteTime: 200, state: {'load_balancing_enable': value}};
2518
+ },
2519
+ convertGet: async (entity, key, meta) => {
2520
+ await entity.read('hvacThermostat', ['danfossLoadBalancingEnable'], manufacturerOptions.danfoss);
2521
+ },
2522
+ },
2523
+ danfoss_load_room_mean: {
2524
+ key: ['load_room_mean'],
2525
+ convertSet: async (entity, key, value, meta) => {
2526
+ await entity.write('hvacThermostat', {'danfossLoadRoomMean': value}, manufacturerOptions.danfoss);
2527
+ return {readAfterWriteTime: 200, state: {'load_room_mean': value}};
2528
+ },
2529
+ convertGet: async (entity, key, meta) => {
2530
+ await entity.read('hvacThermostat', ['danfossLoadRoomMean'], manufacturerOptions.danfoss);
2531
+ },
2532
+ },
2513
2533
  danfoss_load_estimate: {
2514
2534
  key: ['load_estimate'],
2515
2535
  convertGet: async (entity, key, meta) => {
@@ -2712,6 +2732,68 @@ const converters = {
2712
2732
  await tuya.sendDataPointValue(entity, tuya.dataPoints.moesSminTempSet, temp);
2713
2733
  },
2714
2734
  },
2735
+ haozee_thermostat_system_mode: {
2736
+ key: ['preset'],
2737
+ convertSet: async (entity, key, value, meta) => {
2738
+ const lookup = {0: 'auto', 1: 'manual', 2: 'off', 3: 'on'};
2739
+ await tuya.sendDataPointEnum(entity, tuya.dataPoints.haozeeSystemMode, lookup[value]);
2740
+ },
2741
+ },
2742
+ haozee_thermostat_current_heating_setpoint: {
2743
+ key: ['current_heating_setpoint'],
2744
+ convertSet: async (entity, key, value, meta) => {
2745
+ const temp = Math.round(value*10);
2746
+ await tuya.sendDataPointValue(entity, tuya.dataPoints.haozeeHeatingSetpoint, temp);
2747
+ },
2748
+ },
2749
+ haozee_thermostat_boost_heating: {
2750
+ key: ['boost_heating'],
2751
+ convertSet: async (entity, key, value, meta) => {
2752
+ await tuya.sendDataPointBool(entity, tuya.dataPoints.haozeeBoostHeating, value === 'ON');
2753
+ },
2754
+ },
2755
+ haozee_thermostat_boost_heating_countdown: {
2756
+ key: ['boost_heating_countdown'],
2757
+ convertSet: async (entity, key, value, meta) => {
2758
+ await tuya.sendDataPointValue(entity, tuya.dataPoints.haozeeBoostHeatingCountdown, value);
2759
+ },
2760
+ },
2761
+ haozee_thermostat_window_detection: {
2762
+ key: ['window_detection'],
2763
+ convertSet: async (entity, key, value, meta) => {
2764
+ await tuya.sendDataPointBool(entity, tuya.dataPoints.haozeeWindowDetection, value === 'ON');
2765
+ },
2766
+ },
2767
+ haozee_thermostat_child_lock: {
2768
+ key: ['child_lock'],
2769
+ convertSet: async (entity, key, value, meta) => {
2770
+ await tuya.sendDataPointBool(entity, tuya.dataPoints.haozeeChildLock, value === 'LOCK');
2771
+ },
2772
+ },
2773
+ haozee_thermostat_temperature_calibration: {
2774
+ key: ['local_temperature_calibration'],
2775
+ convertSet: async (entity, key, value, meta) => {
2776
+ let temp = Math.round(value * 1);
2777
+ if (temp < 0) {
2778
+ temp = 0xFFFFFFFF + temp + 1;
2779
+ }
2780
+ await tuya.sendDataPointValue(entity, tuya.dataPoints.haozeeTempCalibration, temp);
2781
+ },
2782
+ },
2783
+ haozee_thermostat_max_temperature: {
2784
+ key: ['max_temperature'],
2785
+ convertSet: async (entity, key, value, meta) => {
2786
+ const temp = Math.round(value*10);
2787
+ await tuya.sendDataPointValue(entity, tuya.dataPoints.haozeeMaxTemp, temp);
2788
+ },
2789
+ },
2790
+ haozee_thermostat_min_temperature: {
2791
+ key: ['min_temperature'],
2792
+ convertSet: async (entity, key, value, meta) => {
2793
+ const temp = Math.round(value*10);
2794
+ await tuya.sendDataPointValue(entity, tuya.dataPoints.haozeeMinTemp, temp);
2795
+ },
2796
+ },
2715
2797
  hgkg_thermostat_standby: {
2716
2798
  key: ['system_mode'],
2717
2799
  convertSet: async (entity, key, value, meta) => {
@@ -3206,7 +3288,7 @@ const converters = {
3206
3288
  },
3207
3289
  },
3208
3290
  eurotronic_valve_position: {
3209
- key: ['eurotronic_valve_position'],
3291
+ key: ['eurotronic_valve_position', 'valve_position'],
3210
3292
  convertSet: async (entity, key, value, meta) => {
3211
3293
  const payload = {0x4001: {value, type: 0x20}};
3212
3294
  await entity.write('hvacThermostat', payload, manufacturerOptions.eurotronic);
@@ -3216,7 +3298,7 @@ const converters = {
3216
3298
  },
3217
3299
  },
3218
3300
  eurotronic_trv_mode: {
3219
- key: ['eurotronic_trv_mode'],
3301
+ key: ['eurotronic_trv_mode', 'trv_mode'],
3220
3302
  convertSet: async (entity, key, value, meta) => {
3221
3303
  const payload = {0x4000: {value, type: 0x30}};
3222
3304
  await entity.write('hvacThermostat', payload, manufacturerOptions.eurotronic);
@@ -165,6 +165,31 @@ module.exports = [
165
165
  await reporting.fanMode(endpoint);
166
166
  },
167
167
  },
168
+ {
169
+ zigbeeModel: ['3157100-E'],
170
+ model: '3157100-E',
171
+ vendor: 'Centralite',
172
+ description: '3-Series pearl touch thermostat,',
173
+ fromZigbee: [fz.battery, fz.thermostat, fz.fan, fz.ignore_time_read],
174
+ toZigbee: [tz.factory_reset, tz.thermostat_local_temperature, tz.thermostat_local_temperature_calibration,
175
+ tz.thermostat_occupied_heating_setpoint, tz.thermostat_occupied_cooling_setpoint,
176
+ tz.thermostat_setpoint_raise_lower, tz.thermostat_remote_sensing,
177
+ tz.thermostat_control_sequence_of_operation, tz.thermostat_system_mode,
178
+ tz.thermostat_relay_status_log, tz.fan_mode, tz.thermostat_running_state],
179
+ exposes: [e.battery(), exposes.climate().withSetpoint('occupied_heating_setpoint', 10, 30, 1).withLocalTemperature()
180
+ .withSystemMode(['off', 'heat', 'cool', 'emergency_heating'])
181
+ .withRunningState(['idle', 'heat', 'cool', 'fan_only']).withFanMode(['auto', 'on'])
182
+ .withSetpoint('occupied_cooling_setpoint', 10, 30, 1).withLocalTemperatureCalibration()],
183
+ meta: {battery: {voltageToPercentage: '3V_1500_2800'}},
184
+ configure: async (device, coordinatorEndpoint, logger) => {
185
+ const endpoint = device.getEndpoint(1);
186
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'hvacThermostat', 'hvacFanCtrl']);
187
+ await reporting.batteryVoltage(endpoint);
188
+ await reporting.thermostatRunningState(endpoint);
189
+ await reporting.thermostatTemperature(endpoint);
190
+ await reporting.fanMode(endpoint);
191
+ },
192
+ },
168
193
  {
169
194
  zigbeeModel: ['4200-C'],
170
195
  model: '4200-C',
@@ -20,7 +20,7 @@ module.exports = [
20
20
  tz.danfoss_heat_available, tz.danfoss_heat_required, tz.danfoss_day_of_week, tz.danfoss_trigger_time,
21
21
  tz.danfoss_window_open_internal, tz.danfoss_window_open_external, tz.danfoss_load_estimate,
22
22
  tz.danfoss_viewing_direction, tz.danfoss_external_measured_room_sensor, tz.thermostat_keypad_lockout,
23
- tz.thermostat_system_mode],
23
+ tz.thermostat_system_mode, tz.danfoss_load_balancing_enable, tz.danfoss_load_room_mean],
24
24
  exposes: [e.battery(), e.keypad_lockout(),
25
25
  exposes.binary('mounted_mode_active', ea.STATE_GET, true, false)
26
26
  .withDescription('Is the unit in mounting mode. This is set to `false` for mounted (already on ' +
@@ -57,6 +57,11 @@ module.exports = [
57
57
  exposes.numeric('algorithm_scale_factor', ea.ALL).withValueMin(1).withValueMax(10)
58
58
  .withDescription('Scale factor of setpoint filter timeconstant ("aggressiveness" of control algorithm) '+
59
59
  '1= Quick ... 5=Moderate ... 10=Slow'),
60
+ exposes.binary('load_balancing_enable', ea.ALL, true, false)
61
+ .withDescription('Whether or not the thermostat acts as standalone thermostat or shares load with other ' +
62
+ 'thermostats in the room. The gateway must update load_room_mean if enabled.'),
63
+ exposes.numeric('load_room_mean', ea.ALL)
64
+ .withDescription('Mean radiator load for room calculated by gateway for load balancing purposes'),
60
65
  exposes.numeric('load_estimate', ea.STATE_GET)
61
66
  .withDescription('Load estimate on this radiator')],
62
67
  ota: ota.zigbeeOTA,
@@ -106,6 +111,8 @@ module.exports = [
106
111
  'danfossMountedModeControl',
107
112
  'danfossMountedModeActive',
108
113
  'danfossExternalMeasuredRoomSensor',
114
+ 'danfossLoadBalancingEnable',
115
+ 'danfossLoadRoomMean',
109
116
  ], options);
110
117
 
111
118
  // read systemMode to have an initial value
@@ -21,13 +21,13 @@ module.exports = [
21
21
  exposes: [e.battery(), exposes.climate().withSetpoint('occupied_heating_setpoint', 5, 30, 0.5).withLocalTemperature()
22
22
  .withSystemMode(['off', 'auto', 'heat']).withRunningState(['idle', 'heat']).withLocalTemperatureCalibration()
23
23
  .withPiHeatingDemand(),
24
- exposes.enum('eurotronic_trv_mode', exposes.access.ALL, [1, 2])
25
- .withDescription('Select between direct control of the valve via the `eurotronic_valve_position` or automatic control of the '+
24
+ exposes.enum('trv_mode', exposes.access.ALL, [1, 2])
25
+ .withDescription('Select between direct control of the valve via the `valve_position` or automatic control of the '+
26
26
  'valve based on the `current_heating_setpoint`. For manual control set the value to 1, for automatic control set the value '+
27
27
  'to 2 (the default). When switched to manual mode the display shows a value from 0 (valve closed) to 100 (valve fully open) '+
28
28
  'and the buttons on the device are disabled.'),
29
- exposes.numeric('eurotronic_valve_position', exposes.access.ALL).withValueMin(0).withValueMax(255)
30
- .withDescription('Directly control the radiator valve when `eurotronic_trv_mode` is set to 1. The values range from 0 (valve '+
29
+ exposes.numeric('valve_position', exposes.access.ALL).withValueMin(0).withValueMax(255)
30
+ .withDescription('Directly control the radiator valve when `trv_mode` is set to 1. The values range from 0 (valve '+
31
31
  'closed) to 255 (valve fully open)')],
32
32
  ota: ota.zigbeeOTA,
33
33
  configure: async (device, coordinatorEndpoint, logger) => {
package/devices/heiman.js CHANGED
@@ -10,6 +10,7 @@ const ea = exposes.access;
10
10
 
11
11
  module.exports = [
12
12
  {
13
+ fingerprint: [{modelID: 'TS0212', manufacturerName: '_TYZB01_wpmo3ja3'}],
13
14
  zigbeeModel: ['CO_V15', 'CO_YDLV10', 'CO_V16', '1ccaa94c49a84abaa9e38687913947ba'],
14
15
  model: 'HS1CA-M',
15
16
  description: 'Smart carbon monoxide sensor',
@@ -530,7 +530,7 @@ module.exports = [
530
530
  },
531
531
  {
532
532
  zigbeeModel: ['LWA017'],
533
- model: '929002469202',
533
+ model: '929002469202',
534
534
  vendor: 'Philips',
535
535
  description: 'Hue white A60 bulb E27 1050lm with Bluetooth',
536
536
  meta: {turnsOffAtBrightness1: true},
@@ -1769,6 +1769,20 @@ module.exports = [
1769
1769
  },
1770
1770
  ota: ota.zigbeeOTA,
1771
1771
  },
1772
+ {
1773
+ zigbeeModel: ['LOM007'],
1774
+ model: '929003050601',
1775
+ vendor: 'Philips',
1776
+ description: 'Hue smart plug',
1777
+ extend: extend.switch(),
1778
+ toZigbee: [tz.on_off].concat([tz.hue_power_on_behavior, tz.hue_power_on_error]),
1779
+ configure: async (device, coordinatorEndpoint, logger) => {
1780
+ const endpoint = device.getEndpoint(11);
1781
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
1782
+ await reporting.onOff(endpoint);
1783
+ },
1784
+ ota: ota.zigbeeOTA,
1785
+ },
1772
1786
  {
1773
1787
  zigbeeModel: ['LLC014'],
1774
1788
  model: '7099860PH',
package/devices/tuya.js CHANGED
@@ -109,7 +109,9 @@ module.exports = [
109
109
  {modelID: 'TS0505B', manufacturerName: '_TZ3000_x2fqbdun'},
110
110
  {modelID: 'TS0505B', manufacturerName: '_TZ3000_589kq4ul'},
111
111
  {modelID: 'TS0505B', manufacturerName: '_TZ3000_1mtktxdk'},
112
- {modelID: 'TS0505B', manufacturerName: '_TZ3210_bicjqpg4'}],
112
+ {modelID: 'TS0505B', manufacturerName: '_TZ3210_bicjqpg4'},
113
+ {modelID: 'TS0505B', manufacturerName: '_TZ3000_cmaky9gq'},
114
+ {modelID: 'TS0505B', manufacturerName: '_TZ3000_tza2vjxx'}],
113
115
  model: 'TS0505B',
114
116
  vendor: 'TuYa',
115
117
  description: 'Zigbee RGB+CCT light',
@@ -150,7 +152,8 @@ module.exports = [
150
152
  {modelID: 'TS0202', manufacturerName: '_TYZB01_2b8f6cio'},
151
153
  {modelID: 'TS0202', manufacturerName: '_TYZB01_dl7cejts'},
152
154
  {modelID: 'TS0202', manufacturerName: '_TYZB01_qjqgmqxr'},
153
- {modelID: 'TS0202', manufacturerName: '_TZ3000_mmtwjmaq'}],
155
+ {modelID: 'TS0202', manufacturerName: '_TZ3000_mmtwjmaq'},
156
+ {modelID: 'WHD02', manufacturerName: '_TZ3000_hktqahrq'}],
154
157
  model: 'TS0202',
155
158
  vendor: 'TuYa',
156
159
  description: 'Motion sensor',
@@ -608,7 +611,7 @@ module.exports = [
608
611
  },
609
612
  },
610
613
  {
611
- fingerprint: [{modelID: 'TS0002', manufacturerName: '_TZ3000_01gpyda5'}],
614
+ fingerprint: [{modelID: 'TS0002', manufacturerName: '_TZ3000_01gpyda5'}, {modelID: 'TS0002', manufacturerName: '_TZ3000_bvrlqyj7'}],
612
615
  model: 'TS0002_switch_module',
613
616
  vendor: 'TuYa',
614
617
  description: '2 gang switch module',
@@ -820,6 +823,46 @@ module.exports = [
820
823
  .withSystemMode(['off', 'heat', 'auto'], ea.STATE_SET).withRunningState(['idle', 'heat'], ea.STATE),
821
824
  ],
822
825
  },
826
+ {
827
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_a4bpgplm'}],
828
+ model: 'TS0601',
829
+ vendor: 'TS0601_thermostat_1',
830
+ description: 'Thermostatic radiator valve',
831
+ onEvent: tuya.onEventSetLocalTime,
832
+ fromZigbee: [fz.ignore_basic_report, fz.ignore_tuya_set_time, fz.haozee_thermostat],
833
+ toZigbee: [
834
+ tz.haozee_thermostat_system_mode, tz.haozee_thermostat_current_heating_setpoint, tz.haozee_thermostat_boost_heating,
835
+ tz.haozee_thermostat_boost_heating_countdown, tz.haozee_thermostat_window_detection,
836
+ tz.haozee_thermostat_child_lock, tz.haozee_thermostat_temperature_calibration, tz.haozee_thermostat_max_temperature,
837
+ tz.haozee_thermostat_min_temperature,
838
+ ],
839
+ exposes: [
840
+ e.battery(), e.child_lock(), e.max_temperature(), e.min_temperature(),
841
+ e.position(), e.window_detection(),
842
+ exposes.binary('window', ea.STATE, 'CLOSED', 'OPEN').withDescription('Window status closed or open '),
843
+ exposes.binary('heating', ea.STATE, 'ON', 'OFF').withDescription('Device valve is open or closed (heating or not)'),
844
+ exposes.climate()
845
+ .withLocalTemperature(ea.STATE).withSetpoint('current_heating_setpoint', 5, 35, 0.5, ea.STATE_SET)
846
+ .withLocalTemperatureCalibration(ea.STATE_SET).withPreset(['auto', 'manual', 'off', 'on'],
847
+ 'MANUAL MODE ☝ - In this mode, the device executes manual temperature setting. ' +
848
+ 'When the set temperature is lower than the "minimum temperature", the valve is closed (forced closed). ' +
849
+ 'AUTO MODE ⏱ - In this mode, the device executes a preset week programming temperature time and temperature. ' +
850
+ 'ON - In this mode, the thermostat stays open ' +
851
+ 'OFF - In this mode, the thermostat stays closed'),
852
+ exposes.composite('programming_mode').withDescription('Auto MODE ⏱ - In this mode, ' +
853
+ 'the device executes a preset week programming temperature time and temperature. ')
854
+ .withFeature(exposes.text('monday_schedule', ea.STATE))
855
+ .withFeature(exposes.text('tuesday_schedule', ea.STATE))
856
+ .withFeature(exposes.text('wednesday_schedule', ea.STATE))
857
+ .withFeature(exposes.text('thursday_schedule', ea.STATE))
858
+ .withFeature(exposes.text('friday_schedule', ea.STATE))
859
+ .withFeature(exposes.text('saturday_schedule', ea.STATE))
860
+ .withFeature(exposes.text('sunday_schedule', ea.STATE)),
861
+ exposes.binary('boost_heating', ea.STATE_SET, 'ON', 'OFF').withDescription('Boost Heating: press and hold "+" for 3 seconds, ' +
862
+ 'the device will enter the boost heating mode, and the ▷╵◁ will flash. The countdown will be displayed in the APP'),
863
+ exposes.numeric('boost_heating_countdown', ea.STATE_SET).withUnit('min').withDescription('Countdown in minutes'),
864
+ ],
865
+ },
823
866
  {
824
867
  zigbeeModel: ['TS0121'],
825
868
  model: 'TS0121_plug',
package/devices/xiaomi.js CHANGED
@@ -688,6 +688,27 @@ module.exports = [
688
688
  onEvent: preventReset,
689
689
  ota: ota.zigbeeOTA,
690
690
  },
691
+ {
692
+ zigbeeModel: ['lumi.switch.b1nacn01'],
693
+ model: 'QBKG19LM',
694
+ vendor: 'Xiaomi',
695
+ description: 'Aqara smart wall switch T1 (with neutral, single rocker)',
696
+ fromZigbee: [fz.on_off, fz.xiaomi_power, fz.xiaomi_multistate_action, fz.xiaomi_switch_opple_basic],
697
+ toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory,
698
+ tz.xiaomi_led_disabled_night],
699
+ exposes: [
700
+ e.switch(), e.action(['single', 'double']), e.power().withAccess(ea.STATE), e.energy(),
701
+ e.voltage().withAccess(ea.STATE), e.temperature().withAccess(ea.STATE),
702
+ e.power_outage_memory(), e.led_disabled_night(),
703
+ exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
704
+ .withDescription('Decoupled mode for left button'),
705
+ ],
706
+ configure: async (device, coordinatorEndpoint, logger) => {
707
+ await device.getEndpoint(1).write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
708
+ },
709
+ onEvent: preventReset,
710
+ ota: ota.zigbeeOTA,
711
+ },
691
712
  {
692
713
  zigbeeModel: ['lumi.switch.b2nacn01'],
693
714
  model: 'QBKG20LM',
package/lib/tuya.js CHANGED
@@ -423,6 +423,30 @@ const dataPoints = {
423
423
  tvThursdaySchedule: 113,
424
424
  tvSaturdaySchedule: 114,
425
425
  tvBoostMode: 115,
426
+ // Haozee TS0601 TRV
427
+ haozeeSystemMode: 1,
428
+ haozeeHeatingSetpoint: 2,
429
+ haozeeLocalTemp: 3,
430
+ haozeeBoostHeating: 4,
431
+ haozeeBoostHeatingCountdown: 5,
432
+ haozeeRunningState: 6,
433
+ haozeeWindowState: 7,
434
+ haozeeWindowDetection: 8,
435
+ haozeeChildLock: 12,
436
+ haozeeBattery: 13,
437
+ haozeeFaultAlarm: 14,
438
+ haozeeMinTemp: 15,
439
+ haozeeMaxTemp: 16,
440
+ haozeeScheduleMonday: 17,
441
+ haozeeScheduleTuesday: 18,
442
+ haozeeScheduleWednesday: 19,
443
+ haozeeScheduleThursday: 20,
444
+ haozeeScheduleFriday: 21,
445
+ haozeeScheduleSaturday: 22,
446
+ haozeeScheduleSunday: 23,
447
+ haozeeTempCalibration: 101,
448
+ haozeeValvePosition: 102,
449
+ haozeeSoftVersion: 150,
426
450
  // HOCH / WDYK DIN Rail
427
451
  hochCountdownTimer: 9,
428
452
  hochFaultCode: 26,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.296",
3
+ "version": "14.0.300",
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.296",
3
+ "version": "14.0.300",
4
4
  "description": "Collection of device converters to be used with zigbee-herdsman",
5
5
  "main": "index.js",
6
6
  "files": [