Puerta automática para gallinero

Lo puse y esto es lo que arroja.

Arduino:1.8.18 (Windows 10), Tarjeta:"AI Thinker ESP32-CAM, 240MHz (WiFi/BT), QIO, 80MHz"
gallinero_bueno:9:1: error: 'config' does not name a type
config.server_port = 85;
Se encontraron varias bibliotecas para "WiFi.h"
Usado: C:\Users\insec\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\WiFi
No usado: C:\Program Files (x86)\Arduino\libraries\WiFi
exit status 1
'config' does not name a type
config lo declaras dentro de startCameraServer(), de hecho, ahí tienes la línea config.server_port = 80; la cual es la que debes modificar, si lo pones en cualquier otro lado por supuesto que dará error ya que no existe en ninguna otra parte, normalmente tenías que declararlo fuera de cualquier subrutina al crear el objeto para evitar ese conflicto.

También te recomendaría crear un archivo .h para almacenar las contraseñas, usuarios y ssid y usar #include para importarlas para evitar publicarlas con el resto del código, por ejemplo, esto lo guardas como accesos.h
C:
#ifndef ACCESOS_H_
#define ACCESOS_H_

const char* ssid = "La red";
const char* password = "La contraseña";

#endif
Y ya en el código del Arduino solo pones #include "accesos.h" así nos puedes compartir el código si requieres más asistencia sin poner las contraseñas visibles, aparte de que las tienes más fácil de encontrar cuando necesites editarlas.
 
Última edición:
Ahora tengo un problemilla, ya está colocado y funcionando pero el proveedor de internet no quiere abrir el puerto 80 para el esp32cam,
Me dice que le cambie el puerto http y eso ya no se como, he buscado por ahí y no vi nada que yo entienda.
Alguien sabría que hay que añadir o cambiar??, Agradecería la ayuda.
Este es el codigo
/*
ESP32-CAM
*/
const char* ssid = "COCHERA";
const char* password = "12051205";

// Set your Static IP address
IPAddress local_IP(192, 168, 10, 184);
// Set your Gateway IP address
IPAddress gateway(192, 168, 10, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);
IPAddress secondaryDNS(8, 8, 4, 4);




#include <WebServer.h>
#include "esp_wifi.h"
#include "esp_camera.h"
#include <WiFi.h>
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"

//
// WARNING!!! Make sure that you have either selected ESP32 Wrover Module,
// or another board which has PSRAM enabled
//

// Select camera model
//#define CAMERA_MODEL_WROVER_KIT
//#define CAMERA_MODEL_M5STACK_PSRAM
#define CAMERA_MODEL_AI_THINKER

#if defined(CAMERA_MODEL_WROVER_KIT)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 21
#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 19
#define Y4_GPIO_NUM 18
#define Y3_GPIO_NUM 5
#define Y2_GPIO_NUM 4
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22

#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23

#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21

#elif defined(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

#else
#error "Camera model not selected"
#endif

void startCameraServer();

const int MotPin0 = 12;
const int MotPin1 = 13;
const int MotPin2 = 14;
const int MotPin3 = 15;

void initMotors()
{
ledcSetup(3, 2000, 8); // 2000 hz PWM, 8-bit resolution
ledcSetup(4, 2000, 8); // 2000 hz PWM, 8-bit resolution
ledcSetup(5, 2000, 8); // 2000 hz PWM, 8-bit resolution
ledcSetup(6, 2000, 8); // 2000 hz PWM, 8-bit resolution
ledcAttachPin(MotPin0, 3);
ledcAttachPin(MotPin1, 4);
ledcAttachPin(MotPin2, 5);
ledcAttachPin(MotPin3, 6);
}

const int ServoPin = 2;
void initServo()
{
ledcSetup(8, 50, 16); // 50 hz PWM, 16-bit resolution, range from 3250 to 6500.
ledcAttachPin(ServoPin, 8);
}

void setup()
{
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // prevent brownouts by silencing them

Serial.begin(115200);
Serial.setDebugOutput(true);
Serial.println();

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;
//init with high specs to pre-allocate larger buffers
if(psramFound()){
config.frame_size = FRAMESIZE_QVGA;
config.jpeg_quality = 10;
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_QVGA;
config.jpeg_quality = 12;
config.fb_count = 1;
}

// camera init
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}

//drop down frame size for higher initial frame rate
sensor_t * s = esp_camera_sensor_get();
s->set_framesize(s, FRAMESIZE_QVGA);
s->set_vflip(s, 1);
s->set_hmirror(s, 1);

// Remote Control Car
initMotors();
initServo();

ledcSetup(7, 5000, 8);
ledcAttachPin(4, 7); //pin4 is LED

Serial.println("ssid: " + (String)ssid);
Serial.println("password: " + (String)password);

WiFi.begin(ssid, password);
delay(500);

long int StartTime=millis();
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
if ((StartTime+10000) < millis()) break;
}

/*
int8_t power;
esp_wifi_set_max_tx_power(20);
esp_wifi_get_max_tx_power(&power);
Serial.printf("wifi power: %d \n",power);
*/

startCameraServer();

if(!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
Serial.println("STA Failed to configure");
}
WiFi.begin(ssid, password);





if (WiFi.status() == WL_CONNECTED)
{
Serial.println("");
Serial.println("WiFi connected");
Serial.print("Camera Ready! Use 'http://");
Serial.print(WiFi.localIP());
Serial.println("' to connect");
} else {
Serial.println("");
Serial.println("WiFi disconnected");
Serial.print("Camera Ready! Use 'http://");
Serial.print(WiFi.softAPIP());
Serial.println("' to connect");
char* apssid = "ESP32-CAM";
char* appassword = "12345678"; //AP password require at least 8 characters.
WiFi.softAP((WiFi.softAPIP().toString()+"_"+(String)apssid).c_str(), appassword);
}

for (int i=0;i<5;i++)
{
ledcWrite(7,10); // flash led
delay(50);
ledcWrite(7,0);
delay(50);
}
}

void loop() {
// put your main code here, to run repeatedly:
delay(1000);
Serial.printf("RSSi: %ld dBm\n",WiFi.RSSI());
}

A esta altura del asunto voy sospechando que todo este código, no lo has escrito tu sino que has copiado y pegado.

Es muy difícil sino imposible, que tu ISP te abra el puerto 80, porque es el que usa la WEB de tu ROUTER !!! :ROFLMAO: :ROFLMAO: :ROFLMAO:
En esos casos, el puerto que DEBES usar es el 8080 y NO tienes que abrirlo porque generalmente está disponible.

Si estás en una red local y tu CÁMARA ( con servidor WEB incluido) está en ella, Debes hacer varias cosas.

1- Decirle a la CÁMARA en que puerto va a atender al cliente , supongamos el --> 8080
2- Poner le una IP LOCAL PRIVADA FIJA a la cámara. Si usamos la 192.168. 0. X por ejemplo, tratar de ponerle de 0.150 o superior por ejemplo 192.168.0.180
3- Luego, tienes que ENTRAR a TU ROUTER (usuario y clave) (por el puerto 80) y decirle en el apartado correspondiente que en 192.168.0.180 hay un usuario con IP fina y que la señal va a pasar de largo hacia afuera con MDZ (para control de cámara)
4- Luego la convocas localmente con http://192.168.0.180:8080/ y deberia aparecer en tu PC local la página web de tu cámara.
5 -Para uso externo, en el router debes ir al sector donde se declara un DDNS y rellenar ese formulario con el DDNS de la cámara, para que cuando arranque el router apunte a ese servidor de DDNS para FIJAR la IP PUBLICA del ROUTER para que los clientes del mundo, puedan ENCONTRAR tu cámara.
6- Podria ser que tu cámara tenga un registro de DDNS, en cuyo caso no haria falta entrar en en el DDNS de tu router, pues ese registro se suele usar cuando quieres acceder al router desde el exterior, cosa que NO se recomienda hacer.

La página de tu cámara es del tipo http: porque el código que usas ya es viejo.
Actualmente esa página debería tener mas seguridades y ser del tipo https :
Creo que este aspecto se define en los módulos tipo ---> #include "esp_http_server.h"

Saludos
 
Última edición:
Es muy difícil sino imposible, que tu ISP te abra el puerto 80, porque es el que usa la WEB de tu ROUTER !!! :ROFLMAO: :ROFLMAO: :ROFLMAO:
En esos casos, el puerto que DEBES usar es el 8080 y NO tienes que abrirlo porque generalmente está disponible.
Habría que ver la configuración del router primero, algunos al habilitar la redirección de puerto automáticamente pasan al 8080 para la gestión por WAN, no es cosa de que no se tenga que abrir el puerto, sino que en LAN le funcionará, pero en el router DEBE configurar el redireccionamiento para que este sepa que cuando recibe una solicitud de WAN al puerto X esta debe pasar al dispositivo Y en lugar de intentar procesarlo por sí mismo.
 
Habría que ver la configuración del router primero, algunos al habilitar la redirección de puerto automáticamente pasan al 8080 para la gestión por WAN, no es cosa de que no se tenga que abrir el puerto, sino que en LAN le funcionará, pero en el router DEBE configurar el redireccionamiento para que este sepa que cuando recibe una solicitud de WAN al puerto X esta debe pasar al dispositivo Y en lugar de intentar procesarlo por sí mismo.

