ESPHome 2025.6.0
Loading...
Searching...
No Matches
globals_component.h
Go to the documentation of this file.
1#pragma once
2
6#include <cstring>
7
8namespace esphome {
9namespace globals {
10
11template<typename T> class GlobalsComponent : public Component {
12 public:
13 using value_type = T;
14 explicit GlobalsComponent() = default;
15 explicit GlobalsComponent(T initial_value) : value_(initial_value) {}
16 explicit GlobalsComponent(std::array<typename std::remove_extent<T>::type, std::extent<T>::value> initial_value) {
17 memcpy(this->value_, initial_value.data(), sizeof(T));
18 }
19
20 T &value() { return this->value_; }
21 void setup() override {}
22
23 protected:
24 T value_{};
25};
26
27template<typename T> class RestoringGlobalsComponent : public Component {
28 public:
29 using value_type = T;
30 explicit RestoringGlobalsComponent() = default;
31 explicit RestoringGlobalsComponent(T initial_value) : value_(initial_value) {}
33 std::array<typename std::remove_extent<T>::type, std::extent<T>::value> initial_value) {
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 loop() 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 Component {
70 public:
71 using value_type = T;
72 explicit RestoringGlobalStringComponent() = default;
73 explicit RestoringGlobalStringComponent(T initial_value) { this->value_ = initial_value; }
75 std::array<typename std::remove_extent<T>::type, std::extent<T>::value> initial_value) {
76 memcpy(this->value_, initial_value.data(), sizeof(T));
77 }
78
79 T &value() { return this->value_; }
80
81 void setup() override {
82 char temp[SZ];
83 this->rtc_ = global_preferences->make_preference<uint8_t[SZ]>(1944399030U ^ this->name_hash_);
84 bool hasdata = this->rtc_.load(&temp);
85 if (hasdata) {
86 this->value_.assign(temp + 1, temp[0]);
87 }
88 this->last_checked_value_.assign(this->value_);
89 }
90
91 float get_setup_priority() const override { return setup_priority::HARDWARE; }
92
93 void loop() override { store_value_(); }
94
95 void on_shutdown() override { store_value_(); }
96
97 void set_name_hash(uint32_t name_hash) { this->name_hash_ = name_hash; }
98
99 protected:
101 int diff = this->value_.compare(this->last_checked_value_);
102 if (diff != 0) {
103 // Make it into a length prefixed thing
104 unsigned char temp[SZ];
105
106 // If string is bigger than the allocation, do not save it.
107 int size = this->value_.size();
108 // Less than, not less than or equal, SZ includes the length byte.
109 if (size < SZ) {
110 memcpy(temp + 1, this->value_.c_str(), size);
111 // SZ should be pre checked at the schema level, it can't go past the char range.
112 temp[0] = ((unsigned char) size);
113 this->rtc_.save(&temp);
114 }
115 // Always update last_checked_value_ to match current value, even for oversized strings.
116 // This prevents redundant size checks on every loop iteration when a string remains oversized.
117 // Without this, the diff != 0 check would pass repeatedly for the same oversized string,
118 // wasting CPU cycles on size comparisons.
119 this->last_checked_value_.assign(this->value_);
120 }
121 }
122
125 uint32_t name_hash_{};
127};
128
129template<class C, typename... Ts> class GlobalVarSetAction : public Action<Ts...> {
130 public:
131 explicit GlobalVarSetAction(C *parent) : parent_(parent) {}
132
133 using T = typename C::value_type;
134
136
137 void play(Ts... x) override { this->parent_->value() = this->value_.value(x...); }
138
139 protected:
141};
142
143template<typename T> T &id(GlobalsComponent<T> *value) { return value->value(); }
144template<typename T> T &id(RestoringGlobalsComponent<T> *value) { return value->value(); }
145template<typename T, uint8_t SZ> T &id(RestoringGlobalStringComponent<T, SZ> *value) { return value->value(); }
146
147} // namespace globals
148} // namespace esphome
bool save(const T *src)
Definition preferences.h:21
virtual ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash)=0
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)
T & id(GlobalsComponent< T > *value)
const float HARDWARE
For components that deal with hardware and are very important like GPIO switch.
Definition component.cpp:19
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
ESPPreferences * global_preferences
uint16_t x
Definition tt21100.cpp:5