mirror of
https://github.com/esphome/esphome.git
synced 2026-01-09 11:40:50 -07:00
[abbwelcome] Use stack-based formatting to eliminate heap allocations (#12799)
This commit is contained in:
@@ -51,7 +51,8 @@ void ABBWelcomeProtocol::encode(RemoteTransmitData *dst, const ABBWelcomeData &s
|
||||
dst->reserve(reserve_count);
|
||||
for (size_t i = 0; i < src.size(); i++)
|
||||
this->encode_byte_(dst, src[i]);
|
||||
ESP_LOGD(TAG, "Transmitting: %s", src.to_string().c_str());
|
||||
char buf[ABBWelcomeData::FORMAT_BUFFER_SIZE];
|
||||
ESP_LOGD(TAG, "Transmitting: %s", src.format_to(buf));
|
||||
}
|
||||
|
||||
bool ABBWelcomeProtocol::decode_byte_(RemoteReceiveData &src, bool &done, uint8_t &data) {
|
||||
@@ -94,7 +95,8 @@ optional<ABBWelcomeData> ABBWelcomeProtocol::decode(RemoteReceiveData src) {
|
||||
for (; (received_bytes < length) && !done; received_bytes++) {
|
||||
uint8_t data = 0;
|
||||
if (!this->decode_byte_(src, done, data)) {
|
||||
ESP_LOGW(TAG, "Received incomplete packet: %s", out.to_string(received_bytes).c_str());
|
||||
char buf[ABBWelcomeData::FORMAT_BUFFER_SIZE];
|
||||
ESP_LOGW(TAG, "Received incomplete packet: %s", out.format_to(buf, received_bytes));
|
||||
return {};
|
||||
}
|
||||
if (received_bytes == 2) {
|
||||
@@ -106,17 +108,19 @@ optional<ABBWelcomeData> ABBWelcomeProtocol::decode(RemoteReceiveData src) {
|
||||
ESP_LOGVV(TAG, "Received Byte: 0x%02X", data);
|
||||
out[received_bytes] = data;
|
||||
}
|
||||
char buf[ABBWelcomeData::FORMAT_BUFFER_SIZE];
|
||||
if (out.is_valid()) {
|
||||
ESP_LOGI(TAG, "Received: %s", out.to_string().c_str());
|
||||
ESP_LOGI(TAG, "Received: %s", out.format_to(buf));
|
||||
return out;
|
||||
}
|
||||
ESP_LOGW(TAG, "Received malformed packet: %s", out.to_string(received_bytes).c_str());
|
||||
ESP_LOGW(TAG, "Received malformed packet: %s", out.format_to(buf, received_bytes));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void ABBWelcomeProtocol::dump(const ABBWelcomeData &data) {
|
||||
ESP_LOGD(TAG, "Received ABBWelcome: %s", data.to_string().c_str());
|
||||
char buf[ABBWelcomeData::FORMAT_BUFFER_SIZE];
|
||||
ESP_LOGD(TAG, "Received ABBWelcome: %s", data.format_to(buf));
|
||||
}
|
||||
|
||||
} // namespace remote_base
|
||||
|
||||
@@ -136,22 +136,12 @@ class ABBWelcomeData {
|
||||
this->data_[1] = 0xff;
|
||||
this->data_[this->size() - 1] = this->calc_cs_();
|
||||
}
|
||||
std::string to_string(uint8_t max_print_bytes = 255) const {
|
||||
std::string info;
|
||||
if (this->is_valid()) {
|
||||
info = str_sprintf(this->get_three_byte_address() ? "[%06" PRIX32 " %s %06" PRIX32 "] Type: %02X"
|
||||
: "[%04" PRIX32 " %s %04" PRIX32 "] Type: %02X",
|
||||
this->get_source_address(), this->get_retransmission() ? "»" : ">",
|
||||
this->get_destination_address(), this->get_message_type());
|
||||
if (this->get_data_size())
|
||||
info += str_sprintf(", Data: %s", format_hex_pretty(this->get_data()).c_str());
|
||||
} else {
|
||||
info = "[Invalid]";
|
||||
}
|
||||
uint8_t print_bytes = std::min(this->size(), max_print_bytes);
|
||||
if (print_bytes)
|
||||
info = str_sprintf("%s %s", format_hex_pretty(this->data_.data(), print_bytes).c_str(), info.c_str());
|
||||
return info;
|
||||
// Buffer size: max raw hex output (27*3-1=80) + space(1) + type_info(27) + data(52) + null(1) = 161, rounded up
|
||||
static constexpr size_t FORMAT_BUFFER_SIZE = 192;
|
||||
|
||||
template<size_t N> char *format_to(char (&buffer)[N], uint8_t max_print_bytes = 255) const {
|
||||
static_assert(N >= FORMAT_BUFFER_SIZE, "Buffer too small for format_to()");
|
||||
return this->format_to_internal_(buffer, max_print_bytes);
|
||||
}
|
||||
bool operator==(const ABBWelcomeData &rhs) const {
|
||||
if (std::equal(this->data_.begin(), this->data_.begin() + this->size(), rhs.data_.begin()))
|
||||
@@ -168,6 +158,36 @@ class ABBWelcomeData {
|
||||
std::array<uint8_t, 12 + MAX_DATA_LENGTH> data_;
|
||||
// Calculate checksum
|
||||
uint8_t calc_cs_() const;
|
||||
// Internal format implementation - buffer guaranteed >= FORMAT_BUFFER_SIZE by caller
|
||||
char *format_to_internal_(char *buffer, uint8_t max_print_bytes) const {
|
||||
char *ptr = buffer;
|
||||
char *end = buffer + FORMAT_BUFFER_SIZE;
|
||||
|
||||
uint8_t print_bytes = std::min(this->size(), max_print_bytes);
|
||||
if (print_bytes) {
|
||||
char raw_hex[format_hex_pretty_size(12 + MAX_DATA_LENGTH)];
|
||||
format_hex_pretty_to(raw_hex, this->data_.data(), print_bytes, '.');
|
||||
ptr += snprintf(ptr, end - ptr, "%s ", raw_hex);
|
||||
}
|
||||
|
||||
if (this->is_valid()) {
|
||||
ptr += snprintf(ptr, end - ptr,
|
||||
this->get_three_byte_address() ? "[%06" PRIX32 " %s %06" PRIX32 "] Type: %02X"
|
||||
: "[%04" PRIX32 " %s %04" PRIX32 "] Type: %02X",
|
||||
this->get_source_address(), this->get_retransmission() ? "»" : ">",
|
||||
this->get_destination_address(), this->get_message_type());
|
||||
if (this->get_data_size()) {
|
||||
char data_hex[format_hex_pretty_size(MAX_DATA_LENGTH)];
|
||||
format_hex_pretty_to(data_hex, this->data_.data() + 5 + 2 * this->get_address_length(), this->get_data_size(),
|
||||
'.');
|
||||
snprintf(ptr, end - ptr, ", Data: %s", data_hex);
|
||||
}
|
||||
} else {
|
||||
snprintf(ptr, end - ptr, "[Invalid]");
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
|
||||
class ABBWelcomeProtocol : public RemoteProtocol<ABBWelcomeData> {
|
||||
|
||||
Reference in New Issue
Block a user