diff --git a/CLC-qthing/CMakeLists.txt b/CLC-qthing/CMakeLists.txt
index 2daa6ed90ff637b3dc342d7defc2376143594d71..8449b2a3f9bcc8e281a966fdabb7771e3e25beff 100644
--- a/CLC-qthing/CMakeLists.txt
+++ b/CLC-qthing/CMakeLists.txt
@@ -3,7 +3,7 @@ idf_component_register(
   "." "SiliconTorch" "SpiderLib"
 
   INCLUDE_DIRS
-  "."
+  "." "SpiderLib"
 
   REQUIRES
   main
diff --git a/CLC-qthing/CyanLight.cpp b/CLC-qthing/CyanLight.cpp
index f7007b9bae0fe46113eac4ae70f622bad3d90590..d97ff2aa5f7612a8184081faaa66fd8c601b85e1 100644
--- a/CLC-qthing/CyanLight.cpp
+++ b/CLC-qthing/CyanLight.cpp
@@ -6,20 +6,23 @@
 // ESP32 specific
 #include "esp_log.h"
 
+// project specific
+#include "SpiderLib/NumberTypes.hpp"
 
-uint8_t MAX_CHANNELS = 8;
+
+u8 MAX_CHANNELS = 8;
 
 const char* TAG = "CyanLight";
 
-const uint8_t channelGPIOs[] = { 27, 16, 17, 18, 19, 21, 22, 23 };
+const u8 channelGPIOs[] = { 27, 16, 17, 18, 19, 21, 22, 23 };
 
 namespace CyanLight {
 
-  CyanLightControl::CyanLightControl(uint8_t channelsConfigured, uint32_t baseChannel) : SiliconTorch::FxCyanF(baseChannel) {
+  CyanLightControl::CyanLightControl(u8 channelsConfigured, u32 baseChannel) : SiliconTorch::FxCyanF::FxCyanF(baseChannel) {
 
-    uint8_t channels = std::min(channelsConfigured, MAX_CHANNELS);
+    u8 channels = std::min(channelsConfigured, MAX_CHANNELS);
 
-    for (uint8_t i = 0; i < channels; i++) this->addChannel();
+    for (u8 i = 0; i < channels; i++) this->addChannel();
   }
 
 
@@ -28,7 +31,7 @@ namespace CyanLight {
     auto ch = this->getChannelCount();
 
     if (ch < MAX_CHANNELS) {
-      return SiliconTorch::FxCyanF::addChannel((uint8_t)channelGPIOs[ch]);
+      return SiliconTorch::FxCyanF::FxCyanF::addChannel((u8)channelGPIOs[ch]);
     } else {
       ESP_LOGE(TAG, "Cannot create channel#[ %i ]! CLC hardware limit is #[ %i ]", ch, MAX_CHANNELS);
       return false;
diff --git a/CLC-qthing/CyanLight.hpp b/CLC-qthing/CyanLight.hpp
index 85538773cde97b477f8bc33787feb10b3d6e2eb8..63dd53a93ab6d0fe437e73a7cce9c761274a6fac 100644
--- a/CLC-qthing/CyanLight.hpp
+++ b/CLC-qthing/CyanLight.hpp
@@ -1,18 +1,21 @@
 #pragma once
 
-// TODO: should we include <cinttypes> here or accepts its ingress via FxCyanF.hpp ???
+// TODO: should we include NumberTypes.hpp here or accepts its ingress via FxCyanF.hpp ???
 #include "SiliconTorch/FxCyanF.hpp"
 
+#include "SpiderLib/NumberTypes.hpp"
+
+
 
 namespace CyanLight {
 
-  class CyanLightControl : public SiliconTorch::FxCyanF {
+  class CyanLightControl : public SiliconTorch::FxCyanF::FxCyanF {
     public:
-      CyanLightControl(uint8_t channelsConfigured, uint32_t baseChannel = 0);
+      CyanLightControl(u8 channelsConfigured, u32 baseChannel = 0);
 
       bool addChannel();
 
-      using SiliconTorch::FxCyanF::addChannel;
+      using SiliconTorch::FxCyanF::FxCyanF::addChannel;
 
   };
 
diff --git a/CLC-qthing/IRSender.cpp b/CLC-qthing/IRSender.cpp
index 86f3e982067b9d3bf608a10b24a24e3014655c59..8c9581654188ba022affcc28062ebe83a602a52f 100644
--- a/CLC-qthing/IRSender.cpp
+++ b/CLC-qthing/IRSender.cpp
@@ -5,8 +5,11 @@
 #include "driver/gpio.h"
 #include "driver/ledc.h"
 
+// project specific
+#include "SpiderLib/NumberTypes.hpp"
 
-IRSender::IRSender(uint8_t TXpin, uint8_t CLKpin, uint8_t UARTchannel, uint8_t LEDCchannel) {
+
+IRSender::IRSender(u8 TXpin, u8 CLKpin, u8 UARTchannel, u8 LEDCchannel) {
 
   ledc_timer_config_t ledc_timer;
   ledc_timer.duty_resolution = LEDC_TIMER_1_BIT;
@@ -48,7 +51,7 @@ IRSender::IRSender(uint8_t TXpin, uint8_t CLKpin, uint8_t UARTchannel, uint8_t L
 
 }
 
-void IRSender::send(uint8_t byte) {
+void IRSender::send(u8 byte) {
 
 }
 
@@ -56,7 +59,7 @@ void IRSender::send(std::string &data) {
  
 }
 
-void IRSender::send(uint8_t *buffer, size_t length) {
+void IRSender::send(u8 *buffer, size_t length) {
 
 }
 
diff --git a/CLC-qthing/IRSender.hpp b/CLC-qthing/IRSender.hpp
index 82ebf9a32d53e513b19619099ec5ab9f4e5767a2..618059dbd768ac8b89196f9678a89cbec4b0fb9e 100644
--- a/CLC-qthing/IRSender.hpp
+++ b/CLC-qthing/IRSender.hpp
@@ -1,17 +1,17 @@
 #pragma once
 
-#include <cinttypes>
+#include "SpiderLib/NumberTypes.hpp"
 
 #include <string>
 
 
 class IRSender {
   public:
-    IRSender(uint8_t TXpin, uint8_t CLKpin, uint8_t UARTchannel = 1, uint8_t LEDCchannel = 7);
+    IRSender(u8 TXpin, u8 CLKpin, u8 UARTchannel = 1, u8 LEDCchannel = 7);
 
-    void send(uint8_t byte);
+    void send(u8 byte);
     void send(std::string &data);
-    void send(uint8_t *buffer, size_t length);
+    void send(u8 *buffer, size_t length);
 
 
 };
diff --git a/CLC-qthing/SiliconTorch/CapMan.cpp b/CLC-qthing/SiliconTorch/CapMan.cpp
index 138fa285c1926825e4814279320d4e7460d08c63..e6933fe794e75bcf9771000780098cebdfc2f24f 100644
--- a/CLC-qthing/SiliconTorch/CapMan.cpp
+++ b/CLC-qthing/SiliconTorch/CapMan.cpp
@@ -3,7 +3,6 @@
 // C++ system level
 // #include <cstring>     // memset, strncmp
 // #include <cstdlib>     // TODO: is this for memcpy?
-#include <cinttypes>
 // #include <functional>
 
 // ESP32 specific
@@ -13,7 +12,7 @@
 // #include "driver/uart.h"
 
 // project specific
-// #include ""
+#include "SpiderLib/NumberTypes.hpp"
 
 // qthing stuff
 // #include <qthing>
diff --git a/CLC-qthing/SiliconTorch/CapMan.hpp b/CLC-qthing/SiliconTorch/CapMan.hpp
index 2bcf8840f7b310a4a4ff3a5927bb0c1f6e359340..f84ccabc4b71877cf73f5fd91fd8f77cd9c0eca0 100644
--- a/CLC-qthing/SiliconTorch/CapMan.hpp
+++ b/CLC-qthing/SiliconTorch/CapMan.hpp
@@ -4,7 +4,6 @@
 // #include <string>
 // #include <cstring>     // memset, strncmp
 // #include <cstdlib>     // TODO: is this for memcpy?
-#include <cinttypes>
 // #include <functional>
 
 // ESP32 specific
@@ -14,7 +13,7 @@
 // #include "driver/uart.h"
 
 // project specific
-// #include ""
+#include "SpiderLib/NumberTypes.hpp"
 
 // qthing stuff
 // #include <qthing>
@@ -42,7 +41,7 @@ namespace SiliconTorch {
 
 
 
-        void registerLEDStrip(std::string& name, uint16_t startIdx, uint16_t length, ColorType);
+        void registerLEDStrip(std::string& name, u16 startIdx, u16 length, ColorType);
 
 
 
diff --git a/CLC-qthing/SiliconTorch/CyanBus.cpp b/CLC-qthing/SiliconTorch/CyanBus.cpp
index a53644d5818abaefc5c50de7ecc0795eadd55d72..13e5b35eac04dbd358ba2dc43480ba82ddfaeacb 100644
--- a/CLC-qthing/SiliconTorch/CyanBus.cpp
+++ b/CLC-qthing/SiliconTorch/CyanBus.cpp
@@ -3,7 +3,6 @@
 // C++ system level
 #include <cstring>     // memset, strncmp
 #include <cstdlib>     // TODO: is this for memcpy?
-#include <cinttypes>
 #include <functional>
 
 // ESP32 specific
@@ -19,6 +18,7 @@
 #include "LambdaTask.hpp"
 #include "SpiderLib/Callback.hpp"
 #include "SpiderLib/CallbackMap.hpp"
+#include "SpiderLib/NumberTypes.hpp"
 
 // qthing stuff
 // #include ""
@@ -29,7 +29,7 @@ static const char* TAG = "CyanBus";
 
 
 // Extract the length from a buffer; Network order / Big-Endian
-static uint16_t getLength(const uint8_t* buffer) {
+static u16 getLength(const u8* buffer) {
   return (buffer[0] << 8) | buffer[1];
 }
 
@@ -42,9 +42,9 @@ namespace SiliconTorch {
     const char* const HEADER = "fxCyan";
 
 
-    CyanBus::CyanBus(uint8_t tx, uint8_t rx, uint8_t de, uint8_t re, uint32_t baudRate, uint8_t uartChannel) : tx(tx), rx(rx), de(de), re(re), uartChannel(uartChannel) {
+    CyanBus::CyanBus(u8 tx, u8 rx, u8 de, u8 re, u32 baudRate, u8 uartChannel) : tx(tx), rx(rx), de(de), re(re), uartChannel(uartChannel) {
 
-      uint64_t bitMask = 0;
+      u64 bitMask = 0;
 
       bitMask |= 1ULL << tx;
       bitMask |= 1ULL << de;
@@ -113,14 +113,14 @@ namespace SiliconTorch {
 
       uart_port_t _ch = (uart_port_t)uartChannel;
 
-      const uint32_t bufLEN = MTU + 256;      // MTU + maxEventSize(120) + slack
-      uint8_t* buffer = new uint8_t[bufLEN];  // our packet buffer
-      uint8_t* bufPTR = buffer;               // points inside our buffer; used for envelope parsing…
+      const u32 bufLEN = MTU + 256;      // MTU + maxEventSize(120) + slack
+      u8* buffer = new u8[bufLEN];  // our packet buffer
+      u8* bufPTR = buffer;               // points inside our buffer; used for envelope parsing…
 
-      uint16_t payloadLEN = 0;
-      const uint8_t crcLEN = 4;
-      const uint8_t lengthLEN = 2;
-      const uint8_t headerLEN = std::strlen(HEADER);
+      u16 payloadLEN = 0;
+      const u8 crcLEN = 4;
+      const u8 lengthLEN = 2;
+      const u8 headerLEN = std::strlen(HEADER);
 
       std::memset(buffer, 0x00, bufLEN);
 
@@ -260,8 +260,8 @@ namespace SiliconTorch {
     }
 
     void CyanBus::packetTask() {
-      const uint8_t* buffer = new uint8_t[MTU];
-      uint16_t payloadLEN = 0;
+      const u8* buffer = new u8[MTU];
+      u16 payloadLEN = 0;
 
       auto Q = packetQ;
       while (true) {
@@ -293,12 +293,12 @@ namespace SiliconTorch {
     }
 
 
-    void CyanBus::setBaudRate(uint32_t baudRate) {
+    void CyanBus::setBaudRate(u32 baudRate) {
       uart_set_baudrate((uart_port_t)uartChannel, baudRate);
     }
 
-    uint32_t CyanBus::getBaudRate() {
-      uint32_t baudRate = 0;
+    u32 CyanBus::getBaudRate() {
+      u32 baudRate = 0;
       uart_get_baudrate((uart_port_t)uartChannel, &baudRate);
       return baudRate;
     }
diff --git a/CLC-qthing/SiliconTorch/CyanBus.hpp b/CLC-qthing/SiliconTorch/CyanBus.hpp
index 9891c54e262af1c94a178bc434c39e8c9bab6d6e..de76ae3afde325c893412ef74c2da18e8833423a 100644
--- a/CLC-qthing/SiliconTorch/CyanBus.hpp
+++ b/CLC-qthing/SiliconTorch/CyanBus.hpp
@@ -2,7 +2,6 @@
 
 // C++ system level
 #include <string>
-#include <cinttypes>
 #include <functional>
 
 // ESP32 specific
@@ -13,6 +12,7 @@
 #include "LambdaTask.hpp"
 #include "SpiderLib/Callback.hpp"
 #include "SpiderLib/CallbackMap.hpp"
+#include "SpiderLib/NumberTypes.hpp"
 
 // qthing stuff
 // #include ""
@@ -25,29 +25,29 @@ namespace SiliconTorch {
 
     // CyanBus payload MTU
     // This leads to ~54 P/s @ 2 MBaud at 100% load
-    constexpr uint32_t MTU = 4096;
+    constexpr u32 MTU = 4096;
 
     // CyanBus envelope header
     extern const char* const HEADER;
 
 
     typedef struct {
-      const uint8_t* payload;
-      const uint16_t length;
+      const u8* payload;
+      const u16 length;
     } PacketData;
 
     typedef struct {
       const bool crcOK;
-      const uint16_t payloadLEN;
+      const u16 payloadLEN;
     } PacketMetrics;
 
 
     class CyanBus {
       public:
-        CyanBus(uint8_t tx, uint8_t rx, uint8_t de, uint8_t re, uint32_t baudRate = 115200, uint8_t uartChannel = 1);
+        CyanBus(u8 tx, u8 rx, u8 de, u8 re, u32 baudRate = 115200, u8 uartChannel = 1);
 
-        uint32_t getBaudRate();
-        void setBaudRate(uint32_t baudRate);
+        u32 getBaudRate();
+        void setBaudRate(u32 baudRate);
 
         const SpiderLib::CallbackMap<void(const PacketData&)> packetCallback;
         const SpiderLib::Callback<void(const PacketMetrics&)> metricsCallback;
@@ -57,8 +57,8 @@ namespace SiliconTorch {
         QueueHandle_t uartEvQ;
         QueueHandle_t packetQ;
 
-        uint8_t uartChannel;
-        uint8_t tx, rx, de, re;
+        u8 uartChannel;
+        u8 tx, rx, de, re;
 
         void txEN(bool state);
         void rxEN(bool state);
@@ -67,7 +67,7 @@ namespace SiliconTorch {
 
         // Receive only ATM!  (make public after sound implementation…)
         void write(std::string& data);
-        void write(const uint8_t* data, uint32_t length);
+        void write(const u8* data, u32 length);
 
 
         void readerTask();
diff --git a/CLC-qthing/SiliconTorch/CyanBusCRC.cpp b/CLC-qthing/SiliconTorch/CyanBusCRC.cpp
index fc6a9a7057769ec4febd5ddb3cb43ddf3fd43ec1..7d5cbef8c5b3199800303cb88a1d68252f66e962 100644
--- a/CLC-qthing/SiliconTorch/CyanBusCRC.cpp
+++ b/CLC-qthing/SiliconTorch/CyanBusCRC.cpp
@@ -1,14 +1,14 @@
 #include "CyanBusCRC.hpp"
 
 // C++ system level
-#include <cinttypes>
+// #include <functional>
 
 // ESP32 specific
 #include "esp_log.h"
 #include "esp32/rom/crc.h"
 
 // project specific
-// #include "LambdaTask.hpp"
+#include "SpiderLib/NumberTypes.hpp"
 
 
 static const char* TAG = "CyanBus";
@@ -20,17 +20,17 @@ namespace SiliconTorch {
 
     // Checks CyanBus CRC
     // Note: The last 4 bytes of buffer contain the CRC to check against and are included in the given length
-    bool checkCRC(uint8_t* buffer, uint32_t length) {
+    bool checkCRC(u8* buffer, u32 length) {
 
       if (length < 4) {
         ESP_LOGD(TAG, "CRC calculation failed: Input buffer too small! Got bytes[ %d ] but needs bytes[ >= 4 ]", length);
         return false;
       }
 
-      // uint32_t _init = 0x00000000;
-      uint32_t _init = 0xFFFFFFFF;
-      uint32_t calculatedCRC = crc32_be(_init, buffer, length - 4);
-      uint32_t packetCRC = reinterpret_cast<uint32_t*>(&buffer[length - 4])[0];
+      // u32 _init = 0x00000000;
+      u32 _init = 0xFFFFFFFF;
+      u32 calculatedCRC = crc32_be(_init, buffer, length - 4);
+      u32 packetCRC = reinterpret_cast<u32*>(&buffer[length - 4])[0];
 
       bool crcOK = packetCRC == calculatedCRC;
 
diff --git a/CLC-qthing/SiliconTorch/CyanBusCRC.hpp b/CLC-qthing/SiliconTorch/CyanBusCRC.hpp
index 2cf93e5513c644c7ddb7ac117eb66ff1f32cae8e..23da20d7a1f7b702241f045d0e768ce00fa96699 100644
--- a/CLC-qthing/SiliconTorch/CyanBusCRC.hpp
+++ b/CLC-qthing/SiliconTorch/CyanBusCRC.hpp
@@ -1,13 +1,13 @@
 #pragma once
 
 // C++ system level
-#include <cinttypes>
+// #include <functional>
 
 // ESP32 specific
 // #include "esp_log.h"
 
 // project specific
-// #include "LambdaTask.hpp"
+#include "SpiderLib/NumberTypes.hpp"
 
 
 
@@ -17,7 +17,7 @@ namespace SiliconTorch {
 
     // Checks CyanBus CRC
     // seems to work against Crc32Posix from python crccheck package
-    bool checkCRC(uint8_t* buffer, uint32_t length);
+    bool checkCRC(u8* buffer, u32 length);
 
   }
 
diff --git a/CLC-qthing/SiliconTorch/FxCyanF-classImplementation.cpp b/CLC-qthing/SiliconTorch/FxCyanF-classImplementation.cpp
index 162f12664ef49b1140f98c1d1d0ef6dbeff0bcf2..3db8792d2b07593e99d061898c587519549591ac 100644
--- a/CLC-qthing/SiliconTorch/FxCyanF-classImplementation.cpp
+++ b/CLC-qthing/SiliconTorch/FxCyanF-classImplementation.cpp
@@ -1,29 +1,30 @@
 #include "FxCyanF.hpp"
 
+// C++ system level
+#include <cstdio>
+#include <cstdlib>
+#include <algorithm>
+#include <functional>
+
 // ESP32 specific
 #include "esp_err.h"
 #include "esp_log.h"
 #include "driver/ledc.h"
 #include "tcpip_adapter.h"
 
-// misc
-#include <nlohmann/json.hpp>
+// project specific
+#include "FxVSync.hpp"
+#include "CyanBus.hpp"
+#include "Metrics.hpp"
+#include <SpiderLib/NumberTypes.hpp>
+#include <SpiderLib/ObjectTypes.hpp>
 
 // qthing stuff
 #include <qthing>
 #include <qthing/mqtt_common.hpp>
 
-// C++ system level
-#include <string>
-#include <cstdio>
-#include <cstdlib>
-#include <algorithm>
-#include <functional>
-
-// project specific
-#include "FxVSync.hpp"
-#include "CyanBus.hpp"
-#include "Metrics.hpp"
+// misc
+#include <nlohmann/json.hpp>
 
 
 using namespace qthing;
@@ -33,19 +34,16 @@ using json = nlohmann::json;
 
 namespace SiliconTorch {
 
-  //namespace FxCyanF {
+  namespace FxCyanF {
 
     const char* TAG = "FxCyanF";
+    const str   nvsNameSpace = TAG;
+    const str   HEADER("fxCyanF");
 
-    const std::string HEADER("fxCyanF");
-
-
-    const uint8_t MAX_CHANNELS = 8;  // Maybe 16…?
-
-    const std::string delimiter = ":";
+    const str   delimiter = ":";
 
 
-    static float bytes2float(const uint8_t* bytes) {
+    static float bytes2float(const u8* bytes) {
       float f;
 
       memcpy(&f, bytes, sizeof(f));
@@ -54,7 +52,7 @@ namespace SiliconTorch {
     }
 
 
-    FxCyanF::FxCyanF(uint32_t baseChannel) : metrics(Metrics::Metrics("fxCyan")), baseChannel(baseChannel) {
+    FxCyanF::FxCyanF(u32 baseChannel) : metrics(Metrics::Metrics("fxCyan")), baseChannel(baseChannel) {
 
       this->metrics.registerMetric("frames", "frameCounter");
       this->metrics.registerMetric("errors", "errorCounter");
@@ -78,44 +76,43 @@ namespace SiliconTorch {
 
 
       add_binary_message_callback(this->genDeviceTopic("pwm/$all"), [&](qthing::multipart_message_t message) {
-        if (message.offset == 0) this->handleUnicast((const uint8_t*)message.payload, message.length);
+        if (message.offset == 0) this->handleUnicast((const u8*)message.payload, message.length);
         else ESP_LOGE(TAG, "Invalid message format: Fragmentation is unsupported");
       });
 
 
-      std::string header("fxCyanF");
-      uint8_t headerLength = header.length();
+      u8 headerLength = HEADER.length();
 
-      qthing::addUDPPacketCallback(header, [&, headerLength](udpPacket packet) {
-        this->handleUnicast((const uint8_t*)packet.payload + headerLength, packet.length - headerLength);
+      qthing::addUDPPacketCallback(HEADER, [&, headerLength](udpPacket packet) {
+        this->handleUnicast((const u8*)packet.payload + headerLength, packet.length - headerLength);
       });
 
 
-      std::function<void(const std::string&)> setCh = [&](const std::string& message) {
+      std::function<void(const str&)> setCh = [&](const str& message) {
         long int ch = strtol(message.c_str(), NULL, 0);
         this->setBaseChannel(ch);
       };
 
-      std::function<void(const std::string&)> setFrq = [&](const std::string& message) {
+      std::function<void(const str&)> setFrq = [&](const str& message) {
         long int frq = strtol(message.c_str(), NULL, 0);
         this->setFrequency(frq);
       };
 
-      std::function<void(const std::string&)> setRes = [&](const std::string& message) {
+      std::function<void(const str&)> setRes = [&](const str& message) {
         long int res = strtol(message.c_str(), NULL, 0);
         this->setResolution(res);
       };
 
-      std::function<void(const std::string&)> setFrqRes = [&](const std::string& message) {
-        std::string::size_type found = message.find(delimiter);
+      std::function<void(const str&)> setFrqRes = [&](const str& message) {
+        str::size_type found = message.find(delimiter);
 
-        if (found == std::string::npos) {
+        if (found == str::npos) {
           ESP_LOGE(TAG, "Invalid message format[ %s ]", message.c_str());
           return;
         }
 
-        std::string _frq = message.substr(0, found);
-        std::string _res = message.substr(found + delimiter.length());
+        str _frq = message.substr(0, found);
+        str _res = message.substr(found + delimiter.length());
 
         long int frq = strtol(_frq.c_str(), NULL, 0);
         long int res = strtol(_res.c_str(), NULL, 0);
@@ -129,27 +126,27 @@ namespace SiliconTorch {
       };
 
 
-      std::function<void(const std::string&)> getBCh = [&](const std::string& ignored) {
+      std::function<void(const str&)> getBCh = [&](const str& ignored) {
         this->publishBaseChannel();
       };
 
-      std::function<void(const std::string&)> getChs = [&](const std::string& ignored) {
+      std::function<void(const str&)> getChs = [&](const str& ignored) {
         this->publishChannelCount();
       };
 
-      std::function<void(const std::string&)> getFrq = [&](const std::string& ignored) {
+      std::function<void(const str&)> getFrq = [&](const str& ignored) {
         this->publishFrequency();
       };
 
-      std::function<void(const std::string&)> getRes = [&](const std::string& ignored) {
+      std::function<void(const str&)> getRes = [&](const str& ignored) {
         this->publishResolution();
       };
 
-      std::function<void(const std::string&)> getFrqRes = [&](const std::string& ignored) {
+      std::function<void(const str&)> getFrqRes = [&](const str& ignored) {
         this->publishFrqRes();
       };
 
-      std::function<void(const std::string&)> getListener = [&](const std::string& ignored) {
+      std::function<void(const str&)> getListener = [&](const str& ignored) {
         this->publishListenerInfo();
       };
 
@@ -187,13 +184,13 @@ namespace SiliconTorch {
     }
 
 
-    bool FxCyanF::addChannel(uint8_t gpio) {
+    bool FxCyanF::addChannel(u8 gpio, float initialValue) {
       if (this->channelsConfigured >= MAX_CHANNELS) {
         ESP_LOGE(TAG, "Cannot create channel#[ %i ]! ESP32 hardware limit is #[ %i ]", this->channelsConfigured, MAX_CHANNELS);
         return false;
       }
 
-      uint8_t channel = this->channelsConfigured;
+      u8 channel = this->channelsConfigured;
 
       // TODO: catch channel creation errors from IDF (e.g. on input-only GPIO)
       this->channels[channel] = new Impl::PWMChannel(channel, gpio);
@@ -201,20 +198,21 @@ namespace SiliconTorch {
       char topic[32];
       snprintf(topic, sizeof(topic), "pwm/$%i", channel);
 
-      add_message_callback(this->genDeviceTopic(topic), [&, channel](const std::string& message) {
+      add_message_callback(this->genDeviceTopic(topic), [&, channel](const str& message) {
         this->setPWM(channel, strtof(message.c_str(), NULL));
         this->callPacketCallback();
       });
 
       this->channelsConfigured++;
+      this->setPWM(channel, initialValue);
       return true;
     }
 
 
-    bool FxCyanF::handleUnicast(const uint8_t* data, std::size_t length) {
+    bool FxCyanF::handleUnicast(const u8* data, std::size_t length) {
       std::size_t size = this->getChannelCount() * sizeof(float);
 
-      int32_t diff = length - size;
+      i32 diff = length - size;
       if (diff < 0) {
         ESP_LOGE(TAG, "Invalid |data|[ %d ]: Received ΔB[ %d ] bytes too few", length, -diff);
 
@@ -223,7 +221,7 @@ namespace SiliconTorch {
         return false;
       }
 
-      for (uint8_t ch = 0; ch < this->getChannelCount(); ch++) {
+      for (u8 ch = 0; ch < this->getChannelCount(); ch++) {
         float f = bytes2float(data + ch * sizeof(float));
         this->setPWM(ch, f);
       }
@@ -234,11 +232,11 @@ namespace SiliconTorch {
       return true;
     }
 
-    bool FxCyanF::handleBroadcast(const uint8_t* data, std::size_t length) {
+    bool FxCyanF::handleBroadcast(const u8* data, std::size_t length) {
       std::size_t size = this->getChannelCount() * sizeof(float);
       std::size_t offset = this->getBaseChannel() * sizeof(float);
 
-      int32_t diff = length - offset - size;
+      i32 diff = length - offset - size;
       if (diff < 0) {  // TODO: test thoroughly!
         ESP_LOGE(TAG, "Invalid data length[ %i ]: Received ΔB = %i bytes too few", length, -diff);
 
@@ -247,7 +245,7 @@ namespace SiliconTorch {
         return false;
       }
 
-      for (uint8_t ch = 0; ch < this->getChannelCount(); ch++) {
+      for (u8 ch = 0; ch < this->getChannelCount(); ch++) {
         float f = bytes2float(data + offset + ch * sizeof(float));
         this->setPWM(ch, f);
       }
@@ -259,7 +257,12 @@ namespace SiliconTorch {
     }
 
 
-    void FxCyanF::setPWM(uint8_t channel, float value) {
+    void FxCyanF::setPWM(u8 channel, float value) {
+
+      if (std::isnan(value)) {
+        ESP_LOGW(TAG, "PWM[ NaN ] value for channel[ %i ] out of range", channel);
+        return;
+      }
 
       if (channel >= this->channelsConfigured) {
         ESP_LOGW(TAG, "ChannelID out of range: channel[ %i ]", channel);
@@ -271,8 +274,8 @@ namespace SiliconTorch {
       if (value < 0.0f) value = 0.0f;
       if (value > 1.0f) value = 1.0f;
 
-      uint32_t maxPWM = 1 << (this->resolution - 1);
-      uint32_t pwm = (uint32_t)( value * (maxPWM - 1) );
+      u32 maxPWM = 1 << (this->resolution - 1);
+      u32 pwm = (u32)( value * (maxPWM - 1) );
 
       this->channels[channel]->setPWM(pwm);
     }
@@ -283,7 +286,7 @@ namespace SiliconTorch {
     }
 
 
-    bool FxCyanF::setFrqRes(uint32_t frq_hz, uint8_t res_bits) {
+    bool FxCyanF::setFrqRes(u32 frq_hz, u8 res_bits) {
 
       this->timer_cfg.duty_resolution = (ledc_timer_bit_t)res_bits;
       this->timer_cfg.freq_hz = frq_hz;
@@ -305,10 +308,10 @@ namespace SiliconTorch {
 
     void FxCyanF::registerAtCyanBus(CyanBus::CyanBus& cyanBus) {
     /*
-      uint8_t headerLength = HEADER.length();
+      u8 headerLength = HEADER.length();
 
       cyanBus.packetCallback.add(HEADER, [&, headerLength](const CyanBus::PacketData& packet) {
-        this->handlePacket((uint8_t*)(packet.payload + headerLength), packet.length - headerLength);
+        this->handlePacket((u8*)(packet.payload + headerLength), packet.length - headerLength);
       });
 
       FxVSync::registerAtCyanBus(cyanBus, [&]() {
@@ -317,31 +320,31 @@ namespace SiliconTorch {
     */
     }
 
-    void FxCyanF::setBaseChannel(uint16_t baseChannel) {
+    void FxCyanF::setBaseChannel(u16 baseChannel) {
       this->baseChannel = baseChannel;
     }
 
-    uint16_t FxCyanF::getBaseChannel() {
+    u16 FxCyanF::getBaseChannel() {
       return this->baseChannel;
     }
 
-    uint8_t FxCyanF::getChannelCount() {
+    u8 FxCyanF::getChannelCount() {
       return this->channelsConfigured;
     }
 
-    bool FxCyanF::setFrequency(uint32_t frq_hz) {
+    bool FxCyanF::setFrequency(u32 frq_hz) {
       return this->setFrqRes(frq_hz, this->resolution);
     }
 
-    uint32_t FxCyanF::getFrequency() {
+    u32 FxCyanF::getFrequency() {
       return this->frequency;
     }
 
-    bool FxCyanF::setResolution(uint8_t res_bits) {
+    bool FxCyanF::setResolution(u8 res_bits) {
       return this->setFrqRes(this->frequency, res_bits);
     }
 
-    uint8_t FxCyanF::getResolution() {
+    u8 FxCyanF::getResolution() {
       return this->resolution;
     }
 
@@ -350,12 +353,12 @@ namespace SiliconTorch {
     }
 
 
-    std::string FxCyanF::genDeviceTopic(const char *suffix) {
-      return std::string(DEVICE_NAMESPACE + "fxCyan/") + std::string(suffix);
+    str FxCyanF::genDeviceTopic(const char *suffix) {
+      return str(DEVICE_NAMESPACE + "fxCyan/") + str(suffix);
     }
 
-    std::string FxCyanF::genServiceTopic(const char *suffix) {
-      return std::string("service/fxCyan/") + std::string(suffix);
+    str FxCyanF::genServiceTopic(const char *suffix) {
+      return str("service/fxCyan/") + str(suffix);
     }
 
 
@@ -417,5 +420,5 @@ namespace SiliconTorch {
         }
       }
     }
-//  }
+  }
 }
diff --git a/CLC-qthing/SiliconTorch/FxCyanF-configureFromNVS.cpp b/CLC-qthing/SiliconTorch/FxCyanF-configureFromNVS.cpp
index f5cd73e02095cfe79edc0f1c6c48260ffa0e912c..49e83fd52a7685847586fb3360b25381630633cc 100644
--- a/CLC-qthing/SiliconTorch/FxCyanF-configureFromNVS.cpp
+++ b/CLC-qthing/SiliconTorch/FxCyanF-configureFromNVS.cpp
@@ -1,15 +1,12 @@
 #include "FxCyanF.hpp"
 
 // C++ system level
-#include <string>
-// #include <cstdio>
+#include <cstdio>         // snprintf
 // #include <cstdlib>
 // #include <algorithm>
 // #include <functional>
 
 // ESP32 specific
-#include "nvs.h"
-#include "nvs_flash.h"
 #include "esp_log.h"
 
 // misc
@@ -20,31 +17,81 @@
 // #include <qthing/mqtt_common.hpp>
 
 // project specific
-// #include "FxVSync.hpp"
-// #include "CyanBus.hpp"
-// #include "Metrics.hpp"
+#include "NVSExplorer.hpp"
+#include <SpiderLib/NumberTypes.hpp>
+#include <SpiderLib/ObjectTypes.hpp>
 
 
+const char* TAG_nvs = "FxCyanF-NVS";
+
 
 namespace SiliconTorch {
 
-  // namespace FxCyanF {
+  namespace FxCyanF {
+
+
+    const str ServiceNamespace = "fxCyan";
+
+
+    FxCyanF* configureFromNVS() {
+
+      u8  state = 0;  // disabled -> 0   enabled -> 1
+      state = NVSExplorer::NVSExplorer::instance().getUnsignedInt(ServiceNamespace, "state", state);
+
+      if (state == 0) {
+        ESP_LOGI(TAG_nvs, "Service[ FxCyanF ] disabled[❌]");
+        return NULL;
+      }
+
+      FxCyanF* target = new FxCyanF();
+
+      ESP_LOGI(TAG_nvs, "Service[ FxCyanF ] enabling[✅]…");
+
+      u32 frq = DefaultFrequency;
+      u8  res = DefaultResolution;
+
+      frq = NVSExplorer::NVSExplorer::instance().getUnsignedInt(ServiceNamespace, "frequency", frq);
+      res = NVSExplorer::NVSExplorer::instance().getUnsignedInt(ServiceNamespace, "resolution", res);
+
+
+      ESP_LOGI(TAG_nvs, "Configuring: FxCyanF{ frequency[ %d Hz ]  resolution[ %d Bit ] }", frq, res);
+      target->setFrqRes(frq, res);
+
+      for (u8 ch = 0; ch < MAX_CHANNELS; ch++) {
+
+
+        char buffer[32];
+        snprintf(buffer, 32, "ch%d_gpio", ch);
+
+        u8 gpio = NVSExplorer::NVSExplorer::instance().getUnsignedInt(ServiceNamespace, buffer, 0xFF) & 0xFF;
 
+        snprintf(buffer, 32, "ch%d_pwm", ch);
+        f32 pwm = NVSExplorer::NVSExplorer::instance().getFloat(ServiceNamespace, buffer);
 
-    const std::string nameSpace = "FxCyanF";
+        // NaN == "no value stored" or any other reading error
+        if (std::isnan(pwm)) pwm = 0.0f;
 
+        if (gpio != 0xFF) {  // key exists
 
-    bool configureFromNVS(FxCyanF& target) {
+          if ( target->addChannel(gpio, pwm) ) {  // channel creation successful
+  
+            ESP_LOGI(TAG_nvs, "Configuring: FxCyanF{ channel[ %d ]  gpio[ %d ]  pwm[ %f ] }", ch, gpio, pwm);
 
-      nvs_flash_init();
+            target->setPWM(ch, pwm);
 
-      nvs_handle_t nvs;
-      nvs_open(nameSpace.c_str(), NVS_READONLY, &nvs);
+          } else {
+            ESP_LOGW(TAG_nvs, "Configuring: FxCyanF{ channel[ %d ]  gpio[ %d ] }  FAILED[❌]", ch, gpio);
+            break;
+          }
 
+        } else {
+          break;
+        }
+      }
 
-      return false;
+      return target;
     }
 
 
-  // }
+  }
 }
diff --git a/CLC-qthing/SiliconTorch/FxCyanF.hpp b/CLC-qthing/SiliconTorch/FxCyanF.hpp
index a3fc5e0637b5857d71ecc894740d9ebb336ea4b6..0a7d19e39b619c0db12e4e0d14912f008d5f7d30 100644
--- a/CLC-qthing/SiliconTorch/FxCyanF.hpp
+++ b/CLC-qthing/SiliconTorch/FxCyanF.hpp
@@ -4,53 +4,64 @@
 #include "driver/ledc.h"
 
 // C++ system level
-#include <string>
+#include <cmath>
 #include <functional>
-#include <cinttypes>
 
 // project specific
 #include "CyanBus.hpp"
 #include "Metrics.hpp"
 #include "PWMChannel.hpp"
+#include <SpiderLib/NumberTypes.hpp>
+#include <SpiderLib/ObjectTypes.hpp>
 
 
 
 namespace SiliconTorch {
 
-  //namespace FxCyanF {
+  namespace FxCyanF {
 
-    extern const std::string HEADER;
+    extern const char* TAG;
+    extern const str   nvsNameSpace;  // "fxCyan"
+    extern const str   HEADER;        // "fxCyanF"
+
+    constexpr u8 MAX_CHANNELS = 8;    // vorerst 8
+
+
+    constexpr u32 DefaultFrequency  = 1337;  // Hz
+    constexpr u8  DefaultResolution = 10;    // Bits
+
+
+    using PacketHandledCallback = std::function<void()>;
+    using GammaCorrector        = std::function<float(float)>;
 
-    typedef std::function<void()> PacketHandledCallback;
-    typedef std::function<float(float)> GammaCorrector;
 
     class FxCyanF {
       public:
-        FxCyanF(uint32_t baseChannel = 0);
+        FxCyanF(u32 baseChannel = 0);
 
-        bool addChannel(uint8_t gpio);
+        bool addChannel(u8 gpio, float initialValue = 0.0f);
 
-        void setPWM(uint8_t channel, float value);
+        void setPWM(u8 channel, float value);
 
         void setGammaCorrector(GammaCorrector gammaCorrector);
 
-        uint8_t getChannelCount();
+        u8 getChannelCount();
 
-        void setBaseChannel(uint16_t baseChannel);
-        uint16_t getBaseChannel();
+        void setBaseChannel(u16 baseChannel);
+        u16 getBaseChannel();
 
-        bool setFrequency(uint32_t frq_hz);
-        uint32_t getFrequency();
+        bool setFrequency(u32 frq_hz);
+        u32 getFrequency();
 
-        bool setResolution(uint8_t res_bits);
-        uint8_t getResolution();
+        bool setResolution(u8 res_bits);
+        u8 getResolution();
 
-        bool setFrqRes(uint32_t frq_hz, uint8_t res_bits);
+        bool setFrqRes(u32 frq_hz, u8 res_bits);
 
         void setPacketHandledCallback(PacketHandledCallback callback);
 
-        bool handleUnicast(const uint8_t* data, std::size_t length);
-        bool handleBroadcast(const uint8_t* data, std::size_t length);
+        bool handleUnicast(const u8* data, std::size_t length);
+        bool handleBroadcast(const u8* data, std::size_t length);
 
         void registerAtCyanBus(CyanBus::CyanBus& cyanBus);
 
@@ -66,11 +77,11 @@ namespace SiliconTorch {
 
       private:
 
-        uint32_t frequency = 1000;  // Hz
-        uint8_t resolution =   10;  // bits
+        u32 frequency = 1000;  // Hz
+        u8 resolution =   10;  // bits
 
-        uint32_t baseChannel;
-        uint8_t channelsConfigured = 0;
+        u32 baseChannel;
+        u8 channelsConfigured = 0;
 
         Impl::PWMChannel** channels;
 
@@ -87,7 +98,7 @@ namespace SiliconTorch {
     };
 
 
-    bool configureFromNVS(FxCyanF& target);
+    FxCyanF* configureFromNVS(FxCyanF);
 
-  //}
+  }
 }
diff --git a/CLC-qthing/SiliconTorch/FxCyanRGB8.cpp b/CLC-qthing/SiliconTorch/FxCyanRGB8.cpp
index 24ba38e8568ea5af175ad13e85703de9cc1ecfdf..4351d6ba1060908e4e60e87313ea893f7c92d12a 100644
--- a/CLC-qthing/SiliconTorch/FxCyanRGB8.cpp
+++ b/CLC-qthing/SiliconTorch/FxCyanRGB8.cpp
@@ -3,7 +3,6 @@
 // C++ system level
 #include <string>
 #include <cstring>  // memset
-#include <cinttypes>
 #include <algorithm>
 #include <functional>
 
@@ -14,6 +13,7 @@
 // project specific
 #include "FxVSync.hpp"
 #include "CyanBus.hpp"
+#include "SpiderLib/NumberTypes.hpp"
 
 // qthing stuff
 // #include ""
@@ -27,7 +27,7 @@ namespace SiliconTorch {
     const std::string HEADER("fxCyanRGB8");
 
 
-    FxCyanRGB8::FxCyanRGB8(uint16_t leds, uint16_t startIdx) : leds(leds), startIdx(startIdx) {
+    FxCyanRGB8::FxCyanRGB8(u16 leds, u16 startIdx) : leds(leds), startIdx(startIdx) {
 
       buffer0 = new qthing::RGB[leds];
       buffer1 = new qthing::RGB[leds];
@@ -39,7 +39,7 @@ namespace SiliconTorch {
 
     }
 
-    void FxCyanRGB8::handlePacket(uint8_t* buffer, std::size_t length) {
+    void FxCyanRGB8::handlePacket(u8* buffer, std::size_t length) {
 
       if (length < 3) {
         ESP_LOGE(HEADER.c_str(), "Wrong |buffer|[ %d ]: Must be greater than 2!", length);
@@ -53,13 +53,13 @@ namespace SiliconTorch {
 
 
       Pixel* packetPx = reinterpret_cast<Pixel*>(buffer+2);
-      uint16_t packetPxs = (length - 2) / 3;
-      uint16_t packetStartIdx = (buffer[0] << 8) | buffer[1];
+      u16 packetPxs = (length - 2) / 3;
+      u16 packetStartIdx = (buffer[0] << 8) | buffer[1];
 
 
       if (packetStartIdx == startIdx) {
 
-        for (uint16_t px = 0; px < std::min(leds, packetPxs); px++) {
+        for (u16 px = 0; px < std::min(leds, packetPxs); px++) {
           buffer1[px].r = packetPx[px].r / 255.0f;
           buffer1[px].g = packetPx[px].g / 255.0f;
           buffer1[px].b = packetPx[px].b / 255.0f;
@@ -67,9 +67,9 @@ namespace SiliconTorch {
 
       } else if(packetStartIdx > startIdx) {
 
-        uint16_t delta = packetStartIdx - startIdx;
+        u16 delta = packetStartIdx - startIdx;
 
-        for (uint16_t px = delta; px < std::min(leds, (uint16_t)(packetPxs + delta)); px++) {
+        for (u16 px = delta; px < std::min(leds, (u16)(packetPxs + delta)); px++) {
           buffer1[px].r = packetPx[px - delta].r / 255.0f;
           buffer1[px].g = packetPx[px - delta].g / 255.0f;
           buffer1[px].b = packetPx[px - delta].b / 255.0f;
@@ -77,12 +77,12 @@ namespace SiliconTorch {
 
       } else if (packetStartIdx < startIdx) {
 
-        uint16_t delta = startIdx - packetStartIdx;
+        u16 delta = startIdx - packetStartIdx;
 
         // Packet does not contain any pixels for us
         if (packetPxs < delta) return;
 
-        for (uint16_t px = 0; px < std::min(leds, (uint16_t)(packetPxs - delta)); px++) {
+        for (u16 px = 0; px < std::min(leds, (u16)(packetPxs - delta)); px++) {
           buffer1[px].r = packetPx[px + delta].r / 255.0f;
           buffer1[px].g = packetPx[px + delta].g / 255.0f;
           buffer1[px].b = packetPx[px + delta].b / 255.0f;
@@ -92,10 +92,10 @@ namespace SiliconTorch {
 
     void FxCyanRGB8::registerAtCyanBus(CyanBus::CyanBus& cyanBus) {
 
-      uint8_t headerLength = HEADER.length();
+      u8 headerLength = HEADER.length();
 
       cyanBus.packetCallback.add(HEADER, [&, headerLength](const SiliconTorch::CyanBus::PacketData& packet) {
-        this->handlePacket((uint8_t*)(packet.payload + headerLength), packet.length - headerLength);
+        this->handlePacket((u8*)(packet.payload + headerLength), packet.length - headerLength);
       });
 
       FxVSync::registerAtCyanBus(cyanBus, [&]() {
@@ -108,17 +108,17 @@ namespace SiliconTorch {
       if (!udpHandlerRegistered) {
         udpHandlerRegistered = true;
 
-        uint8_t headerLength = HEADER.length();
+        u8 headerLength = HEADER.length();
 
         qthing::addUDPPacketCallback(HEADER, [&, headerLength](qthing::udpPacket packet) {
-          this->handlePacket((uint8_t*)(packet.payload + headerLength), packet.length - headerLength);
+          this->handlePacket((u8*)(packet.payload + headerLength), packet.length - headerLength);
           requestBufferSwap();
         });
       }
     }
 
     // qthing::Animator
-    qthing::RGB FxCyanRGB8::render(uint16_t addr) {
+    qthing::RGB FxCyanRGB8::render(u16 addr) {
       if (addr < leds) {
         return buffer0[addr];
       } else {
@@ -142,7 +142,7 @@ namespace SiliconTorch {
       buffer0 = buffer1;
       buffer1 = tmp;
 
-      for (uint16_t px = 0; px < leds; px++){
+      for (u16 px = 0; px < leds; px++){
         buffer1[px].r = 0;
         buffer1[px].g = 0;
         buffer1[px].b = 0;
diff --git a/CLC-qthing/SiliconTorch/FxCyanRGB8.hpp b/CLC-qthing/SiliconTorch/FxCyanRGB8.hpp
index 4901f07a1d571ac3ecbb8729b8b87457ace88041..769543bdfc6bd0bcaf8b79d73332af2f7832f556 100644
--- a/CLC-qthing/SiliconTorch/FxCyanRGB8.hpp
+++ b/CLC-qthing/SiliconTorch/FxCyanRGB8.hpp
@@ -2,7 +2,6 @@
 
 // C++ system level
 #include <string>
-#include <cinttypes>
 #include <functional>
 
 // ESP32 specific
@@ -11,6 +10,7 @@
 
 // project specific
 #include "CyanBus.hpp"
+#include "SpiderLib/NumberTypes.hpp"
 
 // qthing stuff
 #include <qthing>
@@ -22,16 +22,16 @@ namespace SiliconTorch {
   namespace FxCyanRGB8 {
 
     typedef struct __attribute__((__packed__)) {
-      uint8_t r;
-      uint8_t g;
-      uint8_t b;
+      u8 r;
+      u8 g;
+      u8 b;
     } Pixel;
 
     extern const std::string HEADER;
 
     class FxCyanRGB8 : public qthing::Animation<qthing::RGB> {
       public:
-        FxCyanRGB8(uint16_t leds, uint16_t startIdx = 0);
+        FxCyanRGB8(u16 leds, u16 startIdx = 0);
 
         void getAnimator();
 
@@ -42,11 +42,11 @@ namespace SiliconTorch {
         void registerUDPHandler();
 
         // Strip the header before calling this function!
-        void handlePacket(uint8_t* buffer, std::size_t length);
+        void handlePacket(u8* buffer, std::size_t length);
 
         // qthing::Animator
         void step();
-        qthing::RGB render(uint16_t addr);
+        qthing::RGB render(u16 addr);
 
       private:
 
@@ -56,8 +56,8 @@ namespace SiliconTorch {
         bool swapRequested = false;
         bool udpHandlerRegistered = false;
 
-        uint16_t leds;
-        uint16_t startIdx;
+        u16 leds;
+        u16 startIdx;
 
 
         void swapBuffers();
diff --git a/CLC-qthing/SiliconTorch/FxPublish.cpp b/CLC-qthing/SiliconTorch/FxPublish.cpp
index 99e8859c91cb1273e66db6eb4720eddc2f550b62..27680c1a9646878940969a45d291ceb11e052d63 100644
--- a/CLC-qthing/SiliconTorch/FxPublish.cpp
+++ b/CLC-qthing/SiliconTorch/FxPublish.cpp
@@ -4,7 +4,6 @@
 #include <string>
 // #include <cstring>     // memset, strncmp
 // #include <cstdlib>     // TODO: is this for memcpy?
-// #include <cinttypes>
 // #include <functional>
 
 // ESP32 specific
@@ -12,6 +11,7 @@
 
 // project specific
 #include "CyanBus.hpp"
+#include "SpiderLib/NumberTypes.hpp"
 
 // qthing stuff
 #include <qthing>
diff --git a/CLC-qthing/SiliconTorch/FxVSync.cpp b/CLC-qthing/SiliconTorch/FxVSync.cpp
index a536a6b0d2788eb2ab955e052cc004c9845d1e64..b1bb375041dbccb73faead3fd7fd7751f96cc62b 100644
--- a/CLC-qthing/SiliconTorch/FxVSync.cpp
+++ b/CLC-qthing/SiliconTorch/FxVSync.cpp
@@ -8,6 +8,8 @@
 
 // project specific
 #include "CyanBus.hpp"
+#include "SpiderLib/NumberTypes.hpp"
+
 
 // qthing stuff
 // #include ""
diff --git a/CLC-qthing/SiliconTorch/LambdaTask.cpp b/CLC-qthing/SiliconTorch/LambdaTask.cpp
index 18a18f7a201ed1d79a86eee45ba37bd31a17da99..5d9fef945dd1380357ad3ed7cbe97bb3a89db1d9 100644
--- a/CLC-qthing/SiliconTorch/LambdaTask.cpp
+++ b/CLC-qthing/SiliconTorch/LambdaTask.cpp
@@ -1,8 +1,12 @@
 #include "LambdaTask.hpp"
 
+// ESP32 system level
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
 
+// project specific
+#include "SpiderLib/NumberTypes.hpp"
+
 
 
 static void taskWrapper(void* body) {
@@ -10,8 +14,8 @@ static void taskWrapper(void* body) {
   (*f)();
 }
 
-static uint16_t taskID = 0;
-static uint16_t nextID() {
+static u16 taskID = 0;
+static u16 nextID() {
   return taskID++;  // TODO: increment thread-safe!
 }
 
@@ -23,7 +27,7 @@ SiliconTorch::Util::LambdaTask::LambdaTask(SiliconTorch::Util::Function0 body) :
   // TODO: allow other niceness than one
   // TODO: allow pinning to other cores than app CPU
 
-  uint8_t priority = 1;
+  u8 priority = 1;
 
   std::function<void()> _body = [&]() {
     this->body();
diff --git a/CLC-qthing/SiliconTorch/Metrics.cpp b/CLC-qthing/SiliconTorch/Metrics.cpp
index 6372778c8d5e3d95a2cd3f8acc02b46e149c9e72..33ba042724047c73b6506e89d1148693c57c19be 100644
--- a/CLC-qthing/SiliconTorch/Metrics.cpp
+++ b/CLC-qthing/SiliconTorch/Metrics.cpp
@@ -1,5 +1,8 @@
 #include "Metrics.hpp"
 
+// C++ system level
+#include <climits>
+
 // ESP32 specific
 #include "freertos/FreeRTOS.h"
 // #include "freertos/semphr.h"
@@ -14,12 +17,9 @@
 // qthing stuff
 #include <qthing>
 
-// C++ system level
-#include <climits>
-#include <cinttypes>
-
 // project specific
 #include "../SpiderLib/SNTP.hpp"
+#include "SpiderLib/NumberTypes.hpp"
 
 
 using namespace qthing;
@@ -29,7 +29,7 @@ using json = nlohmann::json;
 static const char* TAG = "Metrics";
 
 
-static uint8_t nextTask = 0;
+static u8 nextTask = 0;
 static void methodTaskWrapper(void* parameter) {
   std::function<void()>* f = (std::function<void()>*)parameter;
   (*f)();
@@ -40,8 +40,8 @@ namespace SiliconTorch {
 
   namespace Metrics {
 
-    uint32_t uptime_ms() {
-      return (uint32_t)(esp_timer_get_time() / 1000L);
+    u32 uptime_ms() {
+      return (u32)(esp_timer_get_time() / 1000L);
     }
 
     Metrics::Metrics(const std::string& nameSpace) : nameSpace(nameSpace) {
@@ -63,7 +63,7 @@ namespace SiliconTorch {
         ESP_LOGI(TAG, "Found my birth timestamp[ %lld ]", this->birth);
 
         SpiderLib::SNTP::instance().registerTimeSyncHandler([&](){
-          uint64_t now = (uint64_t)std::time(NULL);
+          u64 now = (u64)std::time(NULL);
 
           float age = (float)(now - this->birth);
           age /= 24.0f * 60.0f * 60.0f;
@@ -73,7 +73,7 @@ namespace SiliconTorch {
       } else {
         SpiderLib::SNTP::instance().registerTimeSyncHandler([&](){
 
-          this->birth = (uint64_t)std::time(NULL);
+          this->birth = (u64)std::time(NULL);
 
           esp_err_t err = nvs_set_u64(this->nvs, "birth", this->birth);
 
@@ -149,7 +149,7 @@ namespace SiliconTorch {
         it->second->save(&this->nvs);
 
 
-      uint32_t now = uptime_ms();
+      u32 now = uptime_ms();
 
       lifeTime += now - lifeTimeSaved;
       lifeTimeSaved = now;
@@ -172,7 +172,7 @@ namespace SiliconTorch {
 
       while (true) {
 
-        uint32_t now = uptime_ms();
+        u32 now = uptime_ms();
 
         if ((now - lastSaved    ) / 1000 > saveInterval   ) saveData();
         if ((now - lastPublished) / 1000 > publishInterval) publishData();
@@ -194,7 +194,7 @@ namespace SiliconTorch {
     }
 
 
-    uint64_t Metrics::getCounterValue(const std::string& shortName) {
+    u64 Metrics::getCounterValue(const std::string& shortName) {
 
       auto result = counters.find(shortName);
 
@@ -250,7 +250,7 @@ namespace SiliconTorch {
       }
     }
 
-    uint64_t CounterMetric::getValue() {
+    u64 CounterMetric::getValue() {
       return value;
     }
 
@@ -272,23 +272,23 @@ namespace SiliconTorch {
     }
 
     // pre-increment
-    uint64_t& CounterMetric::CounterMetric::operator++() {
+    u64& CounterMetric::CounterMetric::operator++() {
       inc(); return value;
     }
 
     // pre-decrement
-    uint64_t& CounterMetric::CounterMetric::operator--() {
+    u64& CounterMetric::CounterMetric::operator--() {
       dec(); return value;
     }
 
     // post-increment
-    uint64_t CounterMetric::CounterMetric::operator++(int ignored) {
-      uint64_t out = value; inc(); return out;
+    u64 CounterMetric::CounterMetric::operator++(int ignored) {
+      u64 out = value; inc(); return out;
     }
 
     // post-decrement
-    uint64_t CounterMetric::CounterMetric::operator--(int ignored) {
-      uint64_t out = value; dec(); return out;
+    u64 CounterMetric::CounterMetric::operator--(int ignored) {
+      u64 out = value; dec(); return out;
     }
   }
 }
diff --git a/CLC-qthing/SiliconTorch/Metrics.hpp b/CLC-qthing/SiliconTorch/Metrics.hpp
index 7b00f4193445b81fcb6cca54e817a4578e43d792..e651959e65fe2d90f4fb27cf107b94669ed18715 100644
--- a/CLC-qthing/SiliconTorch/Metrics.hpp
+++ b/CLC-qthing/SiliconTorch/Metrics.hpp
@@ -9,6 +9,9 @@
 // ESP32 specific
 #include "nvs.h"
 
+// project specific
+#include "SpiderLib/NumberTypes.hpp"
+
 
 
 namespace SiliconTorch {
@@ -17,7 +20,7 @@ namespace SiliconTorch {
 
     typedef std::function<void()> Incrementer;
 
-    uint32_t uptime_ms();  // rolls over after about 136 years
+    u32 uptime_ms();  // rolls over after about 136 years
 
     class CounterMetric {
       public:
@@ -28,7 +31,7 @@ namespace SiliconTorch {
 
         bool dirty = false;
 
-        uint64_t getValue();
+        u64 getValue();
 
         void inc();
         void dec();
@@ -37,15 +40,15 @@ namespace SiliconTorch {
         void save(nvs_handle_t* nvs);       // saves only if enoughg time elapsed
         void forceSave(nvs_handle_t* nvs);  // saves value immediately
 
-        uint64_t& operator++();    // pre-increment
-        uint64_t& operator--();    // pre-decrement
+        u64& operator++();    // pre-increment
+        u64& operator--();    // pre-decrement
 
-        uint64_t operator++(int);  // post-increment
-        uint64_t operator--(int);  // post-decrement
+        u64 operator++(int);  // post-increment
+        u64 operator--(int);  // post-decrement
 
       private:
 
-        uint64_t value = 0;
+        u64 value = 0;
 
     };
 
@@ -59,7 +62,7 @@ namespace SiliconTorch {
          * returns the actual value or 0 for unknown counters
          * also supports getting the special bootCnt, uptime and lifetime metrics
         */
-        uint64_t getCounterValue(const std::string& shortName);
+        u64 getCounterValue(const std::string& shortName);
 
         Incrementer generateMetricIncrementer(const std::string& shortName);
 
@@ -72,21 +75,21 @@ namespace SiliconTorch {
 
       private:
 
-        uint32_t saveInterval      = 60*60;        // seconds
-        uint32_t publishInterval   = 60;           // seconds
+        u32 saveInterval      = 60*60;        // seconds
+        u32 publishInterval   = 60;           // seconds
 
-        uint32_t lastSaved         = uptime_ms();  // unix timestamp
-        uint32_t lastPublished     = uptime_ms();  // unix timestamp
+        u32 lastSaved         = uptime_ms();  // unix timestamp
+        u32 lastPublished     = uptime_ms();  // unix timestamp
 
-        uint32_t tickPeriod        = 3000;         // milli seconds
+        u32 tickPeriod        = 3000;         // milli seconds
 
-        uint64_t lifeTime          = 0;            // milli seconds
-        uint64_t lifeTimeSaved     = 0;            // milli seconds
+        u64 lifeTime          = 0;            // milli seconds
+        u64 lifeTimeSaved     = 0;            // milli seconds
 
-        uint32_t bootCnt           = 0;
-        uint32_t bootCntSaveUptime = 60;           // seconds
+        u32 bootCnt           = 0;
+        u32 bootCntSaveUptime = 60;           // seconds
 
-        uint64_t birth             = 0;            // unix timestamp of first device activation
+        u64 birth             = 0;            // unix timestamp of first device activation
 
         void tickTask();
         void saveBootCntTask();
diff --git a/CLC-qthing/SiliconTorch/NVSExplorer.cpp b/CLC-qthing/SiliconTorch/NVSExplorer.cpp
index b3230b3989d1fb9154222539b228ec5371710ab7..65ffb10a1f00d89679333827d935cce78e2fcd32 100644
--- a/CLC-qthing/SiliconTorch/NVSExplorer.cpp
+++ b/CLC-qthing/SiliconTorch/NVSExplorer.cpp
@@ -1,23 +1,28 @@
-#include "CapMan.hpp"
+#include "NVSExplorer.hpp"
 
 // C++ system level
 #include <set>
-// #include <cstring>     // memset, strncmp
-// #include <cstdlib>     // TODO: is this for memcpy?
-#include <cinttypes>
+#include <cmath>
+#include <limits>      // mix/max integer values; used for parsing network data
+#include <vector>
+#include <cstring>     // memset, memcpy, strncmp
+#include <cstdlib>     // std::strtof and such…
 // #include <functional>
 
 // ESP32 specific
 #include "esp_log.h"
 #include "nvs_flash.h"
-// #include "esp_err.h"
+#include "esp_err.h"
 // #include "driver/uart.h"
 
 // project specific
-// #include ""
+#include <Types.hpp>
+#include <SpiderLib/Util.hpp>
 
 // qthing stuff
-// #include <qthing>
+#include <qthing>
+#include <qthing/mqtt_common.hpp>
+
 
 
 
@@ -26,12 +31,967 @@ namespace SiliconTorch {
   namespace NVSExplorer {
 
 
-    // NVSExplorer::NVSExplorer() {
-    void BullShit() {
+    const char* TAG = "NVSExplorer";
+
+
+    NVSExplorer::NVSExplorer() {
+
+      ESP_LOGI(TAG, "Starting NVSExplorer[📡]");
 
       nvs_flash_init();
 
-      ESP_LOGW("NVS", "Scanning 👀");
+
+      registerLambdas0();
+      registerLambdas1();
+
+    }  // end NVSExplorer()-ctor
+
+
+
+    void NVSExplorer::registerLambdas0() {
+
+      u16 deviceTopicLEN = requestTopic("").length();
+
+      auto wrapMessageHandler = [deviceTopicLEN](std::function<void(std::vector<str>&, qthing::multipart_message_t)> handler) {
+        return [handler, deviceTopicLEN](qthing::multipart_message_t msg) {
+          if (msg.length == msg.total_length && msg.offset == 0) {
+
+            str localTopic(msg.topic.c_str() + deviceTopicLEN);
+            std::vector<str> topicParts = SpiderLib::Util::split(localTopic, '/');
+
+            handler(topicParts, msg);
+          } else {
+            ESP_LOGW(TAG, "Multipart messages are not supported atm.  topic[ %s ]", msg.topic.c_str());
+          }
+        };
+      };
+
+
+
+      // TODO: publish error if NS not found…?!
+      qthing::add_binary_message_callback(requestTopic("ls/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+        
+        str delimiter = " ";
+        char* buffer = NULL;
+
+        if (msg.length > 0) {
+          buffer = new char[msg.length + 1];
+          snprintf(buffer, msg.length + 1, "%s", msg.payload);
+          delimiter = str(buffer);
+        }
+
+        auto keys = listKeys(topic[1]);
+        str msgOut = SpiderLib::Util::join(keys, delimiter);
+
+        qthing::publish_message(responseTopic(topic[1]), msgOut);
+
+        if (buffer != NULL) delete buffer;
+      } ));
+
+
+
+      qthing::add_binary_message_callback(requestTopic("ls"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+        
+        str delimiter = " ";
+        char* buffer = NULL;
+
+        if (msg.length > 0) {
+          buffer = new char[msg.length + 1];
+          snprintf(buffer, msg.length + 1, "%s", msg.payload);
+          delimiter = str(buffer);
+        }
+
+        auto nameSpaces = listNamespaces();
+        str msgOut = SpiderLib::Util::join(nameSpaces, delimiter);
+
+        qthing::publish_message(responseTopic("ls"), msgOut);
+
+        if (buffer != NULL) delete buffer;
+      } ));
+
+
+
+      qthing::add_binary_message_callback(requestTopic("rm/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+        this->rmKey(topic[1], topic[2]);
+
+        // publish error…?
+      } ));
+
+
+
+      qthing::add_binary_message_callback(requestTopic("get_float/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+        float value = this->getFloat(topic[1], topic[2]);
+
+        if (!std::isnan(value)) {
+
+          char buffer[64];
+          snprintf(buffer, 64, "%f", value);
+
+          qthing::publish_message(responseTopic("get_float", topic[1], topic[2]), str(buffer));
+        } else {
+          // publish error…?
+
+          ESP_LOGW(TAG, "Retrieving float[] from  namespace[ %s ]  key[ %s ]  FAILED", topic[1].c_str(), topic[2].c_str());
+        }
+      } ));
+
+
+
+      qthing::add_binary_message_callback(requestTopic("get_double/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+        double value = this->getDouble(topic[1], topic[2]);
+
+        if (!std::isnan(value)) {
+
+          char buffer[64];
+          snprintf(buffer, 64, "%f", value);
+
+          qthing::publish_message(responseTopic("get_double", topic[1], topic[2]), str(buffer));
+        } else {
+          // publish error…?
+
+          ESP_LOGW(TAG, "Retrieving double[] from  namespace[ %s ]  key[ %s ]  FAILED", topic[1].c_str(), topic[2].c_str());
+        }
+      } ));
+
+
+
+      qthing::add_binary_message_callback(requestTopic("set_float/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+
+        char* buffer = new char[msg.length + 1];
+        snprintf(buffer, msg.length + 1, "%s", msg.payload);
+
+        float value = std::strtof(buffer, NULL);
+
+        if ( this->setFloat(topic[1], topic[2], value) )
+             ESP_LOGI(TAG, "Set  namespace[ %s ]  key[ %s ]  to float[ %f ]",             topic[1].c_str(), topic[2].c_str(), value);
+        else ESP_LOGW(TAG, "Setting  namespace[ %s ]  key[ %s ]  to float[ %f ]  FAILED", topic[1].c_str(), topic[2].c_str(), value);
+
+        // publish error…?
+      } ));
+
+
+
+      qthing::add_binary_message_callback(requestTopic("set_double/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+
+        char* buffer = new char[msg.length + 1];
+        snprintf(buffer, msg.length + 1, "%s", msg.payload);
+
+        double value = std::strtod(buffer, NULL);
+
+        if ( this->setDouble(topic[1], topic[2], value) )
+             ESP_LOGI(TAG, "Set namespace[ %s ]  key[ %s ] to double[ %f ]",             topic[1].c_str(), topic[2].c_str(), value);
+        else ESP_LOGW(TAG, "Setting namespace[ %s ]  key[ %s ] to double[ %f ]  FAILED", topic[1].c_str(), topic[2].c_str(), value);
+
+        // publish error…?
+      } ));
+
+
+
+      qthing::add_binary_message_callback(requestTopic("get_u8/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+
+        nvs_handle_t nvs;
+        if ( nvs_open(topic[1].c_str(), NVS_READONLY, &nvs) == ESP_OK ) {
+
+          u8 value = 0;
+          if ( nvs_get_u8(nvs, topic[2].c_str(), &value) == ESP_OK ) {
+
+            char buffer[32];
+            snprintf(buffer, 32, "%d", value);
+            qthing::publish_message(responseTopic("get_u8", topic[1], topic[2]), str(buffer));
+
+          } else {
+            // publish error…?
+
+            ESP_LOGW(TAG, "Retrieving u8[] from  namespace[ %s ]  key[ %s ]  FAILED", topic[1].c_str(), topic[2].c_str());
+          }
+          nvs_close(nvs);
+        }
+      } ));
+
+
+      qthing::add_binary_message_callback(requestTopic("get_u16/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+
+        nvs_handle_t nvs;
+        if ( nvs_open(topic[1].c_str(), NVS_READONLY, &nvs) == ESP_OK ) {
+
+          u16 value = 0;
+          if ( nvs_get_u16(nvs, topic[2].c_str(), &value) == ESP_OK ) {
+
+            char buffer[32];
+            snprintf(buffer, 32, "%d", value);
+            qthing::publish_message(responseTopic("get_u16", topic[1], topic[2]), str(buffer));
+
+          } else {
+            // publish error…?
+
+            ESP_LOGW(TAG, "Retrieving u16[] from  namespace[ %s ]  key[ %s ]  FAILED", topic[1].c_str(), topic[2].c_str());
+          }
+          nvs_close(nvs);
+        }
+      } ));
+
+
+      qthing::add_binary_message_callback(requestTopic("get_u32/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+
+        nvs_handle_t nvs;
+        if ( nvs_open(topic[1].c_str(), NVS_READONLY, &nvs) == ESP_OK ) {
+
+          u32 value = 0;
+          if ( nvs_get_u32(nvs, topic[2].c_str(), &value) == ESP_OK ) {
+
+            char buffer[32];
+            snprintf(buffer, 32, "%d", value);
+            qthing::publish_message(responseTopic("get_u32", topic[1], topic[2]), str(buffer));
+
+          } else {
+            // publish error…?
+
+            ESP_LOGW(TAG, "Retrieving u32[] from  namespace[ %s ]  key[ %s ]  FAILED", topic[1].c_str(), topic[2].c_str());
+          }
+          nvs_close(nvs);
+        }
+      } ));
+
+
+      qthing::add_binary_message_callback(requestTopic("get_u64/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+
+        nvs_handle_t nvs;
+        if ( nvs_open(topic[1].c_str(), NVS_READONLY, &nvs) == ESP_OK ) {
+
+          u64 value = 0;
+          if ( nvs_get_u64(nvs, topic[2].c_str(), &value) == ESP_OK ) {
+
+            char buffer[32];
+            snprintf(buffer, 32, "%lld", value);
+            qthing::publish_message(responseTopic("get_u64", topic[1], topic[2]), str(buffer));
+
+          } else {
+            // publish error…?
+
+            ESP_LOGW(TAG, "Retrieving u64[] from  namespace[ %s ]  key[ %s ]  FAILED", topic[1].c_str(), topic[2].c_str());
+          }
+          nvs_close(nvs);
+        }
+      } ));
+
+
+      qthing::add_binary_message_callback(requestTopic("get_i8/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+
+        nvs_handle_t nvs;
+        if ( nvs_open(topic[1].c_str(), NVS_READONLY, &nvs) == ESP_OK ) {
+
+          i8 value = 0;
+          if ( nvs_get_i8(nvs, topic[2].c_str(), &value) == ESP_OK ) {
+
+            char buffer[32];
+            snprintf(buffer, 32, "%d", value);
+            qthing::publish_message(responseTopic("get_i8", topic[1], topic[2]), str(buffer));
+
+          } else {
+            // publish error…?
+
+            ESP_LOGW(TAG, "Retrieving i8[] from  namespace[ %s ]  key[ %s ]  FAILED", topic[1].c_str(), topic[2].c_str());
+          }
+          nvs_close(nvs);
+        }
+      } ));
+
+
+      qthing::add_binary_message_callback(requestTopic("get_i16/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+
+        nvs_handle_t nvs;
+        if ( nvs_open(topic[1].c_str(), NVS_READONLY, &nvs) == ESP_OK ) {
+
+          i16 value = 0;
+          if ( nvs_get_i16(nvs, topic[2].c_str(), &value) == ESP_OK ) {
+
+            char buffer[32];
+            snprintf(buffer, 32, "%d", value);
+            qthing::publish_message(responseTopic("get_i16", topic[1], topic[2]), str(buffer));
+
+          } else {
+            // publish error…?
+
+            ESP_LOGW(TAG, "Retrieving i16[] from  namespace[ %s ]  key[ %s ]  FAILED", topic[1].c_str(), topic[2].c_str());
+          }
+          nvs_close(nvs);
+        }
+      } ));
+
+
+      qthing::add_binary_message_callback(requestTopic("get_i32/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+
+        nvs_handle_t nvs;
+        if ( nvs_open(topic[1].c_str(), NVS_READONLY, &nvs) == ESP_OK ) {
+
+          i32 value = 0;
+          if ( nvs_get_i32(nvs, topic[2].c_str(), &value) == ESP_OK ) {
+
+            char buffer[32];
+            snprintf(buffer, 32, "%d", value);
+            qthing::publish_message(responseTopic("get_i32", topic[1], topic[2]), str(buffer));
+
+          } else {
+            // publish error…?
+
+            ESP_LOGW(TAG, "Retrieving i32[] from  namespace[ %s ]  key[ %s ]  FAILED", topic[1].c_str(), topic[2].c_str());
+          }
+          nvs_close(nvs);
+        }
+      } ));
+
+
+      qthing::add_binary_message_callback(requestTopic("get_i64/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+
+        nvs_handle_t nvs;
+        if ( nvs_open(topic[1].c_str(), NVS_READONLY, &nvs) == ESP_OK ) {
+
+          i64 value = 0;
+          if ( nvs_get_i64(nvs, topic[2].c_str(), &value) == ESP_OK ) {
+
+            char buffer[32];
+            snprintf(buffer, 32, "%lld", value);
+            qthing::publish_message(responseTopic("get_i64", topic[1], topic[2]), str(buffer));
+
+          } else {
+            // publish error…?
+
+            ESP_LOGW(TAG, "Retrieving i64[] from  namespace[ %s ]  key[ %s ]  FAILED", topic[1].c_str(), topic[2].c_str());
+          }
+          nvs_close(nvs);
+        }
+      } ));
+
+
+    }
+
+
+
+    void NVSExplorer::registerLambdas1() {
+
+      u16 deviceTopicLEN = requestTopic("").length();
+
+      auto wrapMessageHandler = [deviceTopicLEN](std::function<void(std::vector<str>&, qthing::multipart_message_t)> handler) {
+        return [handler, deviceTopicLEN](qthing::multipart_message_t msg) {
+          if (msg.length == msg.total_length && msg.offset == 0) {
+
+            str localTopic(msg.topic.c_str() + deviceTopicLEN);
+            std::vector<str> topicParts = SpiderLib::Util::split(localTopic, '/');
+
+            handler(topicParts, msg);
+          } else {
+            ESP_LOGW(TAG, "Multipart messages are not supported atm.  topic[ %s ]", msg.topic.c_str());
+          }
+        };
+      };
+
+
+
+      qthing::add_binary_message_callback(requestTopic("set_u8/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+
+        char* buffer = new char[msg.length + 1];
+        snprintf(buffer, msg.length + 1, "%s", msg.payload);
+
+        u64 value = std::strtoull(buffer, NULL, 10);
+
+        const u8 u8_max = std::numeric_limits<u8>::max();
+        if (value > u8_max) value = u8_max;
+
+        if ( this->setU8(topic[1], topic[2], static_cast<u8>(value)) )
+             ESP_LOGI(TAG, "Set  namespace[ %s ]  key[ %s ]  to u8[ %lld ]",             topic[1].c_str(), topic[2].c_str(), value);
+        else ESP_LOGW(TAG, "Setting  namespace[ %s ]  key[ %s ]  to u8[ %lld ]  FAILED", topic[1].c_str(), topic[2].c_str(), value);
+        // publish error…?
+      } ));
+
+
+      qthing::add_binary_message_callback(requestTopic("set_u16/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+
+        char* buffer = new char[msg.length + 1];
+        snprintf(buffer, msg.length + 1, "%s", msg.payload);
+
+        u64 value = std::strtoull(buffer, NULL, 10);
+
+        const u16 u16_max = std::numeric_limits<u16>::max();
+        if (value > u16_max) value = u16_max;
+
+        if ( this->setU16(topic[1], topic[2], static_cast<u16>(value)) )
+             ESP_LOGI(TAG, "Set  namespace[ %s ]  key[ %s ]  to u16[ %lld ]",             topic[1].c_str(), topic[2].c_str(), value);
+        else ESP_LOGW(TAG, "Setting  namespace[ %s ]  key[ %s ]  to u16[ %lld ]  FAILED", topic[1].c_str(), topic[2].c_str(), value);
+        // publish error…?
+      } ));
+
+
+      qthing::add_binary_message_callback(requestTopic("set_u32/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+
+        char* buffer = new char[msg.length + 1];
+        snprintf(buffer, msg.length + 1, "%s", msg.payload);
+
+        u64 value = std::strtoull(buffer, NULL, 10);
+
+        const u32 u32_max = std::numeric_limits<u32>::max();
+        if (value > u32_max) value = u32_max;
+
+        if ( this->setU32(topic[1], topic[2], static_cast<u32>(value)) )
+             ESP_LOGI(TAG, "Set  namespace[ %s ]  key[ %s ]  to u32[ %lld ]",             topic[1].c_str(), topic[2].c_str(), value);
+        else ESP_LOGW(TAG, "Setting  namespace[ %s ]  key[ %s ]  to u32[ %lld ]  FAILED", topic[1].c_str(), topic[2].c_str(), value);
+        // publish error…?
+      } ));
+
+
+      qthing::add_binary_message_callback(requestTopic("set_u64/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+
+        char* buffer = new char[msg.length + 1];
+        snprintf(buffer, msg.length + 1, "%s", msg.payload);
+
+        u64 value = std::strtoull(buffer, NULL, 10);
+
+        if ( this->setU64(topic[1], topic[2], value) )
+             ESP_LOGI(TAG, "Set  namespace[ %s ]  key[ %s ]  to u64[ %lld ]",             topic[1].c_str(), topic[2].c_str(), value);
+        else ESP_LOGW(TAG, "Setting  namespace[ %s ]  key[ %s ]  to u64[ %lld ]  FAILED", topic[1].c_str(), topic[2].c_str(), value);
+        // publish error…?
+      } ));
+
+
+      qthing::add_binary_message_callback(requestTopic("set_i8/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+
+        char* buffer = new char[msg.length + 1];
+        snprintf(buffer, msg.length + 1, "%s", msg.payload);
+
+        i64 value = std::strtoll(buffer, NULL, 10);
+
+        const i8 i8_max = std::numeric_limits<i8>::max();
+        const i8 i8_min = std::numeric_limits<i8>::lowest();
+
+        if (value > i8_max) value = i8_max;
+        if (value < i8_min) value = i8_min;
+
+        if ( this->setI8(topic[1], topic[2], static_cast<i8>(value)) )
+             ESP_LOGI(TAG, "Set  namespace[ %s ]  key[ %s ]  to i8[ %lld ]",             topic[1].c_str(), topic[2].c_str(), value);
+        else ESP_LOGW(TAG, "Setting  namespace[ %s ]  key[ %s ]  to i8[ %lld ]  FAILED", topic[1].c_str(), topic[2].c_str(), value);
+        // publish error…?
+      } ));
+
+
+      qthing::add_binary_message_callback(requestTopic("set_i16/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+
+        char* buffer = new char[msg.length + 1];
+        snprintf(buffer, msg.length + 1, "%s", msg.payload);
+
+        i64 value = std::strtoll(buffer, NULL, 10);
+
+        const i16 i16_max = std::numeric_limits<i16>::max();
+        const i16 i16_min = std::numeric_limits<i16>::lowest();
+
+        if (value > i16_max) value = i16_max;
+        if (value < i16_min) value = i16_min;
+
+        if ( this->setI16(topic[1], topic[2], static_cast<i16>(value)) )
+             ESP_LOGI(TAG, "Set  namespace[ %s ]  key[ %s ]  to i16[ %lld ]",             topic[1].c_str(), topic[2].c_str(), value);
+        else ESP_LOGW(TAG, "Setting  namespace[ %s ]  key[ %s ]  to i16[ %lld ]  FAILED", topic[1].c_str(), topic[2].c_str(), value);
+        // publish error…?
+      } ));
+
+
+      qthing::add_binary_message_callback(requestTopic("set_i32/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+
+        char* buffer = new char[msg.length + 1];
+        snprintf(buffer, msg.length + 1, "%s", msg.payload);
+
+        i64 value = std::strtoll(buffer, NULL, 10);
+
+        const i32 i32_max = std::numeric_limits<i32>::max();
+        const i32 i32_min = std::numeric_limits<i32>::lowest();
+
+        if (value > i32_max) value = i32_max;
+        if (value < i32_min) value = i32_min;
+
+        if ( this->setI32(topic[1], topic[2], static_cast<i32>(value)) )
+             ESP_LOGI(TAG, "Set  namespace[ %s ]  key[ %s ]  to i32[ %lld ]",             topic[1].c_str(), topic[2].c_str(), value);
+        else ESP_LOGW(TAG, "Setting  namespace[ %s ]  key[ %s ]  to i32[ %lld ]  FAILED", topic[1].c_str(), topic[2].c_str(), value);
+        // publish error…?
+      } ));
+
+
+      qthing::add_binary_message_callback(requestTopic("set_i64/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+
+        char* buffer = new char[msg.length + 1];
+        snprintf(buffer, msg.length + 1, "%s", msg.payload);
+
+        i64 value = std::strtoll(buffer, NULL, 10);
+
+        if ( this->setI64(topic[1], topic[2], value) )
+             ESP_LOGI(TAG, "Set  namespace[ %s ]  key[ %s ]  to i64[ %lld ]",             topic[1].c_str(), topic[2].c_str(), value);
+        else ESP_LOGW(TAG, "Setting  namespace[ %s ]  key[ %s ]  to i64[ %lld ]  FAILED", topic[1].c_str(), topic[2].c_str(), value);
+        // publish error…?
+      } ));
+
+
+
+      qthing::add_binary_message_callback(requestTopic("get_strLen/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+
+        size_t testValue = 1337000;  // way too big for NVS
+        size_t length = getStringLength(topic[1], topic[2], testValue);
+
+        if (length < testValue) {  // key exists and is of type string
+
+          char buffer[32];
+          std::snprintf(&buffer[0], 32, "%d", length);
+
+          str value(&buffer[0]);
+          qthing::publish_message(responseTopic("get_strLen", topic[1], topic[2]), value);
+        } else {
+          // publish error…?
+
+          ESP_LOGW(TAG, "Retrieving |str|[] from  namespace[ %s ]  key[ %s ]  FAILED", topic[1].c_str(), topic[2].c_str());
+        }
+      } ));
+
+
+      qthing::add_binary_message_callback(requestTopic("get_str/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+
+        size_t testValue = 1337000;  // way too big for NVS
+
+        if ( getStringLength(topic[1], topic[2], testValue) < testValue ) {  // key exists and is of type string
+
+          str value = getString(topic[1], topic[2]);
+
+          qthing::publish_message(responseTopic("get_str", topic[1], topic[2]), value);
+        } else {
+          // publish error…?
+
+          ESP_LOGW(TAG, "Retrieving str[] from  namespace[ %s ]  key[ %s ]  FAILED", topic[1].c_str(), topic[2].c_str());
+        }
+      } ));
+
+
+      qthing::add_binary_message_callback(requestTopic("set_str/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+
+        char* buffer = new char[msg.length + 1];
+        snprintf(buffer, msg.length + 1, "%s", msg.payload);
+        str value(buffer);
+
+        if ( this->setString(topic[1], topic[2], value) )
+             ESP_LOGI(TAG, "Set  namespace[ %s ]  key[ %s ]  to str[ %s ]",             topic[1].c_str(), topic[2].c_str(), value.c_str());  // TODO: do we REALLY wanna log the payloads?!
+        else ESP_LOGW(TAG, "Setting  namespace[ %s ]  key[ %s ]  to str[ %s ]  FAILED", topic[1].c_str(), topic[2].c_str(), value.c_str());  // TODO: do we REALLY wanna log the payloads?!
+        // publish error…?
+      } ));
+
+
+      qthing::add_binary_message_callback(requestTopic("get_type/+/+"), wrapMessageHandler(
+        [&](std::vector<str>& topic, qthing::multipart_message_t msg) {
+        qthing::publish_message(responseTopic("get_type", topic[1], topic[2]), getTypeStr(topic[1], topic[2]));
+      } ));
+
+
+    }
+
+
+
+    u8 NVSExplorer::getU8(const str& nameSpace, const str& key, u8 defaultValue) {
+
+      u8 value = defaultValue;
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READONLY, &nvs) == ESP_OK ) {
+           nvs_get_u8(nvs, key.c_str(), &value);
+           nvs_close(nvs);
+      }
+
+      return value;
+    }
+
+    u16 NVSExplorer::getU16(const str& nameSpace, const str& key, u16 defaultValue) {
+
+      u16 value = defaultValue;
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READONLY, &nvs) == ESP_OK ) {
+           nvs_get_u16(nvs, key.c_str(), &value);
+           nvs_close(nvs);
+      }
+
+      return value;
+    }
+
+    u32 NVSExplorer::getU32(const str& nameSpace, const str& key, u32 defaultValue) {
+
+      u32 value = defaultValue;
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READONLY, &nvs) == ESP_OK ) {
+           nvs_get_u32(nvs, key.c_str(), &value);
+           nvs_close(nvs);
+      }
+
+      return value;
+    }
+
+    u64 NVSExplorer::getU64(const str& nameSpace, const str& key, u64 defaultValue) {
+
+      u64 value = defaultValue;
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READONLY, &nvs) == ESP_OK ) {
+           nvs_get_u64(nvs, key.c_str(), &value);
+           nvs_close(nvs);
+      }
+
+      return value;
+    }
+
+    i8 NVSExplorer::getI8(const str& nameSpace, const str& key, i8 defaultValue) {
+
+      i8 value = defaultValue;
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READONLY, &nvs) == ESP_OK ) {
+           nvs_get_i8(nvs, key.c_str(), &value);
+           nvs_close(nvs);
+      }
+
+      return value;
+    }
+
+    i16 NVSExplorer::getI16(const str& nameSpace, const str& key, i16 defaultValue) {
+
+      i16 value = defaultValue;
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READONLY, &nvs) == ESP_OK ) {
+           nvs_get_i16(nvs, key.c_str(), &value);
+           nvs_close(nvs);
+      }
+
+      return value;
+    }
+
+    i32 NVSExplorer::getI32(const str& nameSpace, const str& key, i32 defaultValue) {
+
+      i32 value = defaultValue;
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READONLY, &nvs) == ESP_OK ) {
+           nvs_get_i32(nvs, key.c_str(), &value);
+           nvs_close(nvs);
+      }
+
+      return value;
+    }
+
+    i64 NVSExplorer::getI64(const str& nameSpace, const str& key, i64 defaultValue) {
+
+      i64 value = defaultValue;
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READONLY, &nvs) == ESP_OK ) {
+           nvs_get_i64(nvs, key.c_str(), &value);
+           nvs_close(nvs);
+      }
+
+      return value;
+    }
+
+
+
+    bool NVSExplorer::setU8(const str& nameSpace, const str& key, u8 value) {
+      bool success = true;
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READWRITE, &nvs) == ESP_OK ) {
+        success &= nvs_set_u8(nvs, key.c_str(), value) == ESP_OK;
+        success &= nvs_commit(nvs) == ESP_OK;
+                   nvs_close(nvs);
+
+        return success;
+      } else {
+        return false;
+      }
+    }
+
+    bool NVSExplorer::setU16(const str& nameSpace, const str& key, u16 value) {
+      bool success = true;
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READWRITE, &nvs) == ESP_OK ) {
+        success &= nvs_set_u16(nvs, key.c_str(), value) == ESP_OK;
+        success &= nvs_commit(nvs) == ESP_OK;
+                   nvs_close(nvs);
+
+        return success;
+      } else {
+        return false;
+      }
+    }
+
+    bool NVSExplorer::setU32(const str& nameSpace, const str& key, u32 value) {
+      bool success = true;
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READWRITE, &nvs) == ESP_OK ) {
+        success &= nvs_set_u32(nvs, key.c_str(), value) == ESP_OK;
+        success &= nvs_commit(nvs) == ESP_OK;
+                   nvs_close(nvs);
+
+        return success;
+      } else {
+        return false;
+      }
+    }
+
+    bool NVSExplorer::setU64(const str& nameSpace, const str& key, u64 value) {
+      bool success = true;
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READWRITE, &nvs) == ESP_OK ) {
+        success &= nvs_set_u64(nvs, key.c_str(), value) == ESP_OK;
+        success &= nvs_commit(nvs) == ESP_OK;
+                   nvs_close(nvs);
+
+        return success;
+      } else {
+        return false;
+      }
+    }
+
+    bool NVSExplorer::setI8(const str& nameSpace, const str& key, i8 value) {
+      bool success = true;
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READWRITE, &nvs) == ESP_OK ) {
+        success &= nvs_set_i8(nvs, key.c_str(), value) == ESP_OK;
+        success &= nvs_commit(nvs) == ESP_OK;
+                   nvs_close(nvs);
+
+        return success;
+      } else {
+        return false;
+      }
+    }
+
+    bool NVSExplorer::setI16(const str& nameSpace, const str& key, i16 value) {
+      bool success = true;
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READWRITE, &nvs) == ESP_OK ) {
+        success &= nvs_set_i16(nvs, key.c_str(), value) == ESP_OK;
+        success &= nvs_commit(nvs) == ESP_OK;
+                   nvs_close(nvs);
+
+        return success;
+      } else {
+        return false;
+      }
+    }
+
+    bool NVSExplorer::setI32(const str& nameSpace, const str& key, i32 value) {
+      bool success = true;
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READWRITE, &nvs) == ESP_OK ) {
+        success &= nvs_set_i32(nvs, key.c_str(), value) == ESP_OK;
+        success &= nvs_commit(nvs) == ESP_OK;
+                   nvs_close(nvs);
+
+        return success;
+      } else {
+        return false;
+      }
+    }
+
+    bool NVSExplorer::setI64(const str& nameSpace, const str& key, i64 value) {
+      bool success = true;
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READWRITE, &nvs) == ESP_OK ) {
+        success &= nvs_set_i64(nvs, key.c_str(), value) == ESP_OK;
+        success &= nvs_commit(nvs) == ESP_OK;
+                   nvs_close(nvs);
+
+        return success;
+      } else {
+        return false;
+      }
+    }
+
+
+
+    float NVSExplorer::getFloat(const str& nameSpace, const str& key) {
+
+      float value  = std::nanf("1337");
+      u32*  valptr = reinterpret_cast<u32*>(&value);
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READONLY, &nvs) == ESP_OK ) {
+           nvs_get_u32(nvs, key.c_str(), valptr);
+           nvs_close(nvs);
+      }
+
+      return value;
+    }
+
+    double NVSExplorer::getDouble(const str& nameSpace, const str& key) {
+
+      double value  = std::nan("1337");
+      u64*   valptr = reinterpret_cast<u64*>(&value);
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READONLY, &nvs) == ESP_OK ) {
+           nvs_get_u64(nvs, key.c_str(), valptr);
+           nvs_close(nvs);
+      }
+
+      return value;
+    }
+
+
+    bool NVSExplorer::setFloat(const str& nameSpace, const str& key, float value) {
+
+      bool success = true;
+      u32  intval  = reinterpret_cast<u32*>(&value)[0];
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READWRITE, &nvs) == ESP_OK ) {
+        success &= nvs_set_u32(nvs, key.c_str(), intval) == ESP_OK;
+        success &= nvs_commit(nvs) == ESP_OK;
+                   nvs_close(nvs);
+
+        return success;
+      } else {
+        return false;
+      }
+    }
+
+    bool NVSExplorer::setDouble(const str& nameSpace, const str& key, double value) {
+
+      bool success = true;
+      u64  intval  = reinterpret_cast<u64*>(&value)[0];
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READWRITE, &nvs) == ESP_OK ) {
+        success &= nvs_set_u64(nvs, key.c_str(), intval) == ESP_OK;
+        success &= nvs_commit(nvs) == ESP_OK;
+                   nvs_close(nvs);
+
+        return success;
+      } else {
+        return false;
+      }
+    }
+
+
+    size_t NVSExplorer::getStringLength(const str& nameSpace, const str& key, size_t defaultValue) {
+
+      size_t value = defaultValue;
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READONLY, &nvs) == ESP_OK ) {
+           nvs_get_str(nvs, key.c_str(), NULL, &value);
+           nvs_close(nvs);
+      }
+
+      return value;
+    }
+
+
+    str NVSExplorer::getString(const str& nameSpace, const str& key, const str& defaultValue) {
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READONLY, &nvs) == ESP_OK ) {
+
+        size_t size;
+        if ( nvs_get_str(nvs, key.c_str(), NULL, &size) == ESP_OK ) {
+
+          char buffer[size + 1];
+          std::memset(&buffer[0], 0x00, size + 1);
+
+          nvs_get_str(nvs, key.c_str(), &buffer[0], &size);
+
+          nvs_close(nvs);
+
+          str out(&buffer[0]);
+          return out;
+        }
+      }
+
+      return defaultValue;
+    }
+
+
+    bool NVSExplorer::setString(const str& nameSpace, const str& key, const str& value) {
+
+      bool success = true;
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READWRITE, &nvs) == ESP_OK ) {
+        success &= nvs_set_str(nvs, key.c_str(), value.c_str()) == ESP_OK;
+        success &= nvs_commit(nvs) == ESP_OK;
+                   nvs_close(nvs);
+
+        return success;
+      } else {
+        return false;
+      }
+    }
+
+
+
+    void NVSExplorer::rmKey(const str& nameSpace, const str& key) {
+      nvs_handle_t _nvs;
+      ESP_LOGW(TAG, "rmKey() -> %s / %s", nameSpace.c_str(), key.c_str());
+      ESP_LOGW(TAG, "open() -> %s", esp_err_to_name( nvs_open(nameSpace.c_str(), NVS_READWRITE, &_nvs) ));
+      ESP_LOGW(TAG, "erase() -> %s", esp_err_to_name( nvs_erase_key(_nvs, key.c_str()) ));
+      ESP_LOGW(TAG, "commit() -> %s", esp_err_to_name( nvs_commit(_nvs) ));
+      ESP_LOGW(TAG, "erase²() -> %s", esp_err_to_name( nvs_erase_key(_nvs, key.c_str()) ));
+    }
+
+    std::set<str> NVSExplorer::listKeys(const str& nameSpace) {
+
+      std::set<str> keys;
+
+      nvs_iterator_t it = nvs_entry_find("nvs", nameSpace.c_str(), NVS_TYPE_ANY);
+
+      while (it != NULL) {
+        nvs_entry_info_t info;
+        nvs_entry_info(it, &info);
+        it = nvs_entry_next(it);
+
+        ESP_LOGW(TAG, "namespace[ %s ]   key[ %s ]   type[ %d ]", info.namespace_name, info.key, info.type);  // TODO: remove after dev!
+
+        keys.insert(info.key);
+      }
+
+      return keys;
+    }
+
+    std::set<str> NVSExplorer::listNamespaces() {
+
+      std::set<str> namespaces;
 
       nvs_iterator_t it = nvs_entry_find("nvs", NULL, NVS_TYPE_ANY);
 
@@ -40,22 +1000,216 @@ namespace SiliconTorch {
         nvs_entry_info(it, &info);
         it = nvs_entry_next(it);
 
-        ESP_LOGW("NVS", "namespace[ %s ]   key[ %s ]   type[ %d ]", info.namespace_name, info.key, info.type);
+        ESP_LOGW(TAG, "namespace[ %s ]   key[ %s ]   type[ %d ]", info.namespace_name, info.key, info.type);  // TODO: remove after dev!
+
+        namespaces.insert(info.namespace_name);
+      }
+
+      return namespaces;
+    }
+
+
+    i64 NVSExplorer::getSignedInt(const str& nameSpace, const str& key, i64 defaultValue) {
+
+      // Lets first test & evaluate the other function before duplication………
+
+      return -1337LL;
+    }
+
+
+    u64 NVSExplorer::getUnsignedInt(const str& nameSpace, const str& key, u64 defaultValue) {
+
+      u64 value = defaultValue;
+      nvs_type_t entryType = NVS_TYPE_ANY;
+
+      // search for the key to get its type
+      nvs_iterator_t it = nvs_entry_find("nvs", nameSpace.c_str(), NVS_TYPE_ANY);
+
+      while (it != NULL) {
+        nvs_entry_info_t entry;
+        nvs_entry_info(it, &entry);
+
+        if (key.compare(entry.key) == 0) {
+          entryType = entry.type;
+          nvs_release_iterator(it);
+          break;
+        }
+
+        it = nvs_entry_next(it);
+      }
+
+      if (entryType == NVS_TYPE_ANY)  // key not found
+        return defaultValue;
+
+      nvs_handle_t nvs;
+      if ( nvs_open(nameSpace.c_str(), NVS_READONLY, &nvs) != ESP_OK )  // namespace not found
+        return defaultValue;
+
+      u64* valptr = &value;
+      switch (entryType) {
+        case NVS_TYPE_U8:  { nvs_get_u8(nvs,  key.c_str(), ( u8*)valptr); break; }
+        case NVS_TYPE_I8:  { nvs_get_i8(nvs,  key.c_str(), (  i8*)valptr); break; }
+        case NVS_TYPE_U16: { nvs_get_u16(nvs, key.c_str(), (u16*)valptr); break; }
+        case NVS_TYPE_I16: { nvs_get_i16(nvs, key.c_str(), ( i16*)valptr); break; }
+        case NVS_TYPE_U32: { nvs_get_u32(nvs, key.c_str(), (u32*)valptr); break; }
+        case NVS_TYPE_I32: { nvs_get_i32(nvs, key.c_str(), ( i32*)valptr); break; }
+        case NVS_TYPE_U64: { nvs_get_u64(nvs, key.c_str(), (u64*)valptr); break; }
+        case NVS_TYPE_I64: { nvs_get_i64(nvs, key.c_str(), ( i64*)valptr); break; }
+        default: {}
+      }
+
+      nvs_close(nvs);
+      return value;
+    }
+
+
+    bool NVSExplorer::setSignedInt(const str& nameSpace, const str& key, i64 value, nvs_type_t entryType) {
+
+      // TODO: implementation!
+
+      return false;
+    }
+
+    bool NVSExplorer::setUnsignedInt(const str& nameSpace, const str& key, u64 value, nvs_type_t entryType) {
+
+      bool result = false;
+
+      if (entryType == NVS_TYPE_ANY) {
+
+        // check if key exists and grab its type
+        nvs_iterator_t it = nvs_entry_find("nvs", nameSpace.c_str(), NVS_TYPE_ANY);
+
+        while (it != NULL) {
+          nvs_entry_info_t entry;
+          nvs_entry_info(it, &entry);
+
+          if (key.compare(entry.key) == 0) {
+            entryType = entry.type;
+            nvs_release_iterator(it);
+            break;
+          }
+
+          it = nvs_entry_next(it);
+        }
+
+        // TODO: further implementation……?
+
+      } else {
+
+      }
+
+      return result;
+    }
+
+
+    /**
+      * Converts IDF NVS types to strings
+      */
+    str NVSExplorer::type2str(nvs_type_t typ) {
+      switch (typ) {
+        case NVS_TYPE_U8:   return "u8";
+        case NVS_TYPE_U16:  return "u16";
+        case NVS_TYPE_U32:  return "u32";
+        case NVS_TYPE_U64:  return "u64";
+        case NVS_TYPE_I8:   return "i8";
+        case NVS_TYPE_I16:  return "i16";
+        case NVS_TYPE_I32:  return "i32";
+        case NVS_TYPE_I64:  return "i64";
+        case NVS_TYPE_STR:  return "str";
+        case NVS_TYPE_BLOB: return "blob";
+        default:            return "any";
+      }
+    }
+
+
+    /**
+      * Get the type of the entry, NVS_TYPE_ANY if not found
+      */
+    nvs_type_t NVSExplorer::getType(const str& nameSpace, const str& key) {
+
+      nvs_type_t entryType = NVS_TYPE_ANY;
+
+      nvs_iterator_t it = nvs_entry_find("nvs", nameSpace.c_str(), NVS_TYPE_ANY);
+
+      while (it != NULL) {
+        nvs_entry_info_t entry;
+        nvs_entry_info(it, &entry);
+
+        if (key.compare(entry.key) == 0) {
+          entryType = entry.type;
+          nvs_release_iterator(it);
+          return entryType;
+        }
+
+        it = nvs_entry_next(it);
+      }
+
+      return entryType;
+    }
+
+    /**
+      * Like getType but converts them to string
+      * non-existing keys are converted to `void` instead of `any`
+      */
+    str NVSExplorer::getTypeStr(const str& nameSpace, const str& key) {
+
+      bool entryFound = false;
+      nvs_type_t entryType = NVS_TYPE_ANY;
+
+      nvs_iterator_t it = nvs_entry_find("nvs", nameSpace.c_str(), NVS_TYPE_ANY);
+
+      while (it != NULL) {
+        nvs_entry_info_t entry;
+        nvs_entry_info(it, &entry);
+
+        if (key.compare(entry.key) == 0) {
+          entryFound = true;
+          entryType = entry.type;
+          nvs_release_iterator(it);
+          break;
+        }
+
+        it = nvs_entry_next(it);
       }
 
+      str typ;
+
+      if (entryFound) typ = type2str(entryType);
+      else            typ = "void";
 
+      return typ;
     }
 
 
-    /* std::set<std::string> listKeys(std::string& _namespace) {
+    str NVSExplorer::deviceTopic(const str& suffix) {
+      return str(DEVICE_NAMESPACE + "NVS/") + suffix;
+    }
+
 
+    str NVSExplorer::requestTopic(const str& cmd) {
+      return deviceTopic( str("rq/") + cmd );
     }
 
-    std::set<std::string> listNamespaces() {
-      std::string _namespace = NULL;
-      return listKeys(_namespace);
-    } */
+    str NVSExplorer::requestTopic(const str& cmd, const str& nameSpace) {
+      return deviceTopic( str("rq/") + cmd + str("/") + nameSpace );
+    }
+
+    str NVSExplorer::requestTopic(const str& cmd, const str& nameSpace, const str& key) {
+      return deviceTopic( str("rq/") + cmd + str("/") + nameSpace + str("/") + key );
+    }
 
 
+    str NVSExplorer::responseTopic(const str& cmd) {
+      return deviceTopic( str("rs/") + cmd );
+    }
+
+    str NVSExplorer::responseTopic(const str& cmd, const str& nameSpace) {
+      return deviceTopic( str("rs/") + cmd + str("/") + nameSpace );
+    }
+
+    str NVSExplorer::responseTopic(const str& cmd, const str& nameSpace, const str& key) {
+      return deviceTopic( str("rs/") + cmd + str("/") + nameSpace + str("/") + key );
+    }
+
   }
 }
diff --git a/CLC-qthing/SiliconTorch/NVSExplorer.hpp b/CLC-qthing/SiliconTorch/NVSExplorer.hpp
index 6f0a9e2a8361b6c00bb215205d59db411436c27a..44bf20f10f103515a7db12bd2c5364393c0e84e6 100644
--- a/CLC-qthing/SiliconTorch/NVSExplorer.hpp
+++ b/CLC-qthing/SiliconTorch/NVSExplorer.hpp
@@ -1,19 +1,22 @@
 #pragma once
 
 // C++ system level
-// #include <cstring>     // memset, strncmp
+#include <set>
+#include <cstring>     // memset, strncmp
 // #include <cstdlib>     // TODO: is this for memcpy?
 #include <cinttypes>
 // #include <functional>
 
 // ESP32 specific
 // #include "esp_err.h"
+#include "nvs_flash.h"
 #include "esp_log.h"
 // #include "driver/gpio.h"
 // #include "driver/uart.h"
 
 // project specific
-// #include ""
+#include <Types.hpp>
+// #include "SpiderLib/ManagedMutex.hpp"
 
 // qthing stuff
 // #include <qthing>
@@ -24,22 +27,85 @@ namespace SiliconTorch {
   namespace NVSExplorer {
 
 
-    //class NVSExplorer {
+    extern const char* TAG;
 
-      //public:
 
-        //NVSExplorer();
+    class NVSExplorer {
 
-        static void BullShit();
+      public:
 
+        std::set<str> listNamespaces();
+        std::set<str> listKeys(const str& nameSpace);
 
-        // std::set<std::string> listNamespaces();
-        // std::set<std::string> listKeys(std::string& _namespace);
+        void rmKey(const str& nameSpace, const str& key);
 
 
+        bool setU8(const  str& nameSpace, const str& key, u8  value);
+        bool setI8(const  str& nameSpace, const str& key, i8  value);
+
+        bool setU16(const str& nameSpace, const str& key, u16 value);
+        bool setI16(const str& nameSpace, const str& key, i16 value);
+
+        bool setU32(const str& nameSpace, const str& key, u32 value);
+        bool setI32(const str& nameSpace, const str& key, i32 value);
+
+        bool setU64(const str& nameSpace, const str& key, u64 value);
+        bool setI64(const str& nameSpace, const str& key, i64 value);
+
+
+        u8  getU8(const  str& nameSpace, const str& key, u8  defaultValue = 0);
+        i8  getI8(const  str& nameSpace, const str& key, i8  defaultValue = 0);
+
+        u16 getU16(const str& nameSpace, const str& key, u16 defaultValue = 0);
+        i16 getI16(const str& nameSpace, const str& key, i16 defaultValue = 0);
+
+        u32 getU32(const str& nameSpace, const str& key, u32 defaultValue = 0);
+        i32 getI32(const str& nameSpace, const str& key, i32 defaultValue = 0);
+
+        u64 getU64(const str& nameSpace, const str& key, u64 defaultValue = 0);
+        i64 getI64(const str& nameSpace, const str& key, i64 defaultValue = 0);
+
+
+        float  getFloat(const str& nameSpace, const str& key);
+        double getDouble(const str& nameSpace, const str& key);
+
+        bool setFloat(const str& nameSpace, const str& key, float value);
+        bool setDouble(const str& nameSpace, const str& key, double value);
+
+        // Gets the key regardless of its type in flash
+        i64  getSignedInt(const str& nameSpace, const str& key, i64 defaultValue = 0);
+        u64 getUnsignedInt(const str& nameSpace, const str& key, u64 defaultValue = 0);
+
+        // TODO: ⮦ Both unimplemented atm ⮧ 
+        bool setSignedInt(const str& nameSpace, const str& key, i64 value, nvs_type_t entryType = NVS_TYPE_ANY);
+        bool setUnsignedInt(const str& nameSpace, const str& key, u64 value, nvs_type_t entryType = NVS_TYPE_ANY);
+
+
+        size_t getStringLength(const str& nameSpace, const str& key, size_t defaultValue = 0);
+        str getString(const str& nameSpace, const str& key, const str& defaultValue = "");
+        // size_t getLongString(const str& nameSpace, const str& key, char* const buffer);
+
+        bool setString(const str& nameSpace, const str& key, const str& value);
+
+
+        str type2str(nvs_type_t typ);
+        nvs_type_t getType(const str& nameSpace, const str& key);
+        str getTypeStr(const str& nameSpace, const str& key);
+
+
+        str deviceTopic(const str& suffix);
+
+        str requestTopic(const str& cmd);
+        str requestTopic(const str& cmd, const str& nameSpace);
+        str requestTopic(const str& cmd, const str& nameSpace, const str& key);
+
+        str responseTopic(const str& cmd);
+        str responseTopic(const str& cmd, const str& nameSpace);
+        str responseTopic(const str& cmd, const str& nameSpace, const str& key);
+
         // ⬇⬇ Singleton stuff ⬇⬇
 
-/*        static NVSExplorer& instance() {
+        static NVSExplorer& instance() {
           static NVSExplorer _instance;
           return _instance;
         }
@@ -48,12 +114,16 @@ namespace SiliconTorch {
         void operator=(NVSExplorer const&) = delete;
 
         // ⬆⬆ Singleton stuff ⬆⬆
-*/
-      //private:
 
+      private:
+
+        void registerLambdas0();
+        void registerLambdas1();
+
+        NVSExplorer();
 
+    };
 
-    //};
 
   }
 }
diff --git a/CLC-qthing/SiliconTorch/NVSExplorer.md b/CLC-qthing/SiliconTorch/NVSExplorer.md
new file mode 100644
index 0000000000000000000000000000000000000000..0cf3f1392f14395b191fcb4e3c0fb6add48b52ba
--- /dev/null
+++ b/CLC-qthing/SiliconTorch/NVSExplorer.md
@@ -0,0 +1,91 @@
+NVSExplorer
+===========
+
+A simple tool for exploring the `NVS` on `ESP32` platform through a high-level `C++` API.
+
+All API endpoints are also mapped to `MQTT` topics to provide a some kind of a remote administration toolkit for `ESP32` devices.
+
+
+`MQTT` API
+----------
+
+`NVSExplorer` has its topics living inside the local `qthing` topic scheme.
+
+The base-topic thus is `device/<NAME>/NVS` where `<NAME>` is the device name.
+This topic will further be referred to just as `BASE`, like in `BASE/cmd`.
+
+The request/response scheme doesn't follow the usual property ones as this would lead to publish loops.
+Therefore we establish distinct request/response topics.
+
+- `request` topic:
+  `BASE/rq`
+
+- `response` topic:
+  `BASE/rs`  (the `response`-topic *may* change in the future as I'm certainly unclear about it)
+
+This topics will further on be referred to as `REQUEST` and `RESPONSE`, as in `REQUEST/ls`.
+
+
+### Commands
+
+The following commands are or will be supported by `NVSExplorer`.
+As for the topic convention just swap `REQUEST` and `RESPONSE` to get your result.
+Not all commands will publish a result, but there may be an `ERROR`-topic in the future to indicate failure or success of such commands.
+
+In the following list, `argument` stands for the message content received on the topic, `NS` and `KEY` denote the used namespace and key.
+
+- `ls` - **list namespaces**  
+  **topic**: `REQUEST/ls`  
+  **argument**: used as delimiter for concatenating the list (default: `' '`)  
+  **description**: returns a list of the namespaces found in `NVS`
+
+- `ls` - **list keys**  
+  **topic**: `REQUEST/ls/NS`  
+  **argument**: used as delimiter for concatenating the list (default: `' '`)  
+  **description**: returns a list of the keys found in namespace `NS`
+
+- `get` - **get generic value**  
+  **topic**: `REQUEST/get/NS/KEY`  
+  **description**: reads the value and returns it in its natural form
+
+- `get_type` - **get type of key**  
+  **topic**: `REQUEST/get_type/NS/KEY`  
+  **description**: reads the type and converts it to `string`  
+    returns `void` in case of non-existing `key`  
+    possible return values: `u8`, `u16`, `u32`, `u64`, `i8`, `i16`, `i32`, `i64`, `str`, `blob`, `any`, `void`
+
+- `get_raw` - **get generic value**  
+  **topic**: `REQUEST/get_raw/NS/KEY`  
+  **description**: returns the value in its binary form, for example `2 bytes` in case of `u16`
+
+- `get_<float|double>` - **get floating point value**  
+  **topic**: `REQUEST/get_<float|double>/NS/KEY`  
+  **description**: reads the value, `reinterpret_cast`s it to `float` or `double` and returns it converted to `string`
+
+- `set_<float|double>` - **get floating point value**  
+  **topic**: `REQUEST/get_<float|double>/NS/KEY`  
+  **argument**: the value to set
+  **description**: converts the value from `string` to floating point; `reinterpret_cast`s it to `u32` or `u64` and write it to the `key`
+
+- `get_<u8|i8|u16|i16|u32|i32|u64|i64>` - **get integer value** (`signed` and `unsigned`)  
+  **topic**: `REQUEST/get_<u8|i8|u16|i16|u32|i32|u64|i64>/NS/KEY`  
+  **description**: reads the value, and returns it converted to `string`
+
+- `set_<u8|i8|u16|i16|u32|i32|u64|i64>` - **set integer value** (`signed` and `unsigned`)  
+  **topic**: `REQUEST/set_<u8|i8|u16|i16|u32|i32|u64|i64>/NS/KEY`  
+  **argument**: the value to set
+  **description**: converts the message from `string` to `int` and writes it into the `key`; the value is capped to the bounds of the specified type, e.g. `[0, 128]` in case of `set_u8`
+
+- `get_str` - **get string value**  
+  **topic**: `REQUEST/get_str/NS/KEY`  
+  **description**: returns the stored `string` value
+
+- `get_strlen` - **get string length**  
+  **topic**: `REQUEST/get_strlen/NS/KEY`  
+  **description**: returns the length of a stored `string` value
+
+
+
+### Types
+
+#### TODO
diff --git a/CLC-qthing/SiliconTorch/PWMChannel.cpp b/CLC-qthing/SiliconTorch/PWMChannel.cpp
index e00bf3353549d616183c739ca067d2060b488edf..bb25bacf8ec07bc20afb2346e0284ef7dd3d8b65 100644
--- a/CLC-qthing/SiliconTorch/PWMChannel.cpp
+++ b/CLC-qthing/SiliconTorch/PWMChannel.cpp
@@ -4,9 +4,13 @@
 #include "driver/gpio.h"
 #include "driver/ledc.h"
 
+// project specific
+#include "SpiderLib/NumberTypes.hpp"
 
 
-SiliconTorch::Impl::PWMChannel::PWMChannel(uint8_t channel, uint8_t gpio) : channel{(ledc_channel_t)channel} {
+
+
+SiliconTorch::Impl::PWMChannel::PWMChannel(u8 channel, u8 gpio) : channel{(ledc_channel_t)channel} {
 
   gpio_config_t conf;
 
@@ -35,13 +39,13 @@ SiliconTorch::Impl::PWMChannel::PWMChannel(uint8_t channel, uint8_t gpio) : chan
   this->setPWM(0);
 }
 
-void SiliconTorch::Impl::PWMChannel::setPWM(uint32_t pwm) {
+void SiliconTorch::Impl::PWMChannel::setPWM(u32 pwm) {
   ledc_set_duty(LEDC_HIGH_SPEED_MODE, this->channel, pwm);
   ledc_update_duty(LEDC_HIGH_SPEED_MODE, this->channel);
 
   this->pwm = pwm;
 }
 
-uint32_t SiliconTorch::Impl::PWMChannel::getPWM() {
+u32 SiliconTorch::Impl::PWMChannel::getPWM() {
   return this->pwm;
 }
diff --git a/CLC-qthing/SiliconTorch/PWMChannel.hpp b/CLC-qthing/SiliconTorch/PWMChannel.hpp
index 420213d312225e34da64f756dde9a18ac390f533..6154fa4dbe1777653befca19d2e07243c7b6d808 100644
--- a/CLC-qthing/SiliconTorch/PWMChannel.hpp
+++ b/CLC-qthing/SiliconTorch/PWMChannel.hpp
@@ -3,6 +3,9 @@
 // ESP32 specific
 #include "driver/ledc.h"
 
+// project specific
+#include "SpiderLib/NumberTypes.hpp"
+
 
 namespace SiliconTorch {
 
@@ -10,13 +13,13 @@ namespace SiliconTorch {
 
     class PWMChannel {
       public:
-        PWMChannel(uint8_t channel, uint8_t gpio);
+        PWMChannel(u8 channel, u8 gpio);
 
-        uint32_t getPWM();
-        void setPWM(uint32_t pwm);
+        u32 getPWM();
+        void setPWM(u32 pwm);
       
       private:
-        uint32_t pwm = 0;
+        u32 pwm = 0;
         ledc_channel_t channel;
     };
 
diff --git a/CLC-qthing/SiliconTorch/RS485.cpp b/CLC-qthing/SiliconTorch/RS485.cpp
index c4fd6e9c7353b24a8832bf7fc5e2af5065e02683..805b30a81eba4671df91982317e266ec9491cd26 100644
--- a/CLC-qthing/SiliconTorch/RS485.cpp
+++ b/CLC-qthing/SiliconTorch/RS485.cpp
@@ -1,7 +1,7 @@
 #include "RS485.hpp"
 
 // C++ system level
-#include <cinttypes>
+// #include <functional>
 
 // ESP32 specific
 #include "esp_log.h"
@@ -9,7 +9,7 @@
 #include "driver/uart.h"
 
 // project specific
-// #include "LambdaTask.hpp"
+#include "SpiderLib/NumberTypes.hpp"
 
 // qthing stuff
 // #include ""
@@ -21,7 +21,7 @@ static const char* TAG = "RS485";
 
 // This leads to ~54 P/s @ 2 MBaud at 100% load
 // TODO: Make configurable?!
-const uint32_t CyanBusMTU = 4096;
+const u32 CyanBusMTU = 4096;
 
 
 namespace SiliconTorch {
@@ -29,9 +29,9 @@ namespace SiliconTorch {
   namespace Impl {
 
 
-    RS485::RS485(uint8_t tx, uint8_t rx, uint8_t de, uint8_t re, uint32_t baudRate, uint8_t uartChannel) : tx(tx), rx(rx), de(de), re(re), uartChannel(uartChannel) {
+    RS485::RS485(u8 tx, u8 rx, u8 de, u8 re, u32 baudRate, u8 uartChannel) : tx(tx), rx(rx), de(de), re(re), uartChannel(uartChannel) {
 
-      uint64_t bitMask = 0;
+      u64 bitMask = 0;
 
       bitMask |= 1 << tx;
       bitMask |= 1 << de;
@@ -82,8 +82,8 @@ namespace SiliconTorch {
     }
 
 
-    void RS485::write(const uint8_t* data, uint32_t length) {
-      uint32_t send = uart_write_bytes((uart_port_t)uartChannel, reinterpret_cast<const char*>(data), length);
+    void RS485::write(const u8* data, u32 length) {
+      u32 send = uart_write_bytes((uart_port_t)uartChannel, reinterpret_cast<const char*>(data), length);
 
       // TODO: remove after change!
       ESP_LOGE(TAG, "This class is receive-only atm! TX won't work!");
@@ -92,7 +92,7 @@ namespace SiliconTorch {
     }
 
     void RS485::write(std::string& data) {
-      uint32_t send = uart_write_bytes((uart_port_t)uartChannel, data.c_str(), data.length());
+      u32 send = uart_write_bytes((uart_port_t)uartChannel, data.c_str(), data.length());
 
       // TODO: remove after change!
       ESP_LOGE(TAG, "This class is receive-only atm! TX won't work!");
@@ -101,24 +101,24 @@ namespace SiliconTorch {
     }
 
     // returns the real amount of data read
-    uint32_t RS485::read(uint8_t* data, uint32_t length) {
+    u32 RS485::read(u8* data, u32 length) {
       return uart_read_bytes((uart_port_t)uartChannel, data, length, 0);  // TODO: ticks…???
     }
 
-    uint32_t RS485::available() {
+    u32 RS485::available() {
 
       size_t tmp;
       uart_get_buffered_data_len((uart_port_t)uartChannel, &tmp);
 
-      return (uint32_t)tmp;
+      return (u32)tmp;
     }
 
-    void RS485::setBaudRate(uint32_t baudRate) {
+    void RS485::setBaudRate(u32 baudRate) {
       uart_set_baudrate((uart_port_t)uartChannel, baudRate);
     }
 
-    uint32_t RS485::getBaudRate() {
-      uint32_t baudRate = 0;
+    u32 RS485::getBaudRate() {
+      u32 baudRate = 0;
       uart_get_baudrate((uart_port_t)uartChannel, &baudRate);
       return baudRate;
     }
diff --git a/CLC-qthing/SiliconTorch/RS485.hpp b/CLC-qthing/SiliconTorch/RS485.hpp
index 74a2918eb91a2e9ae7f108adaf736a5f3c14ed55..e691c2930cccb39a2461d2459ec48a3dd6327e86 100644
--- a/CLC-qthing/SiliconTorch/RS485.hpp
+++ b/CLC-qthing/SiliconTorch/RS485.hpp
@@ -2,9 +2,10 @@
 
 // C++ system level
 #include <string>
-#include <cinttypes>
 #include <functional>
 
+// project specific
+#include "SpiderLib/NumberTypes.hpp"
 
 
 namespace SiliconTorch {
@@ -13,18 +14,18 @@ namespace SiliconTorch {
 
     class RS485 {
       public:
-        RS485(uint8_t tx, uint8_t rx, uint8_t de, uint8_t re, uint32_t baudRate = 115200, uint8_t uartChannel = 1);
+        RS485(u8 tx, u8 rx, u8 de, u8 re, u32 baudRate = 115200, u8 uartChannel = 1);
 
-        uint32_t getBaudRate();
-        void setBaudRate(uint32_t baudRate);
+        u32 getBaudRate();
+        void setBaudRate(u32 baudRate);
 
-        uint32_t available();
-        uint32_t read(uint8_t* data, uint32_t length);
+        u32 available();
+        u32 read(u8* data, u32 length);
 
       private:
 
-        uint8_t uartChannel;
-        uint8_t tx, rx, de, re;
+        u8 uartChannel;
+        u8 tx, rx, de, re;
 
         void txEN(bool state);
         void rxEN(bool state);
@@ -32,7 +33,7 @@ namespace SiliconTorch {
 
         // Receive only ATM!
         void write(std::string& data);
-        void write(const uint8_t* data, uint32_t length);
+        void write(const u8* data, u32 length);
 
     };
   }
diff --git a/CLC-qthing/SiliconTorch/SiliconTorch.cpp b/CLC-qthing/SiliconTorch/SiliconTorch.cpp
index 1b61ff1f22b7c5a6e32ab4dc3d5722c4def7eda2..857f2e190175c95fea726aa57061635b3b007711 100644
--- a/CLC-qthing/SiliconTorch/SiliconTorch.cpp
+++ b/CLC-qthing/SiliconTorch/SiliconTorch.cpp
@@ -3,7 +3,6 @@
 // C++ system level
 #include <cstring>     // memset, strncmp
 #include <cstdlib>     // TODO: is this for memcpy?
-#include <cinttypes>
 #include <functional>
 
 // ESP32 specific
@@ -19,6 +18,7 @@
 #include "LambdaTask.hpp"
 #include "SpiderLib/Callback.hpp"
 #include "SpiderLib/CallbackMap.hpp"
+#include "SpiderLib/NumberTypes.hpp"
 
 // qthing stuff
 // #include ""
diff --git a/CLC-qthing/SiliconTorch/SiliconTorch.hpp b/CLC-qthing/SiliconTorch/SiliconTorch.hpp
index 866578a7f8639d12f1957dbeea63358f4fff23b2..65b693fd0ad3d55c257ab2866a2e9794a36bb052 100644
--- a/CLC-qthing/SiliconTorch/SiliconTorch.hpp
+++ b/CLC-qthing/SiliconTorch/SiliconTorch.hpp
@@ -2,7 +2,6 @@
 
 // C++ system level
 #include <string>
-#include <cinttypes>
 #include <functional>
 
 // ESP32 specific
@@ -13,6 +12,7 @@
 #include "LambdaTask.hpp"
 #include "SpiderLib/Callback.hpp"
 #include "SpiderLib/CallbackMap.hpp"
+#include "SpiderLib/NumberTypes.hpp"
 
 // qthing stuff
 // #include ""
diff --git a/CLC-qthing/SimpleUART.hpp b/CLC-qthing/SimpleUART.hpp
index 8ffd2d851b9e26649534d22c9ec172e6351cc447..3d108cce211bc725d9499994e03b711091e3eec4 100644
--- a/CLC-qthing/SimpleUART.hpp
+++ b/CLC-qthing/SimpleUART.hpp
@@ -1,6 +1,6 @@
 #pragma once
 
-#include <cinttypes>
+#include "SpiderLib/NumberTypes.hpp"
 
 
 
diff --git a/CLC-qthing/SpiderLib/Callback.hpp b/CLC-qthing/SpiderLib/Callback.hpp
index d637e17ebdbddbd71eebc99e4386a90cfddee855..561ec8f8bccb0ec80308ad704eec14637eba4413 100644
--- a/CLC-qthing/SpiderLib/Callback.hpp
+++ b/CLC-qthing/SpiderLib/Callback.hpp
@@ -3,7 +3,6 @@
 // C++ system level
 // #include <cstring>  // memset, strncmp
 // #include <cstdlib>  // TODO: is this for memcpy?
-// #include <cinttypes>
 #include <functional>
 
 // ESP32 specific
diff --git a/CLC-qthing/SpiderLib/CallbackMap.hpp b/CLC-qthing/SpiderLib/CallbackMap.hpp
index afe772858868f80d92412f630399989bf10cbbf0..6dfed5c3e4ef3f5786b698694eec9af64a22f3c5 100644
--- a/CLC-qthing/SpiderLib/CallbackMap.hpp
+++ b/CLC-qthing/SpiderLib/CallbackMap.hpp
@@ -10,7 +10,8 @@
 // #include "esp_log.h"
 
 // project specific
-// #include "CyanBusCRC.hpp"
+#include "SpiderLib/NumberTypes.hpp"
+
 
 // qthing stuff
 // #include ""
@@ -29,26 +30,26 @@ namespace SpiderLib {
     public:
       typedef std::function<void(Args...)> CallbackF;
 
-      CallbackMap(uint32_t maxPrefixLength = 16) : maxPrefixLength(maxPrefixLength) {};
+      CallbackMap(u32 maxPrefixLength = 16) : maxPrefixLength(maxPrefixLength) {};
 
       // Doesn't work with zero-length prefixes (callback won't be called but no error occurs)
-      void operator()(const uint8_t* const buffer, uint32_t length, Args&&... args) const {
+      void operator()(const u8* const buffer, u32 length, Args&&... args) const {
 
-        uint32_t _len = std::min(maxPrefixLength, length);
+        u32 _len = std::min(maxPrefixLength, length);
 
         char _prefix[_len + 1];
         _prefix[_len] = 0x00;
         std::memcpy(_prefix, buffer, _len);
         std::string prefix(_prefix);
 
-        uint32_t bestMatchLEN = 0;
+        u32 bestMatchLEN = 0;
         CallbackF callback = NULL;
         for (auto it = callbackMap.begin(); it != callbackMap.end(); ++it) {
 
           // input buffer is >= current iterators magic string length
           if (_len >= it->first.length() && prefix.find(it->first) == 0) {
 
-            uint32_t matchLEN = it->first.length();
+            u32 matchLEN = it->first.length();
             if (matchLEN > bestMatchLEN) {
               bestMatchLEN = it->first.length();
               callback = it->second;
@@ -81,7 +82,7 @@ namespace SpiderLib {
       }
 
     private:
-      uint32_t maxPrefixLength;
+      u32 maxPrefixLength;
       mutable std::map<std::string, CallbackF> callbackMap;
   };
 
diff --git a/CLC-qthing/SpiderLib/ManagedMutex.hpp b/CLC-qthing/SpiderLib/ManagedMutex.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..c95160c98fc49e51f12edc5824889cf14c69a978
--- /dev/null
+++ b/CLC-qthing/SpiderLib/ManagedMutex.hpp
@@ -0,0 +1,55 @@
+#pragma once
+
+// C++ system level
+#include <functional>
+
+// ESP32 specific
+#include "esp_log.h"
+#include "FreeRTOS.h"
+#include "freertos/semphr.h"
+
+// project specific
+// #include <SpiderLib/Util.hpp>
+
+
+namespace SpiderLib {
+
+  class ManagedMutex {
+
+    public:
+      ManagedMutex() {
+
+        semphr = xSemaphoreCreateBinary();
+
+        if (semphr == NULL) {
+          ESP_LOGE("ManagedMutex", "Memory allocation FAILED");
+          abort();
+        }
+
+        xSemaphoreGive(semphr);
+      }
+
+      void run(std::function<void()> body) {
+
+        xSemaphoreTake(semphr, portMAX_DELAY);
+        body();
+        xSemaphoreGive(semphr);
+      }
+
+      template<typename T>
+      T runReturn(std::function<T()> body) {
+
+        xSemaphoreTake(semphr, portMAX_DELAY);
+        T result = body();
+        xSemaphoreGive(semphr);
+
+        return result;
+      }
+
+    private:
+
+      SemaphoreHandle_t semphr;
+
+  };
+
+}
diff --git a/CLC-qthing/SpiderLib/NumberTypes.hpp b/CLC-qthing/SpiderLib/NumberTypes.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..0cd1cd713491b120ea1658d776dfc6527c2dc244
--- /dev/null
+++ b/CLC-qthing/SpiderLib/NumberTypes.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <cinttypes>
+
+
+using u8   = uint8_t;
+using i8   =  int8_t;
+
+using u16  = uint16_t;
+using i16  =  int16_t;
+
+using u32  = uint32_t;
+using i32  =  int32_t;
+
+using u64  = uint64_t;
+using i64  =  int64_t;
+
+using f32  = float;
+using f64  = double;
+using f128 = long double;
diff --git a/CLC-qthing/SpiderLib/ObjectTypes.hpp b/CLC-qthing/SpiderLib/ObjectTypes.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a9a2ddb4e7a831fed8ced69814260feb6242af31
--- /dev/null
+++ b/CLC-qthing/SpiderLib/ObjectTypes.hpp
@@ -0,0 +1,10 @@
+#pragma once
+
+#include <string>
+
+
+
+using str = std::string;
+
+
+// TODO: more useful types…?
diff --git a/CLC-qthing/SpiderLib/SNTP.cpp b/CLC-qthing/SpiderLib/SNTP.cpp
index 575ae2942ee59ab3c1b2df1ba6a58466ee46857d..9fa644f1ea5d4413f269819289c65c574ce01371 100644
--- a/CLC-qthing/SpiderLib/SNTP.cpp
+++ b/CLC-qthing/SpiderLib/SNTP.cpp
@@ -12,10 +12,9 @@
 #include <ctime>
 #include <cstring>
 #include <functional>
-#include <cinttypes>
 
 // project specific
-// #include "Metrics.hpp"
+#include "SpiderLib/NumberTypes.hpp"
 
 
 /*extern "C" {
diff --git a/CLC-qthing/SpiderLib/SNTP.hpp b/CLC-qthing/SpiderLib/SNTP.hpp
index 2dc7d0d075de3a0c5b370b71190b39a69fc3e6a9..517e6b88bcc9b350f4796d9162515156d8417557 100644
--- a/CLC-qthing/SpiderLib/SNTP.hpp
+++ b/CLC-qthing/SpiderLib/SNTP.hpp
@@ -4,11 +4,10 @@
 // #include "driver/ledc.h"
 
 // C++ system level
-// #include <cinttypes>
 #include <functional>
 
 // project specific
-// #include "Metrics.hpp"
+// #include "SpiderLib/NumberTypes.hpp"
 
 
 namespace SpiderLib {
diff --git a/CLC-qthing/SpiderLib/SpiderLib.hpp b/CLC-qthing/SpiderLib/SpiderLib.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..8aa62588f5002f01a8ef263cd12c562f1cbc6bae
--- /dev/null
+++ b/CLC-qthing/SpiderLib/SpiderLib.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+
+// ╔═══════════════════════════════════╗
+// â•‘ Conglomerate-Header for SpiderLib â•‘
+// ╚═══════════════════════════════════╝
+
+
+#include <SpiderLib/UDP.hpp>
+#include <SpiderLib/SNTP.hpp>
+#include <SpiderLib/Time.hpp>
+#include <SpiderLib/Util.hpp>
+#include <SpiderLib/Callback.hpp>
+#include <SpiderLib/CallbackMap.hpp>
+#include <SpiderLib/NumberTypes.hpp>
+#include <SpiderLib/ObjectTypes.hpp>
+#include <SpiderLib/ManagedMutex.hpp>
diff --git a/CLC-qthing/SpiderLib/Time.cpp b/CLC-qthing/SpiderLib/Time.cpp
index f1785a6dfa00c0955dbaf64823572e7129e77f80..4b71702ce0b0b143a73664967b7e846d467cf783 100644
--- a/CLC-qthing/SpiderLib/Time.cpp
+++ b/CLC-qthing/SpiderLib/Time.cpp
@@ -4,17 +4,17 @@
 #include "esp_timer.h"
 
 // C++ system level
-#include <cinttypes>
+// #include <functional>
 
 // project specific
-// #include "MyHeader.hpp"
+#include "SpiderLib/NumberTypes.hpp"
 
 
 
 namespace SpiderLib {
 
-  uint32_t Time::s()  { return (uint32_t)(esp_timer_get_time() / 1000000ULL); }
-  uint64_t Time::ms() { return (uint64_t)(esp_timer_get_time() /    1000ULL); }
-  uint64_t Time::us() { return (uint64_t) esp_timer_get_time(); }
+  u32 Time::s()  { return (u32)(esp_timer_get_time() / 1000000ULL); }
+  u64 Time::ms() { return (u64)(esp_timer_get_time() /    1000ULL); }
+  u64 Time::us() { return (u64) esp_timer_get_time(); }
 
 }
diff --git a/CLC-qthing/SpiderLib/Time.hpp b/CLC-qthing/SpiderLib/Time.hpp
index 9ada8dcbd1099552de1aaa1fd5ad28a0559fca5d..ae4f78f1bd1439695d8ac29a95d08274ff083063 100644
--- a/CLC-qthing/SpiderLib/Time.hpp
+++ b/CLC-qthing/SpiderLib/Time.hpp
@@ -4,10 +4,10 @@
 // #include "MyHeader.h"
 
 // C++ system level
-#include <cinttypes>
+// #include <functional>
 
 // project specific
-// #include "MyHeader.hpp"
+#include "SpiderLib/NumberTypes.hpp"
 
 
 namespace SpiderLib {
@@ -15,9 +15,9 @@ namespace SpiderLib {
 
   class Time {
     public:
-      static uint32_t  s();
-      static uint64_t ms();
-      static uint64_t us();
+      static u32  s();
+      static u64 ms();
+      static u64 us();
   };
 
 }
diff --git a/CLC-qthing/SpiderLib/Types.hpp b/CLC-qthing/SpiderLib/Types.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..f183fbf4fb5486e8a628d8579b964f7060fd6592
--- /dev/null
+++ b/CLC-qthing/SpiderLib/Types.hpp
@@ -0,0 +1,4 @@
+#pragma once
+
+#include <NumberTypes.hpp>
+#include <ObjectTypes.hpp>
diff --git a/CLC-qthing/SpiderLib/UDP.cpp b/CLC-qthing/SpiderLib/UDP.cpp
index 4f4e7f31cd6641161cdd8ce53f4449c0b3b6ed6f..e63be3d0a7b60eb388ac5341c11bab9be74108d3 100644
--- a/CLC-qthing/SpiderLib/UDP.cpp
+++ b/CLC-qthing/SpiderLib/UDP.cpp
@@ -11,13 +11,15 @@
 #include "lwip/sockets.h"
 #include "lwip/sys.h"
 
+#include "SpiderLib/NumberTypes.hpp"
+
 
 static const char* TAG = "udp-server";
 
 static const in_port_t PORT = 4213;
 
 // rate-limits positive udp log messages; time in milliseconds
-static const uint16_t loggingTimeout = 500;  // TODO: make configurable?!
+static const u16 loggingTimeout = 500;  // TODO: make configurable?!
 
 static std::map<std::string, qthing::udpPacketCallback> packetCallbackMap;
 
@@ -66,9 +68,9 @@ static void udp_server_task(void* pvParameters) {
     ESP_LOGI(TAG, "Waiting for data");
 
     // This is for the rate limited logging only
-    uint32_t loggingBytes = 0;
-    uint16_t loggingPackets = 0;
-    uint32_t loggingLastMillis = qthing::millis();
+    u32 loggingBytes = 0;
+    u16 loggingPackets = 0;
+    u32 loggingLastMillis = qthing::millis();
 
     while (true) {
       struct sockaddr_in6 sourceAddr;  // Large enough for both IPv4 or IPv6
@@ -102,7 +104,7 @@ static void udp_server_task(void* pvParameters) {
         }
 
         std::string payload_str(rx_buffer);
-        int16_t lenBestMatch = -1;
+        i16 lenBestMatch = -1;
         qthing::udpPacketCallback callback = NULL;
         for (auto it = packetCallbackMap.begin(); it != packetCallbackMap.end(); ++it) {
           if (len >= it->first.length() && payload_str.find(it->first) == 0) {
@@ -112,7 +114,7 @@ static void udp_server_task(void* pvParameters) {
         }
 
         if (lenBestMatch > -1) {
-          qthing::udpPacket packet = {.sourceAddr = sourceAddr, .payload = rx_buffer, .length = (uint16_t)len};
+          qthing::udpPacket packet = {.sourceAddr = sourceAddr, .payload = rx_buffer, .length = (u16)len};
 
           callback(packet);
         } else {
diff --git a/CLC-qthing/SpiderLib/UDP.hpp b/CLC-qthing/SpiderLib/UDP.hpp
index 40e3bb9e9c7c9c600b6be13761d8487c59c0f3cf..29ce42102127904b1c41bdf73dc7073eeb112a30 100644
--- a/CLC-qthing/SpiderLib/UDP.hpp
+++ b/CLC-qthing/SpiderLib/UDP.hpp
@@ -1,5 +1,7 @@
 #pragma once
 
+#include "SpiderLib/NumberTypes.hpp"
+
 
 /*
 
diff --git a/CLC-qthing/SpiderLib/Util.hpp b/CLC-qthing/SpiderLib/Util.hpp
index 3acace6f7961a2dfbdb210e89c2a15b1f614b84e..050321ac5c0ef0aba5ae573a1a6bf862d6fbbf95 100644
--- a/CLC-qthing/SpiderLib/Util.hpp
+++ b/CLC-qthing/SpiderLib/Util.hpp
@@ -6,10 +6,10 @@
 // C++ system level
 #include <vector>
 #include <string>
-#include <cinttypes>
+#include <cstring>
 
 // project specific
-// #include "MyHeader.hpp"
+#include "SpiderLib/NumberTypes.hpp"
 
 
 namespace SpiderLib {
@@ -18,5 +18,43 @@ namespace SpiderLib {
 
     std::vector<std::string> split(const std::string& s, char delim);
 
+
+    template< template<typename> typename T>
+    std::string join(T<std::string>& collection, const std::string& delimiter) {
+
+      u32 length = 0;
+
+      // caching this temporarily
+      // TODO: do we need this or would the compiler be smart enough to cache it itself?
+      // or couldn't he cache it itself because C++ is strict and it is a method-call?
+      // questions over questions………
+      u32 delimiterLength = delimiter.length();
+
+      for (auto const& item : collection) length += item.length() + delimiterLength;  // TODO: replace delimiterLength -> delimiter.length()  ?
+
+
+      length++;
+      char str[length];
+      char* ptr = str;
+      std::memset(str, 0x00, length);
+
+      for (auto const& item : collection) {
+        
+        u32 len = item.length();
+
+        std::memcpy(ptr, item.c_str(), len);
+        ptr += len;
+
+        std::memcpy(ptr, delimiter.c_str(), delimiterLength);
+        ptr += delimiterLength;
+      }
+
+      ptr -= delimiterLength;
+      std::memset(ptr, 0x00, delimiterLength);  // clear out the trailing delimiter
+
+      return std::string(str);
+    }
+
+
   }
 }
diff --git a/CLC-qthing/device_config.h b/CLC-qthing/device_config.h
index c8ce0fb631620be58343d945e3bc64e0c47af617..41978b1eedd446b4fd95b93ffe764a51999bc075 100644
--- a/CLC-qthing/device_config.h
+++ b/CLC-qthing/device_config.h
@@ -1,5 +1,5 @@
 // hostname and device namespace
-#define DEVICE_NAME "CLC-Drucker"
+#define DEVICE_NAME "CLC"
 
 #define NTP_SERVER "pool.ntp.org"
 
diff --git a/CLC-qthing/device_main.cpp b/CLC-qthing/device_main.cpp
index 0bd8b40b9222467b16a9530014b873b222618917..054ba95dad7b1787860166d66c231518e524db24 100644
--- a/CLC-qthing/device_main.cpp
+++ b/CLC-qthing/device_main.cpp
@@ -8,12 +8,15 @@
 
 
 #include "CyanLight.hpp"
+#include "SiliconTorch/FxCyanF.hpp"
+
+#include "SpiderLib/NumberTypes.hpp"
 
 
 // ### LIBS FOR TESTING ###
 #include <cstdlib>
 //#include "SpiderLib/SNTP.hpp"
-// #include "SpiderLib/Util.hpp"
+#include "SpiderLib/Util.hpp"
 
 #include "SiliconTorch/CyanBus.hpp"
 
@@ -25,10 +28,16 @@
 
 //#include "SiliconTorch/FxPublish.hpp"
 
+
+#include "SiliconTorch/NVSExplorer.hpp"
+#include <set>  // remove after NVSExplorer development!
+
 // ###     END LIBS     ###
 
 
 
+#include <algorithm>
+
 
 
 SiliconTorch::CyanBus::CyanBus* cyanBus = NULL;
@@ -40,16 +49,9 @@ CyanLight::CyanLightControl* ctrl;
 
 
 
-#include "SiliconTorch/NVSExplorer.hpp"
-
 void device_main() {
 
 
-
-  //SiliconTorch::NVSExplorer::BullShit();
-  
-//return;
-
   qthing::Config cfg;
 
   // Needed for packet parsing, animation rendering and stuff
@@ -58,7 +60,6 @@ void device_main() {
 
 
 
-
   //cyanBus = new SiliconTorch::CyanBus::CyanBus(13, 14, 12, 15, 2000000);  // Pinout of CyanStripe
 
 
@@ -79,22 +80,41 @@ void device_main() {
   // TODO: ???
 
 
+  // Trigger singleton initialization
+  SiliconTorch::NVSExplorer::NVSExplorer::instance();
+
+
+  //std::set<std::string> namespaces = SiliconTorch::NVSExplorer::NVSExplorer::instance().listNamespaces();
+
+  //std::string _ns = SiliconTorch::NVSExplorer::toString(namespaces, " ~=[]=~ ");
+
+  //ESP_LOGW("__SET__", "Listing Namespaces: %s", _ns.c_str());
+
+
+
+  ctrl = new CyanLight::CyanLightControl(0);
+
+  // auto fxCyanF = (SiliconTorch::FxCyanF::FxCyanF) *ctrl;
+  // SiliconTorch::FxCyanF::configureFromNVS(fxCyanF);
+
   qthing::enable_wifi();
-  cfg.apply();
+  return;
 
-  //return;
 
-  
-  
 
+
+  // #############################
+  // ### CLC-Drucker init code ###
+  // #############################
+
+
+/*
   ctrl = new CyanLight::CyanLightControl(3);
-  //ctrl->addChannel(16);
-  //ctrl->addChannel(17);
   
   ctrl->setFrqRes(100, 19);
 
 
-  for (uint8_t i = 0; i < 100; i++) {
+  for (u8 i = 0; i < 100; i++) {
 
     bool _f = i % 2 == 0;
 
@@ -111,7 +131,17 @@ void device_main() {
 
 
   qthing::enable_wifi();
+  cfg.apply();
+
   return;
+*/
+
+
+  // ### end CLC-Drucker ###
+  // #############################
+
+
+
 
 
 
@@ -119,13 +149,13 @@ void device_main() {
   float limit = 50.0f;
 
   while (true) {
-    for (uint8_t i = 0; i < limit; i++) {
+    for (u8 i = 0; i < limit; i++) {
       float pwm = i / limit;
       ctrl->setPWM(0, pwm*pwm);
       vTaskDelay(delay);
     }
 
-    for (uint8_t i = 0; i < limit; i++) {
+    for (u8 i = 0; i < limit; i++) {
       float pwm = i / limit;
       ctrl->setPWM(0, 1.0f - pwm*pwm);
       vTaskDelay(delay);
diff --git a/README.md b/README.md
index 82f8280dbf8b5e8662bb382c71c39b804b818c89..00616da77b71ef4b214554c3bd7cb96f2a17dc87 100644
--- a/README.md
+++ b/README.md
@@ -1,85 +1,33 @@
 CyanLight
 =========
 
-Simple `PT4115`-BreakoutBoard, initially designed for my special 490 nm LED but may also be used for generic projects
+Evolved from a "Simple `PT4115`-BreakoutBoard" we now have a full blown electronics and software project!
 
-If you want to know more about `CyanBus`, `CyanLight`'s new animation protocol suite on top of `RS485` just goto [the documentation of SiliconTorch](SiliconTorch/README.md) !
+`CyanLight` now stands for the complete light and animation system which I'm developing for my appartement.
 
-Pinout
-------
+It consists of multiple hardware and software layers with a possible full stack-up looking like this from the bottom upwards:
 
-Pinout of the companion board `CyanLightControl`. All external general purpose IOs are protected against ESD and negative reverse voltage input.
+- `CyanLight v[10W].1` - `PT4115` board (LED current control)  
+- `CyanLightControl` - `ESP32` board outputting some `PWM` signals  
+- `SiliconTorch[C++]` - `ESP32` firmware implementing protocols like `CyanBus` and `FxCyanF`  
+- `CyanBus` - `RS485` serial protocol for packetized data streaming  
+- `FxCyanF` - `LED` animation protocol  
+- `CyanBusInjector` - `Ethernet` to `CyanBus` bridging board  
+- `SiliconTorch[PY]` - High-Level device control via `Python`  
 
-| GPIO |    Function     |
-|-----:|----------------:|
-|  27  |  `PT4115` DIM   |
-|  23  |     IR recv     |
-|  25  | general purpose |
-|  26  | general purpose |
-|  32  | general purpose |
-|  33  | general purpose |
+The last mentioned layer would then run on some SBC in a drawer and do the animation rendering. But what if this is not the end?  
 
+Big things are on the way! Source-less animation building coming soonâ„¢!
 
-Component selection
--------------------
-
-### Current sensing resistor `Rs`
-
-| I_LED |   Rs    |     P | Min PKG |
-|------:|:-------:|------:|--------:|
-| 0.1 A | 1.000 Ω | 10 mW |    0201 |
-| 0.2 A | 0.500 Ω | 20 mW |    0201 |
-|  0.3A | 0.333 Ω | 30 mW |    0201 |
-| 0.4 A | 0.250 Ω | 40 mW |    0201 |
-| 0.5 A | 0.200 Ω | 50 mW |    0201 |
-| 0.6 A | 0.167 Ω | 60 mW |    0402 |
-| 0.7 A | 0.143 Ω | 70 mW |    0603 |
-| 0.8 A | 0.125 Ω | 80 mW |    0603 |
-| 0.9 A | 0.111 Ω | 90 mW |    0603 |
-| 1.0 A | 0.100 Ω |100 mW |    0603 |
-| 1.1 A | 0.091 Ω |110 mW |    0805 |
-| 1.2 A | 0.083 Ω |120 mW |    0805 |
-
-
-### Inductor `I`
-
-|             I_LED |           L |
-|------------------:|------------:|
-|           I > 1 A |  27 - 47 µH |
-|   0.8 A < I ≤ 1 A |  33 - 82 µH |
-| 0.4 A < I ≤ 0.8 A | 47 - 100 µH |
-|         I ≤ 0.4 A | 68 - 220 µH |
 
 `CyanLight` PCBs
 ----------------
 
-### `10W`
-
-Designed for the quadratic standard 10W LED modules. Running from at least 12V input voltage.
-
-![PCB rendering](doc/10W.png "PCB rendering")
-
-
-### `HexPCB`
-
-Designed for the standard 3W single-chip high power LEDs. Running from 12V - 24V depending of LED's forward voltage.
-May be populated with up to 6 individual LEDs and contains `0805` footprints to bridge unpopulated LEDs with 0Ω resistors.
+Section moved to the [PCB README file](/pcb/README.md)
 
-![PCB rendering](doc/HexPCB.png "PCB rendering")
 
-
-### `CyanLightControl`
-
-`ESP32` powered companion board for `CyanLight`.
-
-Contains 3.3 V buck regulator for effiecency and an experimental IR receiver.
-Mates directly with the LED boards for power and PWM signal connection via `Micropart-4` connector.
-
-![PCB rendering](doc/CyanLightControl.png "PCB rendering")
-
-
-`fxCyanF` aka `CyanLight`s network protocol
-----------------------------------------------
+`FxCyanF` aka `CyanLight`s network protocol
+--------------------------------------------
 
 ### Introduction
 
@@ -89,12 +37,13 @@ Both protocols share the same basic concept: Time critical animation data is sen
 
 ### General Architecture
 
-`fxCyanF` constists of the following protocols:
+`FxCyanF` constists of the following protocols:
 
 - `MQTT` for configuration als device status
   - animation data *may* be sent over `MQTT` too, but this is only recommended for very slow animations or setting of a constant mood in your living room
 - `UDP` for animation data
-- `IrDA` for animation data (implementation pending!)
+- `CyanBus` (`RS485`) for animation data
+- ~~`IrDA` for animation data~~
 
 
 ### The `MQTT` protocol
@@ -107,6 +56,11 @@ Both protocols share the same basic concept: Time critical animation data is sen
 **[TODO!]**
 
 
+### The `CyanBus` protocol stack
+
+**[TODO!]**
+
+
 ### ~~The `IrDA` protocol~~
 
 There won't be any `IrDA` as R&D discovered the following problems:
diff --git a/cad/CyanBusTransceiver/PCBSocket.scad b/cad/CyanBusTransceiver/PCBSocket.scad
index ac4f6a39b5ad3c4e9f949062a6f9d158c7afe890..4ef1f76b51391daddbdccf4609d753ce3790bcbe 100644
--- a/cad/CyanBusTransceiver/PCBSocket.scad
+++ b/cad/CyanBusTransceiver/PCBSocket.scad
@@ -2,12 +2,118 @@
 $fs = 0.35;
 $fa = 0.50;
 
+$str  = 3.0;       // base strength
+$str1 = 2.5;       // strength for the smaller sides
 
-nozzle = 0.4;
+$eps  = 0.01;      // epsilon
 
-pcb_w = 50.0 + nozzle;
-pcb_h = 21.5 + nozzle;
+tolerance = 0.4;
 
-pcb_z_off = 11.6;  // hieght of transceiver pcb above ground
+pcb_w     = 50.0 + tolerance;
+pcb_h     = 21.5 + tolerance;
+pcb_str   =  1.6;
+pcb_z_off = 12.0;  // height of transceiver pcb above ground
 
 
+M2_outer  =  6.5;  // outer diameter for the M2 screw receptacles
+
+
+// s = socket
+s_h = 13;
+s_w = pcb_w;
+
+
+// sc = screw; here: the M2 holes of the PCB
+sc_x     = 8.25;
+sc_y     = 7.75;
+sc_drill = 3.0;
+
+
+// ph = PinHeader
+ph_w     =  7.5;          // enough space for SMD PinHeaders
+ph_led_x =  5.7;
+ph_485_x = -1.9  - 1.27;
+ph_led_l =  11.4 + 1.25;
+ph_485_l =  16.5 + 1.25;
+
+
+
+module screwPlacement(tz=0) {
+  translate([ sc_x, -sc_y, tz]) children();
+  translate([-sc_x,  sc_y, tz]) children();
+}
+
+
+module ph_led_placement() {
+  translate([ph_led_x,  pcb_h/2 - $str/2, 0]) children();
+}
+
+module ph_485_placement() {
+  translate([ph_485_x, -pcb_h/2 + $str/2, 0]) children();
+}
+
+
+module border(sy=pcb_z_off, sz=$str1, length=pcb_w, h=pcb_str) {
+
+  translate([-length/2, 0, 0])
+    rotate([0, 90, 0])
+      linear_extrude(length)
+        polygon([
+          [-h,  0],
+          [sy,  0],
+          [-h, sz],
+        ]);
+
+}
+
+
+
+module PCBSocket() {
+
+  linear_extrude(pcb_z_off) difference() {
+    union() {
+      difference() {
+        square([pcb_w,           pcb_h         ], center=true);
+        square([pcb_w - 2*$str1, pcb_h - 2*$str], center=true);
+      }
+
+      pll2 = ph_led_l + 2*$str;
+      translate([0, $str/2, 0])
+        ph_led_placement()
+          translate([-pll2/2, -ph_w -0.2, 0])
+            square([pll2, ph_w +0.2]);
+
+      p4l2 = ph_485_l + 2*$str;
+      translate([0, -$str/2, 0])
+        ph_485_placement()
+          translate([-p4l2/2, 0.2, 0])
+            square([p4l2, ph_w +0.2]);
+      
+      screwPlacement() circle(d=M2_outer);
+    }
+
+    ph_led_placement() square([ph_led_l, ph_w], center=true);
+    ph_485_placement() square([ph_485_l, ph_w], center=true);
+
+
+    screwPlacement() circle(d=sc_drill);
+  }
+
+
+  difference() {
+    union() {
+      translate([0,  pcb_h/2 -$eps, pcb_z_off]) border();
+      translate([0, -pcb_h/2 +$eps, pcb_z_off]) mirror([0, 1, 0]) border();
+    }
+
+
+    ph_led_placement() cube([ph_led_l, 10, 100], center=true);
+    ph_485_placement() cube([ph_485_l, 10, 100], center=true);
+
+  }
+
+}
+
+
+PCBSocket();
+
diff --git a/pcb/README.md b/pcb/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..e65781db5e3ba927e21836fb72584173a4fecf5f
--- /dev/null
+++ b/pcb/README.md
@@ -0,0 +1,84 @@
+CyanLight PCB Documentation
+===========================
+
+This `README` will give you a short introduction to the PCBs of this project
+
+
+`CyanLightControl v1.1`
+-----------------------
+
+`ESP32` powered companion board for `CyanLight`.
+
+Contains 3.3 V buck regulator for effiecency and an experimental IR receiver.
+Mates directly with the LED boards for power and PWM signal connection via `Micropart-4` connector.
+
+![PCB rendering](/doc/CyanLightControl.png "PCB rendering")
+
+There never was a `v1.0` of this board.
+
+### Pinout
+
+| GPIO |    Function     |
+|-----:|----------------:|
+|  27  |  `PT4115` DIM   |
+|  23  |     IR recv     |
+|  25  | general purpose |
+|  26  | general purpose |
+|  32  | general purpose |
+|  33  | general purpose |
+
+
+`CyanLight` LED PCBs
+--------------------
+
+Simple `PT4115`-BreakoutBoard, initially designed for my special 490 nm LED but may also be used for generic projects
+
+If you want to know more about `CyanBus`, `CyanLight`'s new animation protocol suite on top of `RS485` just goto [the documentation of SiliconTorch](/SiliconTorch/README.md) !
+
+
+### Component selection
+
+#### Current sensing resistor `Rs`
+
+| I_LED |   Rs    |     P | Min PKG |
+|------:|:-------:|------:|--------:|
+| 0.1 A | 1.000 Ω | 10 mW |    0201 |
+| 0.2 A | 0.500 Ω | 20 mW |    0201 |
+|  0.3A | 0.333 Ω | 30 mW |    0201 |
+| 0.4 A | 0.250 Ω | 40 mW |    0201 |
+| 0.5 A | 0.200 Ω | 50 mW |    0201 |
+| 0.6 A | 0.167 Ω | 60 mW |    0402 |
+| 0.7 A | 0.143 Ω | 70 mW |    0603 |
+| 0.8 A | 0.125 Ω | 80 mW |    0603 |
+| 0.9 A | 0.111 Ω | 90 mW |    0603 |
+| 1.0 A | 0.100 Ω |100 mW |    0603 |
+| 1.1 A | 0.091 Ω |110 mW |    0805 |
+| 1.2 A | 0.083 Ω |120 mW |    0805 |
+
+
+#### Inductor `I`
+
+|             I_LED |           L |
+|------------------:|------------:|
+|           I > 1 A |  27 - 47 µH |
+|   0.8 A < I ≤ 1 A |  33 - 82 µH |
+| 0.4 A < I ≤ 0.8 A | 47 - 100 µH |
+|         I ≤ 0.4 A | 68 - 220 µH |
+
+### `10W`
+
+Designed for the quadratic standard 10W LED modules. Running from at least 12V input voltage.
+
+![PCB rendering](/doc/10W.png "PCB rendering")
+
+
+### `HexPCB`
+
+Designed for the standard 3W single-chip high power LEDs. Running from 12V - 24V depending of LED's forward voltage.
+May be populated with up to 6 individual LEDs and contains `0805` footprints to bridge unpopulated LEDs with 0Ω resistors.
+
+![PCB rendering](/doc/HexPCB.png "PCB rendering")
+
+
+
+## TODO: futher PCB doc!