Nunca dije que yo escribí el código, Si lo hubiese hecho sabría lo que vosotros y no estaría preguntando. El diseño mío solo ha sido la electrónica convencional externa.
 
Nunca dije que yo escribí el código, Si lo hubiese hecho sabría lo que vosotros y no estaría preguntando. El diseño mío solo ha sido la electrónica convencional externa.
Disculpa, no encuentro la relación al comentario citado. Lo que indiqué fue para evitar la confusión y saltar un paso necesario, eso es un ajuste del router/modem no relacionado a la programación de la cual fue la consulta original.
 
Voy a intentar explicarme de nuevo porque seguramente no he expuesto el tema bien.
Con el tema de redes no tengo problemas aunque no sea experto, se como se abren puertos, se lo que es el DMZ, y demás.
El problema es que el proveedor de internet donde va a estar el esp32cam, yo no tengo acceso al router y dependo del proveedor, tiene cerrado en su red el puerto 80, por eso la necesidad de ponerle un puerto diferente al esp32cam.
Como Visteis ya está probado y funcionando con con un router que si tengo acceso pero con ip dinamica, por eso lo del ddns., que es provisional para testear.
Donde va ha estar tendra ip fija y no pueden habilitar DMZ por tener ya otros puertos abiertos para otros sistemas, si abrir el puero elegido para la cam.
Solo es la necesidad de en lugar del 80 que sea otro, lo que se vea en el codigo ssid y pass, me es indiferente.
He buscado en los ficheros de codigo y no he encontrado nada referente al puerto 80.
app_httpd.cpp, es donde está el codigo html y es el fichero que se incluye en el id de arduino, así funciona.
Espero me hayáis entendido.
Perdonad por coñazo y Gracias.
 
Ok, tomando el ultimo código que pusiste
C++:
/*
ESP32-CAM
*/
const char *ssid = "COCHERA";
const char *password = "12051205";

// Set your Static IP address
IPAddress local_IP(192, 168, 10, 184);
// Set your Gateway IP address
IPAddress gateway(192, 168, 10, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);
IPAddress secondaryDNS(8, 8, 4, 4);

#include <WebServer.h>
#include "esp_wifi.h"
#include "esp_camera.h"
#include <WiFi.h>
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"

//
// WARNING!!! Make sure that you have either selected ESP32 Wrover Module,
// or another board which has PSRAM enabled
//

// Select camera model
// #define CAMERA_MODEL_WROVER_KIT
// #define CAMERA_MODEL_M5STACK_PSRAM
#define CAMERA_MODEL_AI_THINKER

#if defined(CAMERA_MODEL_WROVER_KIT)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 21
#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 19
#define Y4_GPIO_NUM 18
#define Y3_GPIO_NUM 5
#define Y2_GPIO_NUM 4
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22

#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23

#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21

#elif defined(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

#else
#error "Camera model not selected"
#endif

void startCameraServer();

const int MotPin0 = 12;
const int MotPin1 = 13;
const int MotPin2 = 14;
const int MotPin3 = 15;

void initMotors()
{
    ledcSetup(3, 2000, 8); // 2000 hz PWM, 8-bit resolution
    ledcSetup(4, 2000, 8); // 2000 hz PWM, 8-bit resolution
    ledcSetup(5, 2000, 8); // 2000 hz PWM, 8-bit resolution
    ledcSetup(6, 2000, 8); // 2000 hz PWM, 8-bit resolution
    ledcAttachPin(MotPin0, 3);
    ledcAttachPin(MotPin1, 4);
    ledcAttachPin(MotPin2, 5);
    ledcAttachPin(MotPin3, 6);
}

const int ServoPin = 2;
void initServo()
{
    ledcSetup(8, 50, 16); // 50 hz PWM, 16-bit resolution, range from 3250 to 6500.
    ledcAttachPin(ServoPin, 8);
}

void setup()
{
    WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // prevent brownouts by silencing them

    Serial.begin(115200);
    Serial.setDebugOutput(true);
    Serial.println();

    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;
    // init with high specs to pre-allocate larger buffers
    if (psramFound())
    {
        config.frame_size = FRAMESIZE_QVGA;
        config.jpeg_quality = 10;
        config.fb_count = 2;
    }
    else
    {
        config.frame_size = FRAMESIZE_QVGA;
        config.jpeg_quality = 12;
        config.fb_count = 1;
    }

    // camera init
    esp_err_t err = esp_camera_init(&config);
    if (err != ESP_OK)
    {
        Serial.printf("Camera init failed with error 0x%x", err);
        return;
    }

    // drop down frame size for higher initial frame rate
    sensor_t *s = esp_camera_sensor_get();
    s->set_framesize(s, FRAMESIZE_QVGA);
    s->set_vflip(s, 1);
    s->set_hmirror(s, 1);

    // Remote Control Car
    initMotors();
    initServo();

    ledcSetup(7, 5000, 8);
    ledcAttachPin(4, 7); // pin4 is LED

    Serial.println("ssid: " + (String)ssid);
    Serial.println("password: " + (String)password);

    WiFi.begin(ssid, password);
    delay(500);

    long int StartTime = millis();
    while (WiFi.status() != WL_CONNECTED)
    {
        delay(500);
        if ((StartTime + 10000) < millis())
            break;
    }

    /*
    int8_t power;
    esp_wifi_set_max_tx_power(20);
    esp_wifi_get_max_tx_power(&power);
    Serial.printf("wifi power: %d \n",power);
    */

    startCameraServer();

    if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS))
    {
        Serial.println("STA Failed to configure");
    }
    WiFi.begin(ssid, password);

    if (WiFi.status() == WL_CONNECTED)
    {
        Serial.println("");
        Serial.println("WiFi connected");
        Serial.print("Camera Ready! Use 'http://");
        Serial.print(WiFi.localIP());
        Serial.println("' to connect");
    }
    else
    {
        Serial.println("");
        Serial.println("WiFi disconnected");
        Serial.print("Camera Ready! Use 'http://");
        Serial.print(WiFi.softAPIP());
        Serial.println("' to connect");
        char *apssid = "ESP32-CAM";
        char *appassword = "12345678"; // AP password require at least 8 characters.
        WiFi.softAP((WiFi.softAPIP().toString() + "_" + (String)apssid).c_str(), appassword);
    }

    for (int i = 0; i < 5; i++)
    {
        ledcWrite(7, 10); // flash led
        delay(50);
        ledcWrite(7, 0);
        delay(50);
    }
}

void loop()
{
    // put your main code here, to run repeatedly:
    delay(1000);
    Serial.printf("RSSi: %ld dBm\n", WiFi.RSSI());
}

En la linea 93 tienes un prototipo declarado como:
void startCameraServer();
Por favor revísalo, no sé si se perdió al no usar la etiqueta CODE o si está en un archivo aparte, pero probablemente sea donde se declara el puerto, posiblemente esté en "soc/soc.h", si es el IDE 2, presiona la tecla Control y da clic sobre dicha función para que se abra la declaración de la misma.
La linea que debes buscar debe tener algo como WebServer un_nombre_cualquiera(80);


Cuando adjuntes el código en el editor da clic a esta opción
1690957327258.png

Luego elije C++ para tu código Arduino, de lo contrario puede causar perdida del formato y todo termina raro.
 
Última edición:
Si encuentro esto, void startCameraServer(); en la linea 111, no se como abrir el fichero soc/soc.h, debería aparecer en las pestañas del arduino?
solo hay una pestaña y es, app_httpd.cpp.
Si encuentro esto, void startCameraServer(); en la linea 111, no se como abrir el fichero soc/soc.h, debería aparecer en las pestañas del arduino?
solo hay una pestaña y es, app_httpd.cpp.
C++:
#include "dl_lib_matrix3d.h"

#include <esp32-hal-ledc.h>

int speed = 255;

int noStop = 0;



#include "esp_http_server.h"

#include "esp_timer.h"

#include "esp_camera.h"

#include "img_converters.h"

#include "Arduino.h"


//#include "dl_lib.h"


typedef struct {

        httpd_req_t *req;

        size_t len;

} jpg_chunking_t;


#define PART_BOUNDARY "123456789000000000000987654321"

static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;

static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";

static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n";


httpd_handle_t stream_httpd = NULL;

httpd_handle_t camera_httpd = NULL;


static size_t jpg_encode_stream(void * arg, size_t index, const void* data, size_t len){

    jpg_chunking_t *j = (jpg_chunking_t *)arg;

    if(!index){

        j->len = 0;

    }

    if(httpd_resp_send_chunk(j->req, (const char *)data, len) != ESP_OK){

        return 0;

    }

    j->len += len;

    return len;

}


