[TUTO] Caméra à focale fixe basée sur ESP32

@olive
Tout simplement! Merci :blush:

@Theduck38
Je vais intégrer le port dans le code

1 « J'aime »

Re encore moi

J’ai modifié le code pour apporter la modification des liens sur la page d’accueil. Ils incluent maintenant le port défini dans la config.

Il faut donc penser à modifier:

  • le port du webserver (WebServer server(80);)
  • la variable qui servira à afficher le port dans les liens (#define WSPORT 80)
  • le port du asyncwebserver (AsyncWebServer serverasync(81);)

et voici le beau code :slight_smile:

// SERVEUR WEB CAM From: https://community.jeedom.com/t/tuto-camera-a-focale-fixe-basee-sur-esp32/17587/49
// LED WIFI FROM: https://techtutorialsx.com/2018/02/03/esp32-arduino-async-server-controlling-http-methods-allowed/
// For installing Asyncwebserver: https://techtutorialsx.com/2017/12/01/esp32-arduino-asynchronous-http-webserver/
// modified by DRS - May 2020
//
//
#include <WiFi.h>
#include <WebServer.h>
#include <ESPAsyncWebServer.h>  //permet la connexion simultanee pour la gestion de la LED
#include <WiFiClient.h>
#include <AutoConnect.h> // Needs AutoConnect, PageBuilder libraries!
#include "soc/soc.h" //disable brownout problems
#include "soc/rtc_cntl_reg.h"  //disable brownout problems

#define ENABLE_RTSPSERVER
#define ENABLE_WEBSERVER
#define RESOLUTION  FRAMESIZE_XGA // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
#define QUALITY        10          // JPEG quality 10-63 (lower means better quality)
#define PIN_FLASH_LED  -1           // GPIO4 for AIThinker module, set to -1 if not needed!

#define LED_BUILTIN 4         // VA SERVIR POUR ALLUMER et ETEINDRE LA LED

#include "OV2640.h"
#ifdef ENABLE_RTSPSERVER
 #include "OV2640Streamer.h"
 #include "CRtspSession.h"
#endif

OV2640 cam;
boolean useRTSP = true;

WebServer server(80);             // modifier le port si besoin
#define WSPORT  80                // modifier le port idem que Webserver
AsyncWebServer serverasync(81);   // modifier le port si besoin
AutoConnect Portal(server);
AutoConnectConfig acConfig;

#ifdef ENABLE_RTSPSERVER
WiFiServer rtspServer(554);
CStreamer *streamer;
#endif

void setflash(byte state) {
  if (PIN_FLASH_LED>-1){
    digitalWrite(PIN_FLASH_LED, state);
  }   
}

void handle_jpg_stream(void)
{
  WiFiClient client = server.client();
  String response = "HTTP/1.1 200 OK\r\n";
  response += "Content-Type: multipart/x-mixed-replace; boundary=frame\r\n\r\n";
  server.sendContent(response);

  while (1)
  {
    cam.run();
    if (!client.connected())
      break;
    response = "--frame\r\n";
    response += "Content-Type: image/jpeg\r\n\r\n";
    server.sendContent(response);

    client.write((char *)cam.getfb(), cam.getSize());
    server.sendContent("\r\n");
    if (!client.connected())
      break;
  }
}

void handle_jpg(void)
{
  setflash(1);
  WiFiClient client = server.client();
  cam.run();
  if (!client.connected())
  {
    return;
  }
  String response = "HTTP/1.1 200 OK\r\n";
  response += "Content-disposition: inline; filename=snapshot.jpg\r\n";
  response += "Content-type: image/jpeg\r\n\r\n";
  server.sendContent(response);
  client.write((char *)cam.getfb(), cam.getSize());
  setflash(0);
}

void handle_root(void)
{
  
  String reply = F("<!doctype html><html><H1>ESP32CAM</H1>");

  reply += F("<p>Resolution: ");

  switch(RESOLUTION) {
    case FRAMESIZE_QVGA:
     reply += F("QVGA (320x240)");
    break;
    case FRAMESIZE_CIF:
     reply += F("CIF (400x296)");
    break;
    case FRAMESIZE_VGA:
     reply += F("VGA (640x480)");
    break;
    case FRAMESIZE_SVGA:
     reply += F("SVGA (800x600)");
    break;
    case FRAMESIZE_XGA:
     reply += F("XGA (1024x768)");
    break;
    case FRAMESIZE_SXGA:
     reply += F("SXGA (1280x1024)");
    break;
    case FRAMESIZE_UXGA:
     reply += F("UXGA (1600x1200)");
    break;
    default:
     reply += F("Unknown");
    break;
  }
  
  reply += F("<p>PSRAM found: ");
  if (psramFound()){
   reply += F("TRUE");
  } else {
   reply += F("FALSE");
  }
  String url = "http://" + WiFi.localIP().toString() + ":" + WSPORT + "/snapshot.jpg";
  reply += "<p>Snapshot URL:<br> <a href='" + url + "'>" + url + "</a>";
  url = "http://" + WiFi.localIP().toString() +":" + WSPORT + "/mjpg";
  reply += "<p>HTTP MJPEG URL:<br> <a href='" + url + "'>" + url + "</a>";
  url = "rtsp://" + WiFi.localIP().toString() + ":554/mjpeg/1";
  reply += "<p>RTSP MJPEG URL:<br> " + url;
  url = "http://" + WiFi.localIP().toString() +":" + WSPORT + "/_ac";
  reply += "<p>WiFi settings page:<br> <a href='" + url + "'>" + url + "</a>";

  reply += F("</body></html>");
  server.send(200, "text/html", reply);
}

void handleNotFound()
{
  String message = "Server is running!\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  server.send(200, "text/plain", message);
}

void setup(){

  pinMode(LED_BUILTIN, OUTPUT);       // pour LED
  digitalWrite(LED_BUILTIN, LOW);     // pour LED
  
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector 
  Serial.begin(115200);
  //  while (!Serial){;} // debug only
  camera_config_t cconfig;
  cconfig = esp32cam_aithinker_config;
  if (psramFound()) {
    cconfig.frame_size = RESOLUTION; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
    cconfig.jpeg_quality = QUALITY;
    cconfig.fb_count = 2;
  } else {
    if (RESOLUTION>FRAMESIZE_SVGA) {
     cconfig.frame_size = FRAMESIZE_SVGA;
    }
    cconfig.jpeg_quality = 12;
    cconfig.fb_count = 1;
  }
  if (PIN_FLASH_LED>-1){
    pinMode(PIN_FLASH_LED, OUTPUT);
    setflash(0);
  }  
  cam.init(cconfig);

  server.on("/", handle_root);
  server.on("/mjpg", HTTP_GET, handle_jpg_stream);
  server.on("/snapshot.jpg", HTTP_GET, handle_jpg);
  Portal.onNotFound(handleNotFound);
  acConfig.apid = "ESP-" + String((uint32_t)(ESP.getEfuseMac() >> 32), HEX);
  acConfig.psk = "configesp";
//  acConfig.apip = IPAddress(192,168,4,1);
  acConfig.hostName = acConfig.apid;
  acConfig.autoReconnect = true;
  Portal.config(acConfig);
  Portal.begin();

// POUR LED
serverasync.on("/relay/off", HTTP_ANY, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", "ok");
    digitalWrite(LED_BUILTIN, LOW);
  });
  
  serverasync.on("/relay/on", HTTP_ANY, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain","ok");
    digitalWrite(LED_BUILTIN, HIGH);
  });
  
  serverasync.on("/relay/toggle", HTTP_ANY, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain","ok");
     digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  });
  
  serverasync.on("/relay", HTTP_GET, [](AsyncWebServerRequest *request){
     request->send(200, "text/plain", String(digitalRead(LED_BUILTIN)));
  });
  
  serverasync.begin();

