zigbee-herdsman-converters 14.0.444 → 14.0.447
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 +36 -38
- package/converters/toZigbee.js +33 -1
- package/devices/aurora_lighting.js +4 -3
- package/devices/lidl.js +2 -0
- package/devices/livolo.js +22 -5
- package/devices/lonsonho.js +12 -0
- package/devices/philips.js +16 -0
- package/devices/qmotion.js +9 -2
- package/devices/slv.js +7 -0
- package/devices/tuya.js +1 -0
- package/devices/woox.js +2 -2
- package/devices/xiaomi.js +11 -5
- package/devices/zemismart.js +4 -1
- package/lib/ota/zigbeeOTA.js +4 -2
- package/lib/tuya.js +1 -0
- package/lib/utils.js +1 -2
- package/lib/xiaomi.js +36 -14
- package/npm-shrinkwrap.json +1 -1
- package/package.json +1 -1
package/converters/fromZigbee.js
CHANGED
|
@@ -428,7 +428,7 @@ const converters = {
|
|
|
428
428
|
convert: (model, msg, publish, options, meta) => {
|
|
429
429
|
if (msg.data.hasOwnProperty('occupancy')) {
|
|
430
430
|
const payload = {occupancy: (msg.data.occupancy % 2) > 0};
|
|
431
|
-
utils.noOccupancySince(msg.endpoint,
|
|
431
|
+
utils.noOccupancySince(msg.endpoint, options, publish, payload.occupancy ? 'stop' : 'start');
|
|
432
432
|
return payload;
|
|
433
433
|
}
|
|
434
434
|
},
|
|
@@ -464,7 +464,7 @@ const converters = {
|
|
|
464
464
|
}
|
|
465
465
|
|
|
466
466
|
const payload = {occupancy: true};
|
|
467
|
-
utils.noOccupancySince(msg.endpoint,
|
|
467
|
+
utils.noOccupancySince(msg.endpoint, options, publish, 'start');
|
|
468
468
|
return payload;
|
|
469
469
|
},
|
|
470
470
|
},
|
|
@@ -2790,6 +2790,33 @@ const converters = {
|
|
|
2790
2790
|
}
|
|
2791
2791
|
},
|
|
2792
2792
|
},
|
|
2793
|
+
livolo_new_switch_state_4gang: {
|
|
2794
|
+
cluster: 'genPowerCfg',
|
|
2795
|
+
type: ['raw'],
|
|
2796
|
+
convert: (model, msg, publish, options, meta) => {
|
|
2797
|
+
const stateHeader = Buffer.from([122, 209]);
|
|
2798
|
+
if (msg.data.indexOf(stateHeader) === 0) {
|
|
2799
|
+
if (msg.data[10] === 7) {
|
|
2800
|
+
const status = msg.data[14];
|
|
2801
|
+
return {
|
|
2802
|
+
state_left: status & 1 ? 'ON' : 'OFF',
|
|
2803
|
+
state_right: status & 2 ? 'ON' : 'OFF',
|
|
2804
|
+
state_bottom_left: status & 4 ? 'ON' : 'OFF',
|
|
2805
|
+
state_bottom_right: status & 8 ? 'ON' : 'OFF',
|
|
2806
|
+
};
|
|
2807
|
+
}
|
|
2808
|
+
if (msg.data[10] === 13) {
|
|
2809
|
+
const status = msg.data[13];
|
|
2810
|
+
return {
|
|
2811
|
+
state_left: status & 1 ? 'ON' : 'OFF',
|
|
2812
|
+
state_right: status & 2 ? 'ON' : 'OFF',
|
|
2813
|
+
state_bottom_left: status & 4 ? 'ON' : 'OFF',
|
|
2814
|
+
state_bottom_right: status & 8 ? 'ON' : 'OFF',
|
|
2815
|
+
};
|
|
2816
|
+
}
|
|
2817
|
+
}
|
|
2818
|
+
},
|
|
2819
|
+
},
|
|
2793
2820
|
livolo_curtain_switch_state: {
|
|
2794
2821
|
cluster: 'genPowerCfg',
|
|
2795
2822
|
type: ['raw'],
|
|
@@ -2949,7 +2976,8 @@ const converters = {
|
|
|
2949
2976
|
meta.device.modelID = 'TI0001-socket';
|
|
2950
2977
|
meta.device.save();
|
|
2951
2978
|
}
|
|
2952
|
-
|
|
2979
|
+
// No need to detect this switches, will be done by universal procedure
|
|
2980
|
+
/* if (msg.data.includes(Buffer.from([19, 1, 0]), 13)) {
|
|
2953
2981
|
// new switch, hack
|
|
2954
2982
|
meta.device.modelID = 'TI0001-switch';
|
|
2955
2983
|
meta.device.save();
|
|
@@ -2958,7 +2986,7 @@ const converters = {
|
|
|
2958
2986
|
// new switch, hack
|
|
2959
2987
|
meta.device.modelID = 'TI0001-switch-2gang';
|
|
2960
2988
|
meta.device.save();
|
|
2961
|
-
}
|
|
2989
|
+
}*/
|
|
2962
2990
|
if (msg.data.includes(Buffer.from([19, 5, 0]), 13)) {
|
|
2963
2991
|
if (meta.logger) meta.logger.debug('Detected Livolo Curtain Switch');
|
|
2964
2992
|
// curtain switch, hack
|
|
@@ -5231,40 +5259,8 @@ const converters = {
|
|
|
5231
5259
|
type: ['attributeReport', 'readResponse'],
|
|
5232
5260
|
options: [exposes.options.precision('temperature'), exposes.options.calibration('temperature')],
|
|
5233
5261
|
convert: (model, msg, publish, options, meta) => {
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
const payload = {};
|
|
5237
|
-
|
|
5238
|
-
if (data.hasOwnProperty('100')) {
|
|
5239
|
-
if (['QBKG03LM', 'QBKG12LM', 'LLKZMK11LM'].includes(model.model)) {
|
|
5240
|
-
const mapping = model.model === 'LLKZMK11LM' ? ['l1', 'l2'] : ['left', 'right'];
|
|
5241
|
-
payload[`state_${mapping[0]}`] = data['100'] === 1 ? 'ON' : 'OFF';
|
|
5242
|
-
payload[`state_${mapping[1]}`] = data['101'] === 1 ? 'ON' : 'OFF';
|
|
5243
|
-
} else {
|
|
5244
|
-
payload.state = data['100'] === 1 ? 'ON' : 'OFF';
|
|
5245
|
-
}
|
|
5246
|
-
}
|
|
5247
|
-
|
|
5248
|
-
if (data.hasOwnProperty('152')) {
|
|
5249
|
-
payload.power = precisionRound(data['152'], 2);
|
|
5250
|
-
}
|
|
5251
|
-
|
|
5252
|
-
if (data.hasOwnProperty('149')) {
|
|
5253
|
-
// Consumption is deprecated
|
|
5254
|
-
payload.consumption = precisionRound(data['149'], 2);
|
|
5255
|
-
payload.energy = precisionRound(data['149'], 2);
|
|
5256
|
-
}
|
|
5257
|
-
|
|
5258
|
-
if (data.hasOwnProperty('3')) {
|
|
5259
|
-
payload.temperature = calibrateAndPrecisionRoundOptions(data['3'], options, 'temperature');
|
|
5260
|
-
}
|
|
5261
|
-
|
|
5262
|
-
if (data.hasOwnProperty('150')) {
|
|
5263
|
-
payload.voltage = precisionRound(data['150'] * 0.1, 1);
|
|
5264
|
-
}
|
|
5265
|
-
|
|
5266
|
-
return payload;
|
|
5267
|
-
}
|
|
5262
|
+
const payload = xiaomi.numericAttributes2Payload(msg, meta, model, options, msg.data);
|
|
5263
|
+
return payload;
|
|
5268
5264
|
},
|
|
5269
5265
|
},
|
|
5270
5266
|
xiaomi_basic_raw: {
|
|
@@ -7730,6 +7726,8 @@ const converters = {
|
|
|
7730
7726
|
case tuya.dataPoints.trsIlluminanceLux:
|
|
7731
7727
|
result = {illuminance_lux: value};
|
|
7732
7728
|
break;
|
|
7729
|
+
case tuya.dataPoints.trsDetectionData: // Ignore this, function of this DP is unknown at the moment!
|
|
7730
|
+
break;
|
|
7733
7731
|
default:
|
|
7734
7732
|
meta.logger.warn(`fromZigbee.tuya_radar_sensor: NOT RECOGNIZED DP ${dp} with data ${JSON.stringify(dpValue)}`);
|
|
7735
7733
|
}
|
package/converters/toZigbee.js
CHANGED
|
@@ -1599,13 +1599,23 @@ const converters = {
|
|
|
1599
1599
|
}
|
|
1600
1600
|
|
|
1601
1601
|
const state = value.toLowerCase();
|
|
1602
|
+
let oldstate = 1;
|
|
1603
|
+
if (state === 'on') {
|
|
1604
|
+
oldstate = 108;
|
|
1605
|
+
}
|
|
1606
|
+
let channel = 1.0;
|
|
1602
1607
|
const postfix = meta.endpoint_name || 'left';
|
|
1603
1608
|
await entity.command('genOnOff', 'toggle', {}, {transactionSequenceNumber: 0});
|
|
1604
1609
|
const payloadOn = {0x0001: {value: Buffer.from([1, 0, 0, 0, 0, 0, 0, 0]), type: 1}};
|
|
1605
1610
|
const payloadOff = {0x0001: {value: Buffer.from([0, 0, 0, 0, 0, 0, 0, 0]), type: 1}};
|
|
1606
1611
|
const payloadOnRight = {0x0001: {value: Buffer.from([2, 0, 0, 0, 0, 0, 0, 0]), type: 2}};
|
|
1607
1612
|
const payloadOffRight = {0x0001: {value: Buffer.from([0, 0, 0, 0, 0, 0, 0, 0]), type: 2}};
|
|
1613
|
+
const payloadOnBottomLeft = {0x0001: {value: Buffer.from([4, 0, 0, 0, 0, 0, 0, 0]), type: 4}};
|
|
1614
|
+
const payloadOffBottomLeft = {0x0001: {value: Buffer.from([0, 0, 0, 0, 0, 0, 0, 0]), type: 4}};
|
|
1615
|
+
const payloadOnBottomRight = {0x0001: {value: Buffer.from([8, 0, 0, 0, 0, 0, 0, 0]), type: 136}};
|
|
1616
|
+
const payloadOffBottomRight = {0x0001: {value: Buffer.from([0, 0, 0, 0, 0, 0, 0, 0]), type: 136}};
|
|
1608
1617
|
if (postfix === 'left') {
|
|
1618
|
+
await entity.command('genLevelCtrl', 'moveToLevelWithOnOff', {level: oldstate, transtime: channel});
|
|
1609
1619
|
await entity.write('genPowerCfg', (state === 'on') ? payloadOn : payloadOff,
|
|
1610
1620
|
{
|
|
1611
1621
|
manufacturerCode: 0x1ad2, disableDefaultResponse: true, disableResponse: true,
|
|
@@ -1613,12 +1623,28 @@ const converters = {
|
|
|
1613
1623
|
});
|
|
1614
1624
|
return {state: {state_left: value.toUpperCase()}, readAfterWriteTime: 250};
|
|
1615
1625
|
} else if (postfix === 'right') {
|
|
1626
|
+
channel = 2.0;
|
|
1627
|
+
await entity.command('genLevelCtrl', 'moveToLevelWithOnOff', {level: oldstate, transtime: channel});
|
|
1616
1628
|
await entity.write('genPowerCfg', (state === 'on') ? payloadOnRight : payloadOffRight,
|
|
1617
1629
|
{
|
|
1618
1630
|
manufacturerCode: 0x1ad2, disableDefaultResponse: true, disableResponse: true,
|
|
1619
1631
|
reservedBits: 3, direction: 1, transactionSequenceNumber: 0xe9,
|
|
1620
1632
|
});
|
|
1621
1633
|
return {state: {state_right: value.toUpperCase()}, readAfterWriteTime: 250};
|
|
1634
|
+
} else if (postfix === 'bottom_right') {
|
|
1635
|
+
await entity.write('genPowerCfg', (state === 'on') ? payloadOnBottomRight : payloadOffBottomRight,
|
|
1636
|
+
{
|
|
1637
|
+
manufacturerCode: 0x1ad2, disableDefaultResponse: true, disableResponse: true,
|
|
1638
|
+
reservedBits: 3, direction: 1, transactionSequenceNumber: 0xe9,
|
|
1639
|
+
});
|
|
1640
|
+
return {state: {state_bottom_right: value.toUpperCase()}, readAfterWriteTime: 250};
|
|
1641
|
+
} else if (postfix === 'bottom_left') {
|
|
1642
|
+
await entity.write('genPowerCfg', (state === 'on') ? payloadOnBottomLeft : payloadOffBottomLeft,
|
|
1643
|
+
{
|
|
1644
|
+
manufacturerCode: 0x1ad2, disableDefaultResponse: true, disableResponse: true,
|
|
1645
|
+
reservedBits: 3, direction: 1, transactionSequenceNumber: 0xe9,
|
|
1646
|
+
});
|
|
1647
|
+
return {state: {state_bottom_left: value.toUpperCase()}, readAfterWriteTime: 250};
|
|
1622
1648
|
}
|
|
1623
1649
|
return {state: {state: value.toUpperCase()}, readAfterWriteTime: 250};
|
|
1624
1650
|
},
|
|
@@ -2005,7 +2031,7 @@ const converters = {
|
|
|
2005
2031
|
await entity.read('genBasic', [0x0033], manufacturerOptions.hue);
|
|
2006
2032
|
},
|
|
2007
2033
|
},
|
|
2008
|
-
|
|
2034
|
+
aqara_motion_sensitivity: {
|
|
2009
2035
|
key: ['motion_sensitivity'],
|
|
2010
2036
|
convertSet: async (entity, key, value, meta) => {
|
|
2011
2037
|
const lookup = {'low': 1, 'medium': 2, 'high': 3};
|
|
@@ -2048,6 +2074,12 @@ const converters = {
|
|
|
2048
2074
|
await entity.read('aqaraOpple', [0x0146], manufacturerOptions.xiaomi);
|
|
2049
2075
|
},
|
|
2050
2076
|
},
|
|
2077
|
+
RTCZCGQ11LM_reset_nopresence_status: {
|
|
2078
|
+
key: ['reset_nopresence_status'],
|
|
2079
|
+
convertSet: async (entity, key, value, meta) => {
|
|
2080
|
+
await entity.write('aqaraOpple', {0x0157: {value: 1, type: 0x20}}, manufacturerOptions.xiaomi);
|
|
2081
|
+
},
|
|
2082
|
+
},
|
|
2051
2083
|
ZigUP_lock: {
|
|
2052
2084
|
key: ['led'],
|
|
2053
2085
|
convertSet: async (entity, key, value, meta) => {
|
|
@@ -13,7 +13,7 @@ const tzLocal = {
|
|
|
13
13
|
convertSet: async (entity, key, value, meta) => {
|
|
14
14
|
const state = value.toLowerCase();
|
|
15
15
|
utils.validateValue(state, ['toggle', 'off', 'on']);
|
|
16
|
-
const endpoint = meta.
|
|
16
|
+
const endpoint = meta.device.getEndpoint(3);
|
|
17
17
|
await endpoint.command('genOnOff', state, {});
|
|
18
18
|
return {state: {backlight_led: state.toUpperCase()}};
|
|
19
19
|
},
|
|
@@ -184,8 +184,9 @@ module.exports = [
|
|
|
184
184
|
fromZigbee: [fz.identify, fz.on_off, fz.electrical_measurement],
|
|
185
185
|
exposes: [e.switch().withEndpoint('left'), e.switch().withEndpoint('right'),
|
|
186
186
|
e.power().withEndpoint('left'), e.power().withEndpoint('right'),
|
|
187
|
-
exposes.
|
|
188
|
-
|
|
187
|
+
exposes.numeric('brightness', ea.ALL).withValueMin(0).withValueMax(254)
|
|
188
|
+
.withDescription('Brightness of this backlight LED')],
|
|
189
|
+
toZigbee: [tz.light_onoff_brightness],
|
|
189
190
|
meta: {multiEndpoint: true},
|
|
190
191
|
endpoint: (device) => {
|
|
191
192
|
return {'left': 1, 'right': 2};
|
package/devices/lidl.js
CHANGED
|
@@ -446,6 +446,8 @@ module.exports = [
|
|
|
446
446
|
extend: extend.switch(),
|
|
447
447
|
meta: {multiEndpoint: true},
|
|
448
448
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
449
|
+
const endpoint = device.getEndpoint(1);
|
|
450
|
+
await endpoint.read('genBasic', ['manufacturerName', 'zclVersion', 'appVersion', 'modelId', 'powerSource', 0xfffe]);
|
|
449
451
|
for (const ID of [1, 2, 3]) {
|
|
450
452
|
await reporting.bind(device.getEndpoint(ID), coordinatorEndpoint, ['genOnOff']);
|
|
451
453
|
}
|
package/devices/livolo.js
CHANGED
|
@@ -20,13 +20,18 @@ module.exports = [
|
|
|
20
20
|
{
|
|
21
21
|
zigbeeModel: ['TI0001 '],
|
|
22
22
|
model: 'TI0001',
|
|
23
|
-
description: 'Zigbee switch (1
|
|
23
|
+
description: 'Zigbee switch (1, 2, 3, 4 gang)',
|
|
24
24
|
vendor: 'Livolo',
|
|
25
|
-
exposes: [
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
exposes: [
|
|
26
|
+
e.switch().withEndpoint('left'),
|
|
27
|
+
e.switch().withEndpoint('right'),
|
|
28
|
+
e.switch().withEndpoint('bottom_left'),
|
|
29
|
+
e.switch().withEndpoint('bottom_right'),
|
|
30
|
+
],
|
|
31
|
+
fromZigbee: [fz.livolo_switch_state, fz.livolo_switch_state_raw, fz.livolo_new_switch_state_4gang],
|
|
32
|
+
toZigbee: [tz.livolo_socket_switch_on_off],
|
|
28
33
|
endpoint: (device) => {
|
|
29
|
-
return {'left': 6, 'right': 6};
|
|
34
|
+
return {'left': 6, 'right': 6, 'bottom_left': 6, 'bottom_right': 6};
|
|
30
35
|
},
|
|
31
36
|
configure: poll,
|
|
32
37
|
onEvent: async (type, data, device) => {
|
|
@@ -41,6 +46,18 @@ module.exports = [
|
|
|
41
46
|
globalStore.putValue(device, 'interval', interval);
|
|
42
47
|
}
|
|
43
48
|
}
|
|
49
|
+
if (data.cluster === 'genPowerCfg' && data.type === 'raw') {
|
|
50
|
+
const dp = data.data[10];
|
|
51
|
+
if (data.data[0] === 0x7a && data.data[1] === 0xd1) {
|
|
52
|
+
const endpoint = device.getEndpoint(6);
|
|
53
|
+
if (dp === 0x01) {
|
|
54
|
+
const options = {manufacturerCode: 0x1ad2, disableDefaultResponse: true, disableResponse: true,
|
|
55
|
+
reservedBits: 3, direction: 1, writeUndiv: true};
|
|
56
|
+
const payload = {0x2002: {value: [0, 0, 0, 0, 0, 0, 0], type: 0x0e}};
|
|
57
|
+
await endpoint.readResponse('genPowerCfg', 0xe9, payload, options);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
44
61
|
},
|
|
45
62
|
},
|
|
46
63
|
{
|
package/devices/lonsonho.js
CHANGED
|
@@ -197,6 +197,18 @@ module.exports = [
|
|
|
197
197
|
await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
|
|
198
198
|
},
|
|
199
199
|
},
|
|
200
|
+
{
|
|
201
|
+
fingerprint: [{modelID: 'TS130F', manufacturerName: '_TZ3000_zirycpws'}],
|
|
202
|
+
model: 'QS-Zigbee-C03',
|
|
203
|
+
vendor: 'Lonsonho',
|
|
204
|
+
description: 'Curtain/blind motor controller',
|
|
205
|
+
fromZigbee: [fz.cover_position_tilt, fz.tuya_cover_options],
|
|
206
|
+
toZigbee: [tz.cover_state, tz.cover_position_tilt, tz.tuya_cover_calibration, tz.tuya_cover_reversal],
|
|
207
|
+
meta: {coverInverted: true},
|
|
208
|
+
exposes: [e.cover_position(), exposes.enum('moving', ea.STATE, ['UP', 'STOP', 'DOWN']),
|
|
209
|
+
exposes.binary('calibration', ea.ALL, 'ON', 'OFF'), exposes.binary('motor_reversal', ea.ALL, 'ON', 'OFF'),
|
|
210
|
+
exposes.numeric('calibration_time', ea.STATE).withUnit('S').withDescription('Calibration time')],
|
|
211
|
+
},
|
|
200
212
|
{
|
|
201
213
|
fingerprint: [{modelID: 'TS110E', manufacturerName: '_TZ3210_zxbtub8r'}],
|
|
202
214
|
model: 'TS110E_1gang',
|
package/devices/philips.js
CHANGED
|
@@ -2239,6 +2239,13 @@ module.exports = [
|
|
|
2239
2239
|
meta: {turnsOffAtBrightness1: true},
|
|
2240
2240
|
extend: hueExtend.light_onoff_brightness(),
|
|
2241
2241
|
},
|
|
2242
|
+
{
|
|
2243
|
+
zigbeeModel: ['929003055201'],
|
|
2244
|
+
model: '929003055201',
|
|
2245
|
+
vendor: 'Philips',
|
|
2246
|
+
description: 'Hue Being',
|
|
2247
|
+
extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
|
|
2248
|
+
},
|
|
2242
2249
|
{
|
|
2243
2250
|
zigbeeModel: ['1743630P7', '1743630V7'],
|
|
2244
2251
|
model: '17436/30/P7',
|
|
@@ -2785,4 +2792,13 @@ module.exports = [
|
|
|
2785
2792
|
extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
|
|
2786
2793
|
ota: ota.zigbeeOTA,
|
|
2787
2794
|
},
|
|
2795
|
+
{
|
|
2796
|
+
zigbeeModel: ['LWS002'],
|
|
2797
|
+
model: '046677562229',
|
|
2798
|
+
vendor: 'Philips',
|
|
2799
|
+
description: 'Hue White PAR20 with Bluetooth',
|
|
2800
|
+
meta: {turnsOffAtBrightness1: true},
|
|
2801
|
+
extend: hueExtend.light_onoff_brightness(),
|
|
2802
|
+
ota: ota.zigbeeOTA,
|
|
2803
|
+
},
|
|
2788
2804
|
];
|
package/devices/qmotion.js
CHANGED
|
@@ -3,6 +3,7 @@ const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/lega
|
|
|
3
3
|
const tz = require('../converters/toZigbee');
|
|
4
4
|
const e = exposes.presets;
|
|
5
5
|
const ea = exposes.access;
|
|
6
|
+
const reporting = require('../lib/reporting');
|
|
6
7
|
|
|
7
8
|
module.exports = [
|
|
8
9
|
{
|
|
@@ -19,8 +20,14 @@ module.exports = [
|
|
|
19
20
|
model: 'HDM40PV620',
|
|
20
21
|
vendor: 'Qmotion',
|
|
21
22
|
description: 'Motorized roller blind',
|
|
22
|
-
fromZigbee: [fz.identify],
|
|
23
|
+
fromZigbee: [fz.identify, fz.cover_position_tilt, fz.battery],
|
|
23
24
|
toZigbee: [tz.cover_state, tz.cover_position_tilt],
|
|
24
|
-
exposes: [e.cover_position()],
|
|
25
|
+
exposes: [e.cover_position(), e.battery()],
|
|
26
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
27
|
+
const endpoint = device.getEndpoint(1);
|
|
28
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'closuresWindowCovering']);
|
|
29
|
+
await reporting.batteryPercentageRemaining(endpoint);
|
|
30
|
+
await reporting.currentPositionLiftPercentage(endpoint);
|
|
31
|
+
},
|
|
25
32
|
},
|
|
26
33
|
];
|
package/devices/slv.js
CHANGED
|
@@ -17,4 +17,11 @@ module.exports = [
|
|
|
17
17
|
toZigbee: [],
|
|
18
18
|
exposes: [],
|
|
19
19
|
},
|
|
20
|
+
{
|
|
21
|
+
zigbeeModel: ['ZBT-RGBWLight-AR0844'],
|
|
22
|
+
model: '1001923',
|
|
23
|
+
vendor: 'SLV',
|
|
24
|
+
description: 'VALETO LED GU10 RGBW',
|
|
25
|
+
extend: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 556]}),
|
|
26
|
+
},
|
|
20
27
|
];
|
package/devices/tuya.js
CHANGED
|
@@ -234,6 +234,7 @@ module.exports = [
|
|
|
234
234
|
{modelID: 'TS0505B', manufacturerName: '_TZ3000_tza2vjxx'},
|
|
235
235
|
{modelID: 'TS0505B', manufacturerName: '_TZ3210_k1pe6ibm'},
|
|
236
236
|
{modelID: 'TS0505B', manufacturerName: '_TZ3210_bfwvfyx1'},
|
|
237
|
+
{modelID: 'TS0505B', manufacturerName: '_TZ3210_leyz4rju'},
|
|
237
238
|
{modelID: 'TS0505B', manufacturerName: '_TZ3210_jd3z4yig'}],
|
|
238
239
|
model: 'TS0505B',
|
|
239
240
|
vendor: 'TuYa',
|
package/devices/woox.js
CHANGED
|
@@ -13,10 +13,10 @@ module.exports = [
|
|
|
13
13
|
model: 'R7060',
|
|
14
14
|
vendor: 'Woox',
|
|
15
15
|
description: 'Smart garden irrigation control',
|
|
16
|
-
fromZigbee: [fz.on_off, fz.ignore_tuya_set_time, fz.ignore_basic_report, fz.woox_R7060],
|
|
16
|
+
fromZigbee: [fz.on_off, fz.ignore_tuya_set_time, fz.ignore_basic_report, fz.woox_R7060, fz.battery],
|
|
17
17
|
toZigbee: [tz.on_off],
|
|
18
18
|
onEvent: tuya.onEventSetTime,
|
|
19
|
-
exposes: [e.switch()],
|
|
19
|
+
exposes: [e.switch(), e.battery(), e.battery_voltage()],
|
|
20
20
|
meta: {disableDefaultResponse: true},
|
|
21
21
|
},
|
|
22
22
|
{
|
package/devices/xiaomi.js
CHANGED
|
@@ -893,7 +893,7 @@ module.exports = [
|
|
|
893
893
|
vendor: 'Xiaomi',
|
|
894
894
|
description: 'Aqara high precision motion sensor',
|
|
895
895
|
fromZigbee: [fz.RTCGQ13LM_occupancy, fz.aqara_opple, fz.battery],
|
|
896
|
-
toZigbee: [tz.aqara_detection_interval, tz.
|
|
896
|
+
toZigbee: [tz.aqara_detection_interval, tz.aqara_motion_sensitivity],
|
|
897
897
|
exposes: [e.occupancy(), exposes.enum('motion_sensitivity', ea.ALL, ['low', 'medium', 'high']),
|
|
898
898
|
exposes.numeric('detection_interval', ea.ALL).withValueMin(2).withValueMax(65535).withUnit('s')
|
|
899
899
|
.withDescription('Time interval for detecting actions'), e.battery()],
|
|
@@ -910,9 +910,10 @@ module.exports = [
|
|
|
910
910
|
zigbeeModel: ['lumi.motion.ac01'],
|
|
911
911
|
model: 'RTCZCGQ11LM',
|
|
912
912
|
vendor: 'Xiaomi',
|
|
913
|
-
description: 'Aqara
|
|
913
|
+
description: 'Aqara presence detector FP1 (regions not supported for now)',
|
|
914
914
|
fromZigbee: [fz.aqara_opple],
|
|
915
|
-
toZigbee: [tz.RTCZCGQ11LM_presence, tz.RTCZCGQ11LM_monitoring_mode, tz.RTCZCGQ11LM_approach_distance
|
|
915
|
+
toZigbee: [tz.RTCZCGQ11LM_presence, tz.RTCZCGQ11LM_monitoring_mode, tz.RTCZCGQ11LM_approach_distance,
|
|
916
|
+
tz.aqara_motion_sensitivity, tz.RTCZCGQ11LM_reset_nopresence_status],
|
|
916
917
|
exposes: [e.presence().withAccess(ea.STATE_GET),
|
|
917
918
|
exposes.enum('presence_event', ea.STATE, ['enter', 'leave', 'left_enter', 'right_leave', 'right_enter', 'left_leave',
|
|
918
919
|
'approach', 'away']).withDescription('Presence events: "enter", "leave", "left_enter", "right_leave", ' +
|
|
@@ -921,9 +922,14 @@ module.exports = [
|
|
|
921
922
|
'without considering right and left sides'),
|
|
922
923
|
exposes.enum('approach_distance', ea.ALL, ['far', 'medium', 'near']).withDescription('The distance at which the ' +
|
|
923
924
|
'sensor detects approaching'),
|
|
924
|
-
exposes.
|
|
925
|
+
exposes.enum('motion_sensitivity', ea.ALL, ['low', 'medium', 'high']).withDescription('Different sensitivities ' +
|
|
926
|
+
'means different static human body recognition rate and response speed of occupied'),
|
|
927
|
+
exposes.enum('reset_nopresence_status', ea.SET, ['Reset']).withDescription('Reset the status of no presence'),
|
|
928
|
+
exposes.numeric('power_outage_count', ea.STATE).withDescription('Number of power outages (since last pairing)'),
|
|
929
|
+
e.temperature()],
|
|
925
930
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
926
931
|
const endpoint = device.getEndpoint(1);
|
|
932
|
+
await endpoint.read('aqaraOpple', [0x010c], {manufacturerCode: 0x115f});
|
|
927
933
|
await endpoint.read('aqaraOpple', [0x0142], {manufacturerCode: 0x115f});
|
|
928
934
|
await endpoint.read('aqaraOpple', [0x0144], {manufacturerCode: 0x115f});
|
|
929
935
|
await endpoint.read('aqaraOpple', [0x0146], {manufacturerCode: 0x115f});
|
|
@@ -1298,7 +1304,7 @@ module.exports = [
|
|
|
1298
1304
|
endpoint: (device) => {
|
|
1299
1305
|
return {'l1': 1, 'l2': 2};
|
|
1300
1306
|
},
|
|
1301
|
-
exposes: [e.power().withAccess(ea.STATE_GET), e.energy(), e.temperature(), e.voltage().withAccess(ea.STATE),
|
|
1307
|
+
exposes: [e.power().withAccess(ea.STATE_GET), e.energy(), e.temperature(), e.voltage().withAccess(ea.STATE), e.current(),
|
|
1302
1308
|
e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'),
|
|
1303
1309
|
exposes.binary('interlock', ea.STATE_SET, true, false)
|
|
1304
1310
|
.withDescription('Enabling prevents both relais being on at the same time')],
|
package/devices/zemismart.js
CHANGED
|
@@ -125,7 +125,10 @@ module.exports = [
|
|
|
125
125
|
},
|
|
126
126
|
},
|
|
127
127
|
{
|
|
128
|
-
fingerprint: [
|
|
128
|
+
fingerprint: [
|
|
129
|
+
{modelID: 'TS0601', manufacturerName: '_TZE200_iossyxra'},
|
|
130
|
+
{modelID: 'TS0601', manufacturerName: '_TZE200_gubdgai2'},
|
|
131
|
+
],
|
|
129
132
|
model: 'ZM-AM02_cover',
|
|
130
133
|
vendor: 'Zemismart',
|
|
131
134
|
description: 'Zigbee/RF curtain converter',
|
package/lib/ota/zigbeeOTA.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const url = 'https://raw.githubusercontent.com/Koenkk/zigbee-OTA/master/index.json';
|
|
2
|
-
const assert = require('assert');
|
|
3
2
|
const common = require('./common');
|
|
4
3
|
const axios = common.getAxios();
|
|
5
4
|
const fs = require('fs');
|
|
@@ -110,7 +109,10 @@ async function getImageMeta(current, logger, device) {
|
|
|
110
109
|
(!i.minFileVersion || current.fileVersion >= i.minFileVersion) && (!i.maxFileVersion || current.fileVersion <= i.maxFileVersion) &&
|
|
111
110
|
(!i.modelId || i.modelId === modelId) && (!i.manufacturerName || i.manufacturerName.includes(manufacturerName)));
|
|
112
111
|
|
|
113
|
-
|
|
112
|
+
if (!image) {
|
|
113
|
+
throw new Error(`No image available for imageType '${imageType}'`);
|
|
114
|
+
}
|
|
115
|
+
|
|
114
116
|
return {
|
|
115
117
|
fileVersion: image.fileVersion,
|
|
116
118
|
fileSize: image.fileSize,
|
package/lib/tuya.js
CHANGED
package/lib/utils.js
CHANGED
|
@@ -397,13 +397,12 @@ function extendDevice(deviceConfigs, modelName, adjustments) {
|
|
|
397
397
|
return {...baseDevice, ...adjustments};
|
|
398
398
|
}
|
|
399
399
|
|
|
400
|
-
function noOccupancySince(endpoint,
|
|
400
|
+
function noOccupancySince(endpoint, options, publish, action) {
|
|
401
401
|
if (options && options.no_occupancy_since) {
|
|
402
402
|
if (action == 'start') {
|
|
403
403
|
globalStore.getValue(endpoint, 'no_occupancy_since_timers', []).forEach((t) => clearTimeout(t));
|
|
404
404
|
globalStore.putValue(endpoint, 'no_occupancy_since_timers', []);
|
|
405
405
|
|
|
406
|
-
newPayload.no_occupancy_since = 0;
|
|
407
406
|
options.no_occupancy_since.forEach((since) => {
|
|
408
407
|
const timer = setTimeout(() => {
|
|
409
408
|
publish({no_occupancy_since: since});
|
package/lib/xiaomi.js
CHANGED
|
@@ -168,7 +168,7 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
|
|
|
168
168
|
payload.switch_type = {1: 'toggle', 2: 'momentary'}[value];
|
|
169
169
|
break;
|
|
170
170
|
case '100':
|
|
171
|
-
if (['QBKG20LM', 'QBKG31LM', 'QBKG39LM', 'QBKG41LM', 'QBCZ15LM', 'LLKZMK11LM'].includes(model.model)) {
|
|
171
|
+
if (['QBKG20LM', 'QBKG31LM', 'QBKG39LM', 'QBKG41LM', 'QBCZ15LM', 'LLKZMK11LM', 'QBKG12LM', 'QBKG03LM'].includes(model.model)) {
|
|
172
172
|
let mapping;
|
|
173
173
|
switch (model.model) {
|
|
174
174
|
case 'QBCZ15LM':
|
|
@@ -191,7 +191,7 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
|
|
|
191
191
|
}
|
|
192
192
|
break;
|
|
193
193
|
case '101':
|
|
194
|
-
if (['QBKG20LM', 'QBKG31LM', 'QBKG39LM', 'QBKG41LM', 'QBCZ15LM', 'QBKG25LM', 'QBKG34LM', 'LLKZMK11LM']
|
|
194
|
+
if (['QBKG20LM', 'QBKG31LM', 'QBKG39LM', 'QBKG41LM', 'QBCZ15LM', 'QBKG25LM', 'QBKG34LM', 'LLKZMK11LM', 'QBKG12LM', 'QBKG03LM']
|
|
195
195
|
.includes(model.model)) {
|
|
196
196
|
let mapping;
|
|
197
197
|
switch (model.model) {
|
|
@@ -213,19 +213,25 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
|
|
|
213
213
|
payload.illuminance = calibrateAndPrecisionRoundOptions(value, options, 'illuminance');
|
|
214
214
|
} else if (['ZNJLBL01LM'].includes(model.model)) {
|
|
215
215
|
payload.battery = value;
|
|
216
|
+
} else if (['RTCZCGQ11LM'].includes(model.model)) {
|
|
217
|
+
payload.presence = {0: false, 1: true, 255: null}[value];
|
|
216
218
|
}
|
|
217
219
|
break;
|
|
218
220
|
case '102':
|
|
219
221
|
if (['QBKG25LM', 'QBKG34LM'].includes(model.model)) {
|
|
220
222
|
payload.state_right = value === 1 ? 'ON' : 'OFF';
|
|
221
223
|
} else if (['RTCZCGQ11LM'].includes(model.model)) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
+
if (meta.device.applicationVersion < 50) {
|
|
225
|
+
payload.presence_event = {0: 'enter', 1: 'leave', 2: 'left_enter', 3: 'right_leave', 4: 'right_enter',
|
|
226
|
+
5: 'left_leave', 6: 'approach', 7: 'away', 255: null}[value];
|
|
227
|
+
} else {
|
|
228
|
+
payload.motion_sensitivity = {1: 'low', 2: 'medium', 3: 'high'}[value];
|
|
229
|
+
}
|
|
224
230
|
}
|
|
225
231
|
break;
|
|
226
232
|
case '103':
|
|
227
233
|
if (['RTCZCGQ11LM'].includes(model.model)) {
|
|
228
|
-
payload.monitoring_mode =
|
|
234
|
+
payload.monitoring_mode = {0: 'undirected', 1: 'left_right'}[value];
|
|
229
235
|
}
|
|
230
236
|
break;
|
|
231
237
|
case '105':
|
|
@@ -244,7 +250,11 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
|
|
|
244
250
|
payload.voltage = precisionRound(value * 0.1, 1); // 0x96
|
|
245
251
|
break;
|
|
246
252
|
case '151':
|
|
247
|
-
|
|
253
|
+
if (['LLKZMK11LM'].includes(model.model)) {
|
|
254
|
+
payload.current = precisionRound(value, 4);
|
|
255
|
+
} else {
|
|
256
|
+
payload.current = precisionRound(value * 0.001, 4);
|
|
257
|
+
}
|
|
248
258
|
break;
|
|
249
259
|
case '152':
|
|
250
260
|
payload.power = precisionRound(value, 2); // 0x98
|
|
@@ -284,7 +294,7 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
|
|
|
284
294
|
payload.detection_interval = value;
|
|
285
295
|
break;
|
|
286
296
|
case '268':
|
|
287
|
-
if (['RTCGQ13LM'].includes(model.model)) {
|
|
297
|
+
if (['RTCGQ13LM', 'RTCZCGQ11LM'].includes(model.model)) {
|
|
288
298
|
payload.motion_sensitivity = {1: 'low', 2: 'medium', 3: 'high'}[value];
|
|
289
299
|
} else if (['JT-BZ-01AQ/A'].includes(model.model)) {
|
|
290
300
|
payload.gas_sensitivity = {1: '15%LEL', 2: '10%LEL'}[value];
|
|
@@ -309,19 +319,25 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
|
|
|
309
319
|
payload.gas_density = value; // JT-BZ-01AQ/A
|
|
310
320
|
break;
|
|
311
321
|
case '322':
|
|
312
|
-
|
|
322
|
+
if (['RTCZCGQ11LM'].includes(model.model)) {
|
|
323
|
+
payload.presence = {0: false, 1: true, 255: null}[value];
|
|
324
|
+
}
|
|
313
325
|
break;
|
|
314
326
|
case '323':
|
|
315
|
-
|
|
316
|
-
|
|
327
|
+
if (['RTCZCGQ11LM'].includes(model.model)) {
|
|
328
|
+
payload.presence_event = {0: 'enter', 1: 'leave', 2: 'left_enter', 3: 'right_leave', 4: 'right_enter',
|
|
329
|
+
5: 'left_leave', 6: 'approach', 7: 'away'}[value];
|
|
330
|
+
}
|
|
317
331
|
break;
|
|
318
332
|
case '324':
|
|
319
|
-
|
|
320
|
-
|
|
333
|
+
if (['RTCZCGQ11LM'].includes(model.model)) {
|
|
334
|
+
payload.monitoring_mode = {0: 'undirected', 1: 'left_right'}[value];
|
|
335
|
+
}
|
|
321
336
|
break;
|
|
322
337
|
case '326':
|
|
323
|
-
|
|
324
|
-
|
|
338
|
+
if (['RTCZCGQ11LM'].includes(model.model)) {
|
|
339
|
+
payload.approach_distance = {0: 'far', 1: 'medium', 2: 'near'}[value];
|
|
340
|
+
}
|
|
325
341
|
break;
|
|
326
342
|
case '331':
|
|
327
343
|
payload.linkage_alarm = value === 1; // JT-BZ-01AQ/A
|
|
@@ -355,6 +371,12 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
|
|
|
355
371
|
case '1289':
|
|
356
372
|
payload.dimmer_mode = {3: 'rgbw', 1: 'dual_ct'}[value];
|
|
357
373
|
break;
|
|
374
|
+
case '65281':
|
|
375
|
+
{
|
|
376
|
+
const payload65281 = numericAttributes2Payload(msg, meta, model, options, value);
|
|
377
|
+
payload = {...payload, ...payload65281};
|
|
378
|
+
}
|
|
379
|
+
break;
|
|
358
380
|
case 'mode':
|
|
359
381
|
payload.operation_mode = ['command', 'event'][value];
|
|
360
382
|
break;
|
package/npm-shrinkwrap.json
CHANGED