Explorar o código

Make settings available on Menu

Just Call Me Koko %!s(int64=4) %!d(string=hai) anos
pai
achega
373482822a

+ 27 - 0
esp32_marauder/Display.cpp

@@ -144,6 +144,33 @@ bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data)
   return false;
 }*/
 
+void Display::drawFrame()
+{
+  tft.drawRect(FRAME_X, FRAME_Y, FRAME_W, FRAME_H, TFT_BLACK);
+}
+
+void Display::tftDrawRedOnOffButton() {
+  tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, TFT_RED);
+  tft.fillRect(GREENBUTTON_X, GREENBUTTON_Y, GREENBUTTON_W, GREENBUTTON_H, TFT_DARKGREY);
+  drawFrame();
+  tft.setTextColor(TFT_WHITE);
+  tft.setTextSize(2);
+  tft.setTextDatum(MC_DATUM);
+  tft.drawString("ON", GREENBUTTON_X + (GREENBUTTON_W / 2), GREENBUTTON_Y + (GREENBUTTON_H / 2));
+  this->SwitchOn = false;
+}
+
+void Display::tftDrawGreenOnOffButton() {
+  tft.fillRect(GREENBUTTON_X, GREENBUTTON_Y, GREENBUTTON_W, GREENBUTTON_H, TFT_GREEN);
+  tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, TFT_DARKGREY);
+  drawFrame();
+  tft.setTextColor(TFT_WHITE);
+  tft.setTextSize(2);
+  tft.setTextDatum(MC_DATUM);
+  tft.drawString("OFF", REDBUTTON_X + (REDBUTTON_W / 2) + 1, REDBUTTON_Y + (REDBUTTON_H / 2));
+  this->SwitchOn = true;
+}
+
 void Display::tftDrawGraphObjects(byte x_scale)
 {
   //draw the graph objects

+ 22 - 0
esp32_marauder/Display.h

@@ -69,6 +69,23 @@
 #define STATUS_BAR_WIDTH 16
 #define LVGL_TICK_PERIOD 6
 
+#define FRAME_X 100
+#define FRAME_Y 64
+#define FRAME_W 120
+#define FRAME_H 50
+
+// Red zone size
+#define REDBUTTON_X FRAME_X
+#define REDBUTTON_Y FRAME_Y
+#define REDBUTTON_W (FRAME_W/2)
+#define REDBUTTON_H FRAME_H
+
+// Green zone size
+#define GREENBUTTON_X (REDBUTTON_X + REDBUTTON_W)
+#define GREENBUTTON_Y FRAME_Y
+#define GREENBUTTON_W (FRAME_W/2)
+#define GREENBUTTON_H FRAME_H
+
 #define STATUSBAR_COLOR 0x4A49
 
 #define KIT_LED_BUILTIN 13
@@ -90,6 +107,7 @@ PROGMEM static lv_obj_t *kb;
 class Display
 {
   private:
+    bool SwitchOn = false;
     
     bool run_setup = true;
     
@@ -100,6 +118,8 @@ class Display
     boolean change_colour = 1;
     boolean selected = 1;
 
+    void drawFrame();
+
     //void addNodes(Menu* menu, String name, Menu* child, std::function<void()> callable);
     //void changeMenu(Menu* menu);
     //void showMenuList(Menu* menu, int layer);
@@ -150,6 +170,8 @@ class Display
     //void initLVGL();
     //void deinitLVGL();
     //void joinWiFiGFX();
+    void tftDrawRedOnOffButton();
+    void tftDrawGreenOnOffButton();
     void tftDrawGraphObjects(byte x_scale);
     void tftDrawEapolColorKey();
     void tftDrawColorKey();

+ 152 - 56
esp32_marauder/MenuFunctions.cpp

@@ -155,6 +155,90 @@ void MenuFunctions::writeBadUSB(){
   lv_keyboard_set_cursor_manage(kb, true);
 }
 
+// Event handler for settings drop down menus
+void setting_dropdown_cb(lv_obj_t * obj, lv_event_t event) {
+  //lv_event_code_t code = lv_event_get_code(event);
+  //lv_obj_t * obj = lv_event_get_target(event);
+  //lv_obj_t * list1 = lv_obj_get_parent(lv_obj_get_parent(obj));
+  //if(event == LV_EVENT_CLICKED) {
+  //    LV_LOG_USER("Clicked: %s", lv_list_get_btn_text(list1, obj));
+  //}
+}
+
+void settings_list_cb(lv_obj_t * btn, lv_event_t event) {
+  extern Settings settings_obj;
+  extern MenuFunctions menu_function_obj;
+
+  String btn_text = lv_list_get_btn_text(btn);
+  String display_string = "";
+  
+  if (event == LV_EVENT_CLICKED) {
+    if (btn_text == "Exit") {
+      Serial.println("Exiting...");
+      lv_obj_del_async(lv_obj_get_parent(lv_obj_get_parent(btn)));
+
+      printf("LV_EVENT_CANCEL\n");
+      Serial.println("Potato");
+      //menu_function_obj.deinitLVGL();
+      //wifi_scan_obj.StartScan(WIFI_SCAN_OFF);
+      //display_obj.exit_draw = true; // set everything back to normal
+    }
+    else {
+      // Build base obj to host buttons
+      Serial.println("Creating base object...");
+      lv_obj_t * obj;
+      obj = lv_obj_create(lv_scr_act(), NULL);
+      lv_obj_set_size(obj, LV_HOR_RES, LV_VER_RES);
+      
+      lv_obj_t * exit_btn;
+
+      lv_obj_t * label;
+      
+      // Build the generic Exit button
+      exit_btn = lv_btn_create(obj, NULL);
+      lv_obj_set_event_cb(exit_btn, settings_list_cb);
+      lv_label_set_text(label, "Exit");
+      //lv_obj_center(label);
+
+      label = lv_label_create(exit_btn, NULL);
+
+      // Create the type specific device
+      if (settings_obj.getSettingType(btn_text) == "bool") {
+        lv_obj_t * sw = lv_switch_create(obj, NULL);
+        lv_obj_align(sw, NULL, LV_ALIGN_CENTER, 0, 0);
+      }
+    }
+  }
+
+  /*
+  if (event == LV_EVENT_VALUE_CHANGED) {      
+    if (lv_btn_get_state(btn) == LV_BTN_STATE_CHECKED_RELEASED) {
+      //Serial.print("Toggle on: ");
+      //Serial.println(btn_text);
+      for (int i = 0; i < access_points->size(); i++) {
+        if (access_points->get(i).essid == btn_text) {
+          Serial.println("Adding AP: " + (String)access_points->get(i).essid);
+          AccessPoint ap = access_points->get(i);
+          ap.selected = true;
+          access_points->set(i, ap);
+        }
+      }
+    }
+    else {
+      //Serial.print("Toggle off: ");
+      //Serial.println(btn_text);
+      for (int i = 0; i < access_points->size(); i++) {
+        if (access_points->get(i).essid == btn_text) {
+          Serial.println("Removing AP: " + (String)access_points->get(i).essid);
+          AccessPoint ap = access_points->get(i);
+          ap.selected = false;
+          access_points->set(i, ap);
+        }
+      }
+    }
+  }*/
+}
+
 void MenuFunctions::displaySettingsGFX(){
   extern Settings settings_obj;
 
@@ -173,6 +257,8 @@ void MenuFunctions::displaySettingsGFX(){
 
   lv_obj_t * label;
 
+  lv_obj_t * sw;
+
   list_btn = lv_list_add_btn(list1, LV_SYMBOL_CLOSE, "Exit");
   lv_obj_set_event_cb(list_btn, ap_list_cb);
 
@@ -181,9 +267,30 @@ void MenuFunctions::displaySettingsGFX(){
     json["Settings"][i]["name"].as<String>().toCharArray(buf, json["Settings"][i]["name"].as<String>().length() + 1);
     
     list_btn = lv_list_add_btn(list1, LV_SYMBOL_WIFI, buf);
-    lv_btn_set_checkable(list_btn, true);
-    lv_obj_set_event_cb(list_btn, ap_list_cb);
-
+    lv_btn_set_checkable(list_btn, false);
+    lv_obj_set_event_cb(list_btn, settings_list_cb);
+
+    //lv_list_add_text(list1, buf);
+
+    // Create the dropdown menu
+    /*lv_obj_t * dd = lv_dropdown_create(list1, NULL);
+    lv_dropdown_set_options(dd, "Apple\n"
+                                "Banana\n"
+                                "Orange\n"
+                                "Cherry\n"
+                                "Grape\n"
+                                "Raspberry\n"
+                                "Melon\n"
+                                "Orange\n"
+                                "Lemon\n"
+                                "Nuts");
+
+    //lv_obj_align(dd, LV_ALIGN_IN_RIGHT_MID, 0, 20);
+    lv_obj_align(dd, NULL, LV_ALIGN_IN_RIGHT_MID, 0, 0);
+    lv_obj_set_width(dd, LV_HOR_RES / 3);
+    lv_obj_set_event_cb(dd, setting_dropdown_cb);
+    //lv_obj_add_event_cb(dd, setting_dropdown_cb, LV_EVENT_ALL, NULL);*/
+    
     //if (access_points->get(i).selected)
     //  lv_btn_toggle(list_btn);
 
@@ -191,9 +298,6 @@ void MenuFunctions::displaySettingsGFX(){
     //lv_obj_set_event_cb(btn1, ap_list_cb);
     //lv_obj_align(btn1, NULL, LV_ALIGN_CENTER, 0, 0);
     //lv_btn_set_checkable(btn1, true);
-
-    //label = lv_label_create(btn1, NULL);
-    //lv_label_set_text(label, buf);
   }
 }
 
@@ -234,56 +338,7 @@ void MenuFunctions::addAPGFX(){
   }
 }
 
-void settings_list_cb(lv_obj_t * btn, lv_event_t event) {
-  extern Settings settings_obj;
-  extern MenuFunctions menu_function_obj;
 
-  String btn_text = lv_list_get_btn_text(btn);
-  String display_string = "";
-  
-  if (event == LV_EVENT_CLICKED) {
-    if (btn_text != "Exit") {
-      //lv_list_focus_btn(lv_obj_get_parent(lv_obj_get_parent(btn)), btn);
-    }
-    else {
-      Serial.println("Exiting...");
-      lv_obj_del_async(lv_obj_get_parent(lv_obj_get_parent(btn)));
-
-      printf("LV_EVENT_CANCEL\n");
-      menu_function_obj.deinitLVGL();
-      wifi_scan_obj.StartScan(WIFI_SCAN_OFF);
-      display_obj.exit_draw = true; // set everything back to normal
-    }
-  }
-
-  /*
-  if (event == LV_EVENT_VALUE_CHANGED) {      
-    if (lv_btn_get_state(btn) == LV_BTN_STATE_CHECKED_RELEASED) {
-      //Serial.print("Toggle on: ");
-      //Serial.println(btn_text);
-      for (int i = 0; i < access_points->size(); i++) {
-        if (access_points->get(i).essid == btn_text) {
-          Serial.println("Adding AP: " + (String)access_points->get(i).essid);
-          AccessPoint ap = access_points->get(i);
-          ap.selected = true;
-          access_points->set(i, ap);
-        }
-      }
-    }
-    else {
-      //Serial.print("Toggle off: ");
-      //Serial.println(btn_text);
-      for (int i = 0; i < access_points->size(); i++) {
-        if (access_points->get(i).essid == btn_text) {
-          Serial.println("Removing AP: " + (String)access_points->get(i).essid);
-          AccessPoint ap = access_points->get(i);
-          ap.selected = false;
-          access_points->set(i, ap);
-        }
-      }
-    }
-  }*/
-}
 
 void ap_list_cb(lv_obj_t * btn, lv_event_t event) {
   extern LinkedList<AccessPoint>* access_points;
@@ -1141,6 +1196,22 @@ void MenuFunctions::orientDisplay()
   changeMenu(current_menu);
 }
 
+void MenuFunctions::runBoolSetting(String key) {
+  Serial.println("Building bool setting screen...");
+  display_obj.tftDrawRedOnOffButton();
+  //display_obj.tftDrawGreenOnOffButton();
+}
+
+void MenuFunctions::callSetting(String key) {
+  specSettingMenu.name = key;
+  
+  String setting_type = settings_obj.getSettingType(key);
+
+  if (setting_type == "bool") {
+    this->runBoolSetting(key);
+  }
+}
+
 
 // Function to build the menus
 void MenuFunctions::RunSetup()
@@ -1163,6 +1234,8 @@ void MenuFunctions::RunSetup()
   confirmMenu.list = new LinkedList<MenuNode>();
   espUpdateMenu.list = new LinkedList<MenuNode>();
   updateMenu.list = new LinkedList<MenuNode>();
+  settingsMenu.list = new LinkedList<MenuNode>();
+  specSettingMenu.list = new LinkedList<MenuNode>();
   infoMenu.list = new LinkedList<MenuNode>();
 
   // WiFi menu stuff
@@ -1193,6 +1266,7 @@ void MenuFunctions::RunSetup()
   espUpdateMenu.name = " ESP8266 Update ";
   updateMenu.name = " Update Firmware ";
   infoMenu.name = " Device Info ";
+  settingsMenu.name = " Settings ";
   bluetoothMenu.name = " Bluetooth ";
   wifiSnifferMenu.name = " WiFi Sniffers ";
   wifiAttackMenu.name = " WiFi Attacks ";
@@ -1481,11 +1555,33 @@ void MenuFunctions::RunSetup()
     changeMenu(&infoMenu);
     wifi_scan_obj.RunInfo();
   });
-  addNodes(&deviceMenu, "Settings", TFT_NAVY, NULL, KEYBOARD_ICO, [this](){
+  addNodes(&deviceMenu, "Settings", TFT_NAVY, NULL, KEYBOARD_ICO, [this]() {
+    changeMenu(&settingsMenu);
+  });
+  /*addNodes(&deviceMenu, "Settings", TFT_NAVY, NULL, KEYBOARD_ICO, [this](){
     display_obj.clearScreen(); 
     wifi_scan_obj.currentScanMode = LV_ADD_SSID; 
     wifi_scan_obj.StartScan(LV_ADD_SSID, TFT_RED);  
     displaySettingsGFX();
+  });*/
+
+  // Settings menu
+  // Device menu
+  settingsMenu.parentMenu = &deviceMenu;
+  addNodes(&settingsMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this]() {
+    changeMenu(settingsMenu.parentMenu);
+  });
+  for (int i = 0; i < settings_obj.getNumberSettings(); i++) {
+    addNodes(&settingsMenu, settings_obj.setting_index_to_name(i), TFT_LIGHTGREY, NULL, 0, [this, i]() {
+      changeMenu(&specSettingMenu);
+      this->callSetting(settings_obj.setting_index_to_name(i));
+    });
+  }
+
+  // Specific setting menu
+  specSettingMenu.parentMenu = &settingsMenu;
+  addNodes(&specSettingMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this]() {
+    changeMenu(specSettingMenu.parentMenu);
   });
  
   // Select update

+ 5 - 0
esp32_marauder/MenuFunctions.h

@@ -93,6 +93,7 @@ PROGMEM static void write_bad_usb_keyboard_event_cb(lv_obj_t * keyboard, lv_even
 PROGMEM static void load_btn_cb(lv_obj_t * load_btn, lv_event_t event);
 PROGMEM static void test_btn_cb(lv_obj_t * load_btn, lv_event_t event);
 PROGMEM static void ap_list_cb(lv_obj_t * btn, lv_event_t event);
+PROGMEM static void setting_dropdown_cb(lv_obj_t * btn, lv_event_t event);
 PROGMEM static void save_as_keyboard_event_cb(lv_obj_t * keyboard, lv_event_t event);
 
 // lvgl stuff
@@ -145,6 +146,8 @@ class MenuFunctions
     Menu confirmMenu;
     Menu espUpdateMenu;
     Menu updateMenu;
+    Menu settingsMenu;
+    Menu specSettingMenu;
     Menu infoMenu;
 
     // WiFi menu stuff
@@ -176,6 +179,8 @@ class MenuFunctions
     void battery(bool initial = false);
     void battery2(bool initial = false);
     void showMenuList(Menu* menu, int layer);
+    void callSetting(String key);
+    void runBoolSetting(String ley);
 
   public:
     MenuFunctions();

+ 23 - 2
esp32_marauder/WiFiScan.cpp

@@ -152,11 +152,15 @@ void WiFiScan::RunSetup() {
     
   ssids = new LinkedList<ssid>();
   access_points = new LinkedList<AccessPoint>();
+  NimBLEDevice::setScanFilterMode(CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE);
+  NimBLEDevice::setScanDuplicateCacheSize(200);
   NimBLEDevice::init("");
   pBLEScan = NimBLEDevice::getScan(); //create new scan
   this->ble_initialized = true;
   
   this->shutdownBLE();
+
+  this->initWiFi(1);
 }
 
 int WiFiScan::clearAPs() {
@@ -258,10 +262,26 @@ void WiFiScan::joinWiFi(String ssid, String password)
   this->wifi_initialized = true;
 }
 
+// Apply WiFi settings
+void WiFiScan::initWiFi(uint8_t scan_mode) {
+  // Set the channel
+  if (scan_mode != WIFI_SCAN_OFF) {
+    Serial.println(F("Initializing WiFi settings..."));
+    this->set_channel = settings_obj.loadSetting<uint8_t>("Channel");
+    this->changeChannel();
+  
+    this->force_pmkid = settings_obj.loadSetting<bool>("Force PMKID");
+    this->force_probe = settings_obj.loadSetting<bool>("Force Probe");
+    this->save_pcap = settings_obj.loadSetting<bool>("Save PCAP");
+    this->channel_hop_delay = settings_obj.loadSetting<int>("Channel Hop Delay");
+    Serial.println(F("Initialization complete"));
+  }
+}
+
 // Function to prepare to run a specific scan
 void WiFiScan::StartScan(uint8_t scan_mode, uint16_t color)
 {  
-  //Serial.println("Starting Scan...");
+  this->initWiFi(scan_mode);
   if (scan_mode == WIFI_SCAN_OFF)
     StopScan(scan_mode);
   else if (scan_mode == WIFI_SCAN_PROBE)
@@ -1137,6 +1157,7 @@ void WiFiScan::RunBluetoothScan(uint8_t scan_mode, uint16_t color)
   Serial.println("BT Controller Status: " + (String)esp_bt_controller_get_status());
   */
   NimBLEDevice::setScanFilterMode(CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE);
+  NimBLEDevice::setScanDuplicateCacheSize(200);
   NimBLEDevice::init("");
   pBLEScan = NimBLEDevice::getScan(); //create new scan
   if (scan_mode == BT_SCAN_ALL)
@@ -2693,7 +2714,7 @@ void WiFiScan::main(uint32_t currentTime)
   (currentScanMode == WIFI_SCAN_DEAUTH) ||
   (currentScanMode == WIFI_SCAN_ALL))
   {
-    if (currentTime - initTime >= 1000)
+    if (currentTime - initTime >= this->channel_hop_delay * 1000)
     {
       initTime = millis();
       channelHop();

+ 9 - 0
esp32_marauder/WiFiScan.h

@@ -21,6 +21,7 @@
 #include "Buffer.h"
 #include "BatteryInterface.h"
 #include "TemperatureInterface.h"
+#include "settings.h"
 #include "Assets.h"
 //#include "MenuFunctions.h"
 
@@ -60,6 +61,7 @@ extern SDInterface sd_obj;
 extern Buffer buffer_obj;
 extern BatteryInterface battery_obj;
 extern TemperatureInterface temp_obj;
+extern Settings settings_obj;
 
 esp_err_t esp_wifi_80211_tx(wifi_interface_t ifx, const void *buffer, int len, bool en_sys_seq);
 //int ieee80211_raw_frame_sanity_check(int32_t arg, int32_t arg2, int32_t arg3);
@@ -79,6 +81,12 @@ struct AccessPoint {
 class WiFiScan
 {
   private:
+    // Settings
+    int channel_hop_delay = 1;
+    bool force_pmkid = false;
+    bool force_probe = false;
+    bool save_pcap = false;
+  
     int x_pos; //position along the graph x axis
     float y_pos_x; //current graph y axis position of X value
     float y_pos_x_old = 120; //old y axis position of X value
@@ -100,6 +108,7 @@ class WiFiScan
 
     uint32_t initTime = 0;
     bool run_setup = true;
+    void initWiFi(uint8_t scan_mode);
     int bluetoothScanTime = 5;
     int packets_sent = 0;
     const wifi_promiscuous_filter_t filt = {.filter_mask=WIFI_PROMIS_FILTER_MASK_MGMT | WIFI_PROMIS_FILTER_MASK_DATA};

+ 2 - 0
esp32_marauder/esp32_marauder.ino

@@ -77,6 +77,8 @@ void setup()
   
   //Serial.begin(115200);
 
+  Serial.println("\n\nHello, World!\n");
+
   Serial.println("ESP-IDF version is: " + String(esp_get_idf_version()));
   
   display_obj.RunSetup();

+ 55 - 4
esp32_marauder/settings.cpp

@@ -119,6 +119,39 @@ uint8_t Settings::loadSetting<uint8_t>(String key) {
   return 0;
 }
 
+String Settings::setting_index_to_name(int i) {
+  DynamicJsonDocument json(1024); // ArduinoJson v6
+
+  if (deserializeJson(json, this->json_settings_string)) {
+    Serial.println("\nCould not parse json");
+  }
+
+  return json["Settings"][i]["name"];
+}
+
+int Settings::getNumberSettings() {
+  DynamicJsonDocument json(1024); // ArduinoJson v6
+
+  if (deserializeJson(json, this->json_settings_string)) {
+    Serial.println("\nCould not parse json");
+  }
+
+  return json["Settings"].size();
+}
+
+String Settings::getSettingType(String key) {
+  DynamicJsonDocument json(1024); // ArduinoJson v6
+
+  if (deserializeJson(json, this->json_settings_string)) {
+    Serial.println("\nCould not parse json");
+  }
+  
+  for (int i = 0; i < json["Settings"].size(); i++) {
+    if (json["Settings"][i]["name"].as<String>() == key)
+      return json["Settings"][i]["type"];
+  }
+}
+
 void Settings::printJsonSettings(String json_string) {
   DynamicJsonDocument json(1024); // ArduinoJson v6
 
@@ -151,14 +184,32 @@ bool Settings::createDefaultSettings(fs::FS &fs) {
   jsonBuffer["Settings"][0]["name"] = "Channel";
   jsonBuffer["Settings"][0]["type"] = "uint8_t";
   jsonBuffer["Settings"][0]["value"] = 11;
+  jsonBuffer["Settings"][0]["range"]["min"] = 1;
+  jsonBuffer["Settings"][0]["range"]["max"] = 14;
 
-  jsonBuffer["Settings"][1]["name"] = "Force PMKID";
-  jsonBuffer["Settings"][1]["type"] = "bool";
-  jsonBuffer["Settings"][1]["value"] = true;
+  jsonBuffer["Settings"][1]["name"] = "Channel Hop Delay";
+  jsonBuffer["Settings"][1]["type"] = "int";
+  jsonBuffer["Settings"][1]["value"] = 1;
+  jsonBuffer["Settings"][1]["range"]["min"] = 1;
+  jsonBuffer["Settings"][1]["range"]["max"] = 10;
 
-  jsonBuffer["Settings"][2]["name"] = "Save PCAP";
+  jsonBuffer["Settings"][2]["name"] = "Force PMKID";
   jsonBuffer["Settings"][2]["type"] = "bool";
   jsonBuffer["Settings"][2]["value"] = true;
+  jsonBuffer["Settings"][2]["range"]["min"] = false;
+  jsonBuffer["Settings"][2]["range"]["max"] = true;
+
+  jsonBuffer["Settings"][3]["name"] = "Force Probe";
+  jsonBuffer["Settings"][3]["type"] = "bool";
+  jsonBuffer["Settings"][3]["value"] = true;
+  jsonBuffer["Settings"][3]["range"]["min"] = false;
+  jsonBuffer["Settings"][3]["range"]["max"] = true;
+
+  jsonBuffer["Settings"][4]["name"] = "Save PCAP";
+  jsonBuffer["Settings"][4]["type"] = "bool";
+  jsonBuffer["Settings"][4]["value"] = true;
+  jsonBuffer["Settings"][4]["range"]["min"] = false;
+  jsonBuffer["Settings"][4]["range"]["max"] = true;
 
   //jsonBuffer.printTo(settingsFile);
   if (serializeJson(jsonBuffer, settingsFile) == 0) {

+ 4 - 0
esp32_marauder/settings.h

@@ -25,6 +25,10 @@ class Settings {
     template <typename T>
     T loadSetting(String name);
 
+    String getSettingType(String key);
+    String setting_index_to_name(int i);
+    int getNumberSettings();
+
     //template<>
     //int loadSetting<int>(String key);