//

#ifdef ENABLE_RTSPSERVER
  if (useRTSP) {
    rtspServer.begin();
    streamer = new OV2640Streamer(cam);             // our streamer for UDP/TCP based RTP transport
  }
#endif
}

void loop()
{
  //server.handleClient();
  Portal.handleClient();

#ifdef ENABLE_RTSPSERVER
  if (useRTSP) {
    uint32_t msecPerFrame = 100;
    static uint32_t lastimage = millis();

    // If we have an active client connection, just service that until gone
    streamer->handleRequests(0); // we don't use a timeout here,
    // instead we send only if we have new enough frames
    uint32_t now = millis();
    if (streamer->anySessions()) {
      if (now > lastimage + msecPerFrame || now < lastimage) { // handle clock rollover
        streamer->streamImage(now);
        lastimage = now;

        // check if we are overrunning our max frame rate
        now = millis();
        if (now > lastimage + msecPerFrame) {
          printf("warning exceeding max frame rate of %d ms\n", now - lastimage);
        }
      }
    }

    WiFiClient rtspClient = rtspServer.accept();
    if (rtspClient) {
      Serial.print("client: ");
      Serial.print(rtspClient.remoteIP());
      Serial.println();
      streamer->addSession(rtspClient);
    }
  }
#endif
}

Si un pro de l’arduino passe par là, peut être pourra-t-il nettoyer ce code. Et éventuellement repartir sur cette base pour ne laisser que le AsyncWebServer et pas les deux ensembles :slight_smile:

Et me revoilà :slight_smile:

J’ai encore modifié le code, en y apportant les modifs suivantes:

  • j’ai retiré l’option Flash LED, qui ne sert plus à rien ici
  • j’ai intégré toutes les options possibles d’image (flip, mirror, balance des blancs, effets speciaux…)
  • j’ai modifié la définition des ports des serveurs web par des variables, pour n’en modifier qu’une
  • j’ai intégré en commentaire les liens qui m’ont servi, ainsi que la doc d’utilisation.

Et voici le final:

//---------------------------------------------------------------------------------------------------------------------
// DOCS UTILES:
// ------------
// SERVEUR WEB CAM From: https://community.jeedom.com/t/tuto-camera-a-focale-fixe-basee-sur-esp32/17587/49
// LED WIFI FROM: https://techtutorialsx.com/2018/02/03/esp32-arduino-async-server-controlling-http-methods-allowed/
// For installing Asyncwebserver: https://techtutorialsx.com/2017/12/01/esp32-arduino-asynchronous-http-webserver/
// FOR IMAGE PARAMS: https://randomnerdtutorials.com/esp32-cam-ov2640-camera-settings/
// modified by DRS - May 2020
//
// PARAMETRES A MODIFIER:
// ----------------------
// RESOLUTION: FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
// WSPORT: port  web (pour affichage images)
// ASYNCPORT: port AsyncWebServer (pour gestion LED)
// Paramètres image
//
// USAGE:
// ------
// http://ip-esp:port/                page d'accueil
// http://ip-esp:port/_ac             page de config
// http://ip-esp:port/mjpg:           stream
// http://ip-esp:port/snapshot.jpg    image
//
// GESTION DE LA LED:
// ------------------
// http://ip-esp:port/relay           Etat de la led (format binaire)
// http://ip-esp:port/relay/on        Allume la LED
// http://ip-esp:port/relay/off       Eteint la LED
// http://ip-esp:port/relay/toggle    Allume/Eteint la LED
//
// INTEGRATION JEEDOM:
// -------------------
// Plugin Camera:
// Laisser le type de camera sur "Aucun"
// Renseigner l'IP et le port (webserver)
// URL de snapshot:   /snapshot.jpg
// URL de flux:       /mjpg
//
// Script gestion led:
// Action/Default
// URL: voir ci-dessus (le port est celui du AsyncWebServer)
// Cocher "Pas d'erreurs"
// La réponse doit contenir: ok (en minuscule)
//
//---------------------------------------------------------------------------------------------------------------------
#include <WiFi.h>
#include <WebServer.h>
#include <ESPAsyncWebServer.h>  //permet la connexion simultanee pour la gestion de la LED
#include <WiFiClient.h>
#include <AutoConnect.h>        // Needs AutoConnect, PageBuilder libraries!
#include "soc/soc.h"            //disable brownout problems
#include "soc/rtc_cntl_reg.h"  //disable brownout problems
#include "esp_camera.h"        // Pas sur de l'utilité. A vérifier

#define ENABLE_RTSPSERVER
#define ENABLE_WEBSERVER
#define RESOLUTION  FRAMESIZE_XGA   // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
#define QUALITY        10           // JPEG quality 10-63 (lower means better quality)

// PARAMETRES IMAGE
#define BRIGHT    1           // Brightness: -2 to 2
#define CONTRAST  0           // Contrast: -2 to 2
#define SATUR     0           // Color Saturation: -2 to 2
#define SPECIAL   0           // Special effects: 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
#define WHITEBAL  1           // White Balance: 0 = disable , 1 = enable
#define AWBGAIN   1           // White Balance Gain: 0 = disable , 1 = enable
#define AWBMODE   3           // White Balance Mode: 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
#define EXPOS     1           // Exposure Control: 0 = disable , 1 = enable
#define AEC2      0           // 0 = disable , 1 = enable
#define AELEV     0           // -2 to 2
#define AECVAL    300         // 0 to 1200
#define GAINCT    1           // 0 = disable , 1 = enable
#define GAINAGC   0           // 0 = disable , 1 = enable
#define GAINCELL  0           // 0 = disable , 1 = enable
#define BPC       0           // 0 = disable , 1 = enable
#define WPC       1           // 0 = disable , 1 = enable
#define RAWGMA    1           // 0 = disable , 1 = enable
#define LENC      1           // Lens Correction: 0 = disable , 1 = enable
#define MIRROR    0           // Horizontal Mirror: 0 = disable , 1 = enable
#define FLIP      0           // Vertical Flip: 0 = disable , 1 = enable
#define DCW       1           // 0 = disable , 1 = enable
#define CBAR      0           // Set a colorBar: 0 = disable , 1 = enable

