Fix WiFi file transfer stability and improve upload performance

- Add WiFi connection health monitoring for STA mode
  - Detects disconnection and exits gracefully instead of locking up
  - Logs weak signal warnings (< -75 dBm) for debugging

- Implement time-based handleClient processing (50ms budget)
  - Replaces fixed 10-iteration loop with adaptive time-based approach
  - Adds yield() between calls to let WiFi stack receive packets
  - Improves throughput by processing more data when available

- Add 8KB upload write buffer
  - Batches small writes into larger SD card operations
  - Reduces SD write overhead by ~4-8x
  - Includes diagnostic counters for performance analysis

- Add watchdog reset during file scanning
  - Prevents timeout on large directories
This commit is contained in:
Claude
2026-01-12 20:05:10 +00:00
parent d4ae108d9b
commit 87a568c928
2 changed files with 112 additions and 33 deletions

View File

@@ -283,8 +283,30 @@ void CrossPointWebServerActivity::loop() {
dnsServer->processNextRequest();
}
// Handle web server requests - call handleClient multiple times per loop
// to improve responsiveness and upload throughput
// STA mode: Monitor WiFi connection health
if (!isApMode && webServer && webServer->isRunning()) {
static unsigned long lastWifiCheck = 0;
if (millis() - lastWifiCheck > 2000) { // Check every 2 seconds
lastWifiCheck = millis();
const wl_status_t wifiStatus = WiFi.status();
if (wifiStatus != WL_CONNECTED) {
Serial.printf("[%lu] [WEBACT] WiFi disconnected! Status: %d\n", millis(), wifiStatus);
// Show error and exit gracefully
state = WebServerActivityState::SHUTTING_DOWN;
updateRequired = true;
return;
}
// Log weak signal warnings
const int rssi = WiFi.RSSI();
if (rssi < -75) {
Serial.printf("[%lu] [WEBACT] Warning: Weak WiFi signal: %d dBm\n", millis(), rssi);
}
}
}
// Handle web server requests using time-based processing
// Process requests for up to TIME_BUDGET_MS to maximize throughput
// while still allowing other loop activities to run
if (webServer && webServer->isRunning()) {
const unsigned long timeSinceLastHandleClient = millis() - lastHandleClientTime;
@@ -294,12 +316,20 @@ void CrossPointWebServerActivity::loop() {
timeSinceLastHandleClient);
}
// Call handleClient multiple times to process pending requests faster
// This is critical for upload performance - HTTP file uploads send data
// in chunks and each handleClient() call processes incoming data
constexpr int HANDLE_CLIENT_ITERATIONS = 10;
for (int i = 0; i < HANDLE_CLIENT_ITERATIONS && webServer->isRunning(); i++) {
// Time-based processing: handle requests for up to 50ms per loop iteration
// This is more efficient than a fixed iteration count because:
// 1. Processes more data when available (during uploads)
// 2. Returns quickly when idle (no wasted spinning)
// 3. yield() between calls lets WiFi stack receive more data
constexpr unsigned long TIME_BUDGET_MS = 50;
const unsigned long handleStart = millis();
while (webServer->isRunning() && (millis() - handleStart) < TIME_BUDGET_MS) {
webServer->handleClient();
// Yield between calls to let WiFi stack process incoming packets
// This is critical for throughput - without it, TCP flow control
// throttles the sender because our receive buffer fills up
yield();
}
lastHandleClientTime = millis();
}