/*********
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp32-cam-video-streaming-web-server-camera-home-assistant/
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
Anpassung an tuc-special sowie Allgemeinfall
(nicht so'n Murks mit dem Eincompilieren von SSID+Passphrase):
-Videotyp an URL
*********/
#define BOARD_HAS_PSRAM
#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>
#include <Preferences.h>
#include "input.h"
#define PART_BOUNDARY "123456789000000000000987654321"
static httpd_handle_t stream_httpd;
static esp_err_t stream_handler(httpd_req_t *req) {
Serial.println("Stream-Handler startet.");
esp_err_t res = httpd_resp_set_type(req,"multipart/x-mixed-replace;boundary=" PART_BOUNDARY);
while (res == ESP_OK){
camera_fb_t*fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Camera capture failed");
res = ESP_FAIL;
break;
}
size_t jpg_buf_len = 0;
byte*jpg_buf = 0;
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 = 0;
if (!jpeg_converted){
Serial.println("JPEG compression failed");
res = ESP_FAIL;
break;
}
}
}
jpg_buf_len = fb->len;
jpg_buf = fb->buf;
char part_buf[64];
size_t hlen = snprintf(part_buf,sizeof part_buf,
"Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n",
jpg_buf_len);
if (res == ESP_OK) res=httpd_resp_send_chunk(req,part_buf,hlen);
if (res == ESP_OK) res=httpd_resp_send_chunk(req,reinterpret_cast<char*>(jpg_buf),jpg_buf_len);
static const char STREAM_BOUNDARY[] = "\r\n--" PART_BOUNDARY "\r\n";
if (res == ESP_OK) res=httpd_resp_send_chunk(req,STREAM_BOUNDARY,strlen(STREAM_BOUNDARY));
if (fb) esp_camera_fb_return(fb);
else free(jpg_buf);
//Serial.printf("MJPG: %uB\n",(uint32_t)(jpg_buf_len));
};
Serial.println("Stream-Handler beendet.");
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 = 0
};
//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);
}
}
static Preferences preferences;
void setup() {
// Wer/was auch immer noch etws VORHER in die Konsole kritzelt ...
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 = 5;
config.pin_d1 = 18;
config.pin_d2 = 19;
config.pin_d3 = 21;
config.pin_d4 = 36;
config.pin_d5 = 39;
config.pin_d6 = 34;
config.pin_d7 = 35;
config.pin_xclk = 0;
config.pin_pclk = 22;
config.pin_vsync = 25;
config.pin_href = 23;
config.pin_sscb_sda = 26;
config.pin_sscb_scl = 27;
config.pin_pwdn = 32;
config.pin_reset = -1;
config.xclk_freq_hz = 20000000;
config.pixel_format = PIXFORMAT_JPEG;
if (psramFound()){
Serial.println("Kamerainitialisierung mit PSRAM, 1600x1200");
config.frame_size = FRAMESIZE_UXGA; // 1600x1200, kommt aber nicht an!
config.jpeg_quality = 10;
config.fb_count = 2;
} else {
Serial.println("Kamerainitialisierung ohne PSRAM, 800x600");
config.frame_size = FRAMESIZE_SVGA; // 800x600, das kommt an! Kein PSRAM? Sollte drauf sein!
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;
}
// WLAN-Verbindung
char ssid[64], password[64];
auto queryCredentials=[&]() {
Serial.println("\e[6n"); // Cursorposition abfragen und Cursor nach links zurück
char answer[16];
size_t alen=0;
for (auto tic=millis();millis()-tic<100;) {
auto c=Serial.read();
if (c>=0) answer[alen++]=c;
}
isTerm=!!alen; // Wenn Antwort dann Terminal (putty) sonst dummer Arduino Serial Monitor
if (isTerm) Serial.print("\e[4m"); // unterstreichen
Serial.print("WLAN-Infrastruktur-Zugang muss konfiguriert werden!");
if (isTerm) Serial.print("\e[m"); // unterstreichen aus
Serial.println();
int n = WiFi.scanNetworks();
for (int i = 0; i < n; ++i) {
for (int j=0; j<i; j++) {
if (WiFi.encryptionType(j)==WiFi.encryptionType(i)
&& WiFi.SSID(j).equals(WiFi.SSID(i))) goto already;
}
Serial.print(WiFi.encryptionType(i) == WIFI_AUTH_OPEN?"🔓":"🔒"); // 🔐 wenn Schlüssel vorhanden
Serial.println(WiFi.SSID(i));
already:;
}
Serial.print("Diese MAC-Adresse: ");
Serial.println(WiFi.macAddress());
// strcpy(ssid,"tuc-special"); // Vorgabe für TU Chemnitz
do{
input("WLAN-Netzwerkname",ssid,sizeof ssid);
input(" Zugangsschlüssel",password,sizeof password);
}while (!*ssid);
Serial.println("Angaben werden gespeichert.");
preferences.putString("ssid",ssid);
preferences.putString("password",password);
};
preferences.begin("credentials");
preferences.getString("ssid",ssid,sizeof ssid);
preferences.getString("password",password,sizeof password);
if (!*ssid) queryCredentials();
WiFi.mode(WIFI_STA);
for(;;) {
WiFi.disconnect();
WiFi.begin(ssid, password);
char intime=20; // 10 Sekunden
do{
if (WiFi.status() == WL_CONNECTED) break;
Serial.print(".");
delay(500);
}while(--intime);
if (intime) break;
Serial.println(" Zeitüberschreitung!");
queryCredentials();
}
Serial.println();
Serial.println("Verbindung mit WLAN-Router hergestellt.");
Serial.print("Kamera bereit! Bild im Browser durch Aufruf von: ");
if (isTerm) Serial.print("\e[1m"); // fett
Serial.print("http://");
Serial.print(WiFi.localIP());
Serial.print("/");
if (isTerm) Serial.print("\e[m"); // fett aus
Serial.println();
// Start streaming web server
startCameraServer();
}
void loop() {
switch (Serial.read()) {
case 'C'-'@': preferences.clear(); //nobreak
case 'R'-'@': setup(); // ^R wirkt wie Reset
}
delay(1);
}
Detected encoding: UTF-8 | 0
|