#define LED_BUILTIN 4         // VA SERVIR POUR ALLUMER et ETEINDRE LA LED

#include "OV2640.h"
#ifdef ENABLE_RTSPSERVER
 #include "OV2640Streamer.h"
 #include "CRtspSession.h"
#endif

OV2640 cam;
boolean useRTSP = true;

#define WSPORT  80                // modifier le port pour Webserver Image
#define ASYNCPORT  81             // modifier le port pour Webserver LED
WebServer server(WSPORT); 
AsyncWebServer serverasync(ASYNCPORT);
AutoConnect Portal(server);
AutoConnectConfig acConfig;

#ifdef ENABLE_RTSPSERVER
WiFiServer rtspServer(554);
CStreamer *streamer;
#endif

void handle_jpg_stream(void)
{
  WiFiClient client = server.client();
  String response = "HTTP/1.1 200 OK\r\n";
  response += "Content-Type: multipart/x-mixed-replace; boundary=frame\r\n\r\n";
  server.sendContent(response);

  while (1)
  {
    cam.run();
    if (!client.connected())
      break;
    response = "--frame\r\n";
    response += "Content-Type: image/jpeg\r\n\r\n";
    server.sendContent(response);

    client.write((char *)cam.getfb(), cam.getSize());
    server.sendContent("\r\n");
    if (!client.connected())
      break;
  }
}

void handle_jpg(void)
{
//  setflash(1);
  WiFiClient client = server.client();
  cam.run();
  if (!client.connected())
  {
    return;
  }
  String response = "HTTP/1.1 200 OK\r\n";
  response += "Content-disposition: inline; filename=snapshot.jpg\r\n";
  response += "Content-type: image/jpeg\r\n\r\n";
  server.sendContent(response);
  client.write((char *)cam.getfb(), cam.getSize());
//  setflash(0);
}

void handle_root(void)
{
  
  String reply = F("<!doctype html><html><H1>ESP32CAM</H1>");

  reply += F("<p>Resolution: ");

  switch(RESOLUTION) {
    case FRAMESIZE_QVGA:
     reply += F("QVGA (320x240)");
    break;
    case FRAMESIZE_CIF:
     reply += F("CIF (400x296)");
    break;
    case FRAMESIZE_VGA:
     reply += F("VGA (640x480)");
    break;
    case FRAMESIZE_SVGA:
     reply += F("SVGA (800x600)");
    break;
    case FRAMESIZE_XGA:
     reply += F("XGA (1024x768)");
    break;
    case FRAMESIZE_SXGA:
     reply += F("SXGA (1280x1024)");
    break;
    case FRAMESIZE_UXGA:
     reply += F("UXGA (1600x1200)");
    break;
    default:
     reply += F("Unknown");
    break;
  }
  
  reply += F("<p>PSRAM found: ");
  if (psramFound()){
   reply += F("TRUE");
  } else {
   reply += F("FALSE");
  }
  String url = "http://" + WiFi.localIP().toString() + ":" + WSPORT + "/snapshot.jpg";
  reply += "<p>Snapshot URL:<br> <a href='" + url + "'>" + url + "</a>";
  url = "http://" + WiFi.localIP().toString() +":" + WSPORT + "/mjpg";
  reply += "<p>HTTP MJPEG URL:<br> <a href='" + url + "'>" + url + "</a>";
  url = "rtsp://" + WiFi.localIP().toString() + ":554/mjpeg/1";
  reply += "<p>RTSP MJPEG URL:<br> " + url;
  url = "http://" + WiFi.localIP().toString() +":" + WSPORT + "/_ac";
  reply += "<p>WiFi settings page:<br> <a href='" + url + "'>" + url + "</a>";

  reply += F("</body></html>");
  server.send(200, "text/html", reply);
}

void handleNotFound()
{
  String message = "Server is running!\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  server.send(200, "text/plain", message);
}

void setup(){

  pinMode(LED_BUILTIN, OUTPUT);       // pour LED
  digitalWrite(LED_BUILTIN, LOW);     // pour LED
  
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector 
  Serial.begin(115200);
  //  while (!Serial){;} // debug only
  camera_config_t cconfig;
  cconfig = esp32cam_aithinker_config;

  if (psramFound()) {
    cconfig.frame_size = RESOLUTION; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
    cconfig.jpeg_quality = QUALITY;
    cconfig.fb_count = 2;
  } else {
    if (RESOLUTION>FRAMESIZE_SVGA) {
     cconfig.frame_size = FRAMESIZE_SVGA;
    }
    cconfig.jpeg_quality = 12;
    cconfig.fb_count = 1;
  }
//  if (PIN_FLASH_LED>-1){
//    pinMode(PIN_FLASH_LED, OUTPUT);
//    setflash(0);
//  } 

  cam.init(cconfig);

sensor_t * s = esp_camera_sensor_get();
  s->set_brightness(s, BRIGHT);
  s->set_contrast(s, CONTRAST);
  s->set_saturation(s, SATUR);
  s->set_special_effect(s, SPECIAL);
  s->set_whitebal(s, WHITEBAL);
  s->set_awb_gain(s, AWBGAIN);
  s->set_wb_mode(s, AWBMODE);
  s->set_exposure_ctrl(s, EXPOS);
  s->set_aec2(s, AEC2);
  s->set_ae_level(s, AELEV);
  s->set_aec_value(s, AECVAL);
  s->set_gain_ctrl(s, GAINCT);
  s->set_agc_gain(s, GAINAGC);
  s->set_gainceiling(s, (gainceiling_t)GAINCELL);
  s->set_bpc(s, BPC);
  s->set_wpc(s, WPC);
  s->set_raw_gma(s, RAWGMA);
  s->set_lenc(s, LENC);
  s->set_hmirror(s, MIRROR);
  s->set_vflip(s, FLIP);
  s->set_dcw(s, DCW);
  s->set_colorbar(s, CBAR);

  server.on("/", handle_root);
  server.on("/mjpg", HTTP_GET, handle_jpg_stream);
  server.on("/snapshot.jpg", HTTP_GET, handle_jpg);
  Portal.onNotFound(handleNotFound);
  acConfig.apid = "ESP-" + String((uint32_t)(ESP.getEfuseMac() >> 32), HEX);
  acConfig.psk = "configesp";
  acConfig.apip = IPAddress(192,168,4,1);
  acConfig.hostName = acConfig.apid;
  acConfig.autoReconnect = true;
  Portal.config(acConfig);
  Portal.begin();

// POUR LED
serverasync.on("/relay/off", HTTP_ANY, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", "ok");
    digitalWrite(LED_BUILTIN, LOW);
  });
  
  serverasync.on("/relay/on", HTTP_ANY, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain","ok");
    digitalWrite(LED_BUILTIN, HIGH);
  });
  
  serverasync.on("/relay/toggle", HTTP_ANY, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain","ok");
     digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  });
  
  serverasync.on("/relay", HTTP_GET, [](AsyncWebServerRequest *request){
     request->send(200, "text/plain", String(digitalRead(LED_BUILTIN)));
  });
  
  serverasync.begin();

