En aquesta practica amb la placa ESP32-CAM, i un BOT de Telegram volem disparar una foto remotament des de Telegram i visualitzar-la. També activar el flash de la placa.
Esp32-CAM pot interactuar amb un BOT de Telegram per rebre missatges codificar-los i enviar resposta a la nostre compte de Telegram com fotos i lectura de sensors.
En el buscador de Telegram escrivim “Botfather”.
Clic en /start.
Clic en “/newbot” I POSAR EL NOM DEL BOT, en el nostre cas el nom es:
ESP32-CAM-TELEGRAM
Posar el nom del usuari, te que acabar en la paraula “bot”. El nostre nom de usuari es:
Esp32CamTelegramBot
Si el bot s’ha creat adequadament obtenim un link on podem trobar el bot:
t.me/esp32CamTelegramBot
Obtenim un Token que guardem per posar en el codi.
166*******:AAE-_7mJ_**********-edI*rV****n*A*
Telegram User ID.
Qualsevol que conegui el nostre UserName del Bot pot interactuar amb ell.
Per filtrar les connexions amb el Bot, necessitem el User ID. El ESP32 mira si el User ID es el nostre per acceptar les peticions altrament les rebutja.
El User ID o idbot es sempre el mateix per tots els diferents bots que tingui el usuari.
En el nostre compte de Telegram busquem idbot.
Escrivim “/getid”, per obtenir el userID o chatID .
Mòdul ESP32-CAM AI-Thinker amb la càmera OV2640.
Programador FTDI per pujar el codi a la placa.
Cable USB-miniUSB.
Arduino IDE.
Per interactuar amb Telegram utilitzem la llibreria Universal Telegram Bot Library de Brian Lough.
Pagina per descarregar la llibreria:
https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot/archive/master.zipEn el IDE de Arduino anar a Esbós/Inclou biblioteca/Afegeix una biblioteca .ZIP... i seleccionar la carpeta descarregada.
ArduinoJson Library de Benoit Blanchon.
La instalen des del gestor de biblioteques.

