# ESP32 MP3 Player - Web Request & WiFiManager Memory Optimizations ## High-Impact Web Request Optimizations ### 1. **ESPAsyncWifiManager Configuration Optimization** (HIGH IMPACT: 10-20KB) The ESPAsyncWifiManager can be configured to use less memory: ```cpp // In setup(), before wifiManager.autoConnect(): AsyncWiFiManager wifiManager(&server, &dns); // Reduce timeout to free memory faster wifiManager.setTimeout(60); // Reduced from 180 to 60 seconds // Disable debug output to save memory wifiManager.setDebugOutput(false); // Set custom parameters to reduce memory usage wifiManager.setConfigPortalBlocking(false); // Non-blocking mode saves memory wifiManager.setConnectTimeout(20); // Faster connection timeout wifiManager.setConfigPortalTimeout(60); // Shorter portal timeout ``` ### 2. **Web Server Request Handler Optimization** (MEDIUM IMPACT: 5-10KB) Current issue: Each request handler creates temporary objects and strings. **Optimization A: Use String References Instead of Copies** ```cpp // Replace current parameter handling with more efficient version: void id_song_action(AsyncWebServerRequest *request) { const AsyncWebParameter* p = request->getParam("id"); if (p != nullptr) { playSongById(p->value().toInt()); // Direct conversion, no string copy } lastInteraction = millis(); request->send_P(200, "text/plain", "ok"); // Use PROGMEM string } ``` **Optimization B: Reduce JSON Buffer Allocations** ```cpp String getState() { // Use static buffer to avoid repeated allocations static DynamicJsonDocument jsonState(384); // Further reduced from 512 jsonState.clear(); // Clear previous data jsonState[F("playing")] = audio.isRunning(); // Use F() macro if (currentNode != nullptr) jsonState[F("title")] = *currentNode->getCurrentPlaying(); else jsonState[F("title")] = F("Angehalten"); // Store in flash jsonState[F("time")] = audio.getAudioCurrentTime(); jsonState[F("volume")] = audio.getVolume(); jsonState[F("length")] = audio.getAudioFileDuration(); jsonState[F("voltage")] = lastVoltage; jsonState[F("uid")] = lastUid; jsonState[F("heap")] = free_heap; String output; output.reserve(256); // Pre-allocate string buffer serializeJson(jsonState, output); return output; } ``` ### 3. **File Upload Handler Memory Optimization** (HIGH IMPACT: 15-30KB) Current issue: Large temporary buffers and inefficient string operations. ```cpp void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) { static String logBuffer; // Static to avoid repeated allocations if (!index) { // Use const references to avoid string copies const String& lowerFilename = filename; // Pre-allocate log buffer logBuffer.reserve(128); logBuffer = F("Upload Start: "); logBuffer += filename; // More efficient space check uint32_t freeSpace = (SD.cardSize() - SD.usedBytes()) >> 20; // Bit shift instead of division if (freeSpace < 10) { request->send(507, F("text/plain"), F("Insufficient storage space")); return; } Serial.println(logBuffer); logBuffer.clear(); // Free memory immediately // ... rest of upload logic } // Reduce logging frequency to save memory if (len && (index % 204800 == 0)) { // Log every 200KB instead of 100KB logBuffer = F("Upload: "); logBuffer += humanReadableSize(index + len); Serial.println(logBuffer); logBuffer.clear(); } } ``` ### 4. **HTML Template Processing Optimization** (MEDIUM IMPACT: 3-5KB) ```cpp String processor(const String &var) { if (var == F("DIRECTORY")) // Use F() macro { return rootNode.getDirectoryStructureHTML(); } return String(); // Return empty string instead of creating new String } ``` ### 5. **Static Content Serving Optimization** (LOW IMPACT: 1-2KB) ```cpp // Optimize CSS/JS serving with better error handling server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request) { activateSD(); const char* cssPath = "/system/style.css"; if (SD.exists(cssPath)) { request->send(SD, cssPath, F("text/css")); } else { // Serve minimal fallback without creating large strings request->send_P(200, "text/css", "body{font-family:Arial;text-align:center;}"); } deactivateSD(); }); ``` ## ESPAsyncWifiManager Specific Optimizations ### 6. **WiFiManager Memory Pool Configuration** (HIGH IMPACT: 15-25KB) ```cpp // Add these configurations in setup(): void setup() { // ... existing code ... AsyncWiFiManager wifiManager(&server, &dns); // Memory optimizations for WiFiManager wifiManager.setDebugOutput(false); // Disable debug strings wifiManager.setMinimumSignalQuality(20); // Reduce AP scan results wifiManager.setRemoveDuplicateAPs(true); // Remove duplicate APs from memory wifiManager.setConfigPortalBlocking(false); // Non-blocking saves memory wifiManager.setScanDisposeDelay(5000); // Dispose scan results faster // Reduce timeouts to free memory faster wifiManager.setTimeout(60); // Reduced from 180 wifiManager.setConnectTimeout(15); // Faster connection attempts wifiManager.setConfigPortalTimeout(60); // Shorter portal timeout // Custom CSS/HTML to reduce memory usage (optional) wifiManager.setCustomHeadElement(F("")); if (wifiManager.autoConnect("HannaBox")) { // ... existing server setup ... } } ``` ## Additional Compiler & Build Optimizations ### 7. **Enhanced Build Flags** (MEDIUM IMPACT: 5-10KB) Add to `platformio.ini`: ```ini build_flags = -Os ; Optimize for size -DCORE_DEBUG_LEVEL=0 ; Disable all debug output -DARDUINO_LOOP_STACK_SIZE=3072 ; Further reduce from 4096 -DWIFI_TASK_STACK_SIZE=3072 ; Reduce WiFi task stack -DARDUINO_EVENT_TASK_STACK_SIZE=2048 ; Reduce event task stack -DTCPIP_TASK_STACK_SIZE=2048 ; Reduce TCP/IP stack -DESP_TASK_WDT_TIMEOUT_S=10 ; Reduce watchdog timeout -DCONFIG_ASYNC_TCP_MAX_ACK_TIME=3000 ; Reduce TCP ACK timeout -DCONFIG_ASYNC_TCP_QUEUE_SIZE=32 ; Reduce TCP queue size ``` ## Implementation Priority 1. **IMMEDIATE (High Impact)**: - ESPAsyncWifiManager configuration optimization - File upload handler memory optimization - Enhanced build flags 2. **SHORT TERM (Medium Impact)**: - JSON buffer optimization with F() macros - Web request handler optimization - Static content serving optimization 3. **LONG TERM (Maintenance)**: - Monitor memory usage patterns - Consider implementing request queuing if needed - Profile actual memory usage during web operations ## Expected Total Memory Savings | Optimization Category | Memory Saved | |----------------------|--------------| | ESPAsyncWifiManager Config | 15-25KB | | File Upload Handler | 15-30KB | | JSON & String Optimizations | 5-10KB | | Build Flag Optimizations | 5-10KB | | **Total Potential Savings** | **40-75KB** | ## Testing & Validation After implementing these optimizations: 1. Monitor free heap via web interface during: - WiFi connection process - File uploads - Multiple concurrent web requests - JSON state requests 2. Test stability under load: - Multiple rapid web requests - Large file uploads - WiFi reconnection scenarios 3. Verify functionality: - All web endpoints work correctly - File uploads complete successfully - WiFi manager portal functions properly