Puerta automática para gallinero

La IP estática depende del ISP, desde el ESP32 no puedes forzar la IP estática.
Si no la pagas no la vas a tener.

Seguridad, pues deja la puerta de tu casa abierta, si lo más seguro es que no venga un ladrón y llevar llaves es un incordio, se te pueden olvidar, se te clavan en el bolsillo, la cerradura vale cara etc.
 
Puerta para gallinero, He construido para un amigo una puerta para su gallinero totalmente automática y controlable desde internet i desde cualquier lugar.
He usado un esp32cam con servidor web.
Mis conocimientos de programación son limitados y he tenido que añadir algo de electrónica externa, pero he conseguido que funcione, lleva varios días en pruebas y va muy bien.
Se cierra al anochecer, abre en auto a la hora que se elija, o manual desde el móvil por web, abre, cierra,enciende luz, con video en directo.
Si alguien quiere probar está conectada en : gallinero.ddns.net .
Si es de noche no se puede abrir, si funciona la luz.
Me encanta tu proyecto!! Felicidades y gracias por compartir.
No todos somos iguales, así que espero que no te desilusiones con los comentarios agrios que haz recibido. Yo estoy en Argentina y pude acceder perfectamente.
Solo quiero decirte que lo de seguridad que también te comentaron es importante porque hay mucha gente con ganas de molestar o se creen graciosos molestando y podrían acceder a tu equipo afectando su funcionamiento solamente para probarse que lo hacen a su antojo.
Creo que es lo que necesitas saber y el motivo de porqué lo necesitas. Los "relajos irónicos" de algunos mensajes no son gentiles por más razón que tengan y así funcionan también esos "hackers" que podrían atacar tu proyecto solo por molestar
Si no sabes mucho pero haz hecho esto vos solito, pues ya puedes decir que sabes un poco!!😄

Nuevamente felicidades y nuevamente gracias por compartir 😊
 
Gracias por vuestra información, Os explico,
Ahora estoy probando desde casa que no tengo IP fija, por eso lo del ddns.
Después cuando lo ponga en el gallinero de mi Amigo que si tiene IP fija para entrar habrá que escribir solo la púbica y sin puerto, estará redireccionado por DMZ y con esto desde fuera solo se podrá entrar al servidor de la cam, además el vídeo de la cam solo admite un usuario conectado.
Sería perfecto añadirle solicitud para entrar pero no sé cómo.
Insisto, todo está dentro del esp32.
 
A qué te referis?
Yo entré, y pude usarlo normalmente y ver la cámara, y soy de Argentina, yendo en un colectivo a mi trabajo...
A menos que lo prohíban los gobiernos (VPN.. guiño, guiño), puedes entrar desde donde quieras, de cualquier parte del mundo.

Se ve bien, aunque como te dijeron, importantisimo el uso de alguna seguridad para el ingreso, y ojo con los ataques DDoS o similares.
Creo que, aunque sea desde un servidor DNS, tienes que tener presente que te comunicas practicamente a tu router, por lo que deberías tener en cuenta a la hora de que el usuario ingrese datos al sistema, para evitar inyección de código.

Bah, si todo es estático, puede que no haga falta...
Hay una larga lista de aspectos por el cual la señal de una cámara con o sin DDNS pueda NO llegar, hasta un abonado o cliente en algún lugar del mundo.
Lo digo porque instalé una lista de ellas, incluso desde el año 2000 para aquí.
Como casi nadie sabia en ese entonces como hacer el enlace de ese tipo, me tuve que hacer un AUTOCURSO de Prueba ERROR que duró 2 meses hasta ir resolviendo cada uno de los problemas.
Siempre hablo del PCs, porque los enlaces a teléfonos móviles, no me han interesado nunca, tampoco hoy, porque la prestación es muy limitada y yo necesitaba tener los "archivos" para guardarlos como "pruebas".
Unos de los impedimentos posibles mas comunes, es que el ISP de origen o destino o ambos , tenga bloqueado ese servicio.
Hace unos 10 años, he tenido que llegar a INTIMAR a un ISP, para que me permita que la señal de una cámara, salga de sus servidores al la INTERNET GLOBAL.
Otro es EL propio servidor de DDNS, que a menudo falla o te hace problema por las actualizaciones o la tarjeta de crédito o los pagos o LA MAR en coche, porque todo a la postre es un negocio.
Otra limitación es que los DDNS que no esten registrado en el firmware del "APARATO" no los podes usar y la mayoria no trae mas de 2 o 3, es
decir que NO puedes elegir uno de tu agrado.
Es una mar de problemas y al final te aburres de tanto impedimento. La única manera que funcione BIEN es solo para uso EMPRESARIAL, pagas 200 pavos VERDES al año y lo tienes.
Basta un solo detalle que no se cumpla para que la señal no llegue , routers de por medio también.
De hecho yo intenté ver esa cámara de varias maneras, sin lograrlo. ;)
Tampoco uso VPN , se cuelgan a cada rato.
 
