ESP32/components/app_console/cmd_nvs.c

217 lines
6.7 KiB
C

/*
* cmd_nvs.c
*
* Copyright (c) 2025 Umber Networks & Robert McMahon
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* cmd_nvs.c
*
* Copyright (c) 2025 Umber Networks & Robert McMahon
* All rights reserved.
*/
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "esp_log.h"
#include "esp_console.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "argtable3/argtable3.h"
#include "app_console.h"
static void print_nvs_usage(void) {
printf("Usage: nvs <subcommand>\n");
printf("Subcommands:\n");
printf(" dump Dump 'storage' namespace keys and values\n");
printf(" clear Erase 'storage' namespace (Factory Reset)\n");
}
static void print_value(nvs_handle_t h, const char *key, nvs_type_t type) {
esp_err_t err;
switch (type) {
case NVS_TYPE_I8: {
int8_t v = 0;
err = nvs_get_i8(h, key, &v);
if (err == ESP_OK) printf("Value: %d (I8)", v);
break;
}
case NVS_TYPE_U8: {
uint8_t v = 0;
err = nvs_get_u8(h, key, &v);
if (err == ESP_OK) printf("Value: %u (U8)", v);
break;
}
case NVS_TYPE_I16: {
int16_t v = 0;
err = nvs_get_i16(h, key, &v);
if (err == ESP_OK) printf("Value: %d (I16)", v);
break;
}
case NVS_TYPE_U16: {
uint16_t v = 0;
err = nvs_get_u16(h, key, &v);
if (err == ESP_OK) printf("Value: %u (U16)", v);
break;
}
case NVS_TYPE_I32: {
int32_t v = 0;
err = nvs_get_i32(h, key, &v);
if (err == ESP_OK) printf("Value: %" PRIi32 " (I32)", v);
break;
}
case NVS_TYPE_U32: {
uint32_t v = 0;
err = nvs_get_u32(h, key, &v);
if (err == ESP_OK) printf("Value: %" PRIu32 " (U32)", v);
break;
}
case NVS_TYPE_I64: {
int64_t v = 0;
err = nvs_get_i64(h, key, &v);
if (err == ESP_OK) printf("Value: %" PRIi64 " (I64)", v);
break;
}
case NVS_TYPE_U64: {
uint64_t v = 0;
err = nvs_get_u64(h, key, &v);
if (err == ESP_OK) printf("Value: %" PRIu64 " (U64)", v);
break;
}
case NVS_TYPE_STR: {
size_t len = 0;
if (nvs_get_str(h, key, NULL, &len) == ESP_OK) {
char *str = malloc(len);
if (nvs_get_str(h, key, str, &len) == ESP_OK) {
printf("Value: \"%s\" (STR)", str);
}
free(str);
}
break;
}
case NVS_TYPE_BLOB: {
size_t len = 0;
if (nvs_get_blob(h, key, NULL, &len) == ESP_OK) {
printf("Value: [BLOB %u bytes]", (unsigned int)len);
}
break;
}
default:
printf("Value: [Unknown Type 0x%02x]", type);
break;
}
}
static int do_nvs_dump(int argc, char **argv) {
nvs_iterator_t it = NULL;
nvs_handle_t h;
// 1. Open Handle (Needed to read values)
esp_err_t err = nvs_open("storage", NVS_READONLY, &h);
if (err != ESP_OK) {
printf("Error opening NVS handle: %s\n", esp_err_to_name(err));
return 1;
}
// 2. Start Iterator
esp_err_t res = nvs_entry_find("nvs", "storage", NVS_TYPE_ANY, &it);
if (res != ESP_OK) {
nvs_close(h);
if (res == ESP_ERR_NVS_NOT_FOUND) {
printf("No NVS entries found in 'storage'.\n");
} else {
printf("NVS Search Error: %s\n", esp_err_to_name(res));
}
return 0;
}
printf("NVS Dump (Namespace: storage):\n");
printf("%-20s | %-12s | %s\n", "Key", "Type", "Value");
printf("------------------------------------------------------------\n");
while (res == ESP_OK) {
nvs_entry_info_t info;
nvs_entry_info(it, &info);
printf("%-20s | 0x%02x | ", info.key, info.type);
print_value(h, info.key, info.type);
printf("\n");
res = nvs_entry_next(&it);
}
nvs_release_iterator(it);
nvs_close(h);
return 0;
}
static int do_nvs_clear(int argc, char **argv) {
nvs_handle_t h;
esp_err_t err = nvs_open("storage", NVS_READWRITE, &h);
if (err != ESP_OK) {
printf("Error opening NVS: %s\n", esp_err_to_name(err));
return 1;
}
err = nvs_erase_all(h);
if (err == ESP_OK) {
nvs_commit(h);
printf("NVS 'storage' namespace erased.\n");
} else {
printf("Error erasing NVS: %s\n", esp_err_to_name(err));
}
nvs_close(h);
return (err == ESP_OK) ? 0 : 1;
}
static int cmd_nvs(int argc, char **argv) {
if (argc < 2) {
print_nvs_usage();
return 0;
}
if (strcmp(argv[1], "dump") == 0) return do_nvs_dump(argc - 1, &argv[1]);
if (strcmp(argv[1], "clear") == 0) return do_nvs_clear(argc - 1, &argv[1]);
print_nvs_usage();
return 1;
}
void register_nvs_cmd(void) {
const esp_console_cmd_t cmd = {
.command = "nvs",
.help = "Storage Tools: dump, clear",
.hint = "<subcommand>",
.func = &cmd_nvs,
};
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
}