#ifdef ENABLE_RTSPSERVER
  if (useRTSP) {
    rtspServer.begin();
    streamer = new OV2640Streamer(cam);             // our streamer for UDP/TCP based RTP transport
  }
#endif
}

void loop()
{
  //server.handleClient();
  Portal.handleClient();

#ifdef ENABLE_RTSPSERVER
  if (useRTSP) {
    uint32_t msecPerFrame = 100;
    static uint32_t lastimage = millis();

    // If we have an active client connection, just service that until gone
    streamer->handleRequests(0); // we don't use a timeout here,
    // instead we send only if we have new enough frames
    uint32_t now = millis();
    if (streamer->anySessions()) {
      if (now > lastimage + msecPerFrame || now < lastimage) { // handle clock rollover
        streamer->streamImage(now);
        lastimage = now;

        // check if we are overrunning our max frame rate
        now = millis();
        if (now > lastimage + msecPerFrame) {
          printf("warning exceeding max frame rate of %d ms\n", now - lastimage);
        }
      }
    }

    WiFiClient rtspClient = rtspServer.accept();
    if (rtspClient) {
      Serial.print("client: ");
      Serial.print(rtspClient.remoteIP());
      Serial.println();
      streamer->addSession(rtspClient);
    }
  }
#endif
}

Testé et fonctionnel. Comme les fois précédentes, si un nettoyeur de code passe par là…

Bon week end

suggestions :

tu pourrait ajouter une fois le wifi initialisé une variable du style

IP = WiFi.localIP().toString();
au lieu que de répeter x fois ...

Ajoute aussi un N° de version et une date en haut de ton code en commentaire.

ça permet de se retrouver en cas d’évolutions du code et de bien parler de la même chose.

OK Je vais faire ça, et rajouter dates et N° de versions.

Par contre, est-ce que:

IP = WiFi.localIP().toString();

est équivalent à:

#define IP WiFi.localIP().toString()

Si oui, dans quel cas utiliser l’un ou l’autre?

un #define est plutôt fait pour une constante
la il faut plutôt utiliser une variable
car tu ne connais pas forcement la valeur de ton IP avant que tu soit connecter …
Il faut donc le faire après établissement de la connexion

OK donc pour définir le port du webserver par exemple, il faut préférer un define, et pour toutes les valeurs non connues à l’avance, une variable, c’est bien ça?

Mais du coup, il faut que je mette cette ligne après la connexion, et non pas au niveau de mes define déjà présents?

Le port c’est toi qui le choisi il est donc bien défini a l’avance …
l’ip c’est moins sur (si tu est sur une ip statique oui si non sur une dynamique elle peut changée)

OK je vois bien la différence entre les deux maintenant, merci.

Et concernant les serveurs web, j’ai:

  • le webserver pour la partie image
  • le ASYNC webserver pour la partie LED.
    D’après ce que j’ai compris, le ASYNC permet plusieurs connexions simultanées. Penses-tu qu’il est possible de gérer l’image et la LED uniquement avec le ASYNC?
    Cela permettrait aussi de faire diffuser l’image plusieurs fois.

https://openclassrooms.com/fr/courses/2778161-programmez-vos-premiers-montages-avec-arduino/3285142-utilisez-les-constantes-les-variables-les-conditions-et-le-moniteur-serie

http://www.mon-club-elec.fr/pmwiki_reference_arduino/pmwiki.php?n=Main.Define

en faite tu a 3 méthode
#define (c’est avant compilation)

const type NOMDELACONSTANTE=valeur;
tu ne peut la modifier en cour de programme

et les variables …

Merci. J’ai lu, et j’ai ajouté la ligne à mon code:

IP = WiFi.localIP().toString();

Et voici le message que j’ai lors de la vérification:

exit status 1
'IP' does not name a type

Je pense que je ne l’ai pas mis au bon endroit. Pour le moment, il est ici:

IP

(tu l’as compris, je n’y connais rien, donc je tatonnes :slight_smile:))

une ip c’est un type string …
il te faut déclarer le type de variable …

http://diwo.bq.com/fr/les-variables-sur-arduino/

tu a déjà un exemple avec url :

String url = "http://" + WiFi.localIP().toString() + ":" + WSP ..........

Bon, rien à faire je n’y arrive pas. J’ai l’impression qu’on ne peux pas l’utiliser directement, et que je vais devoir écrire quelques lignes. J’ai fait pas mal de tests dans tous les sens, mais non, ça ne veut pas :slight_smile:

Voici la version 1.3 avec:

  • le versionning
  • l’horodatage
  • Ajout de l’ip de l’esp dans la console série
  • Ajout d’un message sur la console série lors de l’action sur la led
//---------------------------------------------------------------------------------------------------------------------
// DOCS UTILES:
// ------------
// SERVEUR WEB CAM: https://community.jeedom.com/t/tuto-camera-a-focale-fixe-basee-sur-esp32/17587/49
// LED WIFI: https://techtutorialsx.com/2018/02/03/esp32-arduino-async-server-controlling-http-methods-allowed/
// Installing Asyncwebserver: https://techtutorialsx.com/2017/12/01/esp32-arduino-asynchronous-http-webserver/
// IMAGE PARAMS: https://randomnerdtutorials.com/esp32-cam-ov2640-camera-settings/
//
// modified by DRS - Version 1.3 - 16 Mai 2020
//
// PARAMETRES A MODIFIER:
// ----------------------
// RESOLUTION: FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA / QUALITY (10-63)
// WSPORT: port  web (pour affichage images)
// ASYNCPORT: port AsyncWebServer (pour gestion LED)
// Paramètres image
//
// USAGE:
// ------
// http://ip-esp:WSPORT/                page d'accueil
// http://ip-esp:WSPORT/_ac             page de config
// http://ip-esp:WSPORT/mjpg:           stream
// http://ip-esp:WSPORT/snapshot.jpg    image
//
// GESTION DE LA LED:
// ------------------
// http://ip-esp:ASYNCPORT/relay           Etat de la led (format binaire)
// http://ip-esp:ASYNCPORT/relay/on        Allume la LED
// http://ip-esp:ASYNCPORT/relay/off       Eteint la LED
// http://ip-esp:ASYNCPORT/relay/toggle    Allume/Eteint la LED
//
// INTEGRATION JEEDOM:
// -------------------
// Plugin Camera:
// Laisser le type de camera sur "Aucun"
// Renseigner l'IP et le port (webserver)
// URL de snapshot:   /snapshot.jpg
// URL de flux:       /mjpg
//
// Script gestion led:
// Action/Default
// URL: voir ci-dessus
// Cocher "Pas d'erreurs"
// La réponse doit contenir: ok (en minuscule)
// Timeout: si besoin (pas nécessaire)
//
//---------------------------------------------------------------------------------------------------------------------
#include <WiFi.h>
#include <WebServer.h>
#include <ESPAsyncWebServer.h>  //permet la connexion simultanee pour la gestion de la LED
#include <WiFiClient.h>
#include <AutoConnect.h>        // Needs AutoConnect, PageBuilder libraries!
#include "soc/soc.h"            //disable brownout problems
#include "soc/rtc_cntl_reg.h"  //disable brownout problems
#include "esp_camera.h"        // Pas sur de l'utilité. A vérifier

