ESPHome 2026.10.2
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
28template<typename T> class RestoringGlobalsComponent : public PollingComponent {
29 public:
30 using value_type = T;
32 explicit RestoringGlobalsComponent(T initial_value) : PollingComponent(1000), value_(initial_value) {}
34 std::array<typename std::remove_extent<T>::type, std::extent<T>::value> initial_value)
35 : PollingComponent(1000) {
36 memcpy(this->value_, initial_value.data(), sizeof(T));
37 }
38
39 T &value() { return this->value_; }
40
41 void setup() override {
42 this->rtc_ = global_preferences->make_preference<T>(1944399030U ^ this->name_hash_);
43 this->rtc_.load(&this->value_);
44 memcpy(&this->last_checked_value_, &this->value_, sizeof(T));
45 }
46
47 float get_setup_priority() const override { return setup_priority::HARDWARE; }
48
49 void update() override { store_value_(); }
50
51 void on_shutdown() override { store_value_(); }
52
53 void set_name_hash(uint32_t name_hash) { this->name_hash_ = name_hash; }
54
55 protected:
56 void store_value_() {
57 int diff = memcmp(&this->value_, &this->last_checked_value_, sizeof(T));
58 if (diff != 0) {
59 this->rtc_.save(&this->value_);
60 memcpy(&this->last_checked_value_, &this->value_, sizeof(T));
61 }
62 }
63
64 T value_{};
68};
69
70// Use with string or subclasses of strings
71template<typename T, uint8_t SZ> class RestoringGlobalStringComponent : public PollingComponent {
72 public:
73 using value_type = T;
75 explicit RestoringGlobalStringComponent(T initial_value) : PollingComponent(1000) { this->value_ = initial_value; }
77 std::array<typename std::remove_extent<T>::type, std::extent<T>::value> initial_value)
78 : PollingComponent(1000) {
79 memcpy(this->value_, initial_value.data(), sizeof(T));
80 }
81
82 T &value() { return this->value_; }
83
84 void setup() override {
85 char temp[SZ];
86 this->rtc_ = global_preferences->make_preference<uint8_t[SZ]>(1944399030U ^ this->name_hash_);
87 bool hasdata = this->rtc_.load(&temp);
88 if (hasdata) {
89 this->value_.assign(temp + 1, static_cast<uint8_t>(temp[0]));
90 }
91 this->last_checked_value_.assign(this->value_);
92 }
93
94 float get_setup_priority() const override { return setup_priority::HARDWARE; }
95
96 void update() override { store_value_(); }
97
98 void on_shutdown() override { store_value_(); }
99
100 void set_name_hash(uint32_t name_hash) { this->name_hash_ = name_hash; }
101
102 protected:
104 int diff = this->value_.compare(this->last_checked_value_);
105 if (diff != 0) {
106 // Make it into a length prefixed thing
107 unsigned char temp[SZ];
108
109 // If string is bigger than the allocation, do not save it.
110 int size = this->value_.size();
111 // Less than, not less than or equal, SZ includes the length byte.
112 if (size < SZ) {
113 memcpy(temp + 1, this->value_.c_str(), size);
114 // SZ should be pre checked at the schema level, it can't go past the char range.
115 temp[0] = ((unsigned char) size);
116 this->rtc_.save(&temp);
117 }
118 // Always update last_checked_value_ to match current value, even for oversized strings.
119 // This prevents redundant size checks on every loop iteration when a string remains oversized.
120 // Without this, the diff != 0 check would pass repeatedly for the same oversized string,
121 // wasting CPU cycles on size comparisons.
122 this->last_checked_value_.assign(this->value_);
123 }
124 }
125
130};
131
132template<typename T> T &id(GlobalsComponent<T> *value) { return value->value(); }
133template<typename T> T &id(RestoringGlobalsComponent<T> *value) { return value->value(); }
134template<typename T, uint8_t SZ> T &id(RestoringGlobalStringComponent<T, SZ> *value) { return value->value(); }
135
136} // namespace esphome::globals
This class simplifies creating components that periodically check a state.
Definition component.h:510
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:33
ESPPreferences * global_preferences
static void uint32_t
ESPPreferenceObject make_preference(size_t, uint32_t, bool)
Definition preferences.h:24