From 81a070d03d04b83cff2e64c904cbc3e9daef5c01 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Wed, 3 Jul 2019 16:34:40 +0200 Subject: [PATCH] ESP32 Use NVS directly (#659) --- esphome/core/application.h | 2 +- esphome/core/preferences.cpp | 59 +++++++++++++++++++++++++++++------- esphome/core/preferences.h | 8 ++--- esphome/core_config.py | 1 - 4 files changed, 51 insertions(+), 19 deletions(-) diff --git a/esphome/core/application.h b/esphome/core/application.h index e2bf8c0ad9..2014b082e9 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -40,7 +40,7 @@ class Application { void pre_setup(const std::string &name, const char *compilation_time) { this->name_ = name; this->compilation_time_ = compilation_time; - global_preferences.begin(this->name_); + global_preferences.begin(); } #ifdef USE_BINARY_SENSOR diff --git a/esphome/core/preferences.cpp b/esphome/core/preferences.cpp index b975426181..f62a764b7e 100644 --- a/esphome/core/preferences.cpp +++ b/esphome/core/preferences.cpp @@ -1,12 +1,17 @@ #include "esphome/core/preferences.h" #include "esphome/core/log.h" #include "esphome/core/helpers.h" +#include "esphome/core/application.h" #ifdef ARDUINO_ARCH_ESP8266 extern "C" { #include "spi_flash.h" } #endif +#ifdef ARDUINO_ARCH_ESP32 +#include "nvs.h" +#include "nvs_flash.h" +#endif namespace esphome { @@ -165,7 +170,7 @@ ESPPreferences::ESPPreferences() // which will be reset each time OTA occurs : current_offset_(0) {} -void ESPPreferences::begin(const std::string &name) { +void ESPPreferences::begin() { this->flash_storage_ = new uint32_t[ESP8266_FLASH_STORAGE_SIZE]; ESP_LOGVV(TAG, "Loading preferences from flash..."); disable_interrupts(); @@ -219,32 +224,64 @@ bool ESPPreferences::is_prevent_write() { return this->prevent_write_; } #ifdef ARDUINO_ARCH_ESP32 bool ESPPreferenceObject::save_internal_() { + if (global_preferences.nvs_handle_ == 0) + return false; + char key[32]; sprintf(key, "%u", this->offset_); uint32_t len = (this->length_words_ + 1) * 4; - size_t ret = global_preferences.preferences_.putBytes(key, this->data_, len); - if (ret != len) { - ESP_LOGV(TAG, "putBytes failed!"); + esp_err_t err = nvs_set_blob(global_preferences.nvs_handle_, key, this->data_, len); + if (err) { + ESP_LOGV(TAG, "nvs_set_blob('%s', len=%u) failed: %s", key, len, esp_err_to_name(err)); + return false; + } + err = nvs_commit(global_preferences.nvs_handle_); + if (err) { + ESP_LOGV(TAG, "nvs_commit('%s', len=%u) failed: %s", key, len, esp_err_to_name(err)); return false; } return true; } bool ESPPreferenceObject::load_internal_() { + if (global_preferences.nvs_handle_ == 0) + return false; + char key[32]; sprintf(key, "%u", this->offset_); uint32_t len = (this->length_words_ + 1) * 4; - size_t ret = global_preferences.preferences_.getBytes(key, this->data_, len); - if (ret != len) { - ESP_LOGV(TAG, "getBytes failed!"); + + uint32_t actual_len; + esp_err_t err = nvs_get_blob(global_preferences.nvs_handle_, key, nullptr, &actual_len); + if (err) { + ESP_LOGV(TAG, "nvs_get_blob('%s'): %s - the key might not be set yet", key, esp_err_to_name(err)); + return false; + } + if (actual_len != len) { + ESP_LOGVV(TAG, "NVS length does not match. Assuming key changed (%u!=%u)", actual_len, len); + return false; + } + err = nvs_get_blob(global_preferences.nvs_handle_, key, this->data_, &len); + if (err) { + ESP_LOGV(TAG, "nvs_get_blob('%s') failed: %s", key, esp_err_to_name(err)); return false; } return true; } ESPPreferences::ESPPreferences() : current_offset_(0) {} -void ESPPreferences::begin(const std::string &name) { - const std::string key = truncate_string(name, 15); - ESP_LOGV(TAG, "Opening preferences with key '%s'", key.c_str()); - this->preferences_.begin(key.c_str()); +void ESPPreferences::begin() { + auto ns = truncate_string(App.get_name(), 15); + esp_err_t err = nvs_open(ns.c_str(), NVS_READWRITE, &this->nvs_handle_); + if (err) { + ESP_LOGW(TAG, "nvs_open failed: %s - erasing NVS...", esp_err_to_name(err)); + nvs_flash_deinit(); + nvs_flash_erase(); + nvs_flash_init(); + + err = nvs_open(ns.c_str(), NVS_READWRITE, &this->nvs_handle_); + if (err) { + this->nvs_handle_ = 0; + } + } } ESPPreferenceObject ESPPreferences::make_preference(size_t length, uint32_t type, bool in_flash) { diff --git a/esphome/core/preferences.h b/esphome/core/preferences.h index d1ec924af7..bfea4c2336 100644 --- a/esphome/core/preferences.h +++ b/esphome/core/preferences.h @@ -2,10 +2,6 @@ #include -#ifdef ARDUINO_ARCH_ESP32 -#include -#endif - #include "esphome/core/esphal.h" #include "esphome/core/defines.h" @@ -56,7 +52,7 @@ static bool DEFAULT_IN_FLASH = true; class ESPPreferences { public: ESPPreferences(); - void begin(const std::string &name); + void begin(); ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash = DEFAULT_IN_FLASH); template ESPPreferenceObject make_preference(uint32_t type, bool in_flash = DEFAULT_IN_FLASH); @@ -77,7 +73,7 @@ class ESPPreferences { uint32_t current_offset_; #ifdef ARDUINO_ARCH_ESP32 - Preferences preferences_; + uint32_t nvs_handle_; #endif #ifdef ARDUINO_ARCH_ESP8266 void save_esp8266_flash_(); diff --git a/esphome/core_config.py b/esphome/core_config.py index 051de896b5..573094db5c 100644 --- a/esphome/core_config.py +++ b/esphome/core_config.py @@ -239,7 +239,6 @@ def to_code(config): # Libraries if CORE.is_esp32: - cg.add_library('Preferences', None) cg.add_library('ESPmDNS', None) elif CORE.is_esp8266: cg.add_library('ESP8266WiFi', None)