ESPHome 2026.1.0-dev
Loading...
Searching...
No Matches
entity_base.h
Go to the documentation of this file.
1#pragma once
2
3#include <cstdint>
4#include <span>
5#include <string>
6#include "string_ref.h"
7#include "helpers.h"
8#include "log.h"
9
10#ifdef USE_DEVICES
11#include "device.h"
12#endif
13
14namespace esphome {
15
16// Maximum size for object_id buffer (friendly_name max ~120 + margin)
17static constexpr size_t OBJECT_ID_MAX_LEN = 128;
18
24
25// The generic Entity base class that provides an interface common to all Entities.
27 public:
28 // Get/set the name of this Entity
29 const StringRef &get_name() const;
30 void set_name(const char *name);
31
32 // Get whether this Entity has its own name or it should use the device friendly_name.
33 bool has_own_name() const { return this->flags_.has_own_name; }
34
35 // Get the sanitized name of this Entity as an ID.
36 // Deprecated: object_id mangles names and all object_id methods are planned for removal.
37 // See https://github.com/esphome/backlog/issues/76
38 // Now is the time to stop using object_id entirely. If you still need it temporarily,
39 // use get_object_id_to() which will remain available longer but will also eventually be removed.
40 ESPDEPRECATED("object_id mangles names and all object_id methods are planned for removal "
41 "(see https://github.com/esphome/backlog/issues/76). "
42 "Now is the time to stop using object_id. If still needed, use get_object_id_to() "
43 "which will remain available longer. get_object_id() will be removed in 2026.7.0",
44 "2025.12.0")
45 std::string get_object_id() const;
46 void set_object_id(const char *object_id);
47
48 // Set both name and object_id in one call (reduces generated code size)
49 void set_name_and_object_id(const char *name, const char *object_id);
50
51 // Get the unique Object ID of this Entity
52 uint32_t get_object_id_hash();
53
57 StringRef get_object_id_to(std::span<char, OBJECT_ID_MAX_LEN> buf) const;
58
61 size_t write_object_id_to(char *buf, size_t buf_size) const;
62
63 // Get/set whether this Entity should be hidden outside ESPHome
64 bool is_internal() const { return this->flags_.internal; }
65 void set_internal(bool internal) { this->flags_.internal = internal; }
66
67 // Check if this object is declared to be disabled by default.
68 // That means that when the device gets added to Home Assistant (or other clients) it should
69 // not be added to the default view by default, and a user action is necessary to manually add it.
70 bool is_disabled_by_default() const { return this->flags_.disabled_by_default; }
71 void set_disabled_by_default(bool disabled_by_default) { this->flags_.disabled_by_default = disabled_by_default; }
72
73 // Get/set the entity category.
75 void set_entity_category(EntityCategory entity_category) {
76 this->flags_.entity_category = static_cast<uint8_t>(entity_category);
77 }
78
79 // Get/set this entity's icon
81 "Use get_icon_ref() instead for better performance (avoids string copy). Will be removed in ESPHome 2026.5.0",
82 "2025.11.0")
83 std::string get_icon() const;
84 void set_icon(const char *icon);
86 static constexpr auto EMPTY_STRING = StringRef::from_lit("");
87#ifdef USE_ENTITY_ICON
88 return this->icon_c_str_ == nullptr ? EMPTY_STRING : StringRef(this->icon_c_str_);
89#else
90 return EMPTY_STRING;
91#endif
92 }
93
94#ifdef USE_DEVICES
95 // Get/set this entity's device id
96 uint32_t get_device_id() const {
97 if (this->device_ == nullptr) {
98 return 0; // No device set, return 0
99 }
100 return this->device_->get_device_id();
101 }
102 void set_device(Device *device) { this->device_ = device; }
103#endif
104
105 // Check if this entity has state
106 bool has_state() const { return this->flags_.has_state; }
107
108 // Set has_state - for components that need to manually set this
109 void set_has_state(bool state) { this->flags_.has_state = state; }
110
129#ifdef USE_DEVICES
130 // Combine object_id_hash with device_id to ensure uniqueness across devices
131 // Note: device_id is 0 for the main device, so XORing with 0 preserves the original hash
132 // This ensures backward compatibility for existing single-device configurations
133 return this->get_object_id_hash() ^ this->get_device_id();
134#else
135 // Without devices, just use object_id_hash as before
136 return this->get_object_id_hash();
137#endif
138 }
139
140 protected:
141 void calc_object_id_();
142
144 bool is_object_id_dynamic_() const;
145
147 const char *object_id_c_str_{nullptr};
148#ifdef USE_ENTITY_ICON
149 const char *icon_c_str_{nullptr};
150#endif
151 uint32_t object_id_hash_{};
152#ifdef USE_DEVICES
154#endif
155
156 // Bit-packed flags to save memory (1 byte instead of 5)
157 struct EntityFlags {
158 uint8_t has_own_name : 1;
159 uint8_t internal : 1;
161 uint8_t has_state : 1;
162 uint8_t entity_category : 2; // Supports up to 4 categories
163 uint8_t reserved : 2; // Reserved for future use
165};
166
167class EntityBase_DeviceClass { // NOLINT(readability-identifier-naming)
168 public:
170 ESPDEPRECATED("Use get_device_class_ref() instead for better performance (avoids string copy). Will be removed in "
171 "ESPHome 2026.5.0",
172 "2025.11.0")
173 std::string get_device_class();
175 void set_device_class(const char *device_class);
178 static constexpr auto EMPTY_STRING = StringRef::from_lit("");
179 return this->device_class_ == nullptr ? EMPTY_STRING : StringRef(this->device_class_);
180 }
181
182 protected:
183 const char *device_class_{nullptr};
184};
185
186class EntityBase_UnitOfMeasurement { // NOLINT(readability-identifier-naming)
187 public:
189 ESPDEPRECATED("Use get_unit_of_measurement_ref() instead for better performance (avoids string copy). Will be "
190 "removed in ESPHome 2026.5.0",
191 "2025.11.0")
192 std::string get_unit_of_measurement();
194 void set_unit_of_measurement(const char *unit_of_measurement);
197 static constexpr auto EMPTY_STRING = StringRef::from_lit("");
198 return this->unit_of_measurement_ == nullptr ? EMPTY_STRING : StringRef(this->unit_of_measurement_);
199 }
200
201 protected:
202 const char *unit_of_measurement_{nullptr};
203};
204
209template<typename T> class StatefulEntityBase : public EntityBase {
210 public:
211 virtual bool has_state() const { return this->state_.has_value(); }
212 virtual const T &get_state() const { return this->state_.value(); }
213 virtual T get_state_default(T default_value) const { return this->state_.value_or(default_value); }
214 void invalidate_state() { this->set_new_state({}); }
215
216 void add_full_state_callback(std::function<void(optional<T> previous, optional<T> current)> &&callback) {
217 if (this->full_state_callbacks_ == nullptr)
218 this->full_state_callbacks_ = new CallbackManager<void(optional<T> previous, optional<T> current)>(); // NOLINT
219 this->full_state_callbacks_->add(std::move(callback));
220 }
221 void add_on_state_callback(std::function<void(T)> &&callback) {
222 if (this->state_callbacks_ == nullptr)
223 this->state_callbacks_ = new CallbackManager<void(T)>(); // NOLINT
224 this->state_callbacks_->add(std::move(callback));
225 }
226
227 void set_trigger_on_initial_state(bool trigger_on_initial_state) {
228 this->trigger_on_initial_state_ = trigger_on_initial_state;
229 }
230
231 protected:
239 virtual bool set_new_state(const optional<T> &new_state) {
240 if (this->state_ != new_state) {
241 // call the full state callbacks with the previous and new state
242 if (this->full_state_callbacks_ != nullptr)
243 this->full_state_callbacks_->call(this->state_, new_state);
244 // trigger legacy callbacks only if the new state is valid and either the trigger on initial state is enabled or
245 // the previous state was valid
246 auto had_state = this->has_state();
247 this->state_ = new_state;
248 if (this->state_callbacks_ != nullptr && new_state.has_value() && (this->trigger_on_initial_state_ || had_state))
249 this->state_callbacks_->call(new_state.value());
250 return true;
251 }
252 return false;
253 }
255 // callbacks with full state and previous state
258};
259} // 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)
ESPDEPRECATED("object_id mangles names and all object_id methods are planned for removal " "(see https://github.com/esphome/backlog/issues/76). " "Now is the time to stop using object_id. If still needed, use get_object_id_to() " "which will remain available longer. get_object_id() will be removed in 2026.7.0", "2025.12.0") std void set_object_id(const char *object_id)
bool has_own_name() const
Definition entity_base.h:33
bool is_internal() const
Definition entity_base.h:64
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:75
StringRef get_icon_ref() const
Definition entity_base.h:85
size_t write_object_id_to(char *buf, size_t buf_size) const
Write object_id directly to buffer, returns length written (excluding null) Useful for building compo...
uint32_t get_device_id() const
Definition entity_base.h:96
bool is_disabled_by_default() const
Definition entity_base.h:70
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:71
void set_has_state(bool state)
void set_name_and_object_id(const char *name, const char *object_id)
const char * icon_c_str_
bool has_state() const
EntityCategory get_entity_category() const
Definition entity_base.h:74
StringRef get_object_id_to(std::span< char, OBJECT_ID_MAX_LEN > buf) const
Get object_id with zero heap allocation For static case: returns StringRef to internal storage (buffe...
void set_internal(bool internal)
Definition entity_base.h:65
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:20
@ ENTITY_CATEGORY_CONFIG
Definition entity_base.h:21
@ ENTITY_CATEGORY_DIAGNOSTIC
Definition entity_base.h:22
struct ESPDEPRECATED("Use std::index_sequence instead. Removed in 2026.6.0", "2025.12.0") seq
Definition automation.h:24