ESPHome 2026.2.4
Loading...
Searching...
No Matches
globals_component.h
Go to the documentation of this file.
1#pragma once
2
6#include <cstring>
7
8namespace esphome::globals {
9
10template<typename T> class GlobalsComponent : public Component {
11 public:
12 using value_type = T;
13 explicit GlobalsComponent() = default;
14 explicit GlobalsComponent(T initial_value) : value_(initial_value) {}
15 explicit GlobalsComponent(std::array<typename std::remove_extent<T>::type, std::extent<T>::value> initial_value) {
16 memcpy(this->value_, initial_value.data(), sizeof(T));
17 }
18
19 T &value() { return this->value_; }
20 void setup() override {}
21
22 protected:
23 T value_{};
24};
25
26template<typename T> class RestoringGlobalsComponent : public PollingComponent {
27 public:
28 using value_type = T;
30 explicit RestoringGlobalsComponent(T initial_value) : PollingComponent(1000), value_(initial_value) {}
32 std::array<typename std::remove_extent<T>::type, std::extent<T>::value> initial_value)
33 : PollingComponent(1000) {
34 memcpy(this->value_, initial_value.data(), sizeof(T));
35 }
36
37 T &value() { return this->value_; }
38
39 void setup() override {
40 this->rtc_ = global_preferences->make_preference<T>(1944399030U ^ this->name_hash_);
41 this->rtc_.load(&this->value_);
42 memcpy(&this->last_checked_value_, &this->value_, sizeof(T));
43 }
44
45 float get_setup_priority() const override { return setup_priority::HARDWARE; }
46
47 void update() override { store_value_(); }
48
49 void on_shutdown() override { store_value_(); }
50
51 void set_name_hash(uint32_t name_hash) { this->name_hash_ = name_hash; }
52
53 protected:
54 void store_value_() {
55 int diff = memcmp(&this->value_, &this->last_checked_value_, sizeof(T));
56 if (diff != 0) {
57 this->rtc_.save(&this->value_);
58 memcpy(&this->last_checked_value_, &this->value_, sizeof(T));
59 }
60 }
61
62 T value_{};
64 uint32_t name_hash_{};
66};
67
68// Use with string or subclasses of strings
69template<typename T, uint8_t SZ> class RestoringGlobalStringComponent : public PollingComponent {
70 public:
71 using value_type = T;
73 explicit RestoringGlobalStringComponent(T initial_value) : PollingComponent(1000) { this->value_ = initial_value; }
75 std::array<typename std::remove_extent<T>::type, std::extent<T>::value> initial_value)
76 : PollingComponent(1000) {
77 memcpy(this->value_, initial_value.data(), sizeof(T));
78 }
79
80 T &value() { return this->value_; }
81
82 void setup() override {
83 char temp[SZ];
84 this->rtc_ = global_preferences->make_preference<uint8_t[SZ]>(1944399030U ^ this->name_hash_);
85 bool hasdata = this->rtc_.load(&temp);
86 if (hasdata) {
87 this->value_.assign(temp + 1, temp[0]);
88 }
89 this->last_checked_value_.assign(this->value_);
90 }
91
92 float get_setup_priority() const override { return setup_priority::HARDWARE; }
93
94 void update() override { store_value_(); }
95
96 void on_shutdown() override { store_value_(); }
97
98 void set_name_hash(uint32_t name_hash) { this->name_hash_ = name_hash; }
99
100 protected:
102 int diff = this->value_.compare(this->last_checked_value_);
103 if (diff != 0) {
104 // Make it into a length prefixed thing
105 unsigned char temp[SZ];
106
107 // If string is bigger than the allocation, do not save it.
108 int size = this->value_.size();
109 // Less than, not less than or equal, SZ includes the length byte.
110 if (size < SZ) {
111 memcpy(temp + 1, this->value_.c_str(), size);
112 // SZ should be pre checked at the schema level, it can't go past the char range.
113 temp[0] = ((unsigned char) size);
114 this->rtc_.save(&temp);
115 }
116 // Always update last_checked_value_ to match current value, even for oversized strings.
117 // This prevents redundant size checks on every loop iteration when a string remains oversized.
118 // Without this, the diff != 0 check would pass repeatedly for the same oversized string,
119 // wasting CPU cycles on size comparisons.
120 this->last_checked_value_.assign(this->value_);
121 }
122 }
123
126 uint32_t name_hash_{};
128};
129
130template<class C, typename... Ts> class GlobalVarSetAction : public Action<Ts...> {
131 public:
132 explicit GlobalVarSetAction(C *parent) : parent_(parent) {}
133
134 using T = typename C::value_type;
135
137
138 void play(const Ts &...x) override { this->parent_->value() = this->value_.value(x...); }
139
140 protected:
142};
143
144template<typename T> T &id(GlobalsComponent<T> *value) { return value->value(); }
145template<typename T> T &id(RestoringGlobalsComponent<T> *value) { return value->value(); }
146template<typename T, uint8_t SZ> T &id(RestoringGlobalStringComponent<T, SZ> *value) { return value->value(); }
147
148} // namespace esphome::globals
bool save(const T *src)
Definition preferences.h:21
virtual ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash)=0
This class simplifies creating components that periodically check a state.
Definition component.h:512
void play(const Ts &...x) override
GlobalsComponent(std::array< typename std::remove_extent< T >::type, std::extent< T >::value > initial_value)
RestoringGlobalStringComponent(std::array< typename std::remove_extent< T >::type, std::extent< T >::value > initial_value)
RestoringGlobalsComponent(std::array< typename std::remove_extent< T >::type, std::extent< T >::value > initial_value)
uint16_t id
const float HARDWARE
For components that deal with hardware and are very important like GPIO switch.
Definition component.cpp:83
size_t size
Definition helpers.h:729
ESPPreferences * global_preferences
uint16_t x
Definition tt21100.cpp:5