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