#define ENABLE_RTSPSERVER
#define ENABLE_WEBSERVER
#define RESOLUTION  FRAMESIZE_XGA   // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
#define QUALITY        10           // JPEG quality 10-63 (lower means better quality)

// PARAMETRES IMAGE
#define BRIGHT    1           // Brightness: -2 to 2
#define CONTRAST  0           // Contrast: -2 to 2
#define SATUR     0           // Color Saturation: -2 to 2
#define SPECIAL   0           // Special effects: 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
#define WHITEBAL  1           // White Balance: 0 = disable , 1 = enable
#define AWBGAIN   1           // White Balance Gain: 0 = disable , 1 = enable
#define AWBMODE   3           // White Balance Mode: 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
#define EXPOS     1           // Exposure Control: 0 = disable , 1 = enable
#define AEC2      0           // 0 = disable , 1 = enable
#define AELEV     0           // -2 to 2
#define AECVAL    300         // 0 to 1200
#define GAINCT    1           // 0 = disable , 1 = enable
#define GAINAGC   0           // 0 = disable , 1 = enable
#define GAINCELL  0           // 0 = disable , 1 = enable
#define BPC       0           // 0 = disable , 1 = enable
#define WPC       1           // 0 = disable , 1 = enable
#define RAWGMA    1           // 0 = disable , 1 = enable
#define LENC      1           // Lens Correction: 0 = disable , 1 = enable
#define MIRROR    0           // Horizontal Mirror: 0 = disable , 1 = enable
#define FLIP      0           // Vertical Flip: 0 = disable , 1 = enable
#define DCW       1           // 0 = disable , 1 = enable
#define CBAR      0           // Set a colorBar: 0 = disable , 1 = enable

#define LED_BUILTIN 4         // VA SERVIR POUR ALLUMER et ETEINDRE LA LED - NE PAS MODIFIER CETTE VALEUR (GPIO4)

#include "OV2640.h"
#ifdef ENABLE_RTSPSERVER
 #include "OV2640Streamer.h"
 #include "CRtspSession.h"
#endif

OV2640 cam;
boolean useRTSP = true;

#define WSPORT  80                // modifier le port pour Webserver Image
#define ASYNCPORT  81             // modifier le port pour Webserver LED
WebServer server(WSPORT); 
AsyncWebServer serverasync(ASYNCPORT);
AutoConnect Portal(server);
AutoConnectConfig acConfig;



#ifdef ENABLE_RTSPSERVER
WiFiServer rtspServer(554);
CStreamer *streamer;
#endif



void handle_jpg_stream(void)
{
  WiFiClient client = server.client();
  String response = "HTTP/1.1 200 OK\r\n";
  response += "Content-Type: multipart/x-mixed-replace; boundary=frame\r\n\r\n";
  server.sendContent(response);

  while (1)
  {
    cam.run();
    if (!client.connected())
      break;
    response = "--frame\r\n";
    response += "Content-Type: image/jpeg\r\n\r\n";
    server.sendContent(response);

    client.write((char *)cam.getfb(), cam.getSize());
    server.sendContent("\r\n");
    if (!client.connected())
      break;
  }
}

void handle_jpg(void)
{
  WiFiClient client = server.client();
  cam.run();
  if (!client.connected())
  {
    return;
  }
  String response = "HTTP/1.1 200 OK\r\n";
  response += "Content-disposition: inline; filename=snapshot.jpg\r\n";
  response += "Content-type: image/jpeg\r\n\r\n";
  server.sendContent(response);
  client.write((char *)cam.getfb(), cam.getSize());
  
}

void handle_root(void)
{
  
  String reply = F("<!doctype html><html><H1>ESP32CAM</H1>");

  reply += F("<p>Resolution: ");

  switch(RESOLUTION) {
    case FRAMESIZE_QVGA:
     reply += F("QVGA (320x240)");
    break;
    case FRAMESIZE_CIF:
     reply += F("CIF (400x296)");
    break;
    case FRAMESIZE_VGA:
     reply += F("VGA (640x480)");
    break;
    case FRAMESIZE_SVGA:
     reply += F("SVGA (800x600)");
    break;
    case FRAMESIZE_XGA:
     reply += F("XGA (1024x768)");
    break;
    case FRAMESIZE_SXGA:
     reply += F("SXGA (1280x1024)");
    break;
    case FRAMESIZE_UXGA:
     reply += F("UXGA (1600x1200)");
    break;
    default:
     reply += F("Unknown");
    break;
  }
  
  reply += F("<p>PSRAM found: ");
  if (psramFound()){
   reply += F("TRUE");
  } else {
   reply += F("FALSE");
  }
  String url = "http://" + WiFi.localIP().toString() + ":" + WSPORT + "/snapshot.jpg";
  reply += "<p>Snapshot URL:<br> <a href='" + url + "'>" + url + "</a>";
  url = "http://" + WiFi.localIP().toString() +":" + WSPORT + "/mjpg";
  reply += "<p>HTTP MJPEG URL:<br> <a href='" + url + "'>" + url + "</a>";
  url = "rtsp://" + WiFi.localIP().toString() + ":554/mjpeg/1";
  reply += "<p>RTSP MJPEG URL:<br> " + url;
  url = "http://" + WiFi.localIP().toString() +":" + WSPORT + "/_ac";
  reply += "<p>WiFi settings page:<br> <a href='" + url + "'>" + url + "</a>";

  reply += F("</body></html>");
  server.send(200, "text/html", reply);
}

void handleNotFound()
{
  String message = "Server is running!\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  server.send(200, "text/plain", message);
}

