Всем привет! Сегодня мы разберем как сделать систему видеонаблюдения на базе esp32-cam и Telegram.
Используя популярный мессенджер Telegram, можно не задумываться о наличии "белого" Ip адреса, для выхода в сеть. Для реализации проекта посмотрим на схему:
Когда мы отправляем боту команду, он через сервера telegram-а пересылает её на esp, которая с периодичностью раз в секунду опрашивает сервер.
После получения запроса на отправку фото, esp делает снимок, загружает его на сайт telegram-а, а уже сам telegram через бот посылает её нам.
Сделаем мини камеру мобильной, чтобы можно было удобно расположить её:
Производить зарядку удобнее всего модулем TP4056, который поддерживает защиту аккумуляторов и отлично подойдет для 18650.
При потреблении esp32 около 260 мА⋅ч, батареи на 5800 mA⋅ч хватит на сутки постоянной передачи.
Я Приклеил модуль tp на esp через двухсторонний скотч, провода от tp OUT+, OUT- подключаем к 5V и GND. А B+, B- к аккумулятору.
Перейдем к созданию бота, для этого отправляемся к @BotFather и отправляем ему команду: /newbot
Далее придумываем название боту:
Последний шаг это username бота — уникальный ник, по которому легко найти и поделится ботом (должен оканчиваться на bot):
Все! Бот успешно создан, копируем его токен, он нам дальше понадобиться:
5853076693:AAGelU8TwAeu6TRtIQbtr97noqHWi1-ORvY
Чтобы запретить другим людям пользоваться ботом, узнаем собственный user_id. Переходим в @myidbot и отправляем команду /getid:
Напишем скетч:
Для работы с TelegramBotApi будем использовать библиотеку UniversalTelegramBot. А для подключения к wifi, менеджер ESPConnect.
Подключаем библиотеки:
#include <Arduino.h> #include <WiFi.h> #include <AsyncTCP.h> #include <WiFiClientSecure.h> #include "soc/soc.h" #include "soc/rtc_cntl_reg.h" #include "esp_camera.h" #include <UniversalTelegramBot.h> #include <ArduinoJson.h> #include <ESPConnect.h> #include <ESPAsyncWebServer.h>
Измените настройки под свои:
String BOTtoken = "ТОКЕН-БОТА"; String CHAT_ID = "ВАШ-USERID"; int botRequestDelay = 1000; //задержка для проверки новых сообщений
Инициализируем объекты:
AsyncWebServer server(80); WiFiClientSecure clientTCP; UniversalTelegramBot bot(BOTtoken, clientTCP); bool sendPhoto = false; bool flashState = LOW; unsigned long lastTimeBotRan; #define FLASH_LED_PIN 4
Начальная настройка:
void setup(){ WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); Serial.begin(115200); //Монитор порта pinMode(FLASH_LED_PIN, OUTPUT); digitalWrite(FLASH_LED_PIN, flashState); configInitCamera(); WiFi.mode(WIFI_STA); // WiFi.begin(ssid, password); ESPConnect.autoConnect("Название точки доступа для менеджера"); //Подключение к wifi clientTCP.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Сертификат для api.telegram.org while (!ESPConnect.begin(&server)) { Serial.print("."); delay(500); } Serial.println(); Serial.print("ESP32-CAM IP Address: "); Serial.println(WiFi.localIP()); }
Главная программа (Если стоит флаг sendPhoto то делаем и отправляем фото):
void loop() { if (sendPhoto) { Serial.println("Готовим фото"); sendPhotoTelegram(); sendPhoto = false; } if (millis() > lastTimeBotRan + botRequestDelay) { int numNewMessages = bot.getUpdates(bot.last_message_received + 1); while (numNewMessages) { Serial.println("Ответ получен!"); handleNewMessages(numNewMessages); numNewMessages = bot.getUpdates(bot.last_message_received + 1); } lastTimeBotRan = millis(); } }
Функция конфигурации камеры (объявляем все пины камеры и инициализируем камеру):
void configInitCamera(){ camera_config_t config; config.ledc_channel = LEDC_CHANNEL_0; config.ledc_timer = LEDC_TIMER_0; config.pin_d0 = 5; config.pin_d1 = 18; config.pin_d2 = 19; config.pin_d3 = 21; config.pin_d4 = 36; config.pin_d5 = 39; config.pin_d6 = 34; config.pin_d7 = 35; config.pin_xclk = 0; config.pin_pclk = 22; config.pin_vsync = 25; config.pin_href = 23; config.pin_sscb_sda = 26; config.pin_sscb_scl = 27; config.pin_pwdn = 32; config.pin_reset = -1; config.xclk_freq_hz = 20000000; config.pixel_format = PIXFORMAT_JPEG; if(psramFound()){ config.frame_size = FRAMESIZE_UXGA; config.jpeg_quality = 10; config.fb_count = 2; } esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) { Serial.printf("Инициализация камеры завершилась с ошибкой: 0x%x", err); delay(1000); ESP.restart(); } sensor_t * s = esp_camera_sensor_get(); s->set_framesize(s, FRAMESIZE_XGA); // Доступные разрешения камеры: UXGA|SXGA|XGA|SVGA|VGA|CIF|QVGA|HQVGA|QQVGA }
В строчке: s->set_framesize(s, FRAMESIZE_XGA); можно указать качество фото, начиная от QQVGA и заканчивая UXGA. На практике лучше всего отправляются фотографии качества XGA и ниже.
Функция отвечающая за прием и обработку новых сообщений:
void handleNewMessages(int numNewMessages) { Serial.print("Ожидаем новые сообщения: "); Serial.println(numNewMessages); for (int i = 0; i < numNewMessages; i++) { String chat_id = String(bot.messages[i].chat_id); if (chat_id != CHAT_ID){ bot.sendMessage(chat_id, "Неавторизованный пользователь", ""); continue; } String text = bot.messages[i].text; Serial.println(text); //присланное сообщение String from_name = bot.messages[i].from_name; //Меню: (Тут можно добавить свои команды) if (text == "/start") { String welcome = "Привет , " + from_name + "!\n"; welcome += "Доступные команды:\n"; welcome += "/photo : сделать фото\n"; welcome += "/flash : включить светодиод\n"; bot.sendMessage(CHAT_ID, welcome, ""); } if (text == "/flash") { flashState = !flashState; digitalWrite(FLASH_LED_PIN, flashState); Serial.println("Изменяем состояние светодиода"); } if (text == "/photo") { sendPhoto = true; Serial.println("Новый запрос на фотографию"); } } }
Функция создания снимка и отправки на сервер:
String sendPhotoTelegram() { const char* myDomain = "api.telegram.org"; String getAll = ""; String getBody = ""; camera_fb_t * fb = NULL; fb = esp_camera_fb_get(); if(!fb) { Serial.println("Ошибка камеры"); delay(1000); ESP.restart(); return "Ошибка камеры"; } Serial.println("Подключаемя к " + String(myDomain)); if (clientTCP.connect(myDomain, 443)) { Serial.println("Успешное подключение"); String head = "--Amperkot\r\nContent-Disposition: form-data; name=\"chat_id\"; \r\n\r\n" + CHAT_ID + "\r\n--Amperkot\r\nContent-Disposition: form-data; name=\"photo\"; filename=\"esp32-cam.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n"; String tail = "\r\n--Amperkot--\r\n"; uint16_t imageLen = fb->len; uint16_t extraLen = head.length() + tail.length(); uint16_t totalLen = imageLen + extraLen; clientTCP.println("POST /bot"+BOTtoken+"/sendPhoto HTTP/1.1"); clientTCP.println("Host: " + String(myDomain)); clientTCP.println("Content-Length: " + String(totalLen)); clientTCP.println("Content-Type: multipart/form-data; boundary=Amperkot"); clientTCP.println(); clientTCP.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) { clientTCP.write(fbBuf, 1024); fbBuf += 1024; } else if (fbLen%1024>0) { size_t remainder = fbLen%1024; clientTCP.write(fbBuf, remainder); } } clientTCP.print(tail); esp_camera_fb_return(fb); int waitTime = 10000; long startTimer = millis(); boolean state = false; while ((startTimer + waitTime) > millis()){ Serial.print("."); delay(100); while (clientTCP.available()) { char c = clientTCP.read(); if (state==true) getBody += String(c); if (c == '\n') { if (getAll.length()==0) state=true; getAll = ""; } else if (c != '\r') getAll += String(c); startTimer = millis(); } if (getBody.length()>0) break; } clientTCP.stop(); Serial.println(getBody); } else { getBody="Не удалось подключиться к api.telegram.org."; Serial.println("Не удалось подключиться к api.telegram.org."); } return getBody; }
Т. к. esp32-cam не имеет встроенного UART-USB входа, то необходим uart-переходник. Подключаем по схеме:
Красный - 5V Черный - GND Зеленый - U0R Белый - U0T
Перед загрузкой обязательно соедините IOO с gnd. (после загрузки разъединить)
Загружаем... после проверяем wifi сети, там должна появиться точка доступа с вашим названием:
Подключаемся и выбираем свою домашнюю сеть. Вводим логин и пароль. Это удобно когда вы не знаете где придется разместить камеру.
После подключения отправляем нашему боту команду /start:
Испробуем /flash:
Отлично, теперь /photo:
Качество очень хорошее (но авто-фокуса нет):
Фотография приходит через пару секунд после отправки команды, это нормально. ESP требуется время, чтобы загрузить и обработать снимок.
Если мы попробуем зайти с другого аккаунта, то получим сообщение: Пользователь не авторизирован
На этом сегодня все! Камеру можно поставить над 3d принтером и следить за прогрессом печати из любой точки мира. Или в дверной глазок. Спасибо за внимание и удачи в ваших проектах!
Данная статья является собственностью Amperkot.ru. При перепечатке данного материала активная ссылка на первоисточник, не закрытая для индексации поисковыми системами, обязательна.
Комментарии