#include "esp_camera.h" #include <WiFi.h> #include <HTTPClient.h> #include <FS.h> #include "SD_MMC.h" // Define your WiFi credentials const char* ssid = "MYSSID"; const char* password = "MYPASS"; // Google Drive upload parameters const char* gdrive_upload_url = "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable"; const char* parentFolderId = "MYFOLDERID"; String metadata = "{"parents":["" + String(parentFolderId) + ""]}"; uint8_t *videoBuffer = NULL; size_t bufferSize = 0; size_t maxBufferSize = 0; // Function to connect to WiFi void connectToWiFi() { Serial.println("Connecting to WiFi..."); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting..."); } Serial.println("Connected to WiFi"); } void captureAndWriteVideoToSD(uint16_t videoDurationInSeconds) { Serial.println("Starting video capture..."); File videoFile = SD_MMC.open("/video.mp4", FILE_WRITE); if (!videoFile) { Serial.println("Failed to open/create file for writing"); return; } uint32_t startTime = millis(); uint32_t endTime = startTime + (videoDurationInSeconds * 1000); while (millis() < endTime) { camera_fb_t *fb = esp_camera_fb_get(); if (fb) { // Write frame data to the file if (videoFile.write(fb->buf, fb->len) != fb->len) { Serial.println("Write error occurred"); esp_camera_fb_return(fb); break; } esp_camera_fb_return(fb); } else { Serial.println("Failed to capture frame"); break; } } // Close the file if (videoFile) { videoFile.close(); Serial.println("Video capture complete."); } else { Serial.println("Error: File not open."); } } void uploadVideoToDrive() { Serial.println("Uploading video to Google Drive..."); // Open the file File videoFile = SD_MMC.open("/video.mp4", FILE_READ); if (!videoFile) { Serial.println("Error opening video file!"); return; } const size_t chunkSize = 1024; // Define the chunk size uint8_t chunk[chunkSize]; // Declare the chunk buffer size_t totalPayloadSize = 0; // Initialize total payload size // Calculate total payload size while (videoFile.available()) { size_t bytesRead = videoFile.readBytes((char*)chunk, chunkSize); totalPayloadSize += bytesRead; } videoFile.seek(0); // Reset file pointer to the beginning // Make the initial POST request to get the upload session URL HTTPClient http; http.begin("https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable"); http.addHeader("Authorization", "Bearer " + gdrive_token); http.addHeader("Content-Type", "video/mp4"); http.addHeader("Content-Length", "0"); // Set initial Content-Length to 0 int httpResponseCode = http.POST(""); // Send the initial POST request Serial.println("Initial POST request response:"); Serial.println(http.getString()); // Print response body if (httpResponseCode != HTTP_CODE_OK) { Serial.print("Error initiating upload. HTTP response code: "); Serial.println(httpResponseCode); http.end(); videoFile.close(); return; } String location = http.header("Location"); // Get the upload session URL http.end(); // Close the connection Serial.print("Upload session URL: "); Serial.println(location); // Check if location is empty or null if (location.isEmpty()) { Serial.println("Error: Upload session URL not found."); videoFile.close(); return; } // Send the file contents in chunks with the correct range headers size_t totalBytesSent = 0; // Initialize totalBytesSent while (videoFile.available()) { size_t bytesRead = videoFile.readBytes((char*)chunk, chunkSize); http.begin(location); // Use the upload session URL http.addHeader("Authorization", "Bearer " + gdrive_token); http.addHeader("Content-Range", "bytes " + String(totalBytesSent) + "-" + String(totalBytesSent + bytesRead - 1) + "/" + String(totalPayloadSize)); httpResponseCode = http.sendRequest("PUT", chunk, bytesRead); if (httpResponseCode != HTTP_CODE_OK && httpResponseCode != HTTP_CODE_CREATED) { Serial.print("Error uploading chunk. HTTP response code: "); Serial.println(httpResponseCode); Serial.println(http.getString()); http.end(); videoFile.close(); return; } totalBytesSent += bytesRead; Serial.print("Uploaded "); Serial.print(totalBytesSent); Serial.print(" bytes out of "); Serial.println(totalPayloadSize); http.end(); delay(10); // Small delay between requests } Serial.println("Upload complete."); // Close the file videoFile.close(); } void setup() { Serial.begin(115200); // Initialize camera camera_config_t config; config.ledc_channel = LEDC_CHANNEL_0; config.ledc_timer = LEDC_TIMER_0; config.pin_d0 = 5; // Y2 config.pin_d1 = 18; // Y3 config.pin_d2 = 19; // Y4 config.pin_d3 = 21; // Y5 config.pin_d4 = 36; // Y6 config.pin_d5 = 39; // Y7 config.pin_d6 = 34; // Y8 config.pin_d7 = 35; // Y9 config.pin_xclk = 0; // XCLK_GPIO_NUM config.pin_pclk = 22; // PCLK_GPIO_NUM config.pin_vsync = 25; // VSYNC_GPIO_NUM config.pin_href = 23; // HREF_GPIO_NUM config.pin_sscb_sda = 26; // SIOD_GPIO_NUM config.pin_sscb_scl = 27; // SIOC_GPIO_NUM config.pin_pwdn = 32; // PWDN_GPIO_NUM config.pin_reset = -1; // RESET_GPIO_NUM, -1 if not used config.xclk_freq_hz = 20000000; config.pixel_format = PIXFORMAT_JPEG; // Init with high specs to pre-allocate larger buffers if (psramFound()) { config.frame_size = FRAMESIZE_UXGA; config.jpeg_quality = 10; config.fb_count = 2; } else { config.frame_size = FRAMESIZE_SVGA; config.jpeg_quality = 12; config.fb_count = 1; } // Initialize camera esp_err_t err = esp_camera_init(&config;); if (err != ESP_OK) { Serial.printf("Camera init failed with error 0x%x", err); return; } while (!SD_MMC.begin()) {} connectToWiFi(); captureAndWriteVideoToSD(10); uploadVideoToDrive(); } void loop() { // captureAndWriteVideoToSD(10); // // Check if video capture was successful // if (bufferSize > 0) { // uploadVideoToDrive(videoBuffer, bufferSize, gdrive_upload_url, gdrive_token); // // Free the memory allocated for videoBuffer // videoBuffer = NULL; // bufferSize = 0; // maxBufferSize = 0; // } delay(1000); }