zigbee-herdsman-converters 15.0.43 → 15.0.45
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 +25 -117
- package/converters/toZigbee.js +12 -74
- package/devices/bitron.js +39 -8
- package/devices/custom_devices_diy.js +2 -2
- package/devices/essentialb.js +51 -2
- package/devices/ewelink.js +1 -1
- package/devices/frankever.js +1 -1
- package/devices/ikea.js +0 -1
- package/devices/livolo.js +37 -0
- package/devices/lonsonho.js +1 -1
- package/devices/mercator.js +4 -0
- package/devices/moes.js +2 -2
- package/devices/namron.js +1 -0
- package/devices/neo.js +2 -2
- package/devices/philips.js +27 -31
- package/devices/sengled.js +5 -3
- package/devices/third_reality.js +1 -0
- package/devices/tuya.js +60 -31
- package/devices/xiaomi.js +27 -4
- package/lib/exposes.js +8 -0
- package/lib/philips.js +3 -3
- package/lib/tuya.js +58 -39
- package/lib/xiaomi.d.ts +11 -0
- package/lib/xiaomi.js +306 -0
- package/package.json +1 -1
package/converters/fromZigbee.js
CHANGED
|
@@ -3068,6 +3068,21 @@ const converters = {
|
|
|
3068
3068
|
}
|
|
3069
3069
|
},
|
|
3070
3070
|
},
|
|
3071
|
+
livolo_pir_state: {
|
|
3072
|
+
cluster: 'genPowerCfg',
|
|
3073
|
+
type: ['raw'],
|
|
3074
|
+
convert: (model, msg, publish, options, meta) => {
|
|
3075
|
+
const stateHeader = Buffer.from([122, 209]);
|
|
3076
|
+
if (msg.data.indexOf(stateHeader) === 0) {
|
|
3077
|
+
if (msg.data[10] === 7) {
|
|
3078
|
+
const status = msg.data[14];
|
|
3079
|
+
return {
|
|
3080
|
+
occupancy: status & 1 ? true : false,
|
|
3081
|
+
};
|
|
3082
|
+
}
|
|
3083
|
+
}
|
|
3084
|
+
},
|
|
3085
|
+
},
|
|
3071
3086
|
easycode_action: {
|
|
3072
3087
|
cluster: 'closuresDoorLock',
|
|
3073
3088
|
type: 'raw',
|
|
@@ -3126,6 +3141,11 @@ const converters = {
|
|
|
3126
3141
|
[122,209, 110,74,116,33,0,75,18,0, 5,1,5,0,2,11] left: 0, right: 0 (off)
|
|
3127
3142
|
[122,209, 110,74,116,33,0,75,18,0, 5,1,5,0,1,11] left: 1, right: 0 (left on)
|
|
3128
3143
|
[122,209, 110,74,116,33,0,75,18,0, 5,1,5,0,0,11] left: 0, right: 1 (right on)
|
|
3144
|
+
|
|
3145
|
+
pir sensor
|
|
3146
|
+
[124,210,21,216,128, 225,52,225,34,0,75,18,0, 19,13,0] after interview
|
|
3147
|
+
[122,209, 245,94,225,34,0,75,18,0, 7,1,7,1,1,11] occupancy: true
|
|
3148
|
+
[122,209, 245,94,225,34,0,75,18,0, 7,1,7,1,0,11] occupancy: false
|
|
3129
3149
|
*/
|
|
3130
3150
|
const malformedHeader = Buffer.from([0x7c, 0xd2, 0x15, 0xd8, 0x00]);
|
|
3131
3151
|
const infoHeader = Buffer.from([0x7c, 0xd2, 0x15, 0xd8, 0x80]);
|
|
@@ -3170,6 +3190,11 @@ const converters = {
|
|
|
3170
3190
|
meta.device.modelID = 'TI0001-cover';
|
|
3171
3191
|
meta.device.save();
|
|
3172
3192
|
}
|
|
3193
|
+
if (msg.data.includes(Buffer.from([19, 13, 0]), 13)) {
|
|
3194
|
+
if (meta.logger) meta.logger.debug('Detected Livolo Pir Sensor');
|
|
3195
|
+
meta.device.modelID = 'TI0001-pir';
|
|
3196
|
+
meta.device.save();
|
|
3197
|
+
}
|
|
3173
3198
|
}
|
|
3174
3199
|
},
|
|
3175
3200
|
},
|
|
@@ -4125,123 +4150,6 @@ const converters = {
|
|
|
4125
4150
|
}
|
|
4126
4151
|
},
|
|
4127
4152
|
},
|
|
4128
|
-
haozee_thermostat: {
|
|
4129
|
-
cluster: 'manuSpecificTuya',
|
|
4130
|
-
type: ['commandDataResponse', 'commandDataReport'],
|
|
4131
|
-
convert: (model, msg, publish, options, meta) => {
|
|
4132
|
-
const dpValue = tuya.firstDpValue(msg, meta, 'haozee_thermostat');
|
|
4133
|
-
const dp = dpValue.dp; // First we get the data point ID
|
|
4134
|
-
const value = tuya.getDataValue(dpValue);
|
|
4135
|
-
const presetLookup = {0: 'auto', 1: 'manual', 2: 'off', 3: 'on'};
|
|
4136
|
-
const systemModeLookup = {0: 'auto', 1: 'auto', 2: 'off', 3: 'heat'};
|
|
4137
|
-
switch (dp) {
|
|
4138
|
-
case tuya.dataPoints.haozeeSystemMode:
|
|
4139
|
-
return {preset: presetLookup[value], system_mode: systemModeLookup[value]};
|
|
4140
|
-
case tuya.dataPoints.haozeeHeatingSetpoint:
|
|
4141
|
-
return {current_heating_setpoint: (value / 10).toFixed(1)};
|
|
4142
|
-
case tuya.dataPoints.haozeeLocalTemp:
|
|
4143
|
-
return {local_temperature: (value / 10).toFixed(1)};
|
|
4144
|
-
case tuya.dataPoints.haozeeBoostHeatingCountdown:
|
|
4145
|
-
// quick heating countdown - not supported by this device
|
|
4146
|
-
return {boost_heating_countdown: value};
|
|
4147
|
-
case tuya.dataPoints.haozeeWindowDetection:
|
|
4148
|
-
// window check
|
|
4149
|
-
return {window_detection: value ? 'ON' : 'OFF'};
|
|
4150
|
-
case tuya.dataPoints.haozeeWindowState:
|
|
4151
|
-
// window state
|
|
4152
|
-
return {window: value ? 'OPEN' : 'CLOSED'};
|
|
4153
|
-
case tuya.dataPoints.haozeeChildLock:
|
|
4154
|
-
return {child_lock: value ? 'LOCK' : 'UNLOCK'};
|
|
4155
|
-
case tuya.dataPoints.haozeeBattery:
|
|
4156
|
-
// battery
|
|
4157
|
-
return {battery: value};
|
|
4158
|
-
case tuya.dataPoints.haozeeFaultAlarm:
|
|
4159
|
-
return {error: value ? 'ON': 'OFF'};
|
|
4160
|
-
case tuya.dataPoints.haozeeScheduleMonday:
|
|
4161
|
-
// Monday
|
|
4162
|
-
return {
|
|
4163
|
-
'monday_schedule': ' ' + value[1] + 'h:' + value[2] + 'm ' + value[4] / 10 + '°C' +
|
|
4164
|
-
', ' + value[5] + 'h:' + value[6] + 'm ' + value[8] / 10 + '°C' +
|
|
4165
|
-
', ' + value[9] + 'h:' + value[10] + 'm ' + value[12] / 10 + '°C' +
|
|
4166
|
-
', ' + value[13] + 'h:' + value[14] + 'm ' + value[16] / 10 + '°C ',
|
|
4167
|
-
};
|
|
4168
|
-
case tuya.dataPoints.haozeeScheduleTuesday:
|
|
4169
|
-
// Tuesday
|
|
4170
|
-
return {
|
|
4171
|
-
'tuesday_schedule': ' ' + value[1] + 'h:' + value[2] + 'm ' + value[4] / 10 + '°C' +
|
|
4172
|
-
', ' + value[5] + 'h:' + value[6] + 'm ' + value[8] / 10 + '°C' +
|
|
4173
|
-
', ' + value[9] + 'h:' + value[10] + 'm ' + value[12] / 10 + '°C' +
|
|
4174
|
-
', ' + value[13] + 'h:' + value[14] + 'm ' + value[16] / 10 + '°C ',
|
|
4175
|
-
};
|
|
4176
|
-
case tuya.dataPoints.haozeeScheduleWednesday:
|
|
4177
|
-
// wednesday
|
|
4178
|
-
return {
|
|
4179
|
-
'wednesday_schedule': ' ' + value[1] + 'h:' + value[2] + 'm ' + value[4] / 10 + '°C' +
|
|
4180
|
-
', ' + value[5] + 'h:' + value[6] + 'm ' + value[8] / 10 + '°C' +
|
|
4181
|
-
', ' + value[9] + 'h:' + value[10] + 'm ' + value[12] / 10 + '°C' +
|
|
4182
|
-
', ' + value[13] + 'h:' + value[14] + 'm ' + value[16] / 10 + '°C ',
|
|
4183
|
-
};
|
|
4184
|
-
case tuya.dataPoints.haozeeScheduleThursday:
|
|
4185
|
-
// Thursday
|
|
4186
|
-
return {
|
|
4187
|
-
'thursday_schedule': ' ' + value[1] + 'h:' + value[2] + 'm ' + value[4] / 10 + '°C' +
|
|
4188
|
-
', ' + value[5] + 'h:' + value[6] + 'm ' + value[8] / 10 + '°C' +
|
|
4189
|
-
', ' + value[9] + 'h:' + value[10] + 'm ' + value[12] / 10 + '°C' +
|
|
4190
|
-
', ' + value[13] + 'h:' + value[14] + 'm ' + value[16] / 10 + '°C ',
|
|
4191
|
-
};
|
|
4192
|
-
case tuya.dataPoints.haozeeScheduleFriday:
|
|
4193
|
-
// Friday
|
|
4194
|
-
return {
|
|
4195
|
-
'friday_schedule': ' ' + value[1] + 'h:' + value[2] + 'm ' + value[4] / 10 + '°C' +
|
|
4196
|
-
', ' + value[5] + 'h:' + value[6] + 'm ' + value[8] / 10 + '°C' +
|
|
4197
|
-
', ' + value[9] + 'h:' + value[10] + 'm ' + value[12] / 10 + '°C' +
|
|
4198
|
-
', ' + value[13] + 'h:' + value[14] + 'm ' + value[16] / 10 + '°C ',
|
|
4199
|
-
};
|
|
4200
|
-
case tuya.dataPoints.haozeeScheduleSaturday:
|
|
4201
|
-
// Saturday
|
|
4202
|
-
return {
|
|
4203
|
-
'saturday_schedule': ' ' + value[1] + 'h:' + value[2] + 'm ' + value[4] / 10 + '°C' +
|
|
4204
|
-
', ' + value[5] + 'h:' + value[6] + 'm ' + value[8] / 10 + '°C' +
|
|
4205
|
-
', ' + value[9] + 'h:' + value[10] + 'm ' + value[12] / 10 + '°C' +
|
|
4206
|
-
', ' + value[13] + 'h:' + value[14] + 'm ' + value[16] / 10 + '°C ',
|
|
4207
|
-
};
|
|
4208
|
-
case tuya.dataPoints.haozeeScheduleSunday:
|
|
4209
|
-
|
|
4210
|
-
// Sunday
|
|
4211
|
-
return {
|
|
4212
|
-
'sunday_schedule': ' ' + value[1] + 'h:' + value[2] + 'm ' + value[4] / 10 + '°C' +
|
|
4213
|
-
', ' + value[5] + 'h:' + value[6] + 'm ' + value[8] / 10 + '°C' +
|
|
4214
|
-
', ' + value[9] + 'h:' + value[10] + 'm ' + value[12] / 10 + '°C' +
|
|
4215
|
-
', ' + value[13] + 'h:' + value[14] + 'm ' + value[16] / 10 + '°C ',
|
|
4216
|
-
};
|
|
4217
|
-
|
|
4218
|
-
case tuya.dataPoints.haozeeRunningState:
|
|
4219
|
-
// working status 0 - pause 1 -working
|
|
4220
|
-
return {'heating': value ? 'ON' : 'OFF'};
|
|
4221
|
-
case tuya.dataPoints.haozeeBoostHeating:
|
|
4222
|
-
// rapid heating -> boolean - not supported by this device
|
|
4223
|
-
return {'boost_heating': value ? 'ON' : 'OFF'};
|
|
4224
|
-
case tuya.dataPoints.haozeeTempCalibration:
|
|
4225
|
-
// temperature calibration
|
|
4226
|
-
return {'local_temperature_calibration': ( value/10 ).toFixed(1)};
|
|
4227
|
-
case tuya.dataPoints.haozeeValvePosition:
|
|
4228
|
-
// valve position
|
|
4229
|
-
return {'position': ( value/10 ).toFixed(1)};
|
|
4230
|
-
case tuya.dataPoints.haozeeMinTemp:
|
|
4231
|
-
// lower limit temperature
|
|
4232
|
-
return {'min_temperature': ( value/10 ).toFixed(1)};
|
|
4233
|
-
case tuya.dataPoints.haozeeMaxTemp:
|
|
4234
|
-
// max limit temperature
|
|
4235
|
-
return {'max_temperature': ( value/10 ).toFixed(1)};
|
|
4236
|
-
case tuya.dataPoints.haozeeSoftVersion:
|
|
4237
|
-
// software
|
|
4238
|
-
break;
|
|
4239
|
-
default:
|
|
4240
|
-
meta.logger.warn(`zigbee-herdsman-converters:haozee: NOT RECOGNIZED DP #${
|
|
4241
|
-
dp} with data ${JSON.stringify(dpValue)}`);
|
|
4242
|
-
}
|
|
4243
|
-
},
|
|
4244
|
-
},
|
|
4245
4153
|
tuya_air_quality: {
|
|
4246
4154
|
cluster: 'manuSpecificTuya',
|
|
4247
4155
|
type: ['commandDataReport', 'commandDataResponse'],
|
package/converters/toZigbee.js
CHANGED
|
@@ -102,6 +102,12 @@ const converters = {
|
|
|
102
102
|
await entity.read('genPowerCfg', ['batteryPercentageRemaining']);
|
|
103
103
|
},
|
|
104
104
|
},
|
|
105
|
+
battery_voltage: {
|
|
106
|
+
key: ['battery', 'voltage'],
|
|
107
|
+
convertGet: async (entity, key, meta) => {
|
|
108
|
+
await entity.read('genPowerCfg', ['batteryVoltage']);
|
|
109
|
+
},
|
|
110
|
+
},
|
|
105
111
|
power_on_behavior: {
|
|
106
112
|
key: ['power_on_behavior'],
|
|
107
113
|
convertSet: async (entity, key, value, meta) => {
|
|
@@ -1260,7 +1266,12 @@ const converters = {
|
|
|
1260
1266
|
if (val === undefined) {
|
|
1261
1267
|
val = utils.getKey(constants.thermostatControlSequenceOfOperations, value, value, Number);
|
|
1262
1268
|
}
|
|
1263
|
-
|
|
1269
|
+
const attributes = {ctrlSeqeOfOper: val};
|
|
1270
|
+
await entity.write('hvacThermostat', attributes);
|
|
1271
|
+
// NOTE: update the cluster attribute we store as this is used by
|
|
1272
|
+
// SMaBiT AV2010/32's dynamic expose function.
|
|
1273
|
+
entity.saveClusterAttributeKeyValue('hvacThermostat', attributes);
|
|
1274
|
+
return {readAfterWriteTime: 250, state: {control_sequence_of_operation: value}};
|
|
1264
1275
|
},
|
|
1265
1276
|
convertGet: async (entity, key, meta) => {
|
|
1266
1277
|
await entity.read('hvacThermostat', ['ctrlSeqeOfOper']);
|
|
@@ -3474,79 +3485,6 @@ const converters = {
|
|
|
3474
3485
|
return tuya.sendDataPointRaw(entity, tuya.dataPoints.moesSschedule, payload);
|
|
3475
3486
|
},
|
|
3476
3487
|
},
|
|
3477
|
-
haozee_thermostat_preset: {
|
|
3478
|
-
key: ['preset'],
|
|
3479
|
-
convertSet: async (entity, key, value, meta) => {
|
|
3480
|
-
const lookup = {'auto': 0, 'manual': 1, 'off': 2, 'on': 3};
|
|
3481
|
-
await tuya.sendDataPointEnum(entity, tuya.dataPoints.haozeeSystemMode, lookup[value]);
|
|
3482
|
-
},
|
|
3483
|
-
},
|
|
3484
|
-
haozee_thermostat_system_mode: {
|
|
3485
|
-
key: ['system_mode'],
|
|
3486
|
-
convertSet: async (entity, key, value, meta) => {
|
|
3487
|
-
// mapping 'heat' system mode to 100% heating (same as preset 'ON'),
|
|
3488
|
-
// mapping 'auto' system mode to heating up to the set point temperature (same as preset 'MANUAL')
|
|
3489
|
-
// mapping 'off' system mode to idle (same as preset 'OFF')
|
|
3490
|
-
// programmed schedule can be enabled by using preset mode 'AUTO' instead of 'MANUAL'
|
|
3491
|
-
const lookup = {'auto': 1, 'off': 2, 'heat': 3};
|
|
3492
|
-
await tuya.sendDataPointEnum(entity, tuya.dataPoints.haozeeSystemMode, lookup[value]);
|
|
3493
|
-
},
|
|
3494
|
-
},
|
|
3495
|
-
haozee_thermostat_current_heating_setpoint: {
|
|
3496
|
-
key: ['current_heating_setpoint'],
|
|
3497
|
-
convertSet: async (entity, key, value, meta) => {
|
|
3498
|
-
const temp = Math.round(value*10);
|
|
3499
|
-
await tuya.sendDataPointValue(entity, tuya.dataPoints.haozeeHeatingSetpoint, temp);
|
|
3500
|
-
},
|
|
3501
|
-
},
|
|
3502
|
-
haozee_thermostat_boost_heating: {
|
|
3503
|
-
key: ['boost_heating'],
|
|
3504
|
-
convertSet: async (entity, key, value, meta) => {
|
|
3505
|
-
await tuya.sendDataPointBool(entity, tuya.dataPoints.haozeeBoostHeating, value === 'ON');
|
|
3506
|
-
},
|
|
3507
|
-
},
|
|
3508
|
-
haozee_thermostat_boost_heating_countdown: {
|
|
3509
|
-
key: ['boost_heating_countdown'],
|
|
3510
|
-
convertSet: async (entity, key, value, meta) => {
|
|
3511
|
-
await tuya.sendDataPointValue(entity, tuya.dataPoints.haozeeBoostHeatingCountdown, value);
|
|
3512
|
-
},
|
|
3513
|
-
},
|
|
3514
|
-
haozee_thermostat_window_detection: {
|
|
3515
|
-
key: ['window_detection'],
|
|
3516
|
-
convertSet: async (entity, key, value, meta) => {
|
|
3517
|
-
await tuya.sendDataPointBool(entity, tuya.dataPoints.haozeeWindowDetection, value === 'ON');
|
|
3518
|
-
},
|
|
3519
|
-
},
|
|
3520
|
-
haozee_thermostat_child_lock: {
|
|
3521
|
-
key: ['child_lock'],
|
|
3522
|
-
convertSet: async (entity, key, value, meta) => {
|
|
3523
|
-
await tuya.sendDataPointBool(entity, tuya.dataPoints.haozeeChildLock, value === 'LOCK');
|
|
3524
|
-
},
|
|
3525
|
-
},
|
|
3526
|
-
haozee_thermostat_temperature_calibration: {
|
|
3527
|
-
key: ['local_temperature_calibration'],
|
|
3528
|
-
convertSet: async (entity, key, value, meta) => {
|
|
3529
|
-
let temp = Math.round(value * 10);
|
|
3530
|
-
if (temp < 0) {
|
|
3531
|
-
temp = 0xFFFFFFFF + temp + 1;
|
|
3532
|
-
}
|
|
3533
|
-
await tuya.sendDataPointValue(entity, tuya.dataPoints.haozeeTempCalibration, temp);
|
|
3534
|
-
},
|
|
3535
|
-
},
|
|
3536
|
-
haozee_thermostat_max_temperature: {
|
|
3537
|
-
key: ['max_temperature'],
|
|
3538
|
-
convertSet: async (entity, key, value, meta) => {
|
|
3539
|
-
const temp = Math.round(value*10);
|
|
3540
|
-
await tuya.sendDataPointValue(entity, tuya.dataPoints.haozeeMaxTemp, temp);
|
|
3541
|
-
},
|
|
3542
|
-
},
|
|
3543
|
-
haozee_thermostat_min_temperature: {
|
|
3544
|
-
key: ['min_temperature'],
|
|
3545
|
-
convertSet: async (entity, key, value, meta) => {
|
|
3546
|
-
const temp = Math.round(value*10);
|
|
3547
|
-
await tuya.sendDataPointValue(entity, tuya.dataPoints.haozeeMinTemp, temp);
|
|
3548
|
-
},
|
|
3549
|
-
},
|
|
3550
3488
|
hgkg_thermostat_standby: {
|
|
3551
3489
|
key: ['system_mode'],
|
|
3552
3490
|
convertSet: async (entity, key, value, meta) => {
|
package/devices/bitron.js
CHANGED
|
@@ -4,6 +4,7 @@ const tz = require('../converters/toZigbee');
|
|
|
4
4
|
const reporting = require('../lib/reporting');
|
|
5
5
|
const extend = require('../lib/extend');
|
|
6
6
|
const e = exposes.presets;
|
|
7
|
+
const ea = exposes.access;
|
|
7
8
|
|
|
8
9
|
module.exports = [
|
|
9
10
|
{
|
|
@@ -190,13 +191,43 @@ module.exports = [
|
|
|
190
191
|
vendor: 'SMaBiT (Bitron Video)',
|
|
191
192
|
description: 'Wireless wall thermostat with relay',
|
|
192
193
|
fromZigbee: [fz.legacy.thermostat_att_report, fz.battery, fz.hvac_user_interface],
|
|
193
|
-
toZigbee: [
|
|
194
|
-
tz.
|
|
195
|
-
tz.
|
|
196
|
-
|
|
197
|
-
.
|
|
198
|
-
|
|
199
|
-
|
|
194
|
+
toZigbee: [
|
|
195
|
+
tz.thermostat_control_sequence_of_operation, tz.thermostat_occupied_heating_setpoint,
|
|
196
|
+
tz.thermostat_occupied_cooling_setpoint, tz.thermostat_local_temperature_calibration,
|
|
197
|
+
tz.thermostat_local_temperature, tz.thermostat_running_state, tz.thermostat_temperature_display_mode,
|
|
198
|
+
tz.thermostat_keypad_lockout, tz.thermostat_system_mode, tz.battery_voltage,
|
|
199
|
+
],
|
|
200
|
+
exposes: (device, options) => {
|
|
201
|
+
const dynExposes = [];
|
|
202
|
+
let ctrlSeqeOfOper = device ? device.getEndpoint(1).getClusterAttributeValue('hvacThermostat', 'ctrlSeqeOfOper') : null;
|
|
203
|
+
const modes = [];
|
|
204
|
+
|
|
205
|
+
// NOTE: ctrlSeqeOfOper defaults to 2 for this device (according to the manual)
|
|
206
|
+
if (ctrlSeqeOfOper == null) ctrlSeqeOfOper = 2;
|
|
207
|
+
|
|
208
|
+
// NOTE: set cool and/or heat support based on ctrlSeqeOfOper (see lib/constants -> thermostatControlSequenceOfOperations)
|
|
209
|
+
// WARN: a restart of zigbee2mqtt is required after changing ctrlSeqeOfOper for expose data to be re-calculated
|
|
210
|
+
if (ctrlSeqeOfOper >= 2) {
|
|
211
|
+
modes.push('heat');
|
|
212
|
+
}
|
|
213
|
+
if (ctrlSeqeOfOper < 2 || ctrlSeqeOfOper > 3) {
|
|
214
|
+
modes.push('cool');
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
dynExposes.push(exposes.climate()
|
|
218
|
+
.withSetpoint('occupied_heating_setpoint', 7, 30, 0.5)
|
|
219
|
+
.withLocalTemperature()
|
|
220
|
+
.withSystemMode(['off'].concat(modes))
|
|
221
|
+
.withRunningState(['idle'].concat(modes))
|
|
222
|
+
.withLocalTemperatureCalibration()
|
|
223
|
+
.withControlSequenceOfOperation(['heating_only', 'cooling_only'], ea.ALL));
|
|
224
|
+
dynExposes.push(e.keypad_lockout());
|
|
225
|
+
dynExposes.push(e.battery().withAccess(ea.STATE_GET));
|
|
226
|
+
dynExposes.push(e.battery_low());
|
|
227
|
+
dynExposes.push(e.linkquality());
|
|
228
|
+
return dynExposes;
|
|
229
|
+
},
|
|
230
|
+
meta: {battery: {voltageToPercentage: '3V_2500'}},
|
|
200
231
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
201
232
|
const endpoint = device.getEndpoint(1);
|
|
202
233
|
const binds = [
|
|
@@ -204,12 +235,12 @@ module.exports = [
|
|
|
204
235
|
];
|
|
205
236
|
await reporting.bind(endpoint, coordinatorEndpoint, binds);
|
|
206
237
|
await reporting.thermostatTemperature(endpoint);
|
|
207
|
-
await reporting.thermostatTemperatureCalibration(endpoint);
|
|
208
238
|
await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
|
|
209
239
|
await reporting.thermostatOccupiedCoolingSetpoint(endpoint);
|
|
210
240
|
await reporting.thermostatRunningState(endpoint);
|
|
211
241
|
await reporting.batteryAlarmState(endpoint);
|
|
212
242
|
await reporting.batteryVoltage(endpoint);
|
|
243
|
+
await endpoint.read('hvacThermostat', ['ctrlSeqeOfOper', 'localTemperatureCalibration']);
|
|
213
244
|
},
|
|
214
245
|
},
|
|
215
246
|
{
|
|
@@ -473,7 +473,7 @@ module.exports = [
|
|
|
473
473
|
await firstEndpoint.configureReporting('genPowerCfg', payload1);
|
|
474
474
|
},
|
|
475
475
|
exposes: [e.soil_moisture(), e.battery(), e.temperature(),
|
|
476
|
-
exposes.numeric('report_delay', ea.STATE_SET).withUnit('
|
|
476
|
+
exposes.numeric('report_delay', ea.STATE_SET).withUnit('min').withValueMin(1).withValueMax(240)
|
|
477
477
|
.withDescription('Adjust Report Delay. Setting the time in minutes, by default 15 minutes')],
|
|
478
478
|
},
|
|
479
479
|
{
|
|
@@ -823,7 +823,7 @@ module.exports = [
|
|
|
823
823
|
await reporting.batteryPercentageRemaining(endpoint, overides);
|
|
824
824
|
},
|
|
825
825
|
exposes: [e.battery(), e.temperature(), e.humidity(),
|
|
826
|
-
exposes.numeric('report_delay', ea.STATE_SET).withUnit('
|
|
826
|
+
exposes.numeric('report_delay', ea.STATE_SET).withUnit('min')
|
|
827
827
|
.withDescription('Adjust Report Delay. Setting the time in minutes, by default 5 minutes')
|
|
828
828
|
.withValueMin(1).withValueMax(60),
|
|
829
829
|
exposes.binary('enable_temperature', ea.STATE_SET, 'ON', 'OFF').withDescription('Enable Temperature Control'),
|
package/devices/essentialb.js
CHANGED
|
@@ -8,11 +8,60 @@ module.exports = [
|
|
|
8
8
|
description: 'Smart LED bulb',
|
|
9
9
|
extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 370]}),
|
|
10
10
|
},
|
|
11
|
+
{
|
|
12
|
+
zigbeeModel: ['EB-E14-FLA-CCT'],
|
|
13
|
+
model: 'EB-E14-FLA-CCT',
|
|
14
|
+
vendor: 'EssentielB',
|
|
15
|
+
description: 'E14 flame CCT light bulb',
|
|
16
|
+
extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
zigbeeModel: ['EB-E27-A60-CCT-FC'],
|
|
20
|
+
model: 'EB-E27-A60-CCT-FC',
|
|
21
|
+
vendor: 'EssentielB',
|
|
22
|
+
description: 'E27 A60 CCT filament clear light bulb',
|
|
23
|
+
extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
zigbeeModel: ['EB-E27-A60-CCT'],
|
|
27
|
+
model: 'EB-E27-A60-CCT',
|
|
28
|
+
vendor: 'EssentielB',
|
|
29
|
+
description: 'E27 A60 CCT light bulb',
|
|
30
|
+
extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
zigbeeModel: ['EB-E27-A60-RGBW'],
|
|
34
|
+
model: 'EB-E27-A60-RGBW',
|
|
35
|
+
vendor: 'EssentielB',
|
|
36
|
+
description: 'E27 A60 RGBW light bulb',
|
|
37
|
+
extend: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 370]}),
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
zigbeeModel: ['EB-E27-G95-CCT-FV'],
|
|
41
|
+
model: 'EB-E27-G95-CCT-FV',
|
|
42
|
+
vendor: 'EssentielB',
|
|
43
|
+
description: 'Filament vintage globe light bulb',
|
|
44
|
+
extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
|
|
45
|
+
},
|
|
11
46
|
{
|
|
12
47
|
zigbeeModel: ['EB-E27-ST64-CCT-FV'],
|
|
13
48
|
model: 'EB-E27-ST64-CCT-FV',
|
|
14
49
|
vendor: 'EssentielB',
|
|
15
|
-
description: 'Filament vintage light bulb',
|
|
16
|
-
extend: extend.
|
|
50
|
+
description: 'Filament vintage edison light bulb',
|
|
51
|
+
extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
zigbeeModel: ['EB-GU10-MR16-CCT'],
|
|
55
|
+
model: 'EB-GU10-MR16-CCT',
|
|
56
|
+
vendor: 'EssentielB',
|
|
57
|
+
description: 'GU10 MR16 CCT light bulb',
|
|
58
|
+
extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
zigbeeModel: ['EB-GU10-MR16-RGBW'],
|
|
62
|
+
model: 'EB-GU10-MR16-RGBW',
|
|
63
|
+
vendor: 'EssentielB',
|
|
64
|
+
description: 'GU10 MR16 RGBW light bulb',
|
|
65
|
+
extend: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 370]}),
|
|
17
66
|
},
|
|
18
67
|
];
|
package/devices/ewelink.js
CHANGED
|
@@ -22,7 +22,7 @@ module.exports = [
|
|
|
22
22
|
model: 'SA-003-Zigbee',
|
|
23
23
|
vendor: 'eWeLink',
|
|
24
24
|
description: 'Zigbee smart plug',
|
|
25
|
-
extend: extend.switch(),
|
|
25
|
+
extend: extend.switch({disablePowerOnBehavior: true}),
|
|
26
26
|
fromZigbee: [fz.on_off_skip_duplicate_transaction],
|
|
27
27
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
28
28
|
const endpoint = device.getEndpoint(1);
|
package/devices/frankever.js
CHANGED
|
@@ -17,7 +17,7 @@ module.exports = [
|
|
|
17
17
|
exposes: [e.switch().setAccess('state', ea.STATE_SET),
|
|
18
18
|
exposes.numeric('threshold', exposes.access.STATE_SET).withValueMin(0).withValueMax(100).withUnit('%')
|
|
19
19
|
.withDescription('Valve open percentage (multiple of 10)'),
|
|
20
|
-
exposes.numeric('timer', exposes.access.STATE_SET).withValueMin(0).withValueMax(600).withUnit('
|
|
20
|
+
exposes.numeric('timer', exposes.access.STATE_SET).withValueMin(0).withValueMax(600).withUnit('min')
|
|
21
21
|
.withDescription('Countdown timer in minutes')],
|
|
22
22
|
},
|
|
23
23
|
];
|
package/devices/ikea.js
CHANGED
|
@@ -741,7 +741,6 @@ module.exports = [
|
|
|
741
741
|
exposes.binary('illuminance_above_threshold', ea.STATE, true, false)
|
|
742
742
|
.withDescription('Indicates whether the device detected bright light (works only in night mode)')],
|
|
743
743
|
ota: ota.tradfri,
|
|
744
|
-
meta: {battery: {dontDividePercentage: true}},
|
|
745
744
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
746
745
|
const endpoint = device.getEndpoint(1);
|
|
747
746
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
|
package/devices/livolo.js
CHANGED
|
@@ -246,4 +246,41 @@ module.exports = [
|
|
|
246
246
|
}
|
|
247
247
|
},
|
|
248
248
|
},
|
|
249
|
+
{
|
|
250
|
+
zigbeeModel: ['TI0001-pir'],
|
|
251
|
+
model: 'TI0001-pir',
|
|
252
|
+
description: 'Zigbee motion Sensor',
|
|
253
|
+
vendor: 'Livolo',
|
|
254
|
+
exposes: [
|
|
255
|
+
e.occupancy(),
|
|
256
|
+
],
|
|
257
|
+
fromZigbee: [fz.livolo_pir_state],
|
|
258
|
+
toZigbee: [],
|
|
259
|
+
configure: poll,
|
|
260
|
+
onEvent: async (type, data, device) => {
|
|
261
|
+
if (type === 'stop') {
|
|
262
|
+
clearInterval(globalStore.getValue(device, 'interval'));
|
|
263
|
+
globalStore.clearValue(device, 'interval');
|
|
264
|
+
}
|
|
265
|
+
if (['start', 'deviceAnnounce'].includes(type)) {
|
|
266
|
+
await poll(device);
|
|
267
|
+
if (!globalStore.hasValue(device, 'interval')) {
|
|
268
|
+
const interval = setInterval(async () => await poll(device), 10*1000);
|
|
269
|
+
globalStore.putValue(device, 'interval', interval);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
if (data.cluster === 'genPowerCfg' && data.type === 'raw') {
|
|
273
|
+
const dp = data.data[10];
|
|
274
|
+
if (data.data[0] === 0x7a && data.data[1] === 0xd1) {
|
|
275
|
+
const endpoint = device.getEndpoint(6);
|
|
276
|
+
if (dp === 0x01) {
|
|
277
|
+
const options = {manufacturerCode: 0x1ad2, disableDefaultResponse: true, disableResponse: true,
|
|
278
|
+
reservedBits: 3, direction: 1, writeUndiv: true};
|
|
279
|
+
const payload = {0x2002: {value: [0, 0, 0, 0, 0, 0, 0], type: 0x0e}};
|
|
280
|
+
await endpoint.readResponse('genPowerCfg', 0xe9, payload, options);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
},
|
|
249
286
|
];
|
package/devices/lonsonho.js
CHANGED
|
@@ -27,7 +27,7 @@ module.exports = [
|
|
|
27
27
|
description: 'Curtain switch',
|
|
28
28
|
fromZigbee: [fz.cover_position_tilt, tuya.fz.backlight_mode_low_medium_high, fz.tuya_cover_options],
|
|
29
29
|
toZigbee: [tz.cover_state, tz.cover_position_tilt, tz.tuya_cover_calibration, tz.tuya_cover_reversal,
|
|
30
|
-
tuya.tz.
|
|
30
|
+
tuya.tz.backlight_indicator_mode_1],
|
|
31
31
|
meta: {coverInverted: true},
|
|
32
32
|
exposes: [e.cover_position(), exposes.enum('moving', ea.STATE, ['UP', 'STOP', 'DOWN']),
|
|
33
33
|
exposes.binary('calibration', ea.ALL, 'ON', 'OFF'), exposes.binary('motor_reversal', ea.ALL, 'ON', 'OFF'),
|
package/devices/mercator.js
CHANGED
|
@@ -183,6 +183,10 @@ module.exports = [
|
|
|
183
183
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genIdentify', 'manuSpecificTuya', 'hvacFanCtrl']);
|
|
184
184
|
await reporting.onOff(endpoint);
|
|
185
185
|
await reporting.fanMode(endpoint);
|
|
186
|
+
|
|
187
|
+
// Device ships with {fanModeSequence: 1} which restricts physical speed
|
|
188
|
+
// button to low/high. Set to 0 to allow low/med/high from physical press.
|
|
189
|
+
await endpoint.write('hvacFanCtrl', {fanModeSequence: 0});
|
|
186
190
|
},
|
|
187
191
|
},
|
|
188
192
|
{
|
package/devices/moes.js
CHANGED
|
@@ -308,9 +308,9 @@ module.exports = [
|
|
|
308
308
|
'You can set up to 4 stages of temperature every for WEEKDAY ➀➁➂➃➄, SATURDAY ➅ and SUNDAY ➆.'),
|
|
309
309
|
exposes.binary('boost_heating', ea.STATE_SET, 'ON', 'OFF').withDescription('Boost Heating: press and hold "+" for 3 seconds, ' +
|
|
310
310
|
'the device will enter the boost heating mode, and the ▷╵◁ will flash. The countdown will be displayed in the APP'),
|
|
311
|
-
exposes.numeric('boost_heating_countdown', ea.STATE).withUnit('
|
|
311
|
+
exposes.numeric('boost_heating_countdown', ea.STATE).withUnit('min').withDescription('Countdown in minutes')
|
|
312
312
|
.withValueMin(0).withValueMax(15),
|
|
313
|
-
exposes.numeric('boost_heating_countdown_time_set', ea.STATE_SET).withUnit('
|
|
313
|
+
exposes.numeric('boost_heating_countdown_time_set', ea.STATE_SET).withUnit('s')
|
|
314
314
|
.withDescription('Boost Time Setting 100 sec - 900 sec, (default = 300 sec)').withValueMin(100)
|
|
315
315
|
.withValueMax(900).withValueStep(100)],
|
|
316
316
|
},
|
package/devices/namron.js
CHANGED
|
@@ -116,6 +116,7 @@ module.exports = [
|
|
|
116
116
|
vendor: 'Namron',
|
|
117
117
|
description: 'ZigBee dimmer 400W',
|
|
118
118
|
extend: extend.light_onoff_brightness({noConfigure: true}),
|
|
119
|
+
ota: ota.zigbeeOTA,
|
|
119
120
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
120
121
|
await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
|
|
121
122
|
const endpoint = device.getEndpoint(1);
|
package/devices/neo.js
CHANGED
|
@@ -19,7 +19,7 @@ module.exports = [
|
|
|
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('
|
|
22
|
+
exposes.numeric('duration', ea.STATE_SET).withUnit('s').withValueMin(0).withValueMax(1800),
|
|
23
23
|
exposes.numeric('temperature_min', ea.STATE_SET).withUnit('°C').withValueMin(-20).withValueMax(80),
|
|
24
24
|
exposes.numeric('temperature_max', ea.STATE_SET).withUnit('°C').withValueMin(-20).withValueMax(80),
|
|
25
25
|
exposes.numeric('humidity_min', ea.STATE_SET).withUnit('%').withValueMin(1).withValueMax(100),
|
|
@@ -46,7 +46,7 @@ module.exports = [
|
|
|
46
46
|
e.battery_low(),
|
|
47
47
|
exposes.binary('alarm', ea.STATE_SET, true, false),
|
|
48
48
|
exposes.enum('melody', ea.STATE_SET, Array.from(Array(18).keys()).map((x)=>(x+1).toString())),
|
|
49
|
-
exposes.numeric('duration', ea.STATE_SET).withUnit('
|
|
49
|
+
exposes.numeric('duration', ea.STATE_SET).withUnit('s').withValueMin(0).withValueMax(1800),
|
|
50
50
|
exposes.enum('volume', ea.STATE_SET, ['low', 'medium', 'high']),
|
|
51
51
|
exposes.numeric('battpercentage', ea.STATE).withUnit('%'),
|
|
52
52
|
],
|