From 213a08504ab87e93fc6f202b86c88e97e0cf2d83 Mon Sep 17 00:00:00 2001 From: ElVit <54866762+ElVit@users.noreply.github.com> Date: Mon, 24 Nov 2025 22:48:35 +0100 Subject: [PATCH] Update panasonic_heatpump_climate.cpp --- .../climate/panasonic_heatpump_climate.cpp | 401 +++++++++--------- 1 file changed, 189 insertions(+), 212 deletions(-) diff --git a/components/panasonic_heatpump/climate/panasonic_heatpump_climate.cpp b/components/panasonic_heatpump/climate/panasonic_heatpump_climate.cpp index 0a04bfb..97cbb87 100644 --- a/components/panasonic_heatpump/climate/panasonic_heatpump_climate.cpp +++ b/components/panasonic_heatpump/climate/panasonic_heatpump_climate.cpp @@ -1,229 +1,206 @@ #include "panasonic_heatpump_climate.h" #include "esphome/core/log.h" +namespace esphome { +namespace panasonic_heatpump { +static const char* const TAG = "panasonic_heatpump.climate"; -namespace esphome -{ - namespace panasonic_heatpump - { - static const char *const TAG = "panasonic_heatpump.climate"; +void PanasonicHeatpumpClimate::dump_config() { + LOG_CLIMATE("", "Panasonic Heatpump Climate", this); +} - void PanasonicHeatpumpClimate::dump_config() - { - LOG_CLIMATE("", "Panasonic Heatpump Climate", this); +climate::ClimateTraits PanasonicHeatpumpClimate::traits() { + auto traits = climate::ClimateTraits(); + + // traits.set_supports_action(true); + traits.set_supports_current_temperature(true); + if (this->cool_mode_ && + (this->id_ == ClimateIds::CONF_CLIMATE_ZONE1 || this->id_ == ClimateIds::CONF_CLIMATE_ZONE2)) { + traits.set_supports_two_point_target_temperature(true); + this->supported_modes_.insert(climate::CLIMATE_MODE_COOL); + this->supported_modes_.insert(climate::CLIMATE_MODE_AUTO); + } + + traits.set_supported_modes(this->supported_modes_); + traits.set_visual_min_temperature(this->min_temperature_); + traits.set_visual_max_temperature(this->max_temperature_); + traits.set_visual_temperature_step(this->temperature_step_); + + return traits; +} + +void PanasonicHeatpumpClimate::control(const climate::ClimateCall& call) { + if (call.get_mode().has_value()) { + int byte6 = this->parent_->getResponseByte(6); + if (byte6 >= 0) { + climate::ClimateMode new_mode = *call.get_mode(); + uint8_t newByte6 = this->setClimateMode(new_mode, (uint8_t)byte6); + this->parent_->set_command_byte(newByte6, 6); } + } - climate::ClimateTraits PanasonicHeatpumpClimate::traits() - { - auto traits = climate::ClimateTraits(); + if (call.get_target_temperature().has_value()) { + float new_temp = *call.get_target_temperature(); + switch (this->id_) { + case ClimateIds::CONF_CLIMATE_TANK: + this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 42); // set11 + break; + case ClimateIds::CONF_CLIMATE_ZONE1: + this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 38); // set5 + break; + case ClimateIds::CONF_CLIMATE_ZONE2: + this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 40); // set7 + break; + }; + } - //traits.set_supports_action(true); - traits.set_supports_current_temperature(true); - if (this->cool_mode_ && - (this->id_ == ClimateIds::CONF_CLIMATE_ZONE1 || - this->id_ == ClimateIds::CONF_CLIMATE_ZONE2)) - { - traits.set_supports_two_point_target_temperature(true); - this->supported_modes_.insert(climate::CLIMATE_MODE_COOL); - this->supported_modes_.insert(climate::CLIMATE_MODE_AUTO); - } + if (call.get_target_temperature_high().has_value()) { + float new_temp = *call.get_target_temperature_high(); + switch (this->id_) { + case ClimateIds::CONF_CLIMATE_ZONE1: + this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 38); // set5 + break; + case ClimateIds::CONF_CLIMATE_ZONE2: + this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 40); // set7 + break; + }; + } - traits.set_supported_modes(this->supported_modes_); - traits.set_visual_min_temperature(this->min_temperature_); - traits.set_visual_max_temperature(this->max_temperature_); - traits.set_visual_temperature_step(this->temperature_step_); + if (call.get_target_temperature_low().has_value()) { + float new_temp = *call.get_target_temperature_low(); + switch (this->id_) { + case ClimateIds::CONF_CLIMATE_ZONE1: + this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 39); // set6 + break; + case ClimateIds::CONF_CLIMATE_ZONE2: + this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 41); // set8 + break; + }; + } - return traits; - } + this->publish_state(); + this->keep_state_ = 2; +} - void PanasonicHeatpumpClimate::control(const climate::ClimateCall &call) - { - if (call.get_mode().has_value()) - { - int byte6 = this->parent_->getResponseByte(6); - if (byte6 >= 0) - { - climate::ClimateMode new_mode = *call.get_mode(); - uint8_t newByte6 = this->setClimateMode(new_mode, (uint8_t)byte6); - this->parent_->set_command_byte(newByte6, 6); - } - } +void PanasonicHeatpumpClimate::publish_new_state(const std::vector& data) { + if (this->keep_state_ > 0) { + this->keep_state_--; + return; + } + if (data.empty()) + return; - if (call.get_target_temperature().has_value()) - { - float new_temp = *call.get_target_temperature(); - switch (this->id_) - { - case ClimateIds::CONF_CLIMATE_TANK: - this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 42); // set11 - break; - case ClimateIds::CONF_CLIMATE_ZONE1: - this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 38); // set5 - break; - case ClimateIds::CONF_CLIMATE_ZONE2: - this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 40); // set7 - break; - }; - } + uint8_t new_mode; + float new_target_temp_heat; + float new_target_temp_cool; + float new_current_temp; - if (call.get_target_temperature_high().has_value()) - { - float new_temp = *call.get_target_temperature_high(); - switch (this->id_) - { - case ClimateIds::CONF_CLIMATE_ZONE1: - this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 38); // set5 - break; - case ClimateIds::CONF_CLIMATE_ZONE2: - this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 40); // set7 - break; - }; - } + new_mode = this->getClimateMode(data[6]); // set9 + switch (this->id_) { + case ClimateIds::CONF_CLIMATE_TANK: + new_target_temp_heat = PanasonicDecode::getByteMinus128(data[42]); // set11 + new_current_temp = PanasonicDecode::getByteMinus128(data[141]); // top10 + break; + case ClimateIds::CONF_CLIMATE_ZONE1: + new_target_temp_heat = PanasonicDecode::getByteMinus128(data[38]); // set5 + new_target_temp_cool = PanasonicDecode::getByteMinus128(data[39]); // set6 + new_current_temp = PanasonicDecode::getByteMinus128(data[139]); // top56 + break; + case ClimateIds::CONF_CLIMATE_ZONE2: + new_target_temp_heat = PanasonicDecode::getByteMinus128(data[40]); // set7 + new_target_temp_cool = PanasonicDecode::getByteMinus128(data[41]); // set8 + new_current_temp = PanasonicDecode::getByteMinus128(data[140]); // top57 + break; + default: + return; + }; - if (call.get_target_temperature_low().has_value()) - { - float new_temp = *call.get_target_temperature_low(); - switch (this->id_) - { - case ClimateIds::CONF_CLIMATE_ZONE1: - this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 39); // set6 - break; - case ClimateIds::CONF_CLIMATE_ZONE2: - this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 41); // set8 - break; - }; - } + if (!this->get_traits().get_supports_two_point_target_temperature() && this->mode == new_mode && + this->target_temperature == new_target_temp_heat && this->current_temperature == new_current_temp) + return; + if (this->get_traits().get_supports_two_point_target_temperature() && this->mode == new_mode && + this->target_temperature_high == new_target_temp_heat && this->target_temperature_low == new_target_temp_cool && + this->current_temperature == new_current_temp) + return; - this->publish_state(); - this->keep_state_ = 2; - } + if (new_mode != 255) + this->mode = (climate::ClimateMode)new_mode; + // this->action = climate::CLIMATE_ACTION_IDLE; + if (this->get_traits().get_supports_two_point_target_temperature()) { + this->target_temperature_high = new_target_temp_heat; + this->target_temperature_low = new_target_temp_cool; + } else { + this->target_temperature = new_target_temp_heat; + } + this->current_temperature = new_current_temp; + this->publish_state(); +} - void PanasonicHeatpumpClimate::publish_new_state(const std::vector& data) - { - if (this->keep_state_ > 0) - { - this->keep_state_--; - return; - } - if (data.empty()) return; +uint8_t PanasonicHeatpumpClimate::getClimateMode(const uint8_t input) { + switch (this->id_) { + case ClimateIds::CONF_CLIMATE_TANK: + switch ((uint8_t)(input & 0b110000)) { + case 0b010000: + return climate::CLIMATE_MODE_OFF; + case 0b100000: + return climate::CLIMATE_MODE_HEAT; + default: + return 255; + }; + case ClimateIds::CONF_CLIMATE_ZONE1: + case ClimateIds::CONF_CLIMATE_ZONE2: + switch ((uint8_t)(input & 0b1111)) { + case 0b0001: + return climate::CLIMATE_MODE_OFF; + case 0b0010: + return climate::CLIMATE_MODE_HEAT; + case 0b0011: + return climate::CLIMATE_MODE_COOL; + case 0b1000: + return climate::CLIMATE_MODE_AUTO; + case 0b1001: + return climate::CLIMATE_MODE_AUTO; // 0x19 = auto-heat + case 0b1010: + return climate::CLIMATE_MODE_AUTO; // 0x1A = auto-cool + default: + return 255; + }; + default: + return 255; + }; +} - uint8_t new_mode; - float new_target_temp_heat; - float new_target_temp_cool; - float new_current_temp; - - new_mode = this->getClimateMode(data[6]); // set9 - switch (this->id_) - { - case ClimateIds::CONF_CLIMATE_TANK: - new_target_temp_heat = PanasonicDecode::getByteMinus128(data[42]); // set11 - new_current_temp = PanasonicDecode::getByteMinus128(data[141]); // top10 - break; - case ClimateIds::CONF_CLIMATE_ZONE1: - new_target_temp_heat = PanasonicDecode::getByteMinus128(data[38]); // set5 - new_target_temp_cool = PanasonicDecode::getByteMinus128(data[39]); // set6 - new_current_temp = PanasonicDecode::getByteMinus128(data[139]); // top56 - break; - case ClimateIds::CONF_CLIMATE_ZONE2: - new_target_temp_heat = PanasonicDecode::getByteMinus128(data[40]); // set7 - new_target_temp_cool = PanasonicDecode::getByteMinus128(data[41]); // set8 - new_current_temp = PanasonicDecode::getByteMinus128(data[140]); // top57 - break; - default: return; - }; - - if (!this->get_traits().get_supports_two_point_target_temperature() && - this->mode == new_mode && - this->target_temperature == new_target_temp_heat && - this->current_temperature == new_current_temp) return; - if (this->get_traits().get_supports_two_point_target_temperature() && - this->mode == new_mode && - this->target_temperature_high == new_target_temp_heat && - this->target_temperature_low == new_target_temp_cool && - this->current_temperature == new_current_temp) return; - - if (new_mode != 255) this->mode = (climate::ClimateMode)new_mode; - //this->action = climate::CLIMATE_ACTION_IDLE; - if (this->get_traits().get_supports_two_point_target_temperature()) - { - this->target_temperature_high = new_target_temp_heat; - this->target_temperature_low = new_target_temp_cool; - } - else - { - this->target_temperature = new_target_temp_heat; - } - this->current_temperature = new_current_temp; - this->publish_state(); - } - - uint8_t PanasonicHeatpumpClimate::getClimateMode(const uint8_t input) - { - switch (this->id_) - { - case ClimateIds::CONF_CLIMATE_TANK: - switch ((uint8_t)(input & 0b110000)) - { - case 0b010000: - return climate::CLIMATE_MODE_OFF; - case 0b100000: - return climate::CLIMATE_MODE_HEAT; - default: return 255; - }; - case ClimateIds::CONF_CLIMATE_ZONE1: - case ClimateIds::CONF_CLIMATE_ZONE2: - switch ((uint8_t)(input & 0b1111)) - { - case 0b0001: - return climate::CLIMATE_MODE_OFF; - case 0b0010: - return climate::CLIMATE_MODE_HEAT; - case 0b0011: - return climate::CLIMATE_MODE_COOL; - case 0b1000: - return climate::CLIMATE_MODE_AUTO; - case 0b1001: - return climate::CLIMATE_MODE_AUTO; // 0x19 = auto-heat - case 0b1010: - return climate::CLIMATE_MODE_AUTO; // 0x1A = auto-cool - default: return 255; - }; - default: return 255; - }; - } - - uint8_t PanasonicHeatpumpClimate::setClimateMode(const climate::ClimateMode mode, uint8_t byte) - { - uint8_t newByte = byte; - switch (this->id_) - { - case ClimateIds::CONF_CLIMATE_TANK: - newByte = newByte & 0b11001111; - switch (mode) - { - case climate::CLIMATE_MODE_OFF: - return newByte + 0b010000; - case climate::CLIMATE_MODE_HEAT: - return newByte + 0b100000; - default: return 0; - }; - case ClimateIds::CONF_CLIMATE_ZONE1: - case ClimateIds::CONF_CLIMATE_ZONE2: - newByte = newByte & 0b11110000; - switch (mode) - { - case climate::CLIMATE_MODE_OFF: - return newByte + 0b0001; - case climate::CLIMATE_MODE_HEAT: - return newByte + 0b0010; - case climate::CLIMATE_MODE_COOL: - return newByte + 0b0011; - case climate::CLIMATE_MODE_AUTO: - return newByte + 0b1000; - default: return 0; - }; - default: return 0; - }; - } - } // namespace panasonic_heatpump -} // namespace esphome +uint8_t PanasonicHeatpumpClimate::setClimateMode(const climate::ClimateMode mode, uint8_t byte) { + uint8_t newByte = byte; + switch (this->id_) { + case ClimateIds::CONF_CLIMATE_TANK: + newByte = newByte & 0b11001111; + switch (mode) { + case climate::CLIMATE_MODE_OFF: + return newByte + 0b010000; + case climate::CLIMATE_MODE_HEAT: + return newByte + 0b100000; + default: + return 0; + }; + case ClimateIds::CONF_CLIMATE_ZONE1: + case ClimateIds::CONF_CLIMATE_ZONE2: + newByte = newByte & 0b11110000; + switch (mode) { + case climate::CLIMATE_MODE_OFF: + return newByte + 0b0001; + case climate::CLIMATE_MODE_HEAT: + return newByte + 0b0010; + case climate::CLIMATE_MODE_COOL: + return newByte + 0b0011; + case climate::CLIMATE_MODE_AUTO: + return newByte + 0b1000; + default: + return 0; + }; + default: + return 0; + }; +} +} // namespace panasonic_heatpump +} // namespace esphome