Merge pull request #1329 from justcallmekoko/develop

Develop
This commit is contained in:
Just Call Me Koko
2026-06-22 13:47:32 -04:00
committed by GitHub
8 changed files with 562 additions and 190 deletions
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -218,7 +218,7 @@ class MenuFunctions
void drawGraph(int16_t *values);
void drawGraphSmall(uint8_t *values);
void renderGraphUI(uint8_t scan_mode = 0);
void addNodes(Menu* menu, const char* name, uint8_t color, Menu* child, int place, std::function<void()> callable, bool selected = false);
void addNodes(Menu* menu, const char* name, uint8_t color, int place, std::function<void()> callable, bool selected = false);
void battery(bool initial = false);
void battery2(bool initial = false);
const char* callSetting(const char* key);
+276
View File
@@ -9867,6 +9867,282 @@ uint16_t WiFiScan::rssiToColor(int8_t rssi) {
return TFT_RED;
}
// Upload one log file to WDG Wars.
// Mirrors backendUpload() but uses X-API-Key auth and wdgwars.pl endpoint.
/*bool WiFiScan::wdgwarsUpload(String filePath) {
//display.clearScreen();
//display.drawCenteredText("WDG Upload...", true);
delay(100);
if (!SD.exists(filePath)) {
//display.drawCenteredText(filePath + " not found", true);
Serial.println("[WDG] File not found: " + filePath);
return false;
}
String apiKey = settings_obj.loadSetting<String>(WDG_KEY_NAME);
if (apiKey.isEmpty()) {
//display.clearScreen();
//display.drawCenteredText("No WDG API key", true);
Serial.println("[WDG] No WDG Wars API key configured");
return false;
}
File fileToUpload = SD.open(filePath);
if (!fileToUpload) {
//display.clearScreen();
//display.drawCenteredText("Could not open file", true);
Serial.println("[WDG] Could not open: " + filePath);
return false;
}
// Build multipart body
String boundary = "----ESP32BOUNDARY";
String part1 = "--" + boundary + "\r\n";
part1 += "Content-Disposition: form-data; name=\"file\"; filename=\"" +
filePath + "\"\r\n";
part1 += "Content-Type: application/octet-stream\r\n\r\n";
String part2 = "\r\n--" + boundary + "--\r\n";
int totalLength = part1.length() + fileToUpload.size() + part2.length();
Serial.println("[WDG] File size: " + String(fileToUpload.size()));
Serial.println("[WDG] Total length: " + String(totalLength));
client->setInsecure();
if (!client->connect("wdgwars.pl", 443)) {
fileToUpload.close();
client->stop();
//display.clearScreen();
//display.drawCenteredText("WDG connect fail", true);
Serial.println("[WDG] Failed to connect to wdgwars.pl");
return false;
}
// HTTP request
client->println("POST /api/v2/upload-csv HTTP/1.1");
client->println("Host: wdgwars.pl");
client->println("User-Agent: ESP32Uploader/1.0");
client->println("Accept: application/json");
client->println("X-API-Key: " + apiKey);
client->println("Content-Type: multipart/form-data; boundary=" + boundary);
client->print("Content-Length: ");
client->println(totalLength);
client->println();
// Send body
client->print(part1);
const size_t CHUNK = 4096;
uint8_t buf[CHUNK];
size_t totalSent = 0;
uint8_t pct = 0;
String pctStr;
while (fileToUpload.available()) {
size_t n = fileToUpload.read(buf, CHUNK);
totalSent += n;
client->write(buf, n);
pct = (totalSent * 100) / fileToUpload.size();
//display.tft->drawRect(0, (TFT_HEIGHT / 3) * 2, TFT_WIDTH, TFT_HEIGHT - (TFT_HEIGHT / 3) * 2, ST77XX_BLACK);
//display.tft->setCursor(0, (TFT_HEIGHT / 3) * 2);
pctStr = String(pct) + "%";
//display.drawCenteredText(pctStr, false);
}
client->print(part2);
fileToUpload.close();
Serial.println("[WDG] Bytes sent: " + String(totalSent));
// Read response
String response;
unsigned long t = millis();
while (millis() - t < 5000) {
while (client->available()) {
char c = client->read();
response += c;
}
if (!client->connected() && !client->available())
break;
}
client->stop();
// Capture first 200 chars of response for log viewer
String respTrunc = response.length() > 200 ? response.substring(0, 200) : response;
Serial.println("[WDG] Response: " + respTrunc);
// WDG Wars returns 200 on success
bool ok = response.indexOf("202 Accepted") >= 0 ||
response.indexOf("\"ok\":true") >= 0;
//display.clearScreen();
//display.drawCenteredText(ok ? "WDG OK" : "WDG Failed", true);
delay(1000);
return ok;
}*/
// Upload one log file to Wigle
/*bool WiFiScan::wigleUpload(String filePath) {
//server.begin();
//display.clearScreen();
//display.drawCenteredText("Wigle Upload...", true);
delay(100);
if (!SD.exists(filePath)) {
//display.clearScreen();
//display.drawCenteredText(filePath + " not found", true);
Serial.println("File does not exist: " + filePath);
return false;
}
File fileToUpload = SD.open(filePath);
if (!fileToUpload) {
//display.clearScreen();
//display.drawCenteredText("Could not open file", true);
Serial.println("Could not open file: " + filePath);
return false;
}
// Load credentials
String username = settings_obj.loadSetting<String>("wu");
String token = settings_obj.loadSetting<String>("wt");
if (username.isEmpty() || token.isEmpty()) {
fileToUpload.close();
//display.clearScreen();
//display.drawCenteredText("No wigle creds", true);
Serial.println("Missing wigle credentials");
return false;
}
Serial.println("Username: " + username);
Serial.println("Token: " + token);
String boundary = "----ESP32BOUNDARY";
String contentType = "multipart/form-data; boundary=" + boundary;
// Build parts
String part1 = "--" + boundary + "\r\n";
part1 += "Content-Disposition: form-data; name=\"file\"; filename=\"" + filePath + "\"\r\n";
part1 += "Content-Type: application/octet-stream\r\n\r\n";
String part2 = "\r\n--" + boundary + "\r\n";
part2 += "Content-Disposition: form-data; name=\"donate\"\r\n\r\non\r\n";
String part3 = "--" + boundary + "--\r\n";
int totalLength = part1.length() + fileToUpload.size() + part2.length() + part3.length();
Serial.println("part1.length(): " + String(part1.length()));
Serial.println("fileToUpload.size(): " + String(fileToUpload.size()));
Serial.println("part2.length(): " + String(part2.length()));
Serial.println("part3.length(): " + String(part3.length()));
Serial.println("Total Content-Length: " + String(totalLength));
Serial.print("File size: ");
Serial.println(fileToUpload.size());
// Connect manually via WiFiClientSecure
//WiFiClientSecure *client = new WiFiClientSecure();
//client.stop();
client->setInsecure();
if (!client->connect("api.wigle.net", 443)) {
fileToUpload.close();
//delete client;
client->stop();
//display.clearScreen();
//display.drawCenteredText("Could not connect", true);
Serial.println("Failed to connected to api.wigle.net");
return false;
}
Serial.println("Connected");
// Compose headers
String auth = base64Encode(username + ":" + token);
Serial.println("Finished encoding");
client->println("POST /api/v2/file/upload HTTP/1.1");
client->println("Host: api.wigle.net");
client->println("User-Agent: ESP32Uploader/1.0");
client->println("Accept: application/json");
client->println("Authorization: Basic " + auth);
client->println("Content-Type: " + contentType);
client->print("Content-Length: ");
client->println(totalLength);
client->println();
delay(100);
Serial.println("Finished sending header");
// Send body
client->print(part1);
const size_t BUFFER_SIZE = 4096; // 1KB at a time
uint8_t buffer[BUFFER_SIZE];
Serial.println("Finished sending part1");
uint8_t percent_sent = 0;
String display_percent = "";
size_t totalBytesSent = 0;
while (fileToUpload.available()) {
size_t bytesRead = fileToUpload.read(buffer, BUFFER_SIZE);
totalBytesSent += bytesRead;
Serial.print("Writing ");
Serial.print(totalBytesSent);
Serial.println(" bytes...");
percent_sent = (totalBytesSent * 100) / fileToUpload.size();
//display.tft->drawRect(0, (TFT_HEIGHT / 3) * 2, TFT_WIDTH, TFT_HEIGHT, ST77XX_BLACK);
//display.tft->setCursor(0, (TFT_HEIGHT / 3) * 2);
display_percent = (String)percent_sent + "%";
//display.drawCenteredText(display_percent, false);
client->write(buffer, bytesRead);
}
Serial.println("Uploaded file bytes: " + String(totalBytesSent));
client->print(part2);
client->print(part3);
Serial.println("Finished sending part2 and part3");
fileToUpload.close();
// Read response
String response;
unsigned long timeout = millis();
while (millis() - timeout < 5000) {
while (client->available()) {
char c = client->read();
response += c;
}
}
if (millis() - timeout > 5000)
Serial.println("Timeout reached");
if (!client->connected())
Serial.println("Client disconnected");
client->stop();
String respTrunc = response.length() > 200 ? response.substring(0, 200) : response;
Serial.println("[WIGLE] Response: " + respTrunc);
bool ok = response.indexOf("200 OK") >= 0;
//display.clearScreen();
//display.drawCenteredText(ok ? "WIGLE OK" : "WIGLE Failed", true);
return ok;
}*/
// Function for updating scan status
void WiFiScan::main(uint32_t currentTime)
{
+8
View File
@@ -68,6 +68,9 @@
#include "LedInterface.h"
#endif
//#include <WiFiClientSecure.h>
//#include "mbedtls/sha256.h"
#define bad_list_length 3
#define OTA_UPDATE 100
@@ -300,6 +303,8 @@ class WiFiScan
// Settings
uint mac_history_cursor = 0;
uint8_t channel_hop_delay = 1;
//WiFiClientSecure *client = new WiFiClientSecure();
int x_pos; //position along the graph x axis
float y_pos_x; //current graph y axis position of X value
@@ -585,6 +590,9 @@ class WiFiScan
NimBLEAdvertisementData GetUniversalAdvertisementData(EBLEPayloadType type);
#endif
bool wigleUpload(String filePath);
bool wdgwarsUpload(String filePath);
void throwThatShitInACircle();
void displayTargetFilter();
void displayTransmitRate();
+5
View File
@@ -2711,6 +2711,11 @@
#undef HAS_MAX1704X
#undef HAS_AXP192
#elif defined(HAS_IP5306)
#undef HAS_AXP2101
#undef HAS_MAX1704X
#undef HAS_AXP192
#elif defined(HAS_AXP192)
#undef HAS_AXP2101
#undef HAS_IP5306
+2
View File
@@ -17,6 +17,8 @@
extern Display display_obj;
#endif
#define WDG_KEY_NAME "wdg_key" // WDG Wars API key (String)
class Settings {
private:
+9
View File
@@ -9,6 +9,7 @@
#include "configs.h"
#include "esp_heap_caps.h"
#include "mbedtls/base64.h"
struct mac_addr {
unsigned char bytes[6];
@@ -256,4 +257,12 @@ inline uint16_t getNextPort(uint16_t port) {
return port + 1;
}
String base64Encode(const String& input) {
size_t outputLen;
unsigned char output[256];
mbedtls_base64_encode(output, sizeof(output), &outputLen,
(const unsigned char*)input.c_str(), input.length());
return String((char*)output).substring(0, outputLen);
}
#endif
+73
View File
@@ -0,0 +1,73 @@
$ErrorActionPreference = "Stop"
$repoRoot = Split-Path -Parent $PSScriptRoot
$configsPath = Join-Path $repoRoot "esp32_marauder/configs.h"
$configs = Get-Content -LiteralPath $configsPath -Raw
function Assert-Match {
param(
[string]$Text,
[string]$Pattern,
[string]$Message
)
if ($Text -notmatch $Pattern) {
throw $Message
}
}
function Get-MatchOrFail {
param(
[string]$Text,
[string]$Pattern,
[string]$Message
)
$match = [regex]::Match($Text, $Pattern, [System.Text.RegularExpressions.RegexOptions]::Singleline)
if (-not $match.Success) {
throw $Message
}
return $match
}
Assert-Match `
-Text $configs `
-Pattern "(?s)#if defined\(MARAUDER_V6\) \|\| defined\(MARAUDER_V6_1\).*?#define HAS_BATTERY.*?#define HAS_IP5306" `
-Message "MARAUDER_V6/MARAUDER_V6_1 must keep IP5306 battery support enabled."
$cleanupMatch = Get-MatchOrFail `
-Text $configs `
-Pattern "(?s)// If we know what we have, we can delete what we're not using(?<cleanup>.*?)#endif\s+// HAS_BATTERY" `
-Message "Could not find battery driver cleanup section."
$cleanup = $cleanupMatch.Groups["cleanup"].Value
$ip5306Match = Get-MatchOrFail `
-Text $cleanup `
-Pattern "(?s)#elif defined\(HAS_IP5306\)(?<ip5306Branch>.*?)(?=\r?\n\s*#elif|\r?\n\s*#else|\r?\n\s*#endif)" `
-Message "HAS_IP5306 must have an explicit cleanup branch before the generic fallback."
$ip5306Branch = $ip5306Match.Groups["ip5306Branch"].Value
Assert-Match `
-Text $ip5306Branch `
-Pattern "#undef HAS_AXP2101" `
-Message "HAS_IP5306 cleanup must disable HAS_AXP2101."
Assert-Match `
-Text $ip5306Branch `
-Pattern "#undef HAS_MAX1704X" `
-Message "HAS_IP5306 cleanup must disable HAS_MAX1704X."
Assert-Match `
-Text $ip5306Branch `
-Pattern "#undef HAS_AXP192" `
-Message "HAS_IP5306 cleanup must disable HAS_AXP192."
if ($ip5306Branch -match "#undef HAS_IP5306") {
throw "HAS_IP5306 cleanup must preserve HAS_IP5306 for v6/v6.1 battery support."
}
Write-Host "Battery driver macro checks passed."