ESPHome 2026.11.0-dev
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>
5#include "preferences.h"
6#include "esphome/core/log.h"
7#include <zephyr/settings/settings.h>
8#include <sys/types.h>
9#include <cinttypes>
10#include <cstring>
11
12namespace esphome::zephyr {
13
14ESPHOME_LOG_TAG(TAG, "preferences");
15
16bool ZephyrPreferenceBackend::save(const uint8_t *data, size_t len) {
17 this->data.resize(len);
18 std::memcpy(this->data.data(), data, len);
19 ESP_LOGVV(TAG, "save key: %" PRIu32 ", len: %zu", this->type_, len);
20 return true;
21}
22
23bool ZephyrPreferenceBackend::load(uint8_t *data, size_t len) {
24 if (len != this->data.size()) {
25 char key_buf[KEY_BUFFER_SIZE];
26 this->format_key(key_buf, sizeof(key_buf));
27 if (this->data.empty()) {
28 ESP_LOGV(TAG, "setting key %s not found", key_buf);
29 } else {
30 ESP_LOGE(TAG, "size of setting key %s changed, from: %zu, to: %zu", key_buf, this->data.size(), len);
31 }
32 return false;
33 }
34 std::memcpy(data, this->data.data(), len);
35 ESP_LOGVV(TAG, "load key: %" PRIu32 ", len: %zu", this->type_, len);
36 return true;
37}
38
40 int err = settings_subsys_init();
41 if (err) {
42 ESP_LOGE(TAG, "Failed to initialize settings subsystem, err: %d", err);
43 return;
44 }
45
46 static struct settings_handler settings_cb = {
47 .name = ESPHOME_SETTINGS_KEY,
48 .h_set = load_setting,
49 .h_export = export_settings,
50 };
51
52 err = settings_register(&settings_cb);
53 if (err) {
54 ESP_LOGE(TAG, "setting_register failed, err, %d", err);
55 return;
56 }
57
58 err = settings_load_subtree(ESPHOME_SETTINGS_KEY);
59 if (err) {
60 ESP_LOGE(TAG, "Cannot load settings, err: %d", err);
61 return;
62 }
63 ESP_LOGD(TAG, "Loaded %zu settings.", this->backends_.size());
64}
65
67 for (auto *backend : this->backends_) {
68 if (backend->get_type() == type) {
69 return backend;
70 }
71 }
72 return nullptr;
73}
74
76 if (auto *backend = this->find_backend_(type)) {
77 return ESPPreferenceObject(backend);
78 }
79 auto *pref = new ZephyrPreferenceBackend(type); // NOLINT(cppcoreguidelines-owning-memory)
80 char key_buf[KEY_BUFFER_SIZE];
81 pref->format_key(key_buf, sizeof(key_buf));
82 ESP_LOGD(TAG, "Add new setting %s.", key_buf);
83 this->backends_.push_back(pref);
84 return ESPPreferenceObject(pref);
85}
86
87bool ZephyrPreferences::load_from_key(uint32_t type, uint8_t *data, size_t len) {
88 // Stored settings are preloaded into backends_ at boot by settings_load_subtree(),
89 // so a key with no registered backend has no stored data.
90 auto *backend = this->find_backend_(type);
91 return backend != nullptr && backend->load(data, len);
92}
93
95 ESP_LOGV(TAG, "Save settings");
96 int err = settings_save();
97 if (err) {
98 ESP_LOGE(TAG, "Cannot save settings, err: %d", err);
99 return false;
100 }
101 return true;
102}
103
105 ESP_LOGD(TAG, "Reset settings");
106 for (auto *backend : this->backends_) {
107 // save empty delete data
108 backend->data.clear();
109 }
110 this->sync();
111 return true;
112}
113
114int ZephyrPreferences::load_setting(const char *name, size_t len, settings_read_cb read_cb, void *cb_arg) {
115 auto type = parse_hex<uint32_t>(name);
116 if (!type.has_value()) {
117 std::string full_name(ESPHOME_SETTINGS_KEY);
118 full_name += '/';
119 full_name += name;
120 // Delete unusable keys. Otherwise it will stay in flash forever.
121 settings_delete(full_name.c_str());
122 return 1;
123 }
124 std::vector<uint8_t> data(len);
125 ssize_t read_len = read_cb(cb_arg, data.data(), len);
126 if (read_len != static_cast<ssize_t>(len)) {
127 ESP_LOGE(TAG, "Cannot read setting %s, got %d of %zu", name, static_cast<int>(read_len), len);
128 return 0;
129 }
130
131 ESP_LOGD(TAG, "load setting, name: %s(%" PRIu32 "), len %zu", name, *type, len);
132 auto *pref = new ZephyrPreferenceBackend(*type, std::move(data)); // NOLINT(cppcoreguidelines-owning-memory)
133 get_preferences()->backends_.push_back(pref);
134 return 0;
135}
136
137int ZephyrPreferences::export_settings(int (*cb)(const char *name, const void *value, size_t val_len)) {
138 int first_err = 0;
139 for (auto *backend : get_preferences()->backends_) {
140 char name[KEY_BUFFER_SIZE];
141 backend->format_key(name, sizeof(name));
142 int err = cb(name, backend->data.data(), backend->data.size());
143 if (err) {
144 ESP_LOGE(TAG, "Cannot save setting %s, err %d", name, err);
145 if (first_err == 0) {
146 first_err = err;
147 }
148 continue;
149 }
150 ESP_LOGV(TAG, "save in flash, name %s, len %zu", name, backend->data.size());
151 }
152 return first_err;
153}
154
155static ZephyrPreferences s_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
156
157ZephyrPreferences *get_preferences() { return &s_preferences; }
158
160 global_preferences = &s_preferences;
161 s_preferences.open();
162}
163
164} // namespace esphome::zephyr
165
166namespace esphome {
167ESPPreferences *global_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
168} // namespace esphome
169
170#endif
171#endif
bool load(uint8_t *data, size_t len)
void format_key(char *buf, size_t size) const
bool save(const uint8_t *data, size_t len)
bool load_from_key(uint32_t type, uint8_t *data, size_t len)
One-shot read of a stored preference by key, without allocating or registering a backend.
ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash)
Definition preferences.h:15
static int load_setting(const char *name, size_t len, settings_read_cb read_cb, void *cb_arg)
std::vector< ZephyrPreferenceBackend * > backends_
Definition preferences.h:26
ZephyrPreferenceBackend * find_backend_(uint32_t type)
static int export_settings(int(*cb)(const char *name, const void *value, size_t val_len))
uint8_t type
__int64 ssize_t
Definition httplib.h:178
ESPHOME_LOG_TAG(TAG, "zephyr")
ZephyrPreferences * get_preferences()
Preferences ESPPreferences
Definition preferences.h:43
const void size_t len
Definition hal.h:68
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:370
ESPPreferences * global_preferences
static void uint32_t
uint16_t length
Definition tt21100.cpp:0