Última edición:
Hay una larga lista de aspectos por el cual la señal de una cámara con o sin DDNS pueda NO llegar, hasta un abonado o cliente en algún lugar del mundo.
Lo digo porque instalé una lista de ellas, incluso desde el año 2000 para aquí.
Como casi nadie sabia en ese entonces como hacer el enlace de ese tipo, me tuve que hacer un AUTOCURSO de Prueba ERROR que duró 2 meses hasta ir resolviendo cada uno de los problemas.
Siempre hablo del PCs, porque los enlaces a teléfonos móviles, no me han interesado nunca, tampoco hoy, porque la prestación es muy limitada y yo necesitaba tener los "archivos" para guardarlos como "pruebas".
Unos de los impedimentos posibles mas comunes, es que el ISP de origen o destino o ambos , tenga bloqueado ese servicio.
Hace unos 10 años, he tenido que llegar a INTIMAR a un ISP, para que me permita que la señal de una cámara, salga de sus servidores al la INTERNET GLOBAL.
Otro es EL propio servidor de DDNS, que a menudo falla o te hace problema por las actualizaciones o la tarjeta de crédito o los pagos o LA MAR en coche, porque todo a la postre es un negocio.
Otra limitación es que los DDNS que no esten registrado en el firmware del "APARATO" no los podes usar y la mayoria no trae mas de 2 o 3, es
decir que NO puedes elegir uno de tu agrado.
Es una mar de problemas y al final te aburres de tanto impedimento. La única manera que funcione BIEN es solo para uso EMPRESARIAL, pagas 200 pavos VERDES al año y lo tienes.
Basta un solo detalle que no se cumpla para que la señal no llegue , routers de por medio también.
De hecho yo intenté ver esa cámara de varias maneras, sin lograrlo. ;)
Tampoco uso VPN , se cuelgan a cada rato.
Decir que solo admite un usuario para ver el video, si alguien esta mirando otro no puede verlo aunque si abra la web.
 
Hace algunos años que me hice del ESP32-CAM y llegué a hacer unas pruebas con el entorno B4R
No fue mucho de mi agrado la baja resolución y sigue guardado en una cajonera.
Creo que si se trata de obtener vídeo se puede usar una cámara IP y el desarrollo de control con un ESPXXX controlado por Android y MQTT.
Si solo se trata de controlar tiempos, hasta con un microcontrolador pequeño se podría implementar.
Experimentar siempre es bueno, pero también hay que tratar de no matar mosquitos a cañonazos.
Ahora que si queremos sacar más partido del ESP32-CAM, le podemos añadir reconocimiento facial o de colores.
Así podremos saber qué gallina se despertó primero o saber si falta la pinta o la colorada. 😅
 
La implementación estática de una página que debe tener algún tipo de seguridad, se resume a utilizar códigos (sea contraseña, token, o una mezcla de ambos), de forma también estática, con lo que limita al lado del cliente el peso de generar dicho token o encriptar la contraseña.
Sumado que la conexión se realiza SIN certificación SSL, o algún método similar, la implementación sigue decayendo en cuanto a seguridad.

Creo que tendrías que pensar en generar de forma aleatoria y encriptada, un token (del lado del servidor), que junto a la contraseña, genere otro token también aleatorio (lado cliente)
 
La implementación estática de una página que debe tener algún tipo de seguridad, se resume a utilizar códigos (sea contraseña, token, o una mezcla de ambos), de forma también estática, con lo que limita al lado del cliente el peso de generar dicho token o encriptar la contraseña.
Sumado que la conexión se realiza SIN certificación SSL, o algún método similar, la implementación sigue decayendo en cuanto a seguridad.

Creo que tendrías que pensar en generar de forma aleatoria y encriptada, un token (del lado del servidor), que junto a la contraseña, genere otro token también aleatorio (lado cliente)
Bueno.... Hoy unas horas después de enterarme que el servidor de esa cámara solo admite 1 usuario , pude conectarme a la cámara de un intento , pero TIO !!! que se vé fatal VIVE DIOS !!!!
Yo me esperaba como mínimo un 4K ó 1080 a 25fps. !!!
Con esas limitaciones de imagen, no sé si van a distinguir a las gallinas, de un Zorro, Lobo, Lince, Gavilán , Hurón, Marta ó Susana.

