zigbee-herdsman-converters 14.0.332 → 14.0.336

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.
@@ -596,7 +596,7 @@ const converters = {
596
596
  // handle color property sync
597
597
  // NOTE: this should the last thing we do, as we need to have processed all attributes,
598
598
  // we use assign here so we do not lose other attributes.
599
- return Object.assign(result, libColor.syncColorState(result, meta.state, options));
599
+ return Object.assign(result, libColor.syncColorState(result, meta.state, msg.endpoint, options, meta.logger));
600
600
  },
601
601
  },
602
602
  metering_datek: {
@@ -668,6 +668,10 @@ const converters = {
668
668
  constants.develcoInterfaceMode[msg.data['develcoInterfaceMode']] :
669
669
  msg.data['develcoInterfaceMode'];
670
670
  }
671
+ if (msg.data.hasOwnProperty('status')) {
672
+ result['battery_low'] = (msg.data.status & 2) > 0;
673
+ result['check_meter'] = (msg.data.status & 1) > 0;
674
+ }
671
675
 
672
676
  return result;
673
677
  },
@@ -1753,6 +1757,29 @@ const converters = {
1753
1757
  }
1754
1758
  },
1755
1759
  },
1760
+ tuya_illuminance_temperature_humidity_sensor: {
1761
+ cluster: 'manuSpecificTuya',
1762
+ type: ['commandSetDataResponse', 'commandGetData'],
1763
+ options: [exposes.options.precision('temperature'), exposes.options.calibration('temperature'),
1764
+ exposes.options.precision('humidity'), exposes.options.calibration('humidity')],
1765
+ convert: (model, msg, publish, options, meta) => {
1766
+ const dp = msg.data.dp;
1767
+ const value = tuya.getDataValue(msg.data.datatype, msg.data.data);
1768
+ switch (dp) {
1769
+ case tuya.dataPoints.thitTemperature:
1770
+ return {temperature: calibrateAndPrecisionRoundOptions(value / 10, options, 'temperature')};
1771
+ case tuya.dataPoints.thitHumidity:
1772
+ return {humidity: calibrateAndPrecisionRoundOptions(value, options, 'humidity')};
1773
+ case tuya.dataPoints.thitBatteryPercentage:
1774
+ return {battery: value};
1775
+ case tuya.dataPoints.thitIlluminanceLux:
1776
+ return {illuminance_lux: value};
1777
+ default:
1778
+ meta.logger.warn(`zigbee-herdsman-converters:tuya_illuminance_temperature_humidity_sensor: NOT RECOGNIZED ` +
1779
+ `DP #${dp} with data ${JSON.stringify(msg.data)}`);
1780
+ }
1781
+ },
1782
+ },
1756
1783
  ts0201_temperature_humidity_alarm: {
1757
1784
  cluster: 'manuSpecificTuya_2',
1758
1785
  type: ['attributeReport', 'readResponse'],
@@ -1958,7 +1985,7 @@ const converters = {
1958
1985
  result.color.s = result.color.saturation;
1959
1986
  }
1960
1987
 
1961
- return Object.assign(result, libColor.syncColorState(result, meta.state, options));
1988
+ return Object.assign(result, libColor.syncColorState(result, meta.state, msg.endpoint, options, meta.logger));
1962
1989
  },
1963
1990
  },
