ESPHome 2026.1.4
Loading...
Searching...
No Matches
preferences.cpp
Go to the documentation of this file.
1#ifdef USE_ZEPHYR
2#ifdef CONFIG_SETTINGS
3
4#include <zephyr/kernel.h>
6#include "esphome/core/log.h"
7#include <zephyr/settings/settings.h>
8
9namespace esphome {
10namespace zephyr {
11
12static const char *const TAG = "zephyr.preferences";
13
14#define ESPHOME_SETTINGS_KEY "esphome"
15
16class ZephyrPreferenceBackend : public ESPPreferenceBackend {
17 public:
18 ZephyrPreferenceBackend(uint32_t type) { this->type_ = type; }
19 ZephyrPreferenceBackend(uint32_t type, std::vector<uint8_t> &&data) : data(std::move(data)) { this->type_ = type; }
20
21 bool save(const uint8_t *data, size_t len) override {
22 this->data.resize(len);
23 std::memcpy(this->data.data(), data, len);
24 ESP_LOGVV(TAG, "save key: %u, len: %d", this->type_, len);
25 return true;
26 }
27
28 bool load(uint8_t *data, size_t len) override {
29 if (len != this->data.size()) {
30 ESP_LOGE(TAG, "size of setting key %s changed, from: %u, to: %u", get_key().c_str(), this->data.size(), len);
31 return false;
32 }
33 std::memcpy(data, this->data.data(), len);
34 ESP_LOGVV(TAG, "load key: %u, len: %d", this->type_, len);
35 return true;
36 }
37
38 uint32_t get_type() const { return this->type_; }
39 std::string get_key() const { return str_sprintf(ESPHOME_SETTINGS_KEY "/%" PRIx32, this->type_); }
40
41 std::vector<uint8_t> data;
42
43 protected:
44 uint32_t type_ = 0;
45};
46
47class ZephyrPreferences : public ESPPreferences {
48 public:
49 void open() {
50 int err = settings_subsys_init();
51 if (err) {
52 ESP_LOGE(TAG, "Failed to initialize settings subsystem, err: %d", err);
53 return;
54 }
55
56 static struct settings_handler settings_cb = {
57 .name = ESPHOME_SETTINGS_KEY,
58 .h_set = load_setting,
59 .h_export = export_settings,
60 };
61
62 err = settings_register(&settings_cb);
63 if (err) {
64 ESP_LOGE(TAG, "setting_register failed, err, %d", err);
65 return;
66 }
67
68 err = settings_load_subtree(ESPHOME_SETTINGS_KEY);
69 if (err) {
70 ESP_LOGE(TAG, "Cannot load settings, err: %d", err);
71 return;
72 }
73 ESP_LOGD(TAG, "Loaded %u settings.", this->backends_.size());
74 }
75
76 ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash) override {
77 return make_preference(length, type);
78 }
79
80 ESPPreferenceObject make_preference(size_t length, uint32_t type) override {
81 for (auto *backend : this->backends_) {
82 if (backend->get_type() == type) {
83 return ESPPreferenceObject(backend);
84 }
85 }
86 printf("type %u size %u\n", type, this->backends_.size());
87 auto *pref = new ZephyrPreferenceBackend(type); // NOLINT(cppcoreguidelines-owning-memory)
88 ESP_LOGD(TAG, "Add new setting %s.", pref->get_key().c_str());
89 this->backends_.push_back(pref);
90 return ESPPreferenceObject(pref);
91 }
92
93 bool sync() override {
94 ESP_LOGD(TAG, "Save settings");
95 int err = settings_save();
96 if (err) {
97 ESP_LOGE(TAG, "Cannot save settings, err: %d", err);
98 return false;
99 }
100 return true;
101 }
102
103 bool reset() override {
104 ESP_LOGD(TAG, "Reset settings");
105 for (auto *backend : this->backends_) {
106 // save empty delete data
107 backend->data.clear();
108 }
109 sync();
110 return true;
111 }
112
113 protected:
114 std::vector<ZephyrPreferenceBackend *> backends_;
115
116 static int load_setting(const char *name, size_t len, settings_read_cb read_cb, void *cb_arg) {
117 auto type = parse_hex<uint32_t>(name);
118 if (!type.has_value()) {
119 std::string full_name(ESPHOME_SETTINGS_KEY);
120 full_name += "/";
121 full_name += name;
122 // Delete unusable keys. Otherwise it will stay in flash forever.
123 settings_delete(full_name.c_str());
124 return 1;
125 }
126 std::vector<uint8_t> data(len);
127 int err = read_cb(cb_arg, data.data(), len);
128
129 ESP_LOGD(TAG, "load setting, name: %s(%u), len %u, err %u", name, *type, len, err);
130 auto *pref = new ZephyrPreferenceBackend(*type, std::move(data)); // NOLINT(cppcoreguidelines-owning-memory)
131 static_cast<ZephyrPreferences *>(global_preferences)->backends_.push_back(pref);
132 return 0;
133 }
134
135 static int export_settings(int (*cb)(const char *name, const void *value, size_t val_len)) {
136 for (auto *backend : static_cast<ZephyrPreferences *>(global_preferences)->backends_) {
137 auto name = backend->get_key();
138 int err = cb(name.c_str(), backend->data.data(), backend->data.size());
139 ESP_LOGD(TAG, "save in flash, name %s, len %u, err %d", name.c_str(), backend->data.size(), err);
140 }
141 return 0;
142 }
143};
144
146 auto *prefs = new ZephyrPreferences(); // NOLINT(cppcoreguidelines-owning-memory)
147 global_preferences = prefs;
148 prefs->open();
149}
150
151} // namespace zephyr
152
153ESPPreferences *global_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
154
155} // namespace esphome
156
157#endif
158#endif
uint16_t type
uint16_t reset
Definition ina226.h:5
const char *const TAG
Definition spi.cpp:7
num_t cb(num_t x)
Definition sun.cpp:30
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
std::string size_t len
Definition helpers.h:595
size_t parse_hex(const char *str, size_t length, uint8_t *data, size_t count)
Parse bytes from a hex-encoded string into a byte array.
Definition helpers.cpp:275
ESPPreferences * global_preferences
std::string str_sprintf(const char *fmt,...)
Definition helpers.cpp:223
uint16_t sync
Definition sun_gtil2.cpp:0
uint16_t length
Definition tt21100.cpp:0