Adding NVS to project

This commit is contained in:
2025-01-01 21:15:01 +01:00
parent dd9f59e418
commit 968d078c07
19 changed files with 812 additions and 28 deletions
+316
View File
@@ -0,0 +1,316 @@
/**
* @file cmd_nvs.cpp
* @author Gustice
* @brief NVS-Diagnosis utility (derived from ESP-IDF Console-Example)
*
* @copyright Copyright (c) 2024
*/
#include "nvsFunctions.hpp"
#include "esp_err.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "nvs.h"
#include "nvsIo.hpp"
#include "nvs_flash.h"
#include <errno.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "nvsDefines.hpp"
static void initializeNvs() {
esp_err_t err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
// 1.OTA app partition table has a smaller NVS partition size than the non-OTA
// partition table. This size mismatch may cause NVS initialization to fail.
// 2.NVS partition contains data in new format and cannot be recognized by this version of code.
// If this happens, we erase NVS partition and initialize NVS again.
ESP_ERROR_CHECK(nvs_flash_erase());
err = nvs_flash_init();
}
ESP_ERROR_CHECK(err);
}
NvsApi *NvsApi::_instance = nullptr;
NvsApi::NvsApi(std::string mount) : _mountingPoint(mount) {
initializeNvs();
}
NvsApi::~NvsApi() {
}
NvsApi &NvsApi::getInstance(std::string mount) {
if (_instance == nullptr) {
init(mount);
}
return *_instance;
}
void NvsApi::init(std::string mount) {
if (_instance != nullptr) {
return;
}
_instance = new NvsApi(mount);
}
const auto [TypeStrMap, StrTypeMap] = CreateNvsDictionaries();
static char activeNameSpace[16] = "storage";
static const char *TAG = "NVS";
static nvs_type_t confStr2Type(const char *type) {
if (auto search = StrTypeMap.find(type); search != StrTypeMap.end()) {
return search->second;
}
ESP_LOGW(TAG, "type '%s' not found", type);
return NVS_TYPE_ANY;
}
static const char *confType2Str(nvs_type_t type) {
if (auto search = TypeStrMap.find(type); search != TypeStrMap.end()) {
return search->second;
}
ESP_LOGW(TAG, "type %d not found", type);
return "Unknown";
}
struct SetArgs {
struct arg_str *key;
struct arg_str *type;
struct arg_str *value;
struct arg_end *end;
};
struct GetArgs {
struct arg_str *key;
struct arg_str *type;
struct arg_end *end;
};
struct EraseArgs {
struct arg_str *key;
struct arg_end *end;
};
struct EraseNameSpaceArgs {
struct arg_str *nameSpace;
struct arg_end *end;
};
struct NameSpaceArgs {
struct arg_str *nameSpace;
struct arg_end *end;
};
struct ListArgs {
struct arg_str *partition;
struct arg_str *nameSpace;
struct arg_str *type;
struct arg_end *end;
};
static esp_err_t setValueInNvs(const char *key, const char *strType, const char *strValue) {
nvs_type_t type = confStr2Type(strType);
if (type == NVS_TYPE_ANY) {
ESP_LOGE(TAG, "Type '%s' is undefined", strType);
return ESP_ERR_NVS_TYPE_MISMATCH;
}
try {
NvsIo nvs(activeNameSpace, NVS_READWRITE);
esp_err_t err = ESP_FAIL;
if (type == NVS_TYPE_I8) {
err = nvs.setValueByStr<int8_t>(key, strValue);
} else if (type == NVS_TYPE_U8) {
err = nvs.setValueByStr<uint8_t>(key, strValue);
} else if (type == NVS_TYPE_I16) {
err = nvs.setValueByStr<int16_t>(key, strValue);
} else if (type == NVS_TYPE_U16) {
err = nvs.setValueByStr<uint16_t>(key, strValue);
} else if (type == NVS_TYPE_I32) {
err = nvs.setValueByStr<int32_t>(key, strValue);
} else if (type == NVS_TYPE_U32) {
err = nvs.setValueByStr<uint32_t>(key, strValue);
} else if (type == NVS_TYPE_I64) {
err = nvs.setValueByStr<int64_t>(key, strValue);
} else if (type == NVS_TYPE_U64) {
err = nvs.setValueByStr<uint64_t>(key, strValue);
} else if (type == NVS_TYPE_STR) {
err = nvs.setString(key, strValue);
} else if (type == NVS_TYPE_BLOB) {
err = nvs.setBlob(key, strValue);
}
if (err != ESP_OK) {
return err;
}
err = nvs.commit();
if (err == ESP_OK) {
ESP_LOGI(TAG, "Value stored under key '%s'", key);
}
return ESP_OK;
} catch (const std::exception &e) {
ESP_LOGE(TAG, "%s", e.what());
}
return ESP_FAIL;
}
void NvsApi::setValue(const std::string &key, const std::string &value) {
if (setValueInNvs(key.c_str(), "str", value.c_str()) != ESP_OK) {
ESP_LOGE(TAG, "setValue failed");
}
}
std::string NvsApi::getValue(const std::string &key) {
try {
NvsIo nvs(activeNameSpace, NVS_READONLY);
auto opt = nvs.getString(key.c_str());
auto value = opt.value();
return value;
} catch (const std::bad_optional_access &e) {
ESP_LOGE(TAG, "%s", "Value not defined");
} catch (const std::exception &e) {
ESP_LOGE(TAG, "%s", e.what());
}
return "";
}
static esp_err_t showValueFromNvs(const char *key, const char *strType) {
nvs_type_t type = confStr2Type(strType);
if (type == NVS_TYPE_ANY) {
ESP_LOGE(TAG, "Type '%s' is undefined", strType);
return ESP_ERR_NVS_TYPE_MISMATCH;
}
try {
NvsIo nvs(activeNameSpace, NVS_READONLY);
if (type == NVS_TYPE_I8) {
auto opt = nvs.getInt8(key);
printf("%d\n", opt.value());
} else if (type == NVS_TYPE_U8) {
auto opt = nvs.getUint8(key);
printf("%u\n", opt.value());
} else if (type == NVS_TYPE_I16) {
auto opt = nvs.getInt16(key);
printf("%u\n", opt.value());
} else if (type == NVS_TYPE_U16) {
auto opt = nvs.getUint16(key);
printf("%u\n", opt.value());
} else if (type == NVS_TYPE_I32) {
auto opt = nvs.getInt32(key);
printf("%" PRIi32 "\n", opt.value());
} else if (type == NVS_TYPE_U32) {
auto opt = nvs.getUint32(key);
printf("%" PRIu32 "\n", opt.value());
} else if (type == NVS_TYPE_I64) {
auto opt = nvs.getInt64(key);
printf("%lld\n", opt.value());
} else if (type == NVS_TYPE_U64) {
auto opt = nvs.getUint64(key);
printf("%llu\n", opt.value());
} else if (type == NVS_TYPE_STR) {
auto opt = nvs.getString(key);
printf("%s\n", opt.value().c_str());
} else if (type == NVS_TYPE_BLOB) {
auto opt = nvs.getBlob(key);
auto value = opt.value();
for (int i = 0; i < value.size(); i++) {
printf("%02x", value[i]);
}
printf("\n");
}
return ESP_OK;
} catch (const std::bad_optional_access &e) {
ESP_LOGE(TAG, "%s", "Value not defined");
} catch (const std::exception &e) {
ESP_LOGE(TAG, "%s", e.what());
}
return ESP_FAIL;
}
static esp_err_t erase(const char *key) {
try {
NvsIo nvs(activeNameSpace, NVS_READWRITE);
esp_err_t err = nvs.erase(key);
if (err != ESP_OK) {
return err;
}
err = nvs.commit();
if (err != ESP_OK) {
return err;
}
ESP_LOGI(TAG, "Value with key '%s' erased", key);
return ESP_OK;
} catch (const std::exception &e) {
ESP_LOGE(TAG, "%s", e.what());
}
return ESP_FAIL;
}
static esp_err_t eraseAllIn(const char *name) {
try {
NvsIo nvs(name, NVS_READWRITE);
esp_err_t err = nvs.clear();
if (err != ESP_OK) {
return err;
}
err = nvs.commit();
if (err != ESP_OK) {
return err;
}
ESP_LOGI(TAG, "Namespace '%s' was %s erased", name, (err == ESP_OK) ? "" : "not");
return ESP_OK;
} catch (const std::exception &e) {
ESP_LOGE(TAG, "%s", e.what());
}
return ESP_FAIL;
}
static int list(const char *part, const char *name, const char *strType) {
nvs_type_t type = confStr2Type(strType);
nvs_iterator_t it = NULL;
esp_err_t result = nvs_entry_find(part, NULL, type, &it);
if (result == ESP_ERR_NVS_NOT_FOUND) {
ESP_LOGE(TAG, "No such entry was found");
return 1;
}
if (result != ESP_OK) {
ESP_LOGE(TAG, "NVS error: %s", esp_err_to_name(result));
return 1;
}
do {
nvs_entry_info_t info;
nvs_entry_info(it, &info);
result = nvs_entry_next(&it);
if ((strlen(name) > 0) && (strcmp(info.namespace_name, name) != 0)) {
continue;
}
printf("namespace '%s', key '%s', type '%s' \n",
info.namespace_name, info.key, confType2Str(info.type));
} while (result == ESP_OK);
if (result != ESP_ERR_NVS_NOT_FOUND) { // the last iteration ran into an internal error
ESP_LOGE(TAG, "NVS error %s at current iteration, stopping.", esp_err_to_name(result));
return 1;
}
return 0;
}