Compare commits

...

1 Commits

Author SHA1 Message Date
J. Nick Koston
36b5f0aaf0 [api] Eliminate heap allocations in Home Assistant state callbacks 2025-12-30 10:17:17 -10:00
14 changed files with 173 additions and 130 deletions

View File

@@ -1711,9 +1711,8 @@ void APIConnection::on_home_assistant_state_response(const HomeAssistantStateRes
continue; continue;
} }
// Create temporary string for callback (callback takes const std::string &) // Create StringRef directly from message data (zero allocation)
// Handle empty state (nullptr with len=0) StringRef state(reinterpret_cast<const char *>(msg.state), msg.state_len);
std::string state(msg.state_len > 0 ? reinterpret_cast<const char *>(msg.state) : "", msg.state_len);
it.callback(state); it.callback(state);
} }
} }

View File

@@ -423,18 +423,18 @@ void APIServer::handle_action_response(uint32_t call_id, bool success, const std
#endif // USE_API_HOMEASSISTANT_SERVICES #endif // USE_API_HOMEASSISTANT_SERVICES
#ifdef USE_API_HOMEASSISTANT_STATES #ifdef USE_API_HOMEASSISTANT_STATES
// Helper to add subscription (reduces duplication) // Helper to add subscription (reduces duplication) - const char* version (zero allocation)
void APIServer::add_state_subscription_(const char *entity_id, const char *attribute, void APIServer::add_state_subscription_(const char *entity_id, const char *attribute, std::function<void(StringRef)> f,
std::function<void(std::string)> f, bool once) { bool once) {
this->state_subs_.push_back(HomeAssistantStateSubscription{ this->state_subs_.push_back(HomeAssistantStateSubscription{
.entity_id = entity_id, .attribute = attribute, .callback = std::move(f), .once = once, .entity_id = entity_id, .attribute = attribute, .callback = std::move(f), .once = once,
// entity_id_dynamic_storage and attribute_dynamic_storage remain nullptr (no heap allocation) // entity_id_dynamic_storage and attribute_dynamic_storage remain nullptr (no heap allocation)
}); });
} }
// Helper to add subscription with heap-allocated strings (reduces duplication) // Helper to add subscription with heap-allocated strings and StringRef callback
void APIServer::add_state_subscription_(std::string entity_id, optional<std::string> attribute, void APIServer::add_state_subscription_(std::string entity_id, optional<std::string> attribute,
std::function<void(std::string)> f, bool once) { std::function<void(StringRef)> f, bool once) {
HomeAssistantStateSubscription sub; HomeAssistantStateSubscription sub;
// Allocate heap storage for the strings // Allocate heap storage for the strings
sub.entity_id_dynamic_storage = std::make_unique<std::string>(std::move(entity_id)); sub.entity_id_dynamic_storage = std::make_unique<std::string>(std::move(entity_id));
@@ -452,25 +452,45 @@ void APIServer::add_state_subscription_(std::string entity_id, optional<std::str
this->state_subs_.push_back(std::move(sub)); this->state_subs_.push_back(std::move(sub));
} }
// Legacy helper: wraps std::string callback and delegates to StringRef version
void APIServer::add_state_subscription_(std::string entity_id, optional<std::string> attribute,
std::function<void(const std::string &)> f, bool once) {
// Wrap callback to convert StringRef -> std::string, then delegate
this->add_state_subscription_(std::move(entity_id), std::move(attribute),
std::function<void(StringRef)>([f = std::move(f)](StringRef state) { f(state.str()); }),
once);
}
// New const char* overload (for internal components - zero allocation) // New const char* overload (for internal components - zero allocation)
void APIServer::subscribe_home_assistant_state(const char *entity_id, const char *attribute, void APIServer::subscribe_home_assistant_state(const char *entity_id, const char *attribute,
std::function<void(std::string)> f) { std::function<void(StringRef)> f) {
this->add_state_subscription_(entity_id, attribute, std::move(f), false); this->add_state_subscription_(entity_id, attribute, std::move(f), false);
} }
void APIServer::get_home_assistant_state(const char *entity_id, const char *attribute, void APIServer::get_home_assistant_state(const char *entity_id, const char *attribute,
std::function<void(std::string)> f) { std::function<void(StringRef)> f) {
this->add_state_subscription_(entity_id, attribute, std::move(f), true); this->add_state_subscription_(entity_id, attribute, std::move(f), true);
} }
// Existing std::string overload (for custom_api_device.h - heap allocation) // std::string overload with StringRef callback (zero-allocation callback)
void APIServer::subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute, void APIServer::subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute,
std::function<void(std::string)> f) { std::function<void(StringRef)> f) {
this->add_state_subscription_(std::move(entity_id), std::move(attribute), std::move(f), false); this->add_state_subscription_(std::move(entity_id), std::move(attribute), std::move(f), false);
} }
void APIServer::get_home_assistant_state(std::string entity_id, optional<std::string> attribute, void APIServer::get_home_assistant_state(std::string entity_id, optional<std::string> attribute,
std::function<void(std::string)> f) { std::function<void(StringRef)> f) {
this->add_state_subscription_(std::move(entity_id), std::move(attribute), std::move(f), true);
}
// Legacy std::string overload (for custom_api_device.h - converts StringRef to std::string)
void APIServer::subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute,
std::function<void(const std::string &)> f) {
this->add_state_subscription_(std::move(entity_id), std::move(attribute), std::move(f), false);
}
void APIServer::get_home_assistant_state(std::string entity_id, optional<std::string> attribute,
std::function<void(const std::string &)> f) {
this->add_state_subscription_(std::move(entity_id), std::move(attribute), std::move(f), true); this->add_state_subscription_(std::move(entity_id), std::move(attribute), std::move(f), true);
} }

