Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add converter for modern moes bht-006 thermostat #8005

Merged
merged 10 commits into from
Sep 24, 2024
52 changes: 35 additions & 17 deletions src/devices/moes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,11 @@ const definitions: DefinitionWithExtend[] = [
},
{
fingerprint: [
{modelID: 'TS0601', manufacturerName: '_TZE200_aoclfnxz'},
{modelID: 'TS0601', manufacturerName: '_TZE200_ye5jkfsb'},
{modelID: 'TS0601', manufacturerName: '_TZE200_ztvwu4nk'},
{modelID: 'TS0601', manufacturerName: '_TZE204_5toc8efa'},
{modelID: 'TS0601', manufacturerName: '_TZE200_5toc8efa'},
{modelID: 'TS0601', manufacturerName: '_TZE200_ye5jkfsb'},
{modelID: 'TS0601', manufacturerName: '_TZE204_5toc8efa'},
{modelID: 'TS0601', manufacturerName: '_TZE200_aoclfnxz'},
Koenkk marked this conversation as resolved.
Show resolved Hide resolved
{modelID: 'TS0601', manufacturerName: '_TZE204_aoclfnxz'},
{modelID: 'TS0601', manufacturerName: '_TZE200_u9bfwha0'},
{modelID: 'TS0601', manufacturerName: '_TZE204_u9bfwha0'},
Expand All @@ -113,35 +113,47 @@ const definitions: DefinitionWithExtend[] = [
description: 'Moes BHT series Thermostat',
fromZigbee: [legacy.fz.moes_thermostat],
toZigbee: [
legacy.tz.moes_thermostat_child_lock,
legacy.tz.moes_thermostat_current_heating_setpoint,
legacy.tz.moes_thermostat_mode,
legacy.tz.moes_thermostat_standby,
legacy.tz.moes_thermostat_sensor,
legacy.tz.moes_thermostat_calibration,
legacy.tz.moes_thermostat_deadzone_temperature,
legacy.tz.moes_thermostat_max_temperature_limit,
legacy.tz.moes_thermostat_min_temperature_limit,
legacy.tz.moes_thermostat_program_schedule,
legacy.tz.moes_thermostat_child_lock, //40 //child lock
legacy.tz.moes_thermostat_current_heating_setpoint, //16 //current set temp
legacy.tz.moes_thermostat_mode, //2 (hold/heat) also sets 3 - schedule enabled //hold/program
legacy.tz.moes_thermostat_standby, //1 //on/off
legacy.tz.moes_thermostat_sensor, //43 //sensor selection
legacy.tz.moes_thermostat_calibration, //27 //temperature correction
legacy.tz.moes_thermostat_deadzone_temperature, //20 //not used in this model
legacy.tz.moes_thermostat_max_temperature_limit, //18 //not used in this model
legacy.tz.moes_thermostat_max_temp, //19 //high limit temperature ceiling
legacy.tz.moes_thermostat_min_temperature_limit, //26 //DeadZone temp
legacy.tz.moes_thermostat_program_schedule, //101 //week program
],
whiteLabel: [tuya.whitelabel('Moes', 'BHT-002/BHT-006', 'Smart heating thermostat', ['_TZE204_aoclfnxz'])],
exposes: (device, options) => {
const heatingStepSize = device?.manufacturerName === '_TZE204_5toc8efa' ? 0.5 : 1;
return [
const calibrationLimit = device?.manufacturerName === '_TZE204_aoclfnxz' ? 9 : 30;
const calibrationStep = device?.manufacturerName === '_TZE204_aoclfnxz' ? 1 : 0.1;
const arr = [
e.linkquality(),
e.child_lock(),
e.deadzone_temperature(),
e.max_temperature_limit().withValueMax(45),
e.min_temperature_limit(),

device?.manufacturerName === '_TZE204_aoclfnxz'
? e.max_temp().withValueMin(45).withValueMax(70)
: e.max_temperature_limit().withValueMax(45),

device?.manufacturerName === '_TZE204_aoclfnxz'
? e.min_temperature_limit().withDescription('The delta between local_temperature and current_heating_setpoint to trigger Heat')
: e.min_temperature_limit(),

e
.climate()
.withSetpoint('current_heating_setpoint', 5, 45, heatingStepSize, ea.STATE_SET)
.withLocalTemperature(ea.STATE)
.withLocalTemperatureCalibration(-30, 30, 0.1, ea.STATE_SET)
.withLocalTemperatureCalibration(-calibrationLimit, calibrationLimit, calibrationStep, ea.STATE_SET)
.withSystemMode(['off', 'heat'], ea.STATE_SET)
.withRunningState(['idle', 'heat', 'cool'], ea.STATE)
.withPreset(['hold', 'program']),

e.temperature_sensor_select(['IN', 'AL', 'OU']),

e
.composite('program', 'program', ea.STATE_SET)
.withDescription('Time of day and setpoint to use when in program mode')
Expand Down Expand Up @@ -182,6 +194,12 @@ const definitions: DefinitionWithExtend[] = [
.withFeature(exposesLocal.minute('sunday_p4_minute'))
.withFeature(exposesLocal.program_temperature('sunday_p4_temperature')),
];

if (device?.manufacturerName === '_TZE204_aoclfnxz') {
arr.splice(2, 1);
}
Koenkk marked this conversation as resolved.
Show resolved Hide resolved

return arr;
},
onEvent: tuya.onEventSetLocalTime,
},
Expand Down
10 changes: 9 additions & 1 deletion src/lib/exposes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1134,6 +1134,14 @@ export const presets = {
)
.withValueMin(0)
.withValueMax(35),
max_temp: () =>
new Numeric('max_temp', access.STATE_SET)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

max_temperature_limit to be in sync with the min_temperature_limit below

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check lines 1127 and 1129

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you update moes_thermostat_max_temperature_limit instead? Use the correct datapoint

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is 18 but needed 19

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Different points for most devices and this one

                device?.manufacturerName === '_TZE204_aoclfnxz'
                    ? e.max_temp().withValueMin(45).withValueMax(70)
                    : e.max_temperature_limit().withValueMax(45),

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But you can do an if/else in moes_thermostat_max_temperature_limit:

if (device?.manufacturerName === '_TZE204_aoclfnxz') {
  // send to 19
} else {
  // send to 18
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two layers of checking manufacturer name looks like layered spaghetty ))

But I'll look to it, ok

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok but then reasonable to do the same with deadzone

.withUnit('°C')
.withDescription(
'Maximum temperature limit. Cuts the thermostat out regardless of air temperature if the external floor sensor exceeds this temperature. Only used by the thermostat when in AL sensor mode.',
)
.withValueMin(0)
.withValueMax(35),
min_temperature_limit: () =>
new Numeric('min_temperature_limit', access.STATE_SET)
.withUnit('°C')
Expand Down Expand Up @@ -1257,7 +1265,7 @@ export const presets = {
new Enum('sensor', access.STATE_SET, sensor_names).withDescription('Select temperature sensor to use').withCategory('config'),
test: () => new Binary('test', access.STATE, true, false).withDescription('Indicates whether the device is being tested'),
trigger_count: (sinceScheduledReport = true) =>
new Numeric('trigger_count', exports.access.STATE)
new Numeric('trigger_count', access.STATE)
.withDescription('Indicates how many times the sensor was triggered' + (sinceScheduledReport ? ' (since last scheduled report)' : ''))
.withCategory('diagnostic'),
trigger_indicator: () =>
Expand Down
10 changes: 10 additions & 0 deletions src/lib/legacy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6433,6 +6433,16 @@ const toZigbee2 = {
}
},
} satisfies Tz.Converter,
moes_thermostat_max_temp: {
key: ['max_temp'],
convertSet: async (entity, key, value: any, meta) => {
if (['_TZE200_5toc8efa', '_TZE204_5toc8efa'].includes(meta.device.manufacturerName)) {
await sendDataPointValue(entity, dataPoints.moesMaxTemp, value * 10);
} else {
await sendDataPointValue(entity, dataPoints.moesMaxTemp, value);
dukobpa3 marked this conversation as resolved.
Show resolved Hide resolved
}
},
} satisfies Tz.Converter,
moes_thermostat_mode: {
key: ['preset'],
convertSet: async (entity, key, value, meta) => {
Expand Down
Loading