mirror of
https://github.com/esphome/esphome.git
synced 2026-01-10 12:10:48 -07:00
[text_sensor][text] Add const char* overloads to publish_state to eliminate heap churn
This commit is contained in:
@@ -2,22 +2,26 @@
|
|||||||
#include "esphome/core/defines.h"
|
#include "esphome/core/defines.h"
|
||||||
#include "esphome/core/controller_registry.h"
|
#include "esphome/core/controller_registry.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace text {
|
namespace text {
|
||||||
|
|
||||||
static const char *const TAG = "text";
|
static const char *const TAG = "text";
|
||||||
|
|
||||||
void Text::publish_state(const std::string &state) {
|
void Text::publish_state(const std::string &state) { this->publish_state(state.data(), state.size()); }
|
||||||
this->set_has_state(true);
|
|
||||||
this->state = state;
|
|
||||||
if (this->traits.get_mode() == TEXT_MODE_PASSWORD) {
|
|
||||||
ESP_LOGD(TAG, "'%s': Sending state " LOG_SECRET("'%s'"), this->get_name().c_str(), state.c_str());
|
|
||||||
|
|
||||||
|
void Text::publish_state(const char *state) { this->publish_state(state, strlen(state)); }
|
||||||
|
|
||||||
|
void Text::publish_state(const char *state, size_t len) {
|
||||||
|
this->set_has_state(true);
|
||||||
|
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 {
|
} else {
|
||||||
ESP_LOGD(TAG, "'%s': Sending state %s", this->get_name().c_str(), state.c_str());
|
ESP_LOGD(TAG, "'%s': Sending state %s", this->get_name().c_str(), this->state.c_str());
|
||||||
}
|
}
|
||||||
this->state_callback_.call(state);
|
this->state_callback_.call(this->state);
|
||||||
#if defined(USE_TEXT) && defined(USE_CONTROLLER_REGISTRY)
|
#if defined(USE_TEXT) && defined(USE_CONTROLLER_REGISTRY)
|
||||||
ControllerRegistry::notify_text_update(this);
|
ControllerRegistry::notify_text_update(this);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ class Text : public EntityBase {
|
|||||||
TextTraits traits;
|
TextTraits traits;
|
||||||
|
|
||||||
void publish_state(const std::string &state);
|
void publish_state(const std::string &state);
|
||||||
|
void publish_state(const char *state);
|
||||||
|
void publish_state(const char *state, size_t len);
|
||||||
|
|
||||||
/// Instantiate a TextCall object to modify this text component's state.
|
/// Instantiate a TextCall object to modify this text component's state.
|
||||||
TextCall make_call() { return TextCall(this); }
|
TextCall make_call() { return TextCall(this); }
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "esphome/core/defines.h"
|
#include "esphome/core/defines.h"
|
||||||
#include "esphome/core/controller_registry.h"
|
#include "esphome/core/controller_registry.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace text_sensor {
|
namespace text_sensor {
|
||||||
@@ -24,20 +25,26 @@ void log_text_sensor(const char *tag, const char *prefix, const char *type, Text
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextSensor::publish_state(const std::string &state) {
|
void TextSensor::publish_state(const std::string &state) { this->publish_state(state.data(), state.size()); }
|
||||||
// Suppress deprecation warning - we need to populate raw_state for backwards compatibility
|
|
||||||
|
void TextSensor::publish_state(const char *state) { this->publish_state(state, strlen(state)); }
|
||||||
|
|
||||||
|
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);
|
||||||
|
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_();
|
||||||
|
} else {
|
||||||
|
// Has filters: need separate raw storage
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||||
this->raw_state = state;
|
this->raw_state.assign(state, len);
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
this->raw_callback_.call(state);
|
this->raw_callback_.call(this->raw_state);
|
||||||
|
ESP_LOGV(TAG, "'%s': Received new state %s", this->name_.c_str(), this->raw_state.c_str());
|
||||||
ESP_LOGV(TAG, "'%s': Received new state %s", this->name_.c_str(), state.c_str());
|
this->filter_list_->input(this->raw_state);
|
||||||
|
|
||||||
if (this->filter_list_ == nullptr) {
|
|
||||||
this->internal_send_state_to_frontend(state);
|
|
||||||
} else {
|
|
||||||
this->filter_list_->input(state);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,6 +87,9 @@ void TextSensor::add_on_raw_state_callback(std::function<void(const std::string
|
|||||||
|
|
||||||
const std::string &TextSensor::get_state() const { return this->state; }
|
const std::string &TextSensor::get_state() const { return this->state; }
|
||||||
const std::string &TextSensor::get_raw_state() const {
|
const std::string &TextSensor::get_raw_state() const {
|
||||||
|
if (this->filter_list_ == nullptr) {
|
||||||
|
return this->state; // No filters, raw == filtered
|
||||||
|
}
|
||||||
// Suppress deprecation warning - get_raw_state() is the replacement API
|
// Suppress deprecation warning - get_raw_state() is the replacement API
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||||
@@ -87,10 +97,18 @@ const std::string &TextSensor::get_raw_state() const {
|
|||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
}
|
}
|
||||||
void TextSensor::internal_send_state_to_frontend(const std::string &state) {
|
void TextSensor::internal_send_state_to_frontend(const std::string &state) {
|
||||||
this->state = state;
|
this->internal_send_state_to_frontend(state.data(), state.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextSensor::internal_send_state_to_frontend(const char *state, size_t len) {
|
||||||
|
this->state.assign(state, len);
|
||||||
|
this->notify_frontend_();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextSensor::notify_frontend_() {
|
||||||
this->set_has_state(true);
|
this->set_has_state(true);
|
||||||
ESP_LOGD(TAG, "'%s': Sending state '%s'", this->name_.c_str(), state.c_str());
|
ESP_LOGD(TAG, "'%s': Sending state '%s'", this->name_.c_str(), this->state.c_str());
|
||||||
this->callback_.call(state);
|
this->callback_.call(this->state);
|
||||||
#if defined(USE_TEXT_SENSOR) && defined(USE_CONTROLLER_REGISTRY)
|
#if defined(USE_TEXT_SENSOR) && defined(USE_CONTROLLER_REGISTRY)
|
||||||
ControllerRegistry::notify_text_sensor_update(this);
|
ControllerRegistry::notify_text_sensor_update(this);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ class TextSensor : public EntityBase, public EntityBase_DeviceClass {
|
|||||||
const std::string &get_raw_state() const;
|
const std::string &get_raw_state() const;
|
||||||
|
|
||||||
void publish_state(const std::string &state);
|
void publish_state(const std::string &state);
|
||||||
|
void publish_state(const char *state);
|
||||||
|
void publish_state(const char *state, size_t len);
|
||||||
|
|
||||||
/// Add a filter to the filter chain. Will be appended to the back.
|
/// Add a filter to the filter chain. Will be appended to the back.
|
||||||
void add_filter(Filter *filter);
|
void add_filter(Filter *filter);
|
||||||
@@ -63,8 +65,11 @@ class TextSensor : public EntityBase, public EntityBase_DeviceClass {
|
|||||||
// (In most use cases you won't need these)
|
// (In most use cases you won't need these)
|
||||||
|
|
||||||
void internal_send_state_to_frontend(const std::string &state);
|
void internal_send_state_to_frontend(const std::string &state);
|
||||||
|
void internal_send_state_to_frontend(const char *state, size_t len);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/// Notify frontend that state has changed (assumes this->state is already set)
|
||||||
|
void notify_frontend_();
|
||||||
LazyCallbackManager<void(const std::string &)> raw_callback_; ///< Storage for raw state callbacks.
|
LazyCallbackManager<void(const std::string &)> raw_callback_; ///< Storage for raw state callbacks.
|
||||||
LazyCallbackManager<void(const std::string &)> callback_; ///< Storage for filtered state callbacks.
|
LazyCallbackManager<void(const std::string &)> callback_; ///< Storage for filtered state callbacks.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user