zigbee-herdsman-converters 14.0.498 → 14.0.501
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 +33 -29
- package/converters/toZigbee.js +27 -4
- package/devices/awox.js +20 -1
- package/devices/danfoss.js +2 -1
- package/devices/miboxer.js +25 -0
- package/devices/neo.js +20 -11
- package/devices/nue_3a.js +6 -2
- package/devices/philips.js +9 -0
- package/devices/tuya.js +4 -5
- package/devices/xiaomi.js +13 -4
- package/devices/zemismart.js +9 -0
- package/lib/exposes.js +1 -1
- package/lib/tuya.js +4 -0
- package/lib/xiaomi.js +10 -4
- package/package.json +1 -1
package/converters/fromZigbee.js
CHANGED
|
@@ -2562,42 +2562,51 @@ const converters = {
|
|
|
2562
2562
|
const dpValue = tuya.firstDpValue(msg, meta, 'neo_nas_pd07');
|
|
2563
2563
|
const dp = dpValue.dp;
|
|
2564
2564
|
const value = tuya.getDataValue(dpValue);
|
|
2565
|
-
|
|
2566
|
-
|
|
2565
|
+
switch (dp) {
|
|
2566
|
+
case tuya.dataPoints.neoOccupancy:
|
|
2567
|
+
return {occupancy: value > 0 ? true : false};
|
|
2568
|
+
case 102:
|
|
2567
2569
|
return {
|
|
2568
2570
|
power_type: {0: 'battery_full', 1: 'battery_high', 2: 'battery_medium', 3: 'battery_low', 4: 'usb'}[value],
|
|
2569
2571
|
battery_low: value === 3,
|
|
2570
2572
|
};
|
|
2571
|
-
|
|
2573
|
+
case tuya.dataPoints.neoTamper:
|
|
2572
2574
|
return {tamper: value > 0 ? true : false};
|
|
2573
|
-
|
|
2575
|
+
case 104:
|
|
2574
2576
|
return {temperature: calibrateAndPrecisionRoundOptions(value / 10, options, 'temperature')};
|
|
2575
|
-
|
|
2577
|
+
case 105:
|
|
2576
2578
|
return {humidity: calibrateAndPrecisionRoundOptions(value, options, 'humidity')};
|
|
2577
|
-
|
|
2579
|
+
case tuya.dataPoints.neoMinTemp:
|
|
2578
2580
|
return {temperature_min: value};
|
|
2579
|
-
|
|
2581
|
+
case tuya.dataPoints.neoMaxTemp:
|
|
2580
2582
|
return {temperature_max: value};
|
|
2581
|
-
|
|
2583
|
+
case tuya.dataPoints.neoMinHumidity:
|
|
2582
2584
|
return {humidity_min: value};
|
|
2583
|
-
|
|
2585
|
+
case tuya.dataPoints.neoMaxHumidity:
|
|
2584
2586
|
return {humidity_max: value};
|
|
2585
|
-
|
|
2587
|
+
case tuya.dataPoints.neoTempScale:
|
|
2588
|
+
return {temperature_scale: value ? '°C' : '°F'};
|
|
2589
|
+
case 111:
|
|
2590
|
+
return {unknown_111: value ? 'ON' : 'OFF'};
|
|
2591
|
+
case 112:
|
|
2592
|
+
return {unknown_112: value ? 'ON' : 'OFF'};
|
|
2593
|
+
case tuya.dataPoints.neoTempHumidityAlarm:
|
|
2586
2594
|
return {alarm: {0: 'over_temperature', 1: 'over_humidity',
|
|
2587
2595
|
2: 'below_min_temperature', 3: 'below_min_humdity', 4: 'off'}[value]};
|
|
2588
|
-
|
|
2589
|
-
meta.logger.warn(`
|
|
2596
|
+
default: // Unknown code
|
|
2597
|
+
meta.logger.warn(`fz.neo_nas_pd07: Unhandled DP #${dp}: ${JSON.stringify(dpValue)}`);
|
|
2590
2598
|
}
|
|
2591
2599
|
},
|
|
2592
2600
|
},
|
|
2593
2601
|
neo_t_h_alarm: {
|
|
2594
2602
|
cluster: 'manuSpecificTuya',
|
|
2595
2603
|
type: ['commandDataReport', 'commandDataResponse'],
|
|
2604
|
+
options: [exposes.options.precision('temperature'), exposes.options.calibration('temperature'),
|
|
2605
|
+
exposes.options.precision('humidity'), exposes.options.calibration('humidity')],
|
|
2596
2606
|
convert: (model, msg, publish, options, meta) => {
|
|
2597
2607
|
const dpValue = tuya.firstDpValue(msg, meta, 'neo_t_h_alarm');
|
|
2598
2608
|
const dp = dpValue.dp;
|
|
2599
2609
|
const value = tuya.getDataValue(dpValue);
|
|
2600
|
-
|
|
2601
2610
|
switch (dp) {
|
|
2602
2611
|
case tuya.dataPoints.neoAlarm:
|
|
2603
2612
|
return {alarm: value};
|
|
@@ -2610,9 +2619,9 @@ const converters = {
|
|
|
2610
2619
|
case tuya.dataPoints.neoDuration: // 0x0267 [0,0,0,10] duration alarm in second
|
|
2611
2620
|
return {duration: value};
|
|
2612
2621
|
case tuya.dataPoints.neoTemp: // 0x0269 [0,0,0,240] temperature
|
|
2613
|
-
return {temperature: (value / 10)
|
|
2622
|
+
return {temperature: calibrateAndPrecisionRoundOptions((value / 10), options, 'temperature')};
|
|
2614
2623
|
case tuya.dataPoints.neoHumidity: // 0x026A [0,0,0,36] humidity
|
|
2615
|
-
return {humidity: value};
|
|
2624
|
+
return {humidity: calibrateAndPrecisionRoundOptions(value, options, 'humidity')};
|
|
2616
2625
|
case tuya.dataPoints.neoMinTemp: // 0x026B [0,0,0,18] min alarm temperature
|
|
2617
2626
|
return {temperature_min: value};
|
|
2618
2627
|
case tuya.dataPoints.neoMaxTemp: // 0x026C [0,0,0,27] max alarm temperature
|
|
@@ -2633,7 +2642,7 @@ const converters = {
|
|
|
2633
2642
|
case tuya.dataPoints.neoVolume: // 0x0474 [0]/[1]/[2] Volume 0-max, 2-low
|
|
2634
2643
|
return {volume: {2: 'low', 1: 'medium', 0: 'high'}[value]};
|
|
2635
2644
|
default: // Unknown code
|
|
2636
|
-
meta.logger.warn(`Unhandled DP #${dp}: ${JSON.stringify(dpValue)}`);
|
|
2645
|
+
meta.logger.warn(`fz.neo_t_h_alarm: Unhandled DP #${dp}: ${JSON.stringify(dpValue)}`);
|
|
2637
2646
|
}
|
|
2638
2647
|
},
|
|
2639
2648
|
},
|
|
@@ -4309,14 +4318,19 @@ const converters = {
|
|
|
4309
4318
|
// DP2: Smart Air Box: co2, Smart Air Housekeeper: MP25
|
|
4310
4319
|
case tuya.dataPoints.tuyaSabCO2:
|
|
4311
4320
|
if (meta.device.manufacturerName === '_TZE200_dwcarsat') {
|
|
4321
|
+
if (value === 0xaaab) return; // Ignore: https://github.com/Koenkk/zigbee2mqtt/issues/11033#issuecomment-1109808552
|
|
4312
4322
|
return {pm25: calibrateAndPrecisionRoundOptions(value, options, 'pm25')};
|
|
4313
4323
|
} else if (meta.device.manufacturerName === '_TZE200_ryfmq5rl') {
|
|
4314
|
-
return {formaldehyd: calibrateAndPrecisionRoundOptions(value, options, 'formaldehyd')};
|
|
4324
|
+
return {formaldehyd: calibrateAndPrecisionRoundOptions(value, options, 'formaldehyd') / 100};
|
|
4315
4325
|
} else {
|
|
4316
4326
|
return {co2: calibrateAndPrecisionRoundOptions(value, options, 'co2')};
|
|
4317
4327
|
}
|
|
4318
4328
|
case tuya.dataPoints.tuyaSabVOC:
|
|
4319
|
-
|
|
4329
|
+
if (meta.device.manufacturerName === '_TZE200_ryfmq5rl') {
|
|
4330
|
+
return {voc: calibrateAndPrecisionRoundOptions(value, options, 'voc') / 10};
|
|
4331
|
+
} else {
|
|
4332
|
+
return {voc: calibrateAndPrecisionRoundOptions(value, options, 'voc')};
|
|
4333
|
+
}
|
|
4320
4334
|
case tuya.dataPoints.tuyaSahkFormaldehyd:
|
|
4321
4335
|
return {formaldehyd: calibrateAndPrecisionRoundOptions(value, options, 'formaldehyd')};
|
|
4322
4336
|
default:
|
|
@@ -5872,19 +5886,9 @@ const converters = {
|
|
|
5872
5886
|
return result;
|
|
5873
5887
|
},
|
|
5874
5888
|
},
|
|
5875
|
-
xiaomi_curtain_acn002_position: {
|
|
5876
|
-
cluster: 'genAnalogOutput',
|
|
5877
|
-
type: ['attributeReport', 'readResponse'],
|
|
5878
|
-
options: [exposes.options.invert_cover()],
|
|
5879
|
-
convert: (model, msg, publish, options, meta) => {
|
|
5880
|
-
let position = precisionRound(msg.data['presentValue'], 2);
|
|
5881
|
-
position = options.invert_cover ? 100 - position : position;
|
|
5882
|
-
return {position: position};
|
|
5883
|
-
},
|
|
5884
|
-
},
|
|
5885
5889
|
xiaomi_curtain_acn002_status: {
|
|
5886
5890
|
cluster: 'genMultistateOutput',
|
|
5887
|
-
type: ['attributeReport'
|
|
5891
|
+
type: ['attributeReport'],
|
|
5888
5892
|
convert: (model, msg, publish, options, meta) => {
|
|
5889
5893
|
let running = false;
|
|
5890
5894
|
const data = msg.data;
|
package/converters/toZigbee.js
CHANGED
|
@@ -792,7 +792,7 @@ const converters = {
|
|
|
792
792
|
},
|
|
793
793
|
},
|
|
794
794
|
light_onoff_brightness: {
|
|
795
|
-
key: ['state', 'brightness', 'brightness_percent'],
|
|
795
|
+
key: ['state', 'brightness', 'brightness_percent', 'on_time'],
|
|
796
796
|
options: [exposes.options.transition()],
|
|
797
797
|
convertSet: async (entity, key, value, meta) => {
|
|
798
798
|
const {message} = meta;
|
|
@@ -2439,6 +2439,20 @@ const converters = {
|
|
|
2439
2439
|
} else {
|
|
2440
2440
|
await entity.command('closuresWindowCovering', 'stop', {}, utils.getOptions(meta.mapped, entity));
|
|
2441
2441
|
}
|
|
2442
|
+
|
|
2443
|
+
if (!['ZNCLDJ11LM', 'ZNJLBL01LM'].includes(meta.mapped.model)) {
|
|
2444
|
+
// The code below is originally added for ZNCLDJ11LM (Koenkk/zigbee2mqtt#4585).
|
|
2445
|
+
// However, in Koenkk/zigbee-herdsman-converters#4039 it was replaced by reading
|
|
2446
|
+
// directly from currentPositionLiftPercentage, so that device is excluded.
|
|
2447
|
+
// For ZNJLBL01LM, in Koenkk/zigbee-herdsman-converters#4163 the position is read
|
|
2448
|
+
// through onEvent each time the motor stops, so it becomes redundant, and the
|
|
2449
|
+
// device is excluded.
|
|
2450
|
+
// The code is left here to avoid breaking compatibility, ideally all devices using
|
|
2451
|
+
// this converter should be tested so the code can be adjusted/deleted.
|
|
2452
|
+
|
|
2453
|
+
// Xiaomi curtain does not send position update on stop, request this.
|
|
2454
|
+
await entity.read('genAnalogOutput', [0x0055]);
|
|
2455
|
+
}
|
|
2442
2456
|
} else {
|
|
2443
2457
|
const lookup = {'open': 100, 'close': 0, 'on': 100, 'off': 0};
|
|
2444
2458
|
|
|
@@ -5517,7 +5531,7 @@ const converters = {
|
|
|
5517
5531
|
},
|
|
5518
5532
|
},
|
|
5519
5533
|
neo_nas_pd07: {
|
|
5520
|
-
key: ['temperature_max', 'temperature_min', 'humidity_max', 'humidity_min'],
|
|
5534
|
+
key: ['temperature_max', 'temperature_min', 'humidity_max', 'humidity_min', 'temperature_scale', 'unknown_111', 'unknown_112'],
|
|
5521
5535
|
convertSet: async (entity, key, value, meta) => {
|
|
5522
5536
|
switch (key) {
|
|
5523
5537
|
case 'temperature_max':
|
|
@@ -5532,8 +5546,17 @@ const converters = {
|
|
|
5532
5546
|
case 'humidity_min':
|
|
5533
5547
|
await tuya.sendDataPointValue(entity, tuya.dataPoints.neoMinHumidity, value);
|
|
5534
5548
|
break;
|
|
5549
|
+
case 'temperature_scale':
|
|
5550
|
+
await tuya.sendDataPointBool(entity, tuya.dataPoints.neoTempScale, value === '°C');
|
|
5551
|
+
break;
|
|
5552
|
+
case 'unknown_111':
|
|
5553
|
+
await tuya.sendDataPointBool(entity, 111, value === 'ON');
|
|
5554
|
+
break;
|
|
5555
|
+
case 'unknown_112':
|
|
5556
|
+
await tuya.sendDataPointBool(entity, 112, value === 'ON');
|
|
5557
|
+
break;
|
|
5535
5558
|
default: // Unknown key
|
|
5536
|
-
throw new Error(`
|
|
5559
|
+
throw new Error(`tz.neo_nas_pd07: Unhandled key ${key}`);
|
|
5537
5560
|
}
|
|
5538
5561
|
},
|
|
5539
5562
|
},
|
|
@@ -5579,7 +5602,7 @@ const converters = {
|
|
|
5579
5602
|
await tuya.sendDataPointBool(entity, tuya.dataPoints.neoHumidityAlarm, value);
|
|
5580
5603
|
break;
|
|
5581
5604
|
default: // Unknown key
|
|
5582
|
-
throw new Error(`Unhandled key ${key}`);
|
|
5605
|
+
throw new Error(`tz.neo_t_h_alarm: Unhandled key ${key}`);
|
|
5583
5606
|
}
|
|
5584
5607
|
},
|
|
5585
5608
|
},
|
package/devices/awox.js
CHANGED
|
@@ -224,11 +224,30 @@ module.exports = [
|
|
|
224
224
|
},
|
|
225
225
|
],
|
|
226
226
|
},
|
|
227
|
+
{
|
|
228
|
+
type: 'Router', manufacturerName: 'AwoX', modelID: 'TLSR82xx', endpoints: [
|
|
229
|
+
{
|
|
230
|
+
ID: 1,
|
|
231
|
+
profileID: 260,
|
|
232
|
+
deviceID: 268,
|
|
233
|
+
inputClusters: [0, 3, 4, 5, 6, 8, 768, 4096, 64599, 10],
|
|
234
|
+
outputClusters: [6],
|
|
235
|
+
},
|
|
236
|
+
{ID: 242, profileID: 41440, deviceID: 97, inputClusters: [], outputClusters: [33]},
|
|
237
|
+
{
|
|
238
|
+
ID: 3,
|
|
239
|
+
profileID: 4751,
|
|
240
|
+
deviceID: 268,
|
|
241
|
+
inputClusters: [65360, 65361],
|
|
242
|
+
outputClusters: [65360, 65361],
|
|
243
|
+
},
|
|
244
|
+
],
|
|
245
|
+
},
|
|
227
246
|
],
|
|
228
247
|
model: '33957',
|
|
229
248
|
vendor: 'AwoX',
|
|
230
249
|
description: 'LED light with color temperature',
|
|
231
|
-
extend: extend.light_onoff_brightness_colortemp(),
|
|
250
|
+
extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 370]}),
|
|
232
251
|
},
|
|
233
252
|
{
|
|
234
253
|
fingerprint: [
|
package/devices/danfoss.js
CHANGED
|
@@ -79,7 +79,8 @@ module.exports = [
|
|
|
79
79
|
.withDescription('Mean radiator load for room calculated by gateway for load balancing purposes (-8000=undefined)')
|
|
80
80
|
.withValueMin(-8000).withValueMax(2000),
|
|
81
81
|
exposes.numeric('load_estimate', ea.STATE_GET)
|
|
82
|
-
.withDescription('Load estimate on this radiator')
|
|
82
|
+
.withDescription('Load estimate on this radiator')
|
|
83
|
+
.withValueMin(-8000).withValueMax(3600),
|
|
83
84
|
exposes.binary('preheat_status', ea.STATE_GET, true, false)
|
|
84
85
|
.withDescription('Specific for pre-heat running in Zigbee Weekly Schedule mode'),
|
|
85
86
|
exposes.enum('adaptation_run_status', ea.STATE_GET, ['none', 'in_progress', 'found', 'lost'])
|
package/devices/miboxer.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const exposes = require('../lib/exposes');
|
|
2
|
+
const fz = require('../converters/fromZigbee');
|
|
2
3
|
const tz = require('../converters/toZigbee');
|
|
3
4
|
const e = exposes.presets;
|
|
4
5
|
const ea = exposes.access;
|
|
@@ -47,4 +48,28 @@ module.exports = [
|
|
|
47
48
|
vendor: 'Miboxer',
|
|
48
49
|
extend: extend.light_onoff_brightness_colortemp_color({disableColorTempStartup: true, colorTempRange: [153, 500]}),
|
|
49
50
|
},
|
|
51
|
+
{
|
|
52
|
+
fingerprint: [{manufacturerName: '_TZ3000_xwh1e22x'}],
|
|
53
|
+
model: 'FUT089Z',
|
|
54
|
+
vendor: 'MiBoxer',
|
|
55
|
+
description: 'RGB+CCT Remote',
|
|
56
|
+
fromZigbee: [fz.battery],
|
|
57
|
+
toZigbee: [],
|
|
58
|
+
exposes: [e.battery(), e.battery_voltage()],
|
|
59
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
60
|
+
const endpoint = device.getEndpoint(1);
|
|
61
|
+
await endpoint.read('genBasic', ['manufacturerName', 'zclVersion', 'appVersion', 'modelId', 'powerSource', 0xfffe]);
|
|
62
|
+
await endpoint.command('genGroups', 'miboxerSetZones', {zones: [
|
|
63
|
+
{zoneNum: 1, groupId: 101},
|
|
64
|
+
{zoneNum: 2, groupId: 102},
|
|
65
|
+
{zoneNum: 3, groupId: 103},
|
|
66
|
+
{zoneNum: 4, groupId: 104},
|
|
67
|
+
{zoneNum: 5, groupId: 105},
|
|
68
|
+
{zoneNum: 6, groupId: 106},
|
|
69
|
+
{zoneNum: 7, groupId: 107},
|
|
70
|
+
{zoneNum: 8, groupId: 108},
|
|
71
|
+
]});
|
|
72
|
+
await endpoint.command('genBasic', 'tuyaSetup', {}, {disableDefaultResponse: true});
|
|
73
|
+
},
|
|
74
|
+
},
|
|
50
75
|
];
|
package/devices/neo.js
CHANGED
|
@@ -12,18 +12,18 @@ module.exports = [
|
|
|
12
12
|
model: 'NAS-AB02B0',
|
|
13
13
|
vendor: 'Neo',
|
|
14
14
|
description: 'Temperature & humidity sensor and alarm',
|
|
15
|
-
fromZigbee: [fz.neo_t_h_alarm, fz.ignore_basic_report],
|
|
15
|
+
fromZigbee: [fz.neo_t_h_alarm, fz.ignore_basic_report, fz.ignore_tuya_set_time],
|
|
16
16
|
toZigbee: [tz.neo_t_h_alarm],
|
|
17
17
|
exposes: [
|
|
18
18
|
e.temperature(), e.humidity(), exposes.binary('humidity_alarm', ea.STATE_SET, true, false), e.battery_low(),
|
|
19
19
|
exposes.binary('temperature_alarm', ea.STATE_SET, true, false),
|
|
20
20
|
exposes.binary('alarm', ea.STATE_SET, true, false),
|
|
21
21
|
exposes.enum('melody', ea.STATE_SET, Array.from(Array(18).keys()).map((x)=>(x+1).toString())),
|
|
22
|
-
exposes.numeric('duration', ea.STATE_SET).withUnit('second').withValueMin(0).withValueMax(
|
|
23
|
-
exposes.numeric('temperature_min', ea.STATE_SET).withUnit('°C').withValueMin(-
|
|
24
|
-
exposes.numeric('temperature_max', ea.STATE_SET).withUnit('°C').withValueMin(-
|
|
25
|
-
exposes.numeric('humidity_min', ea.STATE_SET).withUnit('%').withValueMin(
|
|
26
|
-
exposes.numeric('humidity_max', ea.STATE_SET).withUnit('%').withValueMin(
|
|
22
|
+
exposes.numeric('duration', ea.STATE_SET).withUnit('second').withValueMin(0).withValueMax(1800),
|
|
23
|
+
exposes.numeric('temperature_min', ea.STATE_SET).withUnit('°C').withValueMin(-20).withValueMax(80),
|
|
24
|
+
exposes.numeric('temperature_max', ea.STATE_SET).withUnit('°C').withValueMin(-20).withValueMax(80),
|
|
25
|
+
exposes.numeric('humidity_min', ea.STATE_SET).withUnit('%').withValueMin(1).withValueMax(100),
|
|
26
|
+
exposes.numeric('humidity_max', ea.STATE_SET).withUnit('%').withValueMin(1).withValueMax(100),
|
|
27
27
|
exposes.enum('volume', ea.STATE_SET, ['low', 'medium', 'high']),
|
|
28
28
|
exposes.enum('power_type', ea.STATE, ['battery_full', 'battery_high', 'battery_medium', 'battery_low', 'usb']),
|
|
29
29
|
],
|
|
@@ -62,16 +62,25 @@ module.exports = [
|
|
|
62
62
|
model: 'NAS-PD07',
|
|
63
63
|
vendor: 'Neo',
|
|
64
64
|
description: 'Motion, temperature & humidity sensor',
|
|
65
|
-
fromZigbee: [fz.neo_nas_pd07],
|
|
65
|
+
fromZigbee: [fz.neo_nas_pd07, fz.ignore_tuya_set_time],
|
|
66
66
|
toZigbee: [tz.neo_nas_pd07],
|
|
67
67
|
onEvent: tuya.onEventSetTime,
|
|
68
68
|
exposes: [e.occupancy(), e.humidity(), e.temperature(), e.tamper(), e.battery_low(),
|
|
69
69
|
exposes.enum('power_type', ea.STATE, ['battery_full', 'battery_high', 'battery_medium', 'battery_low', 'usb']),
|
|
70
70
|
exposes.enum('alarm', ea.STATE, ['over_temperature', 'over_humidity', 'below_min_temperature', 'below_min_humdity', 'off'])
|
|
71
71
|
.withDescription('Temperature/humidity alarm status'),
|
|
72
|
-
exposes.numeric('temperature_min', ea.STATE_SET).withUnit('°C').withValueMin(-
|
|
73
|
-
exposes.numeric('temperature_max', ea.STATE_SET).withUnit('°C').withValueMin(-
|
|
74
|
-
exposes.
|
|
75
|
-
exposes.numeric('
|
|
72
|
+
exposes.numeric('temperature_min', ea.STATE_SET).withUnit('°C').withValueMin(-20).withValueMax(80),
|
|
73
|
+
exposes.numeric('temperature_max', ea.STATE_SET).withUnit('°C').withValueMin(-20).withValueMax(80),
|
|
74
|
+
exposes.binary('temperature_scale', ea.STATE_SET, '°C', '°F').withDescription('Temperature scale (°F/°C)'),
|
|
75
|
+
exposes.numeric('humidity_min', ea.STATE_SET).withUnit('%').withValueMin(1).withValueMax(100),
|
|
76
|
+
exposes.numeric('humidity_max', ea.STATE_SET).withUnit('%').withValueMin(1).withValueMax(100),
|
|
77
|
+
// exposes.binary('unknown_111', ea.STATE_SET, 'ON', 'OFF').withDescription('Unknown datapoint 111 (default: ON)'),
|
|
78
|
+
// exposes.binary('unknown_112', ea.STATE_SET, 'ON', 'OFF').withDescription('Unknown datapoint 112 (default: ON)')
|
|
79
|
+
],
|
|
80
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
81
|
+
const endpoint = device.getEndpoint(1);
|
|
82
|
+
await endpoint.read('genBasic', ['manufacturerName', 'zclVersion', 'appVersion', 'modelId', 'powerSource', 0xfffe]);
|
|
83
|
+
await endpoint.command('manuSpecificTuya', 'mcuVersionRequest', {'seq': 0x0002});
|
|
84
|
+
},
|
|
76
85
|
},
|
|
77
86
|
];
|
package/devices/nue_3a.js
CHANGED
|
@@ -137,8 +137,12 @@ module.exports = [
|
|
|
137
137
|
model: 'HGZB-04D / HGZB-4D-UK',
|
|
138
138
|
vendor: 'Nue / 3A',
|
|
139
139
|
description: 'Smart dimmer wall switch',
|
|
140
|
-
extend: extend.light_onoff_brightness({disableEffect: true}),
|
|
140
|
+
extend: extend.light_onoff_brightness({disableEffect: true, noConfigure: true}),
|
|
141
141
|
whiteLabel: [{vendor: 'Sunricher', model: 'SR-ZG9001K8-DIM'}],
|
|
142
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
143
|
+
await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
|
|
144
|
+
await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
|
|
145
|
+
},
|
|
142
146
|
},
|
|
143
147
|
{
|
|
144
148
|
zigbeeModel: ['FB56+ZSW1HKJ1.7', 'FB56+ZSW1HKJ2.5', 'FB56+ZSW1HKJ2.7'],
|
|
@@ -282,7 +286,7 @@ module.exports = [
|
|
|
282
286
|
extend: extend.light_onoff_brightness_colortemp_color(),
|
|
283
287
|
},
|
|
284
288
|
{
|
|
285
|
-
zigbeeModel: ['LXN60-LS27-Z30'],
|
|
289
|
+
zigbeeModel: ['LXN60-LS27-Z30', 'FEB56-ZCW2CLX1.0'],
|
|
286
290
|
model: 'WL-SD001-9W',
|
|
287
291
|
vendor: 'Nue / 3A',
|
|
288
292
|
description: '9W RGB LED downlight',
|
package/devices/philips.js
CHANGED
|
@@ -108,6 +108,15 @@ module.exports = [
|
|
|
108
108
|
extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
|
|
109
109
|
ota: ota.zigbeeOTA,
|
|
110
110
|
},
|
|
111
|
+
{
|
|
112
|
+
zigbeeModel: ['915005996801', '915005996901'],
|
|
113
|
+
model: '915005996901',
|
|
114
|
+
vendor: 'Philips',
|
|
115
|
+
description: 'Hue white ambiance ceiling light Enrave L with Bluetooth',
|
|
116
|
+
meta: {turnsOffAtBrightness1: true},
|
|
117
|
+
extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
|
|
118
|
+
ota: ota.zigbeeOTA,
|
|
119
|
+
},
|
|
111
120
|
{
|
|
112
121
|
zigbeeModel: ['915005997001', '915005997101'],
|
|
113
122
|
model: '915005997001',
|
package/devices/tuya.js
CHANGED
|
@@ -13,7 +13,7 @@ const utils = require('../lib/utils');
|
|
|
13
13
|
const TS011Fplugs = ['_TZ3000_5f43h46b', '_TZ3000_cphmq0q7', '_TZ3000_dpo1ysak', '_TZ3000_ew3ldmgx', '_TZ3000_gjnozsaz',
|
|
14
14
|
'_TZ3000_jvzvulen', '_TZ3000_mraovvmm', '_TZ3000_nfnmi125', '_TZ3000_ps3dmato', '_TZ3000_w0qqde0g', '_TZ3000_u5u4cakc',
|
|
15
15
|
'_TZ3000_rdtixbnu', '_TZ3000_typdpbpg', '_TZ3000_kx0pris5', '_TZ3000_amdymr7l', '_TZ3000_z1pnpsdo', '_TZ3000_ksw8qtmt',
|
|
16
|
-
'_TZ3000_nzkqcvvs', '_TZ3000_1h2x4akh'];
|
|
16
|
+
'_TZ3000_nzkqcvvs', '_TZ3000_1h2x4akh', '_TZ3000_9vo5icau'];
|
|
17
17
|
|
|
18
18
|
const tzLocal = {
|
|
19
19
|
TS0504B_color: {
|
|
@@ -167,7 +167,7 @@ module.exports = [
|
|
|
167
167
|
description: 'Air quality sensor',
|
|
168
168
|
fromZigbee: [fz.tuya_air_quality],
|
|
169
169
|
toZigbee: [],
|
|
170
|
-
exposes: [e.temperature(), e.humidity(), e.co2(), e.voc(), e.formaldehyd()],
|
|
170
|
+
exposes: [e.temperature(), e.humidity(), e.co2(), e.voc().withUnit('ppm'), e.formaldehyd()],
|
|
171
171
|
},
|
|
172
172
|
{
|
|
173
173
|
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_dwcarsat'}],
|
|
@@ -1086,7 +1086,6 @@ module.exports = [
|
|
|
1086
1086
|
// Window pushers:
|
|
1087
1087
|
{modelID: 'TS0601', manufacturerName: '_TZE200_g5wdnuow'},
|
|
1088
1088
|
// Tubular motors:
|
|
1089
|
-
{modelID: 'TS0601', manufacturerName: '_TZE200_fzo2pocs'},
|
|
1090
1089
|
{modelID: 'TS0601', manufacturerName: '_TZE200_5sbebbzs'},
|
|
1091
1090
|
{modelID: 'TS0601', manufacturerName: '_TZE200_zuz7f94z'},
|
|
1092
1091
|
{modelID: 'TS0601', manufacturerName: '_TZE200_zyrdrmno'},
|
|
@@ -1107,7 +1106,6 @@ module.exports = [
|
|
|
1107
1106
|
{vendor: 'Moes', model: 'AM43-0.45/40-ES-EB'},
|
|
1108
1107
|
{vendor: 'Larkkey', model: 'ZSTY-SM-1SRZG-EU'},
|
|
1109
1108
|
{vendor: 'Zemismart', model: 'ZM85EL-2Z', description: 'Roman Rod I type curtains track'},
|
|
1110
|
-
{vendor: 'Zemismart', model: 'ZM25TQ', description: 'Tubular motor'},
|
|
1111
1109
|
{vendor: 'Zemismart', model: 'AM43', description: 'Roller blind motor'},
|
|
1112
1110
|
{vendor: 'Zemismart', model: 'M2805EGBZTN', description: 'Tubular motor'},
|
|
1113
1111
|
{vendor: 'Zemismart', model: 'BCM500DS-TYZ', description: 'Curtain motor'},
|
|
@@ -1415,7 +1413,8 @@ module.exports = [
|
|
|
1415
1413
|
model: 'TS011F_plug_3',
|
|
1416
1414
|
description: 'Smart plug (with power monitoring by polling)',
|
|
1417
1415
|
vendor: 'TuYa',
|
|
1418
|
-
whiteLabel: [{vendor: 'VIKEFON', model: 'TS011F'}, {vendor: 'BlitzWolf', model: 'BW-SHP15'}
|
|
1416
|
+
whiteLabel: [{vendor: 'VIKEFON', model: 'TS011F'}, {vendor: 'BlitzWolf', model: 'BW-SHP15'},
|
|
1417
|
+
{vendor: 'Avatto', model: 'MIUCOT10Z'}],
|
|
1419
1418
|
ota: ota.zigbeeOTA,
|
|
1420
1419
|
fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering, fz.ignore_basic_report, fz.tuya_switch_power_outage_memory,
|
|
1421
1420
|
fz.ts011f_plug_indicator_mode, fz.ts011f_plug_child_mode],
|
package/devices/xiaomi.js
CHANGED
|
@@ -844,15 +844,17 @@ module.exports = [
|
|
|
844
844
|
model: 'WSDCGQ12LM',
|
|
845
845
|
vendor: 'Xiaomi',
|
|
846
846
|
description: 'Aqara T1 temperature, humidity and pressure sensor',
|
|
847
|
-
fromZigbee: [fz.
|
|
847
|
+
fromZigbee: [fz.aqara_opple, fz.temperature, fz.humidity, fz.pressure, fz.battery],
|
|
848
848
|
toZigbee: [],
|
|
849
|
+
exposes: [e.temperature(), e.humidity(), e.pressure(), e.battery(), e.battery_voltage()],
|
|
849
850
|
meta: {battery: {voltageToPercentage: '3V_2850_3000_log'}},
|
|
850
851
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
851
852
|
const endpoint = device.getEndpoint(1);
|
|
852
853
|
const binds = ['msTemperatureMeasurement', 'msRelativeHumidity', 'msPressureMeasurement'];
|
|
853
854
|
await reporting.bind(endpoint, coordinatorEndpoint, binds);
|
|
855
|
+
await endpoint.read('genPowerCfg', ['batteryVoltage']);
|
|
854
856
|
},
|
|
855
|
-
|
|
857
|
+
ota: ota.zigbeeOTA,
|
|
856
858
|
},
|
|
857
859
|
{
|
|
858
860
|
zigbeeModel: ['lumi.sensor_motion'],
|
|
@@ -1348,9 +1350,16 @@ module.exports = [
|
|
|
1348
1350
|
model: 'ZNJLBL01LM',
|
|
1349
1351
|
description: 'Aqara roller shade companion E1',
|
|
1350
1352
|
vendor: 'Xiaomi',
|
|
1351
|
-
fromZigbee: [fz.
|
|
1352
|
-
fz.ignore_basic_report, fz.aqara_opple],
|
|
1353
|
+
fromZigbee: [fz.xiaomi_curtain_position, fz.xiaomi_curtain_acn002_status, fz.ignore_basic_report, fz.aqara_opple],
|
|
1353
1354
|
toZigbee: [tz.xiaomi_curtain_position_state, tz.xiaomi_curtain_acn002_battery, tz.xiaomi_curtain_acn002_charging_status],
|
|
1355
|
+
onEvent: async (type, data, device) => {
|
|
1356
|
+
if (type === 'message' && data.type === 'attributeReport' && data.cluster === 'genMultistateOutput' &&
|
|
1357
|
+
data.data.hasOwnProperty('presentValue') && data.data['presentValue'] > 1) {
|
|
1358
|
+
// Try to read the position after the motor stops, the device occasionally report wrong data right after stopping
|
|
1359
|
+
// Might need to add delay, seems to be working without one but needs more tests.
|
|
1360
|
+
await device.getEndpoint(1).read('genAnalogOutput', ['presentValue']);
|
|
1361
|
+
}
|
|
1362
|
+
},
|
|
1354
1363
|
exposes: [e.cover_position().setAccess('state', ea.ALL), e.battery().withAccess(ea.STATE_GET),
|
|
1355
1364
|
exposes.binary('charging_status', ea.STATE_GET, true, false)
|
|
1356
1365
|
.withDescription('The current charging status.'),
|
package/devices/zemismart.js
CHANGED
|
@@ -154,4 +154,13 @@ module.exports = [
|
|
|
154
154
|
// exposes.enum('situation_set', ea.STATE, Object.values(tuya.ZMAM02.AM02Situation)),
|
|
155
155
|
],
|
|
156
156
|
},
|
|
157
|
+
{
|
|
158
|
+
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_fzo2pocs'}],
|
|
159
|
+
model: 'ZM25TQ',
|
|
160
|
+
vendor: 'Zemismart',
|
|
161
|
+
description: 'Tubular motor',
|
|
162
|
+
fromZigbee: [fz.tuya_cover, fz.ignore_basic_report],
|
|
163
|
+
toZigbee: [tz.tuya_cover_control, tz.tuya_cover_options, tz.tuya_data_point_test],
|
|
164
|
+
exposes: [e.cover_position().setAccess('position', ea.STATE_SET)],
|
|
165
|
+
},
|
|
157
166
|
];
|
package/lib/exposes.js
CHANGED
|
@@ -550,7 +550,7 @@ module.exports = {
|
|
|
550
550
|
fan: () => new Fan(),
|
|
551
551
|
flip_indicator_light: () => new Binary('flip_indicator_light', access.ALL, 'ON', 'OFF').withDescription('After turn on, the indicator light turns on while switch is off, and vice versa'),
|
|
552
552
|
force: () => new Enum('force', access.STATE_SET, ['normal', 'open', 'close']).withDescription('Force the valve position'),
|
|
553
|
-
formaldehyd: () => new Numeric('formaldehyd', access.STATE).withDescription('The measured formaldehyd value'),
|
|
553
|
+
formaldehyd: () => new Numeric('formaldehyd', access.STATE).withDescription('The measured formaldehyd value').withUnit('mg/m³'),
|
|
554
554
|
gas: () => new Binary('gas', access.STATE, true, false).withDescription('Indicates whether the device detected gas'),
|
|
555
555
|
hcho: () => new Numeric('hcho', access.STATE).withUnit('mg/m³').withDescription('Measured Hcho value'),
|
|
556
556
|
holiday_temperature: () => new Numeric('holiday_temperature', access.STATE_SET).withUnit('°C').withDescription('Holiday temperature').withValueMin(0).withValueMax(30),
|
package/lib/tuya.js
CHANGED
|
@@ -358,11 +358,14 @@ const dataPoints = {
|
|
|
358
358
|
moesSmaxTempSet: 108,
|
|
359
359
|
moesSminTempSet: 109,
|
|
360
360
|
// Neo T&H
|
|
361
|
+
neoOccupancy: 101,
|
|
361
362
|
neoPowerType: 101,
|
|
362
363
|
neoMelody: 102,
|
|
363
364
|
neoDuration: 103,
|
|
365
|
+
neoTamper: 103,
|
|
364
366
|
neoAlarm: 104,
|
|
365
367
|
neoTemp: 105,
|
|
368
|
+
neoTempScale: 106,
|
|
366
369
|
neoHumidity: 106,
|
|
367
370
|
neoMinTemp: 107,
|
|
368
371
|
neoMaxTemp: 108,
|
|
@@ -370,6 +373,7 @@ const dataPoints = {
|
|
|
370
373
|
neoMaxHumidity: 110,
|
|
371
374
|
neoUnknown2: 112,
|
|
372
375
|
neoTempAlarm: 113,
|
|
376
|
+
neoTempHumidityAlarm: 113,
|
|
373
377
|
neoHumidityAlarm: 114,
|
|
374
378
|
neoUnknown3: 115,
|
|
375
379
|
neoVolume: 116,
|
package/lib/xiaomi.js
CHANGED
|
@@ -158,7 +158,9 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
|
|
|
158
158
|
}
|
|
159
159
|
break;
|
|
160
160
|
case '3':
|
|
161
|
-
if (
|
|
161
|
+
if (['WSDCGQ12LM'].includes(model.model)) {
|
|
162
|
+
// This temperature value is ignored because with greater accuracy it is reported in key №100
|
|
163
|
+
} else if (!['WXCJKG11LM', 'WXCJKG12LM', 'WXCJKG13LM'].includes(model.model)) {
|
|
162
164
|
payload.temperature = calibrateAndPrecisionRoundOptions(value, options, 'temperature'); // 0x03
|
|
163
165
|
}
|
|
164
166
|
break;
|
|
@@ -196,10 +198,11 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
|
|
|
196
198
|
payload[`state_${mapping}`] = value === 1 ? 'ON' : 'OFF';
|
|
197
199
|
} else if (['WXKG14LM', 'WXKG16LM', 'WXKG17LM'].includes(model.model)) {
|
|
198
200
|
payload.click_mode = {1: 'fast', 2: 'multi'}[value];
|
|
199
|
-
} else if (['WXCJKG11LM', 'WXCJKG12LM', 'WXCJKG13LM'].includes(model.model)) {
|
|
201
|
+
} else if (['WXCJKG11LM', 'WXCJKG12LM', 'WXCJKG13LM', 'ZNMS12LM'].includes(model.model)) {
|
|
200
202
|
// We don't know what the value means for these devices.
|
|
201
203
|
// https://github.com/Koenkk/zigbee2mqtt/issues/11126
|
|
202
|
-
|
|
204
|
+
// https://github.com/Koenkk/zigbee2mqtt/issues/12279
|
|
205
|
+
} else if (['WSDCGQ01LM', 'WSDCGQ11LM', 'WSDCGQ12LM'].includes(model.model)) {
|
|
203
206
|
// https://github.com/Koenkk/zigbee2mqtt/issues/798
|
|
204
207
|
// Sometimes the sensor publishes non-realistic vales, filter these
|
|
205
208
|
const temperature = parseFloat(value) / 100.0;
|
|
@@ -241,7 +244,7 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
|
|
|
241
244
|
payload[`state_${mapping}`] = value === 1 ? 'ON' : 'OFF';
|
|
242
245
|
} else if (['RTCGQ12LM', 'RTCGQ14LM'].includes(model.model)) {
|
|
243
246
|
payload.illuminance = calibrateAndPrecisionRoundOptions(value, options, 'illuminance');
|
|
244
|
-
} else if (['WSDCGQ01LM', 'WSDCGQ11LM'].includes(model.model)) {
|
|
247
|
+
} else if (['WSDCGQ01LM', 'WSDCGQ11LM', 'WSDCGQ12LM'].includes(model.model)) {
|
|
245
248
|
// https://github.com/Koenkk/zigbee2mqtt/issues/798
|
|
246
249
|
// Sometimes the sensor publishes non-realistic vales, filter these
|
|
247
250
|
const humidity = parseFloat(value) / 100.0;
|
|
@@ -259,6 +262,9 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
|
|
|
259
262
|
payload.state_right = value === 1 ? 'ON' : 'OFF';
|
|
260
263
|
} else if (['WSDCGQ01LM', 'WSDCGQ11LM'].includes(model.model)) {
|
|
261
264
|
payload.pressure = calibrateAndPrecisionRoundOptions(value/100.0, options, 'pressure');
|
|
265
|
+
} else if (['WSDCGQ12LM'].includes(model.model)) {
|
|
266
|
+
// This pressure value is ignored because it is less accurate than reported in the 'scaledValue' attribute
|
|
267
|
+
// of the 'msPressureMeasurement' cluster
|
|
262
268
|
} else if (['RTCZCGQ11LM'].includes(model.model)) {
|
|
263
269
|
if (meta.device.applicationVersion < 50) {
|
|
264
270
|
payload.presence_event = {0: 'enter', 1: 'leave', 2: 'left_enter', 3: 'right_leave', 4: 'right_enter',
|