static esp_err_t capture_handler(httpd_req_t *req){

    camera_fb_t * fb = NULL;

    esp_err_t res = ESP_OK;

    int64_t fr_start = esp_timer_get_time();


    fb = esp_camera_fb_get();

    if (!fb) {

        Serial.println("Camera capture failed");

        httpd_resp_send_500(req);

        return ESP_FAIL;

    }


    httpd_resp_set_type(req, "image/jpeg");

    httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg");


    size_t out_len, out_width, out_height;

    uint8_t * out_buf;

    bool s;

    {

        size_t fb_len = 0;

        if(fb->format == PIXFORMAT_JPEG){

            fb_len = fb->len;

            res = httpd_resp_send(req, (const char *)fb->buf, fb->len);

        } else {

            jpg_chunking_t jchunk = {req, 0};

            res = frame2jpg_cb(fb, 80, jpg_encode_stream, &jchunk)?ESP_OK:ESP_FAIL;

            httpd_resp_send_chunk(req, NULL, 0);

            fb_len = jchunk.len;

        }

        esp_camera_fb_return(fb);

        int64_t fr_end = esp_timer_get_time();

        Serial.printf("JPG: %uB %ums\n", (uint32_t)(fb_len), (uint32_t)((fr_end - fr_start)/1000));

        return res;

    }


    dl_matrix3du_t *image_matrix = dl_matrix3du_alloc(1, fb->width, fb->height, 3);

    if (!image_matrix) {

        esp_camera_fb_return(fb);

        Serial.println("dl_matrix3du_alloc failed");

        httpd_resp_send_500(req);

        return ESP_FAIL;

    }


    out_buf = image_matrix->item;

    out_len = fb->width * fb->height * 3;

    out_width = fb->width;

    out_height = fb->height;


    s = fmt2rgb888(fb->buf, fb->len, fb->format, out_buf);

    esp_camera_fb_return(fb);

    if(!s){

        dl_matrix3du_free(image_matrix);

        Serial.println("to rgb888 failed");

        httpd_resp_send_500(req);

        return ESP_FAIL;

    }


    jpg_chunking_t jchunk = {req, 0};

    s = fmt2jpg_cb(out_buf, out_len, out_width, out_height, PIXFORMAT_RGB888, 90, jpg_encode_stream, &jchunk);

    dl_matrix3du_free(image_matrix);

    if(!s){

        Serial.println("JPEG compression failed");

        return ESP_FAIL;

    }


    int64_t fr_end = esp_timer_get_time();

    return res;

}


static esp_err_t stream_handler(httpd_req_t *req){

    camera_fb_t * fb = NULL;

    esp_err_t res = ESP_OK;

    size_t _jpg_buf_len = 0;

    uint8_t * _jpg_buf = NULL;

    char * part_buf[64];

    dl_matrix3du_t *image_matrix = NULL;


    static int64_t last_frame = 0;

    if(!last_frame) {

        last_frame = esp_timer_get_time();

    }


    res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE);

    if(res != ESP_OK){

        return res;

    }


    while(true){

        fb = esp_camera_fb_get();

        if (!fb) {

            Serial.println("Camera capture failed");

            res = ESP_FAIL;

        } else {

             {

                if(fb->format != PIXFORMAT_JPEG){

                    bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len);

                    esp_camera_fb_return(fb);

                    fb = NULL;

                    if(!jpeg_converted){

                        Serial.println("JPEG compression failed");

                        res = ESP_FAIL;

                    }

                } else {

                    _jpg_buf_len = fb->len;

                    _jpg_buf = fb->buf;

                }

            }

        }

        if(res == ESP_OK){

            size_t hlen = snprintf((char *)part_buf, 64, _STREAM_PART, _jpg_buf_len);

            res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen);

        }

        if(res == ESP_OK){

            res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len);

        }

        if(res == ESP_OK){

            res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));

        }

        if(fb){

            esp_camera_fb_return(fb);

            fb = NULL;

            _jpg_buf = NULL;

        } else if(_jpg_buf){

            free(_jpg_buf);

            _jpg_buf = NULL;

        }

        if(res != ESP_OK){

            break;

        }

        int64_t fr_end = esp_timer_get_time();

        int64_t frame_time = fr_end - last_frame;

        last_frame = fr_end;

        frame_time /= 1000;

        Serial.printf("MJPG: %uB %ums (%.1ffps)\n",

            (uint32_t)(_jpg_buf_len),

            (uint32_t)frame_time, 1000.0 / (uint32_t)frame_time         

        );

    }


    last_frame = 0;

    return res;

}


enum state {fwd,rev,stp};

state actstate = stp;


static esp_err_t cmd_handler(httpd_req_t *req)

{

    char*  buf;

    size_t buf_len;

    char variable[32] = {0,};

    char value[32] = {0,};


    buf_len = httpd_req_get_url_query_len(req) + 1;

    if (buf_len > 1) {

        buf = (char*)malloc(buf_len);

        if(!buf){

            httpd_resp_send_500(req);

            return ESP_FAIL;

        }

        if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) {

            if (httpd_query_key_value(buf, "var", variable, sizeof(variable)) == ESP_OK &&

                httpd_query_key_value(buf, "val", value, sizeof(value)) == ESP_OK) {

            } else {

                free(buf);

                httpd_resp_send_404(req);

                return ESP_FAIL;

            }

        } else {

            free(buf);

            httpd_resp_send_404(req);

            return ESP_FAIL;

        }

        free(buf);

    } else {

        httpd_resp_send_404(req);

        return ESP_FAIL;

    }


    int val = atoi(value);

    sensor_t * s = esp_camera_sensor_get();

    int res = 0;

  

    if(!strcmp(variable, "framesize"))

    {

        Serial.println("framesize");

        if(s->pixformat == PIXFORMAT_JPEG) res = s->set_framesize(s, (framesize_t)val);

    }

    else if(!strcmp(variable, "quality"))

    {

      Serial.println("quality");

      res = s->set_quality(s, val);

    }

    //Remote Control Car

    //Don't use channel 1 and channel 2

    else if(!strcmp(variable, "flash"))

    {

      ledcWrite(7,val);

    }

    else if(!strcmp(variable, "speed"))

    {

      if      (val > 255) val = 255;

      else if (val <   0) val = 0;     

      speed = val;

    }   

    else if(!strcmp(variable, "nostop"))

    {

      noStop = val;

    }           

    else if(!strcmp(variable, "servo")) // 3250, 4875, 6500

    {

      if      (val > 650) val = 650;

      else if (val < 325) val = 325;     

      ledcWrite(8,10*val);

    }   

    else if(!strcmp(variable, "car")) {

      if (val==1) {

        Serial.println("Forward");

        actstate = fwd;   

        ledcWrite(4,speed);  // pin 12

        ledcWrite(3,0);      // pin 13

        ledcWrite(5,speed);  // pin 14

        ledcWrite(6,0);      // pin 15 

        delay(1000);

      }

      else if (val==2) {

        Serial.println("TurnLeft");

        ledcWrite(3,0);

        ledcWrite(5,0);

        //if      (actstate == fwd) { ledcWrite(4,speed); ledcWrite(6,    0); }

        //else if (actstate == rev) { ledcWrite(4,    0); ledcWrite(6,speed); }

        //else                      { ledcWrite(4,speed); ledcWrite(6,speed); }

        ledcWrite(4,speed);

        ledcWrite(6,speed);

            

        delay(1000);             

      }

      else if (val==3) {

        Serial.println("Stop");

        actstate = stp;     

        ledcWrite(4,0);

        ledcWrite(3,0);

        ledcWrite(5,0);   

        ledcWrite(6,0);

      }

      else if (val==4) {

        Serial.println("TurnRight");

        ledcWrite(4,0);

        ledcWrite(6,0);

        //if      (actstate == fwd) { ledcWrite(3,    0); ledcWrite(5,speed); }

        //else if (actstate == rev) { ledcWrite(3,speed); ledcWrite(5,    0); }

        //else                      { ledcWrite(3,speed); ledcWrite(5,speed); }

        ledcWrite(3,speed);

        ledcWrite(5,speed);

            

        delay(1000);             

      }

      else if (val==5) {

        Serial.println("Backward");

        actstate = rev;     

        ledcWrite(4,0);

        ledcWrite(3,speed);

        ledcWrite(5,0);

        ledcWrite(6,speed);

        delay(1000);             

      }

      if (noStop!=1)

      {

        ledcWrite(3, 0);

        ledcWrite(4, 0);

        ledcWrite(5, 0);

        ledcWrite(6, 0);

      }       

    }       

    else

    {

      Serial.println("variable");

      res = -1;

    }


    if(res){ return httpd_resp_send_500(req); }


    httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");

    return httpd_resp_send(req, NULL, 0);

}


static esp_err_t status_handler(httpd_req_t *req){

    static char json_response[1024];


    sensor_t * s = esp_camera_sensor_get();

    char * p = json_response;

    *p++ = '{';


    p+=sprintf(p, "\"framesize\":%u,", s->status.framesize);

    p+=sprintf(p, "\"quality\":%u,", s->status.quality);

    *p++ = '}';

    *p++ = 0;

    httpd_resp_set_type(req, "application/json");

    httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");

    return httpd_resp_send(req, json_response, strlen(json_response));

}


static const char PROGMEM INDEX_HTML[] = R"rawliteral(




<!doctype html>

