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