zigbee-herdsman-converters 14.0.305 → 14.0.309

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.
package/README.md CHANGED
@@ -31,3 +31,4 @@ If any of those commands finish with an error your PR won't pass the tests and w
31
31
  - `battery`:
32
32
  - `{dontDividePercentage: true}`: prevents batteryPercentageRemainig from being divided (ZCL 200=100%, but some report 100=100%) (default: false)
33
33
  - `{voltageToPercentage: '3V_2100'}`: convert voltage to percentage using specified option. See utils.batteryVoltageToPercentage() (default: null, no voltage to percentage conversion)
34
+ - `fanStateOn`: value used for fan_mode when using fan_state="ON", the default is "on"
@@ -2798,6 +2798,7 @@ const converters = {
2798
2798
  const h = parseInt(value.substring(0, 4), 16);
2799
2799
  const s = parseInt(value.substring(4, 8), 16);
2800
2800
  const b = parseInt(value.substring(8, 12), 16);
2801
+ result.color_mode = 'hs';
2801
2802
  result.color = {b: mapNumberRange(b, 0, 1000, 0, 255), h, s: mapNumberRange(s, 0, 1000, 0, 100)};
2802
2803
  result.brightness = result.color.b;
2803
2804
  } else if (dp === tuya.dataPoints.silvercrestSetEffect) {
@@ -4751,6 +4752,10 @@ const converters = {
4751
4752
  const lookup = {4: 'anti_flicker_mode', 1: 'quick_mode'};
4752
4753
  payload.mode_switch = lookup[msg.data['4']];
4753
4754
  }
4755
+ if (msg.data.hasOwnProperty('10')) {
4756
+ const lookup = {1: 'toggle', 2: 'momentary'};
4757
+ payload.switch_type = lookup[msg.data['10']];
4758
+ }
4754
4759
  if (msg.data.hasOwnProperty('512')) {
4755
4760
  if (['ZNCZ15LM', 'QBCZ14LM', 'QBCZ15LM'].includes(model.model)) {
4756
4761
  payload.button_lock = msg.data['512'] === 1 ? 'OFF' : 'ON';
@@ -4840,7 +4845,7 @@ const converters = {
4840
4845
  }
4841
4846
 
4842
4847
  let buttonLookup = null;
4843
- if (['WXKG02LM_rev2', 'WXKG07LM'].includes(model.model)) buttonLookup = {1: 'left', 2: 'right', 3: 'both'};
4848
+ if (['WXKG02LM_rev2', 'WXKG07LM', 'WXKG17LM'].includes(model.model)) buttonLookup = {1: 'left', 2: 'right', 3: 'both'};
4844
4849
  if (['QBKG12LM', 'QBKG24LM'].includes(model.model)) buttonLookup = {5: 'left', 6: 'right', 7: 'both'};
4845
4850
  if (['QBKG25LM', 'QBKG26LM'].includes(model.model)) buttonLookup = {41: 'left', 42: 'center', 43: 'right'};
4846
4851
  if (['QBKG39LM', 'QBKG41LM', 'WS-EUK02', 'WS-EUK04', 'QBKG20LM', 'QBKG31LM'].includes(model.model)) {
@@ -4985,15 +4990,6 @@ const converters = {
4985
4990
  }
4986
4991
  },
4987
4992
  },
4988
- WSDCGQ11LM_pressure: {
4989
- cluster: 'msPressureMeasurement',
4990
- type: ['attributeReport', 'readResponse'],
4991
- options: [exposes.options.precision('pressure'), exposes.options.calibration('pressure')],
4992
- convert: (model, msg, publish, options, meta) => {
4993
- const pressure = msg.data.hasOwnProperty('16') ? parseFloat(msg.data['16']) / 10 : parseFloat(msg.data['measuredValue']);
4994
- return {pressure: calibrateAndPrecisionRoundOptions(pressure, options, 'pressure')};
4995
- },
4996
- },
4997
4993
  W2_module_carbon_monoxide: {
4998
4994
  cluster: 'ssIasZone',
4999
4995
  type: 'commandStatusChangeNotification',
@@ -7178,10 +7174,10 @@ const converters = {
7178
7174
  result.voltage_rms = (value[1] | value[0] << 8) / 10;
7179
7175
  }
7180
7176
  if (dp === tuya.dataPoints.hochCurrent) {
7181
- result.current = value[2] | value[1] << 8;
7177
+ result.current = (value[2] | value[1] << 8) / 1000;
7182
7178
  }
7183
7179
  if (dp === tuya.dataPoints.hochHistoricalCurrent) {
7184
- result.current_average = value[2] | value[1] << 8;
7180
+ result.current_average = (value[2] | value[1] << 8) / 1000;
7185
7181
  }
7186
7182
  if (dp === tuya.dataPoints.hochActivePower) {
7187
7183
  result.power = (value[2] | value[1] << 8) / 10;
@@ -1192,6 +1192,9 @@ const converters = {
1192
1192
  fan_mode: {
1193
1193
  key: ['fan_mode', 'fan_state'],
1194
1194
  convertSet: async (entity, key, value, meta) => {
1195
+ if (key == 'fan_state' && value.toLowerCase() == 'on') {
1196
+ value = utils.getMetaValue(entity, meta.mapped, 'fanStateOn', 'allEqual', 'on');
1197
+ }
1195
1198
  const fanMode = constants.fanMode[value.toLowerCase()];
1196
1199
  await entity.write('hvacFanCtrl', {fanMode});
1197
1200
  return {state: {fan_mode: value.toLowerCase(), fan_state: value.toLowerCase() === 'off' ? 'OFF' : 'ON'}};
@@ -2075,7 +2078,7 @@ const converters = {
2075
2078
  xiaomi_led_disabled_night: {
2076
2079
  key: ['led_disabled_night'],
2077
2080
  convertSet: async (entity, key, value, meta) => {
2078
- if (['ZNCZ04LM', 'ZNCZ15LM', 'QBCZ15LM', 'QBCZ14LM', 'QBKG20LM', 'QBKG25LM', 'QBKG19LM',
2081
+ if (['ZNCZ04LM', 'ZNCZ15LM', 'QBCZ15LM', 'QBCZ14LM', 'QBKG20LM', 'QBKG25LM', 'QBKG19LM', 'DLKZMK11LM',
2079
2082
  'QBKG34LM'].includes(meta.mapped.model)) {
2080
2083
  await entity.write('aqaraOpple', {0x0203: {value: value ? 1 : 0, type: 0x10}}, manufacturerOptions.xiaomi);
2081
2084
  } else if (['ZNCZ11LM'].includes(meta.mapped.model)) {
@@ -2090,7 +2093,7 @@ const converters = {
2090
2093
  return {state: {led_disabled_night: value}};
2091
2094
  },
2092
2095
  convertGet: async (entity, key, meta) => {
2093
- if (['ZNCZ04LM', 'ZNCZ15LM', 'QBCZ15LM', 'QBCZ14LM', 'QBKG20LM', 'QBKG25LM', 'QBKG19LM',
2096
+ if (['ZNCZ04LM', 'ZNCZ15LM', 'QBCZ15LM', 'QBCZ14LM', 'QBKG20LM', 'QBKG25LM', 'QBKG19LM', 'DLKZMK11LM',
2094
2097
  'QBKG34LM'].includes(meta.mapped.model)) {
2095
2098
  await entity.read('aqaraOpple', [0x0203], manufacturerOptions.xiaomi);
2096
2099
  } else {
@@ -6114,6 +6117,14 @@ const converters = {
6114
6117
  await endpoint.read('genOnOff', ['tuyaOperationMode']);
6115
6118
  },
6116
6119
  },
6120
+ xiaomi_switch_click_mode: {
6121
+ key: ['click_mode'],
6122
+ convertSet: async (entity, key, value, meta) => {
6123
+ const lookupState = {'fast': 0x1, 'multi': 0x02};
6124
+ await entity.write('aqaraOpple', {0x0125: {value: lookupState[value], type: 0x20}}, manufacturerOptions.xiaomi);
6125
+ return {state: {click_mode: value}};
6126
+ },
6127
+ },
6117
6128
  // #endregion
6118
6129
 
6119
6130
  // #region Ignore converters
package/devices/bitron.js CHANGED
@@ -1,7 +1,6 @@
1
1
  const exposes = require('../lib/exposes');
2
2
  const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/legacy').fromZigbee};
3
3
  const tz = require('../converters/toZigbee');
4
- const constants = require('../lib/constants');
5
4
  const reporting = require('../lib/reporting');
6
5
  const extend = require('../lib/extend');
7
6
  const e = exposes.presets;
@@ -199,7 +198,7 @@ module.exports = [
199
198
  'genBasic', 'genPowerCfg', 'genIdentify', 'genPollCtrl', 'hvacThermostat', 'hvacUserInterfaceCfg',
200
199
  ];
201
200
  await reporting.bind(endpoint, coordinatorEndpoint, binds);
202
- await reporting.thermostatTemperature(endpoint, {min: 900, max: constants.repInterval.HOUR, change: 1});
201
+ await reporting.thermostatTemperature(endpoint);
203
202
  await reporting.thermostatTemperatureCalibration(endpoint);
204
203
  await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
205
204
  await reporting.thermostatRunningState(endpoint);
package/devices/candeo.js CHANGED
@@ -13,7 +13,7 @@ module.exports = [
13
13
  const endpoint = device.getEndpoint(1);
14
14
  await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
15
15
  await reporting.onOff(endpoint);
16
- await reporting.brightness(endpoint, {min: 1});
16
+ await reporting.brightness(endpoint);
17
17
  },
18
18
  },
19
19
  ];
@@ -73,15 +73,15 @@ module.exports = [
73
73
 
74
74
  // standard ZCL attributes
75
75
  await reporting.batteryPercentageRemaining(endpoint);
76
- await reporting.thermostatTemperature(endpoint, {min: 0, max: constants.repInterval.HOUR, change: 5});
76
+ await reporting.thermostatTemperature(endpoint);
77
77
  await reporting.thermostatPIHeatingDemand(endpoint);
78
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint, {min: 0, max: constants.repInterval.HOUR, change: 5});
78
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
79
79
 
80
80
  // danfoss attributes
81
81
  await endpoint.configureReporting('hvacThermostat', [{
82
82
  attribute: 'danfossMountedModeActive',
83
83
  minimumReportInterval: constants.repInterval.MINUTE,
84
- maximumReportInterval: 43200,
84
+ maximumReportInterval: constants.repInterval.MAX,
85
85
  reportableChange: 1,
86
86
  }], options);
87
87
  await endpoint.configureReporting('hvacThermostat', [{
@@ -93,7 +93,7 @@ module.exports = [
93
93
  await endpoint.configureReporting('hvacThermostat', [{
94
94
  attribute: 'danfossHeatRequired',
95
95
  minimumReportInterval: constants.repInterval.MINUTE,
96
- maximumReportInterval: constants.repInterval.MINUTES_10,
96
+ maximumReportInterval: constants.repInterval.HOUR,
97
97
  reportableChange: 1,
98
98
  }], options);
99
99
  await endpoint.configureReporting('hvacThermostat', [{
@@ -1,5 +1,7 @@
1
1
  const reporting = require('../lib/reporting');
2
2
  const extend = require('../lib/extend');
3
+ const exposes = require('zigbee-herdsman-converters/lib/exposes');
4
+ const e = exposes.presets;
3
5
 
4
6
  module.exports = [
5
7
  {
@@ -26,4 +28,20 @@ module.exports = [
26
28
  await reporting.bind(endpoint, coordinatorEndpoint, ['genBasic', 'genIdentify', 'genOnOff']);
27
29
  },
28
30
  },
31
+ {
32
+ zigbeeModel: ['2CH-ZG-BOX-RELAY'],
33
+ model: '2CH-ZG-BOX-RELAY',
34
+ vendor: 'Envilar',
35
+ description: '2 channel box relay',
36
+ extend: extend.switch(),
37
+ exposes: [e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2')],
38
+ endpoint: (device) => {
39
+ return {'l1': 1, 'l2': 2};
40
+ },
41
+ meta: {multiEndpoint: true},
42
+ configure: async (device, coordinatorEndpoint, logger) => {
43
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
44
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
45
+ },
46
+ },
29
47
  ];
@@ -34,12 +34,12 @@ module.exports = [
34
34
  const endpoint = device.getEndpoint(1);
35
35
  const options = {manufacturerCode: 4151};
36
36
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'hvacThermostat']);
37
- await reporting.thermostatTemperature(endpoint, {min: 0, max: constants.repInterval.MINUTES_10, change: 25});
38
- await reporting.thermostatPIHeatingDemand(endpoint, {min: 0, max: constants.repInterval.MINUTES_10, change: 1});
39
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint, {min: 0, max: constants.repInterval.MINUTES_10, change: 25});
40
- await reporting.thermostatUnoccupiedHeatingSetpoint(endpoint, {min: 0, max: constants.repInterval.MINUTES_10, change: 25});
37
+ await reporting.thermostatTemperature(endpoint);
38
+ await reporting.thermostatPIHeatingDemand(endpoint);
39
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
40
+ await reporting.thermostatUnoccupiedHeatingSetpoint(endpoint);
41
41
  await endpoint.configureReporting('hvacThermostat', [{attribute: {ID: 0x4003, type: 41}, minimumReportInterval: 0,
42
- maximumReportInterval: constants.repInterval.MINUTES_10, reportableChange: 25}], options);
42
+ maximumReportInterval: constants.repInterval.HOUR, reportableChange: 25}], options);
43
43
  await endpoint.configureReporting('hvacThermostat', [{attribute: {ID: 0x4008, type: 34}, minimumReportInterval: 0,
44
44
  maximumReportInterval: constants.repInterval.HOUR, reportableChange: 1}], options);
45
45
  },
@@ -0,0 +1,20 @@
1
+ const fz = require('../converters/fromZigbee');
2
+ const tz = require('../converters/toZigbee');
3
+ const exposes = require('../lib/exposes');
4
+ const reporting = require('../lib/reporting');
5
+ const extend = require('../lib/extend');
6
+
7
+ module.exports = [
8
+ {
9
+ fingerprint: [{modelID: 'TS0001', manufacturerName: '_TZ3000_majwnphg'}],
10
+ model: 'JR-ZDS01',
11
+ vendor: 'Girier',
12
+ description: '1 gang mini switch',
13
+ toZigbee: extend.switch().toZigbee.concat([tz.moes_power_on_behavior, tz.tuya_switch_type]),
14
+ fromZigbee: extend.switch().fromZigbee.concat([fz.moes_power_on_behavior, fz.tuya_switch_type]),
15
+ exposes: extend.switch().exposes.concat([exposes.presets.power_on_behavior(), exposes.presets.switch_type_2()]),
16
+ configure: async (device, coordinatorEndpoint, logger) => {
17
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
18
+ },
19
+ },
20
+ ];
package/devices/heiman.js CHANGED
@@ -149,7 +149,7 @@ module.exports = [
149
149
  configure: async (device, coordinatorEndpoint, logger) => {
150
150
  const endpoint = device.getEndpoint(1);
151
151
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
152
- await reporting.batteryPercentageRemaining(endpoint, {min: constants.repInterval.MINUTES_5, max: constants.repInterval.HOUR});
152
+ await reporting.batteryPercentageRemaining(endpoint);
153
153
  await endpoint.read('genPowerCfg', ['batteryPercentageRemaining']);
154
154
  },
155
155
  exposes: [e.contact(), e.battery(), e.battery_low(), e.tamper()],
@@ -164,7 +164,7 @@ module.exports = [
164
164
  configure: async (device, coordinatorEndpoint, logger) => {
165
165
  const endpoint = device.getEndpoint(1);
166
166
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
167
- await reporting.batteryPercentageRemaining(endpoint, {min: constants.repInterval.MINUTES_5, max: constants.repInterval.HOUR});
167
+ await reporting.batteryPercentageRemaining(endpoint);
168
168
  await endpoint.read('genPowerCfg', ['batteryPercentageRemaining']);
169
169
  },
170
170
  exposes: [e.contact(), e.battery_low(), e.tamper(), e.battery()],
@@ -188,7 +188,7 @@ module.exports = [
188
188
  configure: async (device, coordinatorEndpoint, logger) => {
189
189
  const endpoint = device.getEndpoint(1);
190
190
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
191
- await reporting.batteryPercentageRemaining(endpoint, {min: constants.repInterval.MINUTES_5, max: constants.repInterval.HOUR});
191
+ await reporting.batteryPercentageRemaining(endpoint);
192
192
  await endpoint.read('genPowerCfg', ['batteryPercentageRemaining']);
193
193
  },
194
194
  exposes: [e.water_leak(), e.battery_low(), e.tamper(), e.battery()],
@@ -204,7 +204,7 @@ module.exports = [
204
204
  configure: async (device, coordinatorEndpoint, logger) => {
205
205
  const endpoint = device.getEndpoint(1);
206
206
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
207
- await reporting.batteryPercentageRemaining(endpoint, {min: constants.repInterval.MINUTES_5, max: constants.repInterval.HOUR});
207
+ await reporting.batteryPercentageRemaining(endpoint);
208
208
  await endpoint.read('genPowerCfg', ['batteryPercentageRemaining']);
209
209
  },
210
210
  },
@@ -219,7 +219,7 @@ module.exports = [
219
219
  configure: async (device, coordinatorEndpoint, logger) => {
220
220
  const endpoint = device.getEndpoint(1);
221
221
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
222
- await reporting.batteryPercentageRemaining(endpoint, {min: constants.repInterval.MINUTES_5, max: constants.repInterval.HOUR});
222
+ await reporting.batteryPercentageRemaining(endpoint);
223
223
  await endpoint.read('genPowerCfg', ['batteryPercentageRemaining']);
224
224
  },
225
225
  onEvent: async (type, data, device) => {
@@ -241,7 +241,7 @@ module.exports = [
241
241
  configure: async (device, coordinatorEndpoint, logger) => {
242
242
  const endpoint = device.getEndpoint(1);
243
243
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
244
- await reporting.batteryPercentageRemaining(endpoint, {min: constants.repInterval.MINUTES_5, max: constants.repInterval.HOUR});
244
+ await reporting.batteryPercentageRemaining(endpoint);
245
245
  await endpoint.read('genPowerCfg', ['batteryPercentageRemaining']);
246
246
  },
247
247
  },
@@ -334,7 +334,7 @@ module.exports = [
334
334
  const endpoint1 = device.getEndpoint(1);
335
335
  await reporting.bind(endpoint1, coordinatorEndpoint, ['msTemperatureMeasurement', 'genPowerCfg']);
336
336
  await reporting.temperature(endpoint1);
337
- await reporting.batteryPercentageRemaining(endpoint1, {min: constants.repInterval.MINUTES_5, max: constants.repInterval.HOUR});
337
+ await reporting.batteryPercentageRemaining(endpoint1);
338
338
  await endpoint1.read('genPowerCfg', ['batteryPercentageRemaining']);
339
339
 
340
340
  const endpoint2 = device.getEndpoint(2);
@@ -405,7 +405,7 @@ module.exports = [
405
405
  const bindClusters = ['msTemperatureMeasurement', 'msRelativeHumidity', 'genPowerCfg'];
406
406
  await reporting.bind(endpoint, coordinatorEndpoint, bindClusters);
407
407
  await reporting.temperature(endpoint);
408
- await reporting.humidity(endpoint, {min: 0, change: 25});
408
+ await reporting.humidity(endpoint);
409
409
  await reporting.batteryVoltage(endpoint);
410
410
  },
411
411
  exposes: [e.temperature(), e.humidity(), e.battery()],
@@ -421,7 +421,7 @@ module.exports = [
421
421
  configure: async (device, coordinatorEndpoint, logger) => {
422
422
  const endpoint = device.getEndpoint(1);
423
423
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
424
- await reporting.batteryPercentageRemaining(endpoint, {min: constants.repInterval.MINUTES_5, max: constants.repInterval.HOUR});
424
+ await reporting.batteryPercentageRemaining(endpoint);
425
425
  await endpoint.read('genPowerCfg', ['batteryPercentageRemaining']);
426
426
  },
427
427
  },
@@ -436,7 +436,7 @@ module.exports = [
436
436
  configure: async (device, coordinatorEndpoint, logger) => {
437
437
  const endpoint = device.getEndpoint(1);
438
438
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'heimanSpecificScenes']);
439
- await reporting.batteryPercentageRemaining(endpoint, {min: constants.repInterval.MINUTES_5, max: constants.repInterval.HOUR});
439
+ await reporting.batteryPercentageRemaining(endpoint);
440
440
  },
441
441
  },
442
442
  {
@@ -468,7 +468,7 @@ module.exports = [
468
468
  configure: async (device, coordinatorEndpoint, logger) => {
469
469
  const endpoint = device.getEndpoint(1);
470
470
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
471
- await reporting.batteryPercentageRemaining(endpoint, {min: constants.repInterval.MINUTES_5, max: constants.repInterval.HOUR});
471
+ await reporting.batteryPercentageRemaining(endpoint);
472
472
  await endpoint.read('genPowerCfg', ['batteryPercentageRemaining']);
473
473
  },
474
474
  exposes: [e.vibration(), e.battery_low(), e.tamper(), e.battery()],
@@ -483,7 +483,7 @@ module.exports = [
483
483
  configure: async (device, coordinatorEndpoint, logger) => {
484
484
  const endpoint = device.getEndpoint(1);
485
485
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
486
- await reporting.batteryPercentageRemaining(endpoint, {min: constants.repInterval.MINUTES_5, max: constants.repInterval.HOUR});
486
+ await reporting.batteryPercentageRemaining(endpoint);
487
487
  await endpoint.read('genPowerCfg', ['batteryPercentageRemaining']);
488
488
  },
489
489
  exposes: [e.vibration(), e.battery_low(), e.tamper(), e.battery()],
@@ -564,7 +564,7 @@ module.exports = [
564
564
  configure: async (device, coordinatorEndpoint, logger) => {
565
565
  const endpoint = device.getEndpoint(1);
566
566
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'heimanSpecificInfraRedRemote']);
567
- await reporting.batteryPercentageRemaining(endpoint, {min: constants.repInterval.MINUTES_5, max: constants.repInterval.HOUR});
567
+ await reporting.batteryPercentageRemaining(endpoint);
568
568
  },
569
569
  },
570
570
  {
package/devices/hive.js CHANGED
@@ -213,15 +213,15 @@ module.exports = [
213
213
 
214
214
  // standard ZCL attributes
215
215
  await reporting.batteryPercentageRemaining(endpoint);
216
- await reporting.thermostatTemperature(endpoint, {min: 0, max: constants.repInterval.HOUR, change: 5});
216
+ await reporting.thermostatTemperature(endpoint);
217
217
  await reporting.thermostatPIHeatingDemand(endpoint);
218
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint, {min: 0, max: constants.repInterval.HOUR, change: 5});
218
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
219
219
 
220
220
  // danfoss attributes
221
221
  await endpoint.configureReporting('hvacThermostat', [{
222
222
  attribute: 'danfossMountedModeActive',
223
223
  minimumReportInterval: constants.repInterval.MINUTE,
224
- maximumReportInterval: 43200,
224
+ maximumReportInterval: constants.repInterval.MAX,
225
225
  reportableChange: 1,
226
226
  }], options);
227
227
  await endpoint.configureReporting('hvacThermostat', [{
@@ -233,7 +233,7 @@ module.exports = [
233
233
  await endpoint.configureReporting('hvacThermostat', [{
234
234
  attribute: 'danfossHeatRequired',
235
235
  minimumReportInterval: constants.repInterval.MINUTE,
236
- maximumReportInterval: constants.repInterval.MINUTES_10,
236
+ maximumReportInterval: constants.repInterval.HOUR,
237
237
  reportableChange: 1,
238
238
  }], options);
239
239
  await endpoint.configureReporting('hvacThermostat', [{
@@ -293,12 +293,12 @@ module.exports = [
293
293
  const endpoint = device.getEndpoint(5);
294
294
  const binds = ['genBasic', 'genIdentify', 'genAlarms', 'genTime', 'hvacThermostat'];
295
295
  await reporting.bind(endpoint, coordinatorEndpoint, binds);
296
- await reporting.thermostatTemperature(endpoint, {min: 0, max: constants.repInterval.HOUR, change: 5});
297
- await reporting.thermostatRunningState(endpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
298
- await reporting.thermostatSystemMode(endpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
299
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint, {min: 0, max: constants.repInterval.HOUR, change: 5});
300
- await reporting.thermostatTemperatureSetpointHold(endpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
301
- await reporting.thermostatTemperatureSetpointHoldDuration(endpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
296
+ await reporting.thermostatTemperature(endpoint);
297
+ await reporting.thermostatRunningState(endpoint);
298
+ await reporting.thermostatSystemMode(endpoint);
299
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
300
+ await reporting.thermostatTemperatureSetpointHold(endpoint);
301
+ await reporting.thermostatTemperatureSetpointHoldDuration(endpoint);
302
302
  },
303
303
  },
304
304
  {
@@ -324,12 +324,12 @@ module.exports = [
324
324
  const endpoint = device.getEndpoint(5);
325
325
  const binds = ['genBasic', 'genIdentify', 'genAlarms', 'genTime', 'hvacThermostat'];
326
326
  await reporting.bind(endpoint, coordinatorEndpoint, binds);
327
- await reporting.thermostatTemperature(endpoint, {min: 0, max: constants.repInterval.HOUR, change: 5});
328
- await reporting.thermostatRunningState(endpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
329
- await reporting.thermostatSystemMode(endpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
330
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint, {min: 0, max: constants.repInterval.HOUR, change: 5});
331
- await reporting.thermostatTemperatureSetpointHold(endpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
332
- await reporting.thermostatTemperatureSetpointHoldDuration(endpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
327
+ await reporting.thermostatTemperature(endpoint);
328
+ await reporting.thermostatRunningState(endpoint);
329
+ await reporting.thermostatSystemMode(endpoint);
330
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
331
+ await reporting.thermostatTemperatureSetpointHold(endpoint);
332
+ await reporting.thermostatTemperatureSetpointHoldDuration(endpoint);
333
333
  },
334
334
  },
335
335
  {
@@ -352,18 +352,18 @@ module.exports = [
352
352
  'genBasic', 'genIdentify', 'genAlarms', 'genTime', 'hvacThermostat',
353
353
  ];
354
354
  await reporting.bind(heatEndpoint, coordinatorEndpoint, binds);
355
- await reporting.thermostatTemperature(heatEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 5});
356
- await reporting.thermostatRunningState(heatEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
357
- await reporting.thermostatSystemMode(heatEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
358
- await reporting.thermostatOccupiedHeatingSetpoint(heatEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 5});
359
- await reporting.thermostatTemperatureSetpointHold(heatEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
360
- await reporting.thermostatTemperatureSetpointHoldDuration(heatEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
355
+ await reporting.thermostatTemperature(heatEndpoint);
356
+ await reporting.thermostatRunningState(heatEndpoint);
357
+ await reporting.thermostatSystemMode(heatEndpoint);
358
+ await reporting.thermostatOccupiedHeatingSetpoint(heatEndpoint);
359
+ await reporting.thermostatTemperatureSetpointHold(heatEndpoint);
360
+ await reporting.thermostatTemperatureSetpointHoldDuration(heatEndpoint);
361
361
  await reporting.bind(waterEndpoint, coordinatorEndpoint, binds);
362
- await reporting.thermostatRunningState(waterEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
363
- await reporting.thermostatSystemMode(waterEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
364
- await reporting.thermostatOccupiedHeatingSetpoint(waterEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 5});
365
- await reporting.thermostatTemperatureSetpointHold(waterEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
366
- await reporting.thermostatTemperatureSetpointHoldDuration(waterEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
362
+ await reporting.thermostatRunningState(waterEndpoint);
363
+ await reporting.thermostatSystemMode(waterEndpoint);
364
+ await reporting.thermostatOccupiedHeatingSetpoint(waterEndpoint);
365
+ await reporting.thermostatTemperatureSetpointHold(waterEndpoint);
366
+ await reporting.thermostatTemperatureSetpointHoldDuration(waterEndpoint);
367
367
  },
368
368
  exposes: [
369
369
  exposes.climate().withSetpoint('occupied_heating_setpoint', 5, 32, 0.5).withLocalTemperature()
@@ -403,18 +403,18 @@ module.exports = [
403
403
  'genBasic', 'genIdentify', 'genAlarms', 'genTime', 'hvacThermostat',
404
404
  ];
405
405
  await reporting.bind(heatEndpoint, coordinatorEndpoint, binds);
406
- await reporting.thermostatTemperature(heatEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 5});
407
- await reporting.thermostatRunningState(heatEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
408
- await reporting.thermostatSystemMode(heatEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
409
- await reporting.thermostatOccupiedHeatingSetpoint(heatEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 5});
410
- await reporting.thermostatTemperatureSetpointHold(heatEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
411
- await reporting.thermostatTemperatureSetpointHoldDuration(heatEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
406
+ await reporting.thermostatTemperature(heatEndpoint);
407
+ await reporting.thermostatRunningState(heatEndpoint);
408
+ await reporting.thermostatSystemMode(heatEndpoint);
409
+ await reporting.thermostatOccupiedHeatingSetpoint(heatEndpoint);
410
+ await reporting.thermostatTemperatureSetpointHold(heatEndpoint);
411
+ await reporting.thermostatTemperatureSetpointHoldDuration(heatEndpoint);
412
412
  await reporting.bind(waterEndpoint, coordinatorEndpoint, binds);
413
- await reporting.thermostatRunningState(waterEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
414
- await reporting.thermostatSystemMode(waterEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
415
- await reporting.thermostatOccupiedHeatingSetpoint(waterEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 5});
416
- await reporting.thermostatTemperatureSetpointHold(waterEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
417
- await reporting.thermostatTemperatureSetpointHoldDuration(waterEndpoint, {min: 0, max: constants.repInterval.HOUR, change: 1});
413
+ await reporting.thermostatRunningState(waterEndpoint);
414
+ await reporting.thermostatSystemMode(waterEndpoint);
415
+ await reporting.thermostatOccupiedHeatingSetpoint(waterEndpoint);
416
+ await reporting.thermostatTemperatureSetpointHold(waterEndpoint);
417
+ await reporting.thermostatTemperatureSetpointHoldDuration(waterEndpoint);
418
418
  },
419
419
  exposes: [
420
420
  exposes.climate().withSetpoint('occupied_heating_setpoint', 5, 32, 0.5).withLocalTemperature()
package/devices/ikea.js CHANGED
@@ -446,8 +446,8 @@ module.exports = [
446
446
  model: 'E1812',
447
447
  vendor: 'IKEA',
448
448
  description: 'TRADFRI shortcut button',
449
- fromZigbee: [fz.command_on, fz.command_move, fz.command_stop, fz.battery],
450
- exposes: [e.battery(), e.action(['on', 'brightness_move_up', 'brightness_stop'])],
449
+ fromZigbee: [fz.command_on, fz.command_off, fz.command_move, fz.command_stop, fz.battery],
450
+ exposes: [e.battery(), e.action(['on', 'off', 'brightness_move_up', 'brightness_stop'])],
451
451
  toZigbee: [],
452
452
  ota: ota.tradfri,
453
453
  meta: {disableActionGroup: true, battery: {dontDividePercentage: true}},
@@ -625,7 +625,8 @@ module.exports = [
625
625
  model: 'E2007',
626
626
  vendor: 'IKEA',
627
627
  description: 'STARKVIND air purifier',
628
- exposes: [e.fan().withModes(['off', 'low', 'medium', 'high', 'on', 'auto'])],
628
+ exposes: [e.fan().withModes(['off', 'low', 'medium', 'high', 'auto'])],
629
+ meta: {fanStateOn: 'auto'},
629
630
  fromZigbee: [fz.fan],
630
631
  toZigbee: [tz.fan_mode],
631
632
  configure: async (device, coordinatorEndpoint, logger) => {
package/devices/moes.js CHANGED
@@ -288,11 +288,13 @@ module.exports = [
288
288
  exposes.binary('motor_reversal', ea.ALL, 'ON', 'OFF')],
289
289
  },
290
290
  {
291
- fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_e9ba97vf'}],
291
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_e9ba97vf'},
292
+ {modelID: 'TS0601', manufacturerName: '_TZE200_husqqvux'}],
292
293
  model: 'TV01-ZB',
293
294
  vendor: 'Moes',
294
295
  description: 'Thermostat radiator valve',
295
296
  fromZigbee: [fz.moes_thermostat_tv, fz.ignore_tuya_set_time],
297
+ whiteLabel: [{vendor: 'Tesla Smart', model: 'TSL-TRV-TV01ZG'}],
296
298
  toZigbee: [tz.moes_thermostat_tv],
297
299
  exposes: [
298
300
  e.battery(), e.child_lock(), e.window_detection(),
@@ -564,6 +564,15 @@ module.exports = [
564
564
  extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
565
565
  ota: ota.zigbeeOTA,
566
566
  },
567
+ {
568
+ zigbeeModel: ['LTA010'],
569
+ model: '9290024683',
570
+ vendor: 'Philips',
571
+ description: 'Hue white ambiance A19 1100lm with Bluetooth',
572
+ meta: {turnsOffAtBrightness1: true},
573
+ extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
574
+ ota: ota.zigbeeOTA,
575
+ },
567
576
  {
568
577
  zigbeeModel: ['LTA008'],
569
578
  model: '9290022267A',
package/devices/popp.js CHANGED
@@ -73,15 +73,15 @@ module.exports = [
73
73
 
74
74
  // standard ZCL attributes
75
75
  await reporting.batteryPercentageRemaining(endpoint);
76
- await reporting.thermostatTemperature(endpoint, {min: 0, max: constants.repInterval.HOUR, change: 5});
76
+ await reporting.thermostatTemperature(endpoint);
77
77
  await reporting.thermostatPIHeatingDemand(endpoint);
78
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint, {min: 0, max: constants.repInterval.HOUR, change: 5});
78
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
79
79
 
80
80
  // danfoss attributes
81
81
  await endpoint.configureReporting('hvacThermostat', [{
82
82
  attribute: 'danfossMountedModeActive',
83
83
  minimumReportInterval: constants.repInterval.MINUTE,
84
- maximumReportInterval: 43200,
84
+ maximumReportInterval: constants.repInterval.MAX,
85
85
  reportableChange: 1,
86
86
  }], options);
87
87
  await endpoint.configureReporting('hvacThermostat', [{
@@ -93,7 +93,7 @@ module.exports = [
93
93
  await endpoint.configureReporting('hvacThermostat', [{
94
94
  attribute: 'danfossHeatRequired',
95
95
  minimumReportInterval: constants.repInterval.MINUTE,
96
- maximumReportInterval: constants.repInterval.MINUTES_10,
96
+ maximumReportInterval: constants.repInterval.HOUR,
97
97
  reportableChange: 1,
98
98
  }], options);
99
99
  await endpoint.configureReporting('hvacThermostat', [{
@@ -23,9 +23,9 @@ module.exports = [
23
23
  const binds = ['genBasic', 'genPowerCfg', 'hvacThermostat', 'haDiagnostic'];
24
24
  await reporting.bind(endpoint, coordinatorEndpoint, binds);
25
25
  await reporting.batteryVoltage(endpoint);
26
- await reporting.thermostatTemperature(endpoint, {min: 0, max: constants.repInterval.MINUTES_15, change: 25});
27
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint, {min: 0, max: constants.repInterval.MINUTES_15, change: 25});
28
- await reporting.thermostatPIHeatingDemand(endpoint, {min: 0, max: constants.repInterval.MINUTES_15, change: 1});
26
+ await reporting.thermostatTemperature(endpoint);
27
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
28
+ await reporting.thermostatPIHeatingDemand(endpoint);
29
29
  // bind of hvacUserInterfaceCfg fails with 'Table Full', does this have any effect?
30
30
  await endpoint.configureReporting('hvacUserInterfaceCfg', [{attribute: 'keypadLockout', reportableChange: 1,
31
31
  minimumReportInterval: constants.repInterval.MINUTE, maximumReportInterval: constants.repInterval.HOUR}]);
@@ -354,8 +354,8 @@ module.exports = [
354
354
  const endpoint1 = device.getEndpoint(1);
355
355
  const endpoint2 = device.getEndpoint(2);
356
356
  await reporting.bind(endpoint1, coordinatorEndpoint, ['hvacThermostat']);
357
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint1, {min: 0, max: 60, change: 1});
358
- await reporting.thermostatPIHeatingDemand(endpoint1, {min: 0, max: 60, change: 1});
357
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint1);
358
+ await reporting.thermostatPIHeatingDemand(endpoint1);
359
359
  await reporting.bind(endpoint2, coordinatorEndpoint, ['seMetering']);
360
360
  await reporting.instantaneousDemand(endpoint2, {min: 0, max: 60, change: 1});
361
361
  await reporting.currentSummDelivered(endpoint2, {min: 0, max: 60, change: 1});
@@ -458,9 +458,8 @@ module.exports = [
458
458
  const binds = ['genBasic', 'genPowerCfg', 'hvacThermostat'];
459
459
  await reporting.bind(endpoint, coordinatorEndpointB, binds);
460
460
  await reporting.batteryVoltage(endpoint);
461
- await reporting.thermostatTemperature(endpoint, {min: constants.repInterval.MINUTE,
462
- max: constants.repInterval.MINUTES_15, change: 50});
463
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint, {min: 0, max: constants.repInterval.MINUTES_15, change: 25});
461
+ await reporting.thermostatTemperature(endpoint);
462
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
464
463
  await endpoint.configureReporting('hvacUserInterfaceCfg', [{attribute: 'keypadLockout',
465
464
  minimumReportInterval: constants.repInterval.MINUTE,
466
465
  maximumReportInterval: constants.repInterval.HOUR,
@@ -514,7 +513,7 @@ module.exports = [
514
513
  const endpoint = device.getEndpoint(11);
515
514
  const binds = ['genBasic', 'genPowerCfg', 'hvacThermostat', 'msTemperatureMeasurement'];
516
515
  await reporting.bind(endpoint, coordinatorEndpoint, binds);
517
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint, {min: 0, max: constants.repInterval.MINUTES_15, change: 25});
516
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
518
517
  },
519
518
  },
520
519
  {
package/devices/sinope.js CHANGED
@@ -29,12 +29,12 @@ module.exports = [
29
29
  'haElectricalMeasurement', 'seMetering', 'manuSpecificSinope'];
30
30
 
31
31
  await reporting.bind(endpoint, coordinatorEndpoint, binds);
32
- await reporting.thermostatTemperature(endpoint, {min: 10, max: 300, change: 20});
33
- await reporting.thermostatPIHeatingDemand(endpoint, {min: 10, max: 301, change: 5});
34
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint, {min: 1, max: 302, change: 50});
32
+ await reporting.thermostatTemperature(endpoint);
33
+ await reporting.thermostatPIHeatingDemand(endpoint);
34
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
35
35
 
36
36
  try {
37
- await reporting.thermostatSystemMode(endpoint, {min: 1, max: 0});
37
+ await reporting.thermostatSystemMode(endpoint);
38
38
  await reporting.thermostatRunningState(endpoint);
39
39
  await reporting.readMeteringMultiplierDivisor(endpoint);
40
40
  await reporting.currentSummDelivered(endpoint, {min: 10, max: 303, change: [1, 1]});
@@ -71,9 +71,9 @@ module.exports = [
71
71
  const binds = ['genBasic', 'genIdentify', 'genGroups', 'hvacThermostat', 'hvacUserInterfaceCfg', 'msTemperatureMeasurement',
72
72
  'haElectricalMeasurement', 'seMetering', 'manuSpecificSinope'];
73
73
  await reporting.bind(endpoint, coordinatorEndpoint, binds);
74
- await reporting.thermostatTemperature(endpoint, {min: 10, max: 300, change: 20});
75
- await reporting.thermostatPIHeatingDemand(endpoint, {min: 10, max: 301, change: 5});
76
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint, {min: 1, max: 302, change: 50});
74
+ await reporting.thermostatTemperature(endpoint);
75
+ await reporting.thermostatPIHeatingDemand(endpoint);
76
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
77
77
 
78
78
  try {
79
79
  await reporting.thermostatRunningState(endpoint);
@@ -97,7 +97,7 @@ module.exports = [
97
97
  } catch (error) {/* Do nothing*/}
98
98
 
99
99
  try {
100
- await reporting.thermostatKeypadLockMode(endpoint, {min: 1, max: 0});
100
+ await reporting.thermostatKeypadLockMode(endpoint);
101
101
  } catch (error) {
102
102
  // Not all support this: https://github.com/Koenkk/zigbee2mqtt/issues/3760
103
103
  }
@@ -130,16 +130,16 @@ module.exports = [
130
130
  const binds = ['genBasic', 'genIdentify', 'genGroups', 'hvacThermostat', 'hvacUserInterfaceCfg',
131
131
  'msTemperatureMeasurement', 'manuSpecificSinope'];
132
132
  await reporting.bind(endpoint, coordinatorEndpoint, binds);
133
- await reporting.thermostatTemperature(endpoint, {min: 10, max: 300, change: 20});
134
- await reporting.thermostatPIHeatingDemand(endpoint, {min: 10, max: 301, change: 5});
135
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint, {min: 1, max: 302, change: 50});
133
+ await reporting.thermostatTemperature(endpoint);
134
+ await reporting.thermostatPIHeatingDemand(endpoint);
135
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
136
136
 
137
137
  try {
138
138
  await reporting.thermostatRunningState(endpoint);
139
139
  } catch (error) {/* Not all support this */}
140
140
 
141
141
  try {
142
- await reporting.thermostatKeypadLockMode(endpoint, {min: 1, max: 0});
142
+ await reporting.thermostatKeypadLockMode(endpoint);
143
143
  } catch (error) {
144
144
  // Not all support this: https://github.com/Koenkk/zigbee2mqtt/issues/3760
145
145
  }
@@ -156,14 +156,14 @@ module.exports = [
156
156
  model: 'TH1400ZB',
157
157
  vendor: 'Sinopé',
158
158
  description: 'Zigbee low volt thermostat',
159
- fromZigbee: [fz.legacy.sinope_thermostat_att_report],
159
+ fromZigbee: [fz.legacy.sinope_thermostat_att_report, fz.legacy.sinope_thermostat_state],
160
160
  toZigbee: [tz.thermostat_local_temperature, tz.thermostat_occupied_heating_setpoint, tz.thermostat_temperature_display_mode,
161
161
  tz.thermostat_keypad_lockout, tz.thermostat_system_mode, tz.thermostat_running_state,
162
162
  tz.sinope_thermostat_backlight_autodim_param, tz.sinope_thermostat_time, tz.sinope_thermostat_enable_outdoor_temperature,
163
163
  tz.sinope_thermostat_outdoor_temperature],
164
164
  exposes: [exposes.climate().withSetpoint('occupied_heating_setpoint', 7, 30, 1).withLocalTemperature()
165
- .withSystemMode(['off', 'auto', 'heat']).withRunningState(['idle', 'heat']), exposes.enum('backlight_auto_dim',
166
- ea.SET, ['on demand', 'sensing']).withDescription('Control backlight dimming behavior')],
165
+ .withSystemMode(['off', 'auto', 'heat']).withRunningState(['idle', 'heat']).withPiHeatingDemand(), exposes.enum(
166
+ 'backlight_auto_dim', ea.SET, ['on demand', 'sensing']).withDescription('Control backlight dimming behavior')],
167
167
  configure: async (device, coordinatorEndpoint, logger) => {
168
168
  const endpoint = device.getEndpoint(1);
169
169
  const binds = ['genBasic', 'genIdentify', 'genGroups', 'hvacThermostat', 'hvacUserInterfaceCfg', 'msTemperatureMeasurement'];
@@ -3,6 +3,7 @@ const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/lega
3
3
  const tz = require('../converters/toZigbee');
4
4
  const reporting = require('../lib/reporting');
5
5
  const e = exposes.presets;
6
+ const constants = require('../lib/constants');
6
7
 
7
8
  module.exports = [
8
9
  {
@@ -23,14 +24,18 @@ module.exports = [
23
24
  await reporting.bind(endpoint, coordinatorEndpoint, binds);
24
25
 
25
26
  // Those exact parameters (min/max/change) are required for reporting to work with Stelpro Ki
26
- await reporting.thermostatTemperature(endpoint, {min: 10, max: 60, change: 50});
27
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint, {min: 1, max: 0, change: 50});
28
- await reporting.thermostatSystemMode(endpoint, {min: 1, max: 0});
29
- await reporting.thermostatPIHeatingDemand(endpoint, {min: 1, max: 900, change: 5});
30
- await reporting.thermostatKeypadLockMode(endpoint, {min: 1, max: 0});
27
+ await reporting.thermostatTemperature(endpoint);
28
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
29
+ await reporting.thermostatSystemMode(endpoint);
30
+ await reporting.thermostatPIHeatingDemand(endpoint);
31
+ await reporting.thermostatKeypadLockMode(endpoint);
31
32
  // cluster 0x0201 attribute 0x401c
32
- await endpoint.configureReporting('hvacThermostat', [{attribute: 'StelproSystemMode', minimumReportInterval: 1,
33
- maximumReportInterval: 0}]);
33
+ await endpoint.configureReporting('hvacThermostat', [{
34
+ attribute: 'StelproSystemMode',
35
+ minimumReportInterval: constants.repInterval.MINUTE,
36
+ maximumReportInterval: constants.repInterval.HOUR,
37
+ reportableChange: 1,
38
+ }]);
34
39
  },
35
40
  },
36
41
  {
@@ -51,14 +56,18 @@ module.exports = [
51
56
  await reporting.bind(endpoint, coordinatorEndpoint, binds);
52
57
 
53
58
  // Those exact parameters (min/max/change) are required for reporting to work with Stelpro Ki
54
- await reporting.thermostatTemperature(endpoint, {min: 10, max: 60, change: 50});
55
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint, {min: 1, max: 0, change: 50});
56
- await reporting.thermostatSystemMode(endpoint, {min: 1, max: 0});
57
- await reporting.thermostatPIHeatingDemand(endpoint, {min: 1, max: 900, change: 5});
58
- await reporting.thermostatKeypadLockMode(endpoint, {min: 1, max: 0});
59
+ await reporting.thermostatTemperature(endpoint);
60
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
61
+ await reporting.thermostatSystemMode(endpoint);
62
+ await reporting.thermostatPIHeatingDemand(endpoint);
63
+ await reporting.thermostatKeypadLockMode(endpoint);
59
64
  // cluster 0x0201 attribute 0x401c
60
- await endpoint.configureReporting('hvacThermostat', [{attribute: 'StelproSystemMode',
61
- minimumReportInterval: 1, maximumReportInterval: 0}]);
65
+ await endpoint.configureReporting('hvacThermostat', [{
66
+ attribute: 'StelproSystemMode',
67
+ minimumReportInterval: constants.repInterval.MINUTE,
68
+ maximumReportInterval: constants.repInterval.HOUR,
69
+ reportableChange: 1,
70
+ }]);
62
71
  },
63
72
  },
64
73
  {
@@ -80,15 +89,18 @@ module.exports = [
80
89
  await reporting.bind(endpoint, coordinatorEndpoint, binds);
81
90
 
82
91
  // Those exact parameters (min/max/change) are required for reporting to work with Stelpro Maestro
83
- await reporting.thermostatTemperature(endpoint, {min: 10, max: 60, change: 50});
84
- await reporting.humidity(endpoint, {min: 10, max: 300, change: 1});
85
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint, {min: 1, max: 0, change: 50});
86
- await reporting.thermostatSystemMode(endpoint, {min: 1, max: 0});
87
- await reporting.thermostatPIHeatingDemand(endpoint, {min: 1, max: 900, change: 5});
88
- await reporting.thermostatKeypadLockMode(endpoint, {min: 1, max: 0});
92
+ await reporting.thermostatTemperature(endpoint);
93
+ await reporting.humidity(endpoint);
94
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
95
+ await reporting.thermostatSystemMode(endpoint);
96
+ await reporting.thermostatPIHeatingDemand(endpoint);
97
+ await reporting.thermostatKeypadLockMode(endpoint);
89
98
  // cluster 0x0201 attribute 0x401c
90
99
  await endpoint.configureReporting('hvacThermostat', [{
91
- attribute: 'StelproSystemMode', minimumReportInterval: 1, maximumReportInterval: 0}]);
100
+ attribute: 'StelproSystemMode',
101
+ minimumReportInterval: constants.repInterval.MINUTE,
102
+ maximumReportInterval: constants.repInterval.HOUR,
103
+ reportableChange: 1}]);
92
104
  },
93
105
  },
94
106
  {
@@ -110,15 +122,18 @@ module.exports = [
110
122
  await reporting.bind(endpoint, coordinatorEndpoint, binds);
111
123
 
112
124
  // Those exact parameters (min/max/change) are required for reporting to work with Stelpro Maestro
113
- await reporting.thermostatTemperature(endpoint, {min: 10, max: 60, change: 50});
114
- await reporting.humidity(endpoint, {min: 10, max: 300, change: 1});
115
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint, {min: 1, max: 0, change: 50});
116
- await reporting.thermostatSystemMode(endpoint, {min: 1, max: 0});
117
- await reporting.thermostatPIHeatingDemand(endpoint, {min: 1, max: 900, change: 5});
118
- await reporting.thermostatKeypadLockMode(endpoint, {min: 1, max: 0});
125
+ await reporting.thermostatTemperature(endpoint);
126
+ await reporting.humidity(endpoint);
127
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
128
+ await reporting.thermostatSystemMode(endpoint);
129
+ await reporting.thermostatPIHeatingDemand(endpoint);
130
+ await reporting.thermostatKeypadLockMode(endpoint);
119
131
  // cluster 0x0201 attribute 0x401c
120
132
  await endpoint.configureReporting('hvacThermostat', [{
121
- attribute: 'StelproSystemMode', minimumReportInterval: 1, maximumReportInterval: 0}]);
133
+ attribute: 'StelproSystemMode',
134
+ minimumReportInterval: constants.repInterval.MINUTE,
135
+ maximumReportInterval: constants.repInterval.HOUR,
136
+ reportableChange: 1}]);
122
137
  },
123
138
  },
124
139
  ];
package/devices/tuya.js CHANGED
@@ -750,7 +750,8 @@ module.exports = [
750
750
  {
751
751
  zigbeeModel: ['kud7u2l'],
752
752
  fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_ckud7u2l'}, {modelID: 'TS0601', manufacturerName: '_TZE200_ywdxldoj'},
753
- {modelID: 'TS0601', manufacturerName: '_TZE200_cwnjrr72'}, {modelID: 'TS0601', manufacturerName: '_TZE200_chyvmhay'}],
753
+ {modelID: 'TS0601', manufacturerName: '_TZE200_cwnjrr72'}, {modelID: 'TS0601', manufacturerName: '_TZE200_chyvmhay'},
754
+ {modelID: 'TS0601', manufacturerName: '_TZE200_pvvbommb'}],
754
755
  model: 'TS0601_thermostat',
755
756
  vendor: 'TuYa',
756
757
  description: 'Radiator valve with thermostat',
@@ -914,11 +915,12 @@ module.exports = [
914
915
  {modelID: 'TS011F', manufacturerName: '_TZ3000_ew3ldmgx'},
915
916
  {modelID: 'TS011F', manufacturerName: '_TZ3000_ps3dmato'},
916
917
  {modelID: 'TS011F', manufacturerName: '_TZ3000_mraovvmm'},
917
- {modelID: 'TS011F', manufacturerName: '_TZ3000_jvzvulen'}],
918
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_jvzvulen'},
919
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_w0qqde0g'}],
918
920
  model: 'TS011F_plug_1',
919
921
  description: 'Smart plug (with power monitoring)',
920
922
  vendor: 'TuYa',
921
- whiteLabel: [{vendor: 'LELLKI', model: 'TS011F_plug'}],
923
+ whiteLabel: [{vendor: 'LELLKI', model: 'TS011F_plug'}, {vendor: 'NEO', model: 'NAS-WR01B'}],
922
924
  fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering, fz.ignore_basic_report, fz.tuya_switch_power_outage_memory],
923
925
  toZigbee: [tz.on_off, tz.tuya_switch_power_outage_memory],
924
926
  configure: async (device, coordinatorEndpoint, logger) => {
@@ -1501,8 +1503,8 @@ module.exports = [
1501
1503
  exposes.numeric('countdown_timer', ea.STATE_SET).withValueMin(0).withValueMax(86400).withUnit('s'),
1502
1504
  exposes.numeric('voltage', ea.STATE).withUnit('V'),
1503
1505
  exposes.numeric('voltage_rms', ea.STATE).withUnit('V'),
1504
- exposes.numeric('current', ea.STATE).withUnit('mA'),
1505
- exposes.numeric('current_average', ea.STATE).withUnit('mA'),
1506
+ exposes.numeric('current', ea.STATE).withUnit('A'),
1507
+ exposes.numeric('current_average', ea.STATE).withUnit('A'),
1506
1508
  exposes.numeric('power', ea.STATE).withUnit('W'),
1507
1509
  exposes.numeric('energy_consumed', ea.STATE).withUnit('kWh'),
1508
1510
  exposes.numeric('temperature', ea.STATE).withUnit('°C'),
@@ -31,10 +31,10 @@ module.exports = [
31
31
  await reporting.bind(endpoint, coordinatorEndpoint, ['genBasic', 'genPowerCfg', 'genIdentify', 'genTime', 'hvacThermostat']);
32
32
 
33
33
  // standard ZCL attributes
34
- await reporting.batteryPercentageRemaining(endpoint, {min: 60, max: 43200, change: 1});
35
- await reporting.thermostatTemperature(endpoint, {min: 90, max: 900, change: 10});
36
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint, {min: 0, max: 65534, change: 1});
37
- await reporting.thermostatPIHeatingDemand(endpoint, {min: 60, max: 3600, change: 1});
34
+ await reporting.batteryPercentageRemaining(endpoint);
35
+ await reporting.thermostatTemperature(endpoint);
36
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
37
+ await reporting.thermostatPIHeatingDemand(endpoint);
38
38
 
39
39
  // manufacturer attributes
40
40
  await endpoint.configureReporting('hvacThermostat', [{attribute: 'viessmannWindowOpenInternal', minimumReportInterval: 60,
package/devices/xiaomi.js CHANGED
@@ -40,6 +40,15 @@ const preventReset = async (type, data, device) => {
40
40
  };
41
41
 
42
42
  module.exports = [
43
+ {
44
+ zigbeeModel: ['lumi.magnet.acn001'],
45
+ model: 'MCCGQ14LM',
46
+ vendor: 'Xiaomi',
47
+ description: 'Aqara E1 door & window contact sensor',
48
+ fromZigbee: [fz.ias_contact_alarm_1, fz.aqara_opple_report],
49
+ toZigbee: [],
50
+ exposes: [e.contact(), e.battery(), e.battery_voltage()],
51
+ },
43
52
  {
44
53
  zigbeeModel: ['lumi.dimmer.rcbac1'],
45
54
  model: 'ZNDDMK11LM',
@@ -792,7 +801,7 @@ module.exports = [
792
801
  vendor: 'Xiaomi',
793
802
  description: 'Aqara temperature, humidity and pressure sensor',
794
803
  meta: {battery: {voltageToPercentage: '3V_2100'}},
795
- fromZigbee: [fz.xiaomi_battery, fz.xiaomi_temperature, fz.humidity, fz.WSDCGQ11LM_pressure, fz.WSDCGQ01LM_WSDCGQ11LM_interval],
804
+ fromZigbee: [fz.xiaomi_battery, fz.xiaomi_temperature, fz.humidity, fz.pressure, fz.WSDCGQ01LM_WSDCGQ11LM_interval],
796
805
  toZigbee: [],
797
806
  exposes: [e.battery(), e.temperature(), e.humidity(), e.pressure(), e.battery_voltage()],
798
807
  configure: async (device, coordinatorEndpoint, logger) => {
@@ -1392,23 +1401,14 @@ module.exports = [
1392
1401
  model: 'DLKZMK11LM',
1393
1402
  vendor: 'Xiaomi',
1394
1403
  description: 'Aqara single switch module T1 (with neutral)',
1395
- fromZigbee: [fz.on_off, fz.metering, fz.electrical_measurement, fz.device_temperature, fz.xiaomi_switch_type,
1396
- fz.xiaomi_switch_power_outage_memory],
1397
- exposes: [e.switch(), e.energy(), e.power(), e.device_temperature(), e.power_outage_memory(), e.switch_type()],
1398
- toZigbee: [tz.xiaomi_switch_type, tz.on_off, tz.xiaomi_switch_power_outage_memory],
1404
+ fromZigbee: [fz.on_off, fz.xiaomi_power, fz.xiaomi_switch_type, fz.xiaomi_switch_opple_basic],
1405
+ toZigbee: [tz.on_off, tz.xiaomi_power, tz.xiaomi_switch_type, tz.xiaomi_switch_power_outage_memory, tz.xiaomi_led_disabled_night],
1406
+ exposes: [e.switch(), e.power().withAccess(ea.STATE_GET), e.energy(), e.temperature().withAccess(ea.STATE),
1407
+ e.voltage().withAccess(ea.STATE), e.power_outage_memory(), e.led_disabled_night(), e.switch_type()],
1399
1408
  configure: async (device, coordinatorEndpoint, logger) => {
1400
- const endpoint = device.getEndpoint(1);
1401
- await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering', 'genDeviceTempCfg']);
1402
- await reporting.onOff(endpoint);
1403
- // Gives UNSUPPORTED_ATTRIBUTE on reporting.readEletricalMeasurementMultiplierDivisors.
1404
- await endpoint.read('haElectricalMeasurement', ['acPowerMultiplier', 'acPowerDivisor']);
1405
- await reporting.readMeteringMultiplierDivisor(endpoint);
1406
- await reporting.currentSummDelivered(endpoint);
1407
- await reporting.activePower(endpoint, {min: 5, max: 600, change: 10});
1408
- await reporting.deviceTemperature(endpoint);
1409
- device.powerSource = 'Mains (single phase)';
1410
- device.save();
1409
+ await device.getEndpoint(1).write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
1411
1410
  },
1411
+ ota: ota.zigbeeOTA,
1412
1412
  },
1413
1413
  {
1414
1414
  zigbeeModel: ['lumi.switch.l0agl1'],
@@ -1760,4 +1760,24 @@ module.exports = [
1760
1760
  await endpoint1.write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
1761
1761
  },
1762
1762
  },
1763
+ {
1764
+ zigbeeModel: ['lumi.remote.acn004'],
1765
+ model: 'WXKG17LM',
1766
+ vendor: 'Xiaomi',
1767
+ description: 'Aqara E1 double key wireless switch',
1768
+ meta: {battery: {voltageToPercentage: '3V_2100'}},
1769
+ exposes: [e.battery(), e.battery_voltage(),
1770
+ e.action(['single_left', 'single_right', 'single_both', 'double_left', 'double_right', 'hold_left', 'hold_right']),
1771
+ // eslint-disable-next-line max-len
1772
+ exposes.enum('click_mode', ea.SET, ['fast', 'multi']).withDescription('Click mode, fast: only supports single click which will be send immediately after clicking, multi: supports more events like double and hold'),
1773
+ ],
1774
+ fromZigbee: [fz.xiaomi_multistate_action, fz.aqara_opple_report],
1775
+ toZigbee: [tz.xiaomi_switch_click_mode],
1776
+ onEvent: preventReset,
1777
+ configure: async (device, coordinatorEndpoint, logger) => {
1778
+ const endpoint1 = device.getEndpoint(1);
1779
+ // set multiclick mode
1780
+ await endpoint1.write('aqaraOpple', {0x0125: {value: 0x02, type: 0x20}}, {manufacturerCode: 0x115f});
1781
+ },
1782
+ },
1763
1783
  ];
package/lib/exposes.js CHANGED
@@ -477,8 +477,8 @@ module.exports = {
477
477
  expose_pin: () => new Binary(`expose_pin`, access.SET, true, false).withDescription(`Expose pin of this lock in the published payload (default false).`),
478
478
  occupancy_timeout: () => new Numeric(`occupancy_timeout`, access.SET).withValueMin(0).withDescription('Time in seconds after which occupancy is cleared after detecting it (default 90 seconds).'),
479
479
  vibration_timeout: () => new Numeric(`vibration_timeout`, access.SET).withValueMin(0).withDescription('Time in seconds after which vibration is cleared after detecting it (default 90 seconds).'),
480
- simulated_brightness: () => new Composite('simulated_brightness', 'simulated_brightness')
481
- .withDescription('Simulate a brightness value. If this device provides a brightness_move_up or brightness_move_down action it is possible to specify the update interval and delta.')
480
+ simulated_brightness: (extraNote='') => new Composite('simulated_brightness', 'simulated_brightness')
481
+ .withDescription(`Simulate a brightness value. If this device provides a brightness_move_up or brightness_move_down action it is possible to specify the update interval and delta.${extraNote}`)
482
482
  .withFeature(new Numeric('delta', access.SET).withValueMin(0).withDescription('Delta per interval, 20 by default'))
483
483
  .withFeature(new Numeric('interval', access.SET).withValueMin(0).withUnit('ms').withDescription('Interval duration')),
484
484
  no_occupancy_since: () => new List(`no_occupancy_since`, access.SET).withDescription('Sends a message the last time occupancy was detected. When setting this for example to [10, 60] a `{"no_occupancy_since": 10}` will be send after 10 seconds and a `{"no_occupancy_since": 60}` after 60 seconds.'),
package/lib/legacy.js CHANGED
@@ -885,7 +885,7 @@ const fromZigbee = {
885
885
  cmd_move: {
886
886
  cluster: 'genLevelCtrl',
887
887
  type: 'commandMove',
888
- options: [exposes.options.legacy()],
888
+ options: [exposes.options.legacy(), exposes.options.simulated_brightness(' Note: will only work when legacy: false is set.')],
889
889
  convert: (model, msg, publish, options, meta) => {
890
890
  if (hasAlreadyProcessedMessage(msg)) return;
891
891
  if (isLegacyEnabled(options)) {
@@ -900,7 +900,7 @@ const fromZigbee = {
900
900
  cmd_move_with_onoff: {
901
901
  cluster: 'genLevelCtrl',
902
902
  type: 'commandMoveWithOnOff',
903
- options: [exposes.options.legacy()],
903
+ options: [exposes.options.legacy(), exposes.options.simulated_brightness(' Note: will only work when legacy: false is set.')],
904
904
  convert: (model, msg, publish, options, meta) => {
905
905
  if (isLegacyEnabled(options)) {
906
906
  ictcg1(model, msg, publish, options, 'move');
package/lib/reporting.js CHANGED
@@ -148,7 +148,7 @@ module.exports = {
148
148
  await endpoint.configureReporting('hvacThermostat', p);
149
149
  },
150
150
  thermostatPIHeatingDemand: async (endpoint, overrides) => {
151
- const p = payload('pIHeatingDemand', 0, repInterval.MINUTES_5, 10, overrides);
151
+ const p = payload('pIHeatingDemand', 0, repInterval.HOUR, 10, overrides);
152
152
  await endpoint.configureReporting('hvacThermostat', p);
153
153
  },
154
154
  thermostatRunningState: async (endpoint, overrides) => {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.305",
3
+ "version": "14.0.309",
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.305",
3
+ "version": "14.0.309",
4
4
  "description": "Collection of device converters to be used with zigbee-herdsman",
5
5
  "main": "index.js",
6
6
  "files": [