ESPHome 2025.9.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
25
26// The generic Entity base class that provides an interface common to all Entities.
28 public:
29 // Get/set the name of this Entity
30 const StringRef &get_name() const;
31 void set_name(const char *name);
32
33 // Get whether this Entity has its own name or it should use the device friendly_name.
34 bool has_own_name() const { return this->flags_.has_own_name; }
35
36 // Get the sanitized name of this Entity as an ID.
37 std::string get_object_id() const;
38 void set_object_id(const char *object_id);
39
40 // Get the unique Object ID of this Entity
41 uint32_t get_object_id_hash();
42
43 // Get/set whether this Entity should be hidden outside ESPHome
44 bool is_internal() const { return this->flags_.internal; }
45 void set_internal(bool internal) { this->flags_.internal = internal; }
46
47 // Check if this object is declared to be disabled by default.
48 // That means that when the device gets added to Home Assistant (or other clients) it should
49 // not be added to the default view by default, and a user action is necessary to manually add it.
50 bool is_disabled_by_default() const { return this->flags_.disabled_by_default; }
51 void set_disabled_by_default(bool disabled_by_default) { this->flags_.disabled_by_default = disabled_by_default; }
52
53 // Get/set the entity category.
55 void set_entity_category(EntityCategory entity_category) {
56 this->flags_.entity_category = static_cast<uint8_t>(entity_category);
57 }
58
59 // Get/set this entity's icon
60 std::string get_icon() const;
61 void set_icon(const char *icon);
63 static constexpr auto EMPTY_STRING = StringRef::from_lit("");
64#ifdef USE_ENTITY_ICON
65 return this->icon_c_str_ == nullptr ? EMPTY_STRING : StringRef(this->icon_c_str_);
66#else
67 return EMPTY_STRING;
68#endif
69 }
70
71#ifdef USE_DEVICES
72 // Get/set this entity's device id
73 uint32_t get_device_id() const {
74 if (this->device_ == nullptr) {
75 return 0; // No device set, return 0
76 }
77 return this->device_->get_device_id();
78 }
79 void set_device(Device *device) { this->device_ = device; }
80#endif
81
82 // Check if this entity has state
83 bool has_state() const { return this->flags_.has_state; }
84
85 // Set has_state - for components that need to manually set this
86 void set_has_state(bool state) { this->flags_.has_state = state; }
87
106#ifdef USE_DEVICES
107 // Combine object_id_hash with device_id to ensure uniqueness across devices
108 // Note: device_id is 0 for the main device, so XORing with 0 preserves the original hash
109 // This ensures backward compatibility for existing single-device configurations
110 return this->get_object_id_hash() ^ this->get_device_id();
111#else
112 // Without devices, just use object_id_hash as before
113 return this->get_object_id_hash();
114#endif
115 }
116
117 protected:
118 friend class api::APIConnection;
119
120 // Get object_id as StringRef when it's static (for API usage)
121 // Returns empty StringRef if object_id is dynamic (needs allocation)
123
126 virtual uint32_t hash_base() { return 0L; }
127 void calc_object_id_();
128
130 bool is_object_id_dynamic_() const;
131
133 const char *object_id_c_str_{nullptr};
134#ifdef USE_ENTITY_ICON
135 const char *icon_c_str_{nullptr};
136#endif
137 uint32_t object_id_hash_{};
138#ifdef USE_DEVICES
140#endif
141
142 // Bit-packed flags to save memory (1 byte instead of 5)
143 struct EntityFlags {
144 uint8_t has_own_name : 1;
145 uint8_t internal : 1;
147 uint8_t has_state : 1;
148 uint8_t entity_category : 2; // Supports up to 4 categories
149 uint8_t reserved : 2; // Reserved for future use
151};
152
153class EntityBase_DeviceClass { // NOLINT(readability-identifier-naming)
154 public:
156 std::string get_device_class();
158 void set_device_class(const char *device_class);
161 static constexpr auto EMPTY_STRING = StringRef::from_lit("");
162 return this->device_class_ == nullptr ? EMPTY_STRING : StringRef(this->device_class_);
163 }
164
165 protected:
166 const char *device_class_{nullptr};
167};
168
169class EntityBase_UnitOfMeasurement { // NOLINT(readability-identifier-naming)
170 public:
172 std::string get_unit_of_measurement();
174 void set_unit_of_measurement(const char *unit_of_measurement);
177 static constexpr auto EMPTY_STRING = StringRef::from_lit("");
178 return this->unit_of_measurement_ == nullptr ? EMPTY_STRING : StringRef(this->unit_of_measurement_);
179 }
180
181 protected:
182 const char *unit_of_measurement_{nullptr};
183};
184
189template<typename T> class StatefulEntityBase : public EntityBase {
190 public:
191 virtual bool has_state() const { return this->state_.has_value(); }
192 virtual const T &get_state() const { return this->state_.value(); }
193 virtual T get_state_default(T default_value) const { return this->state_.value_or(default_value); }
194 void invalidate_state() { this->set_state_({}); }
195
196 void add_full_state_callback(std::function<void(optional<T> previous, optional<T> current)> &&callback) {
197 if (this->full_state_callbacks_ == nullptr)
198 this->full_state_callbacks_ = new CallbackManager<void(optional<T> previous, optional<T> current)>(); // NOLINT
199 this->full_state_callbacks_->add(std::move(callback));
200 }
201 void add_on_state_callback(std::function<void(T)> &&callback) {
202 if (this->state_callbacks_ == nullptr)
203 this->state_callbacks_ = new CallbackManager<void(T)>(); // NOLINT
204 this->state_callbacks_->add(std::move(callback));
205 }
206
207 void set_trigger_on_initial_state(bool trigger_on_initial_state) {
208 this->trigger_on_initial_state_ = trigger_on_initial_state;
209 }
210
211 protected:
220 if (this->state_ != state) {
221 // call the full state callbacks with the previous and new state
222 if (this->full_state_callbacks_ != nullptr)
223 this->full_state_callbacks_->call(this->state_, state);
224 // trigger legacy callbacks only if the new state is valid and either the trigger on initial state is enabled or
225 // the previous state was valid
226 auto had_state = this->has_state();
227 this->state_ = state;
228 if (this->state_callbacks_ != nullptr && state.has_value() && (this->trigger_on_initial_state_ || had_state))
229 this->state_callbacks_->call(state.value());
230 return true;
231 }
232 return false;
233 }
235 // callbacks with full state and previous state
238};
239} // namespace esphome
uint32_t get_device_id()
Definition device.h:8
std::string get_device_class()
Get the device class, using the manual override if set.
StringRef get_device_class_ref() const
Get the device class as StringRef.
void set_device_class(const char *device_class)
Manually set the device class.
const char * device_class_
Device class override.
std::string get_unit_of_measurement()
Get the unit of measurement, using the manual override if set.
const char * unit_of_measurement_
Unit of measurement override.
void set_unit_of_measurement(const char *unit_of_measurement)
Manually set the unit of measurement.
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:79
void set_object_id(const char *object_id)
bool has_own_name() const
Definition entity_base.h:34
bool is_internal() const
Definition entity_base.h:44
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:55
StringRef get_icon_ref() const
Definition entity_base.h:62
std::string get_icon() const
uint32_t get_device_id() const
Definition entity_base.h:73
bool is_disabled_by_default() const
Definition entity_base.h:50
bool is_object_id_dynamic_() const
Check if the object_id is dynamic (changes with MAC suffix)
void set_name(const char *name)
void set_icon(const char *icon)
void set_disabled_by_default(bool disabled_by_default)
Definition entity_base.h:51
void set_has_state(bool state)
Definition entity_base.h:86
const char * icon_c_str_
virtual uint32_t hash_base()
The hash_base() function has been deprecated.
bool has_state() const
Definition entity_base.h:83
std::string get_object_id() const
EntityCategory get_entity_category() const
Definition entity_base.h:54
StringRef get_object_id_ref_for_api_() const
void set_internal(bool internal)
Definition entity_base.h:45
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:21
@ ENTITY_CATEGORY_CONFIG
Definition entity_base.h:22
@ ENTITY_CATEGORY_DIAGNOSTIC
Definition entity_base.h:23