<html>

    <head>

        <meta charset="utf-8">

        <meta name="viewport" content="width=device-width,initial-scale=1">

        <title>GALLINER LOS QUINTOS</title>

        <style>

          body{font-family:Arial,Helvetica,sans-serif;background:#181818;color:#EFEFEF;font-size:16px}h2{font-size:18px}section.main{display:flex}#menu,section.main{flex-direction:column}#menu{display:none;flex-wrap:nowrap;min-width:340px;background:#363636;padding:8px;border-radius:4px;margin-top:-10px;margin-right:10px}#content{display:flex;flex-wrap:wrap;align-items:stretch}figure{padding:0;margin:0;-webkit-margin-before:0;margin-block-start:0;-webkit-margin-after:0;margin-block-end:0;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:0;margin-inline-end:0}figure img{display:block;width:100%;height:auto;border-radius:4px;margin-top:8px}@media (min-width: 800px) and (orientation:landscape){#content{display:flex;flex-wrap:nowrap;align-items:stretch}figure img{display:block;max-width:100%;max-height:calc(100vh - 40px);width:auto;height:auto}figure{padding:0;margin:0;-webkit-margin-before:0;margin-block-start:0;-webkit-margin-after:0;margin-block-end:0;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:0;margin-inline-end:0}}section#buttons{display:flex;flex-wrap:nowrap;justify-content:space-between}#nav-toggle{cursorointer;display:block}#nav-toggle-cb{outline:0;opacity:0;width:0;height:0}#nav-toggle-cb:checked+#menu{display:flex}.input-group{display:flex;flex-wrap:nowrap;line-height:22px;margin:5px 0}.input-group>label{display:inline-block;padding-right:10px;min-width:47%}.input-group input,.input-group select{flex-grow:1}.range-max,.range-min{display:inline-block;padding:0 5px}button{display:block;margin:5px;padding:0 12px;border:0;line-height:28px;cursorointer;color:#fff;background:#ff3034;border-radius:5px;font-size:16px;outline:0}button:hover{background:#ff494d}button:active{background:#f21c21}button.disabled{cursor:default;background:#a0a0a0}input[type=range]{-webkit-appearance:none;width:100%;height:22px;background:#363636;cursorointer;margin:0}input[type=range]:focus{outline:0}input[type=range]::-webkit-slider-runnable-track{width:100%;height:2px;cursorointer;background:#EFEFEF;border-radius:0;border:0 solid #EFEFEF}input[type=range]::-webkit-slider-thumb{border:1px solid rgba(0,0,30,0);height:22px;width:22px;border-radius:50px;background:#ff3034;cursorointer;-webkit-appearance:none;margin-top:-11.5px}input[type=range]:focus::-webkit-slider-runnable-track{background:#EFEFEF}input[type=range]::-moz-range-track{width:100%;height:2px;cursorointer;background:#EFEFEF;border-radius:0;border:0 solid #EFEFEF}input[type=range]::-moz-range-thumb{border:1px solid rgba(0,0,30,0);height:22px;width:22px;border-radius:50px;background:#ff3034;cursorointer}input[type=range]::-ms-track{width:100%;height:2px;cursorointer;background:0 0;border-color:transparent;color:transparent}input[type=range]::-ms-fill-lower{background:#EFEFEF;border:0 solid #EFEFEF;border-radius:0}input[type=range]::-ms-fill-upper{background:#EFEFEF;border:0 solid #EFEFEF;border-radius:0}input[type=range]::-ms-thumb{border:1px solid rgba(0,0,30,0);height:22px;width:22px;border-radius:50px;background:#ff3034;cursorointer;height:2px}input[type=range]:focus::-ms-fill-lower{background:#EFEFEF}input[type=range]:focus::-ms-fill-upper{background:#363636}.switch{display:block;position:relative;line-height:22px;font-size:16px;height:22px}.switch input{outline:0;opacity:0;width:0;height:0}.slider{width:50px;height:22px;border-radius:22px;cursorointer;background-color:grey}.slider,.slider:before{display:inline-block;transition:.4s}.slider:before{position:relative;content:"";border-radius:50%;height:16px;width:16px;left:4px;top:3px;background-color:#fff}input:checked+.slider{background-color:#ff3034}input:checked+.slider:before{-webkit-transform:translateX(26px);transform:translateX(26px)}select{border:1px solid #363636;font-size:14px;height:22px;outline:0;border-radius:5px}.image-container{position:relative;min-width:160px}.close{position:absolute;right:5px;top:5px;background:#ff3034;width:16px;height:16px;border-radius:100px;color:#fff;text-align:center;line-height:18px;cursorointer}.hidden{display:none}

      

      

      

    </style>

    </head>

    <body>

    <figure>

      <div id="stream-container" class="image-container hidden">

        <div class="close" id="close-stream">×</div>

        <img id="stream" src="">

      </div>

    </figure>

  

  


        <font color="gren"

        <font size=5 >...GALLINERO ...</font>


  

  

  

    <section class="main">

            <section id="buttons">

                <table>

                <tr><td align="center"><button id="get-still">IMAGEN</button></

          

              

                <tr><td></td><td align="center"><button id="toggle-stream">CAMARA</button></

        

        <tr><td>

          <tr><td></td></tr>

              

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

         <tr><td></td><td align="center"><button id="forward" onclick="fetch(document.location.origin+'/control?var=car&val=1');">ABRE</button></td><td></td></tr>

        

         <tr><td></td></tr>

         <tr><td></td></tr>

         <tr><td></td></tr>

         <tr><td></td></tr>

         <tr><td></td></tr>

         <tr><td></td></tr>

         <tr><td></td></tr>

         <tr><td></td></tr>

              

                <tr><td></td><td align="center"><button id="backward" onclick="fetch(document.location.origin+'/control?var=car&val=5');">CIERRA</button></td><tr></td></tr></td><tr></tr></td><tr></tr></td><tr></tr></td><tr></td></tr></td><tr></tr></td><tr></tr></td><tr></tr>

              

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

            

              

              

              

                <tr><td>LUZ</td><td align="center" colspan="2"><input type="range" id="flash" min="0" max="255" value="0" onchange="try{fetch(document.location.origin+'/control?var=flash&val='+this.value);}catch(e){}"></td></tr><tr></td></tr></td><tr></tr></td><tr></tr></td><tr></tr></td><tr></td></tr></td><tr></tr></td><tr></tr></td><tr></tr>

                <tr><td></td></tr>

                <tr><td>CALIDAD</td><td align="center" colspan="2"><input type="range" id="quality" min="10" max="63" value="10" onchange="try{fetch(document.location.origin+'/control?var=quality&val='+this.value);}catch(e){}"></td></tr>

              

              

              

              

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

            

              

              

                </table>

              

          

          

            </section>       

        </section>

      

      

      

        <font color="#FFFFFF"

        <font size=2 ></font>

      

      

        <script>

          document.addEventListener('DOMContentLoaded',function(){function b(B){let C;switch(B.type){case'checkbox':C=B.checked?1:0;break;case'range':case'select-one':C=B.value;break;case'button':case'submit':C='1';break;default:return;}const D=`${c}/control?var=${B.id}&val=${C}`;fetch(D).then(E=>{console.log(`request to ${D} finished, status: ${E.status}`)})}var c=document.location.origin;const e=B=>{B.classList.add('hidden')},f=B=>{B.classList.remove('hidden')},g=B=>{B.classList.add('disabled'),B.disabled=!0},h=B=>{B.classList.remove('disabled'),B.disabled=!1},i=(B,C,D)=>{D=!(null!=D)||D;let E;'checkbox'===B.type?(E=B.checked,C=!!C,B.checked=C)E=B.value,B.value=C),D&&E!==C?b(B):!D&&('aec'===B.id?C?e(v):f(v):'agc'===B.id?C?(f(t),e(s))e(t),f(s)):'awb_gain'===B.id?C?f(x):e(x):'face_recognize'===B.id&&(C?h:g))};document.querySelectorAll('.close').forEach(B=>{B.onclick=()=>{e(B.parentNode)}}),fetch(`${c}/status`).then(function(B){return B.json()}).then(function(B){document.querySelectorAll('.default-action').forEach(C=>{i(C,B[C.id],!1)})});const j=document.getElementById('stream'),k=document.getElementById('stream-container'),l=document.getElementById('get-still'),m=document.getElementById('toggle-stream'),n=document.getElementById('face_enroll'),o=document.getElementById('close-stream'),p=()=>{window.stop(),m.innerHTML='CAMARA'},q=()=>{j.src=`${c+':81'}/stream`,f(k),m.innerHTML='DIRECTO'};l.onclick=()=>{p(),j.src=`${c}/capture?_cb=${Date.now()}`,f(k)},o.onclick=()=>{p(),e(k)},m.onclick=()=>{const B='Stop Stream'===m.innerHTML;B?p():q()},n.onclick=()=>{b},document.querySelectorAll('.default-action').forEach(B=>{B.onchange=()=>b(B)});const r=document.getElementById('agc'),s=document.getElementById('agc_gain-group'),t=document.getElementById('gainceiling-group');r.onchange=()=>{b(r),r.checked?(f(t),e(s))e(t),f(s))};const u=document.getElementById('aec'),v=document.getElementById('aec_value-group');u.onchange=()=>{b(u),u.checked?e(v):f(v)};const w=document.getElementById('awb_gain'),x=document.getElementById('wb_mode-group');w.onchange=()=>{b(w),w.checked?f(x):e(x)};const y=document.getElementById('face_detect'),z=document.getElementById('face_recognize'),A=document.getElementById('framesize');A.onchange=()=>{b(A),5<A.value&&(i(y,!1),i(z,!1))},y.onchange=()=>{return 5<A.value?(alert('Please select CIF or lower resolution before enabling this feature!'),void i(y,!1)):void(b,!y.checked&&(g,i(z,!1)))},z.onchange=()=>{return 5<A.value?(alert('Please select CIF or lower resolution before enabling this feature!'),void i(z,!1)):void(b(z),z.checked?(h,i(y,!0)):g)}});

        </script>

    </body>

