/************************************************************************************************* PROGRAMMINFO ************************************************************************************************** Funktion: ESP32 CAM Bewegungssensor mit Email und Foto bei Bewegung ************************************************************************************************** Version: 04.06.2022 ************************************************************************************************** Board: ESP32 Wrover Module ************************************************************************************************** Libraries: https://github.com/espressif/arduino-esp32/tree/master/libraries C:\Users\User\Documents\Arduino D:\gittemp\Arduino II\A156_Wetterdaten_V3 ************************************************************************************************** C++ Arduino IDE V1.8.19 ************************************************************************************************** Einstellungen: https://dl.espressif.com/dl/package_esp32_index.json http://dan.drown.org/stm32duino/package_STM32duino_index.json http://arduino.esp8266.com/stable/package_esp8266com_index.json **************************************************************************************************/ #include "esp_camera.h" #include "SPI.h" #include "driver/rtc_io.h" #include #include #include #include // REPLACE WITH YOUR NETWORK CREDENTIALS const char* ssid = "xxx"; const char* password = "xxx"; // Gmail port 465 (SSL): https://support.google.com/accounts/answer/185833 #define emailSenderAccount "xx@xx.de" #define emailSenderPassword "xxx" #define smtpServer "smtp.xxx.de" #define smtpServerPort 465 #define emailSubject "[WARNUNG] ESP32-CAM Bewegung erkannt" #define emailRecipient "xx@xx.de" #define CAMERA_MODEL_AI_THINKER #if 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 "Kameramodell nicht ausgewählt" #endif SMTPSession smtp; void smtpCallback(SMTP_Status status); #define FILE_PHOTO "photo.jpg" #define FILE_PHOTO_PATH "/photo.jpg" void setup() { WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // Brownout Detector Serial.begin(115200); Serial.println(); // Wi-Fi Verbindung WiFi.begin(ssid, password); Serial.print("Verbinde mit WiFi..."); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(); if (!SPIFFS.begin(true)) { Serial.println("Beim Mounten von SPIFFS ist ein Fehler aufgetreten"); ESP.restart(); } else { delay(500); Serial.println("SPIFFS erfolgreich gestartet"); } // Lokale ESP32-IP-Adresse ausgeben Serial.print("IP Addresse: "); Serial.println(WiFi.localIP()); 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 start esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) { Serial.printf("Camera init failed with error 0x%x", err); return; } capturePhotoSaveSpiffs(); sendPhoto(); esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 1); Serial.println("Going to sleep now"); WiFi.disconnect(); delay(1000); esp_deep_sleep_start(); } void loop() { } // Überprüfe ob die Fotoaufnahme erfolgreich war bool checkPhoto( fs::FS &fs ) { File f_pic = fs.open(FILE_PHOTO_PATH); unsigned int pic_sz = f_pic.size(); return ( pic_sz > 100 ); } //Das Foto in der SPIFFS speichern void capturePhotoSaveSpiffs( void ) { camera_fb_t * fb = NULL; // pointer bool ok = 0; // Boolescher Wert, der angibt, ob das Bild korrekt aufgenommen wurde do { // Mache das Foto Serial.println("TMache ein Foro..."); fb = esp_camera_fb_get(); if (!fb) { Serial.println("Camera capture failed"); return; } // Foto Dateiname Serial.printf("Picture file name: %s\n", FILE_PHOTO_PATH); File file = SPIFFS.open(FILE_PHOTO_PATH, FILE_WRITE); // Einfügen der Daten in die Fotodatei if (!file) { Serial.println("Datei konnte nicht im Schreibmodus geöffnet werden"); } else { file.write(fb->buf, fb->len); // payload (image), payload length Serial.print("The picture has been saved in "); Serial.print(FILE_PHOTO_PATH); Serial.print(" - Größe: "); Serial.print(file.size()); Serial.println(" Bytes"); } // Schließe Datei file.close(); esp_camera_fb_return(fb); // Überprüfe, ob die Datei korrekt in SPIFFS gespeichert wurde ok = checkPhoto(SPIFFS); } while ( !ok ); } void sendPhoto( void ) { /** Aktiviere das Debuggen über die serielle Schnittstelle * none debug or 0 * basic debug or 1 */ smtp.debug(1); /* Lege die Rückruffunktion fest, um die Sendeergebnisse abzurufen */ smtp.callback(smtpCallback); /* Deklarieren der Sitzungskonfigurationsdaten */ ESP_Mail_Session session; /* Festlegen der Sitzungskonfiguration */ session.server.host_name = smtpServer; session.server.port = smtpServerPort; session.login.email = emailSenderAccount; session.login.password = emailSenderPassword; session.login.user_domain = ""; /* Deklarieren der Nachrichtenklasse */ SMTP_Message message; /* Aktiviere die geblockte Datenübertragung mit Pipelining für große Nachrichten, wenn der Server das unterstützt */ message.enable.chunking = true; /* Festlegen der Nachrichtenkopfzeilen */ message.sender.name = "Oberlab-CAM"; message.sender.email = emailSenderAccount; message.subject = emailSubject; message.addRecipient("kfrank@gmx.net", emailRecipient); String htmlMsg = "

Das Foto wurde mit der ESP32-CAM aufgenommen und ist im E-Mail Anhang.

"; message.html.content = htmlMsg.c_str(); message.html.charSet = "utf-8"; message.html.transfer_encoding = Content_Transfer_Encoding::enc_qp; message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_normal; message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay; /* Das Anlagendatenelement */ SMTP_Attachment att; /** Lege die Anlageninformationen fest, z. B. * Dateiname, MIME-Typ, Dateipfad, Dateispeichertyp, * Übertragung von Kodierung und Inhaltscodierung */ att.descr.filename = FILE_PHOTO; att.descr.mime = "image/png"; att.file.path = FILE_PHOTO_PATH; att.file.storage_type = esp_mail_file_storage_type_flash; att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64; /* Hinzufügen eines Anhangs zur Nachricht */ message.addAttachment(att); /* Herstellen einer Verbindung mit dem Server mit der Sitzungskonfiguration */ if (!smtp.connect(&session)) return; /* Starte das Senden der E-Mail und schließe die Sitzung */ if (!MailClient.sendMail(&smtp, &message, true)) Serial.println("Error sending Email, " + smtp.errorReason()); } // Callback function to get the Email sending status void smtpCallback(SMTP_Status status){ /* Drucken des aktuellen Status */ Serial.println(status.info()); /* Drucken des Sendeergebnisses */ if (status.success()) { Serial.println("----------------"); Serial.printf("Senden der Nachricht war erfolgreich: %d\n", status.completedCount()); Serial.printf("Senden der Nachricht ist fehlgeschlagen: %d\n", status.failedCount()); Serial.println("----------------\n"); struct tm dt; for (size_t i = 0; i < smtp.sendingResult.size(); i++) { /* Abrufen des Ergebniselements SMTP_Result result = smtp.sendingResult.getItem(i); localtime_r(&result.timesstamp, &dt); Serial.printf("Nachricht Nr.: %d\n", i + 1); Serial.printf("Status: %s\n", result.completed ? "erfolgreich" : "misslungen"); Serial.printf("Date/Time: %d/%d/%d %d:%d:%d\n", dt.tm_year + 1900, dt.tm_mon + 1, dt.tm_mday, dt.tm_hour, dt.tm_min, dt.tm_sec); Serial.printf("Empfänger: %s\n", result.recipients); Serial.printf("Betreff: %s\n", result.subject); */ } Serial.println("----------------\n"); } }