ESPHome 2025.12.1
Loading...
Searching...
No Matches
entity_base.h
Go to the documentation of this file.
1#pragma once
2
3#include <string>
4#include <cstdint>
5#include "string_ref.h"
6#include "helpers.h"
7#include "log.h"
8
9#ifdef USE_DEVICES
10#include "device.h"
11#endif
12
13namespace esphome {
14
15// Forward declaration for friend access
16namespace api {
17class APIConnection;
18} // namespace api
19
20namespace web_server {
21struct UrlMatch;
22} // namespace web_server
23
29
30// The generic Entity base class that provides an interface common to all Entities.
32 public:
33 // Get/set the name of this Entity
34 const StringRef &get_name() const;
35 void set_name(const char *name);
36
37 // Get whether this Entity has its own name or it should use the device friendly_name.
38 bool has_own_name() const { return this->flags_.has_own_name; }
39
40 // Get the sanitized name of this Entity as an ID.
41 std::string get_object_id() const;
42 void set_object_id(const char *object_id);
43
44 // Set both name and object_id in one call (reduces generated code size)
45 void set_name_and_object_id(const char *name, const char *object_id);
46
47 // Get the unique Object ID of this Entity
48 uint32_t get_object_id_hash();
49
50 // Get/set whether this Entity should be hidden outside ESPHome
51 bool is_internal() const { return this->flags_.internal; }
52 void set_internal(bool internal) { this->flags_.internal = internal; }
53
54 // Check if this object is declared to be disabled by default.
55 // That means that when the device gets added to Home Assistant (or other clients) it should
56 // not be added to the default view by default, and a user action is necessary to manually add it.
57 bool is_disabled_by_default() const { return this->flags_.disabled_by_default; }
58 void set_disabled_by_default(bool disabled_by_default) { this->flags_.disabled_by_default = disabled_by_default; }
59
60 // Get/set the entity category.
62 void set_entity_category(EntityCategory entity_category) {
63 this->flags_.entity_category = static_cast<uint8_t>(entity_category);
64 }
65
66 // Get/set this entity's icon
68 "Use get_icon_ref() instead for better performance (avoids string copy). Will be removed in ESPHome 2026.5.0",
69 "2025.11.0")
70 std::string get_icon() const;
71 void set_icon(const char *icon);
73 static constexpr auto EMPTY_STRING = StringRef::from_lit("");
74#ifdef USE_ENTITY_ICON
75 return this->icon_c_str_ == nullptr ? EMPTY_STRING : StringRef(this->icon_c_str_);
76#else
77 return EMPTY_STRING;
78#endif
79 }
80
81#ifdef USE_DEVICES
82 // Get/set this entity's device id
83 uint32_t get_device_id() const {
84 if (this->device_ == nullptr) {
85 return 0; // No device set, return 0
86 }
87 return this->device_->get_device_id();
88 }
89 void set_device(Device *device) { this->device_ = device; }
90#endif
91
92 // Check if this entity has state
93 bool has_state() const { return this->flags_.has_state; }
94
95 // Set has_state - for components that need to manually set this
96 void set_has_state(bool state) { this->flags_.has_state = state; }
97
116#ifdef USE_DEVICES
117 // Combine object_id_hash with device_id to ensure uniqueness across devices
118 // Note: device_id is 0 for the main device, so XORing with 0 preserves the original hash
119 // This ensures backward compatibility for existing single-device configurations
120 return this->get_object_id_hash() ^ this->get_device_id();
121#else
122 // Without devices, just use object_id_hash as before
123 return this->get_object_id_hash();
124#endif
125 }
126
127 protected:
128 friend class api::APIConnection;
129 friend struct web_server::UrlMatch;
130
131 // Get object_id as StringRef when it's static (for API usage)
132 // Returns empty StringRef if object_id is dynamic (needs allocation)
134
135 void calc_object_id_();
136
138 bool is_object_id_dynamic_() const;
139
141 const char *object_id_c_str_{nullptr};
142#ifdef USE_ENTITY_ICON
143 const char *icon_c_str_{nullptr};
144#endif
145 uint32_t object_id_hash_{};
146#ifdef USE_DEVICES
148#endif
149
150 // Bit-packed flags to save memory (1 byte instead of 5)
151 struct EntityFlags {
152 uint8_t has_own_name : 1;
153 uint8_t internal : 1;
155 uint8_t has_state : 1;
156 uint8_t entity_category : 2; // Supports up to 4 categories
157 uint8_t reserved : 2; // Reserved for future use
159};
160
161class EntityBase_DeviceClass { // NOLINT(readability-identifier-naming)
162 public:
164 ESPDEPRECATED("Use get_device_class_ref() instead for better performance (avoids string copy). Will be removed in "
165 "ESPHome 2026.5.0",
166 "2025.11.0")
167 std::string get_device_class();
169 void set_device_class(const char *device_class);
172 static constexpr auto EMPTY_STRING = StringRef::from_lit("");
173 return this->device_class_ == nullptr ? EMPTY_STRING : StringRef(this->device_class_);
174 }
175
176 protected:
177 const char *device_class_{nullptr};
178};
179
180class EntityBase_UnitOfMeasurement { // NOLINT(readability-identifier-naming)
181 public:
183 ESPDEPRECATED("Use get_unit_of_measurement_ref() instead for better performance (avoids string copy). Will be "
184 "removed in ESPHome 2026.5.0",
185 "2025.11.0")
186 std::string get_unit_of_measurement();
188 void set_unit_of_measurement(const char *unit_of_measurement);
191 static constexpr auto EMPTY_STRING = StringRef::from_lit("");
192 return this->unit_of_measurement_ == nullptr ? EMPTY_STRING : StringRef(this->unit_of_measurement_);
193 }
194
195 protected:
196 const char *unit_of_measurement_{nullptr};
197};
198
203template<typename T> class StatefulEntityBase : public EntityBase {
204 public:
205 virtual bool has_state() const { return this->state_.has_value(); }
206 virtual const T &get_state() const { return this->state_.value(); }
207 virtual T get_state_default(T default_value) const { return this->state_.value_or(default_value); }
208 void invalidate_state() { this->set_new_state({}); }
209
210 void add_full_state_callback(std::function<void(optional<T> previous, optional<T> current)> &&callback) {
211 if (this->full_state_callbacks_ == nullptr)
212 this->full_state_callbacks_ = new CallbackManager<void(optional<T> previous, optional<T> current)>(); // NOLINT
213 this->full_state_callbacks_->add(std::move(callback));
214 }
215 void add_on_state_callback(std::function<void(T)> &&callback) {
216 if (this->state_callbacks_ == nullptr)
217 this->state_callbacks_ = new CallbackManager<void(T)>(); // NOLINT
218 this->state_callbacks_->add(std::move(callback));
219 }
220
221 void set_trigger_on_initial_state(bool trigger_on_initial_state) {
222 this->trigger_on_initial_state_ = trigger_on_initial_state;
223 }
224
225 protected:
233 virtual bool set_new_state(const optional<T> &new_state) {
234 if (this->state_ != new_state) {
235 // call the full state callbacks with the previous and new state
236 if (this->full_state_callbacks_ != nullptr)
237 this->full_state_callbacks_->call(this->state_, new_state);
238 // trigger legacy callbacks only if the new state is valid and either the trigger on initial state is enabled or
239 // the previous state was valid
240 auto had_state = this->has_state();
241 this->state_ = new_state;
242 if (this->state_callbacks_ != nullptr && new_state.has_value() && (this->trigger_on_initial_state_ || had_state))
243 this->state_callbacks_->call(new_state.value());
244 return true;
245 }
246 return false;
247 }
249 // callbacks with full state and previous state
252};
253} // namespace esphome
uint32_t get_device_id()
Definition device.h:8
StringRef get_device_class_ref() const
Get the device class as StringRef.
ESPDEPRECATED("Use get_device_class_ref() instead for better performance (avoids string copy). Will be removed in " "ESPHome 2026.5.0", "2025.11.0") std void set_device_class(const char *device_class)
Get the device class, using the manual override if set.
const char * device_class_
Device class override.
const char * unit_of_measurement_
Unit of measurement override.
ESPDEPRECATED("Use get_unit_of_measurement_ref() instead for better performance (avoids string copy). Will be " "removed in ESPHome 2026.5.0", "2025.11.0") std void set_unit_of_measurement(const char *unit_of_measurement)
Get the unit of measurement, using the manual override if set.
StringRef get_unit_of_measurement_ref() const
Get the unit of measurement as StringRef.
struct esphome::EntityBase::EntityFlags flags_
void set_device(Device *device)
Definition entity_base.h:89
void set_object_id(const char *object_id)
bool has_own_name() const
Definition entity_base.h:38
bool is_internal() const
Definition entity_base.h:51
const char * object_id_c_str_
uint32_t get_object_id_hash()
const StringRef & get_name() const
uint32_t get_preference_hash()
Get a unique hash for storing preferences/settings for this entity.
void set_entity_category(EntityCategory entity_category)
Definition entity_base.h:62
StringRef get_icon_ref() const
Definition entity_base.h:72
uint32_t get_device_id() const
Definition entity_base.h:83
bool is_disabled_by_default() const
Definition entity_base.h:57
bool is_object_id_dynamic_() const
Check if the object_id is dynamic (changes with MAC suffix)
void set_name(const char *name)
ESPDEPRECATED("Use get_icon_ref() instead for better performance (avoids string copy). Will be removed in ESPHome 2026.5.0", "2025.11.0") std void set_icon(const char *icon)
void set_disabled_by_default(bool disabled_by_default)
Definition entity_base.h:58
void set_has_state(bool state)
Definition entity_base.h:96
void set_name_and_object_id(const char *name, const char *object_id)
const char * icon_c_str_
bool has_state() const
Definition entity_base.h:93
std::string get_object_id() const
EntityCategory get_entity_category() const
Definition entity_base.h:61
StringRef get_object_id_ref_for_api_() const
void set_internal(bool internal)
Definition entity_base.h:52
An entity that has a state.
virtual const T & get_state() const
virtual bool set_new_state(const optional< T > &new_state)
Set a new state for this entity.
void add_full_state_callback(std::function< void(optional< T > previous, optional< T > current)> &&callback)
CallbackManager< void(T)> * state_callbacks_
void add_on_state_callback(std::function< void(T)> &&callback)
void set_trigger_on_initial_state(bool trigger_on_initial_state)
virtual bool has_state() const
virtual T get_state_default(T default_value) const
CallbackManager< void(optional< T > previous, optional< T > current)> * full_state_callbacks_
StringRef is a reference to a string owned by something else.
Definition string_ref.h:22
static constexpr StringRef from_lit(const CharT(&s)[N])
Definition string_ref.h:46
bool has_value() const
Definition optional.h:92
value_type const & value() const
Definition optional.h:94
bool state
Definition fan.h:0
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
@ ENTITY_CATEGORY_NONE
Definition entity_base.h:25
@ ENTITY_CATEGORY_CONFIG
Definition entity_base.h:26
@ ENTITY_CATEGORY_DIAGNOSTIC
Definition entity_base.h:27
struct ESPDEPRECATED("Use std::index_sequence instead. Removed in 2026.6.0", "2025.12.0") seq
Definition automation.h:24
Internal helper struct that is used to parse incoming URLs.
Definition web_server.h:40