</html>



)rawliteral";


static esp_err_t index_handler(httpd_req_t *req){

    httpd_resp_set_type(req, "text/html");

    return httpd_resp_send(req, (const char *)INDEX_HTML, strlen(INDEX_HTML));

}


void startCameraServer()

{

    httpd_config_t config = HTTPD_DEFAULT_CONFIG();


    httpd_uri_t index_uri = {

        .uri       = "/",

        .method    = HTTP_GET,

        .handler   = index_handler,

        .user_ctx  = NULL

    };


    httpd_uri_t status_uri = {

        .uri       = "/status",

        .method    = HTTP_GET,

        .handler   = status_handler,

        .user_ctx  = NULL

    };


    httpd_uri_t cmd_uri = {

        .uri       = "/control",

        .method    = HTTP_GET,

        .handler   = cmd_handler,

        .user_ctx  = NULL

    };


    httpd_uri_t capture_uri = {

        .uri       = "/capture",

        .method    = HTTP_GET,

        .handler   = capture_handler,

        .user_ctx  = NULL

    };


   httpd_uri_t stream_uri = {

        .uri       = "/stream",

        .method    = HTTP_GET,

        .handler   = stream_handler,

        .user_ctx  = NULL

    };

  

    Serial.printf("Starting web server on port: '%d'\n", config.server_port);

    if (httpd_start(&camera_httpd, &config) == ESP_OK) {

        httpd_register_uri_handler(camera_httpd, &index_uri);

        httpd_register_uri_handler(camera_httpd, &cmd_uri);

        httpd_register_uri_handler(camera_httpd, &status_uri);

        httpd_register_uri_handler(camera_httpd, &capture_uri);

    }


    config.server_port += 1;

    config.ctrl_port += 1;

    Serial.printf("Starting stream server on port: '%d'\n", config.server_port);

    if (httpd_start(&stream_httpd, &config) == ESP_OK) {

        httpd_register_uri_handler(stream_httpd, &stream_uri);

    }

}
 
Última edición por un moderador:
No tenia ni idea, lo pego de nuevo.
este es el fichero incluido en arduino:app_httpd.cpp
C++:
#include "dl_lib_matrix3d.h"

#include <esp32-hal-ledc.h>

int speed = 255;

int noStop = 0;



#include "esp_http_server.h"

#include "esp_timer.h"

#include "esp_camera.h"

#include "img_converters.h"

#include "Arduino.h"


//#include "dl_lib.h"


typedef struct {

        httpd_req_t *req;

        size_t len;

} jpg_chunking_t;


#define PART_BOUNDARY "123456789000000000000987654321"

static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;

static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";

static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n";


httpd_handle_t stream_httpd = NULL;

httpd_handle_t camera_httpd = NULL;


static size_t jpg_encode_stream(void * arg, size_t index, const void* data, size_t len){

    jpg_chunking_t *j = (jpg_chunking_t *)arg;

    if(!index){

        j->len = 0;

    }

    if(httpd_resp_send_chunk(j->req, (const char *)data, len) != ESP_OK){

        return 0;

    }

    j->len += len;

    return len;

}


static esp_err_t capture_handler(httpd_req_t *req){

    camera_fb_t * fb = NULL;

    esp_err_t res = ESP_OK;

    int64_t fr_start = esp_timer_get_time();


    fb = esp_camera_fb_get();

    if (!fb) {

        Serial.println("Camera capture failed");

        httpd_resp_send_500(req);

        return ESP_FAIL;

    }


    httpd_resp_set_type(req, "image/jpeg");

    httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg");


    size_t out_len, out_width, out_height;

    uint8_t * out_buf;

    bool s;

    {

        size_t fb_len = 0;

        if(fb->format == PIXFORMAT_JPEG){

            fb_len = fb->len;

            res = httpd_resp_send(req, (const char *)fb->buf, fb->len);

        } else {

            jpg_chunking_t jchunk = {req, 0};

            res = frame2jpg_cb(fb, 80, jpg_encode_stream, &jchunk)?ESP_OK:ESP_FAIL;

            httpd_resp_send_chunk(req, NULL, 0);

            fb_len = jchunk.len;

        }

        esp_camera_fb_return(fb);

        int64_t fr_end = esp_timer_get_time();

        Serial.printf("JPG: %uB %ums\n", (uint32_t)(fb_len), (uint32_t)((fr_end - fr_start)/1000));

        return res;

    }


    dl_matrix3du_t *image_matrix = dl_matrix3du_alloc(1, fb->width, fb->height, 3);

    if (!image_matrix) {

        esp_camera_fb_return(fb);

        Serial.println("dl_matrix3du_alloc failed");

        httpd_resp_send_500(req);

        return ESP_FAIL;

    }


    out_buf = image_matrix->item;

    out_len = fb->width * fb->height * 3;

    out_width = fb->width;

    out_height = fb->height;


    s = fmt2rgb888(fb->buf, fb->len, fb->format, out_buf);

    esp_camera_fb_return(fb);

    if(!s){

        dl_matrix3du_free(image_matrix);

        Serial.println("to rgb888 failed");

        httpd_resp_send_500(req);

        return ESP_FAIL;

    }


    jpg_chunking_t jchunk = {req, 0};

    s = fmt2jpg_cb(out_buf, out_len, out_width, out_height, PIXFORMAT_RGB888, 90, jpg_encode_stream, &jchunk);

    dl_matrix3du_free(image_matrix);

    if(!s){

        Serial.println("JPEG compression failed");

        return ESP_FAIL;

    }


    int64_t fr_end = esp_timer_get_time();

    return res;

}


static esp_err_t stream_handler(httpd_req_t *req){

    camera_fb_t * fb = NULL;

    esp_err_t res = ESP_OK;

    size_t _jpg_buf_len = 0;

    uint8_t * _jpg_buf = NULL;

    char * part_buf[64];

    dl_matrix3du_t *image_matrix = NULL;


    static int64_t last_frame = 0;

    if(!last_frame) {

        last_frame = esp_timer_get_time();

    }


    res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE);

    if(res != ESP_OK){

        return res;

    }


    while(true){

        fb = esp_camera_fb_get();

        if (!fb) {

            Serial.println("Camera capture failed");

            res = ESP_FAIL;

        } else {

             {

                if(fb->format != PIXFORMAT_JPEG){

                    bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len);

                    esp_camera_fb_return(fb);

                    fb = NULL;

                    if(!jpeg_converted){

                        Serial.println("JPEG compression failed");

                        res = ESP_FAIL;

                    }

                } else {

                    _jpg_buf_len = fb->len;

                    _jpg_buf = fb->buf;

                }

            }

        }

        if(res == ESP_OK){

            size_t hlen = snprintf((char *)part_buf, 64, _STREAM_PART, _jpg_buf_len);

            res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen);

        }

        if(res == ESP_OK){

            res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len);

        }

        if(res == ESP_OK){

            res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));

        }

        if(fb){

            esp_camera_fb_return(fb);

            fb = NULL;

            _jpg_buf = NULL;

        } else if(_jpg_buf){

            free(_jpg_buf);

            _jpg_buf = NULL;

        }

        if(res != ESP_OK){

            break;

        }

        int64_t fr_end = esp_timer_get_time();

        int64_t frame_time = fr_end - last_frame;

        last_frame = fr_end;

        frame_time /= 1000;

        Serial.printf("MJPG: %uB %ums (%.1ffps)\n",

            (uint32_t)(_jpg_buf_len),

            (uint32_t)frame_time, 1000.0 / (uint32_t)frame_time         

        );

    }


    last_frame = 0;

    return res;

}


enum state {fwd,rev,stp};

state actstate = stp;


static esp_err_t cmd_handler(httpd_req_t *req)