void setup(){

  pinMode(LED_BUILTIN, OUTPUT);       // pour LED
  digitalWrite(LED_BUILTIN, LOW);     // pour LED
  
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector 
  Serial.begin(115200);
  //  while (!Serial){;} // debug only
  camera_config_t cconfig;
  cconfig = esp32cam_aithinker_config;

  if (psramFound()) {
    cconfig.frame_size = RESOLUTION; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
    cconfig.jpeg_quality = QUALITY;
    cconfig.fb_count = 2;
  } else {
    if (RESOLUTION>FRAMESIZE_SVGA) {
     cconfig.frame_size = FRAMESIZE_SVGA;
    }
    cconfig.jpeg_quality = 12;
    cconfig.fb_count = 1;
  }

  cam.init(cconfig);

sensor_t * s = esp_camera_sensor_get();
  s->set_brightness(s, BRIGHT);
  s->set_contrast(s, CONTRAST);
  s->set_saturation(s, SATUR);
  s->set_special_effect(s, SPECIAL);
  s->set_whitebal(s, WHITEBAL);
  s->set_awb_gain(s, AWBGAIN);
  s->set_wb_mode(s, AWBMODE);
  s->set_exposure_ctrl(s, EXPOS);
  s->set_aec2(s, AEC2);
  s->set_ae_level(s, AELEV);
  s->set_aec_value(s, AECVAL);
  s->set_gain_ctrl(s, GAINCT);
  s->set_agc_gain(s, GAINAGC);
  s->set_gainceiling(s, (gainceiling_t)GAINCELL);
  s->set_bpc(s, BPC);
  s->set_wpc(s, WPC);
  s->set_raw_gma(s, RAWGMA);
  s->set_lenc(s, LENC);
  s->set_hmirror(s, MIRROR);
  s->set_vflip(s, FLIP);
  s->set_dcw(s, DCW);
  s->set_colorbar(s, CBAR);

  server.on("/", handle_root);
  server.on("/mjpg", HTTP_GET, handle_jpg_stream);
  server.on("/snapshot.jpg", HTTP_GET, handle_jpg);
  Portal.onNotFound(handleNotFound);
  acConfig.apid = "ESP-" + String((uint32_t)(ESP.getEfuseMac() >> 32), HEX);
  acConfig.psk = "configesp";
  acConfig.apip = IPAddress(192,168,4,1);
  acConfig.hostName = acConfig.apid;
  acConfig.autoReconnect = true;
  Portal.config(acConfig);
  Portal.begin();

  Serial.println(" ");
  Serial.println("Adresse IP: " + WiFi.localIP().toString());
  Serial.println(" ");

// POUR LED
serverasync.on("/relay/off", HTTP_ANY, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", "ok");
    digitalWrite(LED_BUILTIN, LOW);
    Serial.println("LED TURNED OFF");
  });
  
  serverasync.on("/relay/on", HTTP_ANY, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain","ok");
    digitalWrite(LED_BUILTIN, HIGH);
    Serial.println("LED TURNED ON");
  });
  
  serverasync.on("/relay/toggle", HTTP_ANY, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain","ok");
     digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
     Serial.println("LED TURNED TOGGLE");
  });
  
  serverasync.on("/relay", HTTP_GET, [](AsyncWebServerRequest *request){
     request->send(200, "text/plain", String(digitalRead(LED_BUILTIN)));
  });
  
  serverasync.begin();


#ifdef ENABLE_RTSPSERVER
  if (useRTSP) {
    rtspServer.begin();
    streamer = new OV2640Streamer(cam);             // our streamer for UDP/TCP based RTP transport
  }
#endif
}

void loop()
{
  //server.handleClient();
  Portal.handleClient();


  
#ifdef ENABLE_RTSPSERVER
  if (useRTSP) {
    uint32_t msecPerFrame = 100;
    static uint32_t lastimage = millis();

    // If we have an active client connection, just service that until gone
    streamer->handleRequests(0); // we don't use a timeout here,
    // instead we send only if we have new enough frames
    uint32_t now = millis();
    if (streamer->anySessions()) {
      if (now > lastimage + msecPerFrame || now < lastimage) { // handle clock rollover
        streamer->streamImage(now);
        lastimage = now;

        // check if we are overrunning our max frame rate
        now = millis();
        if (now > lastimage + msecPerFrame) {
          printf("warning exceeding max frame rate of %d ms\n", now - lastimage);
        }
      }
    }

    WiFiClient rtspClient = rtspServer.accept();
    if (rtspClient) {
      Serial.print("client: ");
      Serial.print(rtspClient.remoteIP());
      Serial.println();
      streamer->addSession(rtspClient);
    }
  }
#endif
}
1 « J'aime »

@drs

String ip = WiFi.localIP().toString();
String url = "http://" + ip + ":" + WSPORT + "/snapshot.jpg";
  reply += "<p>Snapshot URL:<br> <a href='" + url + "'>" + url + "</a>";
  url = "http://" + ip +":" + WSPORT + "/mjpg";
  reply += "<p>HTTP MJPEG URL:<br> <a href='" + url + "'>" + url + "</a>";
  url = "rtsp://" + ip + ":554/mjpeg/1";
  reply += "<p>RTSP MJPEG URL:<br> " + url;
  url = "http://" + ip +":" + WSPORT + "/_ac";
  reply += "<p>WiFi settings page:<br> <a href='" + url + "'>" + url + "</a>";

Attention Arduino c’est comme en C il faut faire attention a la portée des variables.
Selon l’endroit ou elles sont déclarée elle seront visible ou pas du reste du code
il y a une notions de golbal qui peut être ajouter lors de la déclaration.

en gros si tu déclare une variable a l’intérieur d’une fonction celle-ci ne sera visible que dans la fonction …

http://www.mon-club-elec.fr/pmwiki_reference_arduino/pmwiki.php?n=Main.PorteeVariables

OK, je pense que c’est pour cela que je ne m’en sortais pas. Mais je pense que cette variable ne peut pas être déclarée en global, car si je la déclare au début, vu que l’esp n’est pas encore connecté, il affiche 0.0.0.0.

Voici donc la version 1.4 :slight_smile:

