zigbee-herdsman-converters 14.0.569 → 14.0.570
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 +9 -4
- package/converters/toZigbee.js +11 -0
- package/devices/custom_devices_diy.js +160 -1
- package/devices/danfoss.js +5 -4
- package/devices/hgkg.js +38 -9
- package/devices/osram.js +2 -3
- package/devices/tuya.js +52 -0
- package/lib/exposes.js +2 -2
- package/lib/extend.js +2 -2
- package/lib/tuya.js +2 -0
- package/package.json +1 -1
package/converters/fromZigbee.js
CHANGED
|
@@ -3597,10 +3597,13 @@ const converters = {
|
|
|
3597
3597
|
msg.data['danfossRoomStatusCode'];
|
|
3598
3598
|
}
|
|
3599
3599
|
if (msg.data.hasOwnProperty('danfossOutputStatus')) {
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3600
|
+
if (msg.data['danfossOutputStatus'] === 1) {
|
|
3601
|
+
result[postfixWithEndpointName('output_status', msg, model)] = 'active';
|
|
3602
|
+
result[postfixWithEndpointName('running_state', msg, model)] = 'heat';
|
|
3603
|
+
} else {
|
|
3604
|
+
result[postfixWithEndpointName('output_status', msg, model)] = 'inactive';
|
|
3605
|
+
result[postfixWithEndpointName('running_state', msg, model)] = 'idle';
|
|
3606
|
+
}
|
|
3604
3607
|
}
|
|
3605
3608
|
return result;
|
|
3606
3609
|
},
|
|
@@ -4028,6 +4031,8 @@ const converters = {
|
|
|
4028
4031
|
default:
|
|
4029
4032
|
return {sensor: 'not_supported'};
|
|
4030
4033
|
}
|
|
4034
|
+
case tuya.dataPoints.bacFanMode:
|
|
4035
|
+
return {fan_mode: tuya.fanModes[value]};
|
|
4031
4036
|
default: // DataPoint 17 is unknown
|
|
4032
4037
|
meta.logger.warn(`zigbee-herdsman-converters:Moes BHT-002: Unrecognized DP #${
|
|
4033
4038
|
dp} with data ${JSON.stringify(dpValue)}`);
|
package/converters/toZigbee.js
CHANGED
|
@@ -4807,6 +4807,17 @@ const converters = {
|
|
|
4807
4807
|
}
|
|
4808
4808
|
},
|
|
4809
4809
|
},
|
|
4810
|
+
tuya_thermostat_bac_fan_mode: {
|
|
4811
|
+
key: ['fan_mode'],
|
|
4812
|
+
convertSet: async (entity, key, value, meta) => {
|
|
4813
|
+
const modeId = utils.getKey(tuya.fanModes, value, null, Number);
|
|
4814
|
+
if (modeId !== null) {
|
|
4815
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.bacFanMode, parseInt(modeId));
|
|
4816
|
+
} else {
|
|
4817
|
+
throw new Error(`TRV fan mode ${value} is not recognized.`);
|
|
4818
|
+
}
|
|
4819
|
+
},
|
|
4820
|
+
},
|
|
4810
4821
|
tuya_thermostat_auto_lock: {
|
|
4811
4822
|
key: ['auto_lock'],
|
|
4812
4823
|
convertSet: async (entity, key, value, meta) => {
|
|
@@ -36,7 +36,7 @@ const tzLocal = {
|
|
|
36
36
|
},
|
|
37
37
|
co2_config: {
|
|
38
38
|
key: ['auto_brightness', 'forced_recalibration', 'factory_reset_co2', 'long_chart_period', 'set_altitude',
|
|
39
|
-
'manual_forced_recalibration'],
|
|
39
|
+
'manual_forced_recalibration', 'light_indicator', 'light_indicator_level'],
|
|
40
40
|
convertSet: async (entity, key, rawValue, meta) => {
|
|
41
41
|
const lookup = {'OFF': 0x00, 'ON': 0x01};
|
|
42
42
|
const value = lookup.hasOwnProperty(rawValue) ? lookup[rawValue] : parseInt(rawValue, 10);
|
|
@@ -47,6 +47,8 @@ const tzLocal = {
|
|
|
47
47
|
long_chart_period: ['msCO2', {0x0204: {value, type: 0x10}}],
|
|
48
48
|
set_altitude: ['msCO2', {0x0205: {value, type: 0x21}}],
|
|
49
49
|
manual_forced_recalibration: ['msCO2', {0x0207: {value, type: 0x21}}],
|
|
50
|
+
light_indicator: ['msCO2', {0x0211: {value, type: 0x10}}],
|
|
51
|
+
light_indicator_level: ['msCO2', {0x0209: {value, type: 0x20}}],
|
|
50
52
|
};
|
|
51
53
|
await entity.write(payloads[key][0], payloads[key][1]);
|
|
52
54
|
return {
|
|
@@ -80,6 +82,54 @@ const tzLocal = {
|
|
|
80
82
|
};
|
|
81
83
|
},
|
|
82
84
|
},
|
|
85
|
+
termostat_config: {
|
|
86
|
+
key: ['high_temperature', 'low_temperature', 'enable_temperature'],
|
|
87
|
+
convertSet: async (entity, key, rawValue, meta) => {
|
|
88
|
+
const lookup = {'OFF': 0x00, 'ON': 0x01};
|
|
89
|
+
const value = lookup.hasOwnProperty(rawValue) ? lookup[rawValue] : parseInt(rawValue, 10);
|
|
90
|
+
const payloads = {
|
|
91
|
+
high_temperature: ['msTemperatureMeasurement', {0x0221: {value, type: 0x29}}],
|
|
92
|
+
low_temperature: ['msTemperatureMeasurement', {0x0222: {value, type: 0x29}}],
|
|
93
|
+
enable_temperature: ['msTemperatureMeasurement', {0x0220: {value, type: 0x10}}],
|
|
94
|
+
};
|
|
95
|
+
await entity.write(payloads[key][0], payloads[key][1]);
|
|
96
|
+
return {
|
|
97
|
+
state: {[key]: rawValue},
|
|
98
|
+
};
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
hydrostat_config: {
|
|
102
|
+
key: ['high_humidity', 'low_humidity', 'enable_humidity'],
|
|
103
|
+
convertSet: async (entity, key, rawValue, meta) => {
|
|
104
|
+
const lookup = {'OFF': 0x00, 'ON': 0x01};
|
|
105
|
+
const value = lookup.hasOwnProperty(rawValue) ? lookup[rawValue] : parseInt(rawValue, 10);
|
|
106
|
+
const payloads = {
|
|
107
|
+
high_humidity: ['msRelativeHumidity', {0x0221: {value, type: 0x21}}],
|
|
108
|
+
low_humidity: ['msRelativeHumidity', {0x0222: {value, type: 0x21}}],
|
|
109
|
+
enable_humidity: ['msRelativeHumidity', {0x0220: {value, type: 0x10}}],
|
|
110
|
+
};
|
|
111
|
+
await entity.write(payloads[key][0], payloads[key][1]);
|
|
112
|
+
return {
|
|
113
|
+
state: {[key]: rawValue},
|
|
114
|
+
};
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
co2_gasstat_config: {
|
|
118
|
+
key: ['high_gas', 'low_gas', 'enable_gas'],
|
|
119
|
+
convertSet: async (entity, key, rawValue, meta) => {
|
|
120
|
+
const lookup = {'OFF': 0x00, 'ON': 0x01};
|
|
121
|
+
const value = lookup.hasOwnProperty(rawValue) ? lookup[rawValue] : parseInt(rawValue, 10);
|
|
122
|
+
const payloads = {
|
|
123
|
+
high_gas: ['msCO2', {0x0221: {value, type: 0x21}}],
|
|
124
|
+
low_gas: ['msCO2', {0x0222: {value, type: 0x21}}],
|
|
125
|
+
enable_gas: ['msCO2', {0x0220: {value, type: 0x10}}],
|
|
126
|
+
};
|
|
127
|
+
await entity.write(payloads[key][0], payloads[key][1]);
|
|
128
|
+
return {
|
|
129
|
+
state: {[key]: rawValue},
|
|
130
|
+
};
|
|
131
|
+
},
|
|
132
|
+
},
|
|
83
133
|
};
|
|
84
134
|
|
|
85
135
|
const fzLocal = {
|
|
@@ -127,6 +177,12 @@ const fzLocal = {
|
|
|
127
177
|
if (msg.data.hasOwnProperty(0x0207)) {
|
|
128
178
|
result.manual_forced_recalibration = msg.data[0x0207];
|
|
129
179
|
}
|
|
180
|
+
if (msg.data.hasOwnProperty(0x0211)) {
|
|
181
|
+
result.light_indicator = ['OFF', 'ON'][msg.data[0x0211]];
|
|
182
|
+
}
|
|
183
|
+
if (msg.data.hasOwnProperty(0x0209)) {
|
|
184
|
+
result.light_indicator_level = msg.data[0x0209];
|
|
185
|
+
}
|
|
130
186
|
return result;
|
|
131
187
|
},
|
|
132
188
|
},
|
|
@@ -152,6 +208,57 @@ const fzLocal = {
|
|
|
152
208
|
return result;
|
|
153
209
|
},
|
|
154
210
|
},
|
|
211
|
+
termostat_config: {
|
|
212
|
+
cluster: 'msTemperatureMeasurement',
|
|
213
|
+
type: ['attributeReport', 'readResponse'],
|
|
214
|
+
convert: (model, msg, publish, options, meta) => {
|
|
215
|
+
const result = {};
|
|
216
|
+
if (msg.data.hasOwnProperty(0x0221)) {
|
|
217
|
+
result.high_temperature = msg.data[0x0221];
|
|
218
|
+
}
|
|
219
|
+
if (msg.data.hasOwnProperty(0x0222)) {
|
|
220
|
+
result.low_temperature = msg.data[0x0222];
|
|
221
|
+
}
|
|
222
|
+
if (msg.data.hasOwnProperty(0x0220)) {
|
|
223
|
+
result.enable_temperature = ['OFF', 'ON'][msg.data[0x0220]];
|
|
224
|
+
}
|
|
225
|
+
return result;
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
hydrostat_config: {
|
|
229
|
+
cluster: 'msRelativeHumidity',
|
|
230
|
+
type: ['attributeReport', 'readResponse'],
|
|
231
|
+
convert: (model, msg, publish, options, meta) => {
|
|
232
|
+
const result = {};
|
|
233
|
+
if (msg.data.hasOwnProperty(0x0221)) {
|
|
234
|
+
result.high_humidity = msg.data[0x0221];
|
|
235
|
+
}
|
|
236
|
+
if (msg.data.hasOwnProperty(0x0222)) {
|
|
237
|
+
result.low_humidity = msg.data[0x0222];
|
|
238
|
+
}
|
|
239
|
+
if (msg.data.hasOwnProperty(0x0220)) {
|
|
240
|
+
result.enable_humidity = ['OFF', 'ON'][msg.data[0x0220]];
|
|
241
|
+
}
|
|
242
|
+
return result;
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
co2_gasstat_config: {
|
|
246
|
+
cluster: 'msCO2',
|
|
247
|
+
type: ['attributeReport', 'readResponse'],
|
|
248
|
+
convert: (model, msg, publish, options, meta) => {
|
|
249
|
+
const result = {};
|
|
250
|
+
if (msg.data.hasOwnProperty(0x0221)) {
|
|
251
|
+
result.high_gas = msg.data[0x0221];
|
|
252
|
+
}
|
|
253
|
+
if (msg.data.hasOwnProperty(0x0222)) {
|
|
254
|
+
result.low_gas = msg.data[0x0222];
|
|
255
|
+
}
|
|
256
|
+
if (msg.data.hasOwnProperty(0x0220)) {
|
|
257
|
+
result.enable_gas = ['OFF', 'ON'][msg.data[0x0220]];
|
|
258
|
+
}
|
|
259
|
+
return result;
|
|
260
|
+
},
|
|
261
|
+
},
|
|
155
262
|
};
|
|
156
263
|
|
|
157
264
|
module.exports = [
|
|
@@ -621,4 +728,56 @@ module.exports = [
|
|
|
621
728
|
.withDescription('Start Manual FRC (Perform Forced Recalibration of the CO2 Sensor)')
|
|
622
729
|
.withValueMin(0).withValueMax(5000)],
|
|
623
730
|
},
|
|
731
|
+
{
|
|
732
|
+
zigbeeModel: ['EFEKTA_CO2_Smart_Monitor'],
|
|
733
|
+
model: 'EFEKTA_CO2_Smart_Monitor',
|
|
734
|
+
vendor: 'Custom devices (DiY)',
|
|
735
|
+
description: '[EFEKTA CO2 Smart Monitor, ws2812b indicator, can control the relay, binding](https://efektalab.com/CO2_Monitor)',
|
|
736
|
+
fromZigbee: [fz.temperature, fz.humidity, fzLocal.co2, fzLocal.co2_config, fzLocal.temperature_config,
|
|
737
|
+
fzLocal.humidity_config, fzLocal.termostat_config, fzLocal.hydrostat_config, fzLocal.co2_gasstat_config],
|
|
738
|
+
toZigbee: [tz.factory_reset, tzLocal.co2_config, tzLocal.temperature_config, tzLocal.humidity_config,
|
|
739
|
+
tzLocal.termostat_config, tzLocal.hydrostat_config, tzLocal.co2_gasstat_config],
|
|
740
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
741
|
+
const endpoint = device.getEndpoint(1);
|
|
742
|
+
const clusters = ['msTemperatureMeasurement', 'msRelativeHumidity', 'msCO2'];
|
|
743
|
+
await reporting.bind(endpoint, coordinatorEndpoint, clusters);
|
|
744
|
+
for (const cluster of clusters) {
|
|
745
|
+
await endpoint.configureReporting(cluster, [
|
|
746
|
+
{attribute: 'measuredValue', minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 0},
|
|
747
|
+
]);
|
|
748
|
+
}
|
|
749
|
+
},
|
|
750
|
+
exposes: [e.co2(), e.temperature(), e.humidity(),
|
|
751
|
+
exposes.binary('light_indicator', ea.STATE_SET, 'ON', 'OFF').withDescription('Enable or Disable light_indicator'),
|
|
752
|
+
exposes.numeric('light_indicator_level', ea.STATE_SET).withUnit('%').withDescription('light_indicator_level')
|
|
753
|
+
.withValueMin(0).withValueMax(100),
|
|
754
|
+
exposes.numeric('set_altitude', ea.STATE_SET).withUnit('meters')
|
|
755
|
+
.withDescription('Setting the altitude above sea level (for high accuracy of the CO2 sensor)')
|
|
756
|
+
.withValueMin(0).withValueMax(3000),
|
|
757
|
+
exposes.numeric('temperature_offset', ea.STATE_SET).withUnit('°C').withDescription('Adjust temperature')
|
|
758
|
+
.withValueMin(-30).withValueMax(60),
|
|
759
|
+
exposes.numeric('humidity_offset', ea.STATE_SET).withUnit('%').withDescription('Adjust humidity')
|
|
760
|
+
.withValueMin(0).withValueMax(99),
|
|
761
|
+
exposes.binary('forced_recalibration', ea.STATE_SET, 'ON', 'OFF')
|
|
762
|
+
.withDescription('Start FRC (Perform Forced Recalibration of the CO2 Sensor)'),
|
|
763
|
+
exposes.numeric('manual_forced_recalibration', ea.STATE_SET)
|
|
764
|
+
.withUnit('ppm').withDescription('Start Manual FRC (Perform Forced Recalibration of the CO2 Sensor)')
|
|
765
|
+
.withValueMin(0).withValueMax(5000),
|
|
766
|
+
exposes.binary('factory_reset_co2', ea.STATE_SET, 'ON', 'OFF').withDescription('Factory Reset CO2 sensor'),
|
|
767
|
+
exposes.binary('enable_gas', ea.STATE_SET, 'ON', 'OFF').withDescription('Enable CO2 Gas Control'),
|
|
768
|
+
exposes.numeric('high_gas', ea.STATE_SET).withUnit('ppm').withDescription('Setting High CO2 Gas Border')
|
|
769
|
+
.withValueMin(0).withValueMax(99),
|
|
770
|
+
exposes.numeric('low_gas', ea.STATE_SET).withUnit('ppm').withDescription('Setting Low CO2 Gas Border')
|
|
771
|
+
.withValueMin(0).withValueMax(99),
|
|
772
|
+
exposes.binary('enable_temperature', ea.STATE_SET, 'ON', 'OFF').withDescription('Enable Temperature Control'),
|
|
773
|
+
exposes.numeric('high_temperature', ea.STATE_SET).withUnit('C').withDescription('Setting High Temperature Border')
|
|
774
|
+
.withValueMin(-5).withValueMax(50),
|
|
775
|
+
exposes.numeric('low_temperature', ea.STATE_SET).withUnit('C').withDescription('Setting Low Temperature Border')
|
|
776
|
+
.withValueMin(-5).withValueMax(50),
|
|
777
|
+
exposes.binary('enable_humidity', ea.STATE_SET, 'ON', 'OFF').withDescription('Enable Humidity Control'),
|
|
778
|
+
exposes.numeric('high_humidity', ea.STATE_SET).withUnit('C').withDescription('Setting High Humidity Border')
|
|
779
|
+
.withValueMin(0).withValueMax(99),
|
|
780
|
+
exposes.numeric('low_humidity', ea.STATE_SET).withUnit('C').withDescription('Setting Low Humidity Border')
|
|
781
|
+
.withValueMin(0).withValueMax(99)],
|
|
782
|
+
},
|
|
624
783
|
];
|
package/devices/danfoss.js
CHANGED
|
@@ -204,6 +204,7 @@ module.exports = [
|
|
|
204
204
|
tz.thermostat_local_temperature,
|
|
205
205
|
tz.thermostat_occupied_heating_setpoint,
|
|
206
206
|
tz.thermostat_system_mode,
|
|
207
|
+
tz.thermostat_running_state,
|
|
207
208
|
tz.thermostat_min_heat_setpoint_limit,
|
|
208
209
|
tz.thermostat_max_heat_setpoint_limit,
|
|
209
210
|
tz.danfoss_output_status,
|
|
@@ -227,8 +228,8 @@ module.exports = [
|
|
|
227
228
|
const epName = `l${i}`;
|
|
228
229
|
if (i!=16) {
|
|
229
230
|
features.push(e.battery().withEndpoint(epName));
|
|
230
|
-
features.push(exposes.climate().withSetpoint('occupied_heating_setpoint',
|
|
231
|
-
.withLocalTemperature().withSystemMode(['heat']).withEndpoint(epName));
|
|
231
|
+
features.push(exposes.climate().withSetpoint('occupied_heating_setpoint', 5, 35, 0.5)
|
|
232
|
+
.withLocalTemperature().withRunningState(['idle', 'heat']).withSystemMode(['heat']).withEndpoint(epName));
|
|
232
233
|
features.push(exposes.numeric('abs_min_heat_setpoint_limit', ea.STATE)
|
|
233
234
|
.withUnit('°C').withEndpoint(epName)
|
|
234
235
|
.withDescription('Absolute min temperature allowed on the device'));
|
|
@@ -236,10 +237,10 @@ module.exports = [
|
|
|
236
237
|
.withUnit('°C').withEndpoint(epName)
|
|
237
238
|
.withDescription('Absolute max temperature allowed on the device'));
|
|
238
239
|
features.push(exposes.numeric('min_heat_setpoint_limit', ea.ALL)
|
|
239
|
-
.withValueMin(4).withValueMax(
|
|
240
|
+
.withValueMin(4).withValueMax(35).withValueStep(0.5).withUnit('°C')
|
|
240
241
|
.withEndpoint(epName).withDescription('Min temperature limit set on the device'));
|
|
241
242
|
features.push(exposes.numeric('max_heat_setpoint_limit', ea.ALL)
|
|
242
|
-
.withValueMin(4).withValueMax(
|
|
243
|
+
.withValueMin(4).withValueMax(35).withValueStep(0.5).withUnit('°C')
|
|
243
244
|
.withEndpoint(epName).withDescription('Max temperature limit set on the device'));
|
|
244
245
|
features.push(exposes.enum('setpoint_change_source', ea.STATE, ['manual', 'schedule', 'externally'])
|
|
245
246
|
.withEndpoint(epName));
|
package/devices/hgkg.js
CHANGED
|
@@ -11,15 +11,44 @@ module.exports = [
|
|
|
11
11
|
model: 'BAC-002-ALZB',
|
|
12
12
|
vendor: 'HKGK',
|
|
13
13
|
description: 'BAC series thermostat',
|
|
14
|
-
fromZigbee: [
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
exposes.climate().withSetpoint('current_heating_setpoint', 5, 30, 1, ea.STATE_SET)
|
|
20
|
-
.withLocalTemperature(ea.STATE).withLocalTemperatureCalibration(-30, 30, 0.1, ea.STATE_SET)
|
|
21
|
-
.withSystemMode(['off', 'cool'], ea.STATE_SET).withRunningState(['idle', 'heat', 'cool'], ea.STATE)
|
|
22
|
-
.withPreset(['hold', 'program']).withSensor(['IN', 'AL', 'OU'], ea.STATE_SET)],
|
|
14
|
+
fromZigbee: [
|
|
15
|
+
fz.moes_thermostat,
|
|
16
|
+
fz.ignore_basic_report,
|
|
17
|
+
fz.ignore_tuya_set_time,
|
|
18
|
+
],
|
|
23
19
|
onEvent: tuya.onEventSetLocalTime,
|
|
20
|
+
toZigbee: [
|
|
21
|
+
tz.moes_thermostat_child_lock,
|
|
22
|
+
tz.moes_thermostat_current_heating_setpoint,
|
|
23
|
+
tz.moes_thermostat_mode,
|
|
24
|
+
tz.hgkg_thermostat_standby,
|
|
25
|
+
tz.moes_thermostat_sensor,
|
|
26
|
+
tz.moes_thermostat_calibration,
|
|
27
|
+
tz.tuya_thermostat_schedule,
|
|
28
|
+
tz.tuya_thermostat_week,
|
|
29
|
+
tz.tuya_thermostat_schedule_programming_mode,
|
|
30
|
+
tz.tuya_thermostat_bac_fan_mode,
|
|
31
|
+
],
|
|
32
|
+
exposes: [
|
|
33
|
+
// e.switch(),
|
|
34
|
+
e.child_lock(),
|
|
35
|
+
// e.deadzone_temperature(),
|
|
36
|
+
exposes.climate()
|
|
37
|
+
.withSetpoint('current_heating_setpoint', 5, 45, 0.5, ea.STATE_SET)
|
|
38
|
+
.withLocalTemperature(ea.STATE)
|
|
39
|
+
.withLocalTemperatureCalibration(-10, 10, 0.1, ea.STATE_SET)
|
|
40
|
+
.withSystemMode(['off', 'cool'], ea.STATE_SET)
|
|
41
|
+
// .withRunningState(['off','on'], ea.STATE)
|
|
42
|
+
.withPreset(['hold', 'program'])
|
|
43
|
+
.withSensor(['IN', 'AL', 'OU'], ea.STATE_SET)
|
|
44
|
+
.withFanMode(['off', 'low', 'medium', 'high', 'auto'], ea.STATE_SET),
|
|
45
|
+
exposes.composite('programming_mode')
|
|
46
|
+
.withDescription(
|
|
47
|
+
'Schedule MODE ⏱ - In this mode, the device executes a preset week programming temperature time and temperature.',
|
|
48
|
+
)
|
|
49
|
+
.withFeature(e.week())
|
|
50
|
+
.withFeature(exposes.text('workdays_schedule', ea.STATE_SET))
|
|
51
|
+
.withFeature(exposes.text('holidays_schedule', ea.STATE_SET)),
|
|
52
|
+
],
|
|
24
53
|
},
|
|
25
54
|
];
|
package/devices/osram.js
CHANGED
|
@@ -75,9 +75,8 @@ module.exports = [
|
|
|
75
75
|
model: 'AC03645',
|
|
76
76
|
vendor: 'OSRAM',
|
|
77
77
|
description: 'LIGHTIFY LED CLA60 E27 RGBW',
|
|
78
|
-
extend: extend.ledvance.light_onoff_brightness_colortemp_color({colorTempRange: [153, 526]
|
|
78
|
+
extend: extend.ledvance.light_onoff_brightness_colortemp_color({colorTempRange: [153, 526]}),
|
|
79
79
|
ota: ota.ledvance,
|
|
80
|
-
exposes: [e.light_brightness_colortemp_colorhs([153, 526]).removeFeature('color_temp_startup'), e.effect()],
|
|
81
80
|
},
|
|
82
81
|
{
|
|
83
82
|
zigbeeModel: ['CLA60 TW OSRAM'],
|
|
@@ -252,7 +251,7 @@ module.exports = [
|
|
|
252
251
|
model: '4058075047853',
|
|
253
252
|
vendor: 'OSRAM',
|
|
254
253
|
description: 'Smart+ gardenpole 4W RGBW',
|
|
255
|
-
extend: extend.ledvance.light_onoff_brightness_colortemp_color(),
|
|
254
|
+
extend: extend.ledvance.light_onoff_brightness_colortemp_color({supportsHS: true, preferHS: true}),
|
|
256
255
|
meta: {disableDefaultResponse: true},
|
|
257
256
|
ota: ota.ledvance,
|
|
258
257
|
},
|
package/devices/tuya.js
CHANGED
|
@@ -128,6 +128,19 @@ const tzLocal = {
|
|
|
128
128
|
}
|
|
129
129
|
},
|
|
130
130
|
},
|
|
131
|
+
temperature_unit: {
|
|
132
|
+
key: ['temperature_unit'],
|
|
133
|
+
convertSet: async (entity, key, value, meta) => {
|
|
134
|
+
switch (key) {
|
|
135
|
+
case 'temperature_unit': {
|
|
136
|
+
await entity.write('manuSpecificTuya_2', {'57355': {value: {'celsius': 0, 'fahrenheit': 1}[value], type: 48}});
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
default: // Unknown key
|
|
140
|
+
meta.logger.warn(`Unhandled key ${key}`);
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
},
|
|
131
144
|
};
|
|
132
145
|
|
|
133
146
|
const fzLocal = {
|
|
@@ -262,6 +275,28 @@ const fzLocal = {
|
|
|
262
275
|
return result;
|
|
263
276
|
},
|
|
264
277
|
},
|
|
278
|
+
humidity10: {
|
|
279
|
+
cluster: 'msRelativeHumidity',
|
|
280
|
+
type: ['attributeReport', 'readResponse'],
|
|
281
|
+
options: [exposes.options.precision('humidity'), exposes.options.calibration('humidity')],
|
|
282
|
+
convert: (model, msg, publish, options, meta) => {
|
|
283
|
+
const humidity = parseFloat(msg.data['measuredValue']) / 10.0;
|
|
284
|
+
if (humidity >= 0 && humidity <= 100) {
|
|
285
|
+
return {humidity: utils.calibrateAndPrecisionRoundOptions(humidity, options, 'humidity')};
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
temperature_unit: {
|
|
290
|
+
cluster: 'manuSpecificTuya_2',
|
|
291
|
+
type: ['attributeReport', 'readResponse'],
|
|
292
|
+
convert: (model, msg, publish, options, meta) => {
|
|
293
|
+
const result = {};
|
|
294
|
+
if (msg.data.hasOwnProperty('57355')) {
|
|
295
|
+
result.temperature_unit = {'0': 'celsius', '1': 'fahrenheit'}[msg.data['57355']];
|
|
296
|
+
}
|
|
297
|
+
return result;
|
|
298
|
+
},
|
|
299
|
+
},
|
|
265
300
|
};
|
|
266
301
|
|
|
267
302
|
module.exports = [
|
|
@@ -2682,4 +2717,21 @@ module.exports = [
|
|
|
2682
2717
|
toZigbee: [tzZosung.zosung_ir_code_to_send, tzZosung.zosung_learn_ir_code],
|
|
2683
2718
|
exposes: [ez.learn_ir_code(), ez.learned_ir_code(), ez.ir_code_to_send()],
|
|
2684
2719
|
},
|
|
2720
|
+
{
|
|
2721
|
+
fingerprint: [{modelID: 'TS0201', manufacturerName: '_TZ3000_itnrsufe'}],
|
|
2722
|
+
model: 'KCTW1Z',
|
|
2723
|
+
vendor: 'TuYa',
|
|
2724
|
+
description: 'Temperature & humidity sensor with LCD',
|
|
2725
|
+
fromZigbee: [fz.temperature, fzLocal.humidity10, fzLocal.temperature_unit, fz.battery, fz.ignore_tuya_set_time],
|
|
2726
|
+
toZigbee: [tzLocal.temperature_unit],
|
|
2727
|
+
onEvent: tuya.onEventSetLocalTime,
|
|
2728
|
+
exposes: [
|
|
2729
|
+
e.temperature(), e.humidity(), e.battery(), e.battery_voltage(),
|
|
2730
|
+
exposes.enum('temperature_unit', ea.STATE_SET, ['celsius', 'fahrenheit']).withDescription('Current display unit'),
|
|
2731
|
+
],
|
|
2732
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2733
|
+
const endpoint = device.getEndpoint(1);
|
|
2734
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'msTemperatureMeasurement', 'msRelativeHumidity']);
|
|
2735
|
+
},
|
|
2736
|
+
},
|
|
2685
2737
|
];
|
package/lib/exposes.js
CHANGED
|
@@ -407,11 +407,11 @@ class Climate extends Base {
|
|
|
407
407
|
return this;
|
|
408
408
|
}
|
|
409
409
|
|
|
410
|
-
withFanMode(modes) {
|
|
410
|
+
withFanMode(modes, access=a.ALL) {
|
|
411
411
|
assert(!this.endpoint, 'Cannot add feature after adding endpoint');
|
|
412
412
|
const allowed = ['off', 'low', 'medium', 'high', 'on', 'auto', 'smart'];
|
|
413
413
|
modes.forEach((m) => assert(allowed.includes(m)));
|
|
414
|
-
this.features.push(new Enum('fan_mode', access
|
|
414
|
+
this.features.push(new Enum('fan_mode', access, modes).withDescription('Mode of the fan'));
|
|
415
415
|
return this;
|
|
416
416
|
}
|
|
417
417
|
|
package/lib/extend.js
CHANGED
|
@@ -125,7 +125,7 @@ const extend = {
|
|
|
125
125
|
...extend.light_onoff_brightness(options),
|
|
126
126
|
toZigbee: extend.light_onoff_brightness(options).toZigbee.concat([tz.ledvance_commands]),
|
|
127
127
|
}),
|
|
128
|
-
light_onoff_brightness_colortemp: (options={}) => ({
|
|
128
|
+
light_onoff_brightness_colortemp: (options={disableColorTempStartup: true}) => ({
|
|
129
129
|
...extend.light_onoff_brightness_colortemp(options),
|
|
130
130
|
toZigbee: extend.light_onoff_brightness_colortemp(options).toZigbee.concat([tz.ledvance_commands]),
|
|
131
131
|
}),
|
|
@@ -133,7 +133,7 @@ const extend = {
|
|
|
133
133
|
...extend.light_onoff_brightness_color({supportsHS: true, ...options}),
|
|
134
134
|
toZigbee: extend.light_onoff_brightness_color({supportsHS: true, ...options}).toZigbee.concat([tz.ledvance_commands]),
|
|
135
135
|
}),
|
|
136
|
-
light_onoff_brightness_colortemp_color: (options={}) => ({
|
|
136
|
+
light_onoff_brightness_colortemp_color: (options={disableColorTempStartup: true}) => ({
|
|
137
137
|
...extend.light_onoff_brightness_colortemp_color({supportsHS: true, ...options}),
|
|
138
138
|
toZigbee: extend.light_onoff_brightness_colortemp_color({supportsHS: true, ...options}).toZigbee.concat([tz.ledvance_commands]),
|
|
139
139
|
}),
|
package/lib/tuya.js
CHANGED