#pragma once #include "esphome/core/component.h" #include "esphome/core/automation.h" #include "esphome/core/helpers.h" namespace esphome { namespace globals { template class GlobalsComponent : public Component { public: using value_type = T; explicit GlobalsComponent() = default; explicit GlobalsComponent(T initial_value) : value_(initial_value) {} explicit GlobalsComponent(std::array::type, std::extent::value> initial_value) { memcpy(this->value_, initial_value.data(), sizeof(T)); } T &value() { return this->value_; } void setup() override { if (this->restore_value_) { this->rtc_ = global_preferences.make_preference(1944399030U ^ this->name_hash_); this->rtc_.load(&this->value_); } memcpy(&this->prev_value_, &this->value_, sizeof(T)); } float get_setup_priority() const override { return setup_priority::HARDWARE; } void loop() override { if (this->restore_value_) { int diff = memcmp(&this->value_, &this->prev_value_, sizeof(T)); if (diff != 0) { this->rtc_.save(&this->value_); memcpy(&this->prev_value_, &this->value_, sizeof(T)); } } } void set_restore_value(uint32_t name_hash) { this->restore_value_ = true; this->name_hash_ = name_hash; } protected: T value_{}; T prev_value_{}; bool restore_value_{false}; uint32_t name_hash_{}; ESPPreferenceObject rtc_; }; template class GlobalVarSetAction : public Action { public: explicit GlobalVarSetAction(C *parent) : parent_(parent) {} using T = typename C::value_type; TEMPLATABLE_VALUE(T, value); void play(Ts... x) override { this->parent_->value() = this->value_.value(x...); } protected: C *parent_; }; template T &id(GlobalsComponent *value) { return value->value(); } } // namespace globals } // namespace esphome