{

    char*  buf;

    size_t buf_len;

    char variable[32] = {0,};

    char value[32] = {0,};


    buf_len = httpd_req_get_url_query_len(req) + 1;

    if (buf_len > 1) {

        buf = (char*)malloc(buf_len);

        if(!buf){

            httpd_resp_send_500(req);

            return ESP_FAIL;

        }

        if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) {

            if (httpd_query_key_value(buf, "var", variable, sizeof(variable)) == ESP_OK &&

                httpd_query_key_value(buf, "val", value, sizeof(value)) == ESP_OK) {

            } else {

                free(buf);

                httpd_resp_send_404(req);

                return ESP_FAIL;

            }

        } else {

            free(buf);

            httpd_resp_send_404(req);

            return ESP_FAIL;

        }

        free(buf);

    } else {

        httpd_resp_send_404(req);

        return ESP_FAIL;

    }


    int val = atoi(value);

    sensor_t * s = esp_camera_sensor_get();

    int res = 0;

  

    if(!strcmp(variable, "framesize"))

    {

        Serial.println("framesize");

        if(s->pixformat == PIXFORMAT_JPEG) res = s->set_framesize(s, (framesize_t)val);

    }

    else if(!strcmp(variable, "quality"))

    {

      Serial.println("quality");

      res = s->set_quality(s, val);

    }

    //Remote Control Car

    //Don't use channel 1 and channel 2

    else if(!strcmp(variable, "flash"))

    {

      ledcWrite(7,val);

    }

    else if(!strcmp(variable, "speed"))

    {

      if      (val > 255) val = 255;

      else if (val <   0) val = 0;     

      speed = val;

    }   

    else if(!strcmp(variable, "nostop"))

    {

      noStop = val;

    }           

    else if(!strcmp(variable, "servo")) // 3250, 4875, 6500

    {

      if      (val > 650) val = 650;

      else if (val < 325) val = 325;     

      ledcWrite(8,10*val);

    }   

    else if(!strcmp(variable, "car")) {

      if (val==1) {

        Serial.println("Forward");

        actstate = fwd;   

        ledcWrite(4,speed);  // pin 12

        ledcWrite(3,0);      // pin 13

        ledcWrite(5,speed);  // pin 14

        ledcWrite(6,0);      // pin 15 

        delay(1000);

      }

      else if (val==2) {

        Serial.println("TurnLeft");

        ledcWrite(3,0);

        ledcWrite(5,0);

        //if      (actstate == fwd) { ledcWrite(4,speed); ledcWrite(6,    0); }

        //else if (actstate == rev) { ledcWrite(4,    0); ledcWrite(6,speed); }

        //else                      { ledcWrite(4,speed); ledcWrite(6,speed); }

        ledcWrite(4,speed);

        ledcWrite(6,speed);

            

        delay(1000);             

      }

      else if (val==3) {

        Serial.println("Stop");

        actstate = stp;     

        ledcWrite(4,0);

        ledcWrite(3,0);

        ledcWrite(5,0);   

        ledcWrite(6,0);

      }

      else if (val==4) {

        Serial.println("TurnRight");

        ledcWrite(4,0);

        ledcWrite(6,0);

        //if      (actstate == fwd) { ledcWrite(3,    0); ledcWrite(5,speed); }

        //else if (actstate == rev) { ledcWrite(3,speed); ledcWrite(5,    0); }

        //else                      { ledcWrite(3,speed); ledcWrite(5,speed); }

        ledcWrite(3,speed);

        ledcWrite(5,speed);

            

        delay(1000);             

      }

      else if (val==5) {

        Serial.println("Backward");

        actstate = rev;     

        ledcWrite(4,0);

        ledcWrite(3,speed);

        ledcWrite(5,0);

        ledcWrite(6,speed);

        delay(1000);             

      }

      if (noStop!=1)

      {

        ledcWrite(3, 0);

        ledcWrite(4, 0);

        ledcWrite(5, 0);

        ledcWrite(6, 0);

      }       

    }       

    else

    {

      Serial.println("variable");

      res = -1;

    }


    if(res){ return httpd_resp_send_500(req); }


    httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");

    return httpd_resp_send(req, NULL, 0);

}


static esp_err_t status_handler(httpd_req_t *req){

    static char json_response[1024];


    sensor_t * s = esp_camera_sensor_get();

    char * p = json_response;

    *p++ = '{';


    p+=sprintf(p, "\"framesize\":%u,", s->status.framesize);

    p+=sprintf(p, "\"quality\":%u,", s->status.quality);

    *p++ = '}';

    *p++ = 0;

    httpd_resp_set_type(req, "application/json");

    httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");

    return httpd_resp_send(req, json_response, strlen(json_response));

}


static const char PROGMEM INDEX_HTML[] = R"rawliteral(




<!doctype html>

<html>

    <head>

        <meta charset="utf-8">

        <meta name="viewport" content="width=device-width,initial-scale=1">

        <title>XXXXXXXXXXXXXXXXXXXX</title>

        <style>

          body{font-family:Arial,Helvetica,sans-serif;background:#181818;color:#EFEFEF;font-size:16px}h2{font-size:18px}section.main{display:flex}#menu,section.main{flex-direction:column}#menu{display:none;flex-wrap:nowrap;min-width:340px;background:#363636;padding:8px;border-radius:4px;margin-top:-10px;margin-right:10px}#content{display:flex;flex-wrap:wrap;align-items:stretch}figure{padding:0;margin:0;-webkit-margin-before:0;margin-block-start:0;-webkit-margin-after:0;margin-block-end:0;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:0;margin-inline-end:0}figure img{display:block;width:100%;height:auto;border-radius:4px;margin-top:8px}@media (min-width: 800px) and (orientation:landscape){#content{display:flex;flex-wrap:nowrap;align-items:stretch}figure img{display:block;max-width:100%;max-height:calc(100vh - 40px);width:auto;height:auto}figure{padding:0;margin:0;-webkit-margin-before:0;margin-block-start:0;-webkit-margin-after:0;margin-block-end:0;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:0;margin-inline-end:0}}section#buttons{display:flex;flex-wrap:nowrap;justify-content:space-between}#nav-toggle{cursor:pointer;display:block}#nav-toggle-cb{outline:0;opacity:0;width:0;height:0}#nav-toggle-cb:checked+#menu{display:flex}.input-group{display:flex;flex-wrap:nowrap;line-height:22px;margin:5px 0}.input-group>label{display:inline-block;padding-right:10px;min-width:47%}.input-group input,.input-group select{flex-grow:1}.range-max,.range-min{display:inline-block;padding:0 5px}button{display:block;margin:5px;padding:0 12px;border:0;line-height:28px;cursor:pointer;color:#fff;background:#ff3034;border-radius:5px;font-size:16px;outline:0}button:hover{background:#ff494d}button:active{background:#f21c21}button.disabled{cursor:default;background:#a0a0a0}input[type=range]{-webkit-appearance:none;width:100%;height:22px;background:#363636;cursor:pointer;margin:0}input[type=range]:focus{outline:0}input[type=range]::-webkit-slider-runnable-track{width:100%;height:2px;cursor:pointer;background:#EFEFEF;border-radius:0;border:0 solid #EFEFEF}input[type=range]::-webkit-slider-thumb{border:1px solid rgba(0,0,30,0);height:22px;width:22px;border-radius:50px;background:#ff3034;cursor:pointer;-webkit-appearance:none;margin-top:-11.5px}input[type=range]:focus::-webkit-slider-runnable-track{background:#EFEFEF}input[type=range]::-moz-range-track{width:100%;height:2px;cursor:pointer;background:#EFEFEF;border-radius:0;border:0 solid #EFEFEF}input[type=range]::-moz-range-thumb{border:1px solid rgba(0,0,30,0);height:22px;width:22px;border-radius:50px;background:#ff3034;cursor:pointer}input[type=range]::-ms-track{width:100%;height:2px;cursor:pointer;background:0 0;border-color:transparent;color:transparent}input[type=range]::-ms-fill-lower{background:#EFEFEF;border:0 solid #EFEFEF;border-radius:0}input[type=range]::-ms-fill-upper{background:#EFEFEF;border:0 solid #EFEFEF;border-radius:0}input[type=range]::-ms-thumb{border:1px solid rgba(0,0,30,0);height:22px;width:22px;border-radius:50px;background:#ff3034;cursor:pointer;height:2px}input[type=range]:focus::-ms-fill-lower{background:#EFEFEF}input[type=range]:focus::-ms-fill-upper{background:#363636}.switch{display:block;position:relative;line-height:22px;font-size:16px;height:22px}.switch input{outline:0;opacity:0;width:0;height:0}.slider{width:50px;height:22px;border-radius:22px;cursor:pointer;background-color:grey}.slider,.slider:before{display:inline-block;transition:.4s}.slider:before{position:relative;content:"";border-radius:50%;height:16px;width:16px;left:4px;top:3px;background-color:#fff}input:checked+.slider{background-color:#ff3034}input:checked+.slider:before{-webkit-transform:translateX(26px);transform:translateX(26px)}select{border:1px solid #363636;font-size:14px;height:22px;outline:0;border-radius:5px}.image-container{position:relative;min-width:160px}.close{position:absolute;right:5px;top:5px;background:#ff3034;width:16px;height:16px;border-radius:100px;color:#fff;text-align:center;line-height:18px;cursor:pointer}.hidden{display:none}

      

      

      

    </style>

    </head>

    <body>

    <figure>

      <div id="stream-container" class="image-container hidden">

        <div class="close" id="close-stream">×</div>

        <img id="stream" src="">

      </div>

    </figure>

  

  


        <font color="gren"

        <font size=5 >...XXXXXXXXXXXXXXXXXXXXXXX...</font>


  

  

  

    <section class="main">

            <section id="buttons">

                <table>

                <tr><td align="center"><button id="get-still">IMAGEN</button></

          

              

                <tr><td></td><td align="center"><button id="toggle-stream">CAMARA</button></

        

        <tr><td>

          <tr><td></td></tr>

              

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

         <tr><td></td><td align="center"><button id="forward" onclick="fetch(document.location.origin+'/control?var=car&val=1');">ABRE</button></td><td></td></tr>

        

         <tr><td></td></tr>

         <tr><td></td></tr>

         <tr><td></td></tr>

         <tr><td></td></tr>

         <tr><td></td></tr>

         <tr><td></td></tr>

         <tr><td></td></tr>

         <tr><td></td></tr>

              

                <tr><td></td><td align="center"><button id="backward" onclick="fetch(document.location.origin+'/control?var=car&val=5');">CIERRA</button></td><tr></td></tr></td><tr></tr></td><tr></tr></td><tr></tr></td><tr></td></tr></td><tr></tr></td><tr></tr></td><tr></tr>

              

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

            

              

              

              

                <tr><td>LUZ</td><td align="center" colspan="2"><input type="range" id="flash" min="0" max="255" value="0" onchange="try{fetch(document.location.origin+'/control?var=flash&val='+this.value);}catch(e){}"></td></tr><tr></td></tr></td><tr></tr></td><tr></tr></td><tr></tr></td><tr></td></tr></td><tr></tr></td><tr></tr></td><tr></tr>

                <tr><td></td></tr>

                <tr><td>CALIDAD</td><td align="center" colspan="2"><input type="range" id="quality" min="10" max="63" value="10" onchange="try{fetch(document.location.origin+'/control?var=quality&val='+this.value);}catch(e){}"></td></tr>

              

              

              

              

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

                <tr><td></td></tr>

            

              

              

                </table>

              

          

          

            </section>       

        </section>

      

      

      

        <font color="#FFFFFF"

        <font size=2 >XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</font>

      

      

        <script>

          document.addEventListener('DOMContentLoaded',function(){function b(B){let C;switch(B.type){case'checkbox':C=B.checked?1:0;break;case'range':case'select-one':C=B.value;break;case'button':case'submit':C='1';break;default:return;}const D=`${c}/control?var=${B.id}&val=${C}`;fetch(D).then(E=>{console.log(`request to ${D} finished, status: ${E.status}`)})}var c=document.location.origin;const e=B=>{B.classList.add('hidden')},f=B=>{B.classList.remove('hidden')},g=B=>{B.classList.add('disabled'),B.disabled=!0},h=B=>{B.classList.remove('disabled'),B.disabled=!1},i=(B,C,D)=>{D=!(null!=D)||D;let E;'checkbox'===B.type?(E=B.checked,C=!!C,B.checked=C):(E=B.value,B.value=C),D&&E!==C?b(B):!D&&('aec'===B.id?C?e(v):f(v):'agc'===B.id?C?(f(t),e(s)):(e(t),f(s)):'awb_gain'===B.id?C?f(x):e(x):'face_recognize'===B.id&&(C?h(n):g(n)))};document.querySelectorAll('.close').forEach(B=>{B.onclick=()=>{e(B.parentNode)}}),fetch(`${c}/status`).then(function(B){return B.json()}).then(function(B){document.querySelectorAll('.default-action').forEach(C=>{i(C,B[C.id],!1)})});const j=document.getElementById('stream'),k=document.getElementById('stream-container'),l=document.getElementById('get-still'),m=document.getElementById('toggle-stream'),n=document.getElementById('face_enroll'),o=document.getElementById('close-stream'),p=()=>{window.stop(),m.innerHTML='CAMARA'},q=()=>{j.src=`${c+':81'}/stream`,f(k),m.innerHTML='DIRECTO'};l.onclick=()=>{p(),j.src=`${c}/capture?_cb=${Date.now()}`,f(k)},o.onclick=()=>{p(),e(k)},m.onclick=()=>{const B='Stop Stream'===m.innerHTML;B?p():q()},n.onclick=()=>{b(n)},document.querySelectorAll('.default-action').forEach(B=>{B.onchange=()=>b(B)});const r=document.getElementById('agc'),s=document.getElementById('agc_gain-group'),t=document.getElementById('gainceiling-group');r.onchange=()=>{b(r),r.checked?(f(t),e(s)):(e(t),f(s))};const u=document.getElementById('aec'),v=document.getElementById('aec_value-group');u.onchange=()=>{b(u),u.checked?e(v):f(v)};const w=document.getElementById('awb_gain'),x=document.getElementById('wb_mode-group');w.onchange=()=>{b(w),w.checked?f(x):e(x)};const y=document.getElementById('face_detect'),z=document.getElementById('face_recognize'),A=document.getElementById('framesize');A.onchange=()=>{b(A),5<A.value&&(i(y,!1),i(z,!1))},y.onchange=()=>{return 5<A.value?(alert('Please select CIF or lower resolution before enabling this feature!'),void i(y,!1)):void(b(y),!y.checked&&(g(n),i(z,!1)))},z.onchange=()=>{return 5<A.value?(alert('Please select CIF or lower resolution before enabling this feature!'),void i(z,!1)):void(b(z),z.checked?(h(n),i(y,!0)):g(n))}});

        </script>

    </body>

</html>



)rawliteral";


