zigbee-herdsman-converters 14.0.320 → 14.0.324

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.
@@ -1425,11 +1425,11 @@ const converters = {
1425
1425
  const invert = model.meta && model.meta.coverInverted ? !options.invert_cover : options.invert_cover;
1426
1426
  if (msg.data.hasOwnProperty('currentPositionLiftPercentage') && msg.data['currentPositionLiftPercentage'] <= 100) {
1427
1427
  const value = msg.data['currentPositionLiftPercentage'];
1428
- result.position = invert ? value : 100 - value;
1428
+ result[postfixWithEndpointName('position', msg, model)] = invert ? value : 100 - value;
1429
1429
  }
1430
1430
  if (msg.data.hasOwnProperty('currentPositionTiltPercentage') && msg.data['currentPositionTiltPercentage'] <= 100) {
1431
1431
  const value = msg.data['currentPositionTiltPercentage'];
1432
- result.tilt = invert ? value : 100 - value;
1432
+ result[postfixWithEndpointName('tilt', msg, model)] = invert ? value : 100 - value;
1433
1433
  }
1434
1434
  return result;
1435
1435
  },
@@ -4293,79 +4293,6 @@ const converters = {
4293
4293
  }
4294
4294
  },
4295
4295
  },
4296
- ikea_air_purifier: {
4297
- cluster: 'manuSpecificIkeaAirPurifier',
4298
- type: ['attributeReport', 'readResponse'],
4299
- options: [exposes.options.precision('pm25'), exposes.options.calibration('pm25')],
4300
- convert: (model, msg, publish, options, meta) => {
4301
- const state = {};
4302
-
4303
- if (msg.data.hasOwnProperty('particulateMatter25Measurement')) {
4304
- const pm25Property = postfixWithEndpointName('pm25', msg, model);
4305
- let pm25 = parseFloat(msg.data['particulateMatter25Measurement']);
4306
-
4307
- // Air Quality Scale (ikea app):
4308
- // 0-35=Good, 35-80=OK, 80+=Not Good
4309
- let airQuality;
4310
- const airQualityProperty = postfixWithEndpointName('air_quality', msg, model);
4311
- if (pm25 <= 35) {
4312
- airQuality = 'good';
4313
- } else if (pm25 <= 80) {
4314
- airQuality = 'ok';
4315
- } else if (pm25 < 65535) {
4316
- airQuality = 'not_good';
4317
- } else {
4318
- airQuality = 'unknown';
4319
- }
4320
-
4321
- // calibrate and round pm25 unless invalid
4322
- pm25 = (pm25 == 65535) ? -1 : calibrateAndPrecisionRoundOptions(pm25, options, 'pm25');
4323
-
4324
- state[pm25Property] = calibrateAndPrecisionRoundOptions(pm25, options, 'pm25');
4325
- state[airQualityProperty] = airQuality;
4326
- }
4327
-
4328
- if (msg.data.hasOwnProperty('filterRunTime')) {
4329
- // Filter needs to be replaced after 6 months
4330
- state['replace_filter'] = (parseInt(msg.data['filterRunTime']) >= 259200);
4331
- }
4332
-
4333
- if (msg.data.hasOwnProperty('controlPanelLight')) {
4334
- state['led_enable'] = (msg.data['controlPanelLight'] == 0);
4335
- }
4336
-
4337
- if (msg.data.hasOwnProperty('childLock')) {
4338
- state['child_lock'] = (msg.data['childLock'] > 0 ? 'LOCK' : 'UNLOCK');
4339
- }
4340
-
4341
- if (msg.data.hasOwnProperty('fanSpeed')) {
4342
- let fanSpeed = msg.data['fanSpeed'];
4343
- if (fanSpeed >= 10) {
4344
- fanSpeed = (((fanSpeed - 5) * 2) / 10);
4345
- } else {
4346
- fanSpeed = 0;
4347
- }
4348
-
4349
- state['fan_speed'] = fanSpeed;
4350
- }
4351
-
4352
- if (msg.data.hasOwnProperty('fanMode')) {
4353
- let fanMode = msg.data['fanMode'];
4354
- if (fanMode >= 10) {
4355
- fanMode = (((fanMode - 5) * 2) / 10).toString();
4356
- } else if (fanMode == 1) {
4357
- fanMode = 'auto';
4358
- } else {
4359
- fanMode = 'off';
4360
- }
4361
-
4362
- state['fan_mode'] = fanMode;
4363
- state['fan_state'] = (fanMode === 'off' ? 'OFF' : 'ON');
4364
- }
4365
-
4366
- return state;
4367
- },
4368
- },
4369
4296
  E1524_E1810_levelctrl: {
4370
4297
  cluster: 'genLevelCtrl',
4371
4298
  type: [
@@ -1922,71 +1922,6 @@ const converters = {
1922
1922
  await entity.read('genBasic', [0x0033], manufacturerOptions.hue);
1923
1923
  },
1924
1924
  },
1925
- ikea_air_purifier_fan_mode: {
1926
- key: ['fan_mode', 'fan_state'],
1927
- convertSet: async (entity, key, value, meta) => {
1928
- if (key == 'fan_state' && value.toLowerCase() == 'on') {
1929
- value = utils.getMetaValue(entity, meta.mapped, 'fanStateOn', 'allEqual', 'on');
1930
- }
1931
-
1932
- let fanMode;
1933
- switch (value.toLowerCase()) {
1934
- case 'off':
1935
- fanMode = 0;
1936
- break;
1937
- case 'auto':
1938
- fanMode = 1;
1939
- break;
1940
- default:
1941
- fanMode = parseInt(((parseInt(value) / 2.0) * 10) + 5);
1942
- }
1943
-
1944
- await entity.write('manuSpecificIkeaAirPurifier', {'fanMode': fanMode}, manufacturerOptions.ikea);
1945
- return {state: {fan_mode: value.toLowerCase(), fan_state: value.toLowerCase() === 'off' ? 'OFF' : 'ON'}};
1946
- },
1947
- convertGet: async (entity, key, meta) => {
1948
- await entity.read('manuSpecificIkeaAirPurifier', ['fanMode']);
1949
- },
1950
- },
1951
- ikea_air_purifier_fan_speed: {
1952
- key: ['fan_speed'],
1953
- convertGet: async (entity, key, meta) => {
1954
- await entity.read('manuSpecificIkeaAirPurifier', ['fanSpeed']);
1955
- },
1956
- },
1957
- ikea_air_purifier_pm25: {
1958
- key: ['pm25', 'air_quality'],
1959
- convertGet: async (entity, key, meta) => {
1960
- await entity.read('manuSpecificIkeaAirPurifier', ['particulateMatter25Measurement']);
1961
- },
1962
- },
1963
- ikea_air_purifier_replace_filter: {
1964
- key: ['replace_filter'],
1965
- convertGet: async (entity, key, meta) => {
1966
- await entity.read('manuSpecificIkeaAirPurifier', ['filterRunTime']);
1967
- },
1968
- },
1969
- ikea_air_purifier_child_lock: {
1970
- key: ['child_lock'],
1971
- convertSet: async (entity, key, value, meta) => {
1972
- await entity.write('manuSpecificIkeaAirPurifier', {'childLock': ((value.toLowerCase() === 'lock') ? 1 : 0)},
1973
- manufacturerOptions.ikea);
1974
- return {state: {child_lock: ((value.toLowerCase() === 'lock') ? 'LOCK' : 'UNLOCK')}};
1975
- },
1976
- convertGet: async (entity, key, meta) => {
1977
- await entity.read('manuSpecificIkeaAirPurifier', ['childLock']);
1978
- },
1979
- },
1980
- ikea_air_purifier_led_enable: {
1981
- key: ['led_enable'],
1982
- convertSet: async (entity, key, value, meta) => {
1983
- await entity.write('manuSpecificIkeaAirPurifier', {'controlPanelLight': ((value) ? 0 : 1)}, manufacturerOptions.ikea);
1984
- return {state: {led_enable: ((value) ? true : false)}};
1985
- },
1986
- convertGet: async (entity, key, meta) => {
1987
- await entity.read('manuSpecificIkeaAirPurifier', ['controlPanelLight']);
1988
- },
1989
- },
1990
1925
  RTCGQ13LM_motion_sensitivity: {
1991
1926
  key: ['motion_sensitivity'],
1992
1927
  convertSet: async (entity, key, value, meta) => {
@@ -2032,9 +1967,9 @@ const converters = {
2032
1967
  xiaomi_switch_power_outage_memory: {
2033
1968
  key: ['power_outage_memory'],
2034
1969
  convertSet: async (entity, key, value, meta) => {
2035
- if (['ZNCZ04LM', 'QBKG25LM', 'SSM-U01', 'SSM-U02', 'DLKZMK11LM', 'QBKG39LM', 'QBKG41LM', 'ZNCZ15LM',
1970
+ if (['ZNCZ04LM', 'QBKG25LM', 'SSM-U01', 'SSM-U02', 'DLKZMK11LM', 'DLKZMK12LM', 'QBKG39LM', 'QBKG41LM', 'ZNCZ15LM',
2036
1971
  'WS-EUK01', 'WS-EUK02', 'WS-EUK03', 'WS-EUK04', 'QBKG31LM', 'QBCZ15LM', 'QBKG20LM', 'QBKG38LM',
2037
- 'QBKG34LM', 'QBCZ14LM', 'QBKG19LM'].includes(meta.mapped.model)) {
1972
+ 'QBKG34LM', 'QBCZ14LM', 'QBKG19LM', 'QBKG40LM', 'QBKG41LM'].includes(meta.mapped.model)) {
2038
1973
  await entity.write('aqaraOpple', {0x0201: {value: value ? 1 : 0, type: 0x10}}, manufacturerOptions.xiaomi);
2039
1974
  } else if (['ZNCZ02LM', 'QBCZ11LM'].includes(meta.mapped.model)) {
2040
1975
  const payload = value ?
@@ -2055,9 +1990,9 @@ const converters = {
2055
1990
  return {state: {power_outage_memory: value}};
2056
1991
  },
2057
1992
  convertGet: async (entity, key, meta) => {
2058
- if (['ZNCZ04LM', 'QBKG25LM', 'SSM-U01', 'SSM-U02', 'DLKZMK11LM', 'QBKG39LM', 'QBKG41LM', 'ZNCZ15LM',
1993
+ if (['ZNCZ04LM', 'QBKG25LM', 'SSM-U01', 'SSM-U02', 'DLKZMK11LM', 'DLKZMK12LM', 'QBKG39LM', 'QBKG41LM', 'ZNCZ15LM',
2059
1994
  'WS-EUK02', 'WS-EUK01', 'QBKG31LM', 'QBCZ15LM', 'QBCZ14LM', 'QBKG20LM', 'QBKG34LM', 'QBKG19LM',
2060
- 'QBKG38LM'].includes(meta.mapped.model)) {
1995
+ 'QBKG38LM', 'QBKG40LM', 'QBKG41LM'].includes(meta.mapped.model)) {
2061
1996
  await entity.read('aqaraOpple', [0x0201]);
2062
1997
  } else if (['ZNCZ02LM', 'QBCZ11LM', 'ZNCZ11LM'].includes(meta.mapped.model)) {
2063
1998
  await entity.read('aqaraOpple', [0xFFF0]);
package/devices/ikea.js CHANGED
@@ -8,6 +8,10 @@ const {repInterval} = require('../lib/constants');
8
8
  const extend = require('../lib/extend');
9
9
  const e = exposes.presets;
10
10
  const ea = exposes.access;
11
+ const herdsman = require('zigbee-herdsman');
12
+ const {
13
+ calibrateAndPrecisionRoundOptions, postfixWithEndpointName, getMetaValue,
14
+ } = require('../lib/utils');
11
15
 
12
16
  const bulbOnEvent = async (type, data, device) => {
13
17
  /**
@@ -49,6 +53,161 @@ const tradfriExtend = {
49
53
  }),
50
54
  };
51
55
 
56
+ const manufacturerOptions = {manufacturerCode: herdsman.Zcl.ManufacturerCode.IKEA_OF_SWEDEN};
57
+
58
+ const ikea = {
59
+ fz: {
60
+ air_purifier: {
61
+ cluster: 'manuSpecificIkeaAirPurifier',
62
+ type: ['attributeReport', 'readResponse'],
63
+ options: [exposes.options.precision('pm25'), exposes.options.calibration('pm25')],
64
+ convert: (model, msg, publish, options, meta) => {
65
+ const state = {};
66
+
67
+ if (msg.data.hasOwnProperty('particulateMatter25Measurement')) {
68
+ const pm25Property = postfixWithEndpointName('pm25', msg, model);
69
+ let pm25 = parseFloat(msg.data['particulateMatter25Measurement']);
70
+
71
+ // Air Quality
72
+ // Scale based on EU AQI (https://www.eea.europa.eu/themes/air/air-quality-index)
73
+ // Using German IAQ labels to match the Develco Air Quality Sensor
74
+ let airQuality;
75
+ const airQualityProperty = postfixWithEndpointName('air_quality', msg, model);
76
+ if (pm25 <= 10) {
77
+ airQuality = 'excellent';
78
+ } else if (pm25 <= 20) {
79
+ airQuality = 'good';
80
+ } else if (pm25 <= 25) {
81
+ airQuality = 'moderate';
82
+ } else if (pm25 <= 50) {
83
+ airQuality = 'poor';
84
+ } else if (pm25 <= 75) {
85
+ airQuality = 'unhealthy';
86
+ } else if (pm25 <= 800) {
87
+ airQuality = 'hazardous';
88
+ } else if (pm25 < 65535) {
89
+ airQuality = 'out_of_range';
90
+ } else {
91
+ airQuality = 'unknown';
92
+ }
93
+
94
+ // calibrate and round pm25 unless invalid
95
+ pm25 = (pm25 == 65535) ? -1 : calibrateAndPrecisionRoundOptions(pm25, options, 'pm25');
96
+
97
+ state[pm25Property] = calibrateAndPrecisionRoundOptions(pm25, options, 'pm25');
98
+ state[airQualityProperty] = airQuality;
99
+ }
100
+
101
+ if (msg.data.hasOwnProperty('filterRunTime')) {
102
+ // Filter needs to be replaced after 6 months
103
+ state['replace_filter'] = (parseInt(msg.data['filterRunTime']) >= 259200);
104
+ }
105
+
106
+ if (msg.data.hasOwnProperty('controlPanelLight')) {
107
+ state['led_enable'] = (msg.data['controlPanelLight'] == 0);
108
+ }
109
+
110
+ if (msg.data.hasOwnProperty('childLock')) {
111
+ state['child_lock'] = (msg.data['childLock'] > 0 ? 'LOCK' : 'UNLOCK');
112
+ }
113
+
114
+ if (msg.data.hasOwnProperty('fanSpeed')) {
115
+ let fanSpeed = msg.data['fanSpeed'];
116
+ if (fanSpeed >= 10) {
117
+ fanSpeed = (((fanSpeed - 5) * 2) / 10);
118
+ } else {
119
+ fanSpeed = 0;
120
+ }
121
+
122
+ state['fan_speed'] = fanSpeed;
123
+ }
124
+
125
+ if (msg.data.hasOwnProperty('fanMode')) {
126
+ let fanMode = msg.data['fanMode'];
127
+ if (fanMode >= 10) {
128
+ fanMode = (((fanMode - 5) * 2) / 10).toString();
129
+ } else if (fanMode == 1) {
130
+ fanMode = 'auto';
131
+ } else {
132
+ fanMode = 'off';
133
+ }
134
+
135
+ state['fan_mode'] = fanMode;
136
+ state['fan_state'] = (fanMode === 'off' ? 'OFF' : 'ON');
137
+ }
138
+
139
+ return state;
140
+ },
141
+ },
142
+ },
143
+ tz: {
144
+ air_purifier_fan_mode: {
145
+ key: ['fan_mode', 'fan_state'],
146
+ convertSet: async (entity, key, value, meta) => {
147
+ if (key == 'fan_state' && value.toLowerCase() == 'on') {
148
+ value = getMetaValue(entity, meta.mapped, 'fanStateOn', 'allEqual', 'on');
149
+ }
150
+
151
+ let fanMode;
152
+ switch (value.toLowerCase()) {
153
+ case 'off':
154
+ fanMode = 0;
155
+ break;
156
+ case 'auto':
157
+ fanMode = 1;
158
+ break;
159
+ default:
160
+ fanMode = parseInt(((parseInt(value) / 2.0) * 10) + 5);
161
+ }
162
+
163
+ await entity.write('manuSpecificIkeaAirPurifier', {'fanMode': fanMode}, manufacturerOptions.ikea);
164
+ return {state: {fan_mode: value.toLowerCase(), fan_state: value.toLowerCase() === 'off' ? 'OFF' : 'ON'}};
165
+ },
166
+ convertGet: async (entity, key, meta) => {
167
+ await entity.read('manuSpecificIkeaAirPurifier', ['fanMode']);
168
+ },
169
+ },
170
+ air_purifier_fan_speed: {
171
+ key: ['fan_speed'],
172
+ convertGet: async (entity, key, meta) => {
173
+ await entity.read('manuSpecificIkeaAirPurifier', ['fanSpeed']);
174
+ },
175
+ },
176
+ air_purifier_pm25: {
177
+ key: ['pm25', 'air_quality'],
178
+ convertGet: async (entity, key, meta) => {
179
+ await entity.read('manuSpecificIkeaAirPurifier', ['particulateMatter25Measurement']);
180
+ },
181
+ },
182
+ air_purifier_replace_filter: {
183
+ key: ['replace_filter'],
184
+ convertGet: async (entity, key, meta) => {
185
+ await entity.read('manuSpecificIkeaAirPurifier', ['filterRunTime']);
186
+ },
187
+ },
188
+ air_purifier_child_lock: {
189
+ key: ['child_lock'],
190
+ convertSet: async (entity, key, value, meta) => {
191
+ await entity.write('manuSpecificIkeaAirPurifier', {'childLock': ((value.toLowerCase() === 'lock') ? 1 : 0)},
192
+ manufacturerOptions);
193
+ return {state: {child_lock: ((value.toLowerCase() === 'lock') ? 'LOCK' : 'UNLOCK')}};
194
+ },
195
+ convertGet: async (entity, key, meta) => {
196
+ await entity.read('manuSpecificIkeaAirPurifier', ['childLock']);
197
+ },
198
+ },
199
+ air_purifier_led_enable: {
200
+ key: ['led_enable'],
201
+ convertSet: async (entity, key, value, meta) => {
202
+ await entity.write('manuSpecificIkeaAirPurifier', {'controlPanelLight': ((value) ? 0 : 1)}, manufacturerOptions);
203
+ return {state: {led_enable: ((value) ? true : false)}};
204
+ },
205
+ convertGet: async (entity, key, meta) => {
206
+ await entity.read('manuSpecificIkeaAirPurifier', ['controlPanelLight']);
207
+ },
208
+ },
209
+ },
210
+ };
52
211
 
53
212
  module.exports = [
54
213
  {
@@ -632,7 +791,9 @@ module.exports = [
632
791
  .withDescription('Current fan speed'),
633
792
  e.pm25().withAccess(ea.STATE_GET),
634
793
  exposes.enum('air_quality', ea.STATE_GET, [
635
- 'good', 'ok', 'not_good', 'unknown',
794
+ 'excellent', 'good', 'moderate', 'poor',
795
+ 'unhealthy', 'hazardous', 'out_of_range',
796
+ 'unknown',
636
797
  ]).withDescription('Measured air quality'),
637
798
  exposes.binary('led_enable', ea.ALL, true, false).withDescription('Enabled LED'),
638
799
  exposes.binary('child_lock', ea.ALL, 'LOCK', 'UNLOCK').withDescription('Enables/disables physical input on the device'),
@@ -640,29 +801,28 @@ module.exports = [
640
801
  .withDescription('Filter is older than 6 months and needs replacing'),
641
802
  ],
642
803
  meta: {fanStateOn: 'auto'},
643
- fromZigbee: [fz.ikea_air_purifier],
804
+ fromZigbee: [ikea.fz.air_purifier],
644
805
  toZigbee: [
645
- tz.ikea_air_purifier_fan_mode, tz.ikea_air_purifier_fan_speed,
646
- tz.ikea_air_purifier_pm25, tz.ikea_air_purifier_child_lock, tz.ikea_air_purifier_led_enable,
647
- tz.ikea_air_purifier_replace_filter,
806
+ ikea.tz.air_purifier_fan_mode, ikea.tz.air_purifier_fan_speed,
807
+ ikea.tz.air_purifier_pm25, ikea.tz.air_purifier_child_lock, ikea.tz.air_purifier_led_enable,
808
+ ikea.tz.air_purifier_replace_filter,
648
809
  ],
649
810
  configure: async (device, coordinatorEndpoint, logger) => {
650
- const options = {manufacturerCode: 0x117c};
651
811
  const endpoint = device.getEndpoint(1);
652
812
 
653
813
  await reporting.bind(endpoint, coordinatorEndpoint, ['manuSpecificIkeaAirPurifier']);
654
814
  await endpoint.configureReporting('manuSpecificIkeaAirPurifier', [{attribute: 'particulateMatter25Measurement',
655
815
  minimumReportInterval: repInterval.MINUTE, maximumReportInterval: repInterval.HOUR, reportableChange: 1}],
656
- options);
816
+ manufacturerOptions);
657
817
  await endpoint.configureReporting('manuSpecificIkeaAirPurifier', [{attribute: 'filterRunTime',
658
818
  minimumReportInterval: repInterval.HOUR, maximumReportInterval: repInterval.HOUR, reportableChange: 0}],
659
- options);
819
+ manufacturerOptions);
660
820
  await endpoint.configureReporting('manuSpecificIkeaAirPurifier', [{attribute: 'fanMode',
661
821
  minimumReportInterval: 0, maximumReportInterval: repInterval.HOUR, reportableChange: 1}],
662
- options);
822
+ manufacturerOptions);
663
823
  await endpoint.configureReporting('manuSpecificIkeaAirPurifier', [{attribute: 'fanSpeed',
664
824
  minimumReportInterval: 0, maximumReportInterval: repInterval.HOUR, reportableChange: 1}],
665
- options);
825
+ manufacturerOptions);
666
826
 
667
827
  await endpoint.read('manuSpecificIkeaAirPurifier', ['controlPanelLight', 'childLock', 'filterRunTime']);
668
828
  },
package/devices/osram.js CHANGED
@@ -30,6 +30,14 @@ module.exports = [
30
30
  extend: extend.ledvance.light_onoff_brightness_colortemp_color(),
31
31
  ota: ota.ledvance,
32
32
  },
33
+ {
34
+ zigbeeModel: ['LIGHTIFY RT RGBW'],
35
+ model: '73741_LIGHTIFY',
36
+ vendor: 'OSRAM',
37
+ description: 'LIGHTIFY RT5/6 LED',
38
+ extend: extend.ledvance.light_onoff_brightness_colortemp_color(),
39
+ ota: ota.ledvance,
40
+ },
33
41
  {
34
42
  zigbeeModel: ['Classic A60 RGBW'],
35
43
  model: 'AA69697',
@@ -735,6 +735,15 @@ module.exports = [
735
735
  extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
736
736
  ota: ota.zigbeeOTA,
737
737
  },
738
+ {
739
+ zigbeeModel: ['LCA009'],
740
+ model: '9290024717',
741
+ vendor: 'Philips',
742
+ description: 'Hue white and color ambiance E26/A19 1600lm',
743
+ meta: {turnsOffAtBrightness1: true},
744
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
745
+ ota: ota.zigbeeOTA,
746
+ },
738
747
  {
739
748
  zigbeeModel: ['LCT001', 'LCT007', 'LCT010', 'LCT012', 'LCT014', 'LCT015', 'LCT016', 'LCT021'],
740
749
  model: '9290012573A',
@@ -1058,6 +1067,15 @@ module.exports = [
1058
1067
  extend: hueExtend.light_onoff_brightness_colortemp_color(),
1059
1068
  ota: ota.zigbeeOTA,
1060
1069
  },
1070
+ {
1071
+ zigbeeModel: ['4090231P9'],
1072
+ model: '4090231P9',
1073
+ vendor: 'Philips',
1074
+ description: 'Hue Liane',
1075
+ meta: {turnsOffAtBrightness1: true},
1076
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
1077
+ ota: ota.zigbeeOTA,
1078
+ },
1061
1079
  {
1062
1080
  zigbeeModel: ['LTC001'],
1063
1081
  model: '3261030P7',
@@ -1306,7 +1324,7 @@ module.exports = [
1306
1324
  vendor: 'Philips',
1307
1325
  description: 'Hue Iris (generation 2, black)',
1308
1326
  meta: {turnsOffAtBrightness1: true},
1309
- extend: hueExtend.light_onoff_brightness_color(),
1327
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
1310
1328
  ota: ota.zigbeeOTA,
1311
1329
  },
1312
1330
  {
@@ -1408,6 +1426,15 @@ module.exports = [
1408
1426
  extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
1409
1427
  ota: ota.zigbeeOTA,
1410
1428
  },
1429
+ {
1430
+ zigbeeModel: ['LCT020'],
1431
+ model: '4080148P7',
1432
+ vendor: 'Philips',
1433
+ description: 'Hue Signe table light',
1434
+ meta: {turnsOffAtBrightness1: true},
1435
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
1436
+ ota: ota.zigbeeOTA,
1437
+ },
1411
1438
  {
1412
1439
  zigbeeModel: ['4080148P9'],
1413
1440
  model: '4080148P9',
@@ -2104,7 +2131,7 @@ module.exports = [
2104
2131
  vendor: 'Philips',
2105
2132
  description: 'Hue Play gradient lightstrip 65',
2106
2133
  meta: {turnsOffAtBrightness1: true},
2107
- extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 500]}),
2134
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
2108
2135
  ota: ota.zigbeeOTA,
2109
2136
  },
2110
2137
  {
@@ -2314,4 +2341,13 @@ module.exports = [
2314
2341
  extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
2315
2342
  ota: ota.zigbeeOTA,
2316
2343
  },
2344
+ {
2345
+ zigbeeModel: ['LTA005'],
2346
+ model: '8719514392830',
2347
+ vendor: 'Philips',
2348
+ description: 'Hue White Ambiance E27 filament screw globe',
2349
+ meta: {turnsOffAtBrightness1: true},
2350
+ extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [222, 454]}),
2351
+ ota: ota.zigbeeOTA,
2352
+ },
2317
2353
  ];
package/devices/tuya.js CHANGED
@@ -1014,11 +1014,15 @@ module.exports = [
1014
1014
  .withDescription('Recover state after power outage')],
1015
1015
  },
1016
1016
  {
1017
- fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_dpo1ysak'},
1018
- {modelID: 'TS011F', manufacturerName: '_TZ3000_cphmq0q7', applicationVersion: 69}],
1017
+ fingerprint: [
1018
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_dpo1ysak'},
1019
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_cphmq0q7', applicationVersion: 69},
1020
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_5f43h46b'},
1021
+ ],
1019
1022
  model: 'TS011F_plug_3',
1020
1023
  description: 'Smart plug (with power monitoring by polling)',
1021
1024
  vendor: 'TuYa',
1025
+ whiteLabel: [{vendor: 'VIKEFON', model: 'TS011F'}],
1022
1026
  fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering, fz.ignore_basic_report, fz.tuya_switch_power_outage_memory],
1023
1027
  toZigbee: [tz.on_off, tz.tuya_switch_power_outage_memory],
1024
1028
  configure: async (device, coordinatorEndpoint, logger) => {
package/devices/xiaomi.js CHANGED
@@ -116,7 +116,7 @@ module.exports = [
116
116
  model: 'JWDL001A',
117
117
  vendor: 'Xiaomi',
118
118
  description: 'Aqara embedded spot led light',
119
- extend: xiaomiExtend.light_onoff_brightness_colortemp(),
119
+ extend: xiaomiExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 370]}),
120
120
  },
121
121
  {
122
122
  zigbeeModel: ['lumi.sensor_switch'],
@@ -1426,6 +1426,22 @@ module.exports = [
1426
1426
  device.save();
1427
1427
  },
1428
1428
  },
1429
+ {
1430
+ zigbeeModel: ['lumi.switch.l0acn1'],
1431
+ model: 'DLKZMK12LM',
1432
+ vendor: 'Xiaomi',
1433
+ description: 'Aqara single switch module T1 (without neutral). Doesn\'t work as a router and doesn\'t support power meter',
1434
+ fromZigbee: [fz.on_off, fz.xiaomi_switch_type, fz.xiaomi_switch_power_outage_memory],
1435
+ exposes: [e.switch(), e.power_outage_memory(), e.switch_type()],
1436
+ toZigbee: [tz.xiaomi_switch_type, tz.on_off, tz.xiaomi_switch_power_outage_memory],
1437
+ configure: async (device, coordinatorEndpoint, logger) => {
1438
+ const endpoint = device.getEndpoint(1);
1439
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
1440
+ await reporting.onOff(endpoint);
1441
+ device.powerSource = 'Mains (single phase)';
1442
+ device.save();
1443
+ },
1444
+ },
1429
1445
  {
1430
1446
  zigbeeModel: ['lumi.switch.n4acn4'],
1431
1447
  model: 'ZNCJMB14LM',
package/lib/exposes.js CHANGED
@@ -503,7 +503,7 @@ module.exports = {
503
503
  battery: () => new Numeric('battery', access.STATE).withUnit('%').withDescription('Remaining battery in %').withValueMin(0).withValueMax(100),
504
504
  battery_low: () => new Binary('battery_low', access.STATE, true, false).withDescription('Indicates if the battery of this device is almost empty'),
505
505
  battery_voltage: () => new Numeric('voltage', access.STATE).withUnit('mV').withDescription('Voltage of the battery in millivolts'),
506
- boost_time: () => new Numeric('boost_time', access.STATE_SET).withUnit('s').withDescription('Boost time'),
506
+ boost_time: () => new Numeric('boost_time', access.STATE_SET).withUnit('s').withDescription('Boost time').withValueMin(0).withValueMax(600),
507
507
  button_lock: () => new Binary('button_lock', access.ALL, 'ON', 'OFF').withDescription('Disables the physical switch button'),
508
508
  carbon_monoxide: () => new Binary('carbon_monoxide', access.STATE, true, false).withDescription('Indicates if CO (carbon monoxide) is detected'),
509
509
  child_lock: () => new Lock().withState('child_lock', 'LOCK', 'UNLOCK', 'Enables/disables physical input on the device', access.STATE_SET),
package/lib/utils.js CHANGED
@@ -72,7 +72,7 @@ function hasAlreadyProcessedMessage(msg, ID=null, key=null) {
72
72
  return false;
73
73
  }
74
74
 
75
- const defaultPrecision = {temperature: 2, humidity: 2, pressure: 1, pm25: 2};
75
+ const defaultPrecision = {temperature: 2, humidity: 2, pressure: 1, pm25: 0};
76
76
  function calibrateAndPrecisionRoundOptions(number, options, type) {
77
77
  // Calibrate
78
78
  const calibrateKey = `${type}_calibration`;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.320",
3
+ "version": "14.0.324",
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.320",
3
+ "version": "14.0.324",
4
4
  "description": "Collection of device converters to be used with zigbee-herdsman",
5
5
  "main": "index.js",
6
6
  "files": [