ESPHome 2025.12.0-dev
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 // Get the unique Object ID of this Entity
45 uint32_t get_object_id_hash();
46
47 // Get/set whether this Entity should be hidden outside ESPHome
48 bool is_internal() const { return this->flags_.internal; }
49 void set_internal(bool internal) { this->flags_.internal = internal; }
50
51 // Check if this object is declared to be disabled by default.
52 // That means that when the device gets added to Home Assistant (or other clients) it should
53 // not be added to the default view by default, and a user action is necessary to manually add it.
54 bool is_disabled_by_default() const { return this->flags_.disabled_by_default; }
55 void set_disabled_by_default(bool disabled_by_default) { this->flags_.disabled_by_default = disabled_by_default; }
56
57 // Get/set the entity category.
59 void set_entity_category(EntityCategory entity_category) {
60 this->flags_.entity_category = static_cast<uint8_t>(entity_category);
61 }
62
63 // Get/set this entity's icon
64 ESPDEPRECATED(
65 "Use get_icon_ref() instead for better performance (avoids string copy). Will be removed in ESPHome 2026.5.0",
66 "2025.11.0")
67 std::string get_icon() const;
68 void set_icon(const char *icon);
70 static constexpr auto EMPTY_STRING = StringRef::from_lit("");
71#ifdef USE_ENTITY_ICON
72 return this->icon_c_str_ == nullptr ? EMPTY_STRING : StringRef(this->icon_c_str_);
73#else
74 return EMPTY_STRING;
75#endif
76 }
77
78#ifdef USE_DEVICES
79 // Get/set this entity's device id
80 uint32_t get_device_id() const {
81 if (this->device_ == nullptr) {
82 return 0; // No device set, return 0
83 }
84 return this->device_->get_device_id();
85 }
86 void set_device(Device *device) { this->device_ = device; }
87#endif
88
89 // Check if this entity has state
90 bool has_state() const { return this->flags_.has_state; }
91
92 // Set has_state - for components that need to manually set this
93 void set_has_state(bool state) { this->flags_.has_state = state; }
94
113#ifdef USE_DEVICES
114 // Combine object_id_hash with device_id to ensure uniqueness across devices
115 // Note: device_id is 0 for the main device, so XORing with 0 preserves the original hash
116 // This ensures backward compatibility for existing single-device configurations
117 return this->get_object_id_hash() ^ this->get_device_id();
118#else
119 // Without devices, just use object_id_hash as before
120 return this->get_object_id_hash();
121#endif
122 }
123
124 protected:
125 friend class api::APIConnection;
126 friend struct web_server::UrlMatch;
127
128 // Get object_id as StringRef when it's static (for API usage)
129 // Returns empty StringRef if object_id is dynamic (needs allocation)
131
132 void calc_object_id_();
133
135 bool is_object_id_dynamic_() const;
136
138 const char *object_id_c_str_{nullptr};
139#ifdef USE_ENTITY_ICON
140 const char *icon_c_str_{nullptr};
141#endif
142 uint32_t object_id_hash_{};
143#ifdef USE_DEVICES
145#endif
146
147 // Bit-packed flags to save memory (1 byte instead of 5)
148 struct EntityFlags {
149 uint8_t has_own_name : 1;
150 uint8_t internal : 1;
152 uint8_t has_state : 1;
153 uint8_t entity_category : 2; // Supports up to 4 categories
154 uint8_t reserved : 2; // Reserved for future use
156};
157
158class EntityBase_DeviceClass { // NOLINT(readability-identifier-naming)
159 public:
161 ESPDEPRECATED("Use get_device_class_ref() instead for better performance (avoids string copy). Will be removed in "
162 "ESPHome 2026.5.0",
163 "2025.11.0")
164 std::string get_device_class();
166 void set_device_class(const char *device_class);
169 static constexpr auto EMPTY_STRING = StringRef::from_lit("");
170 return this->device_class_ == nullptr ? EMPTY_STRING : StringRef(this->device_class_);
171 }
172
173 protected:
174 const char *device_class_{nullptr};
175};
176
177class EntityBase_UnitOfMeasurement { // NOLINT(readability-identifier-naming)
178 public:
180 ESPDEPRECATED("Use get_unit_of_measurement_ref() instead for better performance (avoids string copy). Will be "
181 "removed in ESPHome 2026.5.0",
182 "2025.11.0")
183 std::string get_unit_of_measurement();
185 void set_unit_of_measurement(const char *unit_of_measurement);
188 static constexpr auto EMPTY_STRING = StringRef::from_lit("");
189 return this->unit_of_measurement_ == nullptr ? EMPTY_STRING : StringRef(this->unit_of_measurement_);
190 }
191
192 protected:
193 const char *unit_of_measurement_{nullptr};
194};
195
200template<typename T> class StatefulEntityBase : public EntityBase {
201 public:
202 virtual bool has_state() const { return this->state_.has_value(); }
203 virtual const T &get_state() const { return this->state_.value(); }
204 virtual T get_state_default(T default_value) const { return this->state_.value_or(default_value); }
205 void invalidate_state() { this->set_state_({}); }
206
207 void add_full_state_callback(std::function<void(optional<T> previous, optional<T> current)> &&callback) {
208 if (this->full_state_callbacks_ == nullptr)
209 this->full_state_callbacks_ = new CallbackManager<void(optional<T> previous, optional<T> current)>(); // NOLINT
210 this->full_state_callbacks_->add(std::move(callback));
211 }
212 void add_on_state_callback(std::function<void(T)> &&callback) {
213 if (this->state_callbacks_ == nullptr)
214 this->state_callbacks_ = new CallbackManager<void(T)>(); // NOLINT
215 this->state_callbacks_->add(std::move(callback));
216 }
217
218 void set_trigger_on_initial_state(bool trigger_on_initial_state) {
219 this->trigger_on_initial_state_ = trigger_on_initial_state;
220 }
221
222 protected:
231 if (this->state_ != state) {
232 // call the full state callbacks with the previous and new state
233 if (this->full_state_callbacks_ != nullptr)
234 this->full_state_callbacks_->call(this->state_, state);
235 // trigger legacy callbacks only if the new state is valid and either the trigger on initial state is enabled or
236 // the previous state was valid
237 auto had_state = this->has_state();
238 this->state_ = state;
239 if (this->state_callbacks_ != nullptr && state.has_value() && (this->trigger_on_initial_state_ || had_state))
240 this->state_callbacks_->call(state.value());
241 return true;
242 }
243 return false;
244 }
246 // callbacks with full state and previous state
249};
250} // 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:86
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:48
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:59
StringRef get_icon_ref() const
Definition entity_base.h:69
uint32_t get_device_id() const
Definition entity_base.h:80
bool is_disabled_by_default() const
Definition entity_base.h:54
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:55
void set_has_state(bool state)
Definition entity_base.h:93
const char * icon_c_str_
bool has_state() const
Definition entity_base.h:90
std::string get_object_id() const
EntityCategory get_entity_category() const
Definition entity_base.h:58
StringRef get_object_id_ref_for_api_() const
void set_internal(bool internal)
Definition entity_base.h:49
An entity that has a state.
virtual const T & get_state() const
bool set_state_(const optional< T > &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
Internal helper struct that is used to parse incoming URLs.
Definition web_server.h:37