Move log_uart_hex() to helper class.

Use state machine to lower loop time.
This commit is contained in:
ElVit 2025-05-22 22:34:21 +02:00
parent d3e9139df3
commit e9d1180cc8
4 changed files with 182 additions and 80 deletions

View File

@ -0,0 +1,51 @@
#include "helpers.h"
namespace esphome
{
namespace panasonic_heatpump
{
static const char *const TAG = "panasonic_heatpump";
void PanasonicHelpers::log_uart_hex(UartLogDirection direction, const std::vector<uint8_t>& data, const char separator)
{
PanasonicHelpers::log_uart_hex(direction, &data[0], data.size(), separator);
}
void PanasonicHelpers::log_uart_hex(UartLogDirection direction, const uint8_t* data, const size_t length, const char separator)
{
std::string logStr = "";
std::string msgDir = direction == UART_LOG_TX ? ">>>" : "<<<";
std::string msgType = direction == UART_LOG_TX ? "request" : "response";
switch(data[0])
{
case 0x31:
msgType = "initial_" + msgType;
break;
case 0x71:
msgType = "polling_" + msgType;
break;
case 0xF1:
msgType = "command_" + msgType;
break;
};
ESP_LOGI(TAG, "%s %s[%i]", msgDir.c_str(), msgType.c_str(), length);
delay(10);
char buffer[5];
for (size_t i = 0; i < length; i++)
{
if (i > 0) logStr += separator;
sprintf(buffer, "%02X", data[i]);
logStr += buffer;
}
for (size_t i = 0; i < logStr.length(); i += UART_LOG_CHUNK_SIZE)
{
ESP_LOGI(TAG, "%s %s", msgDir.c_str(), logStr.substr(i, UART_LOG_CHUNK_SIZE).c_str());
delay(10);
}
}
} // namespace panasonic_heatpump
} // namespace esphome

View File

@ -0,0 +1,28 @@
#pragma once
#include "esphome/core/hal.h"
#include "esphome/core/log.h"
#include <vector>
#include <string>
#define UART_LOG_CHUNK_SIZE 153
namespace esphome
{
namespace panasonic_heatpump
{
enum UartLogDirection
{
UART_LOG_RX,
UART_LOG_TX,
};
class PanasonicHelpers
{
public:
static void log_uart_hex(UartLogDirection direction, const std::vector<uint8_t>& data, const char separator);
static void log_uart_hex(UartLogDirection direction, const uint8_t* data, const size_t length, const char separator);
};
}
}

View File

