ESP32-CAM: отправка фото на сервер по HTTP POST (PHP + Arduino IDE)
В этом руководстве вы узнаете, как отправлять HTTP POST запросы с платы ESP32-CAM с помощью Arduino IDE для передачи фотографий на сервер. Мы покажем, как отправить JPG-изображение на локальный сервер (LAMP-сервер на Raspberry Pi) или на облачный сервер (к которому можно получить доступ из любой точки мира). Для сохранения изображений на сервере мы используем PHP.
Обновлено 27 марта 2023
Чтобы собрать этот проект, вам необходимо выполнить следующие шаги. Следуйте инструкциям для LAMP-сервера или хостинга, в зависимости от того, хотите ли вы получать доступ к фотографиям локально или из любой точки мира.
Размещение вашего PHP-приложения
PHP-скрипты для сохранения и отображения фотографий на сервере
1. Размещение вашего PHP-приложения
Цель этого проекта — иметь локальный или облачный сервер для хранения и доступа к фотографиям с ESP32-CAM.
1. Локальный сервер на Raspberry Pi:
С LAMP-сервером на Raspberry Pi вы можете получить доступ к своим изображениям локально (как показано ниже).
Вы можете запустить LAMP-сервер (Linux, Apache, MySQL, PHP) на Raspberry Pi для доступа к данным в локальной сети. LAMP-сервер на Raspberry Pi: локальный Linux-сервер, который вы используете для доступа к изображениям локально.
Настройка локального LAMP-сервера на RPi >>
2. Облачный сервер (хостинг)
Вы также можете просматривать фотографии ESP32-CAM из любой точки мира, подключившись к собственному серверу и домену. Вот общая схема работы:
Bluehost (удобный с cPanel): бесплатное доменное имя при подписке на 3-летний план. Рекомендуется выбрать опцию неограниченного количества сайтов. Обратите внимание, что любой хостинг, поддерживающий PHP, подойдёт для этого урока.
При покупке хостинг-аккаунта вам также нужно будет приобрести доменное имя. Именно это делает проект интересным: вы сможете перейти по своему домену (http://example.com) и увидеть фотографии с ESP32-CAM.
2.1. Подготовка файла .php и папки uploads (LAMP-сервер на Raspberry Pi)
Этот раздел описывает подготовку файла .php и папки uploads для LAMP-сервера на Raspberry Pi. Если вы используете свой собственный сервер + доменное имя, переходите к следующему разделу.
Имея Raspberry Pi с Apache и PHP, в терминале Raspberry Pi перейдите в каталог /var/www/html/:
pi@raspberrypi:~ $ cd /var/www/html/
Создайте новую папку uploads:
pi@raspberrypi:/var/www/html $ mkdir uploads
pi@raspberrypi:/var/www/html $ ls
uploads
В данный момент /var/www/html принадлежит пользователю root, используйте следующие команды для смены владельца на пользователя pi и предоставления всех прав, чтобы позже можно было сохранять фотографии с помощью PHP-скрипта.
sudo chown -R pi:pi /var/www/html
chmod -R 777 /var/www/html/
Наконец, создайте новый файл upload.php:
pi@raspberrypi:/var/www/html $ nano upload.php
Этот PHP-скрипт отвечает за приём входящих изображений от ESP32-CAM, переименование изображений с временной меткой и сохранение их в папке uploads. Отредактируйте созданный файл (upload.php) и скопируйте следующий фрагмент:
<?php
// Rui Santos
// Complete project details at https://RandomNerdTutorials.com/esp32-cam-post-image-photo-server/
// Code Based on this example: w3schools.com/php/php_file_upload.asp
$target_dir = "uploads/";
$datum = mktime(date('H')+0, date('i'), date('s'), date('m'), date('d'), date('y'));
$target_file = $target_dir . date('Y.m.d_H:i:s_', $datum) . basename($_FILES["imageFile"]["name"]);
$uploadOk = 1;
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
// Check if image file is a actual image or fake image
if(isset($_POST["submit"])) {
$check = getimagesize($_FILES["imageFile"]["tmp_name"]);
if($check !== false) {
echo "File is an image - " . $check["mime"] . ".";
$uploadOk = 1;
}
else {
echo "File is not an image.";
$uploadOk = 0;
}
}
// Check if file already exists
if (file_exists($target_file)) {
echo "Sorry, file already exists.";
$uploadOk = 0;
}
// Check file size
if ($_FILES["imageFile"]["size"] > 500000) {
echo "Sorry, your file is too large.";
$uploadOk = 0;
}
// Allow certain file formats
if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
&& $imageFileType != "gif" ) {
echo "Sorry, only JPG, JPEG, PNG & GIF files are allowed.";
$uploadOk = 0;
}
// Check if $uploadOk is set to 0 by an error
if ($uploadOk == 0) {
echo "Sorry, your file was not uploaded.";
// if everything is ok, try to upload file
}
else {
if (move_uploaded_file($_FILES["imageFile"]["tmp_name"], $target_file)) {
echo "The file ". basename( $_FILES["imageFile"]["name"]). " has been uploaded.";
}
else {
echo "Sorry, there was an error uploading your file.";
}
}
?>
Сохраните файл и выйдите (Ctrl+X, Y и Enter):
2.2. Подготовка файлов .php и папки uploads (хостинг-сервис)
Если вы предпочитаете запускать сервер удалённо и получать доступ к фотографиям из любой точки мира, вам нужен хостинг-аккаунт. После регистрации на хостинге и настройки доменного имени, вы можете войти в cPanel или аналогичную панель управления. После этого откройте File Manager.
Откройте вкладку «Advanced» и выберите «File Manager»:
Затем выберите public_html. Нажмите кнопку «+ File», чтобы создать новый файл upload.php и новый файл gallery.php. Затем нажмите кнопку «+Folder», чтобы создать папку Uploads.
После создания трёх элементов отредактируйте файл upload.php:
Этот PHP-скрипт отвечает за приём входящих изображений от ESP32-CAM, переименование изображений с временной меткой и сохранение их в папке uploads. Отредактируйте созданный файл (upload.php) и скопируйте фрагмент ниже. Сохраните файл и выйдите.
<?php
// Rui Santos
// Complete project details at https://RandomNerdTutorials.com/esp32-cam-post-image-photo-server/
// Code Based on this example: w3schools.com/php/php_file_upload.asp
$target_dir = "uploads/";
$datum = mktime(date('H')+0, date('i'), date('s'), date('m'), date('d'), date('y'));
$target_file = $target_dir . date('Y.m.d_H:i:s_', $datum) . basename($_FILES["imageFile"]["name"]);
$uploadOk = 1;
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
// Check if image file is a actual image or fake image
if(isset($_POST["submit"])) {
$check = getimagesize($_FILES["imageFile"]["tmp_name"]);
if($check !== false) {
echo "File is an image - " . $check["mime"] . ".";
$uploadOk = 1;
}
else {
echo "File is not an image.";
$uploadOk = 0;
}
}
// Check if file already exists
if (file_exists($target_file)) {
echo "Sorry, file already exists.";
$uploadOk = 0;
}
// Check file size
if ($_FILES["imageFile"]["size"] > 500000) {
echo "Sorry, your file is too large.";
$uploadOk = 0;
}
// Allow certain file formats
if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
&& $imageFileType != "gif" ) {
echo "Sorry, only JPG, JPEG, PNG & GIF files are allowed.";
$uploadOk = 0;
}
// Check if $uploadOk is set to 0 by an error
if ($uploadOk == 0) {
echo "Sorry, your file was not uploaded.";
// if everything is ok, try to upload file
}
else {
if (move_uploaded_file($_FILES["imageFile"]["tmp_name"], $target_file)) {
echo "The file ". basename( $_FILES["imageFile"]["name"]). " has been uploaded.";
}
else {
echo "Sorry, there was an error uploading your file.";
}
}
?>
3. ESP32-CAM: отправка изображений/фотографий на сервер по HTTP POST
Теперь, когда ваш сервер готов (LAMP-сервер на Raspberry Pi или облачный сервер), пора подготовить ESP32-CAM с кодом для публикации нового изображения на сервер каждые 30 секунд. Прежде чем продолжить этот урок, убедитесь, что выполнены следующие предварительные условия.
Необходимые компоненты
Для выполнения этого урока вам понадобятся следующие компоненты:
ESP32-CAM с OV2640 — ознакомьтесь с лучшими платами ESP32-CAM
Локальный сервер:
Облачный сервер (альтернатива): Bluehost
Arduino IDE
Мы будем программировать ESP32-CAM с помощью Arduino IDE, поэтому убедитесь, что у вас установлено дополнение ESP32.
Проверка PHP URL
Попробуйте открыть локальный IP-адрес Raspberry Pi или ваше внешнее доменное имя example.com, добавив /upload.php — должно отобразиться:
Sorry, only JPG, JPEG, PNG & GIF files are allowed.Sorry, your file was not uploaded.
Если вы видите это сообщение, сохраните URL/доменное имя и путь — ваш сервер должен быть готов и вы можете продолжить.
Код ESP32-CAM
Если вы используете локальный сервер без TLS/SSL, или облачный сервер, который не поддерживает HTTPS, используйте код HTTP POST запроса.
Если вы используете облачный сервер, требующий HTTPS-запросы, используйте этот код: код HTTPS POST запроса.
ESP32-CAM HTTP POST запрос
Следующий скетч отправляет изображение на сервер с помощью HTTP POST. Скопируйте код ниже в Arduino IDE.
/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp32-cam-post-image-photo-server/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
#include <Arduino.h>
#include <WiFi.h>
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#include "esp_camera.h"
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
String serverName = "192.168.1.XXX"; // REPLACE WITH YOUR Raspberry Pi IP ADDRESS
//String serverName = "example.com"; // OR REPLACE WITH YOUR DOMAIN NAME
String serverPath = "/upload.php"; // The default serverPath should be upload.php
const int serverPort = 80;
WiFiClient client;
// CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
const int timerInterval = 30000; // time between each HTTP POST image
unsigned long previousMillis = 0; // last time image was sent
void setup() {
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
Serial.begin(115200);
WiFi.mode(WIFI_STA);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println();
Serial.print("ESP32-CAM IP Address: ");
Serial.println(WiFi.localIP());
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_sccb_sda = SIOD_GPIO_NUM;
config.pin_sccb_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;
// init with high specs to pre-allocate larger buffers
if(psramFound()){
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 10; //0-63 lower number means higher quality
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_CIF;
config.jpeg_quality = 12; //0-63 lower number means higher quality
config.fb_count = 1;
}
// camera init
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
delay(1000);
ESP.restart();
}
sendPhoto();
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= timerInterval) {
sendPhoto();
previousMillis = currentMillis;
}
}
String sendPhoto() {
String getAll;
String getBody;
camera_fb_t * fb = NULL;
fb = esp_camera_fb_get();
if(!fb) {
Serial.println("Camera capture failed");
delay(1000);
ESP.restart();
}
Serial.println("Connecting to server: " + serverName);
if (client.connect(serverName.c_str(), serverPort)) {
Serial.println("Connection successful!");
String head = "--RandomNerdTutorials\r\nContent-Disposition: form-data; name=\"imageFile\"; filename=\"esp32-cam.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";
String tail = "\r\n--RandomNerdTutorials--\r\n";
uint32_t imageLen = fb->len;
uint32_t extraLen = head.length() + tail.length();
uint32_t totalLen = imageLen + extraLen;
client.println("POST " + serverPath + " HTTP/1.1");
client.println("Host: " + serverName);
client.println("Content-Length: " + String(totalLen));
client.println("Content-Type: multipart/form-data; boundary=RandomNerdTutorials");
client.println();
client.print(head);
uint8_t *fbBuf = fb->buf;
size_t fbLen = fb->len;
for (size_t n=0; n<fbLen; n=n+1024) {
if (n+1024 < fbLen) {
client.write(fbBuf, 1024);
fbBuf += 1024;
}
else if (fbLen%1024>0) {
size_t remainder = fbLen%1024;
client.write(fbBuf, remainder);
}
}
client.print(tail);
esp_camera_fb_return(fb);
int timoutTimer = 10000;
long startTimer = millis();
boolean state = false;
while ((startTimer + timoutTimer) > millis()) {
Serial.print(".");
delay(100);
while (client.available()) {
char c = client.read();
if (c == '\n') {
if (getAll.length()==0) { state=true; }
getAll = "";
}
else if (c != '\r') { getAll += String(c); }
if (state==true) { getBody += String(c); }
startTimer = millis();
}
if (getBody.length()>0) { break; }
}
Serial.println();
client.stop();
Serial.println(getBody);
}
else {
getBody = "Connection to " + serverName + " failed.";
Serial.println(getBody);
}
return getBody;
}
ESP32-CAM HTTPS POST запрос
Следующий скетч отправляет изображение на сервер с помощью HTTPS POST. Скопируйте код ниже в Arduino IDE.
/*
Rui Santos
Complete project details at:
https://RandomNerdTutorials.com/esp32-cam-http-post-php-arduino/
https://RandomNerdTutorials.com/esp32-cam-post-image-photo-server/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#include "esp_camera.h"
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
String serverName = "example.com"; //REPLACE WITH YOUR DOMAIN NAME
String serverPath = "/upload.php"; // The default serverPath should be upload.php
const int serverPort = 443; //server port for HTTPS
WiFiClientSecure client;
// CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
const int timerInterval = 30000; // time between each HTTP POST image
unsigned long previousMillis = 0; // last time image was sent
void setup() {
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
Serial.begin(115200);
WiFi.mode(WIFI_STA);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println();
Serial.print("ESP32-CAM IP Address: ");
Serial.println(WiFi.localIP());
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_sccb_sda = SIOD_GPIO_NUM;
config.pin_sccb_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;
// init with high specs to pre-allocate larger buffers
if(psramFound()){
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 10; //0-63 lower number means higher quality
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_CIF;
config.jpeg_quality = 12; //0-63 lower number means higher quality
config.fb_count = 1;
}
// camera init
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
delay(1000);
ESP.restart();
}
sendPhoto();
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= timerInterval) {
sendPhoto();
previousMillis = currentMillis;
}
}
String sendPhoto() {
String getAll;
String getBody;
camera_fb_t * fb = NULL;
fb = esp_camera_fb_get();
if(!fb) {
Serial.println("Camera capture failed");
delay(1000);
ESP.restart();
}
Serial.println("Connecting to server: " + serverName);
client.setInsecure(); //skip certificate validation
if (client.connect(serverName.c_str(), serverPort)) {
Serial.println("Connection successful!");
String head = "--RandomNerdTutorials\r\nContent-Disposition: form-data; name=\"imageFile\"; filename=\"esp32-cam.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";
String tail = "\r\n--RandomNerdTutorials--\r\n";
uint32_t imageLen = fb->len;
uint32_t extraLen = head.length() + tail.length();
uint32_t totalLen = imageLen + extraLen;
client.println("POST " + serverPath + " HTTP/1.1");
client.println("Host: " + serverName);
client.println("Content-Length: " + String(totalLen));
client.println("Content-Type: multipart/form-data; boundary=RandomNerdTutorials");
client.println();
client.print(head);
uint8_t *fbBuf = fb->buf;
size_t fbLen = fb->len;
for (size_t n=0; n<fbLen; n=n+1024) {
if (n+1024 < fbLen) {
client.write(fbBuf, 1024);
fbBuf += 1024;
}
else if (fbLen%1024>0) {
size_t remainder = fbLen%1024;
client.write(fbBuf, remainder);
}
}
client.print(tail);
esp_camera_fb_return(fb);
int timoutTimer = 10000;
long startTimer = millis();
boolean state = false;
while ((startTimer + timoutTimer) > millis()) {
Serial.print(".");
delay(100);
while (client.available()) {
char c = client.read();
if (c == '\n') {
if (getAll.length()==0) { state=true; }
getAll = "";
}
else if (c != '\r') { getAll += String(c); }
if (state==true) { getBody += String(c); }
startTimer = millis();
}
if (getBody.length()>0) { break; }
}
Serial.println();
client.stop();
Serial.println(getBody);
}
else {
getBody = "Connection to " + serverName + " failed.";
Serial.println(getBody);
}
return getBody;
}
Подробнее об HTTPS-запросах с ESP32: ESP32 HTTPS Requests (Arduino IDE).
Ввод сетевых учётных данных, камеры и параметров сервера
Перед загрузкой кода вам необходимо ввести свои сетевые учётные данные в следующие переменные:
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Убедитесь, что вы выбрали правильную модель камеры. В данном случае мы используем модель AI-THINKER. Если вы используете другую модель камеры, вы можете прочитать это руководство по назначению пинов ESP32-CAM.
Добавьте IP-адрес вашего Raspberry Pi или используйте доменное имя сервера:
String serverName = "192.168.1.XXX"; // REPLACE WITH YOUR Raspberry Pi IP ADDRESS
//String serverName = "example.com"; // OR REPLACE WITH YOUR DOMAIN NAME
String serverPath = "/upload.php"; // The default serverPath should be upload.php
Загрузка кода в ESP32-CAM
Теперь вы можете загрузить код на плату ESP32-CAM. Подключите плату ESP32-CAM к компьютеру с помощью FTDI программатора.
Следуйте схеме подключения:
Многие FTDI программаторы имеют перемычку для выбора 3.3V или 5V. Убедитесь, что перемычка установлена в правильное положение для выбора 5V.
Важно: GPIO 0 должен быть подключён к GND, чтобы можно было загрузить код.
ESP32-CAM |
FTDI Programmer |
|---|---|
GND |
GND |
5V |
VCC (5V) |
U0R |
TX |
U0T |
RX |
GPIO 0 |
GND |
Чтобы загрузить код, выполните следующие шаги:
Перейдите в Tools > Board и выберите AI-Thinker ESP32-CAM.
Перейдите в Tools > Port и выберите COM-порт, к которому подключён ESP32.
Затем нажмите кнопку загрузки, чтобы загрузить код.
Когда вы увидите точки в окне отладки, как показано ниже, нажмите встроенную кнопку RST на ESP32-CAM.
Через несколько секунд код должен быть успешно загружен на вашу плату.
Если у вас возникли проблемы с загрузкой кода, прочитайте руководство по устранению неполадок ESP32-CAM.
Как работает код
Вот краткое объяснение того, как работает код:
Импорт всех библиотек;
Определение необходимых переменных;
Определение пинов камеры;
В
setup()устанавливается Wi-Fi соединение и инициализируется камера ESP32.loop()содержит таймер, который вызывает функциюsendPhoto()каждые 30 секунд. Вы можете изменить это время задержки в переменнойtimerInterval.
Функция sendPhoto() — это часть, которая фактически делает фото и отправляет его на ваш сервер. Вы можете использовать эту функцию в других своих проектах, которые требуют съёмки и публикации фото на сервер.
4. Тестирование и финальная демонстрация
После загрузки кода на плату откройте монитор порта Arduino IDE — вы должны увидеть подобное сообщение, выводимое каждые 30 секунд:
The file esp32-cam.jpg has been uploaded.
Если вы перейдёте по URL вашего локального сервера http://IP-Address/uploads или по URL облачного сервера http://example.com/uploads, вы увидите папку со всеми сохранёнными фотографиями.
Вы можете нажать на каждую ссылку, чтобы открыть новую страницу с полным изображением:
Заключение
Вот и всё! Теперь вы можете отправлять фотографии ESP32-CAM на любой сервер с помощью HTTP POST. Модифицируйте этот проект под свои нужды, например, делайте фото и отправляйте на сервер при обнаружении движения.
Другие уроки по ESP32, которые могут быть вам интересны: