# 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("<style>body{font-size:14px;}</style>"));
    
    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