1964
1991
  tuya_cover: {
@@ -2444,7 +2471,7 @@ const converters = {
2444
2471
  buttonMapping = {1: '1', 2: '2'};
2445
2472
  } else if (model.model === 'TS0043') {
2446
2473
  buttonMapping = {1: '1', 2: '2', 3: '3'};
2447
- } else if (['TS0044', 'YSR-MINI-Z'].includes(model.model)) {
2474
+ } else if (['TS0044', 'YSR-MINI-Z', 'TS004F'].includes(model.model)) {
2448
2475
  buttonMapping = {1: '1', 2: '2', 3: '3', 4: '4'};
2449
2476
  }
2450
2477
  const button = buttonMapping ? `${buttonMapping[msg.endpoint.ID]}_` : '';
@@ -913,8 +913,8 @@ const converters = {
913
913
  const payload = {colortemp: value, transtime: utils.getTransition(entity, key, meta).time};
914
914
  await entity.command('lightingColorCtrl', 'moveToColorTemp', payload, utils.getOptions(meta.mapped, entity));
915
915
  return {
916
- state: libColor.syncColorState({'color_mode': constants.colorMode[2], 'color_temp': value}, meta.state, meta.options),
917
- readAfterWriteTime: payload.transtime * 100,
916
+ state: libColor.syncColorState({'color_mode': constants.colorMode[2], 'color_temp': value}, meta.state,
917
+ entity, meta.options, meta.logger), readAfterWriteTime: payload.transtime * 100,
918
918
  };
919
919
  },
920
920
  convertGet: async (entity, key, meta) => {
@@ -1030,7 +1030,8 @@ const converters = {
1030
1030
  }
1031
1031
 
1032
1032
  await entity.command('lightingColorCtrl', command, zclData, utils.getOptions(meta.mapped, entity));
1033
- return {state: libColor.syncColorState(newState, meta.state, meta.options), readAfterWriteTime: zclData.transtime * 100};
1033
+ return {state: libColor.syncColorState(newState, meta.state, entity, meta.options, meta.logger),
1034
+ readAfterWriteTime: zclData.transtime * 100};
1034
1035
  },
1035
1036
  convertGet: async (entity, key, meta) => {
1036
1037
  await entity.read('lightingColorCtrl', light.readColorAttributes(entity, meta));
@@ -3023,7 +3024,8 @@ const converters = {
3023
3024
  color_temp: meta.message.color_temp,
3024
3025
  };
3025
3026
 
3026
- return {state: libColor.syncColorState(newState, meta.state, meta.options), readAfterWriteTime: zclData.transtime * 100};
3027
+ return {state: libColor.syncColorState(newState, meta.state, entity, meta.options, meta.logger),
3028
+ readAfterWriteTime: zclData.transtime * 100};
3027
3029
  }
3028
3030
 
3029
3031
  if (key === 'color_temp') {
@@ -3040,7 +3042,8 @@ const converters = {
3040
3042
  color_temp: value,
3041
3043
  };
3042
3044
 
3043
- return {state: libColor.syncColorState(newState, meta.state, meta.options), readAfterWriteTime: zclData.transtime * 100};
3045
+ return {state: libColor.syncColorState(newState, meta.state, entity, meta.options, meta.logger),
3046
+ readAfterWriteTime: zclData.transtime * 100};
3044
3047
  }
3045
3048
 
3046
3049
  const zclData = {
@@ -3104,7 +3107,8 @@ const converters = {
3104
3107
  color_mode: constants.colorMode[0],
3105
3108
  };
3106
3109
 
3107
- return {state: libColor.syncColorState(newState, meta.state, meta.options), readAfterWriteTime: zclData.transtime * 100};
3110
+ return {state: libColor.syncColorState(newState, meta.state, entity, meta.options, meta.logger),
3111
+ readAfterWriteTime: zclData.transtime * 100};
3108
3112
  },
3109
3113
  convertGet: async (entity, key, meta) => {
3110
3114
  await entity.read('lightingColorCtrl', [
@@ -5063,7 +5067,7 @@ const converters = {
5063
5067
  recalledState = addColorMode(recalledState);
5064
5068
  }
5065
5069
 
5066
- Object.assign(recalledState, libColor.syncColorState(recalledState, meta.state, meta.options));
5070
+ Object.assign(recalledState, libColor.syncColorState(recalledState, meta.state, entity, meta.options, meta.logger));
5067
5071
  membersState[member.getDevice().ieeeAddr] = recalledState;
5068
5072
  } else {
5069
5073
  meta.logger.warn(`Unknown scene was recalled for ${member.getDevice().ieeeAddr}, can't restore state.`);
@@ -5080,7 +5084,7 @@ const converters = {
5080
5084
  recalledState = addColorMode(recalledState);
5081
5085
  }
5082
5086
 
5083
- Object.assign(recalledState, libColor.syncColorState(recalledState, meta.state, meta.options));
5087
+ Object.assign(recalledState, libColor.syncColorState(recalledState, meta.state, entity, meta.options, meta.logger));
5084
5088
  meta.logger.info('Successfully recalled scene');
5085
5089
  return {state: recalledState};
5086
5090
  } else {
package/devices/casaia.js CHANGED
@@ -2,6 +2,7 @@ const exposes = require('../lib/exposes');
2
2
  const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/legacy').fromZigbee};
3
3
  const reporting = require('../lib/reporting');
4
4
  const e = exposes.presets;
5
+ const tz = require('../converters/toZigbee');
5
6
 
6
7
  module.exports = [
7
8
  {
@@ -22,4 +23,21 @@ module.exports = [
22
23
  },
23
24
  exposes: [e.temperature(), e.battery_low(), e.battery()],
24
25
  },
26
+ {
27
+ zigbeeModel: ['CCB432'],
28
+ model: 'CCB432',
29
+ vendor: 'CASAIA',
30
+ description: 'Rail-Din relay and energy meter',
31
+ fromZigbee: [fz.electrical_measurement, fz.metering, fz.on_off],
32
+ toZigbee: [tz.on_off],
33
+ exposes: [e.switch(), e.power(), e.energy()],
34
+ configure: async (device, coordinatorEndpoint, logger) => {
35
+ const endpoint = device.getEndpoint(1);
36
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering']);
37
+ await reporting.onOff(endpoint);
38
+ await reporting.readMeteringMultiplierDivisor(endpoint);
39
+ await reporting.instantaneousDemand(endpoint);
40
+ await reporting.currentSummDelivered(endpoint);
41
+ },
42
+ },
25
43
  ];
@@ -42,8 +42,8 @@ module.exports = [
42
42
  exposes.climate().withSetpoint('occupied_heating_setpoint', 5, 32, 0.5).withLocalTemperature().withPiHeatingDemand()
43
43
  .withSystemMode(['heat']).withRunningState(['idle', 'heat'], ea.STATE),
44
44
  exposes.numeric('external_measured_room_sensor', ea.ALL)
45
- .withDescription('Set at maximum 3 hours interval but not more often than every 30 minutes at every 100 ' +
46
- 'value change. Resets every 3hours to standard. e.g. 21C = 2100 (-8000=undefined).'),
45
+ .withDescription('Set at maximum 3 hours interval but not more often than every 30 minutes and 0.1 ' +
46
+ 'degrees difference. Resets every 3hours to standard. e.g. 21C = 2100 (-8000=undefined).'),
47
47
  exposes.numeric('window_open_internal', ea.STATE_GET).withValueMin(0).withValueMax(4)
48
48
  .withDescription('0=Quarantine, 1=Windows are closed, 2=Hold - Windows are maybe about to open, ' +
49
49
  '3=Open window detected, 4=In window open state from external but detected closed locally'),
@@ -311,6 +311,7 @@ module.exports = [
311
311
  exposes: [
312
312
  e.power(),
313
313
  e.energy(),
314
+ e.battery_low(),
314
315
  exposes.numeric('pulse_configuration', ea.ALL).withValueMin(0).withValueMax(65535)
315
316
  .withDescription('Pulses per kwh. Default 1000 imp/kWh. Range 0 to 65535'),
316
317
  exposes.enum('interface_mode', ea.ALL,
@@ -318,6 +319,8 @@ module.exports = [
318
319
  .withDescription('Operating mode/probe'),
319
320
  exposes.numeric('current_summation', ea.SET)
320
321
  .withDescription('Current summation value sent to the display. e.g. 570 = 0,570 kWh'),
322
+ exposes.binary('check_meter', ea.STATE, true, false)
323
+ .withDescription('Is true if communication problem with meter is experienced'),
321
324
  ],
322
325
  },
323
326
  {
package/devices/hive.js CHANGED
@@ -183,8 +183,8 @@ module.exports = [
183
183
  exposes.climate().withSetpoint('occupied_heating_setpoint', 5, 32, 0.5).withLocalTemperature().withPiHeatingDemand()
184
184
  .withSystemMode(['heat']).withRunningState(['idle', 'heat'], ea.STATE),
185
185
  exposes.numeric('external_measured_room_sensor', ea.ALL)
186
- .withDescription('Set at maximum 3 hours interval but not more often than every 30 minutes at every 100 ' +
187
- 'value change. Resets every 3hours to standard. e.g. 21C = 2100 (-8000=undefined).'),
186
+ .withDescription('Set at maximum 3 hours interval but not more often than every 30 minutes and 0.1 ' +
187
+ 'degrees difference. Resets every 3hours to standard. e.g. 21C = 2100 (-8000=undefined).'),
188
188
  exposes.numeric('window_open_internal', ea.STATE_GET).withValueMin(0).withValueMax(4)
189
189
  .withDescription('0=Quarantine, 1=Windows are closed, 2=Hold - Windows are maybe about to open, ' +
190
190
  '3=Open window detected, 4=In window open state from external but detected closed locally'),
package/devices/icasa.js CHANGED
@@ -81,6 +81,7 @@ module.exports = [
81
81
  model: 'ICZB-RM11S',
82
82
  vendor: 'iCasa',
83
83
  description: 'Zigbee 3.0 remote control',
84
+ meta: {battery: {dontDividePercentage: true}},
84
85
  fromZigbee: [fz.command_recall, fz.command_on, fz.command_off, fz.command_move, fz.command_stop, fz.battery],
85
86
  exposes: [e.battery(), e.action(['recall_*', 'on', 'off', 'brightness_stop', 'brightness_move_up', 'brightness_move_down'])],
86
87
  toZigbee: [],
package/devices/ikea.js CHANGED
@@ -146,10 +146,12 @@ const ikea = {
146
146
  convertSet: async (entity, key, value, meta) => {
147
147
  if (key == 'fan_state' && value.toLowerCase() == 'on') {
148
148
  value = getMetaValue(entity, meta.mapped, 'fanStateOn', 'allEqual', 'on');
149
+ } else {
150
+ value = value.toString().toLowerCase();
149
151
  }
150
152
 
151
153
  let fanMode;
152
- switch (value.toLowerCase()) {
154
+ switch (value) {
153
155
  case 'off':
154
156
  fanMode = 0;
155
157
  break;
@@ -161,7 +163,7 @@ const ikea = {
161
163
  }
162
164
 
163
165
  await entity.write('manuSpecificIkeaAirPurifier', {'fanMode': fanMode}, manufacturerOptions.ikea);
164
- return {state: {fan_mode: value.toLowerCase(), fan_state: value.toLowerCase() === 'off' ? 'OFF' : 'ON'}};
166
+ return {state: {fan_mode: value, fan_state: value === 'off' ? 'OFF' : 'ON'}};
165
167
  },
166
168
  convertGet: async (entity, key, meta) => {
167
169
  await entity.read('manuSpecificIkeaAirPurifier', ['fanMode']);
package/devices/immax.js CHANGED
@@ -140,4 +140,23 @@ module.exports = [
140
140
  description: 'Neo RECUADRO SMART, color temp, dimmable, Zigbee 3.0',
141
141
  extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 370]}),
142
142
  },
143
+ {
144
+ fingerprint: [{modelID: 'TS0202', manufacturerName: '_TZ3210_jijr1sss'}],
145
+ model: '07502L',
146
+ vendor: 'Immax',
147
+ description: '4 in 1 multi sensor',
148
+ fromZigbee: [fz.battery, fz.ignore_basic_report, fz.illuminance, fz.ZB003X, fz.ZB003X_attr, fz.ZB003X_occupancy],
149
+ toZigbee: [tz.ZB003X],
150
+ exposes: [e.occupancy(), e.tamper(), e.battery(), e.illuminance(), e.illuminance_lux().withUnit('lx'), e.temperature(),
151
+ e.humidity(), exposes.numeric('reporting_time', ea.STATE_SET).withDescription('Reporting interval in minutes'),
152
+ exposes.numeric('temperature_calibration', ea.STATE_SET).withDescription('Temperature calibration'),
153
+ exposes.numeric('humidity_calibration', ea.STATE_SET).withDescription('Humidity calibration'),
154
+ exposes.numeric('illuminance_calibration', ea.STATE_SET).withDescription('Illuminance calibration'),
155
+ exposes.binary('pir_enable', ea.STATE_SET, true, false).withDescription('Enable PIR sensor'),
156
+ exposes.binary('led_enable', ea.STATE_SET, true, false).withDescription('Enabled LED'),
157
+ exposes.binary('reporting_enable', ea.STATE_SET, true, false).withDescription('Enabled reporting'),
158
+ exposes.enum('sensitivity', ea.STATE_SET, ['low', 'medium', 'high']).withDescription('PIR sensor sensitivity'),
159
+ // eslint-disable-next-line
160
+ exposes.enum('keep_time', ea.STATE_SET, ['0', '30', '60', '120', '240']).withDescription('PIR keep time in seconds')],
161
+ },
143
162
  ];
@@ -85,7 +85,7 @@ module.exports = [
85
85
  extend: extend.light_onoff_brightness_colortemp(),
86
86
  },
87
87
  {
88
- zigbeeModel: ['ZHA-PIRSensor'],
88
+ fingerprint: [{modelID: 'ZHA-PIRSensor', manufacturerName: 'Leedarson'}],
89
89
  model: '5AA-SS-ZA-H0',
90
90
  vendor: 'Leedarson',
91
91
  description: 'Motion sensor',
package/devices/lidl.js CHANGED
@@ -655,7 +655,7 @@ module.exports = [
655
655
  fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_chyvmhay'}],
656
656
  model: '368308_2010',
657
657
  vendor: 'Lidl',
658
- description: 'Silvercrest rdiator valve with thermostat',
658
+ description: 'Silvercrest radiator valve with thermostat',
659
659
  fromZigbee: [fz.ignore_tuya_set_time, fzLocal.zs_thermostat, fz.tuya_data_point_dump],
660
660
  toZigbee: [tzLocal.zs_thermostat_current_heating_setpoint, tzLocal.zs_thermostat_child_lock,
661
661
  tzLocal.zs_thermostat_comfort_temp, tzLocal.zs_thermostat_eco_temp, tzLocal.zs_thermostat_preset_mode,
package/devices/moes.js CHANGED
@@ -76,7 +76,8 @@ module.exports = [
76
76
  },
77
77
  {
78
78
  fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_aoclfnxz'},
79
- {modelID: 'TS0601', manufacturerName: '_TZE200_ztvwu4nk'}],
79
+ {modelID: 'TS0601', manufacturerName: '_TZE200_ztvwu4nk'},
80
+ {modelID: 'TS0601', manufacturerName: '_TZE200_u9bfwha0'}],
80
81
  model: 'BHT-002-GCLZB',
81
82
  vendor: 'Moes',
82
83
  description: 'Moes BHT series Thermostat',
package/devices/owon.js CHANGED
@@ -83,4 +83,23 @@ module.exports = [
83
83
  await reporting.thermostatAcLouverPosition(endpoint);
84
84
  },
85
85
  },
86
+ {
87
+ zigbeeModel: ['THS317'],
88
+ model: 'THS317',
89
+ vendor: 'OWON',
90
+ description: 'Temperature and humidity sensor',
91
+ fromZigbee: [fz.temperature, fz.humidity, fz.battery],
92
+ toZigbee: [],
93
+ exposes: [e.battery(), e.temperature(), e.humidity()],
94
+ configure: async (device, coordinatorEndpoint, logger) => {
95
+ const endpoint = device.getEndpoint(2);
96
+ await reporting.bind(endpoint, coordinatorEndpoint, ['msTemperatureMeasurement', 'msRelativeHumidity', 'genPowerCfg']);
97
+ await reporting.temperature(endpoint);
98
+ await reporting.humidity(endpoint);
99
+ await reporting.batteryVoltage(endpoint);
100
+ await reporting.batteryPercentageRemaining(endpoint);
101
+ device.powerSource = 'Battery';
102
+ device.save();
103
+ },
104
+ },
86
105
  ];
@@ -33,4 +33,19 @@ module.exports = [
33
33
  await reporting.batteryPercentageRemaining(endpoint);
34
34
  },
35
35
  },
36
+ {
37
+ fingerprint: [{modelID: 'ZHA-PirSensor', manufacturerName: 'LDS'}],
38
+ model: 'PECMS01',
39
+ vendor: 'Perenio',
40
+ description: 'Motion sensor',
41
+ fromZigbee: [fz.battery, fz.ias_occupancy_alarm_1],
42
+ toZigbee: [],
43
+ meta: {battery: {dontDividePercentage: true}},
44
+ exposes: [e.occupancy(), e.battery_low(), e.tamper(), e.battery()],
45
+ configure: async (device, coordinatorEndpoint, logger) => {
46
+ const endpoint = device.getEndpoint(1);
47
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
48
+ await reporting.batteryPercentageRemaining(endpoint);
49
+ },
50
+ },
36
51
  ];
@@ -2244,6 +2244,15 @@ module.exports = [
2244
2244
  extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
2245
2245
  ota: ota.zigbeeOTA,
2246
2246
  },
2247
+ {
2248
+ zigbeeModel: ['5047230P6', '5047230P6'],
2249
+ model: '5047230P6',
2250
+ vendor: 'Philips',
2251
+ description: 'Hue White ambiance Buckram double spotlight',
2252
+ meta: {turnsOffAtBrightness1: true},
2253
+ extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
2254
+ ota: ota.zigbeeOTA,
2255
+ },
2247
2256
  {
2248
2257
  zigbeeModel: ['5047430P6'],
2249
2258
  model: '5047430P6',
package/devices/popp.js CHANGED
@@ -42,8 +42,8 @@ module.exports = [
42
42
  exposes.climate().withSetpoint('occupied_heating_setpoint', 5, 32, 0.5).withLocalTemperature().withPiHeatingDemand()
43
43
  .withSystemMode(['heat']).withRunningState(['idle', 'heat'], ea.STATE),
44
44
  exposes.numeric('external_measured_room_sensor', ea.ALL)
45
- .withDescription('Set at maximum 3 hours interval but not more often than every 30 minutes at every 100 ' +
46
- 'value change. Resets every 3hours to standard. e.g. 21C = 2100 (-8000=undefined).'),
45
+ .withDescription('Set at maximum 3 hours interval but not more often than every 30 minutes and 0.1 ' +
46
+ 'degrees difference. Resets every 3hours to standard. e.g. 21C = 2100 (-8000=undefined).'),
47
47
  exposes.numeric('window_open_internal', ea.STATE_GET).withValueMin(0).withValueMax(4)
48
48
  .withDescription('0=Quarantine, 1=Windows are closed, 2=Hold - Windows are maybe about to open, ' +
49
49
  '3=Open window detected, 4=In window open state from external but detected closed locally'),
@@ -282,4 +282,21 @@ module.exports = [
282
282
  await reporting.batteryVoltage(endpoint, {min: 30, max: 21600, change: 1});
283
283
  },
284
284
  },
285
+ {
286
+ zigbeeModel: ['PMM-300Z1'],
287
+ model: 'PMM-300Z1',
288
+ vendor: 'ShinaSystem',
289
+ description: 'SiHAS energy monitor',
290
+ fromZigbee: [fz.electrical_measurement, fz.metering],
291
+ toZigbee: [tz.electrical_measurement_power],
292
+ exposes: [e.power().withAccess(ea.STATE_GET), e.energy()],
293
+ configure: async (device, coordinatorEndpoint, logger) => {
294
+ const endpoint = device.getEndpoint(1);
295
+ await reporting.bind(endpoint, coordinatorEndpoint, ['haElectricalMeasurement', 'seMetering']);
296
+ await reporting.activePower(endpoint, {min: 1, max: 600, change: 5});
297
+ await reporting.instantaneousDemand(endpoint, {min: 1, max: 600, change: 1});
298
+ endpoint.saveClusterAttributeKeyValue('seMetering', {multiplier: 1, divisor: 1000});
299
+ await reporting.currentSummDelivered(endpoint, {min: 1, max: 600, change: 5});
300
+ },
301
+ },
285
302
  ];
package/devices/tuya.js CHANGED
@@ -36,6 +36,15 @@ module.exports = [
36
36
  toZigbee: [],
37
37
  exposes: [e.temperature(), e.humidity(), e.battery()],
38
38
  },
39
+ {
40
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_vzqtvljm'}],
41
+ model: 'TS0601_illuminance_temperature_humidity_sensor',
42
+ vendor: 'TuYa',
43
+ description: 'Illuminance, temperature & humidity sensor',
44
+ fromZigbee: [fz.tuya_illuminance_temperature_humidity_sensor],
45
+ toZigbee: [],
46
+ exposes: [e.temperature(), e.humidity(), e.illuminance_lux(), e.battery()],
47
+ },
39
48
  {
40
49
  fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_8ygsuhe1'},
41
50
  {modelID: 'TS0601', manufacturerName: '_TZE200_yvx5lh6k'}, {modelID: 'TS0601', manufacturerName: '_TZE200_ryfmq5rl'}],
@@ -115,8 +124,8 @@ module.exports = [
115
124
  model: 'TS0505B',
116
125
  vendor: 'TuYa',
117
126
  description: 'Zigbee RGB+CCT light',
118
- whiteLabel: [{vendor: 'Mercator ikuü', model: 'SMD4106W-RGB-ZB'},
119
- {vendor: 'TuYa', model: 'A5C-21F7-01'}, {vendor: 'Mercator ikuü', model: 'S9E27LED9W-RGB-Z'}],
127
+ whiteLabel: [{vendor: 'Mercator Ikuü', model: 'SMD4106W-RGB-ZB'},
128
+ {vendor: 'TuYa', model: 'A5C-21F7-01'}, {vendor: 'Mercator Ikuü', model: 'S9E27LED9W-RGB-Z'}],
120
129
  extend: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
121
130
  meta: {applyRedFix: true, enhancedHue: false},
122
131
  },
@@ -241,7 +250,7 @@ module.exports = [
241
250
  {vendor: 'Earda', model: 'EDM-1ZAA-EU'},
242
251
  {vendor: 'Earda', model: 'EDM-1ZAB-EU'},
243
252
  {vendor: 'Earda', model: 'EDM-1ZBA-EU'},
244
- {vendor: 'Mercator ikuü', model: 'SSWD01'},
253
+ {vendor: 'Mercator Ikuü', model: 'SSWD01'},
245
254
  ],
246
255
  },
247
256
  {
@@ -437,7 +446,7 @@ module.exports = [
437
446
  model: 'TS0502B',
438
447
  vendor: 'TuYa',
439
448
  description: 'Light controller',
440
- whiteLabel: [{vendor: 'Mercator ikuü', model: 'SMI7040', description: 'Ford Batten Light'}],
449
+ whiteLabel: [{vendor: 'Mercator Ikuü', model: 'SMI7040', description: 'Ford Batten Light'}],
441
450
  extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 500]}),
442
451
  },
443
452
  {
@@ -545,16 +554,24 @@ module.exports = [
545
554
  model: 'TS004F',
546
555
  vendor: 'TuYa',
547
556
  description: 'Wireless switch with 4 buttons',
548
- exposes: [e.battery(), e.action(
549
- ['on', 'off', 'brightness_move_up', 'brightness_step_up', 'brightness_step_down', 'brightness_move_down', 'brightness_stop'])],
550
- fromZigbee: [fz.battery, fz.command_on, fz.command_off, fz.command_step, fz.command_move, fz.command_stop],
551
- toZigbee: [],
557
+ exposes: [e.battery(), e.action(['1_single', '1_double', '1_hold', '2_single', '2_double', '2_hold',
558
+ '3_single', '3_double', '3_hold', '4_single', '4_double', '4_hold'])],
559
+ fromZigbee: [fz.battery, fz.tuya_on_off_action],
560
+ toZigbee: [tz.tuya_operation_mode],
552
561
  configure: async (device, coordinatorEndpoint, logger) => {
553
562
  const endpoint = device.getEndpoint(1);
554
- await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
563
+ await endpoint.read('genBasic', [0x0004, 0x000, 0x0001, 0x0005, 0x0007, 0xfffe]);
564
+ await endpoint.write('genOnOff', {'tuyaOperationMode': 1});
565
+ await endpoint.read('genOnOff', ['tuyaOperationMode']);
555
566
  try {
556
- await reporting.batteryPercentageRemaining(endpoint);
557
- } catch (error) {/* Fails for some*/}
567
+ await endpoint.read(0xE001, [0xD011]);
568
+ } catch (err) {/* do nothing */}
569
+ await endpoint.read('genPowerCfg', ['batteryVoltage', 'batteryPercentageRemaining']);
570
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
571
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
572
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
573
+ await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff']);
574
+ await reporting.bind(device.getEndpoint(4), coordinatorEndpoint, ['genOnOff']);
558
575
  },
559
576
  },
560
577
  {
@@ -1185,7 +1202,7 @@ module.exports = [
1185
1202
  {vendor: 'Vrey', model: 'VR-X712U-0013'},
1186
1203
  {vendor: 'TUYATEC', model: 'GDKES-01TZXD'},
1187
1204
  {vendor: 'Lonsonho', model: 'QS-Zigbee-S05-L', description: '1 gang smart switch module without neutral wire'},
1188
- {vendor: 'Mercator ikuü', model: 'SSW01'},
1205
+ {vendor: 'Mercator Ikuü', model: 'SSW01'},
1189
1206
  ],
1190
1207
  configure: async (device, coordinatorEndpoint, logger) => {
1191
1208
  await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
@@ -1318,7 +1335,7 @@ module.exports = [
1318
1335
  {
1319
1336
  fingerprint: [{modelID: 'TS0014', manufacturerName: '_TZ3000_jr2atpww'}, {modelID: 'TS0014', manufacturerName: '_TYZB01_dvakyzhd'},
1320
1337
  {modelID: 'TS0014', manufacturerName: '_TZ3210_w3hl6rao'}, {modelID: 'TS0014', manufacturerName: '_TYZB01_bagt1e4o'},
1321
- {modelID: 'TS0014', manufacturerName: '_TZ3000_r0pmi2p3'}],
1338
+ {modelID: 'TS0014', manufacturerName: '_TZ3000_r0pmi2p3'}, {modelID: 'TS0014', manufacturerName: '_TZ3000_fxjdcikv'}],
1322
1339
  model: 'TS0014',
1323
1340
  vendor: 'TuYa',
1324
1341
  description: 'Smart light switch - 4 gang without neutral wire',
@@ -1329,7 +1346,7 @@ module.exports = [
1329
1346
  return {'l1': 1, 'l2': 2, 'l3': 3, 'l4': 4};
1330
1347
  },
1331
1348
  whiteLabel: [{vendor: 'TUYATEC', model: 'GDKES-04TZXD'}, {vendor: 'Vizo', model: 'VZ-222S'},
1332
- {vendor: 'MakeGood', model: 'MG-ZG04W/B/G'}],
1349
+ {vendor: 'MakeGood', model: 'MG-ZG04W/B/G'}, {vendor: 'Mercator Ikuü', model: 'SSW04'}],
1333
1350
  meta: {multiEndpoint: true},
1334
1351
  configure: async (device, coordinatorEndpoint, logger) => {
1335
1352
  try {
@@ -1517,7 +1534,8 @@ module.exports = [
1517
1534
  exposes: [e.battery(), e.illuminance(), e.illuminance_lux()],
1518
1535
  },
1519
1536
  {
1520
- fingerprint: [{modelID: 'TS0210', manufacturerName: '_TYZB01_3zv6oleo'}],
1537
+ fingerprint: [{modelID: 'TS0210', manufacturerName: '_TYZB01_3zv6oleo'},
1538
+ {modelID: 'TS0210', manufacturerName: '_TYZB01_j9xxahcl'}],
1521
1539
  model: 'TS0210',
1522
1540
  vendor: 'TuYa',
1523
1541
  description: 'Vibration sensor',
package/devices/xiaomi.js CHANGED
@@ -1772,6 +1772,21 @@ module.exports = [
1772
1772
  await endpoint1.write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
1773
1773
  },
1774
1774
  },
1775
+ {
1776
+ zigbeeModel: ['lumi.remote.acn003'],
1777
+ model: 'WXKG16LM',
1778
+ vendor: 'Xiaomi',
1779
+ description: 'Aqara wireless remote switch E1 (single rocker)',
1780
+ fromZigbee: [fz.xiaomi_multistate_action, fz.aqara_opple],
1781
+ toZigbee: [tz.xiaomi_switch_click_mode],
1782
+ exposes: [e.battery(), e.battery_voltage(), e.action(['single', 'double', 'hold']),
1783
+ exposes.enum('click_mode', ea.SET, ['fast', 'multi'])
1784
+ .withDescription('Click mode, fast: only supports single click which will be send immediately after clicking.' +
1785
+ 'multi: supports more events like double and hold')],
1786
+ configure: async (device, coordinatorEndpoint, logger) => {
1787
+ await device.getEndpoint(1).write('aqaraOpple', {0x0125: {value: 0x02, type: 0x20}}, {manufacturerCode: 0x115f});
1788
+ },
1789
+ },
1775
1790
  {
1776
1791
  zigbeeModel: ['lumi.remote.acn004'],
1777
1792
  model: 'WXKG17LM',
package/lib/color.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const kelvinToXyLookup = require('./kelvinToXy');
2
2
  const {precisionRound} = require('./utils');
3
+ const {findColorTempRange, clampColorTemp} = require('./light');
3
4
 
4
5
  /**
5
6
  * Color represented in HSV space
@@ -637,14 +638,17 @@ class Color {
637
638
  * NOTE: behavior can be disable by setting the 'color_sync' device/group option
638
639
  * @param {Object} newState state with only the changed attributes set
639
640
  * @param {Object} oldState state from the cache with all the old attributes set
641
+ * @param {Object} endpoint with lightingColorCtrl cluster
640
642
  * @param {Object} options meta.options for the device or group
643
+ * @param {Object} logger used for logging
641
644
  * @return {Object} state with color, color_temp, and color_mode set and syncronized from newState's attributes
642
645
  * (other attributes are not included make sure to merge yourself)
643
646
  */
644
- function syncColorState(newState, oldState, options) {
647
+ function syncColorState(newState, oldState, endpoint, options, logger) {
645
648
  const colorTargets = [];
646
649
  const colorSync = (options && options.hasOwnProperty('color_sync')) ? options.color_sync : true;
647
650
  const result = {};
651
+ const [colorTempMin, colorTempMax] = findColorTempRange(endpoint, logger);
648
652
 
649
653
  // check if color sync is enabled
650
654
  if (!colorSync) {
@@ -704,7 +708,8 @@ function syncColorState(newState, oldState, options) {
704
708
  if (result.color.hasOwnProperty('hue') && result.color.hasOwnProperty('saturation')) {
705
709
  const hsv = new ColorHSV(result.color.hue, result.color.saturation);
706
710
  if (colorTargets.includes('color_temp')) {
707
- result.color_temp = precisionRound(hsv.toMireds(), 0);
711
+ result.color_temp = clampColorTemp(precisionRound(hsv.toMireds(), 0),
712
+ colorTempMin, colorTempMax, logger);
708
713
  }
709
714
  if (colorTargets.includes('xy')) {
710
715
  Object.assign(result.color, hsv.toXY().rounded(4).toObject());
@@ -726,7 +731,8 @@ function syncColorState(newState, oldState, options) {
726
731
  if (result.color.hasOwnProperty('x') && result.color.hasOwnProperty('y')) {
727
732
  const xy = new ColorXY(result.color.x, result.color.y);
728
733
  if (colorTargets.includes('color_temp')) {
729
- result.color_temp = precisionRound(xy.toMireds(), 0);
734
+ result.color_temp = clampColorTemp(precisionRound(xy.toMireds(), 0),
735
+ colorTempMin, colorTempMax, logger);
730
736
  }
731
737
  if (colorTargets.includes('hs')) {
732
738
  Object.assign(result.color, xy.toHSV().rounded(0).toObject(false, false));
package/lib/tuya.js CHANGED
@@ -471,6 +471,12 @@ const dataPoints = {
471
471
  hochTotalReverseActivePower: 117,
472
472
  hochHistoricalVoltage: 118,
473
473
  hochHistoricalCurrent: 119,
474
+
475
+ // TUYA / HUMIDITY/ILLUMINANCE/TEMPERATURE SENSOR
476
+ thitBatteryPercentage: 3,
477
+ thitIlluminanceLux: 7,
478
+ thitHumidity: 9,
479
+ thitTemperature: 8,
474
480
  };
475
481
 
476
482
  const thermostatWeekFormat = {