From ec33c9b031c43c84c26fe804ea0cfdcb00b49049 Mon Sep 17 00:00:00 2001 From: ElVit <54866762+ElVit@users.noreply.github.com> Date: Mon, 24 Nov 2025 22:51:11 +0100 Subject: [PATCH] Update panasonic_heatpump.cpp --- .../panasonic_heatpump/panasonic_heatpump.cpp | 743 +++++++++--------- 1 file changed, 354 insertions(+), 389 deletions(-) diff --git a/components/panasonic_heatpump/panasonic_heatpump.cpp b/components/panasonic_heatpump/panasonic_heatpump.cpp index 4561ce5..057b1ec 100644 --- a/components/panasonic_heatpump/panasonic_heatpump.cpp +++ b/components/panasonic_heatpump/panasonic_heatpump.cpp @@ -1,421 +1,386 @@ #include "panasonic_heatpump.h" #include "esphome/core/application.h" +namespace esphome { +namespace panasonic_heatpump { +static const char* const TAG = "panasonic_heatpump"; -namespace esphome -{ - namespace panasonic_heatpump - { - static const char *const TAG = "panasonic_heatpump"; +void PanasonicHeatpumpComponent::dump_config() { + ESP_LOGW(TAG, "*** Panasonic Heatpump Component v0.0.4 ***"); + delay(10); // NOLINT +} - void PanasonicHeatpumpComponent::dump_config() - { - ESP_LOGW(TAG, "*** Panasonic Heatpump Component v0.0.4 ***"); +void PanasonicHeatpumpComponent::setup() { + ESP_LOGCONFIG(TAG, "Setting up Panasonic Heatpump ..."); + delay(10); // NOLINT + this->check_uart_settings(9600, 1, uart::UART_CONFIG_PARITY_EVEN, 8); + + this->update(); +} + +void PanasonicHeatpumpComponent::update() { + if (this->uart_client_ != nullptr) + return; + this->next_request_ = this->send_extra_request_ ? RequestType::POLLING_EXTRA : RequestType::POLLING; +} + +void PanasonicHeatpumpComponent::loop() { + switch (this->loop_state_) { + case LoopState::READ_RESPONSE: + this->read_response(); + this->loop_state_ = LoopState::CHECK_RESPONSE; + break; + case LoopState::CHECK_RESPONSE: + this->current_response_ = this->check_response(this->response_message_); + switch (this->current_response_) { + case ResponseType::UNKNOWN: + this->loop_state_ = LoopState::SEND_REQUEST; + break; + case ResponseType::DEFAULT: + this->loop_state_ = LoopState::PUBLISH_SENSOR; + break; + case ResponseType::EXTRA: + this->loop_state_ = LoopState::PUBLISH_EXTRA_SENSOR; + break; + }; + break; + case LoopState::PUBLISH_SENSOR: + for (auto* entity : this->sensors_) { + entity->publish_new_state(this->heatpump_default_message_); + } + this->loop_state_ = LoopState::PUBLISH_BINARY_SENSOR; + break; + case LoopState::PUBLISH_BINARY_SENSOR: + for (auto* entity : this->binary_sensors_) { + entity->publish_new_state(this->heatpump_default_message_); + } + this->loop_state_ = LoopState::PUBLISH_TEXT_SENSOR; + break; + case LoopState::PUBLISH_TEXT_SENSOR: + for (auto* entity : this->text_sensors_) { + entity->publish_new_state(this->heatpump_default_message_); + } + this->loop_state_ = LoopState::PUBLISH_NUMBER; + break; + case LoopState::PUBLISH_NUMBER: + for (auto* entity : this->numbers_) { + entity->publish_new_state(this->heatpump_default_message_); + } + this->loop_state_ = LoopState::PUBLISH_SELECT; + break; + case LoopState::PUBLISH_SELECT: + for (auto* entity : this->selects_) { + entity->publish_new_state(this->heatpump_default_message_); + } + this->loop_state_ = LoopState::PUBLISH_SWITCH; + break; + case LoopState::PUBLISH_SWITCH: + for (auto* entity : this->switches_) { + entity->publish_new_state(this->heatpump_default_message_); + } + this->loop_state_ = LoopState::PUBLISH_CLIMATE; + break; + case LoopState::PUBLISH_CLIMATE: + for (auto* entity : this->climates_) { + entity->publish_new_state(this->heatpump_default_message_); + } + this->loop_state_ = LoopState::SEND_REQUEST; + break; + case LoopState::PUBLISH_EXTRA_SENSOR: + for (auto* entity : this->extra_sensors_) { + entity->publish_new_state(this->heatpump_extra_message_); + } + this->loop_state_ = LoopState::SEND_REQUEST; + break; + case LoopState::SEND_REQUEST: + this->send_request(this->next_request_); + this->loop_state_ = LoopState::READ_REQUEST; + break; + case LoopState::READ_REQUEST: + this->read_request(); + this->loop_state_ = LoopState::RESTART_LOOP; + break; + default: + this->loop_state_ = LoopState::READ_RESPONSE; + break; + }; +} + +void PanasonicHeatpumpComponent::read_response() { + while (this->available()) { + // Read each byte from heatpump and forward it directly to the client (CZ-TAW1) + this->read_byte(&byte_); + if (this->uart_client_ != nullptr) { + this->uart_client_->write_byte(byte_); + } + + // Message shall start with 0x31, 0x71 or 0xF1, if not skip this byte + if (!this->response_receiving_) { + if (byte_ != 0x31 && byte_ != 0x71 && byte_ != 0xF1) + continue; + this->response_message_.clear(); + this->response_receiving_ = true; + } + // Add current byte to message buffer + this->response_message_.push_back(byte_); + + // 2. byte contains the payload size + if (this->response_message_.size() == 2) { + this->payload_length_ = byte_; + } + // Discard message if format is wrong + if ((this->response_message_.size() == 3 && byte_ != 0x01 && byte_ != 0x10) || + (this->response_message_.size() == 4 && byte_ != 0x10 && byte_ != 0x21)) { + this->response_receiving_ = false; + ESP_LOGW(TAG, "Invalid response message: %d. byte is 0x%02X but expexted is 0x01, 0x10 or 0x21", + response_message_.size(), byte_); delay(10); // NOLINT + continue; } - void PanasonicHeatpumpComponent::setup() - { - ESP_LOGCONFIG(TAG, "Setting up Panasonic Heatpump ..."); + // Check if message is complete + if (this->response_message_.size() > 2 && this->response_message_.size() == this->payload_length_ + 3) { + this->response_receiving_ = false; + this->current_response_count_++; + if (this->log_uart_msg_) + PanasonicHelpers::log_uart_hex(UART_LOG_RX, this->response_message_, ','); + } + } +} + +void PanasonicHeatpumpComponent::send_request(RequestType requestType) { + switch (requestType) { + case RequestType::COMMAND: + if (this->log_uart_msg_) + PanasonicHelpers::log_uart_hex(UART_LOG_TX, this->command_message_, ','); + this->write_array(this->command_message_); + this->flush(); + break; + case RequestType::INITIAL: + // Probably not necessary but CZ-TAW1 sends this query on boot + if (this->log_uart_msg_) + PanasonicHelpers::log_uart_hex(UART_LOG_TX, PanasonicCommand::InitialRequest, INIT_REQUEST_SIZE, ','); + this->write_array(PanasonicCommand::InitialRequest, INIT_REQUEST_SIZE); + this->flush(); + break; + case RequestType::POLLING: + if (this->log_uart_msg_) + PanasonicHelpers::log_uart_hex(UART_LOG_TX, PanasonicCommand::PollingMessage, DATA_MESSAGE_SIZE, ','); + this->write_array(PanasonicCommand::PollingMessage, DATA_MESSAGE_SIZE); + this->flush(); + break; + case RequestType::POLLING_EXTRA: + if (this->log_uart_msg_) + PanasonicHelpers::log_uart_hex(UART_LOG_TX, PanasonicCommand::PollingExtraMessage, DATA_MESSAGE_SIZE, ','); + this->write_array(PanasonicCommand::PollingExtraMessage, DATA_MESSAGE_SIZE); + this->flush(); + break; + }; + + this->next_request_ = RequestType::NONE; +} + +void PanasonicHeatpumpComponent::read_request() { + if (this->uart_client_ == nullptr) + return; + + while (this->uart_client_->available()) { + // Read each byte from client and forward it directly to the heatpump + this->uart_client_->read_byte(&byte_); + this->write_byte(byte_); + + // Message shall start with 0x31, 0x71 or 0xF1, if not skip this byte + if (!this->request_receiving_) { + if (byte_ != 0x31 && byte_ != 0x71 && byte_ != 0xF1) + continue; + this->request_message_.clear(); + this->request_receiving_ = true; + } + // Add current byte to message buffer + this->request_message_.push_back(byte_); + + // 2. byte contains the payload size + if (this->request_message_.size() == 2) { + this->payload_length_ = byte_; + } + // Discard message if format is wrong + if ((this->request_message_.size() == 3 && byte_ != 0x01 && byte_ != 0x10) || + (this->request_message_.size() == 4 && byte_ != 0x10 && byte_ != 0x21)) { + this->request_receiving_ = false; + ESP_LOGW(TAG, "Invalid request message: %d. byte is 0x%02X but expexted is 0x01, 0x10 or 0x21", + request_message_.size(), byte_); delay(10); // NOLINT - this->check_uart_settings(9600, 1, uart::UART_CONFIG_PARITY_EVEN, 8); - - this->update(); + continue; } - void PanasonicHeatpumpComponent::update() - { - if (this->uart_client_ != nullptr) return; - this->next_request_ = this->send_extra_request_ ? RequestType::POLLING_EXTRA : RequestType::POLLING; + // Check if message is complete + if (this->request_message_.size() > 2 && this->request_message_.size() == this->payload_length_ + 3) { + this->request_receiving_ = false; + if (this->log_uart_msg_) + PanasonicHelpers::log_uart_hex(UART_LOG_TX, this->request_message_, ','); } + } +} - void PanasonicHeatpumpComponent::loop() - { - switch (this->loop_state_) - { - case LoopState::READ_RESPONSE: - this->read_response(); - this->loop_state_ = LoopState::CHECK_RESPONSE; - break; - case LoopState::CHECK_RESPONSE: - this->current_response_ = this->check_response(this->response_message_); - switch (this->current_response_) - { - case ResponseType::UNKNOWN: - this->loop_state_ = LoopState::SEND_REQUEST; - break; - case ResponseType::DEFAULT: - this->loop_state_ = LoopState::PUBLISH_SENSOR; - break; - case ResponseType::EXTRA: - this->loop_state_ = LoopState::PUBLISH_EXTRA_SENSOR; - break; - }; - break; - case LoopState::PUBLISH_SENSOR: - for (auto *entity : this->sensors_) - { - entity->publish_new_state(this->heatpump_default_message_); - } - this->loop_state_ = LoopState::PUBLISH_BINARY_SENSOR; - break; - case LoopState::PUBLISH_BINARY_SENSOR: - for (auto *entity : this->binary_sensors_) - { - entity->publish_new_state(this->heatpump_default_message_); - } - this->loop_state_ = LoopState::PUBLISH_TEXT_SENSOR; - break; - case LoopState::PUBLISH_TEXT_SENSOR: - for (auto *entity : this->text_sensors_) - { - entity->publish_new_state(this->heatpump_default_message_); - } - this->loop_state_ = LoopState::PUBLISH_NUMBER; - break; - case LoopState::PUBLISH_NUMBER: - for (auto *entity : this->numbers_) - { - entity->publish_new_state(this->heatpump_default_message_); - } - this->loop_state_ = LoopState::PUBLISH_SELECT; - break; - case LoopState::PUBLISH_SELECT: - for (auto *entity : this->selects_) - { - entity->publish_new_state(this->heatpump_default_message_); - } - this->loop_state_ = LoopState::PUBLISH_SWITCH; - break; - case LoopState::PUBLISH_SWITCH: - for (auto *entity : this->switches_) - { - entity->publish_new_state(this->heatpump_default_message_); - } - this->loop_state_ = LoopState::PUBLISH_CLIMATE; - break; - case LoopState::PUBLISH_CLIMATE: - for (auto *entity : this->climates_) - { - entity->publish_new_state(this->heatpump_default_message_); - } - this->loop_state_ = LoopState::SEND_REQUEST; - break; - case LoopState::PUBLISH_EXTRA_SENSOR: - for (auto *entity : this->extra_sensors_) - { - entity->publish_new_state(this->heatpump_extra_message_); - } - this->loop_state_ = LoopState::SEND_REQUEST; - break; - case LoopState::SEND_REQUEST: - this->send_request(this->next_request_); - this->loop_state_ = LoopState::READ_REQUEST; - break; - case LoopState::READ_REQUEST: - this->read_request(); - this->loop_state_ = LoopState::RESTART_LOOP; - break; - default: - this->loop_state_ = LoopState::READ_RESPONSE; - break; - }; - } +int PanasonicHeatpumpComponent::getResponseByte(const int index) { + if (this->heatpump_default_message_.size() > index) + return this->heatpump_default_message_[index]; + return -1; +} - void PanasonicHeatpumpComponent::read_response() - { - while (this->available()) - { - // Read each byte from heatpump and forward it directly to the client (CZ-TAW1) - this->read_byte(&byte_); - if (this->uart_client_ != nullptr) - { - this->uart_client_->write_byte(byte_); - } +int PanasonicHeatpumpComponent::getExtraResponseByte(const int index) { + if (this->heatpump_extra_message_.size() > index) + return this->heatpump_extra_message_[index]; + return -1; +} - // Message shall start with 0x31, 0x71 or 0xF1, if not skip this byte - if (!this->response_receiving_) - { - if (byte_ != 0x31 && byte_ != 0x71 && byte_ != 0xF1) continue; - this->response_message_.clear(); - this->response_receiving_ = true; - } - // Add current byte to message buffer - this->response_message_.push_back(byte_); +ResponseType PanasonicHeatpumpComponent::check_response(const std::vector& data) { + // Read response message: + // format: 0x71 [payload_length] 0x01 [0x10 || 0x21] [[TOP0 - TOP114] ...] 0x00 [checksum] + // payload_length: payload_length + 3 = packet_length + // checksum: if (sum(all bytes) & 0xFF == 0) ==> valid packet - // 2. byte contains the payload size - if (this->response_message_.size() == 2) - { - this->payload_length_ = byte_; - } - // Discard message if format is wrong - if ((this->response_message_.size() == 3 && byte_ != 0x01 && byte_ != 0x10) || - (this->response_message_.size() == 4 && byte_ != 0x10 && byte_ != 0x21)) - { - this->response_receiving_ = false; - ESP_LOGW(TAG, "Invalid response message: %d. byte is 0x%02X but expexted is 0x01, 0x10 or 0x21", - response_message_.size(), byte_); - delay(10); // NOLINT - continue; - } + if (data.empty()) + return ResponseType::UNKNOWN; + if (data[0] != 0x71) + return ResponseType::UNKNOWN; + if (this->response_receiving_) + return ResponseType::UNKNOWN; + if (data.size() != RESPONSE_MSG_SIZE) { + ESP_LOGW(TAG, "Invalid response message length: recieved %d - expected %d", data.size(), RESPONSE_MSG_SIZE); + delay(10); // NOLINT + return ResponseType::UNKNOWN; + } - // Check if message is complete - if (this->response_message_.size() > 2 && - this->response_message_.size() == this->payload_length_ + 3) - { - this->response_receiving_ = false; - this->current_response_count_++; - if (this->log_uart_msg_) PanasonicHelpers::log_uart_hex(UART_LOG_RX, this->response_message_, ','); - } - } - } + // Verify checksum + uint8_t checksum = 0; + for (int i = 0; i < data.size(); i++) { + checksum += data[i]; + } + // all bytes (including checksum byte) shall be 0x00 + if (checksum != 0) { + ESP_LOGW(TAG, "Invalid response message: checksum = 0x%02X, last_byte = 0x%02X", checksum, data[202]); + delay(10); // NOLINT + return ResponseType::UNKNOWN; + } - void PanasonicHeatpumpComponent::send_request(RequestType requestType) - { - switch (requestType) - { - case RequestType::COMMAND: - if (this->log_uart_msg_) PanasonicHelpers::log_uart_hex(UART_LOG_TX, this->command_message_, ','); - this->write_array(this->command_message_); - this->flush(); - break; - case RequestType::INITIAL: - // Probably not necessary but CZ-TAW1 sends this query on boot - if (this->log_uart_msg_) PanasonicHelpers::log_uart_hex(UART_LOG_TX, PanasonicCommand::InitialRequest, INIT_REQUEST_SIZE, ','); - this->write_array(PanasonicCommand::InitialRequest, INIT_REQUEST_SIZE); - this->flush(); - break; - case RequestType::POLLING: - if (this->log_uart_msg_) PanasonicHelpers::log_uart_hex(UART_LOG_TX, PanasonicCommand::PollingMessage, DATA_MESSAGE_SIZE, ','); - this->write_array(PanasonicCommand::PollingMessage, DATA_MESSAGE_SIZE); - this->flush(); - break; - case RequestType::POLLING_EXTRA: - if (this->log_uart_msg_) PanasonicHelpers::log_uart_hex(UART_LOG_TX, PanasonicCommand::PollingExtraMessage, DATA_MESSAGE_SIZE, ','); - this->write_array(PanasonicCommand::PollingExtraMessage, DATA_MESSAGE_SIZE); - this->flush(); - break; - }; + this->send_extra_request_ = data[3] == 0x10 && data[199] > 0x02 && this->send_extra_request_ == false ? true : false; - this->next_request_ = RequestType::NONE; - } + // Get response type and save the response + auto responseType = ResponseType::UNKNOWN; + if (data[3] == 0x10) { + responseType = ResponseType::DEFAULT; + this->heatpump_default_message_ = data; + } else if (data[3] == 0x21) { + responseType = ResponseType::EXTRA; + this->heatpump_extra_message_ = data; + } + if (responseType == ResponseType::UNKNOWN) { + ESP_LOGW(TAG, "Unknown response type (4. byte): 0x%02X. Expected 0x10 or 0x21.", data[3]); + delay(10); // NOLINT + return responseType; + } - void PanasonicHeatpumpComponent::read_request() - { - if (this->uart_client_ == nullptr) return; + // Check if the current response is a new response + if (this->last_response_count_ == this->current_response_count_) + return ResponseType::UNKNOWN; + this->last_response_count_ = this->current_response_count_; - while (this->uart_client_->available()) - { - // Read each byte from client and forward it directly to the heatpump - this->uart_client_->read_byte(&byte_); - this->write_byte(byte_); + return responseType; +} - // Message shall start with 0x31, 0x71 or 0xF1, if not skip this byte - if (!this->request_receiving_) - { - if (byte_ != 0x31 && byte_ != 0x71 && byte_ != 0xF1) continue; - this->request_message_.clear(); - this->request_receiving_ = true; - } - // Add current byte to message buffer - this->request_message_.push_back(byte_); +void PanasonicHeatpumpComponent::set_command_high_nibble(const uint8_t value, const uint8_t index) { + if (this->next_request_ != RequestType::COMMAND) { + // initialize the command + this->command_message_.assign(std::begin(PanasonicCommand::CommandMessage), + std::end(PanasonicCommand::CommandMessage)); + } + uint8_t lowNibble = this->heatpump_default_message_[index] & 0b1111; + uint8_t highNibble = value << 4; + // set command byte + this->command_message_[index] = highNibble + lowNibble; + // calculate and set set checksum (last element) + this->command_message_.back() = + PanasonicCommand::calcChecksum(this->command_message_, this->command_message_.size() - 1); - // 2. byte contains the payload size - if (this->request_message_.size() == 2) - { - this->payload_length_ = byte_; - } - // Discard message if format is wrong - if ((this->request_message_.size() == 3 && byte_ != 0x01 && byte_ != 0x10) || - (this->request_message_.size() == 4 && byte_ != 0x10 && byte_ != 0x21)) - { - this->request_receiving_ = false; - ESP_LOGW(TAG, "Invalid request message: %d. byte is 0x%02X but expexted is 0x01, 0x10 or 0x21", - request_message_.size(), byte_); - delay(10); // NOLINT - continue; - } + // command will be send on next loop + this->next_request_ = RequestType::COMMAND; +} - // Check if message is complete - if (this->request_message_.size() > 2 && - this->request_message_.size() == this->payload_length_ + 3) - { - this->request_receiving_ = false; - if (this->log_uart_msg_) PanasonicHelpers::log_uart_hex(UART_LOG_TX, this->request_message_, ','); - } - } - } +void PanasonicHeatpumpComponent::set_command_low_nibble(const uint8_t value, const uint8_t index) { + if (this->next_request_ != RequestType::COMMAND) { + // initialize the command + this->command_message_.assign(std::begin(PanasonicCommand::CommandMessage), + std::end(PanasonicCommand::CommandMessage)); + } + uint8_t highNibble = this->heatpump_default_message_[index] & 0b11110000; + uint8_t lowNibble = value & 0b1111; + // set command byte + this->command_message_[index] = highNibble + lowNibble; + // calculate and set set checksum (last element) + this->command_message_.back() = + PanasonicCommand::calcChecksum(this->command_message_, this->command_message_.size() - 1); - int PanasonicHeatpumpComponent::getResponseByte(const int index) - { - if (this->heatpump_default_message_.size() > index) return this->heatpump_default_message_[index]; - return -1; - } + // command will be send on next loop + this->next_request_ = RequestType::COMMAND; +} - int PanasonicHeatpumpComponent::getExtraResponseByte(const int index) - { - if (this->heatpump_extra_message_.size() > index) return this->heatpump_extra_message_[index]; - return -1; - } +void PanasonicHeatpumpComponent::set_command_byte(const uint8_t value, const uint8_t index) { + if (this->next_request_ != RequestType::COMMAND) { + // initialize the command + this->command_message_.assign(std::begin(PanasonicCommand::CommandMessage), + std::end(PanasonicCommand::CommandMessage)); + } + // set command byte + this->command_message_[index] = value; + // calculate and set set checksum (last element) + this->command_message_.back() = + PanasonicCommand::calcChecksum(this->command_message_, this->command_message_.size() - 1); - ResponseType PanasonicHeatpumpComponent::check_response(const std::vector& data) - { - // Read response message: - // format: 0x71 [payload_length] 0x01 [0x10 || 0x21] [[TOP0 - TOP114] ...] 0x00 [checksum] - // payload_length: payload_length + 3 = packet_length - // checksum: if (sum(all bytes) & 0xFF == 0) ==> valid packet + // command will be send on next loop + this->next_request_ = RequestType::COMMAND; +} - if (data.empty()) return ResponseType::UNKNOWN; - if (data[0] != 0x71) return ResponseType::UNKNOWN; - if (this->response_receiving_) return ResponseType::UNKNOWN; - if (data.size() != RESPONSE_MSG_SIZE) - { - ESP_LOGW(TAG, "Invalid response message length: recieved %d - expected %d", data.size(), RESPONSE_MSG_SIZE); - delay(10); // NOLINT - return ResponseType::UNKNOWN; - } +void PanasonicHeatpumpComponent::set_command_curve(const uint8_t value, const uint8_t index) { + if (this->next_request_ != RequestType::COMMAND) { + // initialize the command + this->command_message_.assign(std::begin(PanasonicCommand::CommandMessage), + std::end(PanasonicCommand::CommandMessage)); + } - // Verify checksum - uint8_t checksum = 0; - for (int i = 0; i < data.size(); i++) - { - checksum += data[i]; - } - // all bytes (including checksum byte) shall be 0x00 - if (checksum != 0) - { - ESP_LOGW(TAG, "Invalid response message: checksum = 0x%02X, last_byte = 0x%02X", checksum, data[202]); - delay(10); // NOLINT - return ResponseType::UNKNOWN; - } + // Set zone 1 curve bytes + if (index == 75 || index == 76 || index == 77 || index == 78 || index == 86 || index == 87 || index == 88 || + index == 89) { + this->command_message_[75] = this->heatpump_default_message_[75]; + this->command_message_[76] = this->heatpump_default_message_[76]; + this->command_message_[77] = this->heatpump_default_message_[77]; + this->command_message_[78] = this->heatpump_default_message_[78]; + this->command_message_[86] = this->heatpump_default_message_[86]; + this->command_message_[87] = this->heatpump_default_message_[87]; + this->command_message_[88] = this->heatpump_default_message_[88]; + this->command_message_[89] = this->heatpump_default_message_[89]; + } + // Set zone 2 curve bytes + if (index == 79 || index == 80 || index == 81 || index == 82 || index == 90 || index == 91 || index == 92 || + index == 93) { + this->command_message_[79] = this->heatpump_default_message_[79]; + this->command_message_[80] = this->heatpump_default_message_[80]; + this->command_message_[81] = this->heatpump_default_message_[81]; + this->command_message_[82] = this->heatpump_default_message_[82]; + this->command_message_[90] = this->heatpump_default_message_[90]; + this->command_message_[91] = this->heatpump_default_message_[91]; + this->command_message_[92] = this->heatpump_default_message_[92]; + this->command_message_[93] = this->heatpump_default_message_[93]; + } - this->send_extra_request_ = data[3] == 0x10 && data[199] > 0x02 && - this->send_extra_request_ == false ? true : false; + // set command byte + this->command_message_[index] = value; + // calculate and set set checksum (last element) + this->command_message_.back() = + PanasonicCommand::calcChecksum(this->command_message_, this->command_message_.size() - 1); - // Get response type and save the response - auto responseType = ResponseType::UNKNOWN; - if (data[3] == 0x10) - { - responseType = ResponseType::DEFAULT; - this->heatpump_default_message_ = data; - } - else if (data[3] == 0x21) - { - responseType = ResponseType::EXTRA; - this->heatpump_extra_message_ = data; - } - if (responseType == ResponseType::UNKNOWN) - { - ESP_LOGW(TAG, "Unknown response type (4. byte): 0x%02X. Expected 0x10 or 0x21.", data[3]); - delay(10); // NOLINT - return responseType; - } - - // Check if the current response is a new response - if (this->last_response_count_ == this->current_response_count_) return ResponseType::UNKNOWN; - this->last_response_count_ = this->current_response_count_; - - return responseType; - } - - void PanasonicHeatpumpComponent::set_command_high_nibble(const uint8_t value, const uint8_t index) - { - if (this->next_request_ != RequestType::COMMAND) - { - // initialize the command - this->command_message_.assign(std::begin(PanasonicCommand::CommandMessage), - std::end(PanasonicCommand::CommandMessage)); - } - uint8_t lowNibble = this->heatpump_default_message_[index] & 0b1111; - uint8_t highNibble = value << 4; - // set command byte - this->command_message_[index] = highNibble + lowNibble; - // calculate and set set checksum (last element) - this->command_message_.back() = PanasonicCommand::calcChecksum(this->command_message_, this->command_message_.size() - 1); - - // command will be send on next loop - this->next_request_ = RequestType::COMMAND; - } - - void PanasonicHeatpumpComponent::set_command_low_nibble(const uint8_t value, const uint8_t index) - { - if (this->next_request_ != RequestType::COMMAND) - { - // initialize the command - this->command_message_.assign(std::begin(PanasonicCommand::CommandMessage), - std::end(PanasonicCommand::CommandMessage)); - } - uint8_t highNibble = this->heatpump_default_message_[index] & 0b11110000; - uint8_t lowNibble = value & 0b1111; - // set command byte - this->command_message_[index] = highNibble + lowNibble; - // calculate and set set checksum (last element) - this->command_message_.back() = PanasonicCommand::calcChecksum(this->command_message_, this->command_message_.size() - 1); - - // command will be send on next loop - this->next_request_ = RequestType::COMMAND; - } - - void PanasonicHeatpumpComponent::set_command_byte(const uint8_t value, const uint8_t index) - { - if (this->next_request_ != RequestType::COMMAND) - { - // initialize the command - this->command_message_.assign(std::begin(PanasonicCommand::CommandMessage), - std::end(PanasonicCommand::CommandMessage)); - } - // set command byte - this->command_message_[index] = value; - // calculate and set set checksum (last element) - this->command_message_.back() = PanasonicCommand::calcChecksum(this->command_message_, this->command_message_.size() - 1); - - // command will be send on next loop - this->next_request_ = RequestType::COMMAND; - } - - void PanasonicHeatpumpComponent::set_command_curve(const uint8_t value, const uint8_t index) - { - if (this->next_request_ != RequestType::COMMAND) - { - // initialize the command - this->command_message_.assign(std::begin(PanasonicCommand::CommandMessage), - std::end(PanasonicCommand::CommandMessage)); - } - - // Set zone 1 curve bytes - if (index == 75 || index == 76 || index == 77 || index == 78 || - index == 86 || index == 87 || index == 88 || index == 89) - { - this->command_message_[75] = this->heatpump_default_message_[75]; - this->command_message_[76] = this->heatpump_default_message_[76]; - this->command_message_[77] = this->heatpump_default_message_[77]; - this->command_message_[78] = this->heatpump_default_message_[78]; - this->command_message_[86] = this->heatpump_default_message_[86]; - this->command_message_[87] = this->heatpump_default_message_[87]; - this->command_message_[88] = this->heatpump_default_message_[88]; - this->command_message_[89] = this->heatpump_default_message_[89]; - } - // Set zone 2 curve bytes - if (index == 79 || index == 80 || index == 81 || index == 82 || - index == 90 || index == 91 || index == 92 || index == 93) - { - this->command_message_[79] = this->heatpump_default_message_[79]; - this->command_message_[80] = this->heatpump_default_message_[80]; - this->command_message_[81] = this->heatpump_default_message_[81]; - this->command_message_[82] = this->heatpump_default_message_[82]; - this->command_message_[90] = this->heatpump_default_message_[90]; - this->command_message_[91] = this->heatpump_default_message_[91]; - this->command_message_[92] = this->heatpump_default_message_[92]; - this->command_message_[93] = this->heatpump_default_message_[93]; - } - - // set command byte - this->command_message_[index] = value; - // calculate and set set checksum (last element) - this->command_message_.back() = PanasonicCommand::calcChecksum(this->command_message_, this->command_message_.size() - 1); - - // command will be send on next loop - this->next_request_ = RequestType::COMMAND; - } - } // namespace panasonic_heatpump + // command will be send on next loop + this->next_request_ = RequestType::COMMAND; +} +} // namespace panasonic_heatpump } // namespace esphome