zigbee-herdsman-converters 15.0.98 → 15.0.100
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/devices/develco.js +26 -1
- package/devices/lidl.js +0 -114
- package/devices/niko.js +20 -2
- package/devices/sinope.js +20 -12
- package/devices/tuya.js +310 -4
- package/lib/tuya.js +7 -0
- package/package.json +3 -3
package/devices/develco.js
CHANGED
|
@@ -292,7 +292,7 @@ module.exports = [
|
|
|
292
292
|
description: 'Power plug',
|
|
293
293
|
fromZigbee: [fz.on_off, develco.fz.electrical_measurement, develco.fz.metering],
|
|
294
294
|
toZigbee: [tz.on_off],
|
|
295
|
-
exposes: [e.switch(), e.power(), e.current(), e.voltage(), e.energy()],
|
|
295
|
+
exposes: [e.switch(), e.power(), e.current(), e.voltage(), e.energy(), e.ac_frequency()],
|
|
296
296
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
297
297
|
const endpoint = device.getEndpoint(2);
|
|
298
298
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering']);
|
|
@@ -303,6 +303,7 @@ module.exports = [
|
|
|
303
303
|
await reporting.rmsVoltage(endpoint);
|
|
304
304
|
await reporting.readMeteringMultiplierDivisor(endpoint);
|
|
305
305
|
await reporting.currentSummDelivered(endpoint);
|
|
306
|
+
await reporting.acFrequency(endpoint);
|
|
306
307
|
},
|
|
307
308
|
endpoint: (device) => {
|
|
308
309
|
return {default: 2};
|
|
@@ -361,6 +362,30 @@ module.exports = [
|
|
|
361
362
|
return {default: 2};
|
|
362
363
|
},
|
|
363
364
|
},
|
|
365
|
+
{
|
|
366
|
+
zigbeeModel: ['SPLZB-137'],
|
|
367
|
+
model: 'SPLZB-137',
|
|
368
|
+
vendor: 'Develco',
|
|
369
|
+
description: 'Power plug',
|
|
370
|
+
fromZigbee: [fz.on_off, develco.fz.electrical_measurement, develco.fz.metering],
|
|
371
|
+
toZigbee: [tz.on_off],
|
|
372
|
+
exposes: [e.switch(), e.power(), e.current(), e.voltage(), e.energy(), e.ac_frequency()],
|
|
373
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
374
|
+
const endpoint = device.getEndpoint(2);
|
|
375
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering']);
|
|
376
|
+
await reporting.onOff(endpoint);
|
|
377
|
+
await reporting.readEletricalMeasurementMultiplierDivisors(endpoint, true);
|
|
378
|
+
await reporting.activePower(endpoint);
|
|
379
|
+
await reporting.rmsCurrent(endpoint);
|
|
380
|
+
await reporting.rmsVoltage(endpoint);
|
|
381
|
+
await reporting.readMeteringMultiplierDivisor(endpoint);
|
|
382
|
+
await reporting.currentSummDelivered(endpoint);
|
|
383
|
+
await reporting.acFrequency(endpoint);
|
|
384
|
+
},
|
|
385
|
+
endpoint: (device) => {
|
|
386
|
+
return {default: 2};
|
|
387
|
+
},
|
|
388
|
+
},
|
|
364
389
|
{
|
|
365
390
|
zigbeeModel: ['SMRZB-143'],
|
|
366
391
|
model: 'SMRZB-143',
|
package/devices/lidl.js
CHANGED
|
@@ -7,9 +7,6 @@ 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, colorModeLookup} = require('../lib/constants');
|
|
12
|
-
const libColor = require('../lib/color');
|
|
13
10
|
|
|
14
11
|
const tuyaLocal = {
|
|
15
12
|
dataPoints: {
|
|
@@ -145,105 +142,6 @@ const fzLocal = {
|
|
|
145
142
|
},
|
|
146
143
|
};
|
|
147
144
|
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 ?? colorModeLookup[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 = colorModeLookup[ColorMode.ColorTemp];
|
|
160
|
-
if ('color' in meta.message) colorMode = colorModeLookup[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 == colorModeLookup[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 == colorModeLookup[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 == colorModeLookup[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 ?? {}).hue ?? 0, // red
|
|
197
|
-
saturation: (meta.state.color ?? {}).saturation ?? 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
|
-
hue: color.hue,
|
|
221
|
-
saturation: 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
|
-
// If we're in white mode, calculate a matching display color for the set color temperature. This also kind
|
|
238
|
-
// of works in the other direction.
|
|
239
|
-
Object.assign(newState, libColor.syncColorState(newState, meta.state, entity, meta.options, meta.logger));
|
|
240
|
-
|
|
241
|
-
return {state: newState};
|
|
242
|
-
},
|
|
243
|
-
convertGet: async (entity, key, meta) => {
|
|
244
|
-
await entity.read('lightingColorCtrl', ['currentHue', 'currentSaturation', 'currentLevel', 'tuyaRgbMode', 'colorTemperature']);
|
|
245
|
-
},
|
|
246
|
-
},
|
|
247
145
|
zs_thermostat_child_lock: {
|
|
248
146
|
key: ['child_lock'],
|
|
249
147
|
convertSet: async (entity, key, value, meta) => {
|
|
@@ -626,18 +524,6 @@ module.exports = [
|
|
|
626
524
|
device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
|
|
627
525
|
},
|
|
628
526
|
},
|
|
629
|
-
{
|
|
630
|
-
fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3210_iystcadi'}],
|
|
631
|
-
model: '14149505L/14149506L_2',
|
|
632
|
-
vendor: 'Lidl',
|
|
633
|
-
description: 'Livarno Lux light bar RGB+CCT (black/white)',
|
|
634
|
-
toZigbee: [tz.on_off, tzLocal.led_control],
|
|
635
|
-
fromZigbee: [fz.on_off, fz.tuya_led_controller, fz.brightness, fz.ignore_basic_report],
|
|
636
|
-
exposes: [e.light_brightness_colortemp_colorhs([153, 500]).removeFeature('color_temp_startup')],
|
|
637
|
-
configure: async (device, coordinatorEndpoint, logger) => {
|
|
638
|
-
device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
|
|
639
|
-
},
|
|
640
|
-
},
|
|
641
527
|
{
|
|
642
528
|
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_htnnfasr'}],
|
|
643
529
|
model: 'PSBZS A1',
|
package/devices/niko.js
CHANGED
|
@@ -34,14 +34,27 @@ const local = {
|
|
|
34
34
|
64: 'single',
|
|
35
35
|
32: 'hold',
|
|
36
36
|
48: 'release',
|
|
37
|
+
256: null,
|
|
38
|
+
1024: 'single_ext',
|
|
39
|
+
512: 'hold_ext',
|
|
40
|
+
768: 'release_ext',
|
|
37
41
|
} : {
|
|
38
42
|
16: null,
|
|
39
43
|
64: 'single_left',
|
|
40
44
|
32: 'hold_left',
|
|
41
45
|
48: 'release_left',
|
|
42
|
-
|
|
46
|
+
256: null,
|
|
47
|
+
1024: 'single_left_ext',
|
|
48
|
+
512: 'hold_left_ext',
|
|
49
|
+
768: 'release_left_ext',
|
|
50
|
+
4096: null,
|
|
51
|
+
16384: 'single_right',
|
|
43
52
|
8192: 'hold_right',
|
|
44
53
|
12288: 'release_right',
|
|
54
|
+
65536: null,
|
|
55
|
+
262144: 'single_right_ext',
|
|
56
|
+
131072: 'hold_right_ext',
|
|
57
|
+
196608: 'release_right_ext',
|
|
45
58
|
};
|
|
46
59
|
|
|
47
60
|
state['action'] = actionMap[msg.data.switchAction];
|
|
@@ -262,7 +275,10 @@ module.exports = [
|
|
|
262
275
|
},
|
|
263
276
|
exposes: [
|
|
264
277
|
e.switch(),
|
|
265
|
-
e.action([
|
|
278
|
+
e.action([
|
|
279
|
+
'single', 'hold', 'release',
|
|
280
|
+
'single_ext', 'hold_ext', 'release_ext',
|
|
281
|
+
]),
|
|
266
282
|
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled']),
|
|
267
283
|
exposes.binary('led_enable', ea.ALL, true, false).withDescription('Enable LED'),
|
|
268
284
|
exposes.binary('led_state', ea.ALL, 'ON', 'OFF').withDescription('LED State'),
|
|
@@ -293,7 +309,9 @@ module.exports = [
|
|
|
293
309
|
e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'),
|
|
294
310
|
e.action([
|
|
295
311
|
'single_left', 'hold_left', 'release_left',
|
|
312
|
+
'single_left_ext', 'hold_left_ext', 'release_left_ext',
|
|
296
313
|
'single_right', 'hold_right', 'release_right',
|
|
314
|
+
'single_right_ext', 'hold_right_ext', 'release_right_ext',
|
|
297
315
|
]),
|
|
298
316
|
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled']),
|
|
299
317
|
exposes.binary('led_enable', ea.ALL, true, false).withEndpoint('l1').withDescription('Enable LED'),
|
package/devices/sinope.js
CHANGED
|
@@ -370,7 +370,7 @@ const tzLocal = {
|
|
|
370
370
|
},
|
|
371
371
|
},
|
|
372
372
|
connected_load: {
|
|
373
|
-
// TH1400ZB
|
|
373
|
+
// TH1400ZB and SW2500ZB
|
|
374
374
|
key: ['connected_load'],
|
|
375
375
|
convertSet: async (entity, key, value, meta) => {
|
|
376
376
|
await entity.write('manuSpecificSinope', {connectedLoad: value});
|
|
@@ -413,7 +413,7 @@ const tzLocal = {
|
|
|
413
413
|
if (value >= 0 && value <= 100) {
|
|
414
414
|
await entity.write('manuSpecificSinope', {ledIntensityOn: value});
|
|
415
415
|
}
|
|
416
|
-
return {
|
|
416
|
+
return {state: {led_intensity_on: value}};
|
|
417
417
|
},
|
|
418
418
|
convertGet: async (entity, key, meta) => {
|
|
419
419
|
await entity.read('manuSpecificSinope', ['ledIntensityOn']);
|
|
@@ -426,7 +426,7 @@ const tzLocal = {
|
|
|
426
426
|
if (value >= 0 && value <= 100) {
|
|
427
427
|
await entity.write('manuSpecificSinope', {ledIntensityOff: value});
|
|
428
428
|
}
|
|
429
|
-
return {
|
|
429
|
+
return {state: {led_intensity_off: value}};
|
|
430
430
|
},
|
|
431
431
|
convertGet: async (entity, key, meta) => {
|
|
432
432
|
await entity.read('manuSpecificSinope', ['ledIntensityOff']);
|
|
@@ -476,13 +476,13 @@ const tzLocal = {
|
|
|
476
476
|
if (value >= 0 && value <= 10800) {
|
|
477
477
|
await entity.write('manuSpecificSinope', {dimmerTimmer: value});
|
|
478
478
|
}
|
|
479
|
-
return {
|
|
479
|
+
return {state: {timer_seconds: value}};
|
|
480
480
|
},
|
|
481
481
|
convertGet: async (entity, key, meta) => {
|
|
482
482
|
await entity.read('manuSpecificSinope', ['dimmerTimmer']);
|
|
483
483
|
},
|
|
484
484
|
},
|
|
485
|
-
|
|
485
|
+
keypad_lockout: {
|
|
486
486
|
// SW2500ZB
|
|
487
487
|
key: ['keypad_lockout'],
|
|
488
488
|
convertSet: async (entity, key, value, meta) => {
|
|
@@ -991,16 +991,16 @@ module.exports = [
|
|
|
991
991
|
model: 'SW2500ZB',
|
|
992
992
|
vendor: 'Sinopé',
|
|
993
993
|
description: 'Zigbee smart light switch',
|
|
994
|
-
fromZigbee: [fz.on_off,
|
|
994
|
+
fromZigbee: [fz.on_off, fzLocal.sinope, fz.metering],
|
|
995
995
|
toZigbee: [tz.on_off, tzLocal.timer_seconds, tzLocal.led_intensity_on, tzLocal.led_intensity_off,
|
|
996
|
-
tzLocal.led_color_on, tzLocal.led_color_off, tzLocal.
|
|
996
|
+
tzLocal.led_color_on, tzLocal.led_color_off, tzLocal.keypad_lockout, tzLocal.connected_load],
|
|
997
997
|
exposes: [e.switch(),
|
|
998
998
|
e.action(['up_single', 'up_double', 'up_hold', 'down_single', 'down_double', 'down_hold']),
|
|
999
|
-
exposes.numeric('timer_seconds', ea.ALL).withValueMin(0).withValueMax(10800)
|
|
999
|
+
exposes.numeric('timer_seconds', ea.ALL).withUnit('seconds').withValueMin(0).withValueMax(10800)
|
|
1000
1000
|
.withDescription('Automatically turn off load after x seconds'),
|
|
1001
|
-
exposes.numeric('led_intensity_on', ea.ALL).withValueMin(0).withValueMax(100)
|
|
1001
|
+
exposes.numeric('led_intensity_on', ea.ALL).withUnit('%').withValueMin(0).withValueMax(100)
|
|
1002
1002
|
.withDescription('Control status LED intensity when load ON'),
|
|
1003
|
-
exposes.numeric('led_intensity_off', ea.ALL).withValueMin(0).withValueMax(100)
|
|
1003
|
+
exposes.numeric('led_intensity_off', ea.ALL).withUnit('%').withValueMin(0).withValueMax(100)
|
|
1004
1004
|
.withDescription('Control status LED intensity when load OFF'),
|
|
1005
1005
|
exposes.composite('led_color_on', 'led_color_on', ea.SET)
|
|
1006
1006
|
.withFeature(exposes.numeric('r', ea.SET))
|
|
@@ -1013,12 +1013,20 @@ module.exports = [
|
|
|
1013
1013
|
.withFeature(exposes.numeric('b', ea.SET))
|
|
1014
1014
|
.withDescription('Control status LED color when load OFF'),
|
|
1015
1015
|
exposes.enum('keypad_lockout', ea.ALL, ['unlock', 'lock'])
|
|
1016
|
-
.withDescription('Enables or disables the device’s buttons')
|
|
1016
|
+
.withDescription('Enables or disables the device’s buttons'),
|
|
1017
|
+
exposes.numeric('connected_load', ea.ALL)
|
|
1018
|
+
.withUnit('W').withValueMin(1).withValueMax(1800)
|
|
1019
|
+
.withDescription('Load connected in watt'),
|
|
1020
|
+
e.energy(),
|
|
1021
|
+
],
|
|
1017
1022
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1018
1023
|
const endpoint = device.getEndpoint(1);
|
|
1019
|
-
const binds = ['genOnOff'];
|
|
1024
|
+
const binds = ['genOnOff', 'manuSpecificSinope', 'seMetering'];
|
|
1020
1025
|
await reporting.bind(endpoint, coordinatorEndpoint, binds);
|
|
1021
1026
|
await reporting.onOff(endpoint);
|
|
1027
|
+
try {
|
|
1028
|
+
await reporting.currentSummDelivered(endpoint, {min: 10, max: 300, change: [0, 10]});
|
|
1029
|
+
} catch (error) {/* Do nothing*/}
|
|
1022
1030
|
const payload = [{
|
|
1023
1031
|
attribute: 'actionReport',
|
|
1024
1032
|
minimumReportInterval: 0,
|
package/devices/tuya.js
CHANGED
|
@@ -14,8 +14,108 @@ const fzZosung = zosung.fzZosung;
|
|
|
14
14
|
const tzZosung = zosung.tzZosung;
|
|
15
15
|
const ez = zosung.presetsZosung;
|
|
16
16
|
const globalStore = require('../lib/store');
|
|
17
|
+
const {ColorMode, colorModeLookup} = require('../lib/constants');
|
|
17
18
|
|
|
18
19
|
const tzLocal = {
|
|
20
|
+
led_control: {
|
|
21
|
+
key: ['brightness', 'color', 'color_temp', 'transition'],
|
|
22
|
+
options: [exposes.options.color_sync()],
|
|
23
|
+
convertSet: async (entity, _key, _value, meta) => {
|
|
24
|
+
const newState = {};
|
|
25
|
+
|
|
26
|
+
// The color mode encodes whether the light is using its white LEDs or its color LEDs
|
|
27
|
+
let colorMode = meta.state.color_mode ?? colorModeLookup[ColorMode.ColorTemp];
|
|
28
|
+
|
|
29
|
+
// Color mode switching is done by setting color temperature (switch to white LEDs) or setting color (switch
|
|
30
|
+
// to color LEDs)
|
|
31
|
+
if ('color_temp' in meta.message) colorMode = colorModeLookup[ColorMode.ColorTemp];
|
|
32
|
+
if ('color' in meta.message) colorMode = colorModeLookup[ColorMode.HS];
|
|
33
|
+
|
|
34
|
+
if (colorMode != meta.state.color_mode) {
|
|
35
|
+
newState.color_mode = colorMode;
|
|
36
|
+
|
|
37
|
+
// To switch between white mode and color mode, we have to send a special command:
|
|
38
|
+
const rgbMode = (colorMode == colorModeLookup[ColorMode.HS]);
|
|
39
|
+
await entity.command('lightingColorCtrl', 'tuyaRgbMode', {enable: rgbMode}, {}, {disableDefaultResponse: true});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// A transition time of 0 would be treated as about 1 second, probably some kind of fallback/default
|
|
43
|
+
// transition time, so for "no transition" we use 1 (tenth of a second).
|
|
44
|
+
const transtime = 'transition' in meta.message ? meta.message.transition * 10 : 1;
|
|
45
|
+
|
|
46
|
+
if (colorMode == colorModeLookup[ColorMode.ColorTemp]) {
|
|
47
|
+
if ('brightness' in meta.message) {
|
|
48
|
+
const zclData = {level: Number(meta.message.brightness), transtime};
|
|
49
|
+
await entity.command('genLevelCtrl', 'moveToLevel', zclData, utils.getOptions(meta.mapped, entity));
|
|
50
|
+
newState.brightness = meta.message.brightness;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if ('color_temp' in meta.message) {
|
|
54
|
+
const zclData = {colortemp: meta.message.color_temp, transtime: transtime};
|
|
55
|
+
await entity.command('lightingColorCtrl', 'moveToColorTemp', zclData, utils.getOptions(meta.mapped, entity));
|
|
56
|
+
newState.color_temp = meta.message.color_temp;
|
|
57
|
+
}
|
|
58
|
+
} else if (colorMode == colorModeLookup[ColorMode.HS]) {
|
|
59
|
+
if ('brightness' in meta.message || 'color' in meta.message) {
|
|
60
|
+
// We ignore the brightness of the color and instead use the overall brightness setting of the lamp
|
|
61
|
+
// for the brightness because I think that's the expected behavior and also because the color
|
|
62
|
+
// conversion below always returns 100 as brightness ("value") even for very dark colors, except
|
|
63
|
+
// when the color is completely black/zero.
|
|
64
|
+
|
|
65
|
+
// Load current state or defaults
|
|
66
|
+
const newSettings = {
|
|
67
|
+
brightness: meta.state.brightness ?? 254, // full brightness
|
|
68
|
+
hue: (meta.state.color ?? {}).hue ?? 0, // red
|
|
69
|
+
saturation: (meta.state.color ?? {}).saturation ?? 100, // full saturation
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// Apply changes
|
|
73
|
+
if ('brightness' in meta.message) {
|
|
74
|
+
newSettings.brightness = meta.message.brightness;
|
|
75
|
+
newState.brightness = meta.message.brightness;
|
|
76
|
+
}
|
|
77
|
+
if ('color' in meta.message) {
|
|
78
|
+
// The Z2M UI sends `{ hex:'#xxxxxx' }`.
|
|
79
|
+
// Home Assistant sends `{ h: xxx, s: xxx }`.
|
|
80
|
+
// We convert the former into the latter.
|
|
81
|
+
const c = libColor.Color.fromConverterArg(meta.message.color);
|
|
82
|
+
if (c.isRGB()) {
|
|
83
|
+
// https://github.com/Koenkk/zigbee2mqtt/issues/13421#issuecomment-1426044963
|
|
84
|
+
c.hsv = c.rgb.gammaCorrected().toXY().toHSV();
|
|
85
|
+
}
|
|
86
|
+
const color = c.hsv;
|
|
87
|
+
|
|
88
|
+
newSettings.hue = color.hue;
|
|
89
|
+
newSettings.saturation = color.saturation;
|
|
90
|
+
|
|
91
|
+
newState.color = {
|
|
92
|
+
hue: color.hue,
|
|
93
|
+
saturation: color.saturation,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Convert to device specific format and send
|
|
98
|
+
const zclData = {
|
|
99
|
+
brightness: utils.mapNumberRange(newSettings.brightness, 0, 254, 0, 1000),
|
|
100
|
+
hue: newSettings.hue,
|
|
101
|
+
saturation: utils.mapNumberRange(newSettings.saturation, 0, 100, 0, 1000),
|
|
102
|
+
};
|
|
103
|
+
// This command doesn't support a transition time
|
|
104
|
+
await entity.command('lightingColorCtrl', 'tuyaMoveToHueAndSaturationBrightness2', zclData,
|
|
105
|
+
utils.getOptions(meta.mapped, entity));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// If we're in white mode, calculate a matching display color for the set color temperature. This also kind
|
|
110
|
+
// of works in the other direction.
|
|
111
|
+
Object.assign(newState, libColor.syncColorState(newState, meta.state, entity, meta.options, meta.logger));
|
|
112
|
+
|
|
113
|
+
return {state: newState};
|
|
114
|
+
},
|
|
115
|
+
convertGet: async (entity, key, meta) => {
|
|
116
|
+
await entity.read('lightingColorCtrl', ['currentHue', 'currentSaturation', 'currentLevel', 'tuyaRgbMode', 'colorTemperature']);
|
|
117
|
+
},
|
|
118
|
+
},
|
|
19
119
|
TS110E_options: {
|
|
20
120
|
key: ['min_brightness', 'max_brightness', 'light_type', 'switch_type'],
|
|
21
121
|
convertSet: async (entity, key, value, meta) => {
|
|
@@ -338,6 +438,79 @@ const tzLocal = {
|
|
|
338
438
|
}
|
|
339
439
|
},
|
|
340
440
|
},
|
|
441
|
+
TS011F_threshold: {
|
|
442
|
+
key: [
|
|
443
|
+
'temperature_threshold', 'temperature_breaker', 'power_threshold', 'power_breaker',
|
|
444
|
+
'over_current_threshold', 'over_current_breaker', 'over_voltage_threshold', 'over_voltage_breaker',
|
|
445
|
+
'under_voltage_threshold', 'under_voltage_breaker',
|
|
446
|
+
],
|
|
447
|
+
convertSet: async (entity, key, value, meta) => {
|
|
448
|
+
switch (key) {
|
|
449
|
+
case 'temperature_threshold': {
|
|
450
|
+
const state = meta.state['temperature_breaker'];
|
|
451
|
+
const buf = Buffer.from([5, {'ON': 1, 'OFF': 0}[state], 0, value]);
|
|
452
|
+
await entity.command('manuSpecificTuya_3', 'setOptions2', {data: buf});
|
|
453
|
+
break;
|
|
454
|
+
}
|
|
455
|
+
case 'temperature_breaker': {
|
|
456
|
+
const threshold = meta.state['temperature_threshold'];
|
|
457
|
+
const buf = Buffer.from([5, {'ON': 1, 'OFF': 0}[value], 0, threshold]);
|
|
458
|
+
await entity.command('manuSpecificTuya_3', 'setOptions2', {data: buf});
|
|
459
|
+
break;
|
|
460
|
+
}
|
|
461
|
+
case 'power_threshold': {
|
|
462
|
+
const state = meta.state['power_breaker'];
|
|
463
|
+
const buf = Buffer.from([7, {'ON': 1, 'OFF': 0}[state], 0, value]);
|
|
464
|
+
await entity.command('manuSpecificTuya_3', 'setOptions2', {data: buf});
|
|
465
|
+
break;
|
|
466
|
+
}
|
|
467
|
+
case 'power_breaker': {
|
|
468
|
+
const threshold = meta.state['power_threshold'];
|
|
469
|
+
const buf = Buffer.from([7, {'ON': 1, 'OFF': 0}[value], 0, threshold]);
|
|
470
|
+
await entity.command('manuSpecificTuya_3', 'setOptions2', {data: buf});
|
|
471
|
+
break;
|
|
472
|
+
}
|
|
473
|
+
case 'over_current_threshold': {
|
|
474
|
+
const state = meta.state['over_current_breaker'];
|
|
475
|
+
const buf = Buffer.from([1, {'ON': 1, 'OFF': 0}[state], 0, value]);
|
|
476
|
+
await entity.command('manuSpecificTuya_3', 'setOptions3', {data: buf});
|
|
477
|
+
break;
|
|
478
|
+
}
|
|
479
|
+
case 'over_current_breaker': {
|
|
480
|
+
const threshold = meta.state['over_current_threshold'];
|
|
481
|
+
const buf = Buffer.from([1, {'ON': 1, 'OFF': 0}[value], 0, threshold]);
|
|
482
|
+
await entity.command('manuSpecificTuya_3', 'setOptions3', {data: buf});
|
|
483
|
+
break;
|
|
484
|
+
}
|
|
485
|
+
case 'over_voltage_threshold': {
|
|
486
|
+
const state = meta.state['over_voltage_breaker'];
|
|
487
|
+
const buf = Buffer.from([3, {'ON': 1, 'OFF': 0}[state], 0, value]);
|
|
488
|
+
await entity.command('manuSpecificTuya_3', 'setOptions3', {data: buf});
|
|
489
|
+
break;
|
|
490
|
+
}
|
|
491
|
+
case 'over_voltage_breaker': {
|
|
492
|
+
const threshold = meta.state['over_voltage_threshold'];
|
|
493
|
+
const buf = Buffer.from([3, {'ON': 1, 'OFF': 0}[value], 0, threshold]);
|
|
494
|
+
await entity.command('manuSpecificTuya_3', 'setOptions3', {data: buf});
|
|
495
|
+
break;
|
|
496
|
+
}
|
|
497
|
+
case 'under_voltage_threshold': {
|
|
498
|
+
const state = meta.state['under_voltage_breaker'];
|
|
499
|
+
const buf = Buffer.from([4, {'ON': 1, 'OFF': 0}[state], 0, value]);
|
|
500
|
+
await entity.command('manuSpecificTuya_3', 'setOptions3', {data: buf});
|
|
501
|
+
break;
|
|
502
|
+
}
|
|
503
|
+
case 'under_voltage_breaker': {
|
|
504
|
+
const threshold = meta.state['under_voltage_threshold'];
|
|
505
|
+
const buf = Buffer.from([4, {'ON': 1, 'OFF': 0}[value], 0, threshold]);
|
|
506
|
+
await entity.command('manuSpecificTuya_3', 'setOptions3', {data: buf});
|
|
507
|
+
break;
|
|
508
|
+
}
|
|
509
|
+
default: // Unknown key
|
|
510
|
+
meta.logger.warn(`Unhandled key ${key}`);
|
|
511
|
+
}
|
|
512
|
+
},
|
|
513
|
+
},
|
|
341
514
|
};
|
|
342
515
|
|
|
343
516
|
const fzLocal = {
|
|
@@ -739,6 +912,46 @@ const fzLocal = {
|
|
|
739
912
|
return result;
|
|
740
913
|
},
|
|
741
914
|
},
|
|
915
|
+
TS011F_threshold: {
|
|
916
|
+
cluster: 'manuSpecificTuya_3',
|
|
917
|
+
type: 'raw',
|
|
918
|
+
convert: (model, msg, publish, options, meta) => {
|
|
919
|
+
const splitToAttributes = (value) => {
|
|
920
|
+
const result = {};
|
|
921
|
+
const len = value.length;
|
|
922
|
+
let i = 0;
|
|
923
|
+
while (i < len) {
|
|
924
|
+
const key = value.readUInt8(i);
|
|
925
|
+
result[key] = [value.readUInt8(i+1), value.readUInt16BE(i+2)];
|
|
926
|
+
i += 4;
|
|
927
|
+
}
|
|
928
|
+
return result;
|
|
929
|
+
};
|
|
930
|
+
const lookup = {0: 'OFF', 1: 'ON'};
|
|
931
|
+
const command = msg.data[2];
|
|
932
|
+
const data = msg.data.slice(3);
|
|
933
|
+
if (command == 0xE6) {
|
|
934
|
+
const value = splitToAttributes(data);
|
|
935
|
+
return {
|
|
936
|
+
'temperature_threshold': value[0x05][1],
|
|
937
|
+
'temperature_breaker': lookup[value[0x05][0]],
|
|
938
|
+
'power_threshold': value[0x07][1],
|
|
939
|
+
'power_breaker': lookup[value[0x07][0]],
|
|
940
|
+
};
|
|
941
|
+
}
|
|
942
|
+
if (command == 0xE7) {
|
|
943
|
+
const value = splitToAttributes(data);
|
|
944
|
+
return {
|
|
945
|
+
'over_current_threshold': value[0x01][1],
|
|
946
|
+
'over_current_breaker': lookup[value[0x01][0]],
|
|
947
|
+
'over_voltage_threshold': value[0x03][1],
|
|
948
|
+
'over_voltage_breaker': lookup[value[0x03][0]],
|
|
949
|
+
'under_voltage_threshold': value[0x04][1],
|
|
950
|
+
'under_voltage_breaker': lookup[value[0x04][0]],
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
},
|
|
954
|
+
},
|
|
742
955
|
};
|
|
743
956
|
|
|
744
957
|
module.exports = [
|
|
@@ -823,6 +1036,27 @@ module.exports = [
|
|
|
823
1036
|
return exps;
|
|
824
1037
|
},
|
|
825
1038
|
},
|
|
1039
|
+
{
|
|
1040
|
+
fingerprint: tuya.fingerprint('TS0601', ['_TZE200_nvups4nh']),
|
|
1041
|
+
model: 'TS0601_contact_temperature_humidity_sensor',
|
|
1042
|
+
vendor: 'TuYa',
|
|
1043
|
+
description: 'Contact, temperature and humidity sensor',
|
|
1044
|
+
fromZigbee: [tuya.fz.datapoints, tuya.fz.gateway_connection_status],
|
|
1045
|
+
toZigbee: [tuya.tz.datapoints],
|
|
1046
|
+
configure: tuya.configureMagicPacket,
|
|
1047
|
+
exposes: [e.contact(), e.temperature(), e.humidity(), e.battery()],
|
|
1048
|
+
meta: {
|
|
1049
|
+
tuyaDatapoints: [
|
|
1050
|
+
[1, 'contact', tuya.valueConverter.trueFalseInvert],
|
|
1051
|
+
[2, 'battery', tuya.valueConverter.raw],
|
|
1052
|
+
[7, 'temperature', tuya.valueConverter.divideBy10],
|
|
1053
|
+
[8, 'humidity', tuya.valueConverter.raw],
|
|
1054
|
+
],
|
|
1055
|
+
},
|
|
1056
|
+
whiteLabel: [
|
|
1057
|
+
tuya.whitelabel('Aubess', '1005005194831629', 'Contact, temperature and humidity sensor', ['_TZE200_nvups4nh']),
|
|
1058
|
+
],
|
|
1059
|
+
},
|
|
826
1060
|
{
|
|
827
1061
|
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_vzqtvljm'}],
|
|
828
1062
|
model: 'TS0601_illuminance_temperature_humidity_sensor',
|
|
@@ -1016,7 +1250,7 @@ module.exports = [
|
|
|
1016
1250
|
},
|
|
1017
1251
|
{
|
|
1018
1252
|
zigbeeModel: ['TS0505B'],
|
|
1019
|
-
model: '
|
|
1253
|
+
model: 'TS0505B_1',
|
|
1020
1254
|
vendor: 'TuYa',
|
|
1021
1255
|
description: 'Zigbee RGB+CCT light',
|
|
1022
1256
|
whiteLabel: [{vendor: 'Mercator Ikuü', model: 'SMD4106W-RGB-ZB'},
|
|
@@ -1055,6 +1289,22 @@ module.exports = [
|
|
|
1055
1289
|
device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
|
|
1056
1290
|
},
|
|
1057
1291
|
},
|
|
1292
|
+
{
|
|
1293
|
+
fingerprint: tuya.fingerprint('TS0505B', ['_TZ3210_c0s1xloa', '_TZ3210_iystcadi']),
|
|
1294
|
+
model: 'TS0505B_2',
|
|
1295
|
+
vendor: 'TuYa',
|
|
1296
|
+
description: 'Zigbee RGB+CCT light',
|
|
1297
|
+
whiteLabel: [
|
|
1298
|
+
tuya.whitelabel('Lidl', '14149505L/14149506L_2', 'Livarno Lux light bar RGB+CCT (black/white)', ['_TZ3210_iystcadi']),
|
|
1299
|
+
tuya.whitelabel('Lidl', '399629_2110', 'Livarno Lux Ceiling Panel RGB+CCT', ['_TZ3210_c0s1xloa']),
|
|
1300
|
+
],
|
|
1301
|
+
toZigbee: [tz.on_off, tzLocal.led_control],
|
|
1302
|
+
fromZigbee: [fz.on_off, fz.tuya_led_controller, fz.brightness, fz.ignore_basic_report],
|
|
1303
|
+
exposes: [e.light_brightness_colortemp_colorhs([153, 500]).removeFeature('color_temp_startup')],
|
|
1304
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1305
|
+
device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
|
|
1306
|
+
},
|
|
1307
|
+
},
|
|
1058
1308
|
{
|
|
1059
1309
|
zigbeeModel: ['TS0503B'],
|
|
1060
1310
|
model: 'TS0503B',
|
|
@@ -1175,13 +1425,15 @@ module.exports = [
|
|
|
1175
1425
|
{modelID: 'TS0202', manufacturerName: '_TZ3000_h4wnrtck'},
|
|
1176
1426
|
{modelID: 'TS0202', manufacturerName: '_TZ3000_sr0vaafi'},
|
|
1177
1427
|
{modelID: 'WHD02', manufacturerName: '_TZ3000_hktqahrq'},
|
|
1428
|
+
{modelID: 'TS0202', manufacturerName: '_TZ3040_wqmtjsyk'},
|
|
1178
1429
|
],
|
|
1179
1430
|
model: 'TS0202',
|
|
1180
1431
|
vendor: 'TuYa',
|
|
1181
1432
|
description: 'Motion sensor',
|
|
1182
1433
|
whiteLabel: [{vendor: 'Mercator Ikuü', model: 'SMA02P'},
|
|
1183
1434
|
{vendor: 'TuYa', model: 'TY-ZPR06'},
|
|
1184
|
-
{vendor: 'Tesla Smart', model: 'TS0202'}
|
|
1435
|
+
{vendor: 'Tesla Smart', model: 'TS0202'},
|
|
1436
|
+
tuya.whitelabel('MiBoxer', 'PIR1-ZB', 'PIR Sensor', ['_TZ3040_wqmtjsyk'])],
|
|
1185
1437
|
fromZigbee: [fz.ias_occupancy_alarm_1, fz.battery, fz.ignore_basic_report, fz.ias_occupancy_alarm_1_report],
|
|
1186
1438
|
toZigbee: [],
|
|
1187
1439
|
exposes: [e.occupancy(), e.battery_low(), e.tamper(), e.battery(), e.battery_voltage()],
|
|
@@ -2260,6 +2512,7 @@ module.exports = [
|
|
|
2260
2512
|
{modelID: 'TS0601', manufacturerName: '_TZE200_3ylew7b4'},
|
|
2261
2513
|
{modelID: 'TS0601', manufacturerName: '_TZE200_llm0epxg'},
|
|
2262
2514
|
{modelID: 'TS0601', manufacturerName: '_TZE200_n1aauwb4'},
|
|
2515
|
+
{modelID: 'TS0601', manufacturerName: '_TZE200_xu4a5rhj'},
|
|
2263
2516
|
],
|
|
2264
2517
|
model: 'TS0601_cover_1',
|
|
2265
2518
|
vendor: 'TuYa',
|
|
@@ -2414,8 +2667,8 @@ module.exports = [
|
|
|
2414
2667
|
exposes.enum('motor_direction', ea.STATE_SET, ['normal', 'reversed']).withDescription('Set the motor direction'),
|
|
2415
2668
|
exposes.numeric('motor_speed', ea.STATE_SET).withValueMin(0).withValueMax(255).withDescription('Motor speed').withUnit('rpm'),
|
|
2416
2669
|
exposes.enum('opening_mode', ea.STATE_SET, ['tilt', 'lift']).withDescription('Opening mode'),
|
|
2417
|
-
exposes.enum('set_upper_limit', ea.
|
|
2418
|
-
exposes.enum('set_bottom_limit', ea.
|
|
2670
|
+
exposes.enum('set_upper_limit', ea.STATE_SET, ['SET']).withDescription('Set the upper limit, to reset limits use factory_reset'),
|
|
2671
|
+
exposes.enum('set_bottom_limit', ea.STATE_SET, ['SET']).withDescription('Set the bottom limit, to reset limits use factory_reset'),
|
|
2419
2672
|
exposes.binary('factory_reset', ea.STATE_SET, true, false).withDescription('Factory reset the device'),
|
|
2420
2673
|
],
|
|
2421
2674
|
whiteLabel: [
|
|
@@ -4509,4 +4762,57 @@ module.exports = [
|
|
|
4509
4762
|
toZigbee: [],
|
|
4510
4763
|
configure: tuya.configureMagicPacket,
|
|
4511
4764
|
},
|
|
4765
|
+
{
|
|
4766
|
+
fingerprint: tuya.fingerprint('TS011F', ['_TZ3000_cayepv1a']),
|
|
4767
|
+
model: 'TS011F_with_threshold',
|
|
4768
|
+
description: 'Din rail switch with power monitoring and threshold settings',
|
|
4769
|
+
vendor: 'TuYa',
|
|
4770
|
+
ota: ota.zigbeeOTA,
|
|
4771
|
+
extend: tuya.extend.switch({
|
|
4772
|
+
electricalMeasurements: true, electricalMeasurementsFzConverter: fzLocal.TS011F_electrical_measurement,
|
|
4773
|
+
powerOutageMemory: true, indicatorMode: true,
|
|
4774
|
+
fromZigbee: [fz.temperature, fzLocal.TS011F_threshold],
|
|
4775
|
+
toZigbee: [tzLocal.TS011F_threshold],
|
|
4776
|
+
exposes: [
|
|
4777
|
+
e.temperature(),
|
|
4778
|
+
exposes.numeric('temperature_threshold', ea.STATE_SET).withValueMin(40).withValueMax(100).withValueStep(1).withUnit('*C')
|
|
4779
|
+
.withDescription('High temperature threshold'),
|
|
4780
|
+
exposes.binary('temperature_breaker', ea.STATE_SET, 'ON', 'OFF')
|
|
4781
|
+
.withDescription('High temperature breaker'),
|
|
4782
|
+
exposes.numeric('power_threshold', ea.STATE_SET).withValueMin(1).withValueMax(26).withValueStep(1).withUnit('kW')
|
|
4783
|
+
.withDescription('High power threshold'),
|
|
4784
|
+
exposes.binary('power_breaker', ea.STATE_SET, 'ON', 'OFF')
|
|
4785
|
+
.withDescription('High power breaker'),
|
|
4786
|
+
exposes.numeric('over_current_threshold', ea.STATE_SET).withValueMin(1).withValueMax(64).withValueStep(1).withUnit('A')
|
|
4787
|
+
.withDescription('Over-current threshold'),
|
|
4788
|
+
exposes.binary('over_current_breaker', ea.STATE_SET, 'ON', 'OFF')
|
|
4789
|
+
.withDescription('Over-current breaker'),
|
|
4790
|
+
exposes.numeric('over_voltage_threshold', ea.STATE_SET).withValueMin(220).withValueMax(260).withValueStep(1).withUnit('V')
|
|
4791
|
+
.withDescription('Over-voltage threshold'),
|
|
4792
|
+
exposes.binary('over_voltage_breaker', ea.STATE_SET, 'ON', 'OFF')
|
|
4793
|
+
.withDescription('Over-voltage breaker'),
|
|
4794
|
+
exposes.numeric('under_voltage_threshold', ea.STATE_SET).withValueMin(76).withValueMax(240).withValueStep(1).withUnit('V')
|
|
4795
|
+
.withDescription('Under-voltage threshold'),
|
|
4796
|
+
exposes.binary('under_voltage_breaker', ea.STATE_SET, 'ON', 'OFF')
|
|
4797
|
+
.withDescription('Under-voltage breaker'),
|
|
4798
|
+
],
|
|
4799
|
+
}),
|
|
4800
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
4801
|
+
await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
|
|
4802
|
+
const endpoint = device.getEndpoint(1);
|
|
4803
|
+
endpoint.command('genBasic', 'tuyaSetup', {});
|
|
4804
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['msTemperatureMeasurement']);
|
|
4805
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering']);
|
|
4806
|
+
await reporting.rmsVoltage(endpoint, {change: 5});
|
|
4807
|
+
await reporting.rmsCurrent(endpoint, {change: 50});
|
|
4808
|
+
await reporting.activePower(endpoint, {change: 10});
|
|
4809
|
+
await reporting.currentSummDelivered(endpoint);
|
|
4810
|
+
endpoint.saveClusterAttributeKeyValue('haElectricalMeasurement', {acCurrentDivisor: 1000, acCurrentMultiplier: 1});
|
|
4811
|
+
endpoint.saveClusterAttributeKeyValue('seMetering', {divisor: 100, multiplier: 1});
|
|
4812
|
+
device.save();
|
|
4813
|
+
},
|
|
4814
|
+
whiteLabel: [
|
|
4815
|
+
tuya.whitelabel('TONGOU', 'TO-Q-SY2-163JZT', 'Smart circuit breaker', ['_TZ3000_cayepv1a']),
|
|
4816
|
+
],
|
|
4817
|
+
},
|
|
4512
4818
|
];
|
package/lib/tuya.js
CHANGED
|
@@ -1239,6 +1239,10 @@ const valueConverterBasic = {
|
|
|
1239
1239
|
const valueConverter = {
|
|
1240
1240
|
trueFalse0: valueConverterBasic.trueFalse(0),
|
|
1241
1241
|
trueFalse1: valueConverterBasic.trueFalse(1),
|
|
1242
|
+
trueFalseInvert: {
|
|
1243
|
+
to: (v) => !v,
|
|
1244
|
+
from: (v) => !v,
|
|
1245
|
+
},
|
|
1242
1246
|
trueFalseEnum0: valueConverterBasic.trueFalse(new Enum(0)),
|
|
1243
1247
|
onOff: valueConverterBasic.lookup({'ON': true, 'OFF': false}),
|
|
1244
1248
|
powerOnBehavior: valueConverterBasic.lookup({'off': 0, 'on': 1, 'previous': 2}),
|
|
@@ -1932,6 +1936,9 @@ const tuyaExtend = {
|
|
|
1932
1936
|
toZigbee.push(tuyaTz.child_lock);
|
|
1933
1937
|
exposes.push(e.child_lock());
|
|
1934
1938
|
}
|
|
1939
|
+
if (options.fromZigbee) fromZigbee.push(...options.fromZigbee);
|
|
1940
|
+
if (options.toZigbee) toZigbee.push(...options.toZigbee);
|
|
1941
|
+
if (options.exposes) exposes.push(...options.exposes);
|
|
1935
1942
|
return {exposes, fromZigbee, toZigbee};
|
|
1936
1943
|
},
|
|
1937
1944
|
light_onoff_brightness_colortemp_color: (options={}) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zigbee-herdsman-converters",
|
|
3
|
-
"version": "15.0.
|
|
3
|
+
"version": "15.0.100",
|
|
4
4
|
"description": "Collection of device converters to be used with zigbee-herdsman",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
@@ -34,11 +34,11 @@
|
|
|
34
34
|
},
|
|
35
35
|
"homepage": "https://github.com/Koenkk/zigbee-herdsman-converters",
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"axios": "^1.
|
|
37
|
+
"axios": "^1.4.0",
|
|
38
38
|
"buffer-crc32": "^0.2.13",
|
|
39
39
|
"https-proxy-agent": "^5.0.1",
|
|
40
40
|
"tar-stream": "^3.0.0",
|
|
41
|
-
"zigbee-herdsman": "^0.14.
|
|
41
|
+
"zigbee-herdsman": "^0.14.111"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"eslint": "*",
|