diff --git a/esphome/components/sun_gtil2/sun_gtil2.cpp b/esphome/components/sun_gtil2/sun_gtil2.cpp index 46b4902654..d416d9a636 100644 --- a/esphome/components/sun_gtil2/sun_gtil2.cpp +++ b/esphome/components/sun_gtil2/sun_gtil2.cpp @@ -47,14 +47,15 @@ void SunGTIL2::loop() { } } -std::string SunGTIL2::state_to_string_(uint8_t state) { +const char *SunGTIL2::state_to_string_(uint8_t state, std::span buffer) { switch (state) { case 0x02: return "Starting voltage too low"; case 0x07: return "Working"; default: - return str_sprintf("Unknown (0x%02x)", state); + snprintf(buffer.data(), buffer.size(), "Unknown (0x%02x)", state); + return buffer.data(); } } @@ -106,12 +107,11 @@ void SunGTIL2::handle_char_(uint8_t c) { #endif #ifdef USE_TEXT_SENSOR if (this->state_ != nullptr) { - this->state_->publish_state(this->state_to_string_(msg.state)); + char state_buffer[STATE_BUFFER_SIZE]; + this->state_->publish_state(this->state_to_string_(msg.state, state_buffer)); } if (this->serial_number_ != nullptr) { - std::string serial_number; - serial_number.assign(msg.serial_number, 10); - this->serial_number_->publish_state(serial_number); + this->serial_number_->publish_state(msg.serial_number, 10); } #endif } diff --git a/esphome/components/sun_gtil2/sun_gtil2.h b/esphome/components/sun_gtil2/sun_gtil2.h index 0c29ae695d..ebdd2abe5b 100644 --- a/esphome/components/sun_gtil2/sun_gtil2.h +++ b/esphome/components/sun_gtil2/sun_gtil2.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "esphome/core/component.h" #include "esphome/core/defines.h" @@ -34,8 +36,10 @@ class SunGTIL2 : public Component, public uart::UARTDevice { void set_serial_number(text_sensor::TextSensor *text_sensor) { serial_number_ = text_sensor; } #endif + static constexpr size_t STATE_BUFFER_SIZE = 16; + protected: - std::string state_to_string_(uint8_t state); + const char *state_to_string_(uint8_t state, std::span buffer); #ifdef USE_SENSOR sensor::Sensor *ac_voltage_{nullptr}; sensor::Sensor *dc_voltage_{nullptr}; diff --git a/esphome/components/text/text.cpp b/esphome/components/text/text.cpp index 3824c5004d..c2ade56f69 100644 --- a/esphome/components/text/text.cpp +++ b/esphome/components/text/text.cpp @@ -15,7 +15,10 @@ void Text::publish_state(const char *state) { this->publish_state(state, strlen( void Text::publish_state(const char *state, size_t len) { this->set_has_state(true); - this->state.assign(state, len); + // Only assign if changed to avoid heap allocation + if (len != this->state.size() || memcmp(state, this->state.data(), len) != 0) { + this->state.assign(state, len); + } if (this->traits.get_mode() == TEXT_MODE_PASSWORD) { ESP_LOGD(TAG, "'%s': Sending state " LOG_SECRET("'%s'"), this->get_name().c_str(), this->state.c_str()); } else { diff --git a/esphome/components/text_sensor/text_sensor.cpp b/esphome/components/text_sensor/text_sensor.cpp index 174a98054f..66301564a4 100644 --- a/esphome/components/text_sensor/text_sensor.cpp +++ b/esphome/components/text_sensor/text_sensor.cpp @@ -32,7 +32,10 @@ void TextSensor::publish_state(const char *state) { this->publish_state(state, s void TextSensor::publish_state(const char *state, size_t len) { if (this->filter_list_ == nullptr) { // No filters: raw_state == state, store once and use for both callbacks - this->state.assign(state, len); + // Only assign if changed to avoid heap allocation + if (len != this->state.size() || memcmp(state, this->state.data(), len) != 0) { + this->state.assign(state, len); + } this->raw_callback_.call(this->state); ESP_LOGV(TAG, "'%s': Received new state %s", this->name_.c_str(), this->state.c_str()); this->notify_frontend_(); @@ -40,7 +43,10 @@ void TextSensor::publish_state(const char *state, size_t len) { // Has filters: need separate raw storage #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" - this->raw_state.assign(state, len); + // Only assign if changed to avoid heap allocation + if (len != this->raw_state.size() || memcmp(state, this->raw_state.data(), len) != 0) { + this->raw_state.assign(state, len); + } this->raw_callback_.call(this->raw_state); ESP_LOGV(TAG, "'%s': Received new state %s", this->name_.c_str(), this->raw_state.c_str()); this->filter_list_->input(this->raw_state); @@ -101,7 +107,10 @@ void TextSensor::internal_send_state_to_frontend(const std::string &state) { } void TextSensor::internal_send_state_to_frontend(const char *state, size_t len) { - this->state.assign(state, len); + // Only assign if changed to avoid heap allocation + if (len != this->state.size() || memcmp(state, this->state.data(), len) != 0) { + this->state.assign(state, len); + } this->notify_frontend_(); }