static esp_err_t index_handler(httpd_req_t *req){

    httpd_resp_set_type(req, "text/html");

    return httpd_resp_send(req, (const char *)INDEX_HTML, strlen(INDEX_HTML));

}


void startCameraServer()

{

    httpd_config_t config = HTTPD_DEFAULT_CONFIG();


    httpd_uri_t index_uri = {

        .uri       = "/",

        .method    = HTTP_GET,

        .handler   = index_handler,

        .user_ctx  = NULL

    };


    httpd_uri_t status_uri = {

        .uri       = "/status",

        .method    = HTTP_GET,

        .handler   = status_handler,

        .user_ctx  = NULL

    };


    httpd_uri_t cmd_uri = {

        .uri       = "/control",

        .method    = HTTP_GET,

        .handler   = cmd_handler,

        .user_ctx  = NULL

    };


    httpd_uri_t capture_uri = {

        .uri       = "/capture",

        .method    = HTTP_GET,

        .handler   = capture_handler,

        .user_ctx  = NULL

    };


   httpd_uri_t stream_uri = {

        .uri       = "/stream",

        .method    = HTTP_GET,

        .handler   = stream_handler,

        .user_ctx  = NULL

    };

  

    Serial.printf("Starting web server on port: '%d'\n", config.server_port);

    if (httpd_start(&camera_httpd, &config) == ESP_OK) {

        httpd_register_uri_handler(camera_httpd, &index_uri);

        httpd_register_uri_handler(camera_httpd, &cmd_uri);

        httpd_register_uri_handler(camera_httpd, &status_uri);

        httpd_register_uri_handler(camera_httpd, &capture_uri);

    }


    config.server_port += 1;

    config.ctrl_port += 1;

    Serial.printf("Starting stream server on port: '%d'\n", config.server_port);

    if (httpd_start(&stream_httpd, &config) == ESP_OK) {

        httpd_register_uri_handler(stream_httpd, &stream_uri);

    }

}
Me abrieron los puertos 85,8080,8554, para la ip 192.168.0.190, solo falta saber donde se define en la cam.
 
Última edición por un moderador:
Cielos, que me causas conflicto al no usar bien la etiqueta, luego al copiar los datos se pierde el formato y que ingreses los datos como literal me causa conflicto mayor :,D
Moví toda tu variable INDEX_HTML a un archivo h (básicamente el array del binario del index.html) porque me causaba problemas al visualizarlo y compilar. Dejando eso de lado, la modificación debes hacerla antes de iniciar el servidor.

C++:
void startCameraServer()
{
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();
    //aquí puedes modificar el puerto despues de crear el objeto.
    config.server_port = 8554;

    httpd_uri_t index_uri = {
        .uri       = "/",
        .method    = HTTP_GET,
        .handler   = index_handler,
        .user_ctx  = NULL
    };

    httpd_uri_t status_uri = {
        .uri       = "/status",
        .method    = HTTP_GET,
        .handler   = status_handler,
        .user_ctx  = NULL
    };

    httpd_uri_t cmd_uri = {
        .uri       = "/control",
        .method    = HTTP_GET,
        .handler   = cmd_handler,
        .user_ctx  = NULL
    };

    httpd_uri_t capture_uri = {
        .uri       = "/capture",
        .method    = HTTP_GET,
        .handler   = capture_handler,
        .user_ctx  = NULL
    };

   httpd_uri_t stream_uri = {
        .uri       = "/stream",
        .method    = HTTP_GET,
        .handler   = stream_handler,
        .user_ctx  = NULL
    };
  
    Serial.printf("Starting web server on port: '%d'\n", config.server_port);
    if (httpd_start(&camera_httpd, &config) == ESP_OK) {
        httpd_register_uri_handler(camera_httpd, &index_uri);
        httpd_register_uri_handler(camera_httpd, &cmd_uri);
        httpd_register_uri_handler(camera_httpd, &status_uri);
        httpd_register_uri_handler(camera_httpd, &capture_uri);
    }

    config.server_port += 1; //esta linea debería modificar el puerto para el segundo servicio
    config.ctrl_port += 1; //esta otra posiblemente también cambia el valor
    Serial.printf("Starting stream server on port: '%d'\n", config.server_port);
    if (httpd_start(&stream_httpd, &config) == ESP_OK) { //Aquí ya estas iniciando el servidor
        httpd_register_uri_handler(stream_httpd, &stream_uri);
    }
}

