ESPHome  2024.4.1
globals_component.h
Go to the documentation of this file.
1 #pragma once
2 
5 #include "esphome/core/helpers.h"
6 #include <cstring>
7 
8 namespace esphome {
9 namespace globals {
10 
11 template<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 
27 template<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->prev_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->prev_value_, sizeof(T));
56  if (diff != 0) {
57  this->rtc_.save(&this->value_);
58  memcpy(&this->prev_value_, &this->value_, sizeof(T));
59  }
60  }
61 
62  T value_{};
63  T prev_value_{};
64  uint32_t name_hash_{};
66 };
67 
68 // Use with string or subclasses of strings
69 template<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->prev_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:
100  void store_value_() {
101  int diff = this->value_.compare(this->prev_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  // We don't need to waste ram setting prev_value either.
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  this->prev_value_.assign(this->value_);
116  }
117  }
118  }
119 
120  T value_{};
121  T prev_value_{};
122  uint32_t name_hash_{};
124 };
125 
126 template<class C, typename... Ts> class GlobalVarSetAction : public Action<Ts...> {
127  public:
128  explicit GlobalVarSetAction(C *parent) : parent_(parent) {}
129 
130  using T = typename C::value_type;
131 
132  TEMPLATABLE_VALUE(T, value);
133 
134  void play(Ts... x) override { this->parent_->value() = this->value_.value(x...); }
135 
136  protected:
138 };
139 
140 template<typename T> T &id(GlobalsComponent<T> *value) { return value->value(); }
141 template<typename T> T &id(RestoringGlobalsComponent<T> *value) { return value->value(); }
142 template<typename T, uint8_t SZ> T &id(RestoringGlobalStringComponent<T, SZ> *value) { return value->value(); }
143 
144 } // namespace globals
145 } // namespace esphome
uint16_t x
Definition: tt21100.cpp:17
GlobalsComponent(std::array< typename std::remove_extent< T >::type, std::extent< T >::value > initial_value)
ESPPreferences * global_preferences
uint8_t type
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)
const float HARDWARE
For components that deal with hardware and are very important like GPIO switch.
Definition: component.cpp:18
virtual ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash)=0
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
T & id(GlobalsComponent< T > *value)