Squash of branch setup
This commit is contained in:
26
main/io/io.h
Normal file
26
main/io/io.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include <memory>
|
||||
|
||||
typedef bool(*FilterFunc)(const std::string& key);
|
||||
typedef void (*KeyValueProcessor)(void* arg, const std::string& key, const std::string& value);
|
||||
|
||||
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 std::string& key, const std::string& value) = 0;
|
||||
|
||||
// Retrieve a value by key, returns empty string if key not found
|
||||
virtual std::string get(const std::string& key) const = 0;
|
||||
virtual esp_err_t process_all(KeyValueProcessor processor, void* arg) const = 0;
|
||||
virtual esp_err_t process_filtered(const std::string& key_prefix, KeyValueProcessor processor, void* arg) const = 0;
|
||||
virtual esp_err_t process_filtered(FilterFunc filter_func, KeyValueProcessor processor, void* arg) const = 0;
|
||||
|
||||
// Delete a key-value pair
|
||||
virtual void remove(const std::string& key) = 0;
|
||||
};
|
||||
191
main/io/nvs_handler.cpp
Normal file
191
main/io/nvs_handler.cpp
Normal file
@@ -0,0 +1,191 @@
|
||||
#include "common/constants.h"
|
||||
#include "io/nvs_handler.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "string.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#define TAG "NVSStorageHandler"
|
||||
|
||||
NVSStorageHandler::NVSStorageHandler(
|
||||
const char* name_space
|
||||
) : name_space(name_space) { }
|
||||
|
||||
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(this->name_space, NVS_READWRITE, &this->nvsHandle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error (%s) opening NVS handle!", esp_err_to_name(err));
|
||||
} else {
|
||||
if (system_event_group != nullptr) {
|
||||
xEventGroupSetBits(system_event_group, STORAGE_READY_BIT);
|
||||
}
|
||||
ESP_LOGI(TAG, "NVS Storage initialized.");
|
||||
}
|
||||
}
|
||||
|
||||
void NVSStorageHandler::put(const std::string& key, const std::string& value) {
|
||||
if (this->nvsHandle == 0) {
|
||||
ESP_LOGE(TAG, "NVS handle is not initialized.");
|
||||
return;
|
||||
}
|
||||
|
||||
esp_err_t err = nvs_set_str(this->nvsHandle, key.c_str(), value.c_str());
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error (%s) setting key-value pair in NVS!", esp_err_to_name(err));
|
||||
} else {
|
||||
nvs_commit(this->nvsHandle);
|
||||
// ESP_LOGI(TAG, "Key-value pair (%s, %s) stored in NVS.", key.c_str(), value.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
std::string NVSStorageHandler::get(const std::string& key) const {
|
||||
if (this->nvsHandle == 0) {
|
||||
ESP_LOGE(TAG, "NVS handle is not initialized.");
|
||||
return "";
|
||||
}
|
||||
|
||||
size_t required_size = 0;
|
||||
esp_err_t err = nvs_get_str(this->nvsHandle, key.c_str(), nullptr, &required_size);
|
||||
if (err == ESP_ERR_NVS_NOT_FOUND) {
|
||||
ESP_LOGW(TAG, "Key %s not found in NVS.", key.c_str());
|
||||
return "";
|
||||
} else if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error (%s) getting size for key %s from NVS!", esp_err_to_name(err), key.c_str());
|
||||
return "";
|
||||
}
|
||||
|
||||
// Allocate string buffer with correct size (includes null terminator)
|
||||
std::string value(required_size - 1, '\0');
|
||||
err = nvs_get_str(this->nvsHandle, key.c_str(), &value[0], &required_size);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error (%s) getting value for key %s from NVS!", esp_err_to_name(err), key.c_str());
|
||||
return "";
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
NVSIteratorGuard NVSStorageHandler::create_iterator() const {
|
||||
nvs_iterator_t it = nullptr;
|
||||
esp_err_t err = nvs_entry_find(NVS_DEFAULT_PART_NAME, this->name_space, NVS_TYPE_ANY, &it);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error (%s) creating NVS iterator!", esp_err_to_name(err));
|
||||
return NVSIteratorGuard(nullptr, err);
|
||||
}
|
||||
|
||||
return NVSIteratorGuard(it, ESP_OK);
|
||||
}
|
||||
|
||||
esp_err_t NVSStorageHandler::process_all(KeyValueProcessor processor, void* arg) const {
|
||||
NVSIteratorGuard iterator_guard = this->create_iterator();
|
||||
if (!iterator_guard.is_valid()) {
|
||||
return iterator_guard.get_error();
|
||||
}
|
||||
const nvs_iterator_t& it = iterator_guard.get_iterator();
|
||||
|
||||
for (; it != NULL; iterator_guard.advance_iter()) {
|
||||
nvs_entry_info_t info;
|
||||
esp_err_t err = nvs_entry_info(it, &info);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error (%s) getting NVS entry info!", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
nvs_handle_t temp_handle;
|
||||
err = nvs_open(this->name_space, NVS_READONLY, &temp_handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error (%s) opening NVS handle for reading!", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
// call the processor with the key and value
|
||||
std::string key_str = info.key;
|
||||
processor(arg, key_str, this->get(key_str));
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
esp_err_t NVSStorageHandler::process_filtered(const std::string& key_prefix, KeyValueProcessor processor, void* arg) const {
|
||||
NVSIteratorGuard iterator_guard = this->create_iterator();
|
||||
if (!iterator_guard.is_valid()) {
|
||||
return iterator_guard.get_error();
|
||||
}
|
||||
const nvs_iterator_t& it = iterator_guard.get_iterator();
|
||||
|
||||
for (; it != NULL; iterator_guard.advance_iter()) {
|
||||
nvs_entry_info_t info;
|
||||
esp_err_t err = nvs_entry_info(it, &info);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error (%s) getting NVS entry info!", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
// check if the key matches the prefix
|
||||
if (strncmp(info.key, key_prefix.c_str(), key_prefix.length()) == 0) {
|
||||
nvs_handle_t temp_handle;
|
||||
err = nvs_open(this->name_space, NVS_READONLY, &temp_handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error (%s) opening NVS handle for reading!", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
// call the processor with the key and value
|
||||
processor(arg, std::string(info.key), this->get(std::string(info.key)));
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t NVSStorageHandler::process_filtered(FilterFunc filter_func, KeyValueProcessor processor, void* arg) const {
|
||||
NVSIteratorGuard iterator_guard = this->create_iterator();
|
||||
if (!iterator_guard.is_valid()) {
|
||||
return iterator_guard.get_error();
|
||||
}
|
||||
const nvs_iterator_t& it = iterator_guard.get_iterator();
|
||||
|
||||
for (; it != NULL; iterator_guard.advance_iter()) {
|
||||
nvs_entry_info_t info;
|
||||
esp_err_t err = nvs_entry_info(it, &info);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error (%s) getting NVS entry info!", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
// check if the key matches the filter function
|
||||
std::string key_str(info.key);
|
||||
if (filter_func(key_str)) {
|
||||
nvs_handle_t temp_handle;
|
||||
err = nvs_open(this->name_space, NVS_READONLY, &temp_handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error (%s) opening NVS handle for reading!", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
// call the processor with the key and value
|
||||
processor(arg, key_str, this->get(key_str));
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void NVSStorageHandler::remove(const std::string& key) {
|
||||
if (this->nvsHandle == 0) {
|
||||
ESP_LOGE(TAG, "NVS handle is not initialized.");
|
||||
return;
|
||||
}
|
||||
|
||||
esp_err_t err = nvs_erase_key(this->nvsHandle, key.c_str());
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error (%s) deleting key %s from NVS!", esp_err_to_name(err), key.c_str());
|
||||
} else {
|
||||
nvs_commit(this->nvsHandle);
|
||||
ESP_LOGI(TAG, "Key %s deleted from NVS.", key.c_str());
|
||||
}
|
||||
}
|
||||
70
main/io/nvs_handler.h
Normal file
70
main/io/nvs_handler.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
#include "io/io.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "nvs.h"
|
||||
|
||||
struct NVSIteratorGuard {
|
||||
public:
|
||||
~NVSIteratorGuard() {
|
||||
if (iterator) {
|
||||
nvs_release_iterator(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
// accessors to the iterator, the internal state should not be modified directly
|
||||
// The iterator is advanced using advance_iter(), and is changed to nullptr on error or end
|
||||
// Caller MUST NOT release the iterator manually nor call get_iterator after advance_iter
|
||||
const nvs_iterator_t& get_iterator() const {
|
||||
return iterator;
|
||||
}
|
||||
|
||||
void advance_iter() {
|
||||
if (iterator) {
|
||||
// advance the iterator and update the internal state
|
||||
esp_err_t err = nvs_entry_next(&iterator);
|
||||
if (err != ESP_OK) {
|
||||
error = err;
|
||||
iterator = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t get_error() const {
|
||||
return error;
|
||||
}
|
||||
bool is_valid() const {
|
||||
return iterator != nullptr && error == ESP_OK;
|
||||
}
|
||||
friend class NVSStorageHandler;
|
||||
private:
|
||||
NVSIteratorGuard(nvs_iterator_t it
|
||||
, esp_err_t err
|
||||
) : iterator(it), error(err) { }
|
||||
nvs_iterator_t iterator;
|
||||
esp_err_t error;
|
||||
};
|
||||
|
||||
class NVSStorageHandler : public KVStorageHandler {
|
||||
public:
|
||||
NVSStorageHandler(
|
||||
const char* name_space
|
||||
);
|
||||
~NVSStorageHandler() override;
|
||||
|
||||
void init(const EventGroupHandle_t& system_event_group) override;
|
||||
|
||||
void put(const std::string& key, const std::string& value) override;
|
||||
|
||||
std::string get(const std::string& key) const override;
|
||||
esp_err_t process_all(KeyValueProcessor processor, void* arg) const override;
|
||||
esp_err_t process_filtered(const std::string& key_prefix, KeyValueProcessor processor, void* arg) const override;
|
||||
esp_err_t process_filtered(FilterFunc filter_func, KeyValueProcessor processor, void* arg) const override;
|
||||
|
||||
void remove(const std::string& key) override;
|
||||
|
||||
private:
|
||||
NVSIteratorGuard create_iterator() const;
|
||||
|
||||
nvs_handle_t nvsHandle = 0;
|
||||
const char* name_space;
|
||||
};
|
||||
Reference in New Issue
Block a user