Mira que cuando colocas el cursor sobre la función la expande para que veas la declaración de las variables
1690969109192.png
Después de eso es que podrías editarlas para cambiar config.server_port = nuevo_puerto;
Ahora, hice una prueba y funciona
1690970832488.png

Te adjunto los archivos, solo que unas modificaciones que realicé fueron:
1) Mover la configuración de la red a red.h porque mi red no es la misma y me fastidiaba tener que editar el archivo, así solo cambiaba el include.
2) Sacar el index con incrustado con literal ya que me daba error, lo metí en un index.h, también te adjunto una pequeña aplicación de consola por si te interesa usarlo, la copias en el directorio y por ejemplo para generar el index.h del index.html, la usaba en otro proyecto, lo ejecutas como generadorH .\index.html

Apropósito que el archivo html también tiene errores cuando se abre en el visual code, te recomendaría revisarlo y luego solo conviertes para que te ayude a darle mejor apariencia.
 

Adjuntos

  • generadorH.zip
    70.9 KB · Visitas: 3
  • app_httpd.zip
    13.6 KB · Visitas: 3
Última edición:
Por lo que veo estás puesto en el tema, Y Te gradezco Tu ayuda.
A que te refieres con despues de crear el objeto??
Arduino es una forma maquillada de C++ que es programación orientada a objetos, aunque en este caso si nos vamos al esp_http_server.h está en C por lo que en realidad es solo una struct que es un tipo de variable agrupada, pero se me pega la herencia de la definición en C++ ya que la mayoría de las librerías usan ese lenguaje, si fuera un objeto real el constructor te pediría ingresar los parámetros en lugar de devolver la struct con ellos predefinidos con otra función. Igual como está como #define tampoco es función sino una expansión en el preprocesador.
 
Por lo que veo estás puesto en el tema, Y Te gradezco Tu ayuda.
A que te refieres con despues de crear el objeto??
Lo he cargado en la cam y si abre la web con el puerto 8554 si se pica en imagen abre una imagen estatica pero en camara no abre video.
Ten en cuenta que el 80 lo tienen cerrado en la red del proveedor
Screenshot_2023-08-02-13-05-29-81_40deb401b9ffe8e1df2f1cc5ba480b12.jpg
Ahora está conectada a esa IP
Esta
 
Última edición:
En el código que te marqué, hay una sección donde te comento que se modifica el puerto para el segundo servicio, si cambia el puerto web al 8554 el de stream probablemente tambien se mueve al 8555
En la parte del HTML tendrías que buscar esta sección y modificarla
1690974853395.png
O modificar config.server_port += 1; por config.server_port = Otro_Puerto; de forma explícita, como no tengo la cámara no puedo hacer pruebas de esa sección.
Por cierto, si modificas el index.html en lugar de tu código original, mi aplicación llama la constante
const unsigned char index[], revisalo y corrige a como lo ocupas static const char PROGMEM INDEX_HTML[]
Yo lo usaba en un proyecto con ethernet de STM32 y la función empleaba uint8_t pero la conversión a char (con signo) en la librería que usa el ESP causa conflicto, la verdad no sé por qué usa con signo cuando es literal texto lo que debería transmitir.
 
En el código que te marqué, hay una sección donde te comento que se modifica el puerto para el segundo servicio, si cambia el puerto web al 8554 el de stream probablemente tambien se mueve al 8555
En la parte del HTML tendrías que buscar esta sección y modificarla
Ver el archivo adjunto 302104
O modificar config.server_port += 1; por config.server_port = Otro_Puerto; de forma explícita, como no tengo la cámara no puedo hacer pruebas de esa sección.
Por cierto, si modificas el index.html en lugar de tu código original, mi aplicación llama la constante
const unsigned char index[], revisalo y corrige a como lo ocupas static const char PROGMEM INDEX_HTML[]
Yo lo usaba en un proyecto con ethernet de STM32 y la función empleaba uint8_t pero la conversión a char (con signo) en la librería que usa el ESP causa conflicto, la verdad no sé por qué usa con signo cuando es literal texto lo que debería transmitir.
no encuentro el html, o está ilegible.
lo del puerto web ya lo tengo claro y funciona,
ahora es el streaming que las lines estan ilegibles
El html se puede quedar donde estaba??, y que se pueda modificar?
lo del puerto streaming no lo encuentro por ninguana parte
si lo encuentro en mi codigo
que si se ve el html
 
Si lo modificas de tu código original solo agregando la línea para modificar el puerto pues está bien, si usas los archivos que adjunté es ahí donde está el index.html separado, la verdad te recomiendo que lo revises porque hay tags que no se cierran dentro del código html y el visual code arroja las advertencias, igual no sé si se perdió formato.
Ya luego para incorporarlo con el ejecutable del otro archivo, copias el exe en la misma carpeta y corres el comando
1690976848286.png
Eso te genera el index.h
1690977017743.png
Corriges el nombre a static const char PROGMEM INDEX_HTML[] como lo declaras en tu código, voy a ver si lo edito para que puedas establecer el nombre y luego te paso el script para que solo le des doble clic y se actualicen, así en el futuro podrás generar los incrustados más fácil, yo lo usaba hasta para generar el código del favicon.
 
Ok, aquí está el nuevo conversor
1690985569658.pngTe adjunto los archivos junto con un .bat para que solo le des doble clic, básicamente este es el código
Bash:
@echo off
.\generadorH.exe .\index.html "static const char PROGMEM INDEX_HTML" index.h
echo Conversion completada
pause
Copias el ejecutable adjunto (o lo compilas con visual c++) a la misma carpeta donde almacenes el archivo html. básicamente para convertir cualquier cosa usas la misma estructura, el primer argumento es el ejecutable, el segundo el archivo de entrada, el tercero la declaración y el cuarto el archivo de salida, por ejemplo, si quisieras generar el código para favicon (el pequeño icono que se muestra en el navegador) agregamos la siguiente línea.

Bash:
@echo off
.\generadorH.exe .\index.html "static const char PROGMEM INDEX_HTML" index.h
.\generadorH.exe .\favicon.ico "static const char PROGMEM FAVICON_ICO" favicon_ico.h
echo Conversion completada
pause
El resultado es un favicon_ico.h con una declaración FAVICON_ICO que puedes llamar desde el código. Así puedes trabajar en los archivos originales en HTML o cualquier otro e insertarlos en código.
 

Adjuntos

  • generadorH.zip
    72 KB · Visitas: 1
Si lo modificas de tu código original solo agregando la línea para modificar el puerto pues está bien, si usas los archivos que adjunté es ahí donde está el index.html separado, la verdad te recomiendo que lo revises porque hay tags que no se cierran dentro del código html y el visual code arroja las advertencias, igual no sé si se perdió formato.
Ya luego para incorporarlo con el ejecutable del otro archivo, copias el exe en la misma carpeta y corres el comando
Ver el archivo adjunto 302105
Eso te genera el index.h
Ver el archivo adjunto 302106
Corriges el nombre a static const char PROGMEM INDEX_HTML[] como lo declaras en tu código, voy a ver si lo edito para que puedas establecer el nombre y luego te paso el script para que solo le des doble clic y se actualicen, así en el futuro podrás generar los incrustados más fácil, yo lo usaba hasta para generar el código del favicon.
como se arranca el generador h?
A ver si me puedes encaminar de como va esto que soy muy torpe, al ejecutable Te refieres al conversor.exe?
Lo he descomprimido y hay tres ficheros convertir.bat, generadorH.c, generadorH.exe, estos los copio a la carpeta donde tengo el proyecto con el .ino y demás?, así lo tengo.
ubicacion.jpg
Pero no se como usarlo.
Ok, aquí está el nuevo conversor
Ver el archivo adjunto 302113Te adjunto los archivos junto con un .bat para que solo le des doble clic, básicamente este es el código
Bash:
@echo off
.\generadorH.exe .\index.html "static const char PROGMEM INDEX_HTML" index.h
echo Conversion completada
pause
Copias el ejecutable adjunto (o lo compilas con visual c++) a la misma carpeta donde almacenes el archivo html. básicamente para convertir cualquier cosa usas la misma estructura, el primer argumento es el ejecutable, el segundo el archivo de entrada, el tercero la declaración y el cuarto el archivo de salida, por ejemplo, si quisieras generar el código para favicon (el pequeño icono que se muestra en el navegador) agregamos la siguiente línea.

Bash:
@echo off
.\generadorH.exe .\index.html "static const char PROGMEM INDEX_HTML" index.h
.\generadorH.exe .\favicon.ico "static const char PROGMEM FAVICON_ICO" favicon_ico.h
echo Conversion completada
pause
El resultado es un favicon_ico.h con una declaración FAVICON_ICO que puedes llamar desde el código. Así puedes trabajar en los archivos originales en HTML o cualquier otro e insertarlos en código.
como se arranca el generador h?
A ver si me puedes encaminar de como va esto que soy muy torpe, al ejecutable Te refieres al conversor.exe?
Lo he descomprimido y hay tres ficheros convertir.bat, generadorH.c, generadorH.exe, estos los copio a la carpeta donde tengo el proyecto con el .ino y demás?, así lo tengo.
ubicacion.jpg
Pero no se como usarlo.
msdos.png
 
Última edición:
Atrás
Arriba