#include #include #include #include // Camera pin definition for XIAO ESP32-S3 #define PWDN_GPIO_NUM -1 #define RESET_GPIO_NUM -1 #define XCLK_GPIO_NUM 10 #define SIOD_GPIO_NUM 40 #define SIOC_GPIO_NUM 39 #define Y9_GPIO_NUM 48 #define Y8_GPIO_NUM 11 #define Y7_GPIO_NUM 12 #define Y6_GPIO_NUM 14 #define Y5_GPIO_NUM 16 #define Y4_GPIO_NUM 18 #define Y3_GPIO_NUM 17 #define Y2_GPIO_NUM 15 #define VSYNC_GPIO_NUM 38 #define HREF_GPIO_NUM 47 #define PCLK_GPIO_NUM 13 // Wi-Fi credentials const char* ssid = "Hugger Mugger"; const char* password = "31C0tt0n@d3"; // Server details const char* serverName = "www.circuitdigest.cloud"; const int serverPort = 443; const char* serverPath = "/readqrcode"; const char* apiKey = "XSgFPHVldYVY"; WiFiClientSecure client; WebServer server(80); // HTTP server String serialBuffer = ""; // Buffer for serial commands String logBuffer = ""; // Buffer for serial log messages bool capturing = false; // Flag to prevent overlapping captures void initCamera(); int sendPhoto(); void resetCameraFeed(); void updateLog(const String& message); void processSerialCommand(String command); void startCameraServer(); void handleRoot(); void setup() { Serial.begin(115200); // Connect to Wi-Fi WiFi.begin(ssid, password); Serial.print("Connecting to Wi-Fi"); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("\nConnected to Wi-Fi"); updateLog("Connected to Wi-Fi\nIP Address: " + WiFi.localIP().toString()); // Initialize camera initCamera(); // Start the web server startCameraServer(); updateLog("Type 'CAPTURE' to take a photo or use the web app button."); } void loop() { // Handle Serial input while (Serial.available()) { char c = Serial.read(); if (c == '\n') { processSerialCommand(serialBuffer); serialBuffer = ""; } else { serialBuffer += c; } } // Handle HTTP requests server.handleClient(); } void initCamera() { camera_config_t config; config.ledc_channel = LEDC_CHANNEL_0; config.ledc_timer = LEDC_TIMER_0; config.pin_d0 = Y2_GPIO_NUM; config.pin_d1 = Y3_GPIO_NUM; config.pin_d2 = Y4_GPIO_NUM; config.pin_d3 = Y5_GPIO_NUM; config.pin_d4 = Y6_GPIO_NUM; config.pin_d5 = Y7_GPIO_NUM; config.pin_d6 = Y8_GPIO_NUM; config.pin_d7 = Y9_GPIO_NUM; config.pin_xclk = XCLK_GPIO_NUM; config.pin_pclk = PCLK_GPIO_NUM; config.pin_vsync = VSYNC_GPIO_NUM; config.pin_href = HREF_GPIO_NUM; config.pin_sscb_sda = SIOD_GPIO_NUM; config.pin_sscb_scl = SIOC_GPIO_NUM; config.pin_pwdn = PWDN_GPIO_NUM; config.pin_reset = RESET_GPIO_NUM; config.xclk_freq_hz = 20000000; config.pixel_format = PIXFORMAT_JPEG; config.frame_size = FRAMESIZE_QVGA; config.jpeg_quality = 10; config.fb_count = 1; if (esp_camera_init(&config) != ESP_OK) { updateLog("Camera initialization failed"); while (true); } } void processSerialCommand(String command) { command.trim(); if (command.equalsIgnoreCase("CAPTURE")) { if (!capturing) { capturing = true; updateLog("Capturing photo..."); int status = sendPhoto(); if (status == -1) { updateLog("Photo capture failed."); } else if (status == -2) { updateLog("Server connection failed."); } else { updateLog("Photo sent successfully."); } capturing = false; } else { updateLog("Capture already in progress..."); } } else { updateLog("Unknown command: " + command); } } int sendPhoto() { camera_fb_t* fb = esp_camera_fb_get(); if (!fb) { updateLog("Camera capture failed"); return -1; } client.setInsecure(); if (client.connect(serverName, serverPort)) { String head = "--CircuitDigest\r\nContent-Disposition: form-data; name=\"imageFile\"; filename=\"image.jpeg\"\r\nContent-Type: image/jpeg\r\n\r\n"; String tail = "\r\n--CircuitDigest--\r\n"; uint32_t totalLen = fb->len + head.length() + tail.length(); client.println("POST " + String(serverPath) + " HTTP/1.1"); client.println("Host: " + String(serverName)); client.println("Content-Type: multipart/form-data; boundary=CircuitDigest"); client.println("Content-Length: " + String(totalLen)); client.println("Authorization: " + String(apiKey)); client.println(); client.print(head); uint8_t* fbBuf = fb->buf; size_t fbLen = fb->len; for (size_t n = 0; n < fbLen; n += 1024) { if (n + 1024 < fbLen) { client.write(fbBuf, 1024); fbBuf += 1024; } else { size_t remainder = fbLen % 1024; client.write(fbBuf, remainder); } } client.print(tail); esp_camera_fb_return(fb); String response; long startTime = millis(); while (client.connected() && millis() - startTime < 10000) { if (client.available()) { response += client.readString(); } } updateLog("Server Response:"); updateLog(response); return 0; } else { updateLog("Connection to server failed"); return -2; } } void updateLog(const String& message) { Serial.println(message); logBuffer += message + "\n"; if (logBuffer.length() > 1024) { logBuffer = logBuffer.substring(logBuffer.length() - 1024); } } void startCameraServer() { server.on("/", HTTP_GET, []() { String html = R"rawliteral(

ESP32 Camera


            
        
        
        )rawliteral";
        server.send(200, "text/html", html);
    });

    server.on("/stream", HTTP_GET, handleRoot);

    server.on("/capture", HTTP_GET, []() {
        processSerialCommand("CAPTURE");
        server.send(200, "text/plain", "Capture command sent.");
    });

    server.on("/serial", HTTP_GET, []() {
        server.send(200, "text/plain", logBuffer);
    });

    server.begin();
}

void handleRoot() {
    WiFiClient client = server.client();

    String response = "HTTP/1.1 200 OK\r\n";
    response += "Content-Type: multipart/x-mixed-replace; boundary=frame\r\n\r\n";
    client.print(response);

    while (true) {
        camera_fb_t* fb = esp_camera_fb_get();
        if (!fb) {
            updateLog("Camera capture failed");
            return;
        }

        client.printf("--frame\r\nContent-Type: image/jpeg\r\nContent-Length: %d\r\n\r\n", fb->len);
        client.write(fb->buf, fb->len);
        client.println("\r\n");

        esp_camera_fb_return(fb);

        if (!client.connected()) {
            break;
        }

        delay(100);
    }
}