15 static const char *
const TAG =
"esp32.preferences";
19 std::vector<uint8_t> data;
22 static std::vector<NVSData> s_pending_save;
24 class ESP32PreferenceBackend :
public ESPPreferenceBackend {
28 bool save(
const uint8_t *data,
size_t len)
override {
30 for (
auto &obj : s_pending_save) {
32 obj.data.assign(data, data + len);
38 save.data.assign(data, data + len);
39 s_pending_save.emplace_back(save);
40 ESP_LOGVV(TAG,
"s_pending_save: key: %s, len: %d", key.c_str(),
len);
43 bool load(uint8_t *data,
size_t len)
override {
45 for (
auto &obj : s_pending_save) {
47 if (obj.data.size() !=
len) {
51 memcpy(data, obj.data.data(),
len);
57 esp_err_t err = nvs_get_blob(nvs_handle, key.c_str(),
nullptr, &actual_len);
59 ESP_LOGV(TAG,
"nvs_get_blob('%s'): %s - the key might not be set yet", key.c_str(), esp_err_to_name(err));
62 if (actual_len != len) {
63 ESP_LOGVV(TAG,
"NVS length does not match (%u!=%u)", actual_len, len);
66 err = nvs_get_blob(nvs_handle, key.c_str(), data, &
len);
68 ESP_LOGV(TAG,
"nvs_get_blob('%s') failed: %s", key.c_str(), esp_err_to_name(err));
71 ESP_LOGVV(TAG,
"nvs_get_blob: key: %s, len: %d", key.c_str(),
len);
77 class ESP32Preferences :
public ESPPreferences {
83 esp_err_t err = nvs_open(
"esphome", NVS_READWRITE, &nvs_handle);
87 ESP_LOGW(TAG,
"nvs_open failed: %s - erasing NVS...", esp_err_to_name(err));
92 err = nvs_open(
"esphome", NVS_READWRITE, &nvs_handle);
97 ESPPreferenceObject make_preference(
size_t length, uint32_t
type,
bool in_flash)
override {
98 return make_preference(length, type);
100 ESPPreferenceObject make_preference(
size_t length, uint32_t
type)
override {
101 auto *pref =
new ESP32PreferenceBackend();
102 pref->nvs_handle = nvs_handle;
104 uint32_t keyval =
type;
107 return ESPPreferenceObject(pref);
110 bool sync()
override {
111 if (s_pending_save.empty())
114 ESP_LOGD(TAG,
"Saving %d preferences to flash...", s_pending_save.size());
116 int cached = 0, written = 0, failed = 0;
117 esp_err_t last_err = ESP_OK;
118 std::string last_key{};
121 for (ssize_t i = s_pending_save.size() - 1; i >= 0; i--) {
122 const auto &save = s_pending_save[i];
123 ESP_LOGVV(TAG,
"Checking if NVS data %s has changed", save.key.c_str());
124 if (is_changed(nvs_handle, save)) {
125 esp_err_t err = nvs_set_blob(nvs_handle, save.key.c_str(), save.data.data(), save.data.size());
126 ESP_LOGV(TAG,
"sync: key: %s, len: %d", save.key.c_str(), save.data.size());
128 ESP_LOGV(TAG,
"nvs_set_blob('%s', len=%u) failed: %s", save.key.c_str(), save.data.size(),
129 esp_err_to_name(err));
137 ESP_LOGV(TAG,
"NVS data not changed skipping %s len=%u", save.key.c_str(), save.data.size());
140 s_pending_save.erase(s_pending_save.begin() + i);
142 ESP_LOGD(TAG,
"Saving %d preferences to flash: %d cached, %d written, %d failed", cached + written + failed, cached,
145 ESP_LOGE(TAG,
"Error saving %d preferences to flash. Last error=%s for key=%s", failed, esp_err_to_name(last_err),
150 esp_err_t err = nvs_commit(nvs_handle);
152 ESP_LOGV(TAG,
"nvs_commit() failed: %s", esp_err_to_name(err));
158 bool is_changed(
const uint32_t nvs_handle,
const NVSData &to_save) {
159 NVSData stored_data{};
161 esp_err_t err = nvs_get_blob(nvs_handle, to_save.key.c_str(),
nullptr, &actual_len);
163 ESP_LOGV(TAG,
"nvs_get_blob('%s'): %s - the key might not be set yet", to_save.key.c_str(), esp_err_to_name(err));
166 stored_data.data.resize(actual_len);
167 err = nvs_get_blob(nvs_handle, to_save.key.c_str(), stored_data.data.data(), &actual_len);
169 ESP_LOGV(TAG,
"nvs_get_blob('%s') failed: %s", to_save.key.c_str(), esp_err_to_name(err));
172 return to_save.data != stored_data.data;
175 bool reset()
override {
176 ESP_LOGD(TAG,
"Cleaning up preferences in flash...");
177 s_pending_save.clear();
188 auto *prefs =
new ESP32Preferences();
ESPPreferences * global_preferences
std::string str_sprintf(const char *fmt,...)
Implementation of SPI Controller mode.