zigbee-herdsman-converters 14.0.357 → 14.0.361

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.
@@ -89,6 +89,10 @@ const converters = {
89
89
  result[postfixWithEndpointName('control_sequence_of_operation', msg, model)] =
90
90
  constants.thermostatControlSequenceOfOperations[msg.data['ctrlSeqeOfOper']];
91
91
  }
92
+ if (msg.data.hasOwnProperty('programingOperMode')) {
93
+ result[postfixWithEndpointName('programming_operation_mode', msg, model)] =
94
+ constants.thermostatProgrammingOperationModes[msg.data['programingOperMode']];
95
+ }
92
96
  if (msg.data.hasOwnProperty('systemMode')) {
93
97
  result[postfixWithEndpointName('system_mode', msg, model)] = constants.thermostatSystemModes[msg.data['systemMode']];
94
98
  }
@@ -7347,7 +7351,7 @@ const converters = {
7347
7351
  case tuya.dataPoints.trsMotionSpeed:
7348
7352
  return {motion_speed: value};
7349
7353
  case tuya.dataPoints.trsMotionDirection:
7350
- return {motion_direction: {0: 'still', 1: 'forward', 2: 'backward'}[value]};
7354
+ return {motion_direction: {0: 'standing_still', 1: 'moving_forward', 2: 'moving_backward'}[value]};
7351
7355
  case tuya.dataPoints.trsScene:
7352
7356
  return {radar_scene: {'default': 0, 'area': 1, 'toilet': 2, 'bedroom': 3, 'parlour': 4, 'office': 5, 'hotel': 6}[value]};
7353
7357
  case tuya.dataPoints.trsSensitivity:
@@ -785,7 +785,7 @@ const converters = {
785
785
  const {message} = meta;
786
786
  const transition = utils.getTransition(entity, 'brightness', meta);
787
787
  const turnsOffAtBrightness1 = utils.getMetaValue(entity, meta.mapped, 'turnsOffAtBrightness1', 'allEqual', false);
788
- const state = message.hasOwnProperty('state') ? message.state.toLowerCase() : undefined;
788
+ let state = message.hasOwnProperty('state') ? message.state.toLowerCase() : undefined;
789
789
  let brightness = undefined;
790
790
  if (message.hasOwnProperty('brightness')) {
791
791
  brightness = Number(message.brightness);
@@ -803,7 +803,11 @@ const converters = {
803
803
  }
804
804
 
805
805
  if (state === 'toggle' || state === 'off' || (brightness === undefined && state === 'on')) {
806
- if (transition.specified && (state === 'off' || state === 'on')) {
806
+ if (transition.specified) {
807
+ if (state === 'toggle') {
808
+ state = meta.state.state === 'ON' ? 'OFF' : 'ON';
809
+ }
810
+
807
811
  if (state === 'off' && meta.state.brightness && meta.state.state === 'ON') {
808
812
  // https://github.com/Koenkk/zigbee2mqtt/issues/2850#issuecomment-580365633
809
813
  // We need to remember the state before turning the device off as we need to restore
@@ -1154,6 +1158,20 @@ const converters = {
1154
1158
  await entity.read('hvacThermostat', ['ctrlSeqeOfOper']);
1155
1159
  },
1156
1160
  },
1161
+ thermostat_programming_operation_mode: {
1162
+ key: ['programming_operation_mode'],
1163
+ convertSet: async (entity, key, value, meta) => {
1164
+ const val = utils.getKey(constants.thermostatProgrammingOperationModes, value, undefined, Number);
1165
+ if (val === undefined) {
1166
+ throw new Error('Programming operation mode invalid, must be one of: ' +
1167
+ Object.values(constants.thermostatProgrammingOperationModes).join(', '));
1168
+ }
1169
+ await entity.write('hvacThermostat', {programingOperMode: val});
1170
+ },
1171
+ convertGet: async (entity, key, meta) => {
1172
+ await entity.read('hvacThermostat', ['programingOperMode']);
1173
+ },
1174
+ },
1157
1175
  thermostat_temperature_display_mode: {
1158
1176
  key: ['temperature_display_mode'],
1159
1177
  convertSet: async (entity, key, value, meta) => {
package/devices/climax.js CHANGED
@@ -121,4 +121,18 @@ module.exports = [
121
121
  exposes: [e.battery_low(), e.tamper(), e.action(['emergency', 'panic', 'disarm', 'arm_all_zones', 'arm_day_zones']),
122
122
  ],
123
123
  },
124
+ {
125
+ zigbeeModel: ['PRL_00.00.03.04TC'],
126
+ model: 'PRL-1ZBS-12/24V',
127
+ vendor: 'Climax',
128
+ description: 'Zigbee 12-24V relay controller',
129
+ extend: extend.switch(),
130
+ configure: async (device, coordinatorEndpoint, logger) => {
131
+ const endpoint = device.getEndpoint(1);
132
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
133
+ await reporting.onOff(endpoint);
134
+ device.powerSource = 'Mains (single phase)';
135
+ device.save();
136
+ },
137
+ },
124
138
  ];
@@ -15,14 +15,15 @@ module.exports = [
15
15
  model: '014G2461',
16
16
  vendor: 'Danfoss',
17
17
  description: 'Ally thermostat',
18
- fromZigbee: [fz.battery, fz.thermostat, fz.hvac_user_interface, fz.danfoss_thermostat],
18
+ fromZigbee: [fz.battery, fz.thermostat, fz.thermostat_weekly_schedule, fz.hvac_user_interface, fz.danfoss_thermostat],
19
19
  toZigbee: [tz.danfoss_thermostat_occupied_heating_setpoint, tz.thermostat_local_temperature, tz.danfoss_mounted_mode_active,
20
20
  tz.danfoss_mounted_mode_control, tz.danfoss_thermostat_vertical_orientation, tz.danfoss_algorithm_scale_factor,
21
21
  tz.danfoss_heat_available, tz.danfoss_heat_required, tz.danfoss_day_of_week, tz.danfoss_trigger_time,
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
- tz.thermostat_keypad_lockout, tz.thermostat_system_mode, tz.danfoss_load_balancing_enable, tz.danfoss_load_room_mean],
25
- exposes: [e.battery(), e.keypad_lockout(),
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],
26
+ exposes: [e.battery(), e.keypad_lockout(), e.programming_operation_mode(),
26
27
  exposes.binary('mounted_mode_active', ea.STATE_GET, true, false)
27
28
  .withDescription('Is the unit in mounting mode. This is set to `false` for mounted (already on ' +
28
29
  'the radiator) or `true` for not mounted (after factory reset)'),
@@ -71,7 +72,7 @@ module.exports = [
71
72
  'thermostats in the room. The gateway must update load_room_mean if enabled.'),
72
73
  exposes.numeric('load_room_mean', ea.ALL)
73
74
  .withDescription('Mean radiator load for room calculated by gateway for load balancing purposes (-8000=undefined)')
74
- .withValueMin(-8000).withValueMax(100),
75
+ .withValueMin(-8000).withValueMax(2000),
75
76
  exposes.numeric('load_estimate', ea.STATE_GET)
76
77
  .withDescription('Load estimate on this radiator')],
77
78
  ota: ota.zigbeeOTA,
@@ -237,7 +237,7 @@ module.exports = [
237
237
  vendor: 'Gledopto',
238
238
  ota: ota.zigbeeOTA,
239
239
  description: 'Zigbee LED Controller RGB+CCT (pro)',
240
- extend: gledoptoExtend.light_onoff_brightness_colortemp_color(),
240
+ extend: gledoptoExtend.light_onoff_brightness_colortemp_color({colorTempRange: [158, 495]}),
241
241
  meta: {disableDefaultResponse: true},
242
242
  },
243
243
  {
@@ -327,7 +327,7 @@ module.exports = [
327
327
  extend: gledoptoExtend.light_onoff_brightness_colortemp_color(),
328
328
  },
329
329
  {
330
- zigbeeModel: ['GL-S-007Z'],
330
+ zigbeeModel: ['GL-S-007Z', 'GL-S-007Z(lk)'],
331
331
  model: 'GL-S-007Z',
332
332
  vendor: 'Gledopto',
333
333
  description: 'Zigbee 5W GU10 Bulb RGB+CCT',
package/devices/hive.js CHANGED
@@ -156,14 +156,15 @@ module.exports = [
156
156
  model: 'UK7004240',
157
157
  vendor: 'Hive',
158
158
  description: 'Radiator valve based on Danfos Ally',
159
- fromZigbee: [fz.battery, fz.thermostat, fz.hvac_user_interface, fz.danfoss_thermostat],
159
+ fromZigbee: [fz.battery, fz.thermostat, fz.thermostat_weekly_schedule, fz.hvac_user_interface, fz.danfoss_thermostat],
160
160
  toZigbee: [tz.danfoss_thermostat_occupied_heating_setpoint, tz.thermostat_local_temperature, tz.danfoss_mounted_mode_active,
161
161
  tz.danfoss_mounted_mode_control, tz.danfoss_thermostat_vertical_orientation, tz.danfoss_algorithm_scale_factor,
162
162
  tz.danfoss_heat_available, tz.danfoss_heat_required, tz.danfoss_day_of_week, tz.danfoss_trigger_time,
163
163
  tz.danfoss_window_open_internal, tz.danfoss_window_open_external, tz.danfoss_load_estimate,
164
164
  tz.danfoss_viewing_direction, tz.danfoss_external_measured_room_sensor, tz.thermostat_keypad_lockout,
165
- tz.thermostat_system_mode, tz.danfoss_load_balancing_enable, tz.danfoss_load_room_mean],
166
- exposes: [e.battery(), e.keypad_lockout(),
165
+ tz.thermostat_system_mode, tz.danfoss_load_balancing_enable, tz.danfoss_load_room_mean,
166
+ tz.thermostat_weekly_schedule, tz.thermostat_clear_weekly_schedule, tz.thermostat_programming_operation_mode],
167
+ exposes: [e.battery(), e.keypad_lockout(), e.programming_operation_mode(),
167
168
  exposes.binary('mounted_mode_active', ea.STATE_GET, true, false)
168
169
  .withDescription('Is the unit in mounting mode. This is set to `false` for mounted (already on ' +
169
170
  'the radiator) or `true` for not mounted (after factory reset)'),
@@ -205,7 +206,7 @@ module.exports = [
205
206
  'thermostats in the room. The gateway must update load_room_mean if enabled.'),
206
207
  exposes.numeric('load_room_mean', ea.ALL)
207
208
  .withDescription('Mean radiator load for room calculated by gateway for load balancing purposes (-8000=undefined)')
208
- .withValueMin(-8000).withValueMax(100),
209
+ .withValueMin(-8000).withValueMax(2000),
209
210
  exposes.numeric('load_estimate', ea.STATE_GET)
210
211
  .withDescription('Load estimate on this radiator')],
211
212
  configure: async (device, coordinatorEndpoint, logger) => {
@@ -29,6 +29,15 @@ const hueExtend = {
29
29
  };
30
30
 
31
31
  module.exports = [
32
+ {
33
+ zigbeeModel: ['929003054001'],
34
+ model: '929003054001',
35
+ vendor: 'Philips',
36
+ description: 'Hue Wellness table lamp',
37
+ meta: {turnsOffAtBrightness1: true},
38
+ extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
39
+ ota: ota.zigbeeOTA,
40
+ },
32
41
  {
33
42
  zigbeeModel: ['4076131P6'],
34
43
  model: '4076131P6',
@@ -1913,6 +1922,39 @@ module.exports = [
1913
1922
  },
1914
1923
  ota: ota.zigbeeOTA,
1915
1924
  },
1925
+ {
1926
+ zigbeeModel: ['SML004'],
1927
+ model: '9290030674',
1928
+ vendor: 'Philips',
1929
+ description: 'Hue motion outdoor sensor',
1930
+ fromZigbee: [fz.battery, fz.occupancy, fz.temperature, fz.illuminance, fz.occupancy_timeout,
1931
+ fz.hue_motion_sensitivity, fz.hue_motion_led_indication],
1932
+ exposes: [e.temperature(), e.occupancy(), e.battery(), e.illuminance_lux(), e.illuminance(),
1933
+ exposes.enum('motion_sensitivity', ea.ALL, ['low', 'medium', 'high']),
1934
+ exposes.binary('led_indication', ea.ALL, true, false).withDescription('Blink green LED on motion detection'),
1935
+ exposes.numeric('occupancy_timeout', ea.ALL).withUnit('second').withValueMin(0).withValueMax(65535)],
1936
+ toZigbee: [tz.occupancy_timeout, tz.hue_motion_sensitivity, tz.hue_motion_led_indication],
1937
+ endpoint: (device) => {
1938
+ return {
1939
+ 'default': 2, // default
1940
+ 'ep1': 1,
1941
+ 'ep2': 2, // e.g. for write to msOccupancySensing
1942
+ };
1943
+ },
1944
+ configure: async (device, coordinatorEndpoint, logger) => {
1945
+ const endpoint = device.getEndpoint(2);
1946
+ const binds = ['genPowerCfg', 'msIlluminanceMeasurement', 'msTemperatureMeasurement', 'msOccupancySensing'];
1947
+ await reporting.bind(endpoint, coordinatorEndpoint, binds);
1948
+ await reporting.batteryPercentageRemaining(endpoint);
1949
+ await reporting.occupancy(endpoint);
1950
+ await reporting.temperature(endpoint);
1951
+ await reporting.illuminance(endpoint);
1952
+ // read occupancy_timeout and motion_sensitivity
1953
+ await endpoint.read('msOccupancySensing', ['pirOToUDelay']);
1954
+ await endpoint.read('msOccupancySensing', [48], {manufacturerCode: 4107});
1955
+ },
1956
+ ota: ota.zigbeeOTA,
1957
+ },
1916
1958
  {
1917
1959
  zigbeeModel: ['LOM001'],
1918
1960
  model: '929002240401',
package/devices/popp.js CHANGED
@@ -15,14 +15,15 @@ module.exports = [
15
15
  model: '701721',
16
16
  vendor: 'Popp',
17
17
  description: 'Smart thermostat',
18
- fromZigbee: [fz.battery, fz.thermostat, fz.hvac_user_interface, fz.danfoss_thermostat],
18
+ fromZigbee: [fz.battery, fz.thermostat, fz.thermostat_weekly_schedule, fz.hvac_user_interface, fz.danfoss_thermostat],
19
19
  toZigbee: [tz.danfoss_thermostat_occupied_heating_setpoint, tz.thermostat_local_temperature, tz.danfoss_mounted_mode_active,
20
20
  tz.danfoss_mounted_mode_control, tz.danfoss_thermostat_vertical_orientation, tz.danfoss_algorithm_scale_factor,
21
21
  tz.danfoss_heat_available, tz.danfoss_heat_required, tz.danfoss_day_of_week, tz.danfoss_trigger_time,
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.thermostat_keypad_lockout,
24
- tz.thermostat_system_mode, tz.danfoss_load_balancing_enable, tz.danfoss_load_room_mean],
25
- exposes: [e.battery(), e.keypad_lockout(),
24
+ 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],
26
+ exposes: [e.battery(), e.keypad_lockout(), e.programming_operation_mode(),
26
27
  exposes.binary('mounted_mode_active', ea.STATE_GET, true, false)
27
28
  .withDescription('Is the unit in mounting mode. This is set to `false` for mounted (already on ' +
28
29
  'the radiator) or `true` for not mounted (after factory reset)'),
@@ -64,7 +65,7 @@ module.exports = [
64
65
  'thermostats in the room. The gateway must update load_room_mean if enabled.'),
65
66
  exposes.numeric('load_room_mean', ea.ALL)
66
67
  .withDescription('Mean radiator load for room calculated by gateway for load balancing purposes (-8000=undefined)')
67
- .withValueMin(-8000).withValueMax(100),
68
+ .withValueMin(-8000).withValueMax(2000),
68
69
  exposes.numeric('load_estimate', ea.STATE_GET)
69
70
  .withDescription('Load estimate on this radiator')],
70
71
  ota: ota.zigbeeOTA,
package/devices/sinope.js CHANGED
@@ -151,14 +151,18 @@ module.exports = [
151
151
  await reporting.thermostatRunningState(endpoint);
152
152
  } catch (error) {/* Not all support this */}
153
153
 
154
- await reporting.readEletricalMeasurementMultiplierDivisors(endpoint);
155
154
  try {
155
+ await endpoint.read('haElectricalMeasurement', ['acPowerMultiplier', 'acPowerDivisor']);
156
156
  await reporting.activePower(endpoint, {min: 10, max: 305, change: 1}); // divider 1: 1W
157
- } catch (error) {/* Do nothing*/}
157
+ } catch (error) {
158
+ endpoint.saveClusterAttributeKeyValue('haElectricalMeasurement', {'acPowerMultiplier': 1, 'acPowerDivisor': 1});
159
+ }
158
160
  try {
161
+ await endpoint.read('haElectricalMeasurement', ['acCurrentMultiplier', 'acCurrentDivisor']);
159
162
  await reporting.rmsCurrent(endpoint, {min: 10, max: 306, change: 100}); // divider 1000: 0.1Arms
160
163
  } catch (error) {/* Do nothing*/}
161
164
  try {
165
+ await endpoint.read('haElectricalMeasurement', ['acVoltageMultiplier', 'acVoltageDivisor']);
162
166
  await reporting.rmsVoltage(endpoint, {min: 10, max: 307, change: 5}); // divider 10: 0.5Vrms
163
167
  } catch (error) {/* Do nothing*/}
164
168
 
@@ -133,12 +133,18 @@ module.exports = [
133
133
  model: 'IM6001-OTP05',
134
134
  vendor: 'SmartThings',
135
135
  description: 'Outlet',
136
- extend: extend.switch(),
136
+ fromZigbee: [fz.on_off, fz.electrical_measurement],
137
+ toZigbee: [tz.on_off],
137
138
  configure: async (device, coordinatorEndpoint, logger) => {
138
139
  const endpoint = device.getEndpoint(1);
139
- await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
140
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement']);
140
141
  await reporting.onOff(endpoint);
142
+ await reporting.readEletricalMeasurementMultiplierDivisors(endpoint);
143
+ await reporting.activePower(endpoint);
144
+ await reporting.rmsCurrent(endpoint);
145
+ await reporting.rmsVoltage(endpoint);
141
146
  },
147
+ exposes: [e.switch(), e.power(), e.current(), e.voltage()],
142
148
  },
143
149
  {
144
150
  zigbeeModel: ['outletv4'],
package/devices/tuya.js CHANGED
@@ -7,11 +7,41 @@ const reporting = require('../lib/reporting');
7
7
  const extend = require('../lib/extend');
8
8
  const e = exposes.presets;
9
9
  const ea = exposes.access;
10
-
10
+ const libColor = require('../lib/color');
11
+ const utils = require('../lib/utils');
11
12
 
12
13
  const TS011Fplugs = ['_TZ3000_5f43h46b', '_TZ3000_cphmq0q7', '_TZ3000_dpo1ysak', '_TZ3000_ew3ldmgx', '_TZ3000_gjnozsaz',
13
14
  '_TZ3000_jvzvulen', '_TZ3000_mraovvmm', '_TZ3000_nfnmi125', '_TZ3000_ps3dmato', '_TZ3000_w0qqde0g', '_TZ3000_u5u4cakc',
14
- '_TZ3000_rdtixbnu', '_TZ3000_typdpbpg'];
15
+ '_TZ3000_rdtixbnu', '_TZ3000_typdpbpg', '_TZ3000_v1pdxuqq'];
16
+
17
+ const tzLocal = {
18
+ TS0504B_color: {
19
+ key: ['color'],
20
+ convertSet: async (entity, key, value, meta) => {
21
+ const color = libColor.Color.fromConverterArg(value);
22
+ console.log(color);
23
+ const enableWhite =
24
+ (color.isRGB() && (color.rgb.red === 1 && color.rgb.green === 1 && color.rgb.blue === 1)) ||
25
+ // Zigbee2MQTT frontend white value
26
+ (color.isXY() && (color.xy.x === 0.3125 || color.xy.y === 0.32894736842105265)) ||
27
+ // Home Assistant white color picker value
28
+ (color.isXY() && (color.xy.x === 0.323 || color.xy.y === 0.329));
29
+
30
+ if (enableWhite) {
31
+ await entity.command('lightingColorCtrl', 'tuyaRgbMode', {enable: false});
32
+ const newState = {color_mode: 'xy'};
33
+ if (color.isXY()) {
34
+ newState.color = color.xy;
35
+ } else {
36
+ newState.color = color.rgb.gammaCorrected().toXY().rounded(4);
37
+ }
38
+ return {state: libColor.syncColorState(newState, meta.state, entity, meta.options, meta.logger)};
39
+ } else {
40
+ return await tz.light_color.convertSet(entity, key, value, meta);
41
+ }
42
+ },
43
+ },
44
+ };
15
45
 
16
46
  module.exports = [
17
47
  {
@@ -103,7 +133,8 @@ module.exports = [
103
133
  {
104
134
  fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_rk2yzt0u'},
105
135
  {modelID: 'TS0001', manufacturerName: '_TZ3000_o4cjetlm'}, {manufacturerName: '_TZ3000_o4cjetlm'},
106
- {modelID: 'TS0001', manufacturerName: '_TZ3000_iedbgyxt'}],
136
+ {modelID: 'TS0001', manufacturerName: '_TZ3000_iedbgyxt'}, {modelID: 'TS0001', manufacturerName: '_TZ3000_h3noz0a5'},
137
+ {modelID: 'TS0001', manufacturerName: '_TYZB01_4tlksk8a'}],
107
138
  model: 'ZN231392',
108
139
  vendor: 'TuYa',
109
140
  description: 'Smart water/gas valve',
@@ -151,11 +182,13 @@ module.exports = [
151
182
  meta: {applyRedFix: true, enhancedHue: false},
152
183
  },
153
184
  {
154
- fingerprint: [{modelID: 'TS0504B', manufacturerName: '_TZ3000_ukuvyhaa'}],
185
+ fingerprint: [{modelID: 'TS0504B', manufacturerName: '_TZ3000_ukuvyhaa'},
186
+ {modelID: 'TS0504B', manufacturerName: '_TZ3210_bfvybixd'}],
155
187
  model: 'TS0504B',
156
188
  vendor: 'TuYa',
157
189
  description: 'Zigbee RGBW light',
158
190
  extend: extend.light_onoff_brightness_color(),
191
+ toZigbee: utils.replaceInArray(extend.light_onoff_brightness_color().toZigbee, [tz.light_color], [tzLocal.TS0504B_color]),
159
192
  meta: {applyRedFix: true},
160
193
  },
161
194
  {
@@ -176,6 +209,7 @@ module.exports = [
176
209
  {modelID: 'TS0202', manufacturerName: '_TYZB01_qjqgmqxr'},
177
210
  {modelID: 'TS0202', manufacturerName: '_TZ3000_mmtwjmaq'},
178
211
  {modelID: 'TS0202', manufacturerName: '_TZ3000_kmh5qpmb'},
212
+ {modelID: 'TS0202', manufacturerName: '_TYZB01_zwvaj5wy'},
179
213
  {modelID: 'TS0202', manufacturerName: '_TZ3000_mcxw5ehu'},
180
214
  {modelID: 'TS0202', manufacturerName: '_TZ3000_msl6wxk9'},
181
215
  {modelID: 'TS0202', manufacturerName: '_TYZB01_hqbdru35'},
@@ -457,6 +491,7 @@ module.exports = [
457
491
  {modelID: 'TS0502B', manufacturerName: '_TZ3210_hi1ym4bl'},
458
492
  {modelID: 'TS0502B', manufacturerName: '_TZ3210_psgq7ysz'},
459
493
  {modelID: 'TS0502B', manufacturerName: '_TZ3000_zw7wr5uo'},
494
+ {modelID: 'TS0502B', manufacturerName: '_TZ3210_pz9zmxjj'},
460
495
  ],
461
496
  model: 'TS0502B',
462
497
  vendor: 'TuYa',
@@ -831,7 +866,10 @@ module.exports = [
831
866
  exposes: [
832
867
  e.child_lock(), e.window_detection(), e.battery_low(), e.valve_detection(), e.position(),
833
868
  exposes.climate().withSetpoint('current_heating_setpoint', 5, 35, 0.5, ea.STATE_SET)
834
- .withLocalTemperature(ea.STATE).withSystemMode(['heat', 'auto', 'off'], ea.STATE_SET)
869
+ .withLocalTemperature(ea.STATE).withSystemMode(['heat', 'auto', 'off'], ea.STATE_SET,
870
+ 'Mode of this device, in the `heat` mode the TS0601 will remain continuously heating, i.e. it does not regulate ' +
871
+ 'to the desired temperature. If you want TRV to properly regulate the temperature you need to use mode `auto` ' +
872
+ 'instead setting the desired temperature.')
835
873
  .withLocalTemperatureCalibration(-30, 30, 0.1, ea.STATE_SET)
836
874
  .withAwayMode().withPreset(['schedule', 'manual', 'boost', 'complex', 'comfort', 'eco']),
837
875
  e.auto_lock(), e.away_mode(), e.away_preset_days(), e.boost_time(), e.comfort_temperature(), e.eco_temperature(), e.force(),
@@ -1111,22 +1149,25 @@ module.exports = [
1111
1149
  exposes: [e.switch().setAccess('state', ea.STATE_SET), e.voltage(), e.power(), e.current(), e.energy()],
1112
1150
  },
1113
1151
  {
1114
- fingerprint: [{modelID: 'TS1101', manufacturerName: '_TZ3000_7ysdnebc'},
1115
- {modelID: 'TS1101', manufacturerName: '_TZ3000_xfs39dbf'}],
1116
- model: 'TS1101_dimmer_module',
1152
+ fingerprint: [{modelID: 'TS1101', manufacturerName: '_TZ3000_xfs39dbf'}],
1153
+ model: 'TS1101_dimmer_module_1ch',
1117
1154
  vendor: 'TuYa',
1118
- description: '2CH Zigbee dimmer module',
1155
+ description: 'Zigbee dimmer module 1 channel',
1156
+ fromZigbee: extend.light_onoff_brightness().fromZigbee.concat([fz.tuya_min_brightness]),
1157
+ toZigbee: extend.light_onoff_brightness().toZigbee.concat([tz.tuya_min_brightness]),
1158
+ exposes: [e.light_brightness().withMinBrightness()],
1159
+ extend: extend.light_onoff_brightness(),
1160
+ },
1161
+ {
1162
+ fingerprint: [{modelID: 'TS1101', manufacturerName: '_TZ3000_7ysdnebc'}],
1163
+ model: 'TS1101_dimmer_module_2ch',
1164
+ vendor: 'TuYa',
1165
+ description: 'Zigbee dimmer module 2 channel',
1119
1166
  whiteLabel: [{vendor: 'OXT', model: 'SWTZ25'}],
1120
- fromZigbee: extend.light_onoff_brightness().fromZigbee.concat([
1121
- fz.tuya_min_brightness,
1122
- ]),
1123
- toZigbee: extend.light_onoff_brightness().toZigbee.concat([
1124
- tz.tuya_min_brightness,
1125
- ]),
1126
- exposes: [
1127
- e.light_brightness().withMinBrightness().withEndpoint('l1'),
1128
- e.light_brightness().withMinBrightness().withEndpoint('l2'),
1129
- ],
1167
+ fromZigbee: extend.light_onoff_brightness().fromZigbee.concat([fz.tuya_min_brightness]),
1168
+ toZigbee: extend.light_onoff_brightness().toZigbee.concat([tz.tuya_min_brightness]),
1169
+ exposes: [e.light_brightness().withMinBrightness().withEndpoint('l1'),
1170
+ e.light_brightness().withMinBrightness().withEndpoint('l2')],
1130
1171
  endpoint: (device) => {
1131
1172
  return {'l1': 1, 'l2': 2};
1132
1173
  },
@@ -1631,7 +1672,7 @@ module.exports = [
1631
1672
  e.illuminance_lux(), e.presence(),
1632
1673
  exposes.binary('motion', ea.STATE, [true, false]).withDescription('moving inside the range of the sensor'),
1633
1674
  exposes.numeric('motion_speed', ea.STATE).withDescription('Speed of movement'),
1634
- exposes.enum('motion_direction', ea.STATE, ['standing still', 'moving forward', 'moving backward'])
1675
+ exposes.enum('motion_direction', ea.STATE, ['standing_still', 'moving_forward', 'moving_backward'])
1635
1676
  .withDescription('direction of movement from the point of view of the radar'),
1636
1677
  exposes.numeric('radar_sensitivity', ea.STATE_SET).withValueMin(0).withValueMax(10).withValueStep(1)
1637
1678
  .withDescription('sensitivity of the radar'),
package/devices/xiaomi.js CHANGED
@@ -47,7 +47,7 @@ module.exports = [
47
47
  description: 'Aqara E1 door & window contact sensor',
48
48
  fromZigbee: [fz.ias_contact_alarm_1, fz.aqara_opple],
49
49
  toZigbee: [],
50
- exposes: [e.contact(), e.battery(), e.battery_voltage()],
50
+ exposes: [e.contact(), e.battery(), e.temperature(), e.battery_voltage()],
51
51
  },
52
52
  {
53
53
  zigbeeModel: ['lumi.magnet.ac01'],
@@ -1724,7 +1724,7 @@ module.exports = [
1724
1724
  model: 'MCCGQ12LM',
1725
1725
  vendor: 'Xiaomi',
1726
1726
  description: 'Aqara T1 door & window contact sensor',
1727
- fromZigbee: [fz.ias_contact_alarm_1, fz.battery],
1727
+ fromZigbee: [fz.xiaomi_contact, fz.battery],
1728
1728
  toZigbee: [],
1729
1729
  meta: {battery: {voltageToPercentage: '3V_2100'}},
1730
1730
  exposes: [e.contact(), e.battery(), e.battery_voltage()],
@@ -0,0 +1,21 @@
1
+ const exposes = require('../lib/exposes');
2
+ const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/legacy').fromZigbee};
3
+ const reporting = require('../lib/reporting');
4
+ const e = exposes.presets;
5
+
6
+ module.exports = [
7
+ {
8
+ zigbeeModel: ['ZBT-DIMSwitch-D0000'],
9
+ model: '8718801528334',
10
+ vendor: 'Ynoa',
11
+ description: 'Remote control one button dimmer',
12
+ fromZigbee: [fz.command_on, fz.command_off, fz.command_move, fz.command_stop, fz.battery],
13
+ exposes: [e.action(['on', 'off', 'brightness_move_up', 'brightness_move_down', 'brightness_stop']), e.battery()],
14
+ toZigbee: [],
15
+ configure: async (device, coordinatorEndpoint, logger) => {
16
+ const endpoint = device.getEndpoint(1);
17
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
18
+ await reporting.batteryPercentageRemaining(endpoint);
19
+ },
20
+ },
21
+ ];
package/lib/constants.js CHANGED
@@ -21,6 +21,11 @@ const thermostatControlSequenceOfOperations = {
21
21
  5: 'cooling_and_heating_4-pipes_with_reheat',
22
22
  };
23
23
 
24
+ const thermostatProgrammingOperationModes = {
25
+ 0: 'setpoint',
26
+ 1: 'schedule',
27
+ };
28
+
24
29
  const thermostatSystemModes = {
25
30
  0: 'off',
26
31
  1: 'auto',
@@ -247,6 +252,7 @@ module.exports = {
247
252
  repInterval,
248
253
  defaultBindGroup,
249
254
  thermostatControlSequenceOfOperations,
255
+ thermostatProgrammingOperationModes,
250
256
  thermostatSystemModes,
251
257
  thermostatRunningStates,
252
258
  thermostatRunningMode,
package/lib/exposes.js CHANGED
@@ -378,11 +378,11 @@ class Climate extends Base {
378
378
  return this;
379
379
  }
380
380
 
381
- withSystemMode(modes, access=a.ALL) {
381
+ withSystemMode(modes, access=a.ALL, description='Mode of this device') {
382
382
  assert(!this.endpoint, 'Cannot add feature after adding endpoint');
383
383
  const allowed = ['off', 'heat', 'cool', 'auto', 'dry', 'fan_only', 'sleep', 'emergency_heating'];
384
384
  modes.forEach((m) => assert(allowed.includes(m)));
385
- this.features.push(new Enum('system_mode', access, modes).withDescription('Mode of this device'));
385
+ this.features.push(new Enum('system_mode', access, modes).withDescription(description));
386
386
  return this;
387
387
  }
388
388
 
@@ -574,6 +574,7 @@ module.exports = {
574
574
  power_outage_memory: () => new Binary('power_outage_memory', access.ALL, true, false).withDescription('Enable/disable the power outage memory, this recovers the on/off mode after power failure'),
575
575
  presence: () => new Binary('presence', access.STATE, true, false).withDescription('Indicates whether the device detected presence'),
576
576
  pressure: () => new Numeric('pressure', access.STATE).withUnit('hPa').withDescription('The measured atmospheric pressure'),
577
+ programming_operation_mode: () => new Enum('programming_operation_mode', access.ALL, ['setpoint', 'schedule']).withDescription('Controls how programming affects the thermostat. Possible values: setpoint (only use specified setpoint), schedule (follow programmed setpoint schedule). Changing this value does not clear programmed schedules.'),
577
578
  smoke: () => new Binary('smoke', access.STATE, true, false).withDescription('Indicates whether the device detected smoke'),
578
579
  soil_moisture: () => new Numeric('soil_moisture', access.STATE).withUnit('%').withDescription('Measured soil moisture value'),
579
580
  sos: () => new Binary('sos', access.STATE, true, false).withDescription('SOS alarm'),