/* * 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 #include #include #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 \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 = "", .func = &cmd_nvs, }; ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); }