zigbee-herdsman-converters 15.0.4 → 15.0.6
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/toZigbee.js +28 -1
- package/devices/ikea.js +1 -26
- package/devices/iris.js +2 -2
- package/devices/ledvance.js +16 -0
- package/devices/lidl.js +6 -0
- package/devices/lonsonho.js +1 -1
- package/devices/moes.js +1 -1
- package/devices/philips.js +7 -0
- package/devices/sinope.js +29 -22
- package/devices/tuya.js +6 -7
- package/devices/visonic.js +7 -2
- package/lib/tuya.js +31 -6
- package/package.json +1 -1
package/converters/toZigbee.js
CHANGED
|
@@ -760,6 +760,31 @@ const converters = {
|
|
|
760
760
|
}
|
|
761
761
|
},
|
|
762
762
|
},
|
|
763
|
+
light_color_and_colortemp_via_color: {
|
|
764
|
+
key: ['color', 'color_temp', 'color_temp_percent'],
|
|
765
|
+
options: [exposes.options.color_sync(), exposes.options.transition()],
|
|
766
|
+
convertSet: async (entity, key, value, meta) => {
|
|
767
|
+
if (key == 'color') {
|
|
768
|
+
const result = await converters.light_color.convertSet(entity, key, value, meta);
|
|
769
|
+
return result;
|
|
770
|
+
} else if (key == 'color_temp' || key == 'color_temp_percent') {
|
|
771
|
+
const xy = libColor.ColorXY.fromMireds(value);
|
|
772
|
+
const payload = {
|
|
773
|
+
transtime: utils.getTransition(entity, key, meta).time,
|
|
774
|
+
colorx: utils.mapNumberRange(xy.x, 0, 1, 0, 65535),
|
|
775
|
+
colory: utils.mapNumberRange(xy.y, 0, 1, 0, 65535),
|
|
776
|
+
};
|
|
777
|
+
await entity.command('lightingColorCtrl', 'moveToColor', payload, utils.getOptions(meta.mapped, entity));
|
|
778
|
+
return {
|
|
779
|
+
state: libColor.syncColorState({'color_mode': constants.colorMode[2], 'color_temp': value}, meta.state,
|
|
780
|
+
entity, meta.options, meta.logger), readAfterWriteTime: payload.transtime * 100,
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
},
|
|
784
|
+
convertGet: async (entity, key, meta) => {
|
|
785
|
+
await entity.read('lightingColorCtrl', light.readColorAttributes(entity, meta));
|
|
786
|
+
},
|
|
787
|
+
},
|
|
763
788
|
light_hue_saturation_step: {
|
|
764
789
|
key: ['hue_step', 'saturation_step'],
|
|
765
790
|
options: [exposes.options.transition()],
|
|
@@ -5516,7 +5541,9 @@ const converters = {
|
|
|
5516
5541
|
extensionfieldsets.push({'clstId': 8, 'len': 1, 'extField': [val]});
|
|
5517
5542
|
state['brightness'] = val;
|
|
5518
5543
|
} else if (attribute === 'position') {
|
|
5519
|
-
|
|
5544
|
+
const invert = utils.getMetaValue(entity, meta.mapped, 'coverInverted', 'allEqual', false) ?
|
|
5545
|
+
!meta.options.invert_cover : meta.options.invert_cover;
|
|
5546
|
+
extensionfieldsets.push({'clstId': 258, 'len': 1, 'extField': [invert ? 100 - val : val]});
|
|
5520
5547
|
state['position'] = val;
|
|
5521
5548
|
} else if (attribute === 'color_temp') {
|
|
5522
5549
|
/*
|
package/devices/ikea.js
CHANGED
|
@@ -6,7 +6,6 @@ const constants = require('../lib/constants');
|
|
|
6
6
|
const reporting = require('../lib/reporting');
|
|
7
7
|
const {repInterval} = require('../lib/constants');
|
|
8
8
|
const utils = require('../lib/utils');
|
|
9
|
-
const libColor = require('../lib/color');
|
|
10
9
|
const extend = require('../lib/extend');
|
|
11
10
|
const globalStore = require('../lib/store');
|
|
12
11
|
const e = exposes.presets;
|
|
@@ -73,30 +72,6 @@ const configureRemote = async (device, coordinatorEndpoint, logger) => {
|
|
|
73
72
|
await reporting.batteryPercentageRemaining(endpoint);
|
|
74
73
|
};
|
|
75
74
|
|
|
76
|
-
const tzLocal = {
|
|
77
|
-
LED1624G9_color_colortemp: {
|
|
78
|
-
...tz.light_color_colortemp,
|
|
79
|
-
convertSet: async (entity, key, value, meta) => {
|
|
80
|
-
if (key == 'color') {
|
|
81
|
-
const result = await tz.light_color.convertSet(entity, key, value, meta);
|
|
82
|
-
return result;
|
|
83
|
-
} else if (key == 'color_temp' || key == 'color_temp_percent') {
|
|
84
|
-
const xy = libColor.ColorXY.fromMireds(value);
|
|
85
|
-
const payload = {
|
|
86
|
-
transtime: utils.getTransition(entity, key, meta).time,
|
|
87
|
-
colorx: utils.mapNumberRange(xy.x, 0, 1, 0, 65535),
|
|
88
|
-
colory: utils.mapNumberRange(xy.y, 0, 1, 0, 65535),
|
|
89
|
-
};
|
|
90
|
-
await entity.command('lightingColorCtrl', 'moveToColor', payload, utils.getOptions(meta.mapped, entity));
|
|
91
|
-
return {
|
|
92
|
-
state: libColor.syncColorState({'color_mode': constants.colorMode[2], 'color_temp': value}, meta.state,
|
|
93
|
-
entity, meta.options, meta.logger), readAfterWriteTime: payload.transtime * 100,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
};
|
|
99
|
-
|
|
100
75
|
const fzLocal = {
|
|
101
76
|
// The STYRBAR sends an on +- 500ms after the arrow release. We don't want to send the ON action in this case.
|
|
102
77
|
// https://github.com/Koenkk/zigbee2mqtt/issues/13335
|
|
@@ -490,7 +465,7 @@ module.exports = [
|
|
|
490
465
|
toZigbee: utils.replaceInArray(
|
|
491
466
|
tradfriExtend.light_onoff_brightness_colortemp_color().toZigbee,
|
|
492
467
|
[tz.light_color_colortemp],
|
|
493
|
-
[
|
|
468
|
+
[tz.light_color_and_colortemp_via_color],
|
|
494
469
|
),
|
|
495
470
|
meta: {supportsHueAndSaturation: false},
|
|
496
471
|
},
|
package/devices/iris.js
CHANGED
|
@@ -58,7 +58,7 @@ module.exports = [
|
|
|
58
58
|
await reporting.temperature(endpoint);
|
|
59
59
|
await reporting.batteryVoltage(endpoint);
|
|
60
60
|
},
|
|
61
|
-
exposes: [e.occupancy(), e.battery_low(), e.
|
|
61
|
+
exposes: [e.occupancy(), e.battery_low(), e.temperature(), e.battery()],
|
|
62
62
|
},
|
|
63
63
|
{
|
|
64
64
|
zigbeeModel: ['3320-L'],
|
|
@@ -74,7 +74,7 @@ module.exports = [
|
|
|
74
74
|
await reporting.temperature(endpoint);
|
|
75
75
|
await reporting.batteryVoltage(endpoint);
|
|
76
76
|
},
|
|
77
|
-
exposes: [e.contact(), e.battery_low(), e.
|
|
77
|
+
exposes: [e.contact(), e.battery_low(), e.temperature(), e.battery()],
|
|
78
78
|
},
|
|
79
79
|
{
|
|
80
80
|
zigbeeModel: ['3450-L', '3450-L2'],
|
package/devices/ledvance.js
CHANGED
|
@@ -251,6 +251,22 @@ module.exports = [
|
|
|
251
251
|
extend: extend.ledvance.light_onoff_brightness(),
|
|
252
252
|
ota: ota.ledvance,
|
|
253
253
|
},
|
|
254
|
+
{
|
|
255
|
+
zigbeeModel: ['FLEX RGBW T'],
|
|
256
|
+
model: '4058075729384',
|
|
257
|
+
vendor: 'LEDVANCE',
|
|
258
|
+
description: 'SMART+ Indoor Flex multicolor RGBW',
|
|
259
|
+
extend: extend.ledvance.light_onoff_brightness_colortemp_color({colorTempRange: [153, 526]}),
|
|
260
|
+
ota: ota.ledvance,
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
zigbeeModel: ['OUTDOOR FLEX RGBW T'],
|
|
264
|
+
model: '4058075729360',
|
|
265
|
+
vendor: 'LEDVANCE',
|
|
266
|
+
description: 'SMART+ Outdoor Flex multicolor RGBW',
|
|
267
|
+
extend: extend.ledvance.light_onoff_brightness_colortemp_color({colorTempRange: [153, 526]}),
|
|
268
|
+
ota: ota.ledvance,
|
|
269
|
+
},
|
|
254
270
|
{
|
|
255
271
|
zigbeeModel: ['GLOBE60 FIL DIM T'],
|
|
256
272
|
model: '4058075729247',
|
package/devices/lidl.js
CHANGED
|
@@ -8,6 +8,7 @@ const ea = exposes.access;
|
|
|
8
8
|
const tuya = require('../lib/tuya');
|
|
9
9
|
const globalStore = require('../lib/store');
|
|
10
10
|
const ota = require('../lib/ota');
|
|
11
|
+
const utils = require('../lib/utils');
|
|
11
12
|
|
|
12
13
|
const tuyaLocal = {
|
|
13
14
|
dataPoints: {
|
|
@@ -542,6 +543,11 @@ module.exports = [
|
|
|
542
543
|
vendor: 'Lidl',
|
|
543
544
|
description: 'Livarno smart LED ceiling light',
|
|
544
545
|
...extend.light_onoff_brightness_colortemp_color({disableColorTempStartup: true, colorTempRange: [153, 500]}),
|
|
546
|
+
toZigbee: utils.replaceInArray(
|
|
547
|
+
extend.light_onoff_brightness_colortemp_color({disableColorTempStartup: true, colorTempRange: [153, 500]}).toZigbee,
|
|
548
|
+
[tz.light_color_colortemp],
|
|
549
|
+
[tz.light_color_and_colortemp_via_color],
|
|
550
|
+
),
|
|
545
551
|
meta: {applyRedFix: true, enhancedHue: false},
|
|
546
552
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
547
553
|
device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
|
package/devices/lonsonho.js
CHANGED
|
@@ -25,7 +25,7 @@ module.exports = [
|
|
|
25
25
|
model: '11830304',
|
|
26
26
|
vendor: 'Lonsonho',
|
|
27
27
|
description: 'Curtain switch',
|
|
28
|
-
fromZigbee: [fz.cover_position_tilt, tuya.fz.
|
|
28
|
+
fromZigbee: [fz.cover_position_tilt, tuya.fz.backlight_mode_low_medium_high, fz.tuya_cover_options],
|
|
29
29
|
toZigbee: [tz.cover_state, tz.cover_position_tilt, tz.tuya_cover_calibration, tz.tuya_cover_reversal,
|
|
30
30
|
tuya.tz.backlight_indicator_mode],
|
|
31
31
|
meta: {coverInverted: true},
|
package/devices/moes.js
CHANGED
|
@@ -399,7 +399,7 @@ module.exports = [
|
|
|
399
399
|
model: 'ZS-EUB_1gang',
|
|
400
400
|
vendor: 'Moes',
|
|
401
401
|
description: 'Wall light switch (1 gang)',
|
|
402
|
-
extend: tuya.extend.switch({
|
|
402
|
+
extend: tuya.extend.switch({backlightModeLowMediumHigh: true, switchType: true}),
|
|
403
403
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
404
404
|
await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
|
|
405
405
|
device.powerSource = 'Mains (single phase)';
|
package/devices/philips.js
CHANGED
|
@@ -810,6 +810,13 @@ module.exports = [
|
|
|
810
810
|
description: 'Hue Filament Standard A60/E27 bluetooth',
|
|
811
811
|
extend: hueExtend.light_onoff_brightness(),
|
|
812
812
|
},
|
|
813
|
+
{
|
|
814
|
+
zigbeeModel: ['LWA021'],
|
|
815
|
+
model: '9290030514',
|
|
816
|
+
vendor: 'Philips',
|
|
817
|
+
description: 'Hue Filament Standard A60/E27 bluetooth',
|
|
818
|
+
extend: hueExtend.light_onoff_brightness(),
|
|
819
|
+
},
|
|
813
820
|
{
|
|
814
821
|
zigbeeModel: ['LCB001'],
|
|
815
822
|
model: '548727',
|
package/devices/sinope.js
CHANGED
|
@@ -8,6 +8,7 @@ const extend = require('../lib/extend');
|
|
|
8
8
|
const e = exposes.presets;
|
|
9
9
|
const ea = exposes.access;
|
|
10
10
|
|
|
11
|
+
const manuSinope = {manufacturerCode: 0x119C};
|
|
11
12
|
const fzLocal = {
|
|
12
13
|
sinope_thermostat: {
|
|
13
14
|
cluster: 'hvacThermostat',
|
|
@@ -123,11 +124,11 @@ const tzLocal = {
|
|
|
123
124
|
convertSet: async (entity, key, value, meta) => {
|
|
124
125
|
const sinopeOccupancy = {0: 'unoccupied', 1: 'occupied'};
|
|
125
126
|
const SinopeOccupancy = utils.getKey(sinopeOccupancy, value, value, Number);
|
|
126
|
-
await entity.write('hvacThermostat', {SinopeOccupancy},
|
|
127
|
+
await entity.write('hvacThermostat', {SinopeOccupancy}, manuSinope);
|
|
127
128
|
return {state: {'thermostat_occupancy': value}};
|
|
128
129
|
},
|
|
129
130
|
convertGet: async (entity, key, meta) => {
|
|
130
|
-
await entity.read('hvacThermostat', ['SinopeOccupancy'],
|
|
131
|
+
await entity.read('hvacThermostat', ['SinopeOccupancy'], manuSinope);
|
|
131
132
|
},
|
|
132
133
|
},
|
|
133
134
|
sinope_thermostat_backlight_autodim_param: {
|
|
@@ -135,11 +136,11 @@ const tzLocal = {
|
|
|
135
136
|
convertSet: async (entity, key, value, meta) => {
|
|
136
137
|
const sinopeBacklightParam = {0: 'on_demand', 1: 'sensing'};
|
|
137
138
|
const SinopeBacklight = utils.getKey(sinopeBacklightParam, value, value, Number);
|
|
138
|
-
await entity.write('hvacThermostat', {SinopeBacklight},
|
|
139
|
+
await entity.write('hvacThermostat', {SinopeBacklight}, manuSinope);
|
|
139
140
|
return {state: {'backlight_auto_dim': value}};
|
|
140
141
|
},
|
|
141
142
|
convertGet: async (entity, key, meta) => {
|
|
142
|
-
await entity.read('hvacThermostat', ['SinopeBacklight'],
|
|
143
|
+
await entity.read('hvacThermostat', ['SinopeBacklight'], manuSinope);
|
|
143
144
|
},
|
|
144
145
|
},
|
|
145
146
|
sinope_thermostat_main_cycle_output: {
|
|
@@ -147,11 +148,11 @@ const tzLocal = {
|
|
|
147
148
|
key: ['main_cycle_output'],
|
|
148
149
|
convertSet: async (entity, key, value, meta) => {
|
|
149
150
|
const lookup = {'15_sec': 15, '5_min': 300, '10_min': 600, '15_min': 900, '20_min': 1200, '30_min': 1800};
|
|
150
|
-
await entity.write('hvacThermostat', {SinopeMainCycleOutput: lookup[value]},
|
|
151
|
+
await entity.write('hvacThermostat', {SinopeMainCycleOutput: lookup[value]}, manuSinope);
|
|
151
152
|
return {state: {'main_cycle_output': value}};
|
|
152
153
|
},
|
|
153
154
|
convertGet: async (entity, key, meta) => {
|
|
154
|
-
await entity.read('hvacThermostat', ['SinopeMainCycleOutput'],
|
|
155
|
+
await entity.read('hvacThermostat', ['SinopeMainCycleOutput'], manuSinope);
|
|
155
156
|
},
|
|
156
157
|
},
|
|
157
158
|
sinope_thermostat_aux_cycle_output: {
|
|
@@ -170,22 +171,22 @@ const tzLocal = {
|
|
|
170
171
|
key: ['enable_outdoor_temperature'],
|
|
171
172
|
convertSet: async (entity, key, value, meta) => {
|
|
172
173
|
if (value.toLowerCase() == 'on') {
|
|
173
|
-
await entity.write('manuSpecificSinope', {outdoorTempToDisplayTimeout: 10800});
|
|
174
|
+
await entity.write('manuSpecificSinope', {outdoorTempToDisplayTimeout: 10800}, manuSinope);
|
|
174
175
|
} else if (value.toLowerCase() == 'off') {
|
|
175
176
|
// set timer to 12 sec in order to disable outdoor temperature
|
|
176
|
-
await entity.write('manuSpecificSinope', {outdoorTempToDisplayTimeout: 12});
|
|
177
|
+
await entity.write('manuSpecificSinope', {outdoorTempToDisplayTimeout: 12}, manuSinope);
|
|
177
178
|
}
|
|
178
179
|
return {readAfterWriteTime: 250, state: {enable_outdoor_temperature: value}};
|
|
179
180
|
},
|
|
180
181
|
convertGet: async (entity, key, meta) => {
|
|
181
|
-
await entity.read('manuSpecificSinope', ['outdoorTempToDisplayTimeout']);
|
|
182
|
+
await entity.read('manuSpecificSinope', ['outdoorTempToDisplayTimeout'], manuSinope);
|
|
182
183
|
},
|
|
183
184
|
},
|
|
184
185
|
sinope_thermostat_outdoor_temperature: {
|
|
185
186
|
key: ['thermostat_outdoor_temperature'],
|
|
186
187
|
convertSet: async (entity, key, value, meta) => {
|
|
187
188
|
if (value > -100 && value < 100) {
|
|
188
|
-
await entity.write('manuSpecificSinope', {outdoorTempToDisplay: value * 100});
|
|
189
|
+
await entity.write('manuSpecificSinope', {outdoorTempToDisplay: value * 100}, manuSinope);
|
|
189
190
|
}
|
|
190
191
|
},
|
|
191
192
|
},
|
|
@@ -197,9 +198,9 @@ const tzLocal = {
|
|
|
197
198
|
const thermostatTimeSec = thermostatDate.getTime() / 1000;
|
|
198
199
|
const thermostatTimezoneOffsetSec = thermostatDate.getTimezoneOffset() * 60;
|
|
199
200
|
const currentTimeToDisplay = Math.round(thermostatTimeSec - thermostatTimezoneOffsetSec - 946684800);
|
|
200
|
-
await entity.write('manuSpecificSinope', {currentTimeToDisplay});
|
|
201
|
+
await entity.write('manuSpecificSinope', {currentTimeToDisplay}, manuSinope);
|
|
201
202
|
} else if (value !== '') {
|
|
202
|
-
await entity.write('manuSpecificSinope', {currentTimeToDisplay: value});
|
|
203
|
+
await entity.write('manuSpecificSinope', {currentTimeToDisplay: value}, manuSinope);
|
|
203
204
|
}
|
|
204
205
|
},
|
|
205
206
|
},
|
|
@@ -287,12 +288,12 @@ const tzLocal = {
|
|
|
287
288
|
const lookup = {'24h': 0, '12h': 1};
|
|
288
289
|
value = value.toLowerCase();
|
|
289
290
|
if (lookup.hasOwnProperty(value)) {
|
|
290
|
-
await entity.write('manuSpecificSinope', {timeFormatToDisplay: lookup[value]});
|
|
291
|
+
await entity.write('manuSpecificSinope', {timeFormatToDisplay: lookup[value]}, manuSinope);
|
|
291
292
|
return {readAfterWriteTime: 250, state: {time_format: value}};
|
|
292
293
|
}
|
|
293
294
|
},
|
|
294
295
|
convertGet: async (entity, key, meta) => {
|
|
295
|
-
await entity.read('manuSpecificSinope', ['timeFormatToDisplay']);
|
|
296
|
+
await entity.read('manuSpecificSinope', ['timeFormatToDisplay'], manuSinope);
|
|
296
297
|
},
|
|
297
298
|
},
|
|
298
299
|
sinope_connected_load: {
|
|
@@ -428,6 +429,10 @@ module.exports = [
|
|
|
428
429
|
await reporting.thermostatTemperature(endpoint);
|
|
429
430
|
await reporting.thermostatPIHeatingDemand(endpoint);
|
|
430
431
|
await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
|
|
432
|
+
|
|
433
|
+
await reporting.temperature(endpoint, {min: 1, max: 0xFFFF}); // Disable default reporting
|
|
434
|
+
await endpoint.configureReporting('msTemperatureMeasurement', [{
|
|
435
|
+
attribute: 'tolerance', minimumReportInterval: 1, maximumReportInterval: 0xFFFF, reportableChange: 1}]);
|
|
431
436
|
try {
|
|
432
437
|
await reporting.thermostatSystemMode(endpoint);
|
|
433
438
|
} catch (error) {/* Not all support this */}
|
|
@@ -446,8 +451,6 @@ module.exports = [
|
|
|
446
451
|
}
|
|
447
452
|
await reporting.rmsCurrent(endpoint, {min: 10, max: 306, change: 100}); // divider 1000: 0.1Arms
|
|
448
453
|
await reporting.rmsVoltage(endpoint, {min: 10, max: 307, change: 5}); // divider 10: 0.5Vrms
|
|
449
|
-
|
|
450
|
-
await reporting.temperature(endpoint, {min: 1, max: 0xFFFF}); // Disable default reporting
|
|
451
454
|
},
|
|
452
455
|
},
|
|
453
456
|
{
|
|
@@ -492,6 +495,10 @@ module.exports = [
|
|
|
492
495
|
await reporting.thermostatTemperature(endpoint);
|
|
493
496
|
await reporting.thermostatPIHeatingDemand(endpoint);
|
|
494
497
|
await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
|
|
498
|
+
|
|
499
|
+
await reporting.temperature(endpoint, {min: 1, max: 0xFFFF}); // Disable default reporting
|
|
500
|
+
await endpoint.configureReporting('msTemperatureMeasurement', [{
|
|
501
|
+
attribute: 'tolerance', minimumReportInterval: 1, maximumReportInterval: 0xFFFF, reportableChange: 1}]);
|
|
495
502
|
try {
|
|
496
503
|
await reporting.thermostatSystemMode(endpoint);
|
|
497
504
|
} catch (error) {/* Not all support this */}
|
|
@@ -510,8 +517,6 @@ module.exports = [
|
|
|
510
517
|
}
|
|
511
518
|
await reporting.rmsCurrent(endpoint, {min: 10, max: 306, change: 100}); // divider 1000: 0.1Arms
|
|
512
519
|
await reporting.rmsVoltage(endpoint, {min: 10, max: 307, change: 5}); // divider 10: 0.5Vrms
|
|
513
|
-
|
|
514
|
-
await reporting.temperature(endpoint, {min: 1, max: 0xFFFF}); // Disable default reporting
|
|
515
520
|
},
|
|
516
521
|
},
|
|
517
522
|
{
|
|
@@ -557,22 +562,24 @@ module.exports = [
|
|
|
557
562
|
const thermostatTimeSec = thermostatDate.getTime() / 1000;
|
|
558
563
|
const thermostatTimezoneOffsetSec = thermostatDate.getTimezoneOffset() * 60;
|
|
559
564
|
const currentTimeToDisplay = Math.round(thermostatTimeSec - thermostatTimezoneOffsetSec - 946684800);
|
|
560
|
-
await endpoint.write('manuSpecificSinope', {currentTimeToDisplay},
|
|
561
|
-
await endpoint.write('manuSpecificSinope', {'secondScreenBehavior': 0},
|
|
565
|
+
await endpoint.write('manuSpecificSinope', {currentTimeToDisplay}, manuSinope);
|
|
566
|
+
await endpoint.write('manuSpecificSinope', {'secondScreenBehavior': 0}, manuSinope); // Mode auto
|
|
562
567
|
|
|
563
568
|
await reporting.thermostatTemperature(endpoint);
|
|
564
569
|
await reporting.thermostatPIHeatingDemand(endpoint);
|
|
565
570
|
await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
|
|
566
571
|
await reporting.thermostatSystemMode(endpoint);
|
|
567
572
|
|
|
573
|
+
await reporting.temperature(endpoint, {min: 1, max: 0xFFFF}); // Disable default reporting
|
|
574
|
+
await endpoint.configureReporting('msTemperatureMeasurement', [{
|
|
575
|
+
attribute: 'tolerance', minimumReportInterval: 1, maximumReportInterval: 0xFFFF, reportableChange: 1}]);
|
|
576
|
+
|
|
568
577
|
await reporting.readMeteringMultiplierDivisor(endpoint);
|
|
569
578
|
await reporting.currentSummDelivered(endpoint, {min: 10, max: 303, change: [1, 1]});
|
|
570
579
|
await reporting.readEletricalMeasurementMultiplierDivisors(endpoint);
|
|
571
580
|
await reporting.activePower(endpoint, {min: 10, max: 305, change: 1}); // divider 1: 1W
|
|
572
581
|
await reporting.rmsCurrent(endpoint, {min: 10, max: 306, change: 100}); // divider 1000: 0.1Arms
|
|
573
582
|
await reporting.rmsVoltage(endpoint, {min: 10, max: 307, change: 5}); // divider 10: 0.5Vrms
|
|
574
|
-
|
|
575
|
-
await reporting.temperature(endpoint, {min: 1, max: 0xFFFF}); // Disable default reporting
|
|
576
583
|
try {
|
|
577
584
|
await reporting.thermostatUnoccupiedHeatingSetpoint(endpoint);
|
|
578
585
|
} catch (error) {/* Do nothing */} // Not enought space but shall pass
|
package/devices/tuya.js
CHANGED
|
@@ -931,7 +931,7 @@ module.exports = [
|
|
|
931
931
|
model: 'TS011F_2_gang_wall',
|
|
932
932
|
vendor: 'TuYa',
|
|
933
933
|
description: '2 gang wall outlet',
|
|
934
|
-
extend: tuya.extend.switch({
|
|
934
|
+
extend: tuya.extend.switch({backlightModeLowMediumHigh: true, childLock: true, endpoints: ['l1', 'l2']}),
|
|
935
935
|
whiteLabel: [{vendor: 'ClickSmart+', model: 'CMA30036'}],
|
|
936
936
|
endpoint: (device) => {
|
|
937
937
|
return {'l1': 1, 'l2': 2};
|
|
@@ -1389,7 +1389,7 @@ module.exports = [
|
|
|
1389
1389
|
model: 'TS130F',
|
|
1390
1390
|
vendor: 'TuYa',
|
|
1391
1391
|
description: 'Curtain/blind switch',
|
|
1392
|
-
fromZigbee: [fz.cover_position_tilt, tuya.fz.
|
|
1392
|
+
fromZigbee: [fz.cover_position_tilt, tuya.fz.backlight_mode_low_medium_high, fz.tuya_cover_options],
|
|
1393
1393
|
toZigbee: [tz.cover_state, tz.cover_position_tilt, tz.tuya_cover_calibration, tz.tuya_cover_reversal,
|
|
1394
1394
|
tuya.tz.backlight_indicator_mode],
|
|
1395
1395
|
meta: {coverInverted: true},
|
|
@@ -1676,7 +1676,7 @@ module.exports = [
|
|
|
1676
1676
|
model: 'TS011F_2_gang_2_usb_wall',
|
|
1677
1677
|
vendor: 'TuYa',
|
|
1678
1678
|
description: '2 gang 2 usb wall outlet',
|
|
1679
|
-
extend: tuya.extend.switch({
|
|
1679
|
+
extend: tuya.extend.switch({backlightModeLowMediumHigh: true, endpoints: ['l1', 'l2', 'l3', 'l4']}),
|
|
1680
1680
|
endpoint: () => {
|
|
1681
1681
|
return {'l1': 1, 'l2': 2, 'l3': 3, 'l4': 4};
|
|
1682
1682
|
},
|
|
@@ -2766,8 +2766,7 @@ module.exports = [
|
|
|
2766
2766
|
description: 'Smart light switch - 2 gang',
|
|
2767
2767
|
whiteLabel: [{vendor: 'Vrey', model: 'VR-X712U-0013'}, {vendor: 'TUYATEC', model: 'GDKES-02TZXD'},
|
|
2768
2768
|
{vendor: 'Earda', model: 'ESW-2ZAA-EU'}],
|
|
2769
|
-
extend: tuya.extend.switch(),
|
|
2770
|
-
exposes: [e.switch().withEndpoint('left'), e.switch().withEndpoint('right')],
|
|
2769
|
+
extend: tuya.extend.switch({backlightModeOffNormalInverted: true, endpoints: ['left', 'right']}),
|
|
2771
2770
|
endpoint: (device) => {
|
|
2772
2771
|
return {'left': 1, 'right': 2};
|
|
2773
2772
|
},
|
|
@@ -2806,7 +2805,7 @@ module.exports = [
|
|
|
2806
2805
|
model: 'TS0013',
|
|
2807
2806
|
vendor: 'TuYa',
|
|
2808
2807
|
description: 'Smart light switch - 3 gang without neutral wire',
|
|
2809
|
-
extend: tuya.extend.switch({
|
|
2808
|
+
extend: tuya.extend.switch({backlightModeLowMediumHigh: true, endpoints: ['left', 'center', 'right']}),
|
|
2810
2809
|
endpoint: (device) => {
|
|
2811
2810
|
return {'left': 1, 'center': 2, 'right': 3};
|
|
2812
2811
|
},
|
|
@@ -2857,7 +2856,7 @@ module.exports = [
|
|
|
2857
2856
|
model: 'TS0014',
|
|
2858
2857
|
vendor: 'TuYa',
|
|
2859
2858
|
description: 'Smart light switch - 4 gang without neutral wire',
|
|
2860
|
-
extend: tuya.extend.switch({
|
|
2859
|
+
extend: tuya.extend.switch({backlightModeLowMediumHigh: true, endpoints: ['l1', 'l2', 'l3', 'l4']}),
|
|
2861
2860
|
endpoint: (device) => {
|
|
2862
2861
|
return {'l1': 1, 'l2': 2, 'l3': 3, 'l4': 4};
|
|
2863
2862
|
},
|
package/devices/visonic.js
CHANGED
|
@@ -36,9 +36,14 @@ module.exports = [
|
|
|
36
36
|
model: 'MCT-350 SMA',
|
|
37
37
|
vendor: 'Visonic',
|
|
38
38
|
description: 'Magnetic door & window contact sensor',
|
|
39
|
-
fromZigbee: [fz.ias_contact_alarm_1],
|
|
39
|
+
fromZigbee: [fz.ias_contact_alarm_1, fz.temperature],
|
|
40
40
|
toZigbee: [],
|
|
41
|
-
|
|
41
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
42
|
+
const endpoint = device.getEndpoint(1);
|
|
43
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['msTemperatureMeasurement']);
|
|
44
|
+
await reporting.temperature(endpoint);
|
|
45
|
+
},
|
|
46
|
+
exposes: [e.contact(), e.battery_low(), e.tamper(), e.temperature()],
|
|
42
47
|
},
|
|
43
48
|
{
|
|
44
49
|
zigbeeModel: ['MCT-340 E'],
|
package/lib/tuya.js
CHANGED
|
@@ -1158,7 +1158,10 @@ const tuyaExposes = {
|
|
|
1158
1158
|
powerFactorWithPhase: (phase) => exposes.numeric(`power_factor_${phase}`, ea.STATE).withUnit('%')
|
|
1159
1159
|
.withDescription(`Instantaneous measured power factor (phase ${phase.toUpperCase()})`),
|
|
1160
1160
|
switchType: () => exposes.enum('switch_type', ea.ALL, ['toggle', 'state', 'momentary']).withDescription('Type of the switch'),
|
|
1161
|
-
|
|
1161
|
+
backlightModeLowMediumHigh: () => exposes.enum('backlight_mode', ea.ALL, ['low', 'medium', 'high'])
|
|
1162
|
+
.withDescription('Intensity of the backlight'),
|
|
1163
|
+
backlightModeOffNormalInverted: () => exposes.enum('backlight_mode', ea.ALL, ['off', 'normal', 'inverted'])
|
|
1164
|
+
.withDescription('Mode of the backlight'),
|
|
1162
1165
|
indicatorMode: () => exposes.enum('indicator_mode', ea.ALL, ['off', 'off/on', 'on/off', 'on']).withDescription('LED indicator mode'),
|
|
1163
1166
|
powerOutageMemory: () => exposes.enum('power_outage_memory', ea.ALL, ['on', 'off', 'restore'])
|
|
1164
1167
|
.withDescription('Recover state after power outage'),
|
|
@@ -1546,7 +1549,8 @@ const tuyaTz = {
|
|
|
1546
1549
|
backlight_indicator_mode: {
|
|
1547
1550
|
key: ['backlight_mode', 'indicator_mode'],
|
|
1548
1551
|
convertSet: async (entity, key, value, meta) => {
|
|
1549
|
-
const lookup = key === 'backlight_mode' ? {'low': 0, 'medium': 1, 'high': 2
|
|
1552
|
+
const lookup = key === 'backlight_mode' ? {'low': 0, 'medium': 1, 'high': 2, 'off': 0, 'normal': 1, 'inverted': 2} :
|
|
1553
|
+
{'off': 0, 'off/on': 1, 'on/off': 2, 'on': 3};
|
|
1550
1554
|
value = value.toLowerCase();
|
|
1551
1555
|
utils.validateValue(value, Object.keys(lookup));
|
|
1552
1556
|
await entity.write('genOnOff', {tuyaBacklightMode: lookup[value]});
|
|
@@ -1644,7 +1648,7 @@ const tuyaFz = {
|
|
|
1644
1648
|
}
|
|
1645
1649
|
},
|
|
1646
1650
|
},
|
|
1647
|
-
|
|
1651
|
+
backlight_mode_low_medium_high: {
|
|
1648
1652
|
cluster: 'genOnOff',
|
|
1649
1653
|
type: ['attributeReport', 'readResponse'],
|
|
1650
1654
|
convert: (model, msg, publish, options, meta) => {
|
|
@@ -1655,6 +1659,17 @@ const tuyaFz = {
|
|
|
1655
1659
|
}
|
|
1656
1660
|
},
|
|
1657
1661
|
},
|
|
1662
|
+
backlight_mode_off_normal_inverted: {
|
|
1663
|
+
cluster: 'genOnOff',
|
|
1664
|
+
type: ['attributeReport', 'readResponse'],
|
|
1665
|
+
convert: (model, msg, publish, options, meta) => {
|
|
1666
|
+
if (msg.data.hasOwnProperty('tuyaBacklightMode')) {
|
|
1667
|
+
const value = msg.data['tuyaBacklightMode'];
|
|
1668
|
+
const backlightLookup = {0: 'off', 1: 'normal', 2: 'inverted'};
|
|
1669
|
+
return {backlight_mode: backlightLookup[value]};
|
|
1670
|
+
}
|
|
1671
|
+
},
|
|
1672
|
+
},
|
|
1658
1673
|
indicator_mode: {
|
|
1659
1674
|
cluster: 'genOnOff',
|
|
1660
1675
|
type: ['attributeReport', 'readResponse'],
|
|
@@ -1747,10 +1762,20 @@ const tuyaExtend = {
|
|
|
1747
1762
|
toZigbee.push(tuyaTz.switch_type);
|
|
1748
1763
|
exposes.push(tuyaExposes.switchType());
|
|
1749
1764
|
}
|
|
1750
|
-
if (options.
|
|
1751
|
-
|
|
1765
|
+
if (options.backlightModeLowMediumHigh || options.backlightModeOffNormalInverted || options.indicatorMode) {
|
|
1766
|
+
if (options.backlightModeLowMediumHigh) {
|
|
1767
|
+
fromZigbee.push(tuyaFz.backlight_mode_low_medium_high);
|
|
1768
|
+
exposes.push(tuyaExposes.backlightModeLowMediumHigh());
|
|
1769
|
+
}
|
|
1770
|
+
if (options.backlightModeOffNormalInverted) {
|
|
1771
|
+
fromZigbee.push(tuyaFz.backlight_mode_off_normal_inverted);
|
|
1772
|
+
exposes.push(tuyaExposes.backlightModeOffNormalInverted());
|
|
1773
|
+
}
|
|
1774
|
+
if (options.indicatorMode) {
|
|
1775
|
+
fromZigbee.push(tuyaFz.indicator_mode);
|
|
1776
|
+
exposes.push(tuyaExposes.indicatorMode());
|
|
1777
|
+
}
|
|
1752
1778
|
toZigbee.push(tuyaTz.backlight_indicator_mode);
|
|
1753
|
-
exposes.push(options.backlightMode ? tuyaExposes.backlightMode() : tuyaExposes.indicatorMode());
|
|
1754
1779
|
}
|
|
1755
1780
|
if (options.electricalMeasurements) {
|
|
1756
1781
|
fromZigbee.push(fz.electrical_measurement, fz.metering);
|