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