mirror of
https://github.com/justcallmekoko/ESP32Marauder.git
synced 2026-07-28 14:47:16 -07:00
@@ -2256,8 +2256,6 @@ void WiFiScan::StartScan(uint8_t scan_mode, uint16_t color) {
|
||||
#endif
|
||||
RunProbeScan(scan_mode, color);
|
||||
}
|
||||
else if (scan_mode == WIFI_SCAN_STATION_WAR_DRIVE)
|
||||
RunProbeScan(scan_mode, color);
|
||||
else if (scan_mode == WIFI_SCAN_EVIL_PORTAL)
|
||||
RunEvilPortal(scan_mode, color);
|
||||
else if (scan_mode == WIFI_SCAN_EAPOL)
|
||||
@@ -2554,7 +2552,6 @@ void WiFiScan::StopScan(uint8_t scan_mode) {
|
||||
(currentScanMode == WIFI_SCAN_SAE_COMMIT) ||
|
||||
(currentScanMode == WIFI_SCAN_AP) ||
|
||||
(currentScanMode == WIFI_SCAN_WAR_DRIVE) ||
|
||||
(currentScanMode == WIFI_SCAN_STATION_WAR_DRIVE) ||
|
||||
(currentScanMode == WIFI_SCAN_EVIL_PORTAL) ||
|
||||
(currentScanMode == WIFI_SCAN_RAW_CAPTURE) ||
|
||||
(currentScanMode == WIFI_SCAN_STATION) ||
|
||||
@@ -2646,10 +2643,8 @@ void WiFiScan::StopScan(uint8_t scan_mode) {
|
||||
}
|
||||
|
||||
// Close POI file if wardrive was active
|
||||
if ((currentScanMode == WIFI_SCAN_WAR_DRIVE) ||
|
||||
(currentScanMode == WIFI_SCAN_STATION_WAR_DRIVE)) {
|
||||
if (currentScanMode == WIFI_SCAN_WAR_DRIVE)
|
||||
this->closePoiFile();
|
||||
}
|
||||
|
||||
|
||||
if ((currentScanMode == BT_SCAN_ALL) ||
|
||||
@@ -5134,8 +5129,7 @@ void WiFiScan::RunBeaconScan(uint8_t scan_mode, uint16_t color) {
|
||||
#ifdef HAS_GPS
|
||||
if (gps_obj.getGpsModuleStatus()) {
|
||||
startLog(F("wardrive"));
|
||||
String header_line = "WigleWifi-1.4,appRelease=" + (String)MARAUDER_VERSION + ",model=ESP32 Marauder,release=" + (String)MARAUDER_VERSION + ",device=ESP32 Marauder,display=SPI TFT,board=ESP32 Marauder,brand=JustCallMeKoko\nMAC,SSID,AuthMode,FirstSeen,Channel,RSSI,CurrentLatitude,CurrentLongitude,AltitudeMeters,AccuracyMeters,Type\n";
|
||||
buffer_obj.append(header_line);
|
||||
buffer_obj.append(this->header_line);
|
||||
this->openPoiFile();
|
||||
} else {
|
||||
return;
|
||||
@@ -5320,19 +5314,6 @@ void WiFiScan::RunProbeScan(uint8_t scan_mode, uint16_t color) {
|
||||
startPcap(F("flock"));
|
||||
else if (scan_mode == WIFI_SCAN_DETECT_FOLLOW)
|
||||
startPcap(F("mac_track"));
|
||||
else if (scan_mode == WIFI_SCAN_STATION_WAR_DRIVE) {
|
||||
#ifdef HAS_GPS
|
||||
if (gps_obj.getGpsModuleStatus()) {
|
||||
startLog(F("station_wardrive"));
|
||||
String header_line = "WigleWifi-1.4,appRelease=" + (String)MARAUDER_VERSION + ",model=ESP32 Marauder,release=" + (String)MARAUDER_VERSION + ",device=ESP32 Marauder,display=SPI TFT,board=ESP32 Marauder,brand=JustCallMeKoko\nMAC,SSID,AuthMode,FirstSeen,Channel,RSSI,CurrentLatitude,CurrentLongitude,AltitudeMeters,AccuracyMeters,Type\n";
|
||||
buffer_obj.append(header_line);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
this->setLEDMode(MODE_SNIFF);
|
||||
|
||||
@@ -5344,8 +5325,6 @@ void WiFiScan::RunProbeScan(uint8_t scan_mode, uint16_t color) {
|
||||
display_obj.tft.drawCentreString(text_table4[40],TFT_WIDTH / 2,16,2);
|
||||
else if (scan_mode == WIFI_SCAN_DETECT_FOLLOW)
|
||||
display_obj.tft.drawCentreString("MAC Monitor",TFT_WIDTH / 2,16,2);
|
||||
else if (scan_mode == WIFI_SCAN_STATION_WAR_DRIVE)
|
||||
display_obj.tft.drawCentreString("Station Wardrive",TFT_WIDTH / 2,16,2);
|
||||
else {
|
||||
display_obj.tft.drawCentreString("Flock Sniff",TFT_WIDTH / 2,16,2);
|
||||
}
|
||||
@@ -5356,7 +5335,6 @@ void WiFiScan::RunProbeScan(uint8_t scan_mode, uint16_t color) {
|
||||
#endif
|
||||
display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
if ((scan_mode != WIFI_SCAN_DETECT_FOLLOW) &&
|
||||
(scan_mode != WIFI_SCAN_STATION_WAR_DRIVE) &&
|
||||
(scan_mode != BT_SCAN_FLOCK)) {
|
||||
display_obj.tftDrawChannelScaleButtons(set_channel, false);
|
||||
display_obj.tftDrawExitScaleButtons(false);
|
||||
@@ -5472,8 +5450,7 @@ void WiFiScan::RunBluetoothScan(uint8_t scan_mode, uint16_t color) {
|
||||
this->startWardriverWiFi();
|
||||
this->wifi_initialized = true;
|
||||
}
|
||||
String header_line = "WigleWifi-1.4,appRelease=" + (String)MARAUDER_VERSION + ",model=ESP32 Marauder,release=" + (String)MARAUDER_VERSION + ",device=ESP32 Marauder,display=SPI TFT,board=ESP32 Marauder,brand=JustCallMeKoko\nMAC,SSID,AuthMode,FirstSeen,Channel,RSSI,CurrentLatitude,CurrentLongitude,AltitudeMeters,AccuracyMeters,Type\n";
|
||||
buffer_obj.append(header_line);
|
||||
buffer_obj.append(this->header_line);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -6199,14 +6176,14 @@ String WiFiScan::processPwnagotchiBeacon(const uint8_t* frame, int length) {
|
||||
bool deauth = doc["policy"]["deauth"];
|
||||
int uptime = doc["uptime"];
|
||||
|
||||
Serial.print(F("Pwnagotchi Name: "));
|
||||
Serial.print(F("Name: "));
|
||||
Serial.println(name);
|
||||
Serial.print(F("Pwnd Totals: "));
|
||||
Serial.print(F("Pwnd #: "));
|
||||
Serial.println(pwnd_tot);
|
||||
|
||||
#ifdef HAS_SCREEN
|
||||
|
||||
display_obj.display_buffer->add(String("Pwnagotchi: ") + name + ", ");
|
||||
display_obj.display_buffer->add(String("Name: ") + name + ", ");
|
||||
display_obj.display_buffer->add(" Pwnd: " + String(pwnd_tot) + ", ");
|
||||
display_obj.display_buffer->add(" Uptime: " + String(uptime) + ", ");
|
||||
if (deauth)
|
||||
@@ -6217,7 +6194,7 @@ String WiFiScan::processPwnagotchiBeacon(const uint8_t* frame, int length) {
|
||||
display_obj.display_buffer->add(String(" Ver: ") + ver + " ");
|
||||
#endif
|
||||
|
||||
return String("Pwnagotchi: ") + name + ", \nPwnd: " + String(pwnd_tot) + ", \nVer: " + ver;
|
||||
return String("Name: ") + name + ", \nPwnd: " + String(pwnd_tot) + ", \nVer: " + ver;
|
||||
}
|
||||
else
|
||||
return "";
|
||||
@@ -7135,7 +7112,6 @@ void WiFiScan::beaconSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type
|
||||
String essid = "";
|
||||
|
||||
if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
|
||||
(wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION_WAR_DRIVE) ||
|
||||
(wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
|
||||
(wifi_scan_obj.currentScanMode == WIFI_SCAN_PWN)) {
|
||||
if (type == WIFI_PKT_MGMT) {
|
||||
@@ -9982,7 +9958,6 @@ void WiFiScan::main(uint32_t currentTime)
|
||||
(currentScanMode == WIFI_SCAN_PINESCAN) ||
|
||||
(currentScanMode == WIFI_SCAN_MULTISSID) ||
|
||||
(currentScanMode == WIFI_SCAN_DEAUTH) ||
|
||||
(currentScanMode == WIFI_SCAN_STATION_WAR_DRIVE) ||
|
||||
(currentScanMode == WIFI_SCAN_ALL))
|
||||
{
|
||||
if (currentTime - initTime >= this->channel_hop_delay * HOP_DELAY) {
|
||||
|
||||
@@ -682,6 +682,8 @@ class WiFiScan
|
||||
static MacEntry mac_entries[mac_history_len_half];
|
||||
static uint8_t mac_entry_state[mac_history_len_half];
|
||||
|
||||
String header_line = "WigleWifi-1.4,appRelease=" + (String)MARAUDER_VERSION + ",model=ESP32 Marauder,release=" + (String)MARAUDER_VERSION + ",device=ESP32 Marauder,display=SPI TFT,board=ESP32 Marauder,brand=JustCallMeKoko\nMAC,SSID,AuthMode,FirstSeen,Channel,RSSI,CurrentLatitude,CurrentLongitude,AltitudeMeters,AccuracyMeters,Type\n";
|
||||
|
||||
uint8_t dual_band_channels[DUAL_BAND_CHANNELS] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177};
|
||||
|
||||
uint8_t dual_band_channel_index = 0;
|
||||
|
||||
+456
-410
@@ -1,410 +1,456 @@
|
||||
#include "settings.h"
|
||||
|
||||
String Settings::getSettingsString() {
|
||||
return this->json_settings_string;
|
||||
}
|
||||
|
||||
bool Settings::begin() {
|
||||
if(!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)){
|
||||
return false;
|
||||
}
|
||||
|
||||
File settingsFile;
|
||||
|
||||
//SPIFFS.remove("/settings.json"); // NEED TO REMOVE THIS LINE
|
||||
|
||||
if (SPIFFS.exists("/settings.json")) {
|
||||
settingsFile = SPIFFS.open("/settings.json", FILE_READ);
|
||||
|
||||
if (!settingsFile) {
|
||||
settingsFile.close();
|
||||
if (this->createDefaultSettings(SPIFFS))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this->createDefaultSettings(SPIFFS))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
String json_string;
|
||||
DynamicJsonDocument jsonBuffer(JSON_SETTING_SIZE);
|
||||
DeserializationError error = deserializeJson(jsonBuffer, settingsFile);
|
||||
if (error) {
|
||||
Serial.print("Could not parse json during setup: ");
|
||||
Serial.println(error.f_str());
|
||||
}
|
||||
serializeJson(jsonBuffer, json_string);
|
||||
|
||||
this->json_settings_string = json_string;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T Settings::loadSetting(String key) {}
|
||||
|
||||
// Get type int settings
|
||||
template<>
|
||||
int Settings::loadSetting<int>(String key) {
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE); // 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]["value"];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get type string settings
|
||||
template<>
|
||||
String Settings::loadSetting<String>(String key) {
|
||||
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE); // 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]["value"];
|
||||
}
|
||||
|
||||
Serial.println("Did not find setting named " + (String)key + ". Creating...");
|
||||
if (this->createDefaultSettings(SPIFFS, true, json["Settings"].size(), "String", key))
|
||||
return "";
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
// Get type bool settings
|
||||
template<>
|
||||
bool Settings::loadSetting<bool>(String key) {
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE); // ArduinoJson v6
|
||||
|
||||
if (deserializeJson(json, this->json_settings_string)) {
|
||||
Serial.println("Could not parse json to load");
|
||||
}
|
||||
|
||||
for (int i = 0; i < json["Settings"].size(); i++) {
|
||||
if (json["Settings"][i]["name"].as<String>() == key)
|
||||
return json["Settings"][i]["value"];
|
||||
}
|
||||
|
||||
Serial.println("Did not find setting named " + (String)key + ". Creating...");
|
||||
if (this->createDefaultSettings(SPIFFS, true, json["Settings"].size(), "bool", key))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//Get type uint8_t settings
|
||||
template<>
|
||||
uint8_t Settings::loadSetting<uint8_t>(String key) {
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE); // 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]["value"];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T Settings::saveSetting(String key, bool value) {}
|
||||
|
||||
template<>
|
||||
bool Settings::saveSetting<bool>(String key, bool value) {
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE); // ArduinoJson v6
|
||||
|
||||
if (deserializeJson(json, this->json_settings_string)) {
|
||||
Serial.println("\nCould not parse json");
|
||||
}
|
||||
|
||||
String settings_string;
|
||||
|
||||
for (int i = 0; i < json["Settings"].size(); i++) {
|
||||
if (json["Settings"][i]["name"].as<String>() == key) {
|
||||
json["Settings"][i]["value"] = value;
|
||||
|
||||
Serial.println("Saving setting...");
|
||||
|
||||
File settingsFile = SPIFFS.open("/settings.json", FILE_WRITE);
|
||||
|
||||
if (!settingsFile) {
|
||||
Serial.println(F("Failed to create settings file"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (serializeJson(json, settingsFile) == 0) {
|
||||
Serial.println(F("Failed to write to file"));
|
||||
}
|
||||
if (serializeJson(json, settings_string) == 0) {
|
||||
Serial.println(F("Failed to write to string"));
|
||||
}
|
||||
|
||||
// Close the file
|
||||
settingsFile.close();
|
||||
|
||||
this->json_settings_string = settings_string;
|
||||
|
||||
this->printJsonSettings(settings_string);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T Settings::saveSetting(String key, String value) {}
|
||||
|
||||
template<>
|
||||
bool Settings::saveSetting<bool>(String key, String value) {
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE); // ArduinoJson v6
|
||||
|
||||
if (deserializeJson(json, this->json_settings_string)) {
|
||||
Serial.println("\nCould not parse json");
|
||||
}
|
||||
|
||||
String settings_string;
|
||||
|
||||
for (int i = 0; i < json["Settings"].size(); i++) {
|
||||
if (json["Settings"][i]["name"].as<String>() == key) {
|
||||
json["Settings"][i]["value"] = value;
|
||||
|
||||
File settingsFile = SPIFFS.open("/settings.json", FILE_WRITE);
|
||||
|
||||
if (!settingsFile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (serializeJson(json, settingsFile) == 0) {
|
||||
Serial.println(F("Failed to write to file"));
|
||||
}
|
||||
if (serializeJson(json, settings_string) == 0) {
|
||||
Serial.println(F("Failed to write to string"));
|
||||
}
|
||||
|
||||
// Close the file
|
||||
settingsFile.close();
|
||||
|
||||
this->json_settings_string = settings_string;
|
||||
|
||||
this->printJsonSettings(settings_string);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Settings::toggleSetting(String key) {
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE); // 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) {
|
||||
if (json["Settings"][i]["value"]) {
|
||||
saveSetting<bool>(key, false);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
saveSetting<bool>(key, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String Settings::setting_index_to_name(int i) {
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE); // 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(JSON_SETTING_SIZE); // 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(JSON_SETTING_SIZE); // ArduinoJson v6
|
||||
|
||||
DeserializationError error = deserializeJson(json, this->json_settings_string);
|
||||
|
||||
if (error) {
|
||||
Serial.print("\nCould not parse json: ");
|
||||
Serial.println(error.f_str());
|
||||
}
|
||||
|
||||
for (int i = 0; i < json["Settings"].size(); i++) {
|
||||
if (json["Settings"][i]["name"].as<String>() == key)
|
||||
return json["Settings"][i]["type"];
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void Settings::printJsonSettings(String json_string) {
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE); // ArduinoJson v6
|
||||
|
||||
if (deserializeJson(json, json_string)) {
|
||||
Serial.println("\nCould not parse json");
|
||||
}
|
||||
|
||||
for (int i = 0; i < json["Settings"].size(); i++) {
|
||||
Serial.println("Name: " + json["Settings"][i]["name"].as<String>());
|
||||
Serial.println("Type: " + json["Settings"][i]["type"].as<String>());
|
||||
Serial.println("Value: " + json["Settings"][i]["value"].as<String>() + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
bool Settings::createDefaultSettings(fs::FS &fs, bool spec, uint8_t index, String typeStr, String name) {
|
||||
Serial.println(F("Creating default settings file: settings.json"));
|
||||
|
||||
File settingsFile = fs.open("/settings.json", FILE_WRITE);
|
||||
|
||||
if (!settingsFile) {
|
||||
Serial.println(F("Failed to create settings file"));
|
||||
return false;
|
||||
}
|
||||
|
||||
String settings_string;
|
||||
|
||||
if (!spec) {
|
||||
DynamicJsonDocument jsonBuffer(JSON_SETTING_SIZE);
|
||||
|
||||
jsonBuffer["Settings"][0]["name"] = "ForcePMKID";
|
||||
jsonBuffer["Settings"][0]["type"] = "bool";
|
||||
jsonBuffer["Settings"][0]["value"] = false;
|
||||
jsonBuffer["Settings"][0]["range"]["min"] = false;
|
||||
jsonBuffer["Settings"][0]["range"]["max"] = true;
|
||||
|
||||
jsonBuffer["Settings"][1]["name"] = "ForceProbe";
|
||||
jsonBuffer["Settings"][1]["type"] = "bool";
|
||||
jsonBuffer["Settings"][1]["value"] = false;
|
||||
jsonBuffer["Settings"][1]["range"]["min"] = false;
|
||||
jsonBuffer["Settings"][1]["range"]["max"] = true;
|
||||
|
||||
jsonBuffer["Settings"][2]["name"] = "SavePCAP";
|
||||
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"] = "EnableLED";
|
||||
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"] = "EPDeauth";
|
||||
jsonBuffer["Settings"][4]["type"] = "bool";
|
||||
jsonBuffer["Settings"][4]["value"] = false;
|
||||
jsonBuffer["Settings"][4]["range"]["min"] = false;
|
||||
jsonBuffer["Settings"][4]["range"]["max"] = true;
|
||||
|
||||
jsonBuffer["Settings"][5]["name"] = "ChanHop";
|
||||
jsonBuffer["Settings"][5]["type"] = "bool";
|
||||
jsonBuffer["Settings"][5]["value"] = false;
|
||||
jsonBuffer["Settings"][5]["range"]["min"] = false;
|
||||
jsonBuffer["Settings"][5]["range"]["max"] = true;
|
||||
|
||||
jsonBuffer["Settings"][6]["name"] = "ClientSSID";
|
||||
jsonBuffer["Settings"][6]["type"] = "String";
|
||||
jsonBuffer["Settings"][6]["value"] = "";
|
||||
jsonBuffer["Settings"][6]["range"]["min"] = "";
|
||||
jsonBuffer["Settings"][6]["range"]["max"] = "";
|
||||
|
||||
jsonBuffer["Settings"][7]["name"] = "ClientPW";
|
||||
jsonBuffer["Settings"][7]["type"] = "String";
|
||||
jsonBuffer["Settings"][7]["value"] = "";
|
||||
jsonBuffer["Settings"][7]["range"]["min"] = "";
|
||||
jsonBuffer["Settings"][7]["range"]["max"] = "";
|
||||
|
||||
//jsonBuffer.printTo(settingsFile);
|
||||
if (serializeJson(jsonBuffer, settingsFile) == 0) {
|
||||
}
|
||||
if (serializeJson(jsonBuffer, settings_string) == 0) {
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE); // ArduinoJson v6
|
||||
|
||||
if (deserializeJson(json, this->json_settings_string)) {
|
||||
Serial.println("Could not parse json to create new setting");
|
||||
return false;
|
||||
}
|
||||
|
||||
Serial.println("Creating " + typeStr + " setting...");
|
||||
|
||||
if (typeStr == "bool") {
|
||||
|
||||
json["Settings"][index]["name"] = name;
|
||||
json["Settings"][index]["type"] = typeStr;
|
||||
json["Settings"][index]["value"] = true;
|
||||
json["Settings"][index]["range"]["min"] = false;
|
||||
json["Settings"][index]["range"]["max"] = true;
|
||||
|
||||
if (serializeJson(json, settings_string) == 0) {
|
||||
}
|
||||
|
||||
if (serializeJson(json, settingsFile) == 0) {
|
||||
}
|
||||
}
|
||||
|
||||
else if (typeStr == "String") {
|
||||
json["Settings"][index]["name"] = name;
|
||||
json["Settings"][index]["type"] = typeStr;
|
||||
json["Settings"][index]["value"] = "";
|
||||
json["Settings"][index]["range"]["min"] = "";
|
||||
json["Settings"][index]["range"]["max"] = "";
|
||||
|
||||
if (serializeJson(json, settings_string) == 0) {
|
||||
}
|
||||
|
||||
if (serializeJson(json, settingsFile) == 0) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close the file
|
||||
settingsFile.close();
|
||||
|
||||
this->json_settings_string = settings_string;
|
||||
|
||||
this->printJsonSettings(settings_string);
|
||||
|
||||
return true;
|
||||
}
|
||||
#include "settings.h"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// _buildCache — called once after json_settings_string is loaded/updated.
|
||||
// Parses the JSON exactly once and fills every field of _cache.
|
||||
// All loadSetting<T>() reads hit the cache; no heap is allocated on read.
|
||||
// ---------------------------------------------------------------------------
|
||||
void Settings::_buildCache() {
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE);
|
||||
if (deserializeJson(json, this->json_settings_string)) {
|
||||
Serial.println(F("_buildCache: could not parse json"));
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)json["Settings"].size(); i++) {
|
||||
String name = json["Settings"][i]["name"].as<String>();
|
||||
|
||||
if (name == "ForcePMKID")
|
||||
_cache.ForcePMKID = json["Settings"][i]["value"].as<bool>();
|
||||
else if (name == "ForceProbe")
|
||||
_cache.ForceProbe = json["Settings"][i]["value"].as<bool>();
|
||||
else if (name == "SavePCAP")
|
||||
_cache.SavePCAP = json["Settings"][i]["value"].as<bool>();
|
||||
else if (name == "EnableLED")
|
||||
_cache.EnableLED = json["Settings"][i]["value"].as<bool>();
|
||||
else if (name == "EPDeauth")
|
||||
_cache.EPDeauth = json["Settings"][i]["value"].as<bool>();
|
||||
else if (name == "ChanHop")
|
||||
_cache.ChanHop = json["Settings"][i]["value"].as<bool>();
|
||||
else if (name == "ClientSSID")
|
||||
_cache.ClientSSID = json["Settings"][i]["value"].as<String>();
|
||||
else if (name == "ClientPW")
|
||||
_cache.ClientPW = json["Settings"][i]["value"].as<String>();
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
String Settings::getSettingsString() { return this->json_settings_string; }
|
||||
|
||||
bool Settings::begin() {
|
||||
if (!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
File settingsFile;
|
||||
|
||||
// SPIFFS.remove("/settings.json"); // NEED TO REMOVE THIS LINE
|
||||
|
||||
if (SPIFFS.exists("/settings.json")) {
|
||||
settingsFile = SPIFFS.open("/settings.json", FILE_READ);
|
||||
|
||||
if (!settingsFile) {
|
||||
settingsFile.close();
|
||||
if (this->createDefaultSettings(SPIFFS))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (this->createDefaultSettings(SPIFFS))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
String json_string;
|
||||
DynamicJsonDocument jsonBuffer(JSON_SETTING_SIZE);
|
||||
DeserializationError error = deserializeJson(jsonBuffer, settingsFile);
|
||||
if (error)
|
||||
Serial.println(error.f_str());
|
||||
|
||||
serializeJson(jsonBuffer, json_string);
|
||||
|
||||
this->json_settings_string = json_string;
|
||||
|
||||
// Populate the flat cache from the freshly loaded JSON.
|
||||
this->_buildCache();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// loadSetting<T> — O(1), zero heap, reads straight from the cache struct.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template <typename T> T Settings::loadSetting(String key) {}
|
||||
|
||||
// Get type int settings
|
||||
template <> int Settings::loadSetting<int>(String key) {
|
||||
// No int settings are defined currently; fall back to parsing if ever added.
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE);
|
||||
deserializeJson(json, this->json_settings_string);
|
||||
for (int i = 0; i < (int)json["Settings"].size(); i++) {
|
||||
if (json["Settings"][i]["name"].as<String>() == key)
|
||||
return json["Settings"][i]["value"];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get type String settings — read from cache, no JSON parse
|
||||
template <> String Settings::loadSetting<String>(String key) {
|
||||
if (key == "ClientSSID")
|
||||
return _cache.ClientSSID;
|
||||
if (key == "ClientPW")
|
||||
return _cache.ClientPW;
|
||||
|
||||
// Unknown String key: fall back to JSON so the setting can be auto-created.
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE);
|
||||
deserializeJson(json, this->json_settings_string);
|
||||
for (int i = 0; i < (int)json["Settings"].size(); i++) {
|
||||
if (json["Settings"][i]["name"].as<String>() == key)
|
||||
return json["Settings"][i]["value"].as<String>();
|
||||
}
|
||||
|
||||
//Serial.println("Did not find setting named " + (String)key + ". Creating...");
|
||||
if (this->createDefaultSettings(SPIFFS, true, json["Settings"].size(),
|
||||
"String", key))
|
||||
return "";
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
// Get type bool settings — read from cache, no JSON parse
|
||||
template <> bool Settings::loadSetting<bool>(String key) {
|
||||
if (key == "ForcePMKID")
|
||||
return _cache.ForcePMKID;
|
||||
if (key == "ForceProbe")
|
||||
return _cache.ForceProbe;
|
||||
if (key == "SavePCAP")
|
||||
return _cache.SavePCAP;
|
||||
if (key == "EnableLED")
|
||||
return _cache.EnableLED;
|
||||
if (key == "EPDeauth")
|
||||
return _cache.EPDeauth;
|
||||
if (key == "ChanHop")
|
||||
return _cache.ChanHop;
|
||||
|
||||
// Unknown bool key: fall back to JSON so the setting can be auto-created.
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE);
|
||||
deserializeJson(json, this->json_settings_string);
|
||||
for (int i = 0; i < (int)json["Settings"].size(); i++) {
|
||||
if (json["Settings"][i]["name"].as<String>() == key)
|
||||
return json["Settings"][i]["value"].as<bool>();
|
||||
}
|
||||
|
||||
//Serial.println("Did not find setting named " + (String)key + ". Creating...");
|
||||
if (this->createDefaultSettings(SPIFFS, true, json["Settings"].size(), "bool",
|
||||
key))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get type uint8_t settings — read from cache, no JSON parse
|
||||
template <> uint8_t Settings::loadSetting<uint8_t>(String key) {
|
||||
// uint8_t settings reuse bool cache fields where applicable.
|
||||
if (key == "ForcePMKID")
|
||||
return (uint8_t)_cache.ForcePMKID;
|
||||
if (key == "ForceProbe")
|
||||
return (uint8_t)_cache.ForceProbe;
|
||||
if (key == "SavePCAP")
|
||||
return (uint8_t)_cache.SavePCAP;
|
||||
if (key == "EnableLED")
|
||||
return (uint8_t)_cache.EnableLED;
|
||||
if (key == "EPDeauth")
|
||||
return (uint8_t)_cache.EPDeauth;
|
||||
if (key == "ChanHop")
|
||||
return (uint8_t)_cache.ChanHop;
|
||||
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE);
|
||||
deserializeJson(json, this->json_settings_string);
|
||||
for (int i = 0; i < (int)json["Settings"].size(); i++) {
|
||||
if (json["Settings"][i]["name"].as<String>() == key)
|
||||
return json["Settings"][i]["value"].as<uint8_t>();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// saveSetting — writes SPIFFS, updates json_settings_string, rebuilds cache.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template <typename T> T Settings::saveSetting(String key, bool value) {}
|
||||
|
||||
template <> bool Settings::saveSetting<bool>(String key, bool value) {
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE);
|
||||
|
||||
deserializeJson(json, this->json_settings_string);
|
||||
|
||||
String settings_string;
|
||||
|
||||
for (int i = 0; i < (int)json["Settings"].size(); i++) {
|
||||
if (json["Settings"][i]["name"].as<String>() == key) {
|
||||
json["Settings"][i]["value"] = value;
|
||||
|
||||
File settingsFile = SPIFFS.open("/settings.json", FILE_WRITE);
|
||||
|
||||
if (!settingsFile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
serializeJson(json, settingsFile);
|
||||
serializeJson(json, settings_string);
|
||||
|
||||
settingsFile.close();
|
||||
|
||||
this->json_settings_string = settings_string;
|
||||
|
||||
// Keep the cache in sync — no re-parse needed, just update the field.
|
||||
if (key == "ForcePMKID")
|
||||
_cache.ForcePMKID = value;
|
||||
else if (key == "ForceProbe")
|
||||
_cache.ForceProbe = value;
|
||||
else if (key == "SavePCAP")
|
||||
_cache.SavePCAP = value;
|
||||
else if (key == "EnableLED")
|
||||
_cache.EnableLED = value;
|
||||
else if (key == "EPDeauth")
|
||||
_cache.EPDeauth = value;
|
||||
else if (key == "ChanHop")
|
||||
_cache.ChanHop = value;
|
||||
|
||||
this->printJsonSettings(settings_string);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T> T Settings::saveSetting(String key, String value) {}
|
||||
|
||||
template <> bool Settings::saveSetting<bool>(String key, String value) {
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE);
|
||||
|
||||
deserializeJson(json, this->json_settings_string);
|
||||
|
||||
String settings_string;
|
||||
|
||||
for (int i = 0; i < (int)json["Settings"].size(); i++) {
|
||||
if (json["Settings"][i]["name"].as<String>() == key) {
|
||||
json["Settings"][i]["value"] = value;
|
||||
|
||||
//Serial.println("Saving setting...");
|
||||
|
||||
File settingsFile = SPIFFS.open("/settings.json", FILE_WRITE);
|
||||
|
||||
if (!settingsFile)
|
||||
return false;
|
||||
|
||||
serializeJson(json, settingsFile);
|
||||
serializeJson(json, settings_string);
|
||||
|
||||
settingsFile.close();
|
||||
|
||||
this->json_settings_string = settings_string;
|
||||
|
||||
// Keep the cache in sync for String fields.
|
||||
if (key == "ClientSSID")
|
||||
_cache.ClientSSID = value;
|
||||
else if (key == "ClientPW")
|
||||
_cache.ClientPW = value;
|
||||
|
||||
this->printJsonSettings(settings_string);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// toggleSetting — reads current bool value from cache (fast), then delegates
|
||||
// to saveSetting which will update the cache again.
|
||||
// ---------------------------------------------------------------------------
|
||||
bool Settings::toggleSetting(String key) {
|
||||
// Use the cached value to decide direction — avoids an extra JSON parse.
|
||||
bool current = this->loadSetting<bool>(key);
|
||||
if (current) {
|
||||
saveSetting<bool>(key, false);
|
||||
//Serial.println("Setting value to false");
|
||||
return false;
|
||||
} else {
|
||||
saveSetting<bool>(key, true);
|
||||
//Serial.println("Setting value to true");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Rarely-called utility functions — keep JSON parsing, they are not hot paths.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
String Settings::setting_index_to_name(int i) {
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE);
|
||||
|
||||
deserializeJson(json, this->json_settings_string);
|
||||
|
||||
return json["Settings"][i]["name"];
|
||||
}
|
||||
|
||||
int Settings::getNumberSettings() {
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE);
|
||||
|
||||
deserializeJson(json, this->json_settings_string);
|
||||
|
||||
return json["Settings"].size();
|
||||
}
|
||||
|
||||
String Settings::getSettingType(String key) {
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE);
|
||||
|
||||
deserializeJson(json, this->json_settings_string);
|
||||
|
||||
for (int i = 0; i < (int)json["Settings"].size(); i++) {
|
||||
if (json["Settings"][i]["name"].as<String>() == key)
|
||||
return json["Settings"][i]["type"];
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void Settings::printJsonSettings(String json_string) {
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE);
|
||||
|
||||
deserializeJson(json, json_string);
|
||||
|
||||
Serial.println("Settings\n----------------------------------------------");
|
||||
for (int i = 0; i < (int)json["Settings"].size(); i++) {
|
||||
Serial.println("Name: " + json["Settings"][i]["name"].as<String>());
|
||||
Serial.println("Type: " + json["Settings"][i]["type"].as<String>());
|
||||
Serial.println("Value: " + json["Settings"][i]["value"].as<String>() + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// createDefaultSettings — sets json_settings_string then rebuilds the cache.
|
||||
// ---------------------------------------------------------------------------
|
||||
bool Settings::createDefaultSettings(fs::FS &fs, bool spec, uint8_t index, String typeStr, String name) {
|
||||
File settingsFile = fs.open("/settings.json", FILE_WRITE);
|
||||
|
||||
if (!settingsFile) {
|
||||
//Serial.println(F("Failed to create settings file"));
|
||||
return false;
|
||||
}
|
||||
|
||||
String settings_string;
|
||||
|
||||
if (!spec) {
|
||||
DynamicJsonDocument jsonBuffer(JSON_SETTING_SIZE);
|
||||
|
||||
jsonBuffer["Settings"][0]["name"] = "ForcePMKID";
|
||||
jsonBuffer["Settings"][0]["type"] = "bool";
|
||||
jsonBuffer["Settings"][0]["value"] = false;
|
||||
jsonBuffer["Settings"][0]["range"]["min"] = false;
|
||||
jsonBuffer["Settings"][0]["range"]["max"] = true;
|
||||
|
||||
jsonBuffer["Settings"][1]["name"] = "ForceProbe";
|
||||
jsonBuffer["Settings"][1]["type"] = "bool";
|
||||
jsonBuffer["Settings"][1]["value"] = false;
|
||||
jsonBuffer["Settings"][1]["range"]["min"] = false;
|
||||
jsonBuffer["Settings"][1]["range"]["max"] = true;
|
||||
|
||||
jsonBuffer["Settings"][2]["name"] = "SavePCAP";
|
||||
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"] = "EnableLED";
|
||||
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"] = "EPDeauth";
|
||||
jsonBuffer["Settings"][4]["type"] = "bool";
|
||||
jsonBuffer["Settings"][4]["value"] = false;
|
||||
jsonBuffer["Settings"][4]["range"]["min"] = false;
|
||||
jsonBuffer["Settings"][4]["range"]["max"] = true;
|
||||
|
||||
jsonBuffer["Settings"][5]["name"] = "ChanHop";
|
||||
jsonBuffer["Settings"][5]["type"] = "bool";
|
||||
jsonBuffer["Settings"][5]["value"] = false;
|
||||
jsonBuffer["Settings"][5]["range"]["min"] = false;
|
||||
jsonBuffer["Settings"][5]["range"]["max"] = true;
|
||||
|
||||
jsonBuffer["Settings"][6]["name"] = "ClientSSID";
|
||||
jsonBuffer["Settings"][6]["type"] = "String";
|
||||
jsonBuffer["Settings"][6]["value"] = "";
|
||||
jsonBuffer["Settings"][6]["range"]["min"] = "";
|
||||
jsonBuffer["Settings"][6]["range"]["max"] = "";
|
||||
|
||||
jsonBuffer["Settings"][7]["name"] = "ClientPW";
|
||||
jsonBuffer["Settings"][7]["type"] = "String";
|
||||
jsonBuffer["Settings"][7]["value"] = "";
|
||||
jsonBuffer["Settings"][7]["range"]["min"] = "";
|
||||
jsonBuffer["Settings"][7]["range"]["max"] = "";
|
||||
|
||||
//jsonBuffer.printTo(settingsFile);
|
||||
if (serializeJson(jsonBuffer, settingsFile) == 0) {
|
||||
}
|
||||
if (serializeJson(jsonBuffer, settings_string) == 0) {
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
DynamicJsonDocument json(JSON_SETTING_SIZE); // ArduinoJson v6
|
||||
|
||||
if (deserializeJson(json, this->json_settings_string)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeStr == "bool") {
|
||||
|
||||
json["Settings"][index]["name"] = name;
|
||||
json["Settings"][index]["type"] = typeStr;
|
||||
json["Settings"][index]["value"] = true;
|
||||
json["Settings"][index]["range"]["min"] = false;
|
||||
json["Settings"][index]["range"]["max"] = true;
|
||||
|
||||
if (serializeJson(json, settings_string) == 0) {
|
||||
}
|
||||
|
||||
if (serializeJson(json, settingsFile) == 0) {
|
||||
}
|
||||
}
|
||||
|
||||
else if (typeStr == "String") {
|
||||
json["Settings"][index]["name"] = name;
|
||||
json["Settings"][index]["type"] = typeStr;
|
||||
json["Settings"][index]["value"] = "";
|
||||
json["Settings"][index]["range"]["min"] = "";
|
||||
json["Settings"][index]["range"]["max"] = "";
|
||||
|
||||
if (serializeJson(json, settings_string) == 0) {
|
||||
}
|
||||
|
||||
if (serializeJson(json, settingsFile) == 0) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close the file
|
||||
settingsFile.close();
|
||||
|
||||
this->json_settings_string = settings_string;
|
||||
|
||||
// Rebuild cache from the newly written settings.
|
||||
this->_buildCache();
|
||||
|
||||
this->printJsonSettings(settings_string);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,21 @@ class Settings {
|
||||
private:
|
||||
String json_settings_string;
|
||||
|
||||
// Flat cache populated once at begin() and kept in sync by saveSetting().
|
||||
// All loadSetting<T>() reads hit this struct — zero heap, zero JSON parse.
|
||||
struct SettingsCache {
|
||||
bool ForcePMKID = false;
|
||||
bool ForceProbe = false;
|
||||
bool SavePCAP = true;
|
||||
bool EnableLED = true;
|
||||
bool EPDeauth = false;
|
||||
bool ChanHop = false;
|
||||
String ClientSSID = "";
|
||||
String ClientPW = "";
|
||||
} _cache;
|
||||
|
||||
void _buildCache(); // parse json_settings_string -> _cache
|
||||
|
||||
public:
|
||||
bool begin();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user