From d339a1f4c31823b0b0987570a555cf3cc400d34d Mon Sep 17 00:00:00 2001 From: GW_MC <72297530+GWMCwing@users.noreply.github.com> Date: Sun, 18 Jan 2026 14:46:25 +0800 Subject: [PATCH] Add NVS storage handler and integrate with main application logic --- main/CMakeLists.txt | 1 + main/common/constants.h | 4 +- main/common/queue_defs.h | 1 + main/io/io.h | 20 ++++++++++ main/io/nvs_handler.cpp | 84 ++++++++++++++++++++++++++++++++++++++++ main/io/nvs_handler.h | 21 ++++++++++ main/main.cpp | 6 ++- 7 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 main/io/nvs_handler.cpp create mode 100644 main/io/nvs_handler.h diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 3b65896..4c8dd40 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -2,4 +2,5 @@ file(GLOB SRCS "main.cpp" "*.cpp" "*.c" "**/*.cpp" "**/*.c") idf_component_register(SRCS ${SRCS} PRIV_REQUIRES spi_flash + nvs_flash INCLUDE_DIRS "." "display" "touch" "network" "ui" "io" "common") diff --git a/main/common/constants.h b/main/common/constants.h index c6db730..62eb2b5 100644 --- a/main/common/constants.h +++ b/main/common/constants.h @@ -1,3 +1,4 @@ +#pragma once // 800x480 = 384,000 pixels #define EINK_WIDTH 800 @@ -11,4 +12,5 @@ #define SYSTEM_START_BIT (1 << 2) // #define DISPLAY_READY_BIT (1 << 1) -#define TOUCH_CALIBRATED_BIT (1 << 2) \ No newline at end of file +#define TOUCH_CALIBRATED_BIT (1 << 2) +#define STORAGE_READY_BIT (1 << 3) \ No newline at end of file diff --git a/main/common/queue_defs.h b/main/common/queue_defs.h index 64faede..ac9d9ef 100644 --- a/main/common/queue_defs.h +++ b/main/common/queue_defs.h @@ -1,3 +1,4 @@ +#pragma once #include typedef enum { diff --git a/main/io/io.h b/main/io/io.h index e69de29..a25e2a8 100644 --- a/main/io/io.h +++ b/main/io/io.h @@ -0,0 +1,20 @@ +#pragma once +#include "freertos/FreeRTOS.h" +#include "freertos/event_groups.h" + +class KVStorageHandler { +public: + virtual ~KVStorageHandler() = default; + + virtual void init(const EventGroupHandle_t& system_event_group) = 0; + + // Store a key-value pair + virtual void put(const char*& key, const char*& value) = 0; + + // Retrieve a value by key, returns nullptr if key not found + // The caller is responsible for freeing the returned memory + virtual char* get(const char*& key) const = 0; + + // Delete a key-value pair + virtual void remove(const char*& key) = 0; +}; \ No newline at end of file diff --git a/main/io/nvs_handler.cpp b/main/io/nvs_handler.cpp new file mode 100644 index 0000000..7037d26 --- /dev/null +++ b/main/io/nvs_handler.cpp @@ -0,0 +1,84 @@ +#include "common/constants.h" +#include "io/nvs_handler.h" +#include "nvs_flash.h" + +NVSStorageHandler::~NVSStorageHandler() { + if (this->nvsHandle != 0) { + nvs_close(this->nvsHandle); + this->nvsHandle = 0; + } +} + +void NVSStorageHandler::init(const EventGroupHandle_t& system_event_group) { + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { + nvs_flash_erase(); + err = nvs_flash_init(); + } + ESP_ERROR_CHECK(err); + + err = nvs_open("storage", NVS_READWRITE, &this->nvsHandle); + if (err != ESP_OK) { + printf("Error (%s) opening NVS handle!\n", esp_err_to_name(err)); + } else { + xEventGroupSetBits(system_event_group, STORAGE_READY_BIT); + printf("NVS Storage initialized.\n"); + } +} + +void NVSStorageHandler::put(const char*& key, const char*& value) { + if (this->nvsHandle == 0) { + printf("NVS handle is not initialized.\n"); + return; + } + + esp_err_t err = nvs_set_str(this->nvsHandle, key, value); + if (err != ESP_OK) { + printf("Error (%s) setting key-value pair in NVS!\n", esp_err_to_name(err)); + } else { + nvs_commit(this->nvsHandle); + printf("Key-value pair (%s, %s) stored in NVS.\n", key, value); + } +} + +char* NVSStorageHandler::get(const char*& key) const { + if (this->nvsHandle == 0) { + printf("NVS handle is not initialized.\n"); + return nullptr; + } + + size_t required_size = 0; + esp_err_t err = nvs_get_str(this->nvsHandle, key, nullptr, &required_size); + if (err == ESP_ERR_NVS_NOT_FOUND) { + printf("Key %s not found in NVS.\n", key); + return nullptr; + } else if (err != ESP_OK) { + printf("Error (%s) getting size for key %s from NVS!\n", esp_err_to_name(err), key); + return nullptr; + } + + char* value = (char*)malloc(required_size); + err = nvs_get_str(this->nvsHandle, key, value, &required_size); + if (err != ESP_OK) { + printf("Error (%s) getting value for key %s from NVS!\n", esp_err_to_name(err), key); + free(value); + return nullptr; + } + + return value; +} + +void NVSStorageHandler::remove(const char*& key) { + if (this->nvsHandle == 0) { + printf("NVS handle is not initialized.\n"); + return; + } + + esp_err_t err = nvs_erase_key(this->nvsHandle, key); + if (err != ESP_OK) { + printf("Error (%s) deleting key %s from NVS!\n", esp_err_to_name(err), key); + } else { + nvs_commit(this->nvsHandle); + printf("Key %s deleted from NVS.\n", key); + } +} diff --git a/main/io/nvs_handler.h b/main/io/nvs_handler.h new file mode 100644 index 0000000..cec2968 --- /dev/null +++ b/main/io/nvs_handler.h @@ -0,0 +1,21 @@ +#pragma once +#include "io/io.h" +#include "freertos/FreeRTOS.h" +#include "nvs.h" + +class NVSStorageHandler : public KVStorageHandler { +public: + NVSStorageHandler() = default; + ~NVSStorageHandler() override; + + void init(const EventGroupHandle_t& system_event_group) override; + + void put(const char*& key, const char*& value) override; + + char* get(const char*& key) const override; + + void remove(const char*& key) override; + +private: + nvs_handle_t nvsHandle = 0; +}; diff --git a/main/main.cpp b/main/main.cpp index 545bc5c..c8d45d7 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -18,6 +18,7 @@ // #include "common/constants.h" #include "common/queue_defs.h" +#include "io/nvs_handler.h" #include "info/info.h" #include "display/display.h" #include "touch/touch.h" @@ -49,9 +50,11 @@ void app_main(void) { throw std::runtime_error("Failed to create LVGL mutex"); } // + KVStorageHandler* kv_storage_handler = new NVSStorageHandler(); DisplayHandler* display_handler = new EInkDisplayHandler(touch_event_queue, lvgl_mutex); TouchHandler* touch_handler = new EInkTouchHandler(touch_event_queue); // + kv_storage_handler->init(system_event_group); display_handler->init(system_event_group); touch_handler->init(system_event_group); // @@ -75,7 +78,8 @@ void app_main(void) { printf("Waiting for system to be ready...\n"); xEventGroupWaitBits( system_event_group, - DISPLAY_READY_BIT | TOUCH_CALIBRATED_BIT, + DISPLAY_READY_BIT | TOUCH_CALIBRATED_BIT | STORAGE_READY_BIT, + // do not clear on exit, require explicit reset pdFALSE, pdTRUE, portMAX_DELAY