//---------------------------------------------------------------------------------------------------------------------
// DOCS UTILES:
// ------------
// SERVEUR WEB CAM: https://community.jeedom.com/t/tuto-camera-a-focale-fixe-basee-sur-esp32/17587/49
// LED WIFI: https://techtutorialsx.com/2018/02/03/esp32-arduino-async-server-controlling-http-methods-allowed/
// Installing Asyncwebserver: https://techtutorialsx.com/2017/12/01/esp32-arduino-asynchronous-http-webserver/
// IMAGE PARAMS: https://randomnerdtutorials.com/esp32-cam-ov2640-camera-settings/
//
// modified by DRS - Version 1.4 - 16 Mai 2020
//
// PARAMETRES A MODIFIER:
// ----------------------
// RESOLUTION: FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA / QUALITY (10-63)
// WSPORT: port  web (pour affichage images)
// ASYNCPORT: port AsyncWebServer (pour gestion LED)
// Paramètres image
//
// USAGE:
// ------
// http://ip-esp:WSPORT/                page d'accueil
// http://ip-esp:WSPORT/_ac             page de config
// http://ip-esp:WSPORT/mjpg:           stream
// http://ip-esp:WSPORT/snapshot.jpg    image
//
// GESTION DE LA LED:
// ------------------
// http://ip-esp:ASYNCPORT/relay           Etat de la led (format binaire)
// http://ip-esp:ASYNCPORT/relay/on        Allume la LED
// http://ip-esp:ASYNCPORT/relay/off       Eteint la LED
// http://ip-esp:ASYNCPORT/relay/toggle    Allume/Eteint la LED
//
// INTEGRATION JEEDOM:
// -------------------
// Plugin Camera:
// Laisser le type de camera sur "Aucun"
// Renseigner l'IP et le port (webserver)
// URL de snapshot:   /snapshot.jpg
// URL de flux:       /mjpg
//
// Script gestion led:
// Action/Default
// URL: voir ci-dessus
// Cocher "Pas d'erreurs"
// La réponse doit contenir: ok (en minuscule)
// Timeout: si besoin (pas nécessaire)
//
//---------------------------------------------------------------------------------------------------------------------
#include <WiFi.h>
#include <WebServer.h>
#include <ESPAsyncWebServer.h>  //permet la connexion simultanee pour la gestion de la LED
#include <WiFiClient.h>
#include <AutoConnect.h>        // Needs AutoConnect, PageBuilder libraries!
#include "soc/soc.h"            //disable brownout problems
#include "soc/rtc_cntl_reg.h"  //disable brownout problems
#include "esp_camera.h"        // Pas sur de l'utilité. A vérifier

#define ENABLE_RTSPSERVER
#define ENABLE_WEBSERVER
#define RESOLUTION  FRAMESIZE_XGA   // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
#define QUALITY        10           // JPEG quality 10-63 (lower means better quality)

// PARAMETRES IMAGE
#define BRIGHT    1           // Brightness: -2 to 2
#define CONTRAST  0           // Contrast: -2 to 2
#define SATUR     0           // Color Saturation: -2 to 2
#define SPECIAL   0           // Special effects: 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
#define WHITEBAL  1           // White Balance: 0 = disable , 1 = enable
#define AWBGAIN   1           // White Balance Gain: 0 = disable , 1 = enable
#define AWBMODE   3           // White Balance Mode: 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
#define EXPOS     1           // Exposure Control: 0 = disable , 1 = enable
#define AEC2      0           // 0 = disable , 1 = enable
#define AELEV     0           // -2 to 2
#define AECVAL    300         // 0 to 1200
#define GAINCT    1           // 0 = disable , 1 = enable
#define GAINAGC   0           // 0 = disable , 1 = enable
#define GAINCELL  0           // 0 = disable , 1 = enable
#define BPC       0           // 0 = disable , 1 = enable
#define WPC       1           // 0 = disable , 1 = enable
#define RAWGMA    1           // 0 = disable , 1 = enable
#define LENC      1           // Lens Correction: 0 = disable , 1 = enable
#define MIRROR    0           // Horizontal Mirror: 0 = disable , 1 = enable
#define FLIP      0           // Vertical Flip: 0 = disable , 1 = enable
#define DCW       1           // 0 = disable , 1 = enable
#define CBAR      0           // Set a colorBar: 0 = disable , 1 = enable

#define LED_BUILTIN 4         // VA SERVIR POUR ALLUMER et ETEINDRE LA LED - NE PAS MODIFIER CETTE VALEUR (GPIO4)

#include "OV2640.h"
#ifdef ENABLE_RTSPSERVER
 #include "OV2640Streamer.h"
 #include "CRtspSession.h"
#endif

OV2640 cam;
boolean useRTSP = true;

#define WSPORT  80                // modifier le port pour Webserver Image
#define ASYNCPORT  81             // modifier le port pour Webserver LED
WebServer server(WSPORT); 
AsyncWebServer serverasync(ASYNCPORT);
AutoConnect Portal(server);
AutoConnectConfig acConfig;



#ifdef ENABLE_RTSPSERVER
WiFiServer rtspServer(554);
CStreamer *streamer;
#endif



void handle_jpg_stream(void)
{
  WiFiClient client = server.client();
  String response = "HTTP/1.1 200 OK\r\n";
  response += "Content-Type: multipart/x-mixed-replace; boundary=frame\r\n\r\n";
  server.sendContent(response);

  while (1)
  {
    cam.run();
    if (!client.connected())
      break;
    response = "--frame\r\n";
    response += "Content-Type: image/jpeg\r\n\r\n";
    server.sendContent(response);

    client.write((char *)cam.getfb(), cam.getSize());
    server.sendContent("\r\n");
    if (!client.connected())
      break;
  }
}

void handle_jpg(void)
{
  WiFiClient client = server.client();
  cam.run();
  if (!client.connected())
  {
    return;
  }
  String response = "HTTP/1.1 200 OK\r\n";
  response += "Content-disposition: inline; filename=snapshot.jpg\r\n";
  response += "Content-type: image/jpeg\r\n\r\n";
  server.sendContent(response);
  client.write((char *)cam.getfb(), cam.getSize());
  
}

void handle_root(void)
{
  
  String reply = F("<!doctype html><html><H1>ESP32CAM</H1>");

  reply += F("<p>Resolution: ");

  switch(RESOLUTION) {
    case FRAMESIZE_QVGA:
     reply += F("QVGA (320x240)");
    break;
    case FRAMESIZE_CIF:
     reply += F("CIF (400x296)");
    break;
    case FRAMESIZE_VGA:
     reply += F("VGA (640x480)");
    break;
    case FRAMESIZE_SVGA:
     reply += F("SVGA (800x600)");
    break;
    case FRAMESIZE_XGA:
     reply += F("XGA (1024x768)");
    break;
    case FRAMESIZE_SXGA:
     reply += F("SXGA (1280x1024)");
    break;
    case FRAMESIZE_UXGA:
     reply += F("UXGA (1600x1200)");
    break;
    default:
     reply += F("Unknown");
    break;
  }
  
  reply += F("<p>PSRAM found: ");
  if (psramFound()){
   reply += F("TRUE");
  } else {
   reply += F("FALSE");
  }
  String espip = WiFi.localIP().toString();
  String url = "http://" + espip + ":" + WSPORT + "/snapshot.jpg";
  reply += "<p>Snapshot URL:<br> <a href='" + url + "'>" + url + "</a>";
  url = "http://" + espip +":" + WSPORT + "/mjpg";
  reply += "<p>HTTP MJPEG URL:<br> <a href='" + url + "'>" + url + "</a>";
  url = "rtsp://" + espip + ":554/mjpeg/1";
  reply += "<p>RTSP MJPEG URL:<br> " + url;
  url = "http://" + espip +":" + WSPORT + "/_ac";
  reply += "<p>WiFi settings page:<br> <a href='" + url + "'>" + url + "</a>";

  reply += F("</body></html>");
  server.send(200, "text/html", reply);
}

