zigbee-herdsman-converters 14.0.311 → 14.0.316
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 +328 -28
- package/converters/toZigbee.js +168 -2
- package/devices/aurora_lighting.js +29 -22
- package/devices/candeo.js +6 -1
- package/devices/develco.js +16 -3
- package/devices/hive.js +82 -0
- package/devices/ikea.js +1 -1
- package/devices/javis.js +21 -1
- package/devices/leedarson.js +1 -1
- package/devices/lidl.js +41 -1
- package/devices/livolo.js +29 -0
- package/devices/miboxer.js +7 -0
- package/devices/neo.js +6 -0
- package/devices/philips.js +28 -1
- package/devices/rgb_genie.js +8 -0
- package/devices/tuya.js +139 -6
- package/devices/xiaomi.js +1 -1
- package/devices/zen.js +1 -1
- package/lib/constants.js +12 -0
- package/lib/exposes.js +2 -0
- package/npm-shrinkwrap.json +1 -1
- package/package.json +1 -1
package/converters/fromZigbee.js
CHANGED
|
@@ -648,6 +648,26 @@ const converters = {
|
|
|
648
648
|
return payload;
|
|
649
649
|
},
|
|
650
650
|
},
|
|
651
|
+
develco_metering: {
|
|
652
|
+
cluster: 'seMetering',
|
|
653
|
+
type: ['attributeReport', 'readResponse'],
|
|
654
|
+
convert: (model, msg, publish, options, meta) => {
|
|
655
|
+
const result = {};
|
|
656
|
+
if (msg.data.hasOwnProperty('develcoPulseConfiguration')) {
|
|
657
|
+
result[postfixWithEndpointName('pulse_configuration', msg, model)] =
|
|
658
|
+
msg.data['develcoPulseConfiguration'];
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
if (msg.data.hasOwnProperty('develcoInterfaceMode')) {
|
|
662
|
+
result[postfixWithEndpointName('interface_mode', msg, model)] =
|
|
663
|
+
constants.develcoInterfaceMode.hasOwnProperty(msg.data['develcoInterfaceMode']) ?
|
|
664
|
+
constants.develcoInterfaceMode[msg.data['develcoInterfaceMode']] :
|
|
665
|
+
msg.data['develcoInterfaceMode'];
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
return result;
|
|
669
|
+
},
|
|
670
|
+
},
|
|
651
671
|
electrical_measurement: {
|
|
652
672
|
/**
|
|
653
673
|
* When using this converter also add the following to the configure method of the device:
|
|
@@ -2485,6 +2505,22 @@ const converters = {
|
|
|
2485
2505
|
}
|
|
2486
2506
|
},
|
|
2487
2507
|
},
|
|
2508
|
+
livolo_curtain_switch_state: {
|
|
2509
|
+
cluster: 'genPowerCfg',
|
|
2510
|
+
type: ['raw'],
|
|
2511
|
+
convert: (model, msg, publish, options, meta) => {
|
|
2512
|
+
const stateHeader = Buffer.from([122, 209]);
|
|
2513
|
+
if (msg.data.indexOf(stateHeader) === 0) {
|
|
2514
|
+
if (msg.data[10] === 5) {
|
|
2515
|
+
const status = msg.data[14];
|
|
2516
|
+
return {
|
|
2517
|
+
state_left: status === 1 ? 'ON' : 'OFF',
|
|
2518
|
+
state_right: status === 0 ? 'ON' : 'OFF',
|
|
2519
|
+
};
|
|
2520
|
+
}
|
|
2521
|
+
}
|
|
2522
|
+
},
|
|
2523
|
+
},
|
|
2488
2524
|
livolo_dimmer_state: {
|
|
2489
2525
|
cluster: 'genPowerCfg',
|
|
2490
2526
|
type: ['raw'],
|
|
@@ -2592,16 +2628,24 @@ const converters = {
|
|
|
2592
2628
|
[124,210,21,216,128, 199,147,3,24,0,75,18,0, 19,7,0] after interview
|
|
2593
2629
|
[122,209, 199,147,3,24,0,75,18,0, 7,1,6,1,0,11] off
|
|
2594
2630
|
[122,209, 199,147,3,24,0,75,18,0, 7,1,6,1,1,11] on
|
|
2631
|
+
|
|
2595
2632
|
new switch
|
|
2596
2633
|
[124,210,21,216,128, 228,41,3,24,0,75,18,0, 19,1,0] after interview
|
|
2597
2634
|
[122,209, 228,41,3,24,0,75,18,0, 7,1,0,1,0,11] off
|
|
2598
2635
|
[122,209, 228,41,3,24,0,75,18,0, 7,1,0,1,1,11] on
|
|
2636
|
+
|
|
2599
2637
|
old switch
|
|
2600
2638
|
[124,210,21,216,128, 170, 10,2,24,0,75,18,0, 17,0,1] after interview
|
|
2601
2639
|
[124,210,21,216,0, 18, 15,5,24,0,75,18,0, 34,0,0] left: 0, right: 0
|
|
2602
2640
|
[124,210,21,216,0, 18, 15,5,24,0,75,18,0, 34,0,1] left: 1, right: 0
|
|
2603
2641
|
[124,210,21,216,0, 18, 15,5,24,0,75,18,0, 34,0,2] left: 0, right: 1
|
|
2604
2642
|
[124,210,21,216,0, 18, 15,5,24,0,75,18,0, 34,0,3] left: 1, right: 1
|
|
2643
|
+
|
|
2644
|
+
curtain switch
|
|
2645
|
+
[124,210,21,216,128, 110,74,116,33,0,75,18,0, 19,5,0] after interview
|
|
2646
|
+
[122,209, 110,74,116,33,0,75,18,0, 5,1,5,0,2,11] left: 0, right: 0 (off)
|
|
2647
|
+
[122,209, 110,74,116,33,0,75,18,0, 5,1,5,0,1,11] left: 1, right: 0 (left on)
|
|
2648
|
+
[122,209, 110,74,116,33,0,75,18,0, 5,1,5,0,0,11] left: 0, right: 1 (right on)
|
|
2605
2649
|
*/
|
|
2606
2650
|
const malformedHeader = Buffer.from([0x7c, 0xd2, 0x15, 0xd8, 0x00]);
|
|
2607
2651
|
const infoHeader = Buffer.from([0x7c, 0xd2, 0x15, 0xd8, 0x80]);
|
|
@@ -2630,6 +2674,12 @@ const converters = {
|
|
|
2630
2674
|
meta.device.modelID = 'TI0001-switch-2gang';
|
|
2631
2675
|
meta.device.save();
|
|
2632
2676
|
}
|
|
2677
|
+
if (msg.data.includes(Buffer.from([19, 5, 0]), 13)) {
|
|
2678
|
+
if (meta.logger) meta.logger.debug('Detected Livolo Curtain Switch');
|
|
2679
|
+
// curtain switch, hack
|
|
2680
|
+
meta.device.modelID = 'TI0001-curtain-switch';
|
|
2681
|
+
meta.device.save();
|
|
2682
|
+
}
|
|
2633
2683
|
if (msg.data.includes(Buffer.from([19, 20, 0]), 13)) {
|
|
2634
2684
|
// new dimmer, hack
|
|
2635
2685
|
meta.device.modelID = 'TI0001-dimmer';
|
|
@@ -3539,6 +3589,157 @@ const converters = {
|
|
|
3539
3589
|
}
|
|
3540
3590
|
},
|
|
3541
3591
|
},
|
|
3592
|
+
tvtwo_thermostat: {
|
|
3593
|
+
cluster: 'manuSpecificTuya',
|
|
3594
|
+
type: ['commandGetData', 'commandSetDataResponse'],
|
|
3595
|
+
convert: (model, msg, publish, options, meta) => {
|
|
3596
|
+
const dp = msg.data.dp;
|
|
3597
|
+
const value = tuya.getDataValue(msg.data.datatype, msg.data.data);
|
|
3598
|
+
const presetLookup = {0: 'auto', 1: 'manual', 2: 'holiday'};
|
|
3599
|
+
switch (dp) {
|
|
3600
|
+
case tuya.dataPoints.tvMode:
|
|
3601
|
+
return {preset: presetLookup[value]};
|
|
3602
|
+
case tuya.dataPoints.tvChildLock:
|
|
3603
|
+
return {child_lock: value ? 'LOCK' : 'UNLOCK'};
|
|
3604
|
+
case tuya.dataPoints.tvHolidayTemp:
|
|
3605
|
+
return {holiday_temperature: (value / 10).toFixed(1)};
|
|
3606
|
+
case tuya.dataPoints.tvHeatingSetpoint:
|
|
3607
|
+
return {current_heating_setpoint: (value / 10).toFixed(1)};
|
|
3608
|
+
case tuya.dataPoints.tvFrostDetection:
|
|
3609
|
+
return {frost_protection: value ? 'ON' : 'OFF'};
|
|
3610
|
+
case tuya.dataPoints.tvWindowDetection:
|
|
3611
|
+
return {window_detection: value ? 'ON' : 'OFF'};
|
|
3612
|
+
case tuya.dataPoints.tvHeatingStop:
|
|
3613
|
+
return {heating_stop: value ? 'ON' : 'OFF'};
|
|
3614
|
+
case tuya.dataPoints.tvLocalTemp:
|
|
3615
|
+
return {local_temperature: (value / 10).toFixed(1)};
|
|
3616
|
+
case tuya.dataPoints.tvBattery:
|
|
3617
|
+
return {battery_low: value === 0 ? true : false};
|
|
3618
|
+
case tuya.dataPoints.tvTempCalibration:
|
|
3619
|
+
return {local_temperature_calibration: value > 55 ?
|
|
3620
|
+
((value - 0x100000000)/10).toFixed(1): (value/ 10).toFixed(1)};
|
|
3621
|
+
case tuya.dataPoints.tvBoostTime:
|
|
3622
|
+
// Setting minimum 0 - maximum 465 seconds
|
|
3623
|
+
return {boost_timeset_countdown: value};
|
|
3624
|
+
case tuya.dataPoints.tvComfortTemp:
|
|
3625
|
+
return {comfort_temperature: (value / 10).toFixed(1)};
|
|
3626
|
+
case tuya.dataPoints.tvEcoTemp:
|
|
3627
|
+
return {eco_temperature: (value / 10).toFixed(1)};
|
|
3628
|
+
case tuya.dataPoints.tvOpenWindowTemp:
|
|
3629
|
+
return {open_window_temperature: (value / 10).toFixed(1)};
|
|
3630
|
+
case tuya.dataPoints.tvErrorStatus:
|
|
3631
|
+
return {fault_alarm: value};
|
|
3632
|
+
case tuya.dataPoints.tvHolidayMode:
|
|
3633
|
+
return {holiday_mode_date: value};
|
|
3634
|
+
|
|
3635
|
+
case tuya.dataPoints.tvBoostMode:
|
|
3636
|
+
// Online ?
|
|
3637
|
+
return {online: value ? 'ON' : 'OFF'};
|
|
3638
|
+
case tuya.dataPoints.tvWorkingDay:
|
|
3639
|
+
// tvWorkingDay: 31,
|
|
3640
|
+
return {working_day: value};
|
|
3641
|
+
case tuya.dataPoints.tvWeekSchedule:
|
|
3642
|
+
// tvWeekSchedule: 106, Week select 0 - 5 days, 1 - 6 days, 2 - 7 days
|
|
3643
|
+
return {week_schedule: value};
|
|
3644
|
+
|
|
3645
|
+
case tuya.dataPoints.tvMondaySchedule:
|
|
3646
|
+
return {schedule_monday:
|
|
3647
|
+
' ' + value[0] / 6 + 'h:' + value[1] + 'm ' + value[2] / 10 + '°C' +
|
|
3648
|
+
', ' + value[3] / 6 + 'h:' + value[4] + 'm ' + value[5] / 10 + '°C' +
|
|
3649
|
+
', ' + value[6] / 6 + 'h:' + value[7] + 'm ' + value[8] / 10 + '°C' +
|
|
3650
|
+
', ' + value[9] / 6 + 'h:' + value[10] + 'm ' + value[11] / 10 + '°C' +
|
|
3651
|
+
', ' + value[12] / 6 + 'h:' + value[13] + 'm ' + value[14] / 10 + '°C ' +
|
|
3652
|
+
', ' + value[15] / 6 + 'h:' + value[16] + 'm ' + value[17] / 10 + '°C ' +
|
|
3653
|
+
', ' + value[18] / 6 + 'h:' + value[19] + 'm ' + value[20] / 10 + '°C ' +
|
|
3654
|
+
', ' + value[21] / 6 + 'h:' + value[22] + 'm ' + value[23] / 10 + '°C ' +
|
|
3655
|
+
', ' + value[24] / 6 + 'h:' + value[25] + 'm ' + value[26] / 10 + '°C ' +
|
|
3656
|
+
', ' + value[27] / 6 + 'h:' + value[28] + 'm ' + value[29] / 10 + '°C ',
|
|
3657
|
+
};
|
|
3658
|
+
case tuya.dataPoints.tvTuesdaySchedule:
|
|
3659
|
+
return {schedule_tuesday:
|
|
3660
|
+
' ' + value[0] / 6 + 'h:' + value[1] + 'm ' + value[2] / 10 + '°C' +
|
|
3661
|
+
', ' + value[3] / 6 + 'h:' + value[4] + 'm ' + value[5] / 10 + '°C' +
|
|
3662
|
+
', ' + value[6] / 6 + 'h:' + value[7] + 'm ' + value[8] / 10 + '°C' +
|
|
3663
|
+
', ' + value[9] / 6 + 'h:' + value[10] + 'm ' + value[11] / 10 + '°C' +
|
|
3664
|
+
', ' + value[12] / 6 + 'h:' + value[13] + 'm ' + value[14] / 10 + '°C ' +
|
|
3665
|
+
', ' + value[15] / 6 + 'h:' + value[16] + 'm ' + value[17] / 10 + '°C ' +
|
|
3666
|
+
', ' + value[18] / 6 + 'h:' + value[19] + 'm ' + value[20] / 10 + '°C ' +
|
|
3667
|
+
', ' + value[21] / 6 + 'h:' + value[22] + 'm ' + value[23] / 10 + '°C ' +
|
|
3668
|
+
', ' + value[24] / 6 + 'h:' + value[25] + 'm ' + value[26] / 10 + '°C ' +
|
|
3669
|
+
', ' + value[27] / 6 + 'h:' + value[28] + 'm ' + value[29] / 10 + '°C ',
|
|
3670
|
+
};
|
|
3671
|
+
case tuya.dataPoints.tvWednesdaySchedule:
|
|
3672
|
+
return {schedule_wednesday:
|
|
3673
|
+
' ' + value[0] / 6 + 'h:' + value[1] + 'm ' + value[2] / 10 + '°C' +
|
|
3674
|
+
', ' + value[3] / 6 + 'h:' + value[4] + 'm ' + value[5] / 10 + '°C' +
|
|
3675
|
+
', ' + value[6] / 6 + 'h:' + value[7] + 'm ' + value[8] / 10 + '°C' +
|
|
3676
|
+
', ' + value[9] / 6 + 'h:' + value[10] + 'm ' + value[11] / 10 + '°C' +
|
|
3677
|
+
', ' + value[12] / 6 + 'h:' + value[13] + 'm ' + value[14] / 10 + '°C ' +
|
|
3678
|
+
', ' + value[15] / 6 + 'h:' + value[16] + 'm ' + value[17] / 10 + '°C ' +
|
|
3679
|
+
', ' + value[18] / 6 + 'h:' + value[19] + 'm ' + value[20] / 10 + '°C ' +
|
|
3680
|
+
', ' + value[21] / 6 + 'h:' + value[22] + 'm ' + value[23] / 10 + '°C ' +
|
|
3681
|
+
', ' + value[24] / 6 + 'h:' + value[25] + 'm ' + value[26] / 10 + '°C ' +
|
|
3682
|
+
', ' + value[27] / 6 + 'h:' + value[28] + 'm ' + value[29] / 10 + '°C ',
|
|
3683
|
+
};
|
|
3684
|
+
case tuya.dataPoints.tvThursdaySchedule:
|
|
3685
|
+
return {schedule_thursday:
|
|
3686
|
+
' ' + value[0] / 6 + 'h:' + value[1] + 'm ' + value[2] / 10 + '°C' +
|
|
3687
|
+
', ' + value[3] / 6 + 'h:' + value[4] + 'm ' + value[5] / 10 + '°C' +
|
|
3688
|
+
', ' + value[6] / 6 + 'h:' + value[7] + 'm ' + value[8] / 10 + '°C' +
|
|
3689
|
+
', ' + value[9] / 6 + 'h:' + value[10] + 'm ' + value[11] / 10 + '°C' +
|
|
3690
|
+
', ' + value[12] / 6 + 'h:' + value[13] + 'm ' + value[14] / 10 + '°C ' +
|
|
3691
|
+
', ' + value[15] / 6 + 'h:' + value[16] + 'm ' + value[17] / 10 + '°C ' +
|
|
3692
|
+
', ' + value[18] / 6 + 'h:' + value[19] + 'm ' + value[20] / 10 + '°C ' +
|
|
3693
|
+
', ' + value[21] / 6 + 'h:' + value[22] + 'm ' + value[23] / 10 + '°C ' +
|
|
3694
|
+
', ' + value[24] / 6 + 'h:' + value[25] + 'm ' + value[26] / 10 + '°C ' +
|
|
3695
|
+
', ' + value[27] / 6 + 'h:' + value[28] + 'm ' + value[29] / 10 + '°C ',
|
|
3696
|
+
};
|
|
3697
|
+
case tuya.dataPoints.tvFridaySchedule:
|
|
3698
|
+
return {schedule_friday:
|
|
3699
|
+
' ' + value[0] / 6 + 'h:' + value[1] + 'm ' + value[2] / 10 + '°C' +
|
|
3700
|
+
', ' + value[3] / 6 + 'h:' + value[4] + 'm ' + value[5] / 10 + '°C' +
|
|
3701
|
+
', ' + value[6] / 6 + 'h:' + value[7] + 'm ' + value[8] / 10 + '°C' +
|
|
3702
|
+
', ' + value[9] / 6 + 'h:' + value[10] + 'm ' + value[11] / 10 + '°C' +
|
|
3703
|
+
', ' + value[12] / 6 + 'h:' + value[13] + 'm ' + value[14] / 10 + '°C ' +
|
|
3704
|
+
', ' + value[15] / 6 + 'h:' + value[16] + 'm ' + value[17] / 10 + '°C ' +
|
|
3705
|
+
', ' + value[18] / 6 + 'h:' + value[19] + 'm ' + value[20] / 10 + '°C ' +
|
|
3706
|
+
', ' + value[21] / 6 + 'h:' + value[22] + 'm ' + value[23] / 10 + '°C ' +
|
|
3707
|
+
', ' + value[24] / 6 + 'h:' + value[25] + 'm ' + value[26] / 10 + '°C ' +
|
|
3708
|
+
', ' + value[27] / 6 + 'h:' + value[28] + 'm ' + value[29] / 10 + '°C ',
|
|
3709
|
+
};
|
|
3710
|
+
case tuya.dataPoints.tvSaturdaySchedule:
|
|
3711
|
+
return {schedule_saturday:
|
|
3712
|
+
' ' + value[0] / 6 + 'h:' + value[1] + 'm ' + value[2] / 10 + '°C' +
|
|
3713
|
+
', ' + value[3] / 6 + 'h:' + value[4] + 'm ' + value[5] / 10 + '°C' +
|
|
3714
|
+
', ' + value[6] / 6 + 'h:' + value[7] + 'm ' + value[8] / 10 + '°C' +
|
|
3715
|
+
', ' + value[9] / 6 + 'h:' + value[10] + 'm ' + value[11] / 10 + '°C' +
|
|
3716
|
+
', ' + value[12] / 6 + 'h:' + value[13] + 'm ' + value[14] / 10 + '°C ' +
|
|
3717
|
+
', ' + value[15] / 6 + 'h:' + value[16] + 'm ' + value[17] / 10 + '°C ' +
|
|
3718
|
+
', ' + value[18] / 6 + 'h:' + value[19] + 'm ' + value[20] / 10 + '°C ' +
|
|
3719
|
+
', ' + value[21] / 6 + 'h:' + value[22] + 'm ' + value[23] / 10 + '°C ' +
|
|
3720
|
+
', ' + value[24] / 6 + 'h:' + value[25] + 'm ' + value[26] / 10 + '°C ' +
|
|
3721
|
+
', ' + value[27] / 6 + 'h:' + value[28] + 'm ' + value[29] / 10 + '°C ',
|
|
3722
|
+
};
|
|
3723
|
+
case tuya.dataPoints.tvSundaySchedule:
|
|
3724
|
+
return {schedule_sunday:
|
|
3725
|
+
' ' + value[0] / 6 + 'h:' + value[1] + 'm ' + value[2] / 10 + '°C' +
|
|
3726
|
+
', ' + value[3] / 6 + 'h:' + value[4] + 'm ' + value[5] / 10 + '°C' +
|
|
3727
|
+
', ' + value[6] / 6 + 'h:' + value[7] + 'm ' + value[8] / 10 + '°C' +
|
|
3728
|
+
', ' + value[9] / 6 + 'h:' + value[10] + 'm ' + value[11] / 10 + '°C' +
|
|
3729
|
+
', ' + value[12] / 6 + 'h:' + value[13] + 'm ' + value[14] / 10 + '°C ' +
|
|
3730
|
+
', ' + value[15] / 6 + 'h:' + value[16] + 'm ' + value[17] / 10 + '°C ' +
|
|
3731
|
+
', ' + value[18] / 6 + 'h:' + value[19] + 'm ' + value[20] / 10 + '°C ' +
|
|
3732
|
+
', ' + value[21] / 6 + 'h:' + value[22] + 'm ' + value[23] / 10 + '°C ' +
|
|
3733
|
+
', ' + value[24] / 6 + 'h:' + value[25] + 'm ' + value[26] / 10 + '°C ' +
|
|
3734
|
+
', ' + value[27] / 6 + 'h:' + value[28] + 'm ' + value[29] / 10 + '°C ',
|
|
3735
|
+
};
|
|
3736
|
+
|
|
3737
|
+
default:
|
|
3738
|
+
meta.logger.warn(`zigbee-herdsman-converters:tvtwo_thermostat: NOT RECOGNIZED DP #${
|
|
3739
|
+
dp} with data ${JSON.stringify(msg.data)}`);
|
|
3740
|
+
}
|
|
3741
|
+
},
|
|
3742
|
+
},
|
|
3542
3743
|
haozee_thermostat: {
|
|
3543
3744
|
cluster: 'manuSpecificTuya',
|
|
3544
3745
|
type: ['commandGetData', 'commandSetDataResponse'],
|
|
@@ -3554,7 +3755,7 @@ const converters = {
|
|
|
3554
3755
|
case tuya.dataPoints.haozeeLocalTemp:
|
|
3555
3756
|
return {local_temperature: (value / 10).toFixed(1)};
|
|
3556
3757
|
case tuya.dataPoints.haozeeBoostHeatingCountdown:
|
|
3557
|
-
// quick heating countdown
|
|
3758
|
+
// quick heating countdown - not supported by this device
|
|
3558
3759
|
return {boost_heating_countdown: value};
|
|
3559
3760
|
case tuya.dataPoints.haozeeWindowDetection:
|
|
3560
3761
|
// window check
|
|
@@ -3631,11 +3832,11 @@ const converters = {
|
|
|
3631
3832
|
// working status 0 - pause 1 -working
|
|
3632
3833
|
return {'heating': value ? 'ON' : 'OFF'};
|
|
3633
3834
|
case tuya.dataPoints.haozeeBoostHeating:
|
|
3634
|
-
// rapid heating -> boolean
|
|
3635
|
-
|
|
3835
|
+
// rapid heating -> boolean - not supported by this device
|
|
3836
|
+
return {'boost_heating': value ? 'ON' : 'OFF'};
|
|
3636
3837
|
case tuya.dataPoints.haozeeTempCalibration:
|
|
3637
3838
|
// temperature calibration
|
|
3638
|
-
|
|
3839
|
+
return {'local_temperature_calibration': ( value/10 ).toFixed(1)};
|
|
3639
3840
|
case tuya.dataPoints.haozeeValvePosition:
|
|
3640
3841
|
// valve position
|
|
3641
3842
|
return {'position': value};
|
|
@@ -3869,32 +4070,33 @@ const converters = {
|
|
|
3869
4070
|
minutes: value[2],
|
|
3870
4071
|
},
|
|
3871
4072
|
};
|
|
3872
|
-
case tuya.dataPoints.scheduleWorkday: // set schedule for workdays [6,0,20,8,0,15,11,30,15,12,30,15,17,30,20,22,0,15]
|
|
3873
|
-
|
|
3874
|
-
// Top bits in hours have special meaning
|
|
3875
|
-
// 8: ??
|
|
3876
|
-
// 7: Current schedule indicator
|
|
3877
|
-
return {workdays: [
|
|
3878
|
-
{hour: value[0] & 0x3F, minute: value[1], temperature: value[2]},
|
|
3879
|
-
{hour: value[3] & 0x3F, minute: value[4], temperature: value[5]},
|
|
3880
|
-
{hour: value[6] & 0x3F, minute: value[7], temperature: value[8]},
|
|
3881
|
-
{hour: value[9] & 0x3F, minute: value[10], temperature: value[11]},
|
|
3882
|
-
{hour: value[12] & 0x3F, minute: value[13], temperature: value[14]},
|
|
3883
|
-
{hour: value[15] & 0x3F, minute: value[16], temperature: value[17]},
|
|
3884
|
-
]};
|
|
3885
|
-
case tuya.dataPoints.scheduleHoliday: // set schedule for holidays [6,0,20,8,0,15,11,30,15,12,30,15,17,30,20,22,0,15]
|
|
4073
|
+
case tuya.dataPoints.scheduleWorkday: // set schedule for workdays/holidays [6,0,20,8,0,15,11,30,15,12,30,15,17,30,20,22,0,15]
|
|
4074
|
+
case tuya.dataPoints.scheduleHoliday: {
|
|
3886
4075
|
// 6:00 - 20*, 8:00 - 15*, 11:30 - 15*, 12:30 - 15*, 17:30 - 20*, 22:00 - 15*
|
|
3887
4076
|
// Top bits in hours have special meaning
|
|
3888
|
-
//
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
{hour: value[
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
4077
|
+
// 6: Current schedule indicator
|
|
4078
|
+
const items = [];
|
|
4079
|
+
const programmingMode = [];
|
|
4080
|
+
|
|
4081
|
+
for (let i = 0; i < 6; i++) {
|
|
4082
|
+
const item = {hour: value[i*3] & 0x3F, minute: value[i*3+1], temperature: value[i*3+2]};
|
|
4083
|
+
if (value[i*3] & 0x40) {
|
|
4084
|
+
item['current'] = true;
|
|
4085
|
+
}
|
|
4086
|
+
|
|
4087
|
+
items[i] = item;
|
|
4088
|
+
programmingMode[i] =
|
|
4089
|
+
item['hour'].toString().padStart(2, '0') + ':' +
|
|
4090
|
+
item['minute'].toString().padStart(2, '0') + '/' +
|
|
4091
|
+
item['temperature'] + '°C';
|
|
4092
|
+
}
|
|
4093
|
+
|
|
4094
|
+
if (dp == tuya.dataPoints.scheduleWorkday) {
|
|
4095
|
+
return {workdays: items, workdays_schedule: programmingMode.join(' ')};
|
|
4096
|
+
} else {
|
|
4097
|
+
return {holidays: items, holidays_schedule: programmingMode.join(' ')};
|
|
4098
|
+
}
|
|
4099
|
+
}
|
|
3898
4100
|
case tuya.dataPoints.childLock:
|
|
3899
4101
|
return {child_lock: value ? 'LOCK' : 'UNLOCK'};
|
|
3900
4102
|
case tuya.dataPoints.siterwellWindowDetection:
|
|
@@ -5810,6 +6012,11 @@ const converters = {
|
|
|
5810
6012
|
};
|
|
5811
6013
|
|
|
5812
6014
|
const data = utf8FromStr(msg['data']['16896']);
|
|
6015
|
+
|
|
6016
|
+
clearTimeout(globalStore.getValue(msg.endpoint, 'timer'));
|
|
6017
|
+
const timer = setTimeout(() => publish({action: 'lock', state: 'LOCK'}), 2 * 1000);
|
|
6018
|
+
globalStore.putValue(msg.endpoint, 'timer', timer);
|
|
6019
|
+
|
|
5813
6020
|
return {
|
|
5814
6021
|
action: 'unlock',
|
|
5815
6022
|
action_user: data[3],
|
|
@@ -5818,6 +6025,77 @@ const converters = {
|
|
|
5818
6025
|
};
|
|
5819
6026
|
},
|
|
5820
6027
|
},
|
|
6028
|
+
javis_microwave_sensor: {
|
|
6029
|
+
cluster: 'manuSpecificTuya',
|
|
6030
|
+
type: ['commandSetDataResponse', 'commandGetData'],
|
|
6031
|
+
convert: (model, msg, publish, options, meta) => {
|
|
6032
|
+
const dp = msg.data.dp;
|
|
6033
|
+
const value = tuya.getDataValue(msg.data.datatype, msg.data.data);
|
|
6034
|
+
const lookup = {
|
|
6035
|
+
0: 'no_motion',
|
|
6036
|
+
1: 'big_motion',
|
|
6037
|
+
2: 'minor_motion',
|
|
6038
|
+
3: 'breathing',
|
|
6039
|
+
4: 'abnormal_state',
|
|
6040
|
+
5: 'initializing',
|
|
6041
|
+
6: 'initialization_completed',
|
|
6042
|
+
};
|
|
6043
|
+
switch (dp) {
|
|
6044
|
+
case 1:
|
|
6045
|
+
return {
|
|
6046
|
+
states: lookup[value],
|
|
6047
|
+
occupancy: (0 < value && value < 5) ? true: false,
|
|
6048
|
+
};
|
|
6049
|
+
case 2:
|
|
6050
|
+
return {
|
|
6051
|
+
sensitivity: value,
|
|
6052
|
+
};
|
|
6053
|
+
case 101:
|
|
6054
|
+
return {
|
|
6055
|
+
illuminance_lux: value,
|
|
6056
|
+
};
|
|
6057
|
+
case 102:
|
|
6058
|
+
if (meta.device.manufacturerName === '_TZE200_kagkgk0i') {
|
|
6059
|
+
return {
|
|
6060
|
+
illuminance_calibration: value,
|
|
6061
|
+
};
|
|
6062
|
+
} else {
|
|
6063
|
+
return {
|
|
6064
|
+
keep_time: value,
|
|
6065
|
+
};
|
|
6066
|
+
}
|
|
6067
|
+
case 103:
|
|
6068
|
+
return {
|
|
6069
|
+
led_enable: value == 1 ? true : false,
|
|
6070
|
+
};
|
|
6071
|
+
case 104:
|
|
6072
|
+
return {illuminance_lux: value};
|
|
6073
|
+
case 105:
|
|
6074
|
+
return {
|
|
6075
|
+
illuminance_calibration: value,
|
|
6076
|
+
};
|
|
6077
|
+
case 106:
|
|
6078
|
+
if (meta.device.manufacturerName === '_TZE200_kagkgk0i') {
|
|
6079
|
+
return {
|
|
6080
|
+
keep_time: value,
|
|
6081
|
+
};
|
|
6082
|
+
} else {
|
|
6083
|
+
break;
|
|
6084
|
+
}
|
|
6085
|
+
case 107:
|
|
6086
|
+
if (meta.device.manufacturerName === '_TZE200_kagkgk0i') {
|
|
6087
|
+
return {
|
|
6088
|
+
led_enable: value == 1 ? true : false,
|
|
6089
|
+
};
|
|
6090
|
+
} else {
|
|
6091
|
+
break;
|
|
6092
|
+
}
|
|
6093
|
+
default:
|
|
6094
|
+
meta.logger.warn(`zigbee-herdsman-converters:javis_microwave_sensor: NOT RECOGNIZED ` +
|
|
6095
|
+
`DP #${dp} with data ${JSON.stringify(msg.data)}`);
|
|
6096
|
+
}
|
|
6097
|
+
},
|
|
6098
|
+
},
|
|
5821
6099
|
diyruz_freepad_config: {
|
|
5822
6100
|
cluster: 'genOnOffSwitchCfg',
|
|
5823
6101
|
type: ['readResponse'],
|
|
@@ -6047,12 +6325,34 @@ const converters = {
|
|
|
6047
6325
|
DJT11LM_vibration: {
|
|
6048
6326
|
cluster: 'closuresDoorLock',
|
|
6049
6327
|
type: ['attributeReport', 'readResponse'],
|
|
6328
|
+
options: [exposes.options.vibration_timeout()],
|
|
6050
6329
|
convert: (model, msg, publish, options, meta) => {
|
|
6051
6330
|
const result = {};
|
|
6052
6331
|
|
|
6053
6332
|
if (msg.data['85']) {
|
|
6054
6333
|
const vibrationLookup = {1: 'vibration', 2: 'tilt', 3: 'drop'};
|
|
6055
6334
|
result.action = vibrationLookup[msg.data['85']];
|
|
6335
|
+
|
|
6336
|
+
// Device only sends a message when vibration is detected.
|
|
6337
|
+
// Therefore we need to publish a no_vibration message on our own.
|
|
6338
|
+
if (result.action === 'vibration') {
|
|
6339
|
+
result.vibration = true;
|
|
6340
|
+
|
|
6341
|
+
const timeout = options && options.hasOwnProperty('vibration_timeout') ? options.vibration_timeout : 90;
|
|
6342
|
+
|
|
6343
|
+
// Stop any existing timer cause vibration detected
|
|
6344
|
+
clearTimeout(globalStore.getValue(msg.endpoint, 'vibration_timer', null));
|
|
6345
|
+
globalStore.putValue(msg.endpoint, 'vibration_timer', null);
|
|
6346
|
+
|
|
6347
|
+
// Set new timer to publish no_vibration message
|
|
6348
|
+
if (timeout !== 0) {
|
|
6349
|
+
const timer = setTimeout(() => {
|
|
6350
|
+
publish({vibration: false});
|
|
6351
|
+
}, timeout * 1000);
|
|
6352
|
+
|
|
6353
|
+
globalStore.putValue(msg.endpoint, 'vibration_timer', timer);
|
|
6354
|
+
}
|
|
6355
|
+
}
|
|
6056
6356
|
}
|
|
6057
6357
|
|
|
6058
6358
|
if (msg.data['1283']) {
|
package/converters/toZigbee.js
CHANGED
|
@@ -15,6 +15,7 @@ const manufacturerOptions = {
|
|
|
15
15
|
osram: {manufacturerCode: herdsman.Zcl.ManufacturerCode.OSRAM},
|
|
16
16
|
eurotronic: {manufacturerCode: herdsman.Zcl.ManufacturerCode.JENNIC},
|
|
17
17
|
danfoss: {manufacturerCode: herdsman.Zcl.ManufacturerCode.DANFOSS},
|
|
18
|
+
develco: {manufacturerCode: herdsman.Zcl.ManufacturerCode.DEVELCO},
|
|
18
19
|
hue: {manufacturerCode: herdsman.Zcl.ManufacturerCode.PHILIPS},
|
|
19
20
|
sinope: {manufacturerCode: herdsman.Zcl.ManufacturerCode.SINOPE_TECH},
|
|
20
21
|
/*
|
|
@@ -2569,6 +2570,34 @@ const converters = {
|
|
|
2569
2570
|
await entity.read('haDiagnostic', ['danfossMultimasterRole'], manufacturerOptions.danfoss);
|
|
2570
2571
|
},
|
|
2571
2572
|
},
|
|
2573
|
+
develco_pulse_configuration: {
|
|
2574
|
+
key: ['pulse_configuration'],
|
|
2575
|
+
convertSet: async (entity, key, value, meta) => {
|
|
2576
|
+
await entity.write('seMetering', {'develcoPulseConfiguration': value}, manufacturerOptions.develco);
|
|
2577
|
+
return {readAfterWriteTime: 200, state: {'pulse_configuration': value}};
|
|
2578
|
+
},
|
|
2579
|
+
convertGet: async (entity, key, meta) => {
|
|
2580
|
+
await entity.read('seMetering', ['develcoPulseConfiguration'], manufacturerOptions.develco);
|
|
2581
|
+
},
|
|
2582
|
+
},
|
|
2583
|
+
develco_interface_mode: {
|
|
2584
|
+
key: ['interface_mode'],
|
|
2585
|
+
convertSet: async (entity, key, value, meta) => {
|
|
2586
|
+
const payload = {'develcoInterfaceMode': utils.getKey(constants.develcoInterfaceMode, value, undefined, Number)};
|
|
2587
|
+
await entity.write('seMetering', payload, manufacturerOptions.develco);
|
|
2588
|
+
return {readAfterWriteTime: 200, state: {'interface_mode': value}};
|
|
2589
|
+
},
|
|
2590
|
+
convertGet: async (entity, key, meta) => {
|
|
2591
|
+
await entity.read('seMetering', ['develcoInterfaceMode'], manufacturerOptions.develco);
|
|
2592
|
+
},
|
|
2593
|
+
},
|
|
2594
|
+
develco_current_summation: {
|
|
2595
|
+
key: ['current_summation'],
|
|
2596
|
+
convertSet: async (entity, key, value, meta) => {
|
|
2597
|
+
await entity.write('seMetering', {'develcoCurrentSummation': value}, manufacturerOptions.develco);
|
|
2598
|
+
return {state: {'current_summation': value}};
|
|
2599
|
+
},
|
|
2600
|
+
},
|
|
2572
2601
|
ZMCSW032D_cover_position: {
|
|
2573
2602
|
key: ['position', 'tilt'],
|
|
2574
2603
|
convertSet: async (entity, key, value, meta) => {
|
|
@@ -2735,10 +2764,79 @@ const converters = {
|
|
|
2735
2764
|
await tuya.sendDataPointValue(entity, tuya.dataPoints.moesSminTempSet, temp);
|
|
2736
2765
|
},
|
|
2737
2766
|
},
|
|
2767
|
+
tvtwo_thermostat: {
|
|
2768
|
+
key: [
|
|
2769
|
+
'window_detection', 'frost_protection', 'child_lock',
|
|
2770
|
+
'current_heating_setpoint', 'local_temperature_calibration',
|
|
2771
|
+
'holiday_temperature', 'comfort_temperature', 'eco_temperature',
|
|
2772
|
+
'open_window_temperature', 'heating_stop', 'preset', 'boost_timeset_countdown',
|
|
2773
|
+
'holiday_mode_date', 'working_day', 'week_schedule', 'week', 'online',
|
|
2774
|
+
],
|
|
2775
|
+
convertSet: async (entity, key, value, meta) => {
|
|
2776
|
+
switch (key) {
|
|
2777
|
+
case 'preset': {
|
|
2778
|
+
const presetLookup = {'auto': 0, 'manual': 1, 'holiday': 3};
|
|
2779
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.tvMode, presetLookup[value]);
|
|
2780
|
+
return {state: {preset: value}};}
|
|
2781
|
+
case 'frost_protection':
|
|
2782
|
+
await tuya.sendDataPointBool(entity, tuya.dataPoints.tvFrostDetection, value === 'ON');
|
|
2783
|
+
break;
|
|
2784
|
+
case 'heating_stop':
|
|
2785
|
+
await tuya.sendDataPointBool(entity, tuya.dataPoints.tvHeatingStop, value === 'ON');
|
|
2786
|
+
break;
|
|
2787
|
+
case 'window_detection':
|
|
2788
|
+
await tuya.sendDataPointBool(entity, tuya.dataPoints.tvWindowDetection, value === 'ON');
|
|
2789
|
+
break;
|
|
2790
|
+
case 'child_lock':
|
|
2791
|
+
await tuya.sendDataPointBool(entity, tuya.dataPoints.tvChildLock, value === 'LOCK');
|
|
2792
|
+
break;
|
|
2793
|
+
case 'local_temperature_calibration':
|
|
2794
|
+
if (value > 0) value = value*10;
|
|
2795
|
+
if (value < 0) value = value*10 + 0x100000000;
|
|
2796
|
+
await tuya.sendDataPointValue(entity, tuya.dataPoints.tvTempCalibration, value);
|
|
2797
|
+
break;
|
|
2798
|
+
case 'current_heating_setpoint':
|
|
2799
|
+
await tuya.sendDataPointValue(entity, tuya.dataPoints.tvHeatingSetpoint, value * 10);
|
|
2800
|
+
break;
|
|
2801
|
+
case 'holiday_temperature':
|
|
2802
|
+
await tuya.sendDataPointValue(entity, tuya.dataPoints.tvHolidayTemp, value * 10);
|
|
2803
|
+
break;
|
|
2804
|
+
case 'comfort_temperature':
|
|
2805
|
+
await tuya.sendDataPointValue(entity, tuya.dataPoints.tvComfortTemp, value * 10);
|
|
2806
|
+
break;
|
|
2807
|
+
case 'eco_temperature':
|
|
2808
|
+
await tuya.sendDataPointValue(entity, tuya.dataPoints.tvEcoTemp, value * 10);
|
|
2809
|
+
break;
|
|
2810
|
+
case 'boost_timeset_countdown':
|
|
2811
|
+
// set min 0 - max 465 sec boost time
|
|
2812
|
+
await tuya.sendDataPointValue(entity, tuya.dataPoints.tvBoostTime, value);
|
|
2813
|
+
break;
|
|
2814
|
+
case 'open_window_temperature':
|
|
2815
|
+
await tuya.sendDataPointValue(entity, tuya.dataPoints.tvOpenWindowTemp, value * 10);
|
|
2816
|
+
break;
|
|
2817
|
+
case 'holiday_mode_date':
|
|
2818
|
+
await tuya.sendDataPointBitmap(entity, tuya.dataPoints.tvWorkingDayTimetvHolidayMode, value);
|
|
2819
|
+
break;
|
|
2820
|
+
|
|
2821
|
+
case 'online':
|
|
2822
|
+
// 115 ????? online
|
|
2823
|
+
await tuya.sendDataPointBool(entity, tuya.dataPoints.tvBoostMode, value === 'ON');
|
|
2824
|
+
break;
|
|
2825
|
+
case 'week': {
|
|
2826
|
+
const weekLookup = {'5+2': 0, '6+1': 1, '7': 2};
|
|
2827
|
+
const week = weekLookup[value];
|
|
2828
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.tvWorkingDay, week);
|
|
2829
|
+
return {state: {week: value}};}
|
|
2830
|
+
|
|
2831
|
+
default: // Unknown key
|
|
2832
|
+
meta.logger.warn(`toZigbee.tvtwo_thermostat: Unhandled key ${key}`);
|
|
2833
|
+
}
|
|
2834
|
+
},
|
|
2835
|
+
},
|
|
2738
2836
|
haozee_thermostat_system_mode: {
|
|
2739
2837
|
key: ['preset'],
|
|
2740
2838
|
convertSet: async (entity, key, value, meta) => {
|
|
2741
|
-
const lookup = {
|
|
2839
|
+
const lookup = {'auto': 0, 'manual': 1, 'off': 2, 'on': 3};
|
|
2742
2840
|
await tuya.sendDataPointEnum(entity, tuya.dataPoints.haozeeSystemMode, lookup[value]);
|
|
2743
2841
|
},
|
|
2744
2842
|
},
|
|
@@ -2776,7 +2874,7 @@ const converters = {
|
|
|
2776
2874
|
haozee_thermostat_temperature_calibration: {
|
|
2777
2875
|
key: ['local_temperature_calibration'],
|
|
2778
2876
|
convertSet: async (entity, key, value, meta) => {
|
|
2779
|
-
let temp = Math.round(value *
|
|
2877
|
+
let temp = Math.round(value * 10);
|
|
2780
2878
|
if (temp < 0) {
|
|
2781
2879
|
temp = 0xFFFFFFFF + temp + 1;
|
|
2782
2880
|
}
|
|
@@ -4488,6 +4586,34 @@ const converters = {
|
|
|
4488
4586
|
}
|
|
4489
4587
|
},
|
|
4490
4588
|
},
|
|
4589
|
+
tuya_thermostat_schedule_programming_mode: { // payload example "00:20/5°C 01:20/5°C 6:59/15°C 18:00/5°C 20:00/5°C 23:30/5°C"
|
|
4590
|
+
key: ['workdays_schedule', 'holidays_schedule'],
|
|
4591
|
+
convertSet: async (entity, key, value, meta) => {
|
|
4592
|
+
const dpId =
|
|
4593
|
+
(key === 'workdays_schedule') ?
|
|
4594
|
+
tuya.dataPoints.scheduleWorkday :
|
|
4595
|
+
tuya.dataPoints.scheduleHoliday;
|
|
4596
|
+
const payload = [];
|
|
4597
|
+
const items = value.split(' ');
|
|
4598
|
+
|
|
4599
|
+
for (let i = 0; i < 6; i++) {
|
|
4600
|
+
const hourTemperature = items[i].split('/');
|
|
4601
|
+
const hourMinute = hourTemperature[0].split(':', 2);
|
|
4602
|
+
const hour = parseInt(hourMinute[0]);
|
|
4603
|
+
const minute = parseInt(hourMinute[1]);
|
|
4604
|
+
const temperature = parseInt(hourTemperature[1]);
|
|
4605
|
+
|
|
4606
|
+
if (hour < 0 || hour >= 24 || minute < 0 || minute >= 60 || temperature < 5 || temperature >= 35) {
|
|
4607
|
+
throw new Error('Invalid hour, minute or temperature of:' + items[i]);
|
|
4608
|
+
}
|
|
4609
|
+
|
|
4610
|
+
payload[i*3] = hour;
|
|
4611
|
+
payload[i*3+1] = minute;
|
|
4612
|
+
payload[i*3+2] = temperature;
|
|
4613
|
+
}
|
|
4614
|
+
tuya.sendDataPointRaw(entity, dpId, payload);
|
|
4615
|
+
},
|
|
4616
|
+
},
|
|
4491
4617
|
tuya_thermostat_week: {
|
|
4492
4618
|
key: ['week'],
|
|
4493
4619
|
convertSet: async (entity, key, value, meta) => {
|
|
@@ -6011,6 +6137,46 @@ const converters = {
|
|
|
6011
6137
|
}
|
|
6012
6138
|
},
|
|
6013
6139
|
},
|
|
6140
|
+
javis_microwave_sensor: {
|
|
6141
|
+
key: [
|
|
6142
|
+
'illuminance_calibration', 'led_enable',
|
|
6143
|
+
'sensitivity', 'keep_time',
|
|
6144
|
+
],
|
|
6145
|
+
convertSet: async (entity, key, value, meta) => {
|
|
6146
|
+
switch (key) {
|
|
6147
|
+
case 'illuminance_calibration':// (10--100) sensor illuminance sensitivity
|
|
6148
|
+
if (meta.device.manufacturerName === '_TZE200_kagkgk0i') {
|
|
6149
|
+
await tuya.sendDataPointRaw(entity, 102, [value]);
|
|
6150
|
+
break;
|
|
6151
|
+
} else {
|
|
6152
|
+
tuya.sendDataPointRaw(entity, 105, [value]);
|
|
6153
|
+
break;
|
|
6154
|
+
}
|
|
6155
|
+
case 'led_enable':// OK (value true/false or 1/0)
|
|
6156
|
+
if (meta.device.manufacturerName === '_TZE200_kagkgk0i') {
|
|
6157
|
+
await tuya.sendDataPointRaw(entity, 107, [value ? 1 : 0]);
|
|
6158
|
+
break;
|
|
6159
|
+
} else {
|
|
6160
|
+
await tuya.sendDataPointRaw(entity, 103, [value ? 1 : 0]);
|
|
6161
|
+
break;
|
|
6162
|
+
}
|
|
6163
|
+
|
|
6164
|
+
case 'sensitivity':// value: 25, 50, 75, 100
|
|
6165
|
+
await tuya.sendDataPointRaw(entity, 2, [value]);
|
|
6166
|
+
break;
|
|
6167
|
+
case 'keep_time': // value 0 --> 7 corresponding 5s, 30s, 1, 3, 5, 10, 20, 30 min
|
|
6168
|
+
if (meta.device.manufacturerName === '_TZE200_kagkgk0i') {
|
|
6169
|
+
await tuya.sendDataPointRaw(entity, 106, [value]);
|
|
6170
|
+
break;
|
|
6171
|
+
} else {
|
|
6172
|
+
await tuya.sendDataPointRaw(entity, 102, [value]);
|
|
6173
|
+
break;
|
|
6174
|
+
}
|
|
6175
|
+
default: // Unknown key
|
|
6176
|
+
throw new Error(`Unhandled key ${key}`);
|
|
6177
|
+
}
|
|
6178
|
+
},
|
|
6179
|
+
},
|
|
6014
6180
|
moes_thermostat_tv: {
|
|
6015
6181
|
key: [
|
|
6016
6182
|
'system_mode', 'window_detection', 'frost_detection', 'child_lock',
|