Загрузка данных


if (now - lastServoTime >= 100) {
    if (panDir != 0 || tiltDir != 0) {
      panAngle = constrain(panAngle + panDir, 0, 180);
      tiltAngle = constrain(tiltAngle + tiltDir, 0, 180);
      panServo.write(panAngle);
      tiltServo.write(tiltAngle);
    }
    lastServoTime = now;
  }

  if (streamServer.hasClient()) {
    if (streamClient) streamClient.stop();
    streamClient = streamServer.available();
    streamClient.print("HTTP/1.1 200 OK\r\nContent-Type: multipart/x-mixed-replace; boundary=frame\r\n\r\n");
  }

  if (isStreaming && streamClient.connected()) {
    if (now - lastFrameTime >= (1000 / STREAM_FPS)) {
      camera_fb_t *fb = esp_camera_fb_get();
      if (fb) {
        streamClient.printf("--frame\r\nContent-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n", fb->len);
        streamClient.write(fb->buf, fb->len);
        streamClient.print("\r\n");
        esp_camera_fb_return(fb);
      }
      lastFrameTime = now;
    }
  }
}

server.on("/last_photo", HTTP_GET, []() {
    // 1. Очистка старого кадра из очереди
    camera_fb_t *fb_old = esp_camera_fb_get();
    if (fb_old) esp_camera_fb_return(fb_old);

    // 2. Захват актуального кадра
    camera_fb_t *fb = esp_camera_fb_get();
    if (!fb) {
      Serial.println("[ERROR] Failed to capture photo for web update");
      server.send(500);
      return;
    }

    // --- ВОТ ЭТУ СТРОКУ МЫ ДОБАВЛЯЕМ ---
    Serial.printf("[LOG] Photo sent to browser. Size: %u bytes | Time: %lu ms\n", fb->len, millis());
    // ----------------------------------

    server.sendHeader("Content-Type", "image/jpeg");
    server.sendContent((const char *)fb->buf, fb->len);
    
    esp_camera_fb_return(fb);
  });