@ -38,13 +38,63 @@ namespace esphome
void PanasonicHeatpumpComponent::loop()
{
this->read_response();
this->send_request();
this->read_request();
// Next request will be polling
this->next_request_ = 1;
this->trigger_request_ = false;
if (loop_state_ == 0)
{
this->read_response();
this->loop_state_ = 1;
}
else if (loop_state_ == 1)
{
bool result = this->check_response(this->heatpump_message_);
this->loop_state_ = result ? 2 : 8;
}
else if (loop_state_ == 2)
{
this->publish_sensor(this->heatpump_message_);
this->loop_state_ = 3;
}
else if (loop_state_ == 3)
{
this->publish_binary_sensor(this->heatpump_message_);
this->loop_state_ = 4;
}
else if (loop_state_ == 4)
{
this->publish_text_sensor(this->heatpump_message_);
this->loop_state_ = 5;
}
else if (loop_state_ == 5)
{
this->publish_number(this->heatpump_message_);
this->loop_state_ = 6;
}
else if (loop_state_ == 6)
{
this->publish_select(this->heatpump_message_);
this->loop_state_ = 7;
}
else if (loop_state_ == 7)
{
this->publish_switch(this->heatpump_message_);
this->loop_state_ = 8;
}
else if (loop_state_ == 8)
{
this->send_request();
this->loop_state_ = 9;
}
else if (loop_state_ == 9)
{
this->read_request();
this->loop_state_ = 10;
}
else
{
// Next request will be polling
this->next_request_ = 1;
this->trigger_request_ = false;
this->loop_state_ = 0;
}
}
void PanasonicHeatpumpComponent::read_response()
@ -89,10 +139,10 @@ namespace esphome
if (this->response_message_.size() > 2 &&
this->response_message_.size() == this->response_payload_length_ + 3)
{
this->temp_message_ = this->response_message_;
this->heatpump_message_ = this->response_message_;
this->response_receiving_ = false;
this->log_uart_hex(UART_LOG_RX, this->response_message_, ',');
this->decode_response(this->response_message_);;
this->current_response_count_++;
if (this->log_uart_msg_) PanasonicHelpers::log_uart_hex(UART_LOG_RX, this->response_message_, ',');
}
}
}
@ -103,7 +153,7 @@ namespace esphome
if (this->next_request_ == 2) // command
{
this->log_uart_hex(UART_LOG_TX, this->command_message_, ',');
if (this->log_uart_msg_) PanasonicHelpers::log_uart_hex(UART_LOG_TX, this->command_message_, ',');
this->write_array(this->command_message_);
this->flush();
return;
@ -114,13 +164,13 @@ namespace esphome
if (this->next_request_ == 0) // initial
{
// Probably not necessary but CZ-TAW1 sends this query on boot
this->log_uart_hex(UART_LOG_TX, PanasonicCommand::InitialRequest, INIT_REQUEST_SIZE, ',');
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();
}
else if (this->next_request_ == 1) // polling
{
this->log_uart_hex(UART_LOG_TX, PanasonicCommand::PollingMessage, DATA_MESSAGE_SIZE, ',');
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();
}
@ -168,73 +218,32 @@ namespace esphome
this->request_message_.size() == this->request_payload_length_ + 3)
{
this->request_receiving_ = false;
this->log_uart_hex(UART_LOG_TX, this->request_message_, ',');
if (this->log_uart_msg_) PanasonicHelpers::log_uart_hex(UART_LOG_TX, this->request_message_, ',');
}
}
}
int PanasonicHeatpumpComponent::getResponseByte(const int index)
{
if (this->heatpump_message_.size() > index) return this->heatpump_message_[index];
if (this->response_message_.size() > index) return this->response_message_[index];
if (this->temp_message_.size() > index) return this->temp_message_[index];
return -1;
}
void PanasonicHeatpumpComponent::log_uart_hex(UartLogDirection direction, const std::vector<uint8_t>& data, const char separator)
{
this->log_uart_hex(direction, &data[0], data.size(), separator);
}
void PanasonicHeatpumpComponent::log_uart_hex(UartLogDirection direction, const uint8_t* data, const size_t length, const char separator)
{
if (this->log_uart_msg_ == false) return;
std::string logStr = "";
std::string msgDir = direction == UART_LOG_TX ? ">>>" : "<<<";
std::string msgType = direction == UART_LOG_TX ? "request" : "response";
switch(data[0])
{
case 0x31:
msgType = "initial_" + msgType;
break;
case 0x71:
msgType = "polling_" + msgType;
break;
case 0xF1:
msgType = "command_" + msgType;
break;
};
ESP_LOGI(TAG, "%s %s[%i]", msgDir.c_str(), msgType.c_str(), length);
delay(10);
char buffer[5];
for (size_t i = 0; i < length; i++)
{
if (i > 0) logStr += separator;
sprintf(buffer, "%02X", data[i]);
logStr += buffer;
}
for (size_t i = 0; i < logStr.length(); i += UART_LOG_CHUNK_SIZE)
{
ESP_LOGI(TAG, "%s %s", msgDir.c_str(), logStr.substr(i, UART_LOG_CHUNK_SIZE).c_str());
delay(10);
}
}
void PanasonicHeatpumpComponent::decode_response(const std::vector<uint8_t>& data)
bool PanasonicHeatpumpComponent::check_response(const std::vector<uint8_t>& data)
{
// Read response message:
// format: 0x71 [payload_length] 0x01 0x10 [[TOP0 - TOP114] ...] 0x00 [checksum]
// payload_length: payload_length + 3 = packet_length
// checksum: if (sum(all bytes) & 0xFF == 0) ==> valid packet
if (data[0] != 0x71) return;
if (data.empty()) return false;
if (data[0] != 0x71) return false;
if (data.size() != RESPONSE_MSG_SIZE)
{
ESP_LOGW(TAG, "Invalid response message length: recieved %d - expected %d", data.size(), RESPONSE_MSG_SIZE);
delay(10);
return;
return false;
}
uint8_t checksum = 0;
@ -247,15 +256,12 @@ namespace esphome
{
ESP_LOGW(TAG, "Invalid response message: checksum = 0x%02X, last_byte = 0x%02X", checksum, data[202]);
delay(10);
return;
return false;
}
this->publish_sensor(data);
this->publish_binary_sensor(data);
this->publish_text_sensor(data);
this->publish_number(data);
this->publish_select(data);
this->publish_switch(data);
if (this->last_response_count_ == this->current_response_count_) return false;
this->last_response_count_ = this->current_response_count_;
return true;
}
void PanasonicHeatpumpComponent::set_command_byte(const uint8_t value, const uint8_t index)
@ -453,6 +459,30 @@ namespace esphome
if (this->top125_text_sensor_) this->top125_text_sensor_->publish_state(PanasonicDecode::getTextState(PanasonicDecode::Valve2, PanasonicDecode::getBit5and6(data[116])));
if (this->top126_text_sensor_) this->top126_text_sensor_->publish_state(PanasonicDecode::getTextState(PanasonicDecode::Valve, PanasonicDecode::getBit7and8(data[116])));
if (this->top130_text_sensor_) this->top130_text_sensor_->publish_state(PanasonicDecode::getTextState(PanasonicDecode::Bivalent, PanasonicDecode::getBit5and6(data[26])));
// ToDo: Check if state of text_sensor has changed. If yes change min/max values of number entities
// if (this->top76_text_sensor_->get_state() == "Direct")
// this->set5_number_->traits.set_max_value(20);
// this->set5_number_->traits.set_max_value(0);
// this->set6_number_->traits.set_max_value(20);
// this->set6_number_->traits.set_max_value(0);
// else
// this->set5_number_->traits.set_max_value(5);
// this->set5_number_->traits.set_max_value(-5);
// this->set6_number_->traits.set_max_value(5);
// this->set6_number_->traits.set_max_value(-5);
// if (this->top81_text_sensor_->get_state() == "Direct")
// this->set7_number_->traits.set_max_value(20);
// this->set7_number_->traits.set_max_value(0);
// this->set8_number_->traits.set_max_value(20);
// this->set8_number_->traits.set_max_value(0);
// else
// this->set7_number_->traits.set_max_value(5);
// this->set7_number_->traits.set_max_value(-5);
// this->set8_number_->traits.set_max_value(5);
// this->set8_number_->traits.set_max_value(-5);
#endif
}