View File

@@ -195,7 +195,7 @@ class APIServer : public Component,
struct HomeAssistantStateSubscription { struct HomeAssistantStateSubscription {
const char *entity_id; // Pointer to flash (internal) or heap (external) const char *entity_id; // Pointer to flash (internal) or heap (external)
const char *attribute; // Pointer to flash or nullptr (nullptr means no attribute) const char *attribute; // Pointer to flash or nullptr (nullptr means no attribute)
std::function<void(std::string)> callback; std::function<void(StringRef)> callback;
bool once; bool once;
// Dynamic storage for external components using std::string API (custom_api_device.h) // Dynamic storage for external components using std::string API (custom_api_device.h)
@@ -205,14 +205,20 @@ class APIServer : public Component,
}; };
// New const char* overload (for internal components - zero allocation) // New const char* overload (for internal components - zero allocation)
void subscribe_home_assistant_state(const char *entity_id, const char *attribute, std::function<void(std::string)> f); void subscribe_home_assistant_state(const char *entity_id, const char *attribute, std::function<void(StringRef)> f);
void get_home_assistant_state(const char *entity_id, const char *attribute, std::function<void(std::string)> f); void get_home_assistant_state(const char *entity_id, const char *attribute, std::function<void(StringRef)> f);
// Existing std::string overload (for custom_api_device.h - heap allocation) // std::string overload with StringRef callback (for custom_api_device.h with zero-allocation callback)
void subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute, void subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute,
std::function<void(std::string)> f); std::function<void(StringRef)> f);
void get_home_assistant_state(std::string entity_id, optional<std::string> attribute, void get_home_assistant_state(std::string entity_id, optional<std::string> attribute,
std::function<void(std::string)> f); std::function<void(StringRef)> f);
// Legacy std::string overload (for custom_api_device.h - converts StringRef to std::string for callback)
void subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute,
std::function<void(const std::string &)> f);
void get_home_assistant_state(std::string entity_id, optional<std::string> attribute,
std::function<void(const std::string &)> f);
const std::vector<HomeAssistantStateSubscription> &get_state_subs() const; const std::vector<HomeAssistantStateSubscription> &get_state_subs() const;
#endif #endif
@@ -236,10 +242,12 @@ class APIServer : public Component,
#endif // USE_API_NOISE #endif // USE_API_NOISE
#ifdef USE_API_HOMEASSISTANT_STATES #ifdef USE_API_HOMEASSISTANT_STATES
// Helper methods to reduce code duplication // Helper methods to reduce code duplication
void add_state_subscription_(const char *entity_id, const char *attribute, std::function<void(std::string)> f, void add_state_subscription_(const char *entity_id, const char *attribute, std::function<void(StringRef)> f,
bool once);
void add_state_subscription_(std::string entity_id, optional<std::string> attribute, std::function<void(StringRef)> f,
bool once); bool once);
void add_state_subscription_(std::string entity_id, optional<std::string> attribute, void add_state_subscription_(std::string entity_id, optional<std::string> attribute,
std::function<void(std::string)> f, bool once); std::function<void(const std::string &)> f, bool once);
#endif // USE_API_HOMEASSISTANT_STATES #endif // USE_API_HOMEASSISTANT_STATES
// Pointers and pointer-like types first (4 bytes each) // Pointers and pointer-like types first (4 bytes each)
std::unique_ptr<socket::Socket> socket_ = nullptr; std::unique_ptr<socket::Socket> socket_ = nullptr;