Una vegada creat el Bot podem establir una conversa amb el microcontrolador ESP32.
Els comandos per interactuar son: /foto, /flash i /start.
/start. Al enviar aquest missatge la resposta es un missatge de benvinguda amb tots el comandos de control de la placa.
/foto. La placa ESP32-CAM dispara una foto i respon enviant-la per Telegram.
/flash.ESP32-CAM al rebre aquest missatge encén el led de la placa. Si es troba encès l’apaga.
Comprovar el jumper del FTDI que estigui en 5V i no en 3.3V.
Per mes informació visitar la pàgina:
esp32-cam.php#conexio
/* Rui Santos Complete project details at https://TresAvis.com/telegram-esp32-cam-photo-arduino/ Projecte modificat per Treavis https://tresavis.cat 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. */ // Llibreries #include <Arduino.h> #include <WiFi.h> #include <WiFiClientSecure.h> #include "soc/soc.h" // Desactiva apagades per falta de potencia #include "soc/rtc_cntl_reg.h" // Desactiva apagades per falta de potencia #include "esp_camera.h" #include <UniversalTelegramBot.h> #include <ArduinoJson.h> // Parametres WiFi const char* ssid = "mirablau"; const char* password = "*********"; // Initializa Telegram BOT // bot token obtingut del gotFather String BOTtoken = "**********:**************************************"; /* Comandos que accepta el BOT * /start per rebre la benvinguda i el llistat de comandos * /foto per capturar una foto i enviar-la a Telegram * /flash per disparar el flash de la camera. */ // El nostre userID String CHAT_ID = "***********"; bool enviaFoto = false; // Instanciem el bot WiFiClientSecure clientTCP; UniversalTelegramBot bot(BOTtoken, clientTCP); #define FLASH_LED_PIN 4 bool flashEstat = LOW; //ESP32 mira cada 1 segon si hi han noves peticions. int intervalEntrePeticions = 1000; // Temps que la placa esta en funcionament unsigned long tempsFuncionant; //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 ///////////////////// configurarIniciarCamera() //////////////////////////////// void configurarIniciarCamera(){ 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; // Inicia amb altes prestacions per treballar amb un buffer gran if(psramFound()){ config.frame_size = FRAMESIZE_UXGA; config.jpeg_quality = 10; //0-63 a mes petit mes qualitat config.fb_count = 2; } else { config.frame_size = FRAMESIZE_SVGA; config.jpeg_quality = 12; //0-63 a mes petit mes qualitat config.fb_count = 1; } // Inicia la camera esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) { Serial.printf("Camera ha fallat al iniciar-se. amb error: 0x%x", err); delay(1000); ESP.restart(); } // Mida desplegable del quadre per obtenir una freqüència inicial de fotogrames més alta sensor_t * s = esp_camera_sensor_get(); s->set_framesize(s, FRAMESIZE_CIF); // UXGA|SXGA|XGA|SVGA|VGA|CIF|QVGA|HQVGA|QQVGA } //////////////////////////// FI configurarIniciarCamera() //////////////////////////////////////////// // Funció que per cada nou missatge rebut: // Compara el ID del usuari, si es el correcte, continua, altrament rebutxa // Analitza el missatge (Comando) rebut i obra en consecuencia per cada cas. // /start envia missatge de benvinguda // /foto dispara i envia la foto a Telegram, canvia la variable enviaFoto a true // /flash canvia el estat del flash void manipulaNousMissatges(int numMissatgesNous) { Serial.print("Manipula els missatges nous: "); Serial.println(numMissatgesNous); for (int i = 0; i < numMissatgesNous; i++) { String chat_id = String(bot.messages[i].chat_id); if (chat_id != CHAT_ID){ bot.sendMessage(chat_id, "Usuari no autoritzat", ""); continue; } // Mostra el nou missatge rebut String text = bot.messages[i].text; Serial.println(text); String nomUsuari = bot.messages[i].from_name; // El comando /start mostra el missatge de benvinguda if (text == "/start") { String benvinguda = "Benvingut , " + nomUsuari + "\n"; benvinguda += "Utilitza els següents comandos per interectuar amb ESP32-CAM \n"; benvinguda += "/foto : dispara una foto nova\n"; benvinguda += "/flash : encen/apaga el flash LED \n"; bot.sendMessage(CHAT_ID, benvinguda, ""); } // El comando /flash canvia el estat del LED del ESP32-CAM if (text == "/flash") { flashEstat = !flashEstat; digitalWrite(FLASH_LED_PIN, flashEstat); Serial.println("Canvia el estat del flash LED"); } // El comando /foto dispara la foto if (text == "/foto") { enviaFoto = true; Serial.println("Petició de una nova foto"); } } } // ///////// Dispara i envia la foto al BOT de telegram ////////////////////////////////////////////// String disparaEnviaFotoTelegram() { const char* myDomain = "api.telegram.org"; String getAll = ""; String getBody = ""; //buffer fb camera_fb_t * fb = NULL; fb = esp_camera_fb_get(); // si el buffer es buit, ha fallat, reinicia la placa if(!fb) { Serial.println("La capture de la camera ha fallat"); delay(1000); ESP.restart(); return "Camera capture failed"; } Serial.println("Connectem amb: " + String(myDomain)); if (clientTCP.connect(myDomain, 443)) { Serial.println("Connecxió exitosa"); String head = "--TresAvis\r\nContent-Disposition: form-data; name=\"chat_id\"; \r\n\r\n" + CHAT_ID + "\r\n--TresAvis\r\nContent-Disposition: form-data; name=\"photo\"; filename=\"esp32-cam.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n"; String tail = "\r\n--TresAvis--\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=TresAvis"); 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; // timeout 10 seconds 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="La connexió amb api.telegram.org ha fallat."; Serial.println("La connexió amb api.telegram.org ha fallat."); } return getBody; } /////////////////////// fi de disparaEnviaFotoTelegram() ///////////////////////////////////// /////////////////////// setup() /////////////////////////////////////////////////////// void setup(){ WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // Init Serial Monitor Serial.begin(115200); // Set LED Flash as output pinMode(FLASH_LED_PIN, OUTPUT); digitalWrite(FLASH_LED_PIN, flashEstat); // Config and init the camera configurarIniciarCamera(); // Connect to Wi-Fi WiFi.mode(WIFI_STA); Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); clientTCP.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Add root certificate for api.telegram.org while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(500); } Serial.println(); Serial.print("ESP32-CAM IP Address: "); Serial.println(WiFi.localIP()); } void loop() { if (enviaFoto) { Serial.println("Preparing photo"); disparaEnviaFotoTelegram(); enviaFoto = false; } if (millis() > tempsFuncionant + intervalEntrePeticions) { int numMissatgesNous = bot.getUpdates(bot.last_message_received + 1); while (numMissatgesNous) { Serial.println("got response"); manipulaNousMissatges(numMissatgesNous); numMissatgesNous = bot.getUpdates(bot.last_message_received + 1); } tempsFuncionant = millis(); } }
Paràmetres constants per connectar amb el BOT, el USER_ID o CHAT_ID i el BOTtoken:
// Initializa Telegram BOT // bot token obtingut del gotFather String BOTtoken = "XXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXX"; /* Comandos que accepta el BOT * /start per rebre la benvinguda i el llistat de comandos * /foto per capturar una foto i enviar-la a Telegram * /flash per disparar el flash de la camera. */ // El nostre userID String CHAT_ID = "XXXXXXXXXXX";
Variable booleana que ordena fer la foto quant es true:
bool enviaFoto = false;
Definim un client WiFi, instanciant un objecte de la classe WiFiClientSecure.
WiFiClientSecure clientTCP;
Crear un BOT amb el BOTtoken i el client WiFi.
UniversalTelegramBot bot(BOTtoken, clientTCP);
Definim la variable flahState a LOW. En la placa ESP32-CAM AI Thinker el LED flash esta connectat a GPIO4.
#define FLASH_LED_PIN 4 bool flashEstat = LOW;
ESP32 mira per nous missatges cada 1000 mili segons.
//ESP32 mira cada 1 segon si hi han noves peticions. int intervalEntrePeticions = 1000; // Temps que la placa esta en funcionament unsigned long tempsFuncionant;
Configurar i iniciar la càmera ho fa la funció: configurarIniciarCamera(). No entrem en detall, el codi esta suficient comentat.
Metode manipulaNousMissatges(int numMissatgesNous):
// Funció que per cada nou missatge rebut: // Compara el ID del usuari, si es el correcte, continua, altrament rebutxa // Analitza el missatge (Comando) rebut i obra en consecuencia per cada cas. // /start envia missatge de benvinguda // /foto dispara i envia la foto a Telegram, canvia la variable enviaFoto a true // /flash canvia el estat del flash
void manipulaNousMissatges(int numMissatgesNous) { Serial.print("Manipula els missatges nous: "); Serial.println(numMissatgesNous); for (int i = 0; i < numMissatgesNous; i++) { String chat_id = String(bot.messages[i].chat_id); if (chat_id != CHAT_ID){ bot.sendMessage(chat_id, "Usuari no autoritzat", ""); continue; } // Mostra el nou missatge rebut String text = bot.messages[i].text; Serial.println(text); String nomUsuari = bot.messages[i].from_name; // El comando /start mostra el missatge de benvinguda if (text == "/start") { String benvinguda = "Benvingut , " + nomUsuari + "\n"; benvinguda += "Utilitza els següents comandos per interectuar amb ESP32-CAM \n"; benvinguda += "/foto : dispara una foto nova\n"; benvinguda += "/flash : encen/apaga el flash LED \n"; bot.sendMessage(CHAT_ID, benvinguda, ""); } // El comando /flash canvia el estat del LED del ESP32-CAM if (text == "/flash") { flashEstat = !flashEstat; digitalWrite(FLASH_LED_PIN, flashEstat); Serial.println("Canvia el estat del flash LED"); } // El comando /foto dispara la foto if (text == "/foto") { enviaFoto = true; Serial.println("Petició de una nova foto"); } } }
La funció disparaEnviaFotoTelegram():
ESP32-CAM captura la foto:
//buffer fb camera_fb_t * fb = NULL; fb = esp_camera_fb_get(); // si el buffer es buit, ha fallat, reinicia la placa if(!fb) { Serial.println("La capture de la camera ha fallat"); delay(1000); ESP.restart(); return "Camera capture failed"; }
Amb una petició HTTP POST envia la foto al BOT de Telegram:
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=TresAvis"); clientTCP.println(); clientTCP.print(head);
En el loop si la variable enviaFoto es true captura una nova foto i l’envia al BOT i després posa la variable a false.
void loop() { if (enviaFoto) { Serial.println("Preparing photo"); disparaEnviaFotoTelegram(); enviaFoto = false; }
També en el loop, mira cada segon si hi ha nous missatges. Quan arriba un nou missatge crida al mètode manipulaNousMissatges(numeroDeMissatges).
if (millis() > tempsFuncionant + intervalEntrePeticions) { int numMissatgesNous = bot.getUpdates(bot.last_message_received + 1); while (numMissatgesNous) { Serial.println("got response"); manipulaNousMissatges(numMissatgesNous); numMissatgesNous = bot.getUpdates(bot.last_message_received + 1); } tempsFuncionant = millis(); }


El mar.
Havaneres.
Lloret antic.
Lloret avui.
De cala Morisca a Sa Carabera.
De Sa Carabera a Treumal.
Lloret en kayak.
Vígilancia remota.
Caixa-tpv.
Cambrer-app.
Client webApp.
Relats del banc del si no fos
Històries d'ahir
Vídeos antics de Lloret
El caiac
Contes de l'avi.
Control d’accés amb contrasenya.
Orgue de llums.
Comparativa de editors Arduino.
Projecte bon Nadal.
Control de la qualitat del aire interior (CO2) amb semàfor LED.
NodeMCU-ThingSpeak
ThingSpeak.
NodeMCU com AccessPoint.
Control de la llum de casa per web.
Control de un led per el mòbil.
Sistema de fitxers en ESP8266.
Altura del nivell d'aigua.
Avis d’alarma a Telegram.
Control de la intensitat de llum de un LED per Internet.
Magatzematge de temperatura i humitat en Thinger.
Publicar temperatura i humitat en Google Sheets.
ESP8266 i Firebase.
La bàscula. ESP8266 NodeMCU amb cèl·lula de càrrega.
ESP32-CAM
ESP32-CAM captura fotos per ser vistes en la WEB.
Pujar fotos a un servidor FTP amb ESP32-CAM.
MicroPython en ESP8266.
Visual Estudio Code per Arduino.
Classificador d’imatges.
Instal·lar i configurar Apache en Ubuntu.
Accés a un servidor Linux remotament.
Client i Servidor FTP.
Màquina virtual UBUNTU.
WindowsXP en Virtualbox.
Multisim, simulador de circuits electrònics.
Proteus, simulador de circuits electrònics.
MySQL. Instal·lació.
MySQL. Aplicacions.
Netbeans Maven MySQL.
Java+Netbeans+Maven+EclipseLink+Mysql
Aplicació d’escriptori JavaFX
App JavaFX amb SceneBuilder
App Java-Swing











Noves tecnologies WEB Arduino Domótica MycroPython NodeMCU IoT Java ESP8266 Lora C++ Programació Server-Client