From bd006006171def44a11b8c2cc13f506687000d34 Mon Sep 17 00:00:00 2001
From: Jochen Vothknecht <jochen3120@gmail.com>
Date: Sun, 3 Jul 2022 22:20:12 +0200
Subject: [PATCH] ST: Adding export_json command to NVSExplorer

---
 CLC-qthing/SiliconTorch/NVSExplorer.cpp | 76 ++++++++++++++++++++++++-
 CLC-qthing/SiliconTorch/NVSExplorer.hpp |  4 ++
 CLC-qthing/SiliconTorch/NVSExplorer.md  | 14 +++++
 3 files changed, 93 insertions(+), 1 deletion(-)

diff --git a/CLC-qthing/SiliconTorch/NVSExplorer.cpp b/CLC-qthing/SiliconTorch/NVSExplorer.cpp
index cac14fb..348c745 100644
--- a/CLC-qthing/SiliconTorch/NVSExplorer.cpp
+++ b/CLC-qthing/SiliconTorch/NVSExplorer.cpp
@@ -23,6 +23,12 @@
 #include <qthing>
 #include <qthing/mqtt_common.hpp>
 
+// misc
+#include <nlohmann/json.hpp>
+
+
+using json = nlohmann::json;
+
 
 
 
@@ -40,7 +46,6 @@ namespace SiliconTorch {
 
       nvs_flash_init();
 
-
       registerLambdas0();
       registerLambdas1();
 
@@ -609,6 +614,11 @@ namespace SiliconTorch {
       } ));
 
 
+      qthing::add_message_callback(requestTopic("export_json"), [&](str ignored) {
+        publishJSON(false);
+      });
+
+
     }
 
 
@@ -1227,7 +1237,71 @@ namespace SiliconTorch {
     }
 
 
+    str NVSExplorer::exportJSON(bool prettyPrint) {
+
+      json storage;
+
+      for (const auto& ns : listNamespaces()) {
+        json keys;
+
+        nvs_iterator_t it = nvs_entry_find("nvs", ns.c_str(), NVS_TYPE_ANY);
+
+        while (it != NULL) {
+          nvs_entry_info_t entry;
+          nvs_entry_info(it, &entry);
+
+          json _entry;
+          str key(entry.key);
+          bool entryOK = true;
+
+          switch (entry.type) {
+            case NVS_TYPE_U8:  { _entry["value"] = getU8    (ns, key); break; }
+            case NVS_TYPE_U16: { _entry["value"] = getU16   (ns, key); break; }
+            case NVS_TYPE_U32: { _entry["value"] = getU32   (ns, key); break; }
+            case NVS_TYPE_U64: { _entry["value"] = getU64   (ns, key); break; }
+            case NVS_TYPE_I8:  { _entry["value"] = getI8    (ns, key); break; }
+            case NVS_TYPE_I16: { _entry["value"] = getI16   (ns, key); break; }
+            case NVS_TYPE_I32: { _entry["value"] = getI32   (ns, key); break; }
+            case NVS_TYPE_I64: { _entry["value"] = getI64   (ns, key); break; }
+            case NVS_TYPE_STR: { _entry["value"] = getString(ns, key); break; }
+            // case NVS_TYPE_BLOB: {}  // BLOB type currently unsupported
+            default: { entryOK = false; }
+          }
+
+          if (entryOK) {
+            _entry["type"] = type2str(entry.type);
+            keys[entry.key] = _entry;
+          }
+
+          it = nvs_entry_next(it);
+        }
+
+        if (keys.is_object())
+          storage[ns.c_str()] = keys;
+      }
+
+
+      nvs_stats_t nvs_stats;
+      nvs_get_stats("nvs", &nvs_stats);
 
+      json stats;
+
+      stats["used_entries"] = nvs_stats.used_entries;
+      stats["free_entries"] = nvs_stats.free_entries;
+      stats["total_entries"] = nvs_stats.total_entries;
+
+
+      json out;
+
+      out["stats"]   = stats;
+      out["storage"] = storage;
+
+      return out.dump(prettyPrint ? 2 : -1);
+    }
+
+    void NVSExplorer::publishJSON(bool prettyPrint) {
+      qthing::publish_message(responseTopic("export_json"), exportJSON(prettyPrint).c_str());
+    }
 
 
     str NVSExplorer::deviceTopic(const str& suffix) {
diff --git a/CLC-qthing/SiliconTorch/NVSExplorer.hpp b/CLC-qthing/SiliconTorch/NVSExplorer.hpp
index c318d5d..2120ee2 100644
--- a/CLC-qthing/SiliconTorch/NVSExplorer.hpp
+++ b/CLC-qthing/SiliconTorch/NVSExplorer.hpp
@@ -99,6 +99,10 @@ namespace SiliconTorch {
         str getTypeStr(const str& nameSpace, const str& key);
 
 
+        str  exportJSON (bool prettyPrint = false);
+        void publishJSON(bool prettyPrint = false);
+
+
         str deviceTopic(const str& suffix);
 
         str requestTopic(const str& cmd);
diff --git a/CLC-qthing/SiliconTorch/NVSExplorer.md b/CLC-qthing/SiliconTorch/NVSExplorer.md
index 1582dfa..10693c8 100644
--- a/CLC-qthing/SiliconTorch/NVSExplorer.md
+++ b/CLC-qthing/SiliconTorch/NVSExplorer.md
@@ -84,6 +84,20 @@ In the following list, `argument` stands for the message content received on the
   **topic**: `REQUEST/get_strlen/NS/KEY`  
   **description**: returns the length of a stored `string` value
 
+- `export_json` - **export all NVS data as JSON**  
+  **topic**: `REQUEST/export_json`  
+  **description**: returns a `JSON` string containing every key from `NVS` except `NVS_TYPE_BLOB` with the structure:  
+    `{`  
+    `  "stats": { "": 0, "": 0, "": 0 },`  
+    `  "storage": {`  
+    `    "<NAMESPACE>": {`  
+    `      "<KEY>": {`  
+    `        "type": "<TYPE>",`  
+    `        "value": "<VALUE>"`  
+    `      }`  
+    `    }`  
+    `  }`
+    `}`
 
 
 ### Types
-- 
GitLab