Climate IR LG - Support fan only mode and all "on" commands (#3712)

This commit is contained in:
Daniel D'Abate 2024-06-12 02:04:25 +02:00 committed by GitHub
parent a64106e48c
commit 562700bd2c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 102 additions and 87 deletions

View file

@ -6,18 +6,24 @@ namespace climate_ir_lg {
static const char *const TAG = "climate.climate_ir_lg"; static const char *const TAG = "climate.climate_ir_lg";
const uint32_t COMMAND_ON = 0x00000; // Commands
const uint32_t COMMAND_ON_AI = 0x03000; const uint32_t COMMAND_MASK = 0xFF000;
const uint32_t COMMAND_COOL = 0x08000;
const uint32_t COMMAND_HEAT = 0x0C000;
const uint32_t COMMAND_OFF = 0xC0000; const uint32_t COMMAND_OFF = 0xC0000;
const uint32_t COMMAND_SWING = 0x10000; const uint32_t COMMAND_SWING = 0x10000;
// On, 25C, Mode: Auto, Fan: Auto, Zone Follow: Off, Sensor Temp: Ignore.
const uint32_t COMMAND_AUTO = 0x0B000;
const uint32_t COMMAND_DRY_FAN = 0x09000;
const uint32_t COMMAND_MASK = 0xFF000; const uint32_t COMMAND_ON_COOL = 0x00000;
const uint32_t COMMAND_ON_DRY = 0x01000;
const uint32_t COMMAND_ON_FAN_ONLY = 0x02000;
const uint32_t COMMAND_ON_AI = 0x03000;
const uint32_t COMMAND_ON_HEAT = 0x04000;
const uint32_t COMMAND_COOL = 0x08000;
const uint32_t COMMAND_DRY = 0x09000;
const uint32_t COMMAND_FAN_ONLY = 0x0A000;
const uint32_t COMMAND_AI = 0x0B000;
const uint32_t COMMAND_HEAT = 0x0C000;
// Fan speed
const uint32_t FAN_MASK = 0xF0; const uint32_t FAN_MASK = 0xF0;
const uint32_t FAN_AUTO = 0x50; const uint32_t FAN_AUTO = 0x50;
const uint32_t FAN_MIN = 0x00; const uint32_t FAN_MIN = 0x00;
@ -35,28 +41,28 @@ void LgIrClimate::transmit_state() {
uint32_t remote_state = 0x8800000; uint32_t remote_state = 0x8800000;
// ESP_LOGD(TAG, "climate_lg_ir mode_before_ code: 0x%02X", modeBefore_); // ESP_LOGD(TAG, "climate_lg_ir mode_before_ code: 0x%02X", modeBefore_);
// Set command
if (send_swing_cmd_) { if (send_swing_cmd_) {
send_swing_cmd_ = false; send_swing_cmd_ = false;
remote_state |= COMMAND_SWING; remote_state |= COMMAND_SWING;
} else { } else {
if (mode_before_ == climate::CLIMATE_MODE_OFF && this->mode == climate::CLIMATE_MODE_HEAT_COOL) { bool climate_is_off = (mode_before_ == climate::CLIMATE_MODE_OFF);
remote_state |= COMMAND_ON_AI;
} else if (mode_before_ == climate::CLIMATE_MODE_OFF && this->mode != climate::CLIMATE_MODE_OFF) {
remote_state |= COMMAND_ON;
this->mode = climate::CLIMATE_MODE_COOL;
} else {
switch (this->mode) { switch (this->mode) {
case climate::CLIMATE_MODE_COOL: case climate::CLIMATE_MODE_COOL:
remote_state |= COMMAND_COOL; remote_state |= climate_is_off ? COMMAND_ON_COOL : COMMAND_COOL;
break;
case climate::CLIMATE_MODE_HEAT:
remote_state |= COMMAND_HEAT;
break;
case climate::CLIMATE_MODE_HEAT_COOL:
remote_state |= COMMAND_AUTO;
break; break;
case climate::CLIMATE_MODE_DRY: case climate::CLIMATE_MODE_DRY:
remote_state |= COMMAND_DRY_FAN; remote_state |= climate_is_off ? COMMAND_ON_DRY : COMMAND_DRY;
break;
case climate::CLIMATE_MODE_FAN_ONLY:
remote_state |= climate_is_off ? COMMAND_ON_FAN_ONLY : COMMAND_FAN_ONLY;
break;
case climate::CLIMATE_MODE_HEAT_COOL:
remote_state |= climate_is_off ? COMMAND_ON_AI : COMMAND_AI;
break;
case climate::CLIMATE_MODE_HEAT:
remote_state |= climate_is_off ? COMMAND_ON_HEAT : COMMAND_HEAT;
break; break;
case climate::CLIMATE_MODE_OFF: case climate::CLIMATE_MODE_OFF:
default: default:
@ -64,14 +70,15 @@ void LgIrClimate::transmit_state() {
break; break;
} }
} }
mode_before_ = this->mode; mode_before_ = this->mode;
ESP_LOGD(TAG, "climate_lg_ir mode code: 0x%02X", this->mode); ESP_LOGD(TAG, "climate_lg_ir mode code: 0x%02X", this->mode);
// Set fan speed
if (this->mode == climate::CLIMATE_MODE_OFF) { if (this->mode == climate::CLIMATE_MODE_OFF) {
remote_state |= FAN_AUTO; remote_state |= FAN_AUTO;
} else if (this->mode == climate::CLIMATE_MODE_COOL || this->mode == climate::CLIMATE_MODE_DRY || } else {
this->mode == climate::CLIMATE_MODE_HEAT) {
switch (this->fan_mode.value()) { switch (this->fan_mode.value()) {
case climate::CLIMATE_FAN_HIGH: case climate::CLIMATE_FAN_HIGH:
remote_state |= FAN_MAX; remote_state |= FAN_MAX;
@ -89,15 +96,12 @@ void LgIrClimate::transmit_state() {
} }
} }
if (this->mode == climate::CLIMATE_MODE_HEAT_COOL) { // Set temperature
this->fan_mode = climate::CLIMATE_FAN_AUTO;
// remote_state |= FAN_MODE_AUTO_DRY;
}
if (this->mode == climate::CLIMATE_MODE_COOL || this->mode == climate::CLIMATE_MODE_HEAT) { if (this->mode == climate::CLIMATE_MODE_COOL || this->mode == climate::CLIMATE_MODE_HEAT) {
auto temp = (uint8_t) roundf(clamp<float>(this->target_temperature, TEMP_MIN, TEMP_MAX)); auto temp = (uint8_t) roundf(clamp<float>(this->target_temperature, TEMP_MIN, TEMP_MAX));
remote_state |= ((temp - 15) << TEMP_SHIFT); remote_state |= ((temp - 15) << TEMP_SHIFT);
} }
}
transmit_(remote_state); transmit_(remote_state);
this->publish_state(); this->publish_state();
} }
@ -125,37 +129,42 @@ bool LgIrClimate::on_receive(remote_base::RemoteReceiveData data) {
if ((remote_state & 0xFF00000) != 0x8800000) if ((remote_state & 0xFF00000) != 0x8800000)
return false; return false;
if ((remote_state & COMMAND_MASK) == COMMAND_ON) { // Get command
this->mode = climate::CLIMATE_MODE_COOL;
} else if ((remote_state & COMMAND_MASK) == COMMAND_ON_AI) {
this->mode = climate::CLIMATE_MODE_HEAT_COOL;
}
if ((remote_state & COMMAND_MASK) == COMMAND_OFF) { if ((remote_state & COMMAND_MASK) == COMMAND_OFF) {
this->mode = climate::CLIMATE_MODE_OFF; this->mode = climate::CLIMATE_MODE_OFF;
} else if ((remote_state & COMMAND_MASK) == COMMAND_SWING) { } else if ((remote_state & COMMAND_MASK) == COMMAND_SWING) {
this->swing_mode = this->swing_mode =
this->swing_mode == climate::CLIMATE_SWING_OFF ? climate::CLIMATE_SWING_VERTICAL : climate::CLIMATE_SWING_OFF; this->swing_mode == climate::CLIMATE_SWING_OFF ? climate::CLIMATE_SWING_VERTICAL : climate::CLIMATE_SWING_OFF;
} else { } else {
if ((remote_state & COMMAND_MASK) == COMMAND_AUTO) { switch (remote_state & COMMAND_MASK) {
this->mode = climate::CLIMATE_MODE_HEAT_COOL; case COMMAND_DRY:
} else if ((remote_state & COMMAND_MASK) == COMMAND_DRY_FAN) { case COMMAND_ON_DRY:
this->mode = climate::CLIMATE_MODE_DRY; this->mode = climate::CLIMATE_MODE_DRY;
} else if ((remote_state & COMMAND_MASK) == COMMAND_HEAT) { break;
case COMMAND_FAN_ONLY:
case COMMAND_ON_FAN_ONLY:
this->mode = climate::CLIMATE_MODE_FAN_ONLY;
break;
case COMMAND_AI:
case COMMAND_ON_AI:
this->mode = climate::CLIMATE_MODE_HEAT_COOL;
break;
case COMMAND_HEAT:
case COMMAND_ON_HEAT:
this->mode = climate::CLIMATE_MODE_HEAT; this->mode = climate::CLIMATE_MODE_HEAT;
} else { break;
case COMMAND_COOL:
case COMMAND_ON_COOL:
default:
this->mode = climate::CLIMATE_MODE_COOL; this->mode = climate::CLIMATE_MODE_COOL;
break;
} }
// Temperature // Get fan speed
if (this->mode == climate::CLIMATE_MODE_COOL || this->mode == climate::CLIMATE_MODE_HEAT)
this->target_temperature = ((remote_state & TEMP_MASK) >> TEMP_SHIFT) + 15;
// Fan Speed
if (this->mode == climate::CLIMATE_MODE_HEAT_COOL) { if (this->mode == climate::CLIMATE_MODE_HEAT_COOL) {
this->fan_mode = climate::CLIMATE_FAN_AUTO; this->fan_mode = climate::CLIMATE_FAN_AUTO;
} else if (this->mode == climate::CLIMATE_MODE_COOL || this->mode == climate::CLIMATE_MODE_HEAT || } else if (this->mode == climate::CLIMATE_MODE_COOL || this->mode == climate::CLIMATE_MODE_DRY ||
this->mode == climate::CLIMATE_MODE_DRY) { this->mode == climate::CLIMATE_MODE_FAN_ONLY || this->mode == climate::CLIMATE_MODE_HEAT) {
if ((remote_state & FAN_MASK) == FAN_AUTO) { if ((remote_state & FAN_MASK) == FAN_AUTO) {
this->fan_mode = climate::CLIMATE_FAN_AUTO; this->fan_mode = climate::CLIMATE_FAN_AUTO;
} else if ((remote_state & FAN_MASK) == FAN_MIN) { } else if ((remote_state & FAN_MASK) == FAN_MIN) {
@ -166,11 +175,17 @@ bool LgIrClimate::on_receive(remote_base::RemoteReceiveData data) {
this->fan_mode = climate::CLIMATE_FAN_HIGH; this->fan_mode = climate::CLIMATE_FAN_HIGH;
} }
} }
// Get temperature
if (this->mode == climate::CLIMATE_MODE_COOL || this->mode == climate::CLIMATE_MODE_HEAT) {
this->target_temperature = ((remote_state & TEMP_MASK) >> TEMP_SHIFT) + 15;
}
} }
this->publish_state(); this->publish_state();
return true; return true;
} }
void LgIrClimate::transmit_(uint32_t value) { void LgIrClimate::transmit_(uint32_t value) {
calc_checksum_(value); calc_checksum_(value);
ESP_LOGD(TAG, "Sending climate_lg_ir code: 0x%02" PRIX32, value); ESP_LOGD(TAG, "Sending climate_lg_ir code: 0x%02" PRIX32, value);

View file

@ -14,7 +14,7 @@ const uint8_t TEMP_MAX = 30; // Celsius
class LgIrClimate : public climate_ir::ClimateIR { class LgIrClimate : public climate_ir::ClimateIR {
public: public:
LgIrClimate() LgIrClimate()
: climate_ir::ClimateIR(TEMP_MIN, TEMP_MAX, 1.0f, true, false, : climate_ir::ClimateIR(TEMP_MIN, TEMP_MAX, 1.0f, true, true,
{climate::CLIMATE_FAN_AUTO, climate::CLIMATE_FAN_LOW, climate::CLIMATE_FAN_MEDIUM, {climate::CLIMATE_FAN_AUTO, climate::CLIMATE_FAN_LOW, climate::CLIMATE_FAN_MEDIUM,
climate::CLIMATE_FAN_HIGH}, climate::CLIMATE_FAN_HIGH},
{climate::CLIMATE_SWING_OFF, climate::CLIMATE_SWING_VERTICAL}) {} {climate::CLIMATE_SWING_OFF, climate::CLIMATE_SWING_VERTICAL}) {}