zigbee-herdsman-converters 15.0.53 → 15.0.55
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/converters/fromZigbee.js +15 -15
- package/converters/toZigbee.js +14 -14
- package/devices/heiman.js +3 -3
- package/devices/ikea.js +27 -1
- package/devices/innr.js +2 -3
- package/devices/ledvance.js +7 -0
- package/devices/lellki.js +1 -1
- package/devices/lidl.js +101 -1
- package/devices/makegood.js +1 -2
- package/devices/miboxer.js +1 -1
- package/devices/micromatic.js +1 -3
- package/devices/robb.js +2 -3
- package/devices/sonoff.js +1 -1
- package/devices/third_reality.js +14 -6
- package/devices/tuya.js +32 -4
- package/devices/ubisys.js +2 -1
- package/devices/vesternet.js +188 -0
- package/devices/xiaomi.js +15 -15
- package/lib/constants.js +12 -5
- package/lib/tuya.js +2 -2
- package/package.json +1 -1
package/converters/fromZigbee.js
CHANGED
|
@@ -327,7 +327,7 @@ const converters = {
|
|
|
327
327
|
type: ['attributeReport', 'readResponse'],
|
|
328
328
|
convert: (model, msg, publish, options, meta) => {
|
|
329
329
|
const payload = {};
|
|
330
|
-
if (msg.data.hasOwnProperty('batteryPercentageRemaining')) {
|
|
330
|
+
if (msg.data.hasOwnProperty('batteryPercentageRemaining') && (msg.data['batteryPercentageRemaining'] < 255)) {
|
|
331
331
|
// Some devices do not comply to the ZCL and report a
|
|
332
332
|
// batteryPercentageRemaining of 100 when the battery is full (should be 200).
|
|
333
333
|
const dontDividePercentage = model.meta && model.meta.battery && model.meta.battery.dontDividePercentage;
|
|
@@ -336,7 +336,7 @@ const converters = {
|
|
|
336
336
|
payload.battery = precisionRound(percentage, 2);
|
|
337
337
|
}
|
|
338
338
|
|
|
339
|
-
if (msg.data.hasOwnProperty('batteryVoltage')) {
|
|
339
|
+
if (msg.data.hasOwnProperty('batteryVoltage') && (msg.data['batteryVoltage'] < 255)) {
|
|
340
340
|
// Deprecated: voltage is = mV now but should be V
|
|
341
341
|
payload.voltage = msg.data['batteryVoltage'] * 100;
|
|
342
342
|
|
|
@@ -408,6 +408,15 @@ const converters = {
|
|
|
408
408
|
}
|
|
409
409
|
},
|
|
410
410
|
},
|
|
411
|
+
pm25: {
|
|
412
|
+
cluster: 'pm25Measurement',
|
|
413
|
+
type: ['attributeReport', 'readResponse'],
|
|
414
|
+
convert: (model, msg, publish, options, meta) => {
|
|
415
|
+
if (msg.data['measuredValue']) {
|
|
416
|
+
return {pm25: msg.data['measuredValue']};
|
|
417
|
+
}
|
|
418
|
+
},
|
|
419
|
+
},
|
|
411
420
|
soil_moisture: {
|
|
412
421
|
cluster: 'msSoilMoisture',
|
|
413
422
|
type: ['attributeReport', 'readResponse'],
|
|
@@ -601,8 +610,8 @@ const converters = {
|
|
|
601
610
|
}
|
|
602
611
|
|
|
603
612
|
if (msg.data.hasOwnProperty('colorMode')) {
|
|
604
|
-
result.color_mode = constants.
|
|
605
|
-
constants.
|
|
613
|
+
result.color_mode = constants.colorModeLookup.hasOwnProperty(msg.data['colorMode']) ?
|
|
614
|
+
constants.colorModeLookup[msg.data['colorMode']] : msg.data['colorMode'];
|
|
606
615
|
}
|
|
607
616
|
|
|
608
617
|
if (
|
|
@@ -2299,9 +2308,9 @@ const converters = {
|
|
|
2299
2308
|
|
|
2300
2309
|
if (msg.data.hasOwnProperty('tuyaRgbMode')) {
|
|
2301
2310
|
if (msg.data['tuyaRgbMode'] === 1) {
|
|
2302
|
-
result.color_mode = constants.
|
|
2311
|
+
result.color_mode = constants.colorModeLookup[0];
|
|
2303
2312
|
} else {
|
|
2304
|
-
result.color_mode = constants.
|
|
2313
|
+
result.color_mode = constants.colorModeLookup[2];
|
|
2305
2314
|
}
|
|
2306
2315
|
}
|
|
2307
2316
|
|
|
@@ -5926,15 +5935,6 @@ const converters = {
|
|
|
5926
5935
|
};
|
|
5927
5936
|
},
|
|
5928
5937
|
},
|
|
5929
|
-
heiman_pm25: {
|
|
5930
|
-
cluster: 'heimanSpecificPM25Measurement',
|
|
5931
|
-
type: ['attributeReport', 'readResponse'],
|
|
5932
|
-
convert: (model, msg, publish, options, meta) => {
|
|
5933
|
-
if (msg.data['measuredValue']) {
|
|
5934
|
-
return {pm25: msg.data['measuredValue']};
|
|
5935
|
-
}
|
|
5936
|
-
},
|
|
5937
|
-
},
|
|
5938
5938
|
heiman_hcho: {
|
|
5939
5939
|
cluster: 'heimanSpecificFormaldehydeMeasurement',
|
|
5940
5940
|
type: ['attributeReport', 'readResponse'],
|
package/converters/toZigbee.js
CHANGED
|
@@ -796,7 +796,7 @@ const converters = {
|
|
|
796
796
|
};
|
|
797
797
|
await entity.command('lightingColorCtrl', 'moveToColor', payload, utils.getOptions(meta.mapped, entity));
|
|
798
798
|
return {
|
|
799
|
-
state: libColor.syncColorState({'color_mode': constants.
|
|
799
|
+
state: libColor.syncColorState({'color_mode': constants.colorModeLookup[2], 'color_temp': value}, meta.state,
|
|
800
800
|
entity, meta.options, meta.logger), readAfterWriteTime: payload.transtime * 100,
|
|
801
801
|
};
|
|
802
802
|
}
|
|
@@ -1031,7 +1031,7 @@ const converters = {
|
|
|
1031
1031
|
const payload = {colortemp: value, transtime: utils.getTransition(entity, key, meta).time};
|
|
1032
1032
|
await entity.command('lightingColorCtrl', 'moveToColorTemp', payload, utils.getOptions(meta.mapped, entity));
|
|
1033
1033
|
return {
|
|
1034
|
-
state: libColor.syncColorState({'color_mode': constants.
|
|
1034
|
+
state: libColor.syncColorState({'color_mode': constants.colorModeLookup[2], 'color_temp': value}, meta.state,
|
|
1035
1035
|
entity, meta.options, meta.logger), readAfterWriteTime: payload.transtime * 100,
|
|
1036
1036
|
};
|
|
1037
1037
|
},
|
|
@@ -1091,7 +1091,7 @@ const converters = {
|
|
|
1091
1091
|
xy.y = 0.2993;
|
|
1092
1092
|
}
|
|
1093
1093
|
|
|
1094
|
-
newState.color_mode = constants.
|
|
1094
|
+
newState.color_mode = constants.colorModeLookup[1];
|
|
1095
1095
|
newState.color = xy.toObject();
|
|
1096
1096
|
zclData.colorx = utils.mapNumberRange(xy.x, 0, 1, 0, 65535);
|
|
1097
1097
|
zclData.colory = utils.mapNumberRange(xy.y, 0, 1, 0, 65535);
|
|
@@ -1100,7 +1100,7 @@ const converters = {
|
|
|
1100
1100
|
const enhancedHue = utils.getMetaValue(entity, meta.mapped, 'enhancedHue', 'allEqual', true);
|
|
1101
1101
|
const hsv = newColor.hsv;
|
|
1102
1102
|
const hsvCorrected = hsv.colorCorrected(meta);
|
|
1103
|
-
newState.color_mode = constants.
|
|
1103
|
+
newState.color_mode = constants.colorModeLookup[0];
|
|
1104
1104
|
newState.color = hsv.toObject(false);
|
|
1105
1105
|
|
|
1106
1106
|
if (hsv.hue !== null) {
|
|
@@ -3542,7 +3542,7 @@ const converters = {
|
|
|
3542
3542
|
key: ['brightness', 'color', 'color_temp'],
|
|
3543
3543
|
options: [exposes.options.color_sync()],
|
|
3544
3544
|
convertSet: async (entity, key, value, meta) => {
|
|
3545
|
-
if (key === 'brightness' && meta.state.color_mode == constants.
|
|
3545
|
+
if (key === 'brightness' && meta.state.color_mode == constants.colorModeLookup[2] &&
|
|
3546
3546
|
!meta.message.hasOwnProperty('color') && !meta.message.hasOwnProperty('color_temp')) {
|
|
3547
3547
|
const zclData = {level: Number(value), transtime: 0};
|
|
3548
3548
|
|
|
@@ -3565,7 +3565,7 @@ const converters = {
|
|
|
3565
3565
|
|
|
3566
3566
|
const newState = {
|
|
3567
3567
|
brightness: zclDataBrightness.level,
|
|
3568
|
-
color_mode: constants.
|
|
3568
|
+
color_mode: constants.colorModeLookup[2],
|
|
3569
3569
|
color_temp: meta.message.color_temp,
|
|
3570
3570
|
};
|
|
3571
3571
|
|
|
@@ -3583,7 +3583,7 @@ const converters = {
|
|
|
3583
3583
|
|
|
3584
3584
|
const newState = {
|
|
3585
3585
|
brightness: zclDataBrightness.level,
|
|
3586
|
-
color_mode: constants.
|
|
3586
|
+
color_mode: constants.colorModeLookup[2],
|
|
3587
3587
|
color_temp: value,
|
|
3588
3588
|
};
|
|
3589
3589
|
|
|
@@ -3649,7 +3649,7 @@ const converters = {
|
|
|
3649
3649
|
s: utils.mapNumberRange(zclData.saturation, 0, 254, 0, 100),
|
|
3650
3650
|
saturation: utils.mapNumberRange(zclData.saturation, 0, 254, 0, 100),
|
|
3651
3651
|
},
|
|
3652
|
-
color_mode: constants.
|
|
3652
|
+
color_mode: constants.colorModeLookup[0],
|
|
3653
3653
|
};
|
|
3654
3654
|
|
|
3655
3655
|
return {state: libColor.syncColorState(newState, meta.state, entity, meta.options, meta.logger),
|
|
@@ -5285,12 +5285,12 @@ const converters = {
|
|
|
5285
5285
|
|
|
5286
5286
|
const addColorMode = (newState) => {
|
|
5287
5287
|
if (newState.hasOwnProperty('color_temp')) {
|
|
5288
|
-
newState.color_mode = constants.
|
|
5288
|
+
newState.color_mode = constants.colorModeLookup[2];
|
|
5289
5289
|
} else if (newState.hasOwnProperty('color')) {
|
|
5290
5290
|
if (newState.color.hasOwnProperty('x')) {
|
|
5291
|
-
newState.color_mode = constants.
|
|
5291
|
+
newState.color_mode = constants.colorModeLookup[1];
|
|
5292
5292
|
} else {
|
|
5293
|
-
newState.color_mode = constants.
|
|
5293
|
+
newState.color_mode = constants.colorModeLookup[0];
|
|
5294
5294
|
}
|
|
5295
5295
|
}
|
|
5296
5296
|
|
|
@@ -5391,7 +5391,7 @@ const converters = {
|
|
|
5391
5391
|
const xScaled = utils.mapNumberRange(xy.x, 0, 1, 0, 65535);
|
|
5392
5392
|
const yScaled = utils.mapNumberRange(xy.y, 0, 1, 0, 65535);
|
|
5393
5393
|
extensionfieldsets.push({'clstId': 768, 'len': 4, 'extField': [xScaled, yScaled]});
|
|
5394
|
-
state['color_mode'] = constants.
|
|
5394
|
+
state['color_mode'] = constants.colorModeLookup[2];
|
|
5395
5395
|
state['color_temp'] = val;
|
|
5396
5396
|
} else if (attribute === 'color') {
|
|
5397
5397
|
try {
|
|
@@ -5411,7 +5411,7 @@ const converters = {
|
|
|
5411
5411
|
'extField': [xScaled, yScaled],
|
|
5412
5412
|
},
|
|
5413
5413
|
);
|
|
5414
|
-
state['color_mode'] = constants.
|
|
5414
|
+
state['color_mode'] = constants.colorModeLookup[1];
|
|
5415
5415
|
state['color'] = newColor.xy.toObject();
|
|
5416
5416
|
} else if (newColor.isHSV()) {
|
|
5417
5417
|
const hsvCorrected = newColor.hsv.colorCorrected(meta);
|
|
@@ -5439,7 +5439,7 @@ const converters = {
|
|
|
5439
5439
|
},
|
|
5440
5440
|
);
|
|
5441
5441
|
}
|
|
5442
|
-
state['color_mode'] = constants.
|
|
5442
|
+
state['color_mode'] = constants.colorModeLookup[0];
|
|
5443
5443
|
state['color'] = newColor.hsv.toObject(false, false);
|
|
5444
5444
|
}
|
|
5445
5445
|
}
|
package/devices/heiman.js
CHANGED
|
@@ -557,14 +557,14 @@ module.exports = [
|
|
|
557
557
|
model: 'HS2AQ-EM',
|
|
558
558
|
vendor: 'HEIMAN',
|
|
559
559
|
description: 'Air quality monitor',
|
|
560
|
-
fromZigbee: [fz.battery, fz.temperature, fz.humidity, fz.
|
|
560
|
+
fromZigbee: [fz.battery, fz.temperature, fz.humidity, fz.pm25, fz.heiman_hcho, fz.heiman_air_quality],
|
|
561
561
|
toZigbee: [],
|
|
562
562
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
563
563
|
const heiman = {
|
|
564
564
|
configureReporting: {
|
|
565
565
|
pm25MeasuredValue: async (endpoint, overrides) => {
|
|
566
566
|
const payload = reporting.payload('measuredValue', 0, constants.repInterval.HOUR, 1, overrides);
|
|
567
|
-
await endpoint.configureReporting('
|
|
567
|
+
await endpoint.configureReporting('pm25Measurement', payload);
|
|
568
568
|
},
|
|
569
569
|
formAldehydeMeasuredValue: async (endpoint, overrides) => {
|
|
570
570
|
const payload = reporting.payload('measuredValue', 0, constants.repInterval.HOUR, 1, overrides);
|
|
@@ -591,7 +591,7 @@ module.exports = [
|
|
|
591
591
|
|
|
592
592
|
const endpoint = device.getEndpoint(1);
|
|
593
593
|
await reporting.bind(endpoint, coordinatorEndpoint, [
|
|
594
|
-
'genPowerCfg', 'genTime', 'msTemperatureMeasurement', 'msRelativeHumidity', '
|
|
594
|
+
'genPowerCfg', 'genTime', 'msTemperatureMeasurement', 'msRelativeHumidity', 'pm25Measurement',
|
|
595
595
|
'heimanSpecificFormaldehydeMeasurement', 'heimanSpecificAirQuality']);
|
|
596
596
|
|
|
597
597
|
await reporting.batteryPercentageRemaining(endpoint);
|
package/devices/ikea.js
CHANGED
|
@@ -186,7 +186,7 @@ const ikea = {
|
|
|
186
186
|
type: ['attributeReport', 'readResponse'],
|
|
187
187
|
convert: (model, msg, publish, options, meta) => {
|
|
188
188
|
const payload = {};
|
|
189
|
-
if (msg.data.hasOwnProperty('batteryPercentageRemaining')) {
|
|
189
|
+
if (msg.data.hasOwnProperty('batteryPercentageRemaining') && (msg.data['batteryPercentageRemaining'] < 255)) {
|
|
190
190
|
// Some devices do not comply to the ZCL and report a
|
|
191
191
|
// batteryPercentageRemaining of 100 when the battery is full (should be 200).
|
|
192
192
|
//
|
|
@@ -1025,4 +1025,30 @@ module.exports = [
|
|
|
1025
1025
|
description: 'PILSKOTT LED floor lamp',
|
|
1026
1026
|
extend: tradfriExtend.light_onoff_brightness(),
|
|
1027
1027
|
},
|
|
1028
|
+
{
|
|
1029
|
+
zigbeeModel: ['VINDSTYRKA'],
|
|
1030
|
+
model: 'E2112',
|
|
1031
|
+
vendor: 'IKEA',
|
|
1032
|
+
description: 'Vindstyrka air quality and humidity sensor',
|
|
1033
|
+
fromZigbee: [fz.temperature, fz.humidity, fz.pm25],
|
|
1034
|
+
toZigbee: [],
|
|
1035
|
+
exposes: [e.temperature(), e.humidity(), e.pm25()],
|
|
1036
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1037
|
+
const ep = device.getEndpoint(1);
|
|
1038
|
+
await reporting.bind(ep, coordinatorEndpoint,
|
|
1039
|
+
['msTemperatureMeasurement', 'msRelativeHumidity', 'pm25Measurement']);
|
|
1040
|
+
await ep.configureReporting('msTemperatureMeasurement', [{
|
|
1041
|
+
attribute: 'measuredValue',
|
|
1042
|
+
minimumReportInterval: 60, maximumReportInterval: 120,
|
|
1043
|
+
}]);
|
|
1044
|
+
await ep.configureReporting('msRelativeHumidity', [{
|
|
1045
|
+
attribute: 'measuredValue',
|
|
1046
|
+
minimumReportInterval: 60, maximumReportInterval: 120,
|
|
1047
|
+
}]);
|
|
1048
|
+
await ep.configureReporting('pm25Measurement', [{
|
|
1049
|
+
attribute: 'measuredValueIkea',
|
|
1050
|
+
minimumReportInterval: 60, maximumReportInterval: 120, reportableChange: 2,
|
|
1051
|
+
}]);
|
|
1052
|
+
},
|
|
1053
|
+
},
|
|
1028
1054
|
];
|
package/devices/innr.js
CHANGED
|
@@ -4,7 +4,6 @@ const tz = require('../converters/toZigbee');
|
|
|
4
4
|
const reporting = require('../lib/reporting');
|
|
5
5
|
const extend = require('../lib/extend');
|
|
6
6
|
const e = exposes.presets;
|
|
7
|
-
const ea = exposes.access;
|
|
8
7
|
const ota = require('../lib/ota');
|
|
9
8
|
|
|
10
9
|
module.exports = [
|
|
@@ -543,7 +542,7 @@ module.exports = [
|
|
|
543
542
|
endpoint.saveClusterAttributeKeyValue('seMetering', {multiplier: 1, divisor: 100});
|
|
544
543
|
await reporting.currentSummDelivered(endpoint);
|
|
545
544
|
},
|
|
546
|
-
exposes: [e.power(), e.current(), e.voltage()
|
|
545
|
+
exposes: [e.power(), e.current(), e.voltage(), e.switch(), e.energy()],
|
|
547
546
|
},
|
|
548
547
|
{
|
|
549
548
|
zigbeeModel: ['SP 110'],
|
|
@@ -618,7 +617,7 @@ module.exports = [
|
|
|
618
617
|
await reporting.currentSummDelivered(endpoint);
|
|
619
618
|
},
|
|
620
619
|
ota: ota.zigbeeOTA,
|
|
621
|
-
exposes: [e.power(), e.current(), e.voltage()
|
|
620
|
+
exposes: [e.power(), e.current(), e.voltage(), e.switch(), e.energy()],
|
|
622
621
|
},
|
|
623
622
|
{
|
|
624
623
|
zigbeeModel: ['OFL 120 C'],
|
package/devices/ledvance.js
CHANGED
|
@@ -35,6 +35,13 @@ module.exports = [
|
|
|
35
35
|
extend: extend.ledvance.light_onoff_brightness_colortemp(),
|
|
36
36
|
ota: ota.ledvance,
|
|
37
37
|
},
|
|
38
|
+
{
|
|
39
|
+
zigbeeModel: ['Panel Light 2x2 TW'],
|
|
40
|
+
model: '74746',
|
|
41
|
+
vendor: 'LEDVANCE',
|
|
42
|
+
description: 'LEDVANCE 74746 Sylvania smart+ Zigbee dimmable edge-lit panel',
|
|
43
|
+
extend: extend.ledvance.light_onoff_brightness_colortemp_color({colorTempRange: [200, 370]}),
|
|
44
|
+
},
|
|
38
45
|
{
|
|
39
46
|
zigbeeModel: ['Panel TW 620 UGR19'],
|
|
40
47
|
model: 'GPDRPLOP401100CE',
|
package/devices/lellki.js
CHANGED
|
@@ -135,7 +135,7 @@ module.exports = [
|
|
|
135
135
|
},
|
|
136
136
|
options: [exposes.options.measurement_poll_interval()],
|
|
137
137
|
exposes: [e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'),
|
|
138
|
-
e.switch().withEndpoint('l3'), e.power(), e.current(), e.voltage()
|
|
138
|
+
e.switch().withEndpoint('l3'), e.power(), e.current(), e.voltage(),
|
|
139
139
|
e.energy(), exposes.enum('power_outage_memory', ea.ALL, ['on', 'off', 'restore'])
|
|
140
140
|
.withDescription('Recover state after power outage')],
|
|
141
141
|
endpoint: (device) => {
|
package/devices/lidl.js
CHANGED
|
@@ -7,6 +7,9 @@ const ea = exposes.access;
|
|
|
7
7
|
const tuya = require('../lib/tuya');
|
|
8
8
|
const globalStore = require('../lib/store');
|
|
9
9
|
const ota = require('../lib/ota');
|
|
10
|
+
const utils = require('../lib/utils');
|
|
11
|
+
const {ColorMode} = require('../lib/constants');
|
|
12
|
+
const libColor = require('../lib/color');
|
|
10
13
|
|
|
11
14
|
const tuyaLocal = {
|
|
12
15
|
dataPoints: {
|
|
@@ -142,6 +145,101 @@ const fzLocal = {
|
|
|
142
145
|
},
|
|
143
146
|
};
|
|
144
147
|
const tzLocal = {
|
|
148
|
+
led_control: {
|
|
149
|
+
key: ['brightness', 'color', 'color_temp', 'transition'],
|
|
150
|
+
options: [exposes.options.color_sync()],
|
|
151
|
+
convertSet: async (entity, _key, _value, meta) => {
|
|
152
|
+
const newState = {};
|
|
153
|
+
|
|
154
|
+
// The color mode encodes whether the light is using its white LEDs or its color LEDs
|
|
155
|
+
let colorMode = meta.state.color_mode ?? ColorMode.ColorTemp;
|
|
156
|
+
|
|
157
|
+
// Color mode switching is done by setting color temperature (switch to white LEDs) or setting color (switch
|
|
158
|
+
// to color LEDs)
|
|
159
|
+
if ('color_temp' in meta.message) colorMode = ColorMode.ColorTemp;
|
|
160
|
+
if ('color' in meta.message) colorMode = ColorMode.HS;
|
|
161
|
+
|
|
162
|
+
if (colorMode != meta.state.color_mode) {
|
|
163
|
+
newState.color_mode = colorMode;
|
|
164
|
+
|
|
165
|
+
// To switch between white mode and color mode, we have to send a special command:
|
|
166
|
+
const rgbMode = (colorMode == ColorMode.HS);
|
|
167
|
+
await entity.command('lightingColorCtrl', 'tuyaRgbMode', {enable: rgbMode}, {}, {disableDefaultResponse: true});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// A transition time of 0 would be treated as about 1 second, probably some kind of fallback/default
|
|
171
|
+
// transition time, so for "no transition" we use 1 (tenth of a second).
|
|
172
|
+
const transtime = 'transition' in meta.message ? meta.message.transition * 10 : 1;
|
|
173
|
+
|
|
174
|
+
if (colorMode == ColorMode.ColorTemp) {
|
|
175
|
+
if ('brightness' in meta.message) {
|
|
176
|
+
const zclData = {level: Number(meta.message.brightness), transtime};
|
|
177
|
+
await entity.command('genLevelCtrl', 'moveToLevel', zclData, utils.getOptions(meta.mapped, entity));
|
|
178
|
+
newState.brightness = meta.message.brightness;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if ('color_temp' in meta.message) {
|
|
182
|
+
const zclData = {colortemp: meta.message.color_temp, transtime: transtime};
|
|
183
|
+
await entity.command('lightingColorCtrl', 'moveToColorTemp', zclData, utils.getOptions(meta.mapped, entity));
|
|
184
|
+
newState.color_temp = meta.message.color_temp;
|
|
185
|
+
}
|
|
186
|
+
} else if (colorMode == ColorMode.HS) {
|
|
187
|
+
if ('brightness' in meta.message || 'color' in meta.message) {
|
|
188
|
+
// We ignore the brightness of the color and instead use the overall brightness setting of the lamp
|
|
189
|
+
// for the brightness because I think that's the expected behavior and also because the color
|
|
190
|
+
// conversion below always returns 100 as brightness ("value") even for very dark colors, except
|
|
191
|
+
// when the color is completely black/zero.
|
|
192
|
+
|
|
193
|
+
// Load current state or defaults
|
|
194
|
+
const newSettings = {
|
|
195
|
+
brightness: meta.state.brightness ?? 254, // full brightness
|
|
196
|
+
hue: (meta.state.color ?? {}).h ?? 0, // red
|
|
197
|
+
saturation: (meta.state.color ?? {}).s ?? 100, // full saturation
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
// Apply changes
|
|
201
|
+
if ('brightness' in meta.message) {
|
|
202
|
+
newSettings.brightness = meta.message.brightness;
|
|
203
|
+
newState.brightness = meta.message.brightness;
|
|
204
|
+
}
|
|
205
|
+
if ('color' in meta.message) {
|
|
206
|
+
// The Z2M UI sends `{ hex:'#xxxxxx' }`.
|
|
207
|
+
// Home Assistant sends `{ h: xxx, s: xxx }`.
|
|
208
|
+
// We convert the former into the latter.
|
|
209
|
+
const c = libColor.Color.fromConverterArg(meta.message.color);
|
|
210
|
+
if (c.isRGB()) {
|
|
211
|
+
// https://github.com/Koenkk/zigbee2mqtt/issues/13421#issuecomment-1426044963
|
|
212
|
+
c.hsv = c.rgb.gammaCorrected().toXY().toHSV();
|
|
213
|
+
}
|
|
214
|
+
const color = c.hsv;
|
|
215
|
+
|
|
216
|
+
newSettings.hue = color.hue;
|
|
217
|
+
newSettings.saturation = color.saturation;
|
|
218
|
+
|
|
219
|
+
newState.color = {
|
|
220
|
+
h: color.hue,
|
|
221
|
+
s: color.saturation,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Convert to device specific format and send
|
|
226
|
+
const zclData = {
|
|
227
|
+
brightness: utils.mapNumberRange(newSettings.brightness, 0, 254, 0, 1000),
|
|
228
|
+
hue: newSettings.hue,
|
|
229
|
+
saturation: utils.mapNumberRange(newSettings.saturation, 0, 100, 0, 1000),
|
|
230
|
+
};
|
|
231
|
+
// This command doesn't support a transition time
|
|
232
|
+
await entity.command('lightingColorCtrl', 'tuyaMoveToHueAndSaturationBrightness2', zclData,
|
|
233
|
+
utils.getOptions(meta.mapped, entity));
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return {state: newState};
|
|
238
|
+
},
|
|
239
|
+
convertGet: async (entity, key, meta) => {
|
|
240
|
+
await entity.read('lightingColorCtrl', ['currentHue', 'currentSaturation', 'currentLevel', 'tuyaRgbMode', 'colorTemperature']);
|
|
241
|
+
},
|
|
242
|
+
},
|
|
145
243
|
zs_thermostat_child_lock: {
|
|
146
244
|
key: ['child_lock'],
|
|
147
245
|
convertSet: async (entity, key, value, meta) => {
|
|
@@ -739,7 +837,9 @@ module.exports = [
|
|
|
739
837
|
model: '14149505L/14149506L',
|
|
740
838
|
vendor: 'Lidl',
|
|
741
839
|
description: 'Livarno Lux light bar RGB+CCT (black/white)',
|
|
742
|
-
|
|
840
|
+
toZigbee: [tz.on_off, tzLocal.led_control],
|
|
841
|
+
fromZigbee: [fz.on_off, fz.tuya_led_controller, fz.brightness, fz.ignore_basic_report],
|
|
842
|
+
exposes: [e.light_brightness_colortemp_colorhs([153, 500]).removeFeature('color_temp_startup')],
|
|
743
843
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
744
844
|
device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
|
|
745
845
|
},
|
package/devices/makegood.js
CHANGED
|
@@ -5,7 +5,6 @@ const reporting = require('../lib/reporting');
|
|
|
5
5
|
const tuya = require('../lib/tuya');
|
|
6
6
|
const utils = require('../lib/utils');
|
|
7
7
|
const e = exposes.presets;
|
|
8
|
-
const ea = exposes.access;
|
|
9
8
|
|
|
10
9
|
const fzLocal = {
|
|
11
10
|
// MG-AUZG01 requires multiEndpoint only for on_off
|
|
@@ -30,7 +29,7 @@ module.exports = [
|
|
|
30
29
|
description: 'Double Zigbee power point',
|
|
31
30
|
fromZigbee: [fzLocal.MGAUZG01_on_off, fz.electrical_measurement, fz.metering, fz.ignore_basic_report],
|
|
32
31
|
toZigbee: [tz.on_off],
|
|
33
|
-
exposes: [e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'), e.power(), e.current(), e.voltage()
|
|
32
|
+
exposes: [e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'), e.power(), e.current(), e.voltage(),
|
|
34
33
|
e.energy()],
|
|
35
34
|
endpoint: (device) => {
|
|
36
35
|
return {'l1': 1, 'l2': 2};
|
package/devices/miboxer.js
CHANGED
|
@@ -36,7 +36,7 @@ module.exports = [
|
|
|
36
36
|
model: 'FUT035Z',
|
|
37
37
|
description: 'Dual white LED controller',
|
|
38
38
|
vendor: 'Miboxer',
|
|
39
|
-
extend: tuya.extend.light_onoff_brightness_colortemp({colorTempRange: [153, 500]}),
|
|
39
|
+
extend: tuya.extend.light_onoff_brightness_colortemp({colorTempRange: [153, 500], disablePowerOnBehavior: true}),
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
fingerprint: [{modelID: 'TS0504B', manufacturerName: '_TZ3210_ttkgurpb'}],
|
package/devices/micromatic.js
CHANGED
|
@@ -3,8 +3,6 @@ const exposes = require('../lib/exposes');
|
|
|
3
3
|
const reporting = require('../lib/reporting');
|
|
4
4
|
const extend = require('../lib/extend');
|
|
5
5
|
const e = exposes.presets;
|
|
6
|
-
const ea = exposes.access;
|
|
7
|
-
|
|
8
6
|
|
|
9
7
|
module.exports = [
|
|
10
8
|
{
|
|
@@ -26,6 +24,6 @@ module.exports = [
|
|
|
26
24
|
await reporting.activePower(endpoint, {min: 10, change: 15}); // W - Min change of 1,5W
|
|
27
25
|
await reporting.currentSummDelivered(endpoint, {min: 300}); // Report KWH every 5min
|
|
28
26
|
},
|
|
29
|
-
exposes: [e.light_brightness(), e.power(), e.current(), e.voltage()
|
|
27
|
+
exposes: [e.light_brightness(), e.power(), e.current(), e.voltage(), e.energy()],
|
|
30
28
|
},
|
|
31
29
|
];
|
package/devices/robb.js
CHANGED
|
@@ -4,7 +4,6 @@ const tz = require('../converters/toZigbee');
|
|
|
4
4
|
const reporting = require('../lib/reporting');
|
|
5
5
|
const extend = require('../lib/extend');
|
|
6
6
|
const e = exposes.presets;
|
|
7
|
-
const ea = exposes.access;
|
|
8
7
|
|
|
9
8
|
module.exports = [
|
|
10
9
|
{
|
|
@@ -242,7 +241,7 @@ module.exports = [
|
|
|
242
241
|
await reporting.temperature(endpoint);
|
|
243
242
|
await reporting.currentSummDelivered(endpoint);
|
|
244
243
|
},
|
|
245
|
-
exposes: [e.power(), e.current(), e.voltage()
|
|
244
|
+
exposes: [e.power(), e.current(), e.voltage(), e.switch(), e.energy(), e.temperature()],
|
|
246
245
|
},
|
|
247
246
|
{
|
|
248
247
|
zigbeeModel: ['ROB_200-017-1'],
|
|
@@ -264,7 +263,7 @@ module.exports = [
|
|
|
264
263
|
await reporting.temperature(endpoint);
|
|
265
264
|
await reporting.currentSummDelivered(endpoint);
|
|
266
265
|
},
|
|
267
|
-
exposes: [e.power(), e.current(), e.voltage()
|
|
266
|
+
exposes: [e.power(), e.current(), e.voltage(), e.switch(), e.energy(), e.temperature()],
|
|
268
267
|
},
|
|
269
268
|
{
|
|
270
269
|
zigbeeModel: ['ROB_200-016-0'],
|
package/devices/sonoff.js
CHANGED
package/devices/third_reality.js
CHANGED
|
@@ -171,17 +171,25 @@ module.exports = [
|
|
|
171
171
|
model: '3RSP02028BZ',
|
|
172
172
|
vendor: 'Third Reality',
|
|
173
173
|
description: 'Zigbee / BLE smart plug with power',
|
|
174
|
-
fromZigbee: [fz.on_off, fz.electrical_measurement],
|
|
174
|
+
fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering],
|
|
175
175
|
toZigbee: [tz.on_off],
|
|
176
176
|
ota: ota.zigbeeOTA,
|
|
177
|
-
exposes: [e.switch(), e.power(), e.current(), e.voltage()],
|
|
177
|
+
exposes: [e.switch(), e.ac_frequency(), e.power(), e.power_factor(), e.energy(), e.current(), e.voltage()],
|
|
178
178
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
179
179
|
const endpoint = device.getEndpoint(1);
|
|
180
|
-
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement']);
|
|
180
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering']);
|
|
181
|
+
await endpoint.read('haElectricalMeasurement', ['acPowerMultiplier', 'acPowerDivisor']);
|
|
181
182
|
await reporting.onOff(endpoint);
|
|
182
|
-
await reporting.activePower(endpoint);
|
|
183
|
-
await reporting.rmsCurrent(endpoint);
|
|
184
|
-
await reporting.rmsVoltage(endpoint);
|
|
183
|
+
await reporting.activePower(endpoint, {change: 10});
|
|
184
|
+
await reporting.rmsCurrent(endpoint, {change: 50});
|
|
185
|
+
await reporting.rmsVoltage(endpoint, {change: 5});
|
|
186
|
+
await reporting.readMeteringMultiplierDivisor(endpoint);
|
|
187
|
+
endpoint.saveClusterAttributeKeyValue('seMetering', {divisor: 100, multiplier: 1});
|
|
188
|
+
endpoint.saveClusterAttributeKeyValue('haElectricalMeasurement', {
|
|
189
|
+
acVoltageMultiplier: 1, acVoltageDivisor: 10, acCurrentMultiplier: 1, acCurrentDivisor: 1000, acPowerMultiplier: 1,
|
|
190
|
+
acPowerDivisor: 10,
|
|
191
|
+
});
|
|
192
|
+
device.save();
|
|
185
193
|
},
|
|
186
194
|
},
|
|
187
195
|
];
|
package/devices/tuya.js
CHANGED
|
@@ -1914,7 +1914,7 @@ module.exports = [
|
|
|
1914
1914
|
endpoint.saveClusterAttributeKeyValue('seMetering', {divisor: 100, multiplier: 1});
|
|
1915
1915
|
device.save();
|
|
1916
1916
|
},
|
|
1917
|
-
exposes: [e.switch(), e.power(), e.current(), e.voltage()
|
|
1917
|
+
exposes: [e.switch(), e.power(), e.current(), e.voltage(), e.energy(), tuya.exposes.switchType(),
|
|
1918
1918
|
exposes.enum('power_outage_memory', ea.ALL, ['on', 'off', 'restore']).withDescription('Recover state after power outage')],
|
|
1919
1919
|
},
|
|
1920
1920
|
{
|
|
@@ -1960,7 +1960,7 @@ module.exports = [
|
|
|
1960
1960
|
device.save();
|
|
1961
1961
|
},
|
|
1962
1962
|
whiteLabel: [{vendor: 'Aubess', model: 'WHD02'}],
|
|
1963
|
-
exposes: [e.switch(), e.power(), e.current(), e.voltage()
|
|
1963
|
+
exposes: [e.switch(), e.power(), e.current(), e.voltage(), e.energy(), e.power_on_behavior(),
|
|
1964
1964
|
tuya.exposes.switchType()],
|
|
1965
1965
|
},
|
|
1966
1966
|
{
|
|
@@ -2133,6 +2133,7 @@ module.exports = [
|
|
|
2133
2133
|
{modelID: 'TS0601', manufacturerName: '_TZE200_5sbebbzs'},
|
|
2134
2134
|
{modelID: 'TS0601', manufacturerName: '_TZE200_udank5zs'},
|
|
2135
2135
|
{modelID: 'TS0601', manufacturerName: '_TZE200_zuz7f94z'},
|
|
2136
|
+
{modelID: 'TS0601', manufacturerName: '_TZE200_nv6nxo0c'},
|
|
2136
2137
|
{modelID: 'TS0601', manufacturerName: '_TZE200_68nvbio9'},
|
|
2137
2138
|
{modelID: 'TS0601', manufacturerName: '_TZE200_3ylew7b4'},
|
|
2138
2139
|
{modelID: 'TS0601', manufacturerName: '_TZE200_llm0epxg'},
|
|
@@ -2594,7 +2595,7 @@ module.exports = [
|
|
|
2594
2595
|
options: [exposes.options.measurement_poll_interval()],
|
|
2595
2596
|
// This device doesn't support reporting correctly.
|
|
2596
2597
|
// https://github.com/Koenkk/zigbee-herdsman-converters/pull/1270
|
|
2597
|
-
exposes: [e.switch(), e.power(), e.current(), e.voltage()
|
|
2598
|
+
exposes: [e.switch(), e.power(), e.current(), e.voltage(),
|
|
2598
2599
|
e.energy(), exposes.enum('power_outage_memory', ea.ALL, ['on', 'off', 'restore'])
|
|
2599
2600
|
.withDescription('Recover state after power outage'),
|
|
2600
2601
|
exposes.enum('indicator_mode', ea.ALL, ['off', 'off/on', 'on/off']).withDescription('LED indicator mode')],
|
|
@@ -3408,7 +3409,7 @@ module.exports = [
|
|
|
3408
3409
|
endpoint.saveClusterAttributeKeyValue('seMetering', {divisor: 100, multiplier: 1});
|
|
3409
3410
|
device.save();
|
|
3410
3411
|
},
|
|
3411
|
-
exposes: [e.switch(), e.power(), e.current(), e.voltage()
|
|
3412
|
+
exposes: [e.switch(), e.power(), e.current(), e.voltage(),
|
|
3412
3413
|
e.energy(), exposes.enum('power_outage_memory', ea.ALL, ['on', 'off', 'restore'])
|
|
3413
3414
|
.withDescription('Recover state after power outage'),
|
|
3414
3415
|
exposes.enum('indicator_mode', ea.STATE_SET, ['off', 'on_off', 'off_on'])
|
|
@@ -4114,4 +4115,31 @@ module.exports = [
|
|
|
4114
4115
|
],
|
|
4115
4116
|
},
|
|
4116
4117
|
},
|
|
4118
|
+
{
|
|
4119
|
+
fingerprint: tuya.fingerprint('TS0601', ['_TZE200_r32ctezx']),
|
|
4120
|
+
model: 'TS0601_fan_switch',
|
|
4121
|
+
vendor: 'TuYa',
|
|
4122
|
+
description: 'Fan switch',
|
|
4123
|
+
fromZigbee: [tuya.fz.datapoints],
|
|
4124
|
+
toZigbee: [tuya.tz.datapoints],
|
|
4125
|
+
configure: tuya.configureMagicPacket,
|
|
4126
|
+
exposes: [
|
|
4127
|
+
tuya.exposes.switch(), e.power_on_behavior(['off', 'on']).withAccess(ea.STATE_SET),
|
|
4128
|
+
tuya.exposes.countdown().withValueMin(0).withValueMax(43200).withUnit('s').withDescription('Max ON time in seconds'),
|
|
4129
|
+
exposes.numeric('fan_speed', ea.STATE_SET).withValueMin(1).withValueMax(5).withValueStep(1)
|
|
4130
|
+
.withDescription('Speed off the fan'),
|
|
4131
|
+
],
|
|
4132
|
+
meta: {
|
|
4133
|
+
tuyaDatapoints: [
|
|
4134
|
+
[1, 'state', tuya.valueConverter.onOff],
|
|
4135
|
+
[2, 'countdown', tuya.valueConverter.countdown],
|
|
4136
|
+
[3, 'fan_speed', tuya.valueConverterBasic
|
|
4137
|
+
.lookup({'1': tuya.enum(0), '2': tuya.enum(1), '3': tuya.enum(2), '4': tuya.enum(3), '5': tuya.enum(4)})],
|
|
4138
|
+
[11, 'power_on_behavior', tuya.valueConverterBasic.lookup({'off': tuya.enum(0), 'on': tuya.enum(1)})],
|
|
4139
|
+
],
|
|
4140
|
+
},
|
|
4141
|
+
whiteLabel: [
|
|
4142
|
+
{vendor: 'Lerlink', model: 'T2-Z67/T2-W67'},
|
|
4143
|
+
],
|
|
4144
|
+
},
|
|
4117
4145
|
];
|
package/devices/ubisys.js
CHANGED
|
@@ -903,7 +903,8 @@ module.exports = [
|
|
|
903
903
|
{min: 0, max: constants.repInterval.HOUR, change: 50});
|
|
904
904
|
await reporting.thermostatOccupiedHeatingSetpoint(endpoint,
|
|
905
905
|
{min: 0, max: constants.repInterval.HOUR, change: 50});
|
|
906
|
-
await reporting.thermostatPIHeatingDemand(endpoint
|
|
906
|
+
await reporting.thermostatPIHeatingDemand(endpoint,
|
|
907
|
+
{min: 15, max: constants.repInterval.HOUR, change: 1});
|
|
907
908
|
await reporting.thermostatOccupancy(endpoint);
|
|
908
909
|
await reporting.batteryPercentageRemaining(endpoint,
|
|
909
910
|
{min: constants.repInterval.HOUR, max: 43200, change: 1});
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
const exposes = require('../lib/exposes');
|
|
2
|
+
const fz = require('../converters/fromZigbee');
|
|
3
|
+
const tz = require('../converters/toZigbee');
|
|
4
|
+
const reporting = require('../lib/reporting');
|
|
5
|
+
const extend = require('../lib/extend');
|
|
6
|
+
const e = exposes.presets;
|
|
7
|
+
|
|
8
|
+
module.exports = [
|
|
9
|
+
{
|
|
10
|
+
fingerprint: [{modelID: 'HK-SL-DIM-A', softwareBuildID: '2.5.3_r52'}],
|
|
11
|
+
model: 'VES-ZB-DIM-004',
|
|
12
|
+
vendor: 'Vesternet',
|
|
13
|
+
description: 'Zigbee dimmer',
|
|
14
|
+
fromZigbee: extend.light_onoff_brightness().fromZigbee
|
|
15
|
+
.concat([fz.electrical_measurement, fz.metering, fz.ignore_genOta]),
|
|
16
|
+
toZigbee: extend.light_onoff_brightness().toZigbee.concat([tz.power_on_behavior]),
|
|
17
|
+
exposes: [e.light_brightness(), e.power(), e.voltage(), e.current(), e.energy(), e.power_on_behavior(['off', 'on', 'previous'])],
|
|
18
|
+
whiteLabel: [{vendor: 'Sunricher', model: 'SR-ZG9040A'}],
|
|
19
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
20
|
+
const endpoint = device.getEndpoint(1);
|
|
21
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl', 'haElectricalMeasurement', 'seMetering']);
|
|
22
|
+
await reporting.onOff(endpoint);
|
|
23
|
+
await reporting.brightness(endpoint);
|
|
24
|
+
await reporting.readEletricalMeasurementMultiplierDivisors(endpoint);
|
|
25
|
+
await reporting.activePower(endpoint);
|
|
26
|
+
await reporting.rmsCurrent(endpoint, {min: 10, change: 10});
|
|
27
|
+
await reporting.rmsVoltage(endpoint, {min: 10});
|
|
28
|
+
await reporting.readMeteringMultiplierDivisor(endpoint);
|
|
29
|
+
await reporting.currentSummDelivered(endpoint);
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
fingerprint: [{modelID: 'ON/OFF -M', softwareBuildID: '2.9.2_r54'}],
|
|
34
|
+
model: 'VES-ZB-HLD-017',
|
|
35
|
+
vendor: 'Vesternet',
|
|
36
|
+
description: 'Zigbee high load switch',
|
|
37
|
+
fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering, fz.power_on_behavior, fz.ignore_genOta],
|
|
38
|
+
toZigbee: [tz.on_off, tz.power_on_behavior],
|
|
39
|
+
exposes: [e.switch(), e.power(), e.current(), e.voltage(), e.energy(), e.power_on_behavior(['off', 'on', 'previous'])],
|
|
40
|
+
whiteLabel: [{vendor: 'Sunricher', model: 'SR-ZG9101SAC-HP-SWITCH-B'}],
|
|
41
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
42
|
+
const endpoint = device.getEndpoint(1);
|
|
43
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering']);
|
|
44
|
+
await reporting.onOff(endpoint);
|
|
45
|
+
await reporting.readEletricalMeasurementMultiplierDivisors(endpoint);
|
|
46
|
+
await reporting.activePower(endpoint);
|
|
47
|
+
await reporting.rmsCurrent(endpoint, {min: 10, change: 10});
|
|
48
|
+
await reporting.rmsVoltage(endpoint, {min: 10});
|
|
49
|
+
await reporting.readMeteringMultiplierDivisor(endpoint);
|
|
50
|
+
await reporting.currentSummDelivered(endpoint);
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
fingerprint: [{modelID: 'HK-ZCC-A', softwareBuildID: '2.5.3_r48'}],
|
|
55
|
+
model: 'VES-ZB-MOT-019',
|
|
56
|
+
vendor: 'Vesternet',
|
|
57
|
+
description: 'Zigbee motor controller',
|
|
58
|
+
fromZigbee: [fz.cover_position_tilt, fz.ignore_genOta],
|
|
59
|
+
toZigbee: [tz.cover_state, tz.cover_position_tilt],
|
|
60
|
+
exposes: [e.cover_position()],
|
|
61
|
+
whiteLabel: [{vendor: 'Sunricher', model: 'SR-ZG9080A'}],
|
|
62
|
+
meta: {coverInverted: true},
|
|
63
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
64
|
+
const endpoint = device.getEndpoint(1);
|
|
65
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['closuresWindowCovering']);
|
|
66
|
+
await reporting.currentPositionLiftPercentage(endpoint);
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
fingerprint: [{modelID: 'ZGRC-KEY-013', softwareBuildID: '2.5.3_r20'}],
|
|
71
|
+
model: 'VES-ZB-REM-013',
|
|
72
|
+
vendor: 'Vesternet',
|
|
73
|
+
description: 'Zigbee remote control - 12 button',
|
|
74
|
+
fromZigbee: [fz.command_on, fz.command_off, fz.command_move, fz.command_stop, fz.command_recall, fz.battery, fz.ignore_genOta],
|
|
75
|
+
exposes: [e.battery(),
|
|
76
|
+
e.action(['on_*', 'off_*', 'stop_*', 'brightness_move_up_*', 'brightness_move_down_*', 'brightness_stop_*', 'recall_*'])],
|
|
77
|
+
toZigbee: [],
|
|
78
|
+
meta: {multiEndpoint: true, battery: {dontDividePercentage: true}, publishDuplicateTransaction: true},
|
|
79
|
+
whiteLabel: [{vendor: 'Sunricher', model: 'SR-ZG9001K12-DIM-Z4'}],
|
|
80
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
81
|
+
await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl', 'genScenes', 'genPowerCfg']);
|
|
82
|
+
await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl', 'genScenes']);
|
|
83
|
+
await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl', 'genScenes']);
|
|
84
|
+
await reporting.bind(device.getEndpoint(4), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl', 'genScenes']);
|
|
85
|
+
await reporting.batteryPercentageRemaining(device.getEndpoint(1));
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
fingerprint: [{modelID: 'HK-SL-RELAY-A', softwareBuildID: '2.5.3_r47'}],
|
|
90
|
+
model: 'VES-ZB-SWI-005',
|
|
91
|
+
vendor: 'Vesternet',
|
|
92
|
+
description: 'Zigbee switch',
|
|
93
|
+
fromZigbee: [fz.on_off, fz.power_on_behavior, fz.ignore_genOta],
|
|
94
|
+
toZigbee: [tz.on_off, tz.power_on_behavior],
|
|
95
|
+
exposes: [e.switch(), e.power_on_behavior(['off', 'on', 'previous'])],
|
|
96
|
+
whiteLabel: [{vendor: 'Sunricher', model: 'SR-ZG9100A-S'}],
|
|
97
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
98
|
+
const endpoint = device.getEndpoint(1);
|
|
99
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
|
|
100
|
+
await reporting.onOff(endpoint);
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
fingerprint: [{modelID: 'ON/OFF(2CH)', softwareBuildID: '2.5.3_r2'}],
|
|
105
|
+
model: 'VES-ZB-SWI-015',
|
|
106
|
+
vendor: 'Vesternet',
|
|
107
|
+
description: 'Zigbee 2 channel switch',
|
|
108
|
+
fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering, fz.power_on_behavior, fz.ignore_genOta],
|
|
109
|
+
toZigbee: [tz.on_off, tz.power_on_behavior],
|
|
110
|
+
exposes: [e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'), e.power(), e.current(),
|
|
111
|
+
e.voltage(), e.energy(), e.power_on_behavior(['off', 'on', 'previous'])],
|
|
112
|
+
whiteLabel: [{vendor: 'Sunricher', model: 'SR-ZG9101SAC-HP-SWITCH-2CH'}],
|
|
113
|
+
endpoint: (device) => {
|
|
114
|
+
return {'l1': 1, 'l2': 2};
|
|
115
|
+
},
|
|
116
|
+
meta: {multiEndpoint: true},
|
|
117
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
118
|
+
const endpoint1 = device.getEndpoint(1);
|
|
119
|
+
const endpoint2 = device.getEndpoint(2);
|
|
120
|
+
await reporting.bind(endpoint1, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering']);
|
|
121
|
+
await reporting.bind(endpoint2, coordinatorEndpoint, ['genOnOff']);
|
|
122
|
+
await reporting.onOff(endpoint1);
|
|
123
|
+
await reporting.onOff(endpoint2);
|
|
124
|
+
await reporting.readEletricalMeasurementMultiplierDivisors(endpoint1);
|
|
125
|
+
await reporting.activePower(endpoint1);
|
|
126
|
+
await reporting.rmsCurrent(endpoint1, {min: 10, change: 10});
|
|
127
|
+
await reporting.rmsVoltage(endpoint1, {min: 10});
|
|
128
|
+
await reporting.readMeteringMultiplierDivisor(endpoint1);
|
|
129
|
+
await reporting.currentSummDelivered(endpoint1);
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
fingerprint: [{modelID: 'ZG2833K2_EU07', softwareBuildID: '2.5.3_r20'}],
|
|
134
|
+
model: 'VES-ZB-WAL-006',
|
|
135
|
+
vendor: 'Vesternet',
|
|
136
|
+
description: 'Zigbee wall controller - 2 button',
|
|
137
|
+
fromZigbee: [fz.command_on, fz.command_off, fz.command_move, fz.command_stop, fz.battery, fz.ignore_genOta],
|
|
138
|
+
exposes: [e.battery(), e.action([
|
|
139
|
+
'on_1', 'off_1', 'stop_1', 'brightness_move_up_1', 'brightness_move_down_1', 'brightness_stop_1'])],
|
|
140
|
+
toZigbee: [],
|
|
141
|
+
meta: {multiEndpoint: true, battery: {dontDividePercentage: true}},
|
|
142
|
+
whiteLabel: [{vendor: 'Sunricher', model: 'SR-ZG9001K2-DIM2'}],
|
|
143
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
144
|
+
await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl', 'genPowerCfg']);
|
|
145
|
+
await reporting.batteryPercentageRemaining(device.getEndpoint(1));
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
fingerprint: [{modelID: 'ZG2833K4_EU06', softwareBuildID: '2.5.3_r20'}],
|
|
150
|
+
model: 'VES-ZB-WAL-011',
|
|
151
|
+
vendor: 'Vesternet',
|
|
152
|
+
description: 'Zigbee wall controller - 4 button',
|
|
153
|
+
fromZigbee: [fz.command_on, fz.command_off, fz.command_move, fz.command_stop, fz.battery, fz.ignore_genOta],
|
|
154
|
+
exposes: [e.battery(), e.action([
|
|
155
|
+
'on_1', 'off_1', 'stop_1', 'brightness_move_up_1', 'brightness_move_down_1', 'brightness_stop_1',
|
|
156
|
+
'on_2', 'off_2', 'stop_2', 'brightness_move_up_2', 'brightness_move_down_2', 'brightness_stop_2'])],
|
|
157
|
+
toZigbee: [],
|
|
158
|
+
meta: {multiEndpoint: true, battery: {dontDividePercentage: true}},
|
|
159
|
+
whiteLabel: [{vendor: 'Sunricher', model: 'SR-ZG9001K4-DIM2'}],
|
|
160
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
161
|
+
await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl', 'genPowerCfg']);
|
|
162
|
+
await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
|
|
163
|
+
await reporting.batteryPercentageRemaining(device.getEndpoint(1));
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
fingerprint: [{modelID: 'ZG2833K8_EU05', softwareBuildID: '2.5.3_r20'}],
|
|
168
|
+
model: 'VES-ZB-WAL-012',
|
|
169
|
+
vendor: 'Vesternet',
|
|
170
|
+
description: 'Zigbee wall controller - 8 button',
|
|
171
|
+
fromZigbee: [fz.command_on, fz.command_off, fz.command_move, fz.command_stop, fz.battery, fz.ignore_genOta],
|
|
172
|
+
exposes: [e.battery(), e.action([
|
|
173
|
+
'on_1', 'off_1', 'stop_1', 'brightness_move_up_1', 'brightness_move_down_1', 'brightness_stop_1',
|
|
174
|
+
'on_2', 'off_2', 'stop_2', 'brightness_move_up_2', 'brightness_move_down_2', 'brightness_stop_2',
|
|
175
|
+
'on_3', 'off_3', 'stop_3', 'brightness_move_up_3', 'brightness_move_down_3', 'brightness_stop_3',
|
|
176
|
+
'on_4', 'off_4', 'stop_4', 'brightness_move_up_4', 'brightness_move_down_4', 'brightness_stop_4'])],
|
|
177
|
+
toZigbee: [],
|
|
178
|
+
meta: {multiEndpoint: true, battery: {dontDividePercentage: true}},
|
|
179
|
+
whiteLabel: [{vendor: 'Sunricher', model: 'SR-ZG9001K8-DIM'}],
|
|
180
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
181
|
+
await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl', 'genPowerCfg']);
|
|
182
|
+
await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
|
|
183
|
+
await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
|
|
184
|
+
await reporting.bind(device.getEndpoint(4), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
|
|
185
|
+
await reporting.batteryPercentageRemaining(device.getEndpoint(1));
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
];
|
package/devices/xiaomi.js
CHANGED
|
@@ -68,7 +68,7 @@ const fzLocal = {
|
|
|
68
68
|
},
|
|
69
69
|
},
|
|
70
70
|
aqara_s1_pm25: {
|
|
71
|
-
cluster: '
|
|
71
|
+
cluster: 'pm25Measurement',
|
|
72
72
|
type: ['attributeReport', 'readResponse'],
|
|
73
73
|
convert: (model, msg, publish, options, meta) => {
|
|
74
74
|
if (msg.data['measuredValue']) {
|
|
@@ -1490,7 +1490,7 @@ module.exports = [
|
|
|
1490
1490
|
exposes: [
|
|
1491
1491
|
e.switch(), e.power().withAccess(ea.STATE_GET),
|
|
1492
1492
|
e.energy(), e.device_temperature().withAccess(ea.STATE),
|
|
1493
|
-
e.voltage()
|
|
1493
|
+
e.voltage(), e.action(['single', 'release']),
|
|
1494
1494
|
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1495
1495
|
.withDescription('Decoupled mode'),
|
|
1496
1496
|
],
|
|
@@ -1539,7 +1539,7 @@ module.exports = [
|
|
|
1539
1539
|
tz.xiaomi_led_disabled_night, tz.xiaomi_flip_indicator_light],
|
|
1540
1540
|
exposes: [
|
|
1541
1541
|
e.switch(), e.action(['single', 'double']), e.power().withAccess(ea.STATE), e.energy(),
|
|
1542
|
-
e.voltage()
|
|
1542
|
+
e.voltage(), e.device_temperature().withAccess(ea.STATE),
|
|
1543
1543
|
e.power_outage_memory(), e.led_disabled_night(), e.flip_indicator_light(),
|
|
1544
1544
|
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1545
1545
|
.withDescription('Decoupled mode for left button'),
|
|
@@ -1561,7 +1561,7 @@ module.exports = [
|
|
|
1561
1561
|
},
|
|
1562
1562
|
exposes: [
|
|
1563
1563
|
e.switch().withEndpoint('left'), e.switch().withEndpoint('right'),
|
|
1564
|
-
e.power().withAccess(ea.STATE), e.energy(), e.voltage()
|
|
1564
|
+
e.power().withAccess(ea.STATE), e.energy(), e.voltage(), e.flip_indicator_light(),
|
|
1565
1565
|
e.power_outage_memory(), e.led_disabled_night(), e.device_temperature().withAccess(ea.STATE),
|
|
1566
1566
|
e.action([
|
|
1567
1567
|
'single_left', 'double_left', 'single_right', 'double_right', 'single_both', 'double_both']),
|
|
@@ -1589,7 +1589,7 @@ module.exports = [
|
|
|
1589
1589
|
},
|
|
1590
1590
|
exposes: [
|
|
1591
1591
|
e.switch().withEndpoint('left'), e.switch().withEndpoint('center'), e.switch().withEndpoint('right'),
|
|
1592
|
-
e.power().withAccess(ea.STATE), e.energy(), e.voltage()
|
|
1592
|
+
e.power().withAccess(ea.STATE), e.energy(), e.voltage(), e.flip_indicator_light(),
|
|
1593
1593
|
e.power_outage_memory(), e.led_disabled_night(), e.device_temperature().withAccess(ea.STATE),
|
|
1594
1594
|
e.action([
|
|
1595
1595
|
'single_left', 'double_left', 'single_center', 'double_center',
|
|
@@ -1908,7 +1908,7 @@ module.exports = [
|
|
|
1908
1908
|
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.xiaomi_basic, fz.ignore_occupancy_report, fz.ignore_illuminance_report],
|
|
1909
1909
|
toZigbee: [tz.on_off, tz.xiaomi_power],
|
|
1910
1910
|
exposes: [e.switch(), e.power().withAccess(ea.STATE_GET), e.energy(), e.device_temperature().withAccess(ea.STATE),
|
|
1911
|
-
e.voltage()
|
|
1911
|
+
e.voltage()],
|
|
1912
1912
|
},
|
|
1913
1913
|
{
|
|
1914
1914
|
zigbeeModel: ['lumi.plug.mmeu01'],
|
|
@@ -1921,7 +1921,7 @@ module.exports = [
|
|
|
1921
1921
|
tz.xiaomi_overload_protection],
|
|
1922
1922
|
exposes: [
|
|
1923
1923
|
e.switch(), e.power().withAccess(ea.STATE_GET), e.energy(), e.device_temperature().withAccess(ea.STATE),
|
|
1924
|
-
e.voltage()
|
|
1924
|
+
e.voltage(), e.current(), e.consumer_connected(), e.led_disabled_night(),
|
|
1925
1925
|
e.power_outage_memory(), exposes.binary('auto_off', ea.STATE_SET, true, false)
|
|
1926
1926
|
.withDescription('Turn the device automatically off when attached device consumes less than 2W for 20 minutes'),
|
|
1927
1927
|
exposes.numeric('overload_protection', exposes.access.ALL).withValueMin(100).withValueMax(2300).withUnit('W')
|
|
@@ -1938,7 +1938,7 @@ module.exports = [
|
|
|
1938
1938
|
tz.xiaomi_overload_protection],
|
|
1939
1939
|
exposes: [
|
|
1940
1940
|
e.switch(), e.power().withAccess(ea.STATE_GET), e.energy(), e.device_temperature().withAccess(ea.STATE),
|
|
1941
|
-
e.voltage()
|
|
1941
|
+
e.voltage(), e.current(), e.consumer_connected(), e.led_disabled_night(),
|
|
1942
1942
|
e.power_outage_memory(), exposes.binary('auto_off', ea.STATE_SET, true, false)
|
|
1943
1943
|
.withDescription('Turn the device automatically off when attached device consumes less than 2W for 20 minutes'),
|
|
1944
1944
|
exposes.numeric('overload_protection', exposes.access.ALL).withValueMin(100).withValueMax(2300).withUnit('W')
|
|
@@ -2002,7 +2002,7 @@ module.exports = [
|
|
|
2002
2002
|
}
|
|
2003
2003
|
},
|
|
2004
2004
|
exposes: [e.switch(), e.power(), e.energy(), e.power_outage_memory(),
|
|
2005
|
-
e.voltage()
|
|
2005
|
+
e.voltage(), e.current(),
|
|
2006
2006
|
e.device_temperature().withDescription('Device temperature (polled every 30 min)')],
|
|
2007
2007
|
ota: ota.zigbeeOTA,
|
|
2008
2008
|
},
|
|
@@ -2014,7 +2014,7 @@ module.exports = [
|
|
|
2014
2014
|
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.ignore_occupancy_report, fz.xiaomi_basic],
|
|
2015
2015
|
toZigbee: [tz.on_off, tz.xiaomi_power, tz.xiaomi_led_disabled_night,
|
|
2016
2016
|
tz.xiaomi_switch_power_outage_memory, tz.xiaomi_auto_off],
|
|
2017
|
-
exposes: [e.switch(), e.power().withAccess(ea.STATE_GET), e.energy(), e.device_temperature(), e.voltage()
|
|
2017
|
+
exposes: [e.switch(), e.power().withAccess(ea.STATE_GET), e.energy(), e.device_temperature(), e.voltage(),
|
|
2018
2018
|
e.power_outage_memory(), e.led_disabled_night(),
|
|
2019
2019
|
exposes.binary('auto_off', ea.STATE_SET, true, false)
|
|
2020
2020
|
.withDescription('If the power is constantly lower than 2W within half an hour, ' +
|
|
@@ -2041,7 +2041,7 @@ module.exports = [
|
|
|
2041
2041
|
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.xiaomi_basic],
|
|
2042
2042
|
toZigbee: [tz.on_off, tz.xiaomi_switch_power_outage_memory, tz.xiaomi_power],
|
|
2043
2043
|
exposes: [e.switch(), e.power().withAccess(ea.STATE_GET), e.energy(), e.device_temperature().withAccess(ea.STATE),
|
|
2044
|
-
e.voltage()
|
|
2044
|
+
e.voltage(), e.power_outage_memory()],
|
|
2045
2045
|
ota: ota.zigbeeOTA,
|
|
2046
2046
|
},
|
|
2047
2047
|
{
|
|
@@ -2576,7 +2576,7 @@ module.exports = [
|
|
|
2576
2576
|
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.aqara_opple],
|
|
2577
2577
|
toZigbee: [tz.on_off, tz.xiaomi_power, tz.xiaomi_switch_type, tz.xiaomi_switch_power_outage_memory, tz.xiaomi_led_disabled_night],
|
|
2578
2578
|
exposes: [e.switch(), e.power().withAccess(ea.STATE_GET), e.energy(), e.device_temperature().withAccess(ea.STATE),
|
|
2579
|
-
e.voltage()
|
|
2579
|
+
e.voltage(), e.power_outage_memory(), e.led_disabled_night(), e.switch_type()],
|
|
2580
2580
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2581
2581
|
await device.getEndpoint(1).write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
2582
2582
|
device.powerSource = 'Mains (single phase)';
|
|
@@ -2822,7 +2822,7 @@ module.exports = [
|
|
|
2822
2822
|
toZigbee: [tz.on_off, tz.xiaomi_switch_power_outage_memory, tz.xiaomi_led_disabled_night,
|
|
2823
2823
|
tz.xiaomi_overload_protection, tz.xiaomi_socket_button_lock],
|
|
2824
2824
|
exposes: [e.switch(), e.power().withAccess(ea.STATE), e.energy(), e.device_temperature().withAccess(ea.STATE),
|
|
2825
|
-
e.voltage()
|
|
2825
|
+
e.voltage(), e.current(), e.consumer_connected().withAccess(ea.STATE),
|
|
2826
2826
|
e.power_outage_memory(), e.led_disabled_night(), e.button_lock(),
|
|
2827
2827
|
exposes.numeric('overload_protection', exposes.access.ALL).withValueMin(100).withValueMax(2500).withUnit('W')
|
|
2828
2828
|
.withDescription('Maximum allowed load, turns off if exceeded')],
|
|
@@ -2891,7 +2891,7 @@ module.exports = [
|
|
|
2891
2891
|
},
|
|
2892
2892
|
exposes: [
|
|
2893
2893
|
e.switch().withEndpoint('relay'), e.switch().withEndpoint('usb'),
|
|
2894
|
-
e.power().withAccess(ea.STATE), e.energy(), e.device_temperature().withAccess(ea.STATE), e.voltage()
|
|
2894
|
+
e.power().withAccess(ea.STATE), e.energy(), e.device_temperature().withAccess(ea.STATE), e.voltage(),
|
|
2895
2895
|
e.current(), e.power_outage_memory(), e.led_disabled_night(), e.button_lock(),
|
|
2896
2896
|
exposes.enum('button_switch_mode', exposes.access.ALL, ['relay', 'relay_and_usb'])
|
|
2897
2897
|
.withDescription('Control both relay and usb or only the relay with the physical switch button'),
|
|
@@ -2919,7 +2919,7 @@ module.exports = [
|
|
|
2919
2919
|
tz.xiaomi_overload_protection, tz.xiaomi_socket_button_lock],
|
|
2920
2920
|
exposes: [
|
|
2921
2921
|
e.switch(), e.power().withAccess(ea.STATE), e.energy(),
|
|
2922
|
-
e.device_temperature().withAccess(ea.STATE), e.voltage()
|
|
2922
|
+
e.device_temperature().withAccess(ea.STATE), e.voltage(),
|
|
2923
2923
|
e.current(), e.power_outage_memory(), e.led_disabled_night(), e.button_lock(),
|
|
2924
2924
|
exposes.numeric('overload_protection', exposes.access.ALL).withValueMin(100).withValueMax(2500).withUnit('W')
|
|
2925
2925
|
.withDescription('Maximum allowed load, turns off if exceeded')],
|
package/lib/constants.js
CHANGED
|
@@ -210,10 +210,16 @@ const armNotification = {
|
|
|
210
210
|
|
|
211
211
|
// ID's from ZCL mapped to ha names where appropriate
|
|
212
212
|
// https://github.com/home-assistant/core/pull/47720
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
213
|
+
const ColorMode = {
|
|
214
|
+
HS: 0,
|
|
215
|
+
XY: 1,
|
|
216
|
+
ColorTemp: 2,
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
const colorModeLookup = {
|
|
220
|
+
[ColorMode.HS]: 'hs',
|
|
221
|
+
[ColorMode.XY]: 'xy',
|
|
222
|
+
[ColorMode.ColorTemp]: 'color_temp',
|
|
217
223
|
};
|
|
218
224
|
|
|
219
225
|
const lockSoundVolume = ['silent_mode', 'low_volume', 'high_volume'];
|
|
@@ -294,7 +300,8 @@ module.exports = {
|
|
|
294
300
|
lockSourceName,
|
|
295
301
|
armMode,
|
|
296
302
|
armNotification,
|
|
297
|
-
|
|
303
|
+
colorModeLookup,
|
|
304
|
+
ColorMode,
|
|
298
305
|
lockSoundVolume,
|
|
299
306
|
lockUserStatus,
|
|
300
307
|
easyCodeTouchActions,
|
package/lib/tuya.js
CHANGED
|
@@ -1615,7 +1615,7 @@ const tuyaTz = {
|
|
|
1615
1615
|
'week_schedule_programming', 'online', 'holiday_mode_date', 'schedule', 'schedule_monday', 'schedule_tuesday',
|
|
1616
1616
|
'schedule_wednesday', 'schedule_thursday', 'schedule_friday', 'schedule_saturday', 'schedule_sunday', 'clear_fault',
|
|
1617
1617
|
'scale_protection', 'error', 'radar_scene', 'radar_sensitivity', 'tumble_alarm_time', 'tumble_switch', 'fall_sensitivity',
|
|
1618
|
-
'min_temperature', 'max_temperature', 'window_detection', 'boost_heating', 'alarm_ringtone', 'alarm_time',
|
|
1618
|
+
'min_temperature', 'max_temperature', 'window_detection', 'boost_heating', 'alarm_ringtone', 'alarm_time', 'fan_speed',
|
|
1619
1619
|
],
|
|
1620
1620
|
convertSet: async (entity, key, value, meta) => {
|
|
1621
1621
|
// A set converter is only called once; therefore we need to loop
|
|
@@ -1868,7 +1868,7 @@ const tuyaExtend = {
|
|
|
1868
1868
|
|
|
1869
1869
|
if (options.electricalMeasurements) {
|
|
1870
1870
|
fromZigbee.push(fz.electrical_measurement, fz.metering);
|
|
1871
|
-
exposes.push(e.power(), e.current(), e.voltage()
|
|
1871
|
+
exposes.push(e.power(), e.current(), e.voltage(), e.energy());
|
|
1872
1872
|
}
|
|
1873
1873
|
if (options.childLock) {
|
|
1874
1874
|
fromZigbee.push(tuyaFz.child_lock);
|