×

ARDUINO

Control d’accés amb contrasenya. Orgue de llums. Comparativa de editors Arduino. Projecte bon Nadal. Sensor de gas i de fums. Control de la qualitat del aire interior (CO2) amb semàfor LED.

NodeMCU

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 llum de casa des de 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. ESP8266-BME280 Firebase. La bàscula. ESP8266 NodeMCU amb cèl·lula de càrrega..

ESP32

ESP32-CAM, exemple de prova. Esp32-Cam captura fotos per ser vistes en la WEB. Pujar fotos a un servidor FTP amb ESP32-CAM. Foto amb ESP32-CAM i Telegram. Alarma amb avis a Telegram, utilitzant la placa ESP32-CAM.

PROGRAMACIÓ

Matemàtiques. App Inventor tutorial. MicroPython en ESP8266. Visual Estudio Code per Arduino

Intel·ligència artificial

Classificador d’imatges.

SERVIDORS

Instal·lar i configurar Apache en Ubuntu. Accés a un servidor Linux remotament. Client i Servidor FTP.

MÀQUINES VIRTUALS

Màquina virtual UBUNTU. WindowsXP en Virtualbox.

ELECTRÒNICA

Simulador Multisim. Simulador Proteus.

BASE DE DADES

MySQL. Instal·lació. MySQL. Aplicacions.

JAVA

Netbeans Maven MySQL. Java+Netbeans+Maven+EclipseLink+MySQL Aplicació d’escriptori JavaFX App JavaFX amb SceneBuilder App Java-Swing
favicon
logo

Tresavis

Benvinguts al blog de tresavis de noves tecnologies i més.

Correu : tresavis3@gmail.com

facebook   Instagram   youtube   x   tiktok

☰ Pràctiques   ☰ Articles

Foto amb ESP32-CAM i Telegram.

Descripció.

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.

Contingut:

diagrama

Estudis previs.

Per informació de la placa ESP32-CAM cal visitar la pagina:

esp32-cam.php

BOT de Telegram.

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.

bot1

Clic en “/newbot” I POSAR EL NOM DEL BOT, en el nostre cas el nom es:

ESP32-CAM-TELEGRAM

bot2

Posar el nom del usuari, te que acabar en la paraula “bot”. El nostre nom de usuari es:

Esp32CamTelegramBot

bot3

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.

bot4

Escrivim “/getid”, per obtenir el userID o chatID .

bot5

Components per desenvolupar la practica.

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.

Llibreries.

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.zip

En 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.

llibraria

Comandos que accepta el Bot de Telegram.

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.

Connexió de ESP32-CAM amb el programador FTDI.

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 programador0
programador

Codi.

/*
  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();
  }
}

Explicacions del codi.

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();
  }

Resultat.

resultat0
resultat

Contingut.


Nosaltres

tresBraques
canyelles
lluna
kayak1
kayack2
cami
santPere
conill
invent
celRogent
bosc

Tags

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