mirror of
https://github.com/esphome/esphome.git
synced 2024-11-25 08:28:12 +01:00
add tcl112 support for dry, fan and swing (#939)
This commit is contained in:
parent
d7a2816c58
commit
92d93d658c
2 changed files with 72 additions and 5 deletions
|
@ -15,6 +15,12 @@ const uint8_t TCL112_COOL = 3;
|
||||||
const uint8_t TCL112_FAN = 7;
|
const uint8_t TCL112_FAN = 7;
|
||||||
const uint8_t TCL112_AUTO = 8;
|
const uint8_t TCL112_AUTO = 8;
|
||||||
|
|
||||||
|
const uint8_t TCL112_FAN_AUTO = 0;
|
||||||
|
const uint8_t TCL112_FAN_LOW = 2;
|
||||||
|
const uint8_t TCL112_FAN_MED = 3;
|
||||||
|
const uint8_t TCL112_FAN_HIGH = 5;
|
||||||
|
|
||||||
|
const uint8_t TCL112_VSWING_MASK = 0x38;
|
||||||
const uint8_t TCL112_POWER_MASK = 0x04;
|
const uint8_t TCL112_POWER_MASK = 0x04;
|
||||||
|
|
||||||
const uint8_t TCL112_HALF_DEGREE = 0b00100000;
|
const uint8_t TCL112_HALF_DEGREE = 0b00100000;
|
||||||
|
@ -53,6 +59,14 @@ void Tcl112Climate::transmit_state() {
|
||||||
remote_state[6] &= 0xF0;
|
remote_state[6] &= 0xF0;
|
||||||
remote_state[6] |= TCL112_HEAT;
|
remote_state[6] |= TCL112_HEAT;
|
||||||
break;
|
break;
|
||||||
|
case climate::CLIMATE_MODE_DRY:
|
||||||
|
remote_state[6] &= 0xF0;
|
||||||
|
remote_state[6] |= TCL112_DRY;
|
||||||
|
break;
|
||||||
|
case climate::CLIMATE_MODE_FAN_ONLY:
|
||||||
|
remote_state[6] &= 0xF0;
|
||||||
|
remote_state[6] |= TCL112_FAN;
|
||||||
|
break;
|
||||||
case climate::CLIMATE_MODE_OFF:
|
case climate::CLIMATE_MODE_OFF:
|
||||||
default:
|
default:
|
||||||
remote_state[5] &= ~TCL112_POWER_MASK;
|
remote_state[5] &= ~TCL112_POWER_MASK;
|
||||||
|
@ -72,6 +86,29 @@ void Tcl112Climate::transmit_state() {
|
||||||
remote_state[7] &= 0xF0; // Clear temp bits.
|
remote_state[7] &= 0xF0; // Clear temp bits.
|
||||||
remote_state[7] |= ((uint8_t) TCL112_TEMP_MAX - half_degrees / 2);
|
remote_state[7] |= ((uint8_t) TCL112_TEMP_MAX - half_degrees / 2);
|
||||||
|
|
||||||
|
// Set fan
|
||||||
|
uint8_t selected_fan;
|
||||||
|
switch (this->fan_mode) {
|
||||||
|
case climate::CLIMATE_FAN_HIGH:
|
||||||
|
selected_fan = TCL112_FAN_HIGH;
|
||||||
|
break;
|
||||||
|
case climate::CLIMATE_FAN_MEDIUM:
|
||||||
|
selected_fan = TCL112_FAN_MED;
|
||||||
|
break;
|
||||||
|
case climate::CLIMATE_FAN_LOW:
|
||||||
|
selected_fan = TCL112_FAN_LOW;
|
||||||
|
break;
|
||||||
|
case climate::CLIMATE_FAN_AUTO:
|
||||||
|
default:
|
||||||
|
selected_fan = TCL112_FAN_AUTO;
|
||||||
|
}
|
||||||
|
remote_state[8] |= selected_fan;
|
||||||
|
|
||||||
|
// Set swing
|
||||||
|
if (this->swing_mode == climate::CLIMATE_SWING_VERTICAL) {
|
||||||
|
remote_state[8] |= TCL112_VSWING_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate & set the checksum for the current internal state of the remote.
|
// Calculate & set the checksum for the current internal state of the remote.
|
||||||
// Stored the checksum value in the last byte.
|
// Stored the checksum value in the last byte.
|
||||||
for (uint8_t checksum_byte = 0; checksum_byte < TCL112_STATE_LENGTH - 1; checksum_byte++)
|
for (uint8_t checksum_byte = 0; checksum_byte < TCL112_STATE_LENGTH - 1; checksum_byte++)
|
||||||
|
@ -107,7 +144,7 @@ void Tcl112Climate::transmit_state() {
|
||||||
bool Tcl112Climate::on_receive(remote_base::RemoteReceiveData data) {
|
bool Tcl112Climate::on_receive(remote_base::RemoteReceiveData data) {
|
||||||
// Validate header
|
// Validate header
|
||||||
if (!data.expect_item(TCL112_HEADER_MARK, TCL112_HEADER_SPACE)) {
|
if (!data.expect_item(TCL112_HEADER_MARK, TCL112_HEADER_SPACE)) {
|
||||||
ESP_LOGV(TAG, "Header fail");
|
ESP_LOGVV(TAG, "Header fail");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,14 +156,14 @@ bool Tcl112Climate::on_receive(remote_base::RemoteReceiveData data) {
|
||||||
if (data.expect_item(TCL112_BIT_MARK, TCL112_ONE_SPACE))
|
if (data.expect_item(TCL112_BIT_MARK, TCL112_ONE_SPACE))
|
||||||
remote_state[i] |= 1 << j;
|
remote_state[i] |= 1 << j;
|
||||||
else if (!data.expect_item(TCL112_BIT_MARK, TCL112_ZERO_SPACE)) {
|
else if (!data.expect_item(TCL112_BIT_MARK, TCL112_ZERO_SPACE)) {
|
||||||
ESP_LOGV(TAG, "Byte %d bit %d fail", i, j);
|
ESP_LOGVV(TAG, "Byte %d bit %d fail", i, j);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Validate footer
|
// Validate footer
|
||||||
if (!data.expect_mark(TCL112_BIT_MARK)) {
|
if (!data.expect_mark(TCL112_BIT_MARK)) {
|
||||||
ESP_LOGV(TAG, "Footer fail");
|
ESP_LOGVV(TAG, "Footer fail");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +173,7 @@ bool Tcl112Climate::on_receive(remote_base::RemoteReceiveData data) {
|
||||||
for (uint8_t checksum_byte = 0; checksum_byte < TCL112_STATE_LENGTH - 1; checksum_byte++)
|
for (uint8_t checksum_byte = 0; checksum_byte < TCL112_STATE_LENGTH - 1; checksum_byte++)
|
||||||
checksum += remote_state[checksum_byte];
|
checksum += remote_state[checksum_byte];
|
||||||
if (checksum != remote_state[TCL112_STATE_LENGTH - 1]) {
|
if (checksum != remote_state[TCL112_STATE_LENGTH - 1]) {
|
||||||
ESP_LOGV(TAG, "Checksum fail");
|
ESP_LOGVV(TAG, "Checksum fail");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +198,11 @@ bool Tcl112Climate::on_receive(remote_base::RemoteReceiveData data) {
|
||||||
this->mode = climate::CLIMATE_MODE_COOL;
|
this->mode = climate::CLIMATE_MODE_COOL;
|
||||||
break;
|
break;
|
||||||
case TCL112_DRY:
|
case TCL112_DRY:
|
||||||
|
this->mode = climate::CLIMATE_MODE_DRY;
|
||||||
|
break;
|
||||||
case TCL112_FAN:
|
case TCL112_FAN:
|
||||||
|
this->mode = climate::CLIMATE_MODE_FAN_ONLY;
|
||||||
|
break;
|
||||||
case TCL112_AUTO:
|
case TCL112_AUTO:
|
||||||
this->mode = climate::CLIMATE_MODE_AUTO;
|
this->mode = climate::CLIMATE_MODE_AUTO;
|
||||||
break;
|
break;
|
||||||
|
@ -171,6 +212,28 @@ bool Tcl112Climate::on_receive(remote_base::RemoteReceiveData data) {
|
||||||
if (remote_state[12] & TCL112_HALF_DEGREE)
|
if (remote_state[12] & TCL112_HALF_DEGREE)
|
||||||
temp += .5f;
|
temp += .5f;
|
||||||
this->target_temperature = temp;
|
this->target_temperature = temp;
|
||||||
|
auto fan = remote_state[8] & 0x7;
|
||||||
|
switch (fan) {
|
||||||
|
case TCL112_FAN_HIGH:
|
||||||
|
this->fan_mode = climate::CLIMATE_FAN_HIGH;
|
||||||
|
break;
|
||||||
|
case TCL112_FAN_MED:
|
||||||
|
this->fan_mode = climate::CLIMATE_FAN_MEDIUM;
|
||||||
|
break;
|
||||||
|
case TCL112_FAN_LOW:
|
||||||
|
this->fan_mode = climate::CLIMATE_FAN_LOW;
|
||||||
|
break;
|
||||||
|
case TCL112_FAN_AUTO:
|
||||||
|
default:
|
||||||
|
this->fan_mode = climate::CLIMATE_FAN_AUTO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((remote_state[8] & TCL112_VSWING_MASK) == TCL112_VSWING_MASK) {
|
||||||
|
this->swing_mode = climate::CLIMATE_SWING_VERTICAL;
|
||||||
|
} else {
|
||||||
|
this->swing_mode = climate::CLIMATE_SWING_OFF;
|
||||||
|
}
|
||||||
|
|
||||||
this->publish_state();
|
this->publish_state();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,11 @@ const float TCL112_TEMP_MIN = 16.0;
|
||||||
|
|
||||||
class Tcl112Climate : public climate_ir::ClimateIR {
|
class Tcl112Climate : public climate_ir::ClimateIR {
|
||||||
public:
|
public:
|
||||||
Tcl112Climate() : climate_ir::ClimateIR(TCL112_TEMP_MIN, TCL112_TEMP_MAX, .5f) {}
|
Tcl112Climate()
|
||||||
|
: climate_ir::ClimateIR(TCL112_TEMP_MIN, TCL112_TEMP_MAX, .5f, true, true,
|
||||||
|
{climate::CLIMATE_FAN_AUTO, climate::CLIMATE_FAN_LOW, climate::CLIMATE_FAN_MEDIUM,
|
||||||
|
climate::CLIMATE_FAN_HIGH},
|
||||||
|
{climate::CLIMATE_SWING_OFF, climate::CLIMATE_SWING_VERTICAL}) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Transmit via IR the state of this climate controller.
|
/// Transmit via IR the state of this climate controller.
|
||||||
|
|
Loading…
Reference in a new issue