Para los citadinos :
Estas serian las gallinas 👇 ;)

5a36373b-5179-4bfb-81f4-28d342c5c0c0_16-9-aspect-ratio_default_0.jpg

Gavilan 👇
zgavilan.jpg
 
Es que el ESP32-CAM no está dedicado al vídeo por Stream, lo que toma son fotos que se van actualizando.
Lo bonito es que tiene un potente diodo LED que puede ser usado como flash.
Realizar una petición fotográfica cuando uno lo requiera entregaría más calidad y se consume menos recursos.

Esta publicación fue la que me animó a comprar el dispositivo:

ESP32 Camera Picture Capture and Video Streaming! (Updated with code!)

Cuando vi los resultados por mi parte, me desanimé. 🥲
Aunque no puedo negar que me entretuve un rato haciendo más pruebas.
Pero definitivamente lo guardé y hasta ahora no le he encontrado ningún uso conveniente.
 
Es que el ESP32-CAM no está dedicado al vídeo por Stream, lo que toma son fotos que se van actualizando.
Lo bonito es que tiene un potente diodo LED que puede ser usado como flash.
Realizar una petición fotográfica cuando uno lo requiera entregaría más calidad y se consume menos recursos.

Esta publicación fue la que me animó a comprar el dispositivo:

ESP32 Camera Picture Capture and Video Streaming! (Updated with code!)

Cuando vi los resultados por mi parte, me desanimé. 🥲
Aunque no puedo negar que me entretuve un rato haciendo más pruebas.
Pero definitivamente lo guardé y hasta ahora no le he encontrado ningún uso conveniente.
Para el cometido que va a tener sirve, no se trata de controlar a las gallinas solo ver si la puerta abre o cierra y con la imagen que da la cam es suficiente, por 4€. No se le puede pedir más.

Para el cometido que va a tener sirve, no se trata de controlar a las gallinas solo ver si la puerta abre o cierra y con la imagen que da la cam es suficiente, por 4€. No se le puede pedir más.
Bueno Amigos, ya la voy a colocar en su sitio, ya no estará operativa la web.
Doy por finalizada la exhibición, muchas gracias a todos por vuestras opiniones y pruebas.
 
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());
}
 
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());
}
Eso es desde el router,haciendo re dirección
 
config.server_port = 80;
/*********
Rui Santos
Complete project details at ESP32-CAM Video Streaming Web Server (works with Home Assistant) | Random Nerd Tutorials

IMPORTANT!!!
- Select Board "AI Thinker ESP32-CAM"
- GPIO 0 must be connected to GND to upload a sketch
- After connecting GPIO 0 to GND, press the ESP32-CAM on-board RESET button to put your board in flashing mode

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*********/

#include "esp_camera.h"
#include <WiFi.h>
#include "esp_timer.h"
#include "img_converters.h"
#include "Arduino.h"
#include "fb_gfx.h"
#include "soc/soc.h" //disable brownout problems
#include "soc/rtc_cntl_reg.h" //disable brownout problems
#include "esp_http_server.h"

//Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

#define PART_BOUNDARY "123456789000000000000987654321"

// This project was tested with the AI Thinker Model, M5STACK PSRAM Model and M5STACK WITHOUT PSRAM
#define CAMERA_MODEL_AI_THINKER
//#define CAMERA_MODEL_M5STACK_PSRAM
//#define CAMERA_MODEL_M5STACK_WITHOUT_PSRAM

// Not tested with this model
//#define CAMERA_MODEL_WROVER_KIT

#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_M5STACK_WITHOUT_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 17
#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

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;

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];

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->width > 400){
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;
}
//Serial.printf("MJPG: %uB\n",(uint32_t)(_jpg_buf_len));
}
return res;
}

void startCameraServer(){
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.server_port = 80;

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

//Serial.printf("Starting web server on port: '%d'\n", config.server_port);
if (httpd_start(&stream_httpd, &config) == ESP_OK) {
httpd_register_uri_handler(stream_httpd, &index_uri);
}
}

void setup() {
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector

Serial.begin(115200);
Serial.setDebugOutput(false);

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;

if(psramFound()){
config.frame_size = FRAMESIZE_UXGA;
config.jpeg_quality = 10;
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_SVGA;
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;
}
// Wi-Fi connection
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");

Serial.print("Camera Stream Ready! Go to: http://");
Serial.print(WiFi.localIP());

// Start streaming web server
startCameraServer();
}