View File

@ -24,23 +24,16 @@
#endif
#include "decode.h"
#include "commands.h"
#include "helpers.h"
#include <vector>
#include <tuple>
#include <string>
#define UART_LOG_CHUNK_SIZE 153
namespace esphome
{
namespace panasonic_heatpump
{
enum UartLogDirection
{
UART_LOG_RX,
UART_LOG_TX,
};
class PanasonicHeatpumpComponent : public PollingComponent, public uart::UARTDevice
{
public:
@ -274,23 +267,26 @@ namespace esphome
uart::UARTComponent* uart_client_ { nullptr };
bool log_uart_msg_ { false };
// uart message variables
std::vector<uint8_t> temp_message_;
std::vector<uint8_t> heatpump_message_;
std::vector<uint8_t> response_message_;
std::vector<uint8_t> request_message_;
std::vector<uint8_t> command_message_;
uint8_t response_payload_length_;
uint8_t request_payload_length_;
uint8_t byte_;
uint8_t current_response_count_ { 0 };
uint8_t last_response_count_ { 0 };
bool response_receiving_ { false };
bool request_receiving_ { false };
bool trigger_request_ { false };
uint8_t next_request_ { 0 }; // 0 = initial, 1 = polling, 2 = command
uint8_t loop_state_ { 0 };
// uart message functions
void read_response();
void send_request();
void read_request();
void decode_response(const std::vector<uint8_t>& data);
bool check_response(const std::vector<uint8_t>& data);
void set_command_byte(const uint8_t value, const uint8_t index);
void set_command_bytes(const std::vector<std::tuple<uint8_t, uint8_t>>& data);
// sensor and control publish functions
@ -300,9 +296,6 @@ namespace esphome
void publish_number(const std::vector<uint8_t>& data);
void publish_select(const std::vector<uint8_t>& data);
void publish_switch(const std::vector<uint8_t>& data);
// helper functions
void log_uart_hex(UartLogDirection direction, const std::vector<uint8_t>& data, const char separator);
void log_uart_hex(UartLogDirection direction, const uint8_t* data, const size_t length, const char separator);
};
} // namespace panasonic_heatpump
} // namespace esphome