View File

@@ -122,17 +122,29 @@ class CustomAPIDevice {
* subscribe_homeassistant_state(&CustomNativeAPI::on_state_changed, "climate.kitchen", "current_temperature"); * subscribe_homeassistant_state(&CustomNativeAPI::on_state_changed, "climate.kitchen", "current_temperature");
* } * }
* *
* void on_state_changed(std::string state) { * void on_state_changed(StringRef state) {
* // State of sensor.weather_forecast is `state` * // State of climate.kitchen current_temperature is `state`
* // Use state.c_str() for C string, state.str() for std::string
* } * }
* ``` * ```
* *
* @tparam T The class type creating the service, automatically deduced from the function pointer. * @tparam T The class type creating the service, automatically deduced from the function pointer.
* @param callback The member function to call when the entity state changes. * @param callback The member function to call when the entity state changes (zero-allocation).
* @param entity_id The entity_id to track. * @param entity_id The entity_id to track.
* @param attribute The entity state attribute to track. * @param attribute The entity state attribute to track.
*/ */
template<typename T> template<typename T>
void subscribe_homeassistant_state(void (T::*callback)(StringRef), const std::string &entity_id,
const std::string &attribute = "") {
auto f = std::bind(callback, (T *) this, std::placeholders::_1);
global_api_server->subscribe_home_assistant_state(entity_id, optional<std::string>(attribute), std::move(f));
}
/** Subscribe to the state (or attribute state) of an entity from Home Assistant (legacy std::string version).
*
* @deprecated Use the StringRef overload for zero-allocation callbacks.
*/
template<typename T>
void subscribe_homeassistant_state(void (T::*callback)(std::string), const std::string &entity_id, void subscribe_homeassistant_state(void (T::*callback)(std::string), const std::string &entity_id,
const std::string &attribute = "") { const std::string &attribute = "") {
auto f = std::bind(callback, (T *) this, std::placeholders::_1); auto f = std::bind(callback, (T *) this, std::placeholders::_1);
@@ -148,23 +160,42 @@ class CustomAPIDevice {
* subscribe_homeassistant_state(&CustomNativeAPI::on_state_changed, "sensor.weather_forecast"); * subscribe_homeassistant_state(&CustomNativeAPI::on_state_changed, "sensor.weather_forecast");
* } * }
* *
* void on_state_changed(std::string entity_id, std::string state) { * void on_state_changed(const std::string &entity_id, StringRef state) {
* // State of `entity_id` is `state` * // State of `entity_id` is `state`
* } * }
* ``` * ```
* *
* @tparam T The class type creating the service, automatically deduced from the function pointer. * @tparam T The class type creating the service, automatically deduced from the function pointer.
* @param callback The member function to call when the entity state changes. * @param callback The member function to call when the entity state changes (zero-allocation for state).
* @param entity_id The entity_id to track. * @param entity_id The entity_id to track.
* @param attribute The entity state attribute to track. * @param attribute The entity state attribute to track.
*/ */
template<typename T> template<typename T>
void subscribe_homeassistant_state(void (T::*callback)(const std::string &, StringRef), const std::string &entity_id,
const std::string &attribute = "") {
auto f = std::bind(callback, (T *) this, entity_id, std::placeholders::_1);
global_api_server->subscribe_home_assistant_state(entity_id, optional<std::string>(attribute), std::move(f));
}
/** Subscribe to the state (or attribute state) of an entity from Home Assistant (legacy std::string version).
*
* @deprecated Use the StringRef overload for zero-allocation callbacks.
*/
template<typename T>
void subscribe_homeassistant_state(void (T::*callback)(std::string, std::string), const std::string &entity_id, void subscribe_homeassistant_state(void (T::*callback)(std::string, std::string), const std::string &entity_id,
const std::string &attribute = "") { const std::string &attribute = "") {
auto f = std::bind(callback, (T *) this, entity_id, std::placeholders::_1); auto f = std::bind(callback, (T *) this, entity_id, std::placeholders::_1);
global_api_server->subscribe_home_assistant_state(entity_id, optional<std::string>(attribute), f); global_api_server->subscribe_home_assistant_state(entity_id, optional<std::string>(attribute), f);
} }
#else #else
template<typename T>
void subscribe_homeassistant_state(void (T::*callback)(StringRef), const std::string &entity_id,
const std::string &attribute = "") {
static_assert(sizeof(T) == 0,
"subscribe_homeassistant_state() requires 'homeassistant_states: true' in the 'api:' section "
"of your YAML configuration");
}
template<typename T> template<typename T>
void subscribe_homeassistant_state(void (T::*callback)(std::string), const std::string &entity_id, void subscribe_homeassistant_state(void (T::*callback)(std::string), const std::string &entity_id,
const std::string &attribute = "") { const std::string &attribute = "") {
@@ -173,6 +204,14 @@ class CustomAPIDevice {
"of your YAML configuration"); "of your YAML configuration");
} }
template<typename T>
void subscribe_homeassistant_state(void (T::*callback)(const std::string &, StringRef), const std::string &entity_id,
const std::string &attribute = "") {
static_assert(sizeof(T) == 0,
"subscribe_homeassistant_state() requires 'homeassistant_states: true' in the 'api:' section "
"of your YAML configuration");
}
template<typename T> template<typename T>
void subscribe_homeassistant_state(void (T::*callback)(std::string, std::string), const std::string &entity_id, void subscribe_homeassistant_state(void (T::*callback)(std::string, std::string), const std::string &entity_id,
const std::string &attribute = "") { const std::string &attribute = "") {

View File

@@ -2,37 +2,35 @@
#include "esphome/core/log.h" #include "esphome/core/log.h"
#include "esphome/components/api/api_server.h" #include "esphome/components/api/api_server.h"
namespace esphome { namespace esphome::homeassistant {
namespace homeassistant {
static const char *const TAG = "homeassistant.binary_sensor"; static const char *const TAG = "homeassistant.binary_sensor";
void HomeassistantBinarySensor::setup() { void HomeassistantBinarySensor::setup() {
api::global_api_server->subscribe_home_assistant_state( api::global_api_server->subscribe_home_assistant_state(this->entity_id_, this->attribute_, [this](StringRef state) {
this->entity_id_, this->attribute_, [this](const std::string &state) { auto val = parse_on_off(state.c_str());
auto val = parse_on_off(state.c_str()); switch (val) {
switch (val) { case PARSE_NONE:
case PARSE_NONE: case PARSE_TOGGLE:
case PARSE_TOGGLE: ESP_LOGW(TAG, "Can't convert '%s' to binary state!", state.c_str());
ESP_LOGW(TAG, "Can't convert '%s' to binary state!", state.c_str()); break;
break; case PARSE_ON:
case PARSE_ON: case PARSE_OFF:
case PARSE_OFF: bool new_state = val == PARSE_ON;
bool new_state = val == PARSE_ON; if (this->attribute_ != nullptr) {
if (this->attribute_ != nullptr) { ESP_LOGD(TAG, "'%s::%s': Got attribute state %s", this->entity_id_, this->attribute_, ONOFF(new_state));
ESP_LOGD(TAG, "'%s::%s': Got attribute state %s", this->entity_id_, this->attribute_, ONOFF(new_state)); } else {
} else { ESP_LOGD(TAG, "'%s': Got state %s", this->entity_id_, ONOFF(new_state));
ESP_LOGD(TAG, "'%s': Got state %s", this->entity_id_, ONOFF(new_state));
}
if (this->initial_) {
this->publish_initial_state(new_state);
} else {
this->publish_state(new_state);
}
break;
} }
this->initial_ = false; if (this->initial_) {
}); this->publish_initial_state(new_state);
} else {
this->publish_state(new_state);
}
break;
}
this->initial_ = false;
});
} }
void HomeassistantBinarySensor::dump_config() { void HomeassistantBinarySensor::dump_config() {
LOG_BINARY_SENSOR("", "Homeassistant Binary Sensor", this); LOG_BINARY_SENSOR("", "Homeassistant Binary Sensor", this);
@@ -43,5 +41,4 @@ void HomeassistantBinarySensor::dump_config() {
} }
float HomeassistantBinarySensor::get_setup_priority() const { return setup_priority::AFTER_WIFI; } float HomeassistantBinarySensor::get_setup_priority() const { return setup_priority::AFTER_WIFI; }
} // namespace homeassistant } // namespace esphome::homeassistant
} // namespace esphome

View File

@@ -3,8 +3,7 @@
#include "esphome/core/component.h" #include "esphome/core/component.h"
#include "esphome/components/binary_sensor/binary_sensor.h" #include "esphome/components/binary_sensor/binary_sensor.h"
namespace esphome { namespace esphome::homeassistant {
namespace homeassistant {
class HomeassistantBinarySensor : public binary_sensor::BinarySensor, public Component { class HomeassistantBinarySensor : public binary_sensor::BinarySensor, public Component {
public: public:
@@ -20,5 +19,4 @@ class HomeassistantBinarySensor : public binary_sensor::BinarySensor, public Com
bool initial_{true}; bool initial_{true};
}; };
} // namespace homeassistant } // namespace esphome::homeassistant
} // namespace esphome

View File

@@ -4,13 +4,12 @@
#include "esphome/components/api/api_server.h" #include "esphome/components/api/api_server.h"
#include "esphome/core/log.h" #include "esphome/core/log.h"
namespace esphome { namespace esphome::homeassistant {
namespace homeassistant {
static const char *const TAG = "homeassistant.number"; static const char *const TAG = "homeassistant.number";
void HomeassistantNumber::state_changed_(const std::string &state) { void HomeassistantNumber::state_changed_(StringRef state) {
auto number_value = parse_number<float>(state); auto number_value = parse_number<float>(state.c_str());
if (!number_value.has_value()) { if (!number_value.has_value()) {
ESP_LOGW(TAG, "'%s': Can't convert '%s' to number!", this->entity_id_, state.c_str()); ESP_LOGW(TAG, "'%s': Can't convert '%s' to number!", this->entity_id_, state.c_str());
this->publish_state(NAN); this->publish_state(NAN);
@@ -23,8 +22,8 @@ void HomeassistantNumber::state_changed_(const std::string &state) {
this->publish_state(number_value.value()); this->publish_state(number_value.value());
} }
void HomeassistantNumber::min_retrieved_(const std::string &min) { void HomeassistantNumber::min_retrieved_(StringRef min) {
auto min_value = parse_number<float>(min); auto min_value = parse_number<float>(min.c_str());
if (!min_value.has_value()) { if (!min_value.has_value()) {
ESP_LOGE(TAG, "'%s': Can't convert 'min' value '%s' to number!", this->entity_id_, min.c_str()); ESP_LOGE(TAG, "'%s': Can't convert 'min' value '%s' to number!", this->entity_id_, min.c_str());
return; return;
@@ -33,8 +32,8 @@ void HomeassistantNumber::min_retrieved_(const std::string &min) {
this->traits.set_min_value(min_value.value()); this->traits.set_min_value(min_value.value());
} }
void HomeassistantNumber::max_retrieved_(const std::string &max) { void HomeassistantNumber::max_retrieved_(StringRef max) {
auto max_value = parse_number<float>(max); auto max_value = parse_number<float>(max.c_str());
if (!max_value.has_value()) { if (!max_value.has_value()) {
ESP_LOGE(TAG, "'%s': Can't convert 'max' value '%s' to number!", this->entity_id_, max.c_str()); ESP_LOGE(TAG, "'%s': Can't convert 'max' value '%s' to number!", this->entity_id_, max.c_str());
return; return;
@@ -43,8 +42,8 @@ void HomeassistantNumber::max_retrieved_(const std::string &max) {
this->traits.set_max_value(max_value.value()); this->traits.set_max_value(max_value.value());
} }
void HomeassistantNumber::step_retrieved_(const std::string &step) { void HomeassistantNumber::step_retrieved_(StringRef step) {
auto step_value = parse_number<float>(step); auto step_value = parse_number<float>(step.c_str());
if (!step_value.has_value()) { if (!step_value.has_value()) {
ESP_LOGE(TAG, "'%s': Can't convert 'step' value '%s' to number!", this->entity_id_, step.c_str()); ESP_LOGE(TAG, "'%s': Can't convert 'step' value '%s' to number!", this->entity_id_, step.c_str());
return; return;
@@ -99,5 +98,4 @@ void HomeassistantNumber::control(float value) {
api::global_api_server->send_homeassistant_action(resp); api::global_api_server->send_homeassistant_action(resp);
} }
} // namespace homeassistant } // namespace esphome::homeassistant
} // namespace esphome

View File

@@ -1,13 +1,10 @@
#pragma once #pragma once
#include <map>
#include <string>
#include "esphome/components/number/number.h" #include "esphome/components/number/number.h"
#include "esphome/core/component.h" #include "esphome/core/component.h"
#include "esphome/core/string_ref.h"
namespace esphome { namespace esphome::homeassistant {
namespace homeassistant {
class HomeassistantNumber : public number::Number, public Component { class HomeassistantNumber : public number::Number, public Component {
public: public:
@@ -18,14 +15,14 @@ class HomeassistantNumber : public number::Number, public Component {
float get_setup_priority() const override; float get_setup_priority() const override;
protected: protected:
void state_changed_(const std::string &state); void state_changed_(StringRef state);
void min_retrieved_(const std::string &min); void min_retrieved_(StringRef min);
void max_retrieved_(const std::string &max); void max_retrieved_(StringRef max);
void step_retrieved_(const std::string &step); void step_retrieved_(StringRef step);
void control(float value) override; void control(float value) override;
const char *entity_id_{nullptr}; const char *entity_id_{nullptr};
}; };
} // namespace homeassistant
} // namespace esphome } // namespace esphome::homeassistant

View File

@@ -2,28 +2,26 @@
#include "esphome/core/log.h" #include "esphome/core/log.h"
#include "esphome/components/api/api_server.h" #include "esphome/components/api/api_server.h"
namespace esphome { namespace esphome::homeassistant {
namespace homeassistant {
static const char *const TAG = "homeassistant.sensor"; static const char *const TAG = "homeassistant.sensor";
void HomeassistantSensor::setup() { void HomeassistantSensor::setup() {
api::global_api_server->subscribe_home_assistant_state( api::global_api_server->subscribe_home_assistant_state(this->entity_id_, this->attribute_, [this](StringRef state) {
this->entity_id_, this->attribute_, [this](const std::string &state) { auto val = parse_number<float>(state.c_str());
auto val = parse_number<float>(state); if (!val.has_value()) {
if (!val.has_value()) { ESP_LOGW(TAG, "'%s': Can't convert '%s' to number!", this->entity_id_, state.c_str());
ESP_LOGW(TAG, "'%s': Can't convert '%s' to number!", this->entity_id_, state.c_str()); this->publish_state(NAN);
this->publish_state(NAN); return;
return; }
}
if (this->attribute_ != nullptr) { if (this->attribute_ != nullptr) {
ESP_LOGD(TAG, "'%s::%s': Got attribute state %.2f", this->entity_id_, this->attribute_, *val); ESP_LOGD(TAG, "'%s::%s': Got attribute state %.2f", this->entity_id_, this->attribute_, *val);
} else { } else {
ESP_LOGD(TAG, "'%s': Got state %.2f", this->entity_id_, *val); ESP_LOGD(TAG, "'%s': Got state %.2f", this->entity_id_, *val);
} }
this->publish_state(*val); this->publish_state(*val);
}); });
} }
void HomeassistantSensor::dump_config() { void HomeassistantSensor::dump_config() {
LOG_SENSOR("", "Homeassistant Sensor", this); LOG_SENSOR("", "Homeassistant Sensor", this);
@@ -34,5 +32,4 @@ void HomeassistantSensor::dump_config() {
} }
float HomeassistantSensor::get_setup_priority() const { return setup_priority::AFTER_CONNECTION; } float HomeassistantSensor::get_setup_priority() const { return setup_priority::AFTER_CONNECTION; }
} // namespace homeassistant } // namespace esphome::homeassistant
} // namespace esphome

View File

@@ -3,8 +3,7 @@
#include "esphome/core/component.h" #include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h" #include "esphome/components/sensor/sensor.h"
namespace esphome { namespace esphome::homeassistant {
namespace homeassistant {
class HomeassistantSensor : public sensor::Sensor, public Component { class HomeassistantSensor : public sensor::Sensor, public Component {
public: public:
@@ -19,5 +18,4 @@ class HomeassistantSensor : public sensor::Sensor, public Component {
const char *attribute_{nullptr}; const char *attribute_{nullptr};
}; };
} // namespace homeassistant } // namespace esphome::homeassistant
} // namespace esphome

View File

@@ -2,15 +2,14 @@
#include "esphome/components/api/api_server.h" #include "esphome/components/api/api_server.h"
#include "esphome/core/log.h" #include "esphome/core/log.h"
namespace esphome { namespace esphome::homeassistant {
namespace homeassistant {
static const char *const TAG = "homeassistant.switch"; static const char *const TAG = "homeassistant.switch";
using namespace esphome::switch_; using namespace esphome::switch_;
void HomeassistantSwitch::setup() { void HomeassistantSwitch::setup() {
api::global_api_server->subscribe_home_assistant_state(this->entity_id_, nullptr, [this](const std::string &state) { api::global_api_server->subscribe_home_assistant_state(this->entity_id_, nullptr, [this](StringRef state) {
auto val = parse_on_off(state.c_str()); auto val = parse_on_off(state.c_str());
switch (val) { switch (val) {
case PARSE_NONE: case PARSE_NONE:
@@ -59,5 +58,4 @@ void HomeassistantSwitch::write_state(bool state) {
api::global_api_server->send_homeassistant_action(resp); api::global_api_server->send_homeassistant_action(resp);
} }
} // namespace homeassistant } // namespace esphome::homeassistant
} // namespace esphome

View File

@@ -3,8 +3,7 @@
#include "esphome/components/switch/switch.h" #include "esphome/components/switch/switch.h"
#include "esphome/core/component.h" #include "esphome/core/component.h"
namespace esphome { namespace esphome::homeassistant {
namespace homeassistant {
class HomeassistantSwitch : public switch_::Switch, public Component { class HomeassistantSwitch : public switch_::Switch, public Component {
public: public:
@@ -18,5 +17,4 @@ class HomeassistantSwitch : public switch_::Switch, public Component {
const char *entity_id_{nullptr}; const char *entity_id_{nullptr};
}; };
} // namespace homeassistant } // namespace esphome::homeassistant
} // namespace esphome

View File

@@ -2,21 +2,19 @@
#include "esphome/core/log.h" #include "esphome/core/log.h"
#include "esphome/components/api/api_server.h" #include "esphome/components/api/api_server.h"
namespace esphome { namespace esphome::homeassistant {
namespace homeassistant {
static const char *const TAG = "homeassistant.text_sensor"; static const char *const TAG = "homeassistant.text_sensor";
void HomeassistantTextSensor::setup() { void HomeassistantTextSensor::setup() {
api::global_api_server->subscribe_home_assistant_state( api::global_api_server->subscribe_home_assistant_state(this->entity_id_, this->attribute_, [this](StringRef state) {
this->entity_id_, this->attribute_, [this](const std::string &state) { if (this->attribute_ != nullptr) {
if (this->attribute_ != nullptr) { ESP_LOGD(TAG, "'%s::%s': Got attribute state '%s'", this->entity_id_, this->attribute_, state.c_str());
ESP_LOGD(TAG, "'%s::%s': Got attribute state '%s'", this->entity_id_, this->attribute_, state.c_str()); } else {
} else { ESP_LOGD(TAG, "'%s': Got state '%s'", this->entity_id_, state.c_str());
ESP_LOGD(TAG, "'%s': Got state '%s'", this->entity_id_, state.c_str()); }
} this->publish_state(state.str());
this->publish_state(state); });
});
} }
void HomeassistantTextSensor::dump_config() { void HomeassistantTextSensor::dump_config() {
LOG_TEXT_SENSOR("", "Homeassistant Text Sensor", this); LOG_TEXT_SENSOR("", "Homeassistant Text Sensor", this);
@@ -26,5 +24,5 @@ void HomeassistantTextSensor::dump_config() {
} }
} }
float HomeassistantTextSensor::get_setup_priority() const { return setup_priority::AFTER_CONNECTION; } float HomeassistantTextSensor::get_setup_priority() const { return setup_priority::AFTER_CONNECTION; }
} // namespace homeassistant
} // namespace esphome } // namespace esphome::homeassistant

View File

@@ -3,8 +3,7 @@
#include "esphome/core/component.h" #include "esphome/core/component.h"
#include "esphome/components/text_sensor/text_sensor.h" #include "esphome/components/text_sensor/text_sensor.h"
namespace esphome { namespace esphome::homeassistant {
namespace homeassistant {
class HomeassistantTextSensor : public text_sensor::TextSensor, public Component { class HomeassistantTextSensor : public text_sensor::TextSensor, public Component {
public: public:
@@ -19,5 +18,4 @@ class HomeassistantTextSensor : public text_sensor::TextSensor, public Component
const char *attribute_{nullptr}; const char *attribute_{nullptr};
}; };
} // namespace homeassistant } // namespace esphome::homeassistant
} // namespace esphome