void loop() {
delay(1);
}
 
Por defecto el puerto http es el 80, y eso ya está configurado en la variable
config.server_port = 80
del código de @jihacc

Ahora se trata de que redirecciones las conexiones entrantes por el puerto 80 TCP al servidor web, y eso se hace entrando en la configuración del router.

La manera de hacerlo varía dependiendo del modelo de router. Averigua dicho modelo y haz una búsqueda en internet sobre cómo hacerlo.

Si el equipo donde tienes instalado el servidor web tiene un firewall activado, deberás crear una regla de acceso que también redirija las conexiones entrantes al servidor web.

No hay necesidad de usar otro puerto, salvo que uses conexión segura tipo https.

En ese caso el puerto no es el 80 sino el 443.
 
Que tengo que hacer con ese código??

Esa página ya la vi pero no entiendo como hacerlo
El problema es que ya hay puertos abiertos para otros sistemas y al router solo tiene acceso el proveedor, necesariamente hay que definir un puerto web y otro de video que no sean 80, 8091,8092 porque el 80 lo tienen cerrado globalmente y los otros los usan Ellos para sus redes internas, eso me dijeron.
 
En ese caso, se pueden redireccionar las conexiones entrantes por el puerto 80 a otro puerto cualquiera entre el 1024 y el 65535.

El problema es que, hacer esas cosas dependiendo de un operador telefónico sin poder hacerlas uno mismo, puede llegar a ser desespe... complicado.

----------------------

A continuación se debe modificar
config.server_port = 80
con el nuevo puerto definido arriba
config.server_port = elpuertoquesea

Por cierto, también deberás configurar en el código ese, dos variables, que definen el nombre de tu red y su contraseña:

const char* ssid = "EL_NOMBRE_DE_TU_RED";
const char* password = "LA_CONTRASEÑA_DE_TU_RED";
 
Última edición:
En ese caso, se pueden redireccionar las conexiones entrantes por el puerto 80 a otro puerto cualquiera entre el 1024 y el 65535.

El problema es que, hacer esas cosas dependiendo de un operador telefónico sin poder hacerlas uno mismo, puede llegar a ser desespe... complicado.

----------------------

A continuación se debe modificar
config.server_port = 80
con el nuevo puerto definido arriba
config.server_port = elpuertoquesea

Por cierto, también deberás configurar en el código ese, dos variables, que definen el nombre de tu red y su contraseña:

const char* ssid = "EL_NOMBRE_DE_TU_RED";
const char* password = "LA_CONTRASEÑA_DE_TU_RED";
Lo de la red está puesto al principio del código que he subido está funcionando.
Ahora desde casa que si tengo acceso total al router con IP dinámica, por eso lo del dns.
Sólo sería cambiarp
En ese caso, se pueden redireccionar las conexiones entrantes por el puerto 80 a otro puerto cualquiera entre el 1024 y el 65535.

El problema es que, hacer esas cosas dependiendo de un operador telefónico sin poder hacerlas uno mismo, puede llegar a ser desespe... complicado.

----------------------

A continuación se debe modificar
config.server_port = 80
con el nuevo puerto definido arriba
config.server_port = elpuertoquesea

Por cierto, también deberás configurar en el código ese, dos variables, que definen el nombre de tu red y su contraseña:

const char* ssid = "EL_NOMBRE_DE_TU_RED";
const char* password = "LA_CONTRASEÑA_DE_TU_RED";
l
Lo de la red está puesto al principio del código que he subido está funcionando.
Ahora desde casa que si tengo acceso total al router con IP dinámica, por eso lo del dns.
Sólo sería cambiarp
le anadi, config.server_port = 85 y me da error,

gallinero_bueno:27:1: error: 'config' does not name a type
config.server_port = 85

In file included from c:\users\insec\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\1.22.0-97-gc752ad5-5.2.0\xtensa-esp32-elf\include\c++\5.2.0\functional:53:0,
from C:\Users\insec\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\WebServer\src/WebServer.h:27,
from C:\Users\insec\AppData\Local\Temp\arduino_modified_sketch_826665\gallinero_bueno.ino:30:
c:\users\insec\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\1.22.0-97-gc752ad5-5.2.0\xtensa-esp32-elf\include\c++\5.2.0\typeinfo:39:37: error: expected declaration before end of line
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

en que parte hay que ponerlo??
 
Última edición:
Fallo mio, que no lo puse.

Escribe un punto y coma al final:
config.server_port = 85;
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
 
Atrás
Arriba