void handleNotFound()
{
  String message = "Server is running!\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  server.send(200, "text/plain", message);
}

void setup(){

  pinMode(LED_BUILTIN, OUTPUT);       // pour LED
  digitalWrite(LED_BUILTIN, LOW);     // pour LED
  
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector 
  Serial.begin(115200);
  //  while (!Serial){;} // debug only
  camera_config_t cconfig;
  cconfig = esp32cam_aithinker_config;

  if (psramFound()) {
    cconfig.frame_size = RESOLUTION; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
    cconfig.jpeg_quality = QUALITY;
    cconfig.fb_count = 2;
  } else {
    if (RESOLUTION>FRAMESIZE_SVGA) {
     cconfig.frame_size = FRAMESIZE_SVGA;
    }
    cconfig.jpeg_quality = 12;
    cconfig.fb_count = 1;
  }

  cam.init(cconfig);

sensor_t * s = esp_camera_sensor_get();
  s->set_brightness(s, BRIGHT);
  s->set_contrast(s, CONTRAST);
  s->set_saturation(s, SATUR);
  s->set_special_effect(s, SPECIAL);
  s->set_whitebal(s, WHITEBAL);
  s->set_awb_gain(s, AWBGAIN);
  s->set_wb_mode(s, AWBMODE);
  s->set_exposure_ctrl(s, EXPOS);
  s->set_aec2(s, AEC2);
  s->set_ae_level(s, AELEV);
  s->set_aec_value(s, AECVAL);
  s->set_gain_ctrl(s, GAINCT);
  s->set_agc_gain(s, GAINAGC);
  s->set_gainceiling(s, (gainceiling_t)GAINCELL);
  s->set_bpc(s, BPC);
  s->set_wpc(s, WPC);
  s->set_raw_gma(s, RAWGMA);
  s->set_lenc(s, LENC);
  s->set_hmirror(s, MIRROR);
  s->set_vflip(s, FLIP);
  s->set_dcw(s, DCW);
  s->set_colorbar(s, CBAR);

  server.on("/", handle_root);
  server.on("/mjpg", HTTP_GET, handle_jpg_stream);
  server.on("/snapshot.jpg", HTTP_GET, handle_jpg);
  Portal.onNotFound(handleNotFound);
  acConfig.apid = "ESP-" + String((uint32_t)(ESP.getEfuseMac() >> 32), HEX);
  acConfig.psk = "configesp";
  acConfig.apip = IPAddress(192,168,4,1);
  acConfig.hostName = acConfig.apid;
  acConfig.autoReconnect = true;
  Portal.config(acConfig);
  Portal.begin();

  Serial.println(" ");
  Serial.println("Adresse IP: " + WiFi.localIP().toString());
  Serial.println(" ");


// POUR LED
serverasync.on("/relay/off", HTTP_ANY, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", "ok");
    digitalWrite(LED_BUILTIN, LOW);
    Serial.println("LED TURNED OFF");
  });
  
  serverasync.on("/relay/on", HTTP_ANY, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain","ok");
    digitalWrite(LED_BUILTIN, HIGH);
    Serial.println("LED TURNED ON");
  });
  
  serverasync.on("/relay/toggle", HTTP_ANY, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain","ok");
     digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
     Serial.println("LED TOGGLE");
  });
  
  serverasync.on("/relay", HTTP_GET, [](AsyncWebServerRequest *request){
     request->send(200, "text/plain", String(digitalRead(LED_BUILTIN)));
  });
  
  serverasync.begin();


#ifdef ENABLE_RTSPSERVER
  if (useRTSP) {
    rtspServer.begin();
    streamer = new OV2640Streamer(cam);             // our streamer for UDP/TCP based RTP transport
  }
#endif
}

void loop()
{
  //server.handleClient();
  Portal.handleClient();


  
#ifdef ENABLE_RTSPSERVER
  if (useRTSP) {
    uint32_t msecPerFrame = 100;
    static uint32_t lastimage = millis();

    // If we have an active client connection, just service that until gone
    streamer->handleRequests(0); // we don't use a timeout here,
    // instead we send only if we have new enough frames
    uint32_t now = millis();
    if (streamer->anySessions()) {
      if (now > lastimage + msecPerFrame || now < lastimage) { // handle clock rollover
        streamer->streamImage(now);
        lastimage = now;

        // check if we are overrunning our max frame rate
        now = millis();
        if (now > lastimage + msecPerFrame) {
          printf("warning exceeding max frame rate of %d ms\n", now - lastimage);
        }
      }
    }

    WiFiClient rtspClient = rtspServer.accept();
    if (rtspClient) {
      Serial.print("client: ");
      Serial.print(rtspClient.remoteIP());
      Serial.println();
      streamer->addSession(rtspClient);
    }
  }
#endif
}

merci beaucoup pour ce taff très intéressant ! super idée l’horodatage

si je peux me permettre de proposer des nouvelles fonctionnalitées ? :

  • possibilité de changer la resolution+qualité depuis webserver (surement necessiterais de faire un soft reboot)
    ça éviterais de devoir reflasher
  • pouvoir activer/desactiver séparemment les services de snapshot/RTSP/HTTP Mjpeg (perso le http mjpeg je l’utilise pas et sohaiterais garder les ressources pour le RTSP notamment qui chez moi est pas super fluide)

je comprends parfaitement si trop embettant/pas le temps, perso je suis pas codeur du tout :slight_smile:

merci encore pour ton code

Tu peux déclarer la variable - c’est à dire en fait réserver une place dans la mémoire - avec String ip; dans la partie globale, puis lui affecter une valeur plus loin avec ip = WiFi.localIP().toString();.

Oui tu peux :slight_smile:
tes idées sont super, mais moi non plus je n’y connais rien, donc difficile pour moi de faire cela.

oui j’ai vu ça. Mais à quoi sert de réserver la place avant? Au cas où il n’y aurait plus assez de mémoire par la suite pour stocker la variable?

ok pas de soucis je comprends, j’ai hate de voir la version finalisée

Bon vous m’avez donner envie, j’ai craqué j’ai commander une ESP-CAM et je compte bien mettre mon nez dans le code je vais tester ça en MicroPython !

1 « J'aime »