Closed dr-garimella closed 11 months ago
It is something I will investigate in the future
Your work is really excellent. Really, I don't have any words to express the gratitude.
Small doubt if possible:
Is it possible to access (open) the SD card files through telegram group.?!
Regards.
In the meantime, I would suggest you try this application which send a photo and video to telegram when movement is detected by a PIR connected to GPIO13: https://github.com/jameszah/ESP32-CAM-Video-Telegram
Your work is really excellent. Really, I don't have any words to express the gratitude. Small doubt if possible: Is it possible to access (open) the SD card files through telegram group.?! Regards.
In the meantime, I would suggest you try this application which send a photo and video to telegram when movement is detected by a PIR connected to GPIO13: https://github.com/jameszah/ESP32-CAM-Video-Telegram
Thank you for the response.
However, it doesn't work. Already tried the code. Videos are not sending properly. The code is good to send Photos alone.
However, it doesn't work. Already tried the code. Videos are not sending properly. The code is good to send Photos alone.
I have had 3 cameras working outside for over 12 months without a problem, they send video and photo when movement is detected.
However, it doesn't work. Already tried the code. Videos are not sending properly. The code is good to send Photos alone.
I have had 3 cameras working outside for over 12 months without a problem, they send video and photo when movement is detected.
Ohh.! May be my hard luck. I tried many times and finally, left it.
I put this together, it sends a photo to Telegram when haveMotion() returns true, one photo per 10sec interval at most, so not to flood the connection.
#include <WiFi.h>
#include <AsyncTelegram2.h>
#include "esp_camera.h"
#include "soc/soc.h" // Brownout error fix
#include "soc/rtc_cntl_reg.h" // Brownout error fix
#include <WiFiClientSecure.h>
WiFiClientSecure secure_client;
const char* ssid = "***********"; // SSID WiFi network
const char* pass = "***********"; // Password WiFi network
const char* token = "***********"; // Telegram token
int64_t userid = ***********;
// Timezone definition to get properly time from NTP server
#define MYTZ "WET0WEST,M3.5.0/1,M10.5.0"
AsyncTelegram2 myBot(secure_client);
#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
static camera_config_t camera_config = {
.pin_pwdn = PWDN_GPIO_NUM,
.pin_reset = RESET_GPIO_NUM,
.pin_xclk = XCLK_GPIO_NUM,
.pin_sscb_sda = SIOD_GPIO_NUM,
.pin_sscb_scl = SIOC_GPIO_NUM,
.pin_d7 = Y9_GPIO_NUM,
.pin_d6 = Y8_GPIO_NUM,
.pin_d5 = Y7_GPIO_NUM,
.pin_d4 = Y6_GPIO_NUM,
.pin_d3 = Y5_GPIO_NUM,
.pin_d2 = Y4_GPIO_NUM,
.pin_d1 = Y3_GPIO_NUM,
.pin_d0 = Y2_GPIO_NUM,
.pin_vsync = VSYNC_GPIO_NUM,
.pin_href = HREF_GPIO_NUM,
.pin_pclk = PCLK_GPIO_NUM,
.xclk_freq_hz = 20000000,
.ledc_timer = LEDC_TIMER_0,
.ledc_channel = LEDC_CHANNEL_0,
.pixel_format = PIXFORMAT_JPEG, /* PIXFORMAT_RGB565, // for face detection/recognition */
.frame_size = FRAMESIZE_VGA,
.jpeg_quality = 12,
.fb_count = 1,
.fb_location = CAMERA_FB_IN_PSRAM,
.grab_mode = CAMERA_GRAB_WHEN_EMPTY,
#if CONFIG_CAMERA_CONVERTER_ENABLED
.conv_mode = CONV_DISABLE, /*!< RGB<->YUV Conversion mode */
#endif
//.sccb_i2c_port = 1 /*!< If pin_sccb_sda is -1, use the already configured I2C bus by number */
};
static esp_err_t init_camera() {
// Best picture quality, but first frame requestes get lost sometimes (comment/uncomment to try)
if (psramFound()) {
Serial.println("PSRAM found");
camera_config.fb_count = 2;
camera_config.grab_mode = CAMERA_GRAB_LATEST;
}
//initialize the camera
Serial.println("Camera init... ");
esp_err_t err = esp_camera_init(&camera_config);
if (err != ESP_OK) {
delay(100); // need a delay here or the next serial o/p gets missed
Serial.printf("\n\nCRITICAL FAILURE: Camera sensor failed to initialise.\n\n");
Serial.printf("A full (hard, power off/on) reboot will probably be needed to recover from this.\n");
return err;
} else {
Serial.println("succeeded");
// Get a reference to the sensor
sensor_t* s = esp_camera_sensor_get();
// Dump camera module, warn for unsupported modules.
switch (s->id.PID) {
case OV9650_PID: Serial.println("WARNING: OV9650 camera module is not properly supported, will fallback to OV2640 operation"); break;
case OV7725_PID: Serial.println("WARNING: OV7725 camera module is not properly supported, will fallback to OV2640 operation"); break;
case OV2640_PID: Serial.println("OV2640 camera module detected"); break;
case OV3660_PID: Serial.println("OV3660 camera module detected"); break;
default: Serial.println("WARNING: Camera module is unknown and not properly supported, will fallback to OV2640 operation");
}
}
return ESP_OK;
}
size_t sendPicture(int64_t userid) {
// Take picture with Camera and send to Telegram
Serial.println("Camera capture requested");
// for (int j = 0; j < 4; j++) {
// camera_fb_t * newfb = esp_camera_fb_get();
// if (!newfb) {
// Serial.println("Camera Capture Failed");
// } else {
// //Serial.print("Pic, len="); Serial.print(newfb->len);
// //Serial.printf(", new fb %X\n", (long)newfb->buf);
// esp_camera_fb_return(newfb);
// delay(10);
// }
// }
camera_fb_t* fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Camera capture failed");
return 0;
}
size_t len = fb->len;
myBot.sendPhoto(userid, fb->buf, fb->len);
// Clear buffer
esp_camera_fb_return(fb);
return len;
}
#define THIS_FRAME FRAMESIZE_QVGA // JPEG frames size to be retrieved
#define LAMP_PIN 4
bool debug = true;
uint8_t fsizePtr = THIS_FRAME; // framesize selection
uint8_t lightLevel; // Current ambient light level
uint8_t nightSwitch = 10; // white level % for night/day switching
uint8_t motionVal = 7; // motion sensitivity difference setting
bool haveMotion = false;
struct frameStruct {
const char* frameSizeStr;
const uint16_t frameWidth;
const uint16_t frameHeight;
const uint16_t defaultFPS;
const uint8_t scaleFactor;
const uint8_t sampleRate;
};
// sample factors, 5th arg is scaling factor (1..N), 6th arg is sample factor (0..3)
// indexed by frame size - needs to be consistent with sensor.h enum
extern const frameStruct frameData[] = {
{"QQVGA", 160, 120, 25, 2, 1},
{"n/a", 0, 0, 0, 0, 1},
{"n/a", 0, 0, 0, 0, 1},
{"HQVGA", 240, 176, 25, 3, 1},
{"QVGA", 320, 240, 25, 3, 1},
{"CIF", 400, 296, 25, 3, 1},
{"VGA", 640, 480, 15, 3, 2},
{"SVGA", 800, 600, 10, 3, 2},
{"XGA", 1024, 768, 5, 3, 3},
{"SXGA", 1280, 1024, 3, 3, 4},
{"UXGA", 1600, 1200, 2, 6, 5}
};
bool checkMotion(camera_fb_t* fb, bool motionStatus);
bool isNight(uint8_t nightSwitch);
void setup_camera() {
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 = 10000000; // https://github.com/esphome/issues/issues/4191
config.pixel_format = PIXFORMAT_JPEG;
//init with high specs to pre-allocate larger buffers
if (psramFound())
{
config.frame_size = FRAMESIZE_VGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
config.jpeg_quality = 10;
config.fb_count = 2;
}
else
{
config.frame_size = FRAMESIZE_VGA;
config.jpeg_quality = 12;
config.fb_count = 1;
}
// camera init
esp_err_t err = ESP_FAIL;
uint8_t retries = 2;
while (retries && err != ESP_OK) {
err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
digitalWrite(PWDN_GPIO_NUM, 1);
delay(100);
digitalWrite(PWDN_GPIO_NUM, 0); // power cycle the camera (OV2640)
retries--;
}
}
if (err != ESP_OK) ESP.restart();
}
void setup() {
Serial.begin(115200);
Serial.println();
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // disable brownout detector
// Initiate the camera module
// init_camera(); // alternative camera setup routine for testing purposes only
setup_camera();
// Start WiFi connection
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println(WiFi.localIP());
// Sync time with NTP
configTzTime(MYTZ, "time.google.com", "time.windows.com", "pool.ntp.org");
secure_client.setCACert(telegram_cert);
myBot.addSentCallback([](bool sent) {
const char* res = sent ? "Picture delivered!" : "Error! Picture NOT delivered";
if (!sent)
myBot.sendTo(userid, res);
}, 3000);
// Set the Telegram bot properies
myBot.setUpdateTime(1000);
myBot.setTelegramToken(token);
// Check if all things are ok
Serial.print("\nTest Telegram connection... ");
myBot.begin() ? Serial.println("OK") : Serial.println("NOK");
// Serial.println("\nSending Photo from CAM");
// if (sendPicture(userid))
// Serial.println("Picture sent successfull");
// else
// myBot.sendTo(userid, "Error, picture not sent.");
}
unsigned long lastPictureTime = 0;
const long interval = 10000; // wait 10sec between sending a new photo when there is movement
void loop() {
camera_fb_t* fb = esp_camera_fb_get();
if (fb) {
haveMotion = checkMotion(fb, haveMotion);
if (haveMotion) {
haveMotion = false;
Serial.println("movement detected");
unsigned long currentTime = millis();
if (currentTime - lastPictureTime >= interval) {
lastPictureTime = currentTime;
Serial.println("\nSending Photo from CAM");
if (sendPicture(userid))
Serial.println("Picture sent successfull");
else
myBot.sendTo(userid, "Error, picture not sent.");
}
}
esp_camera_fb_return(fb);
} else Serial.println("Failed to get frame");
delay(100);
}
I put this together, it sends a photo to Telegram when haveMotion() returns true, one photo per 10sec interval at most, so not to flood the connection.
#include <WiFi.h> #include <AsyncTelegram2.h> #include "esp_camera.h" #include "soc/soc.h" // Brownout error fix #include "soc/rtc_cntl_reg.h" // Brownout error fix #include <WiFiClientSecure.h> WiFiClientSecure secure_client; const char* ssid = "***********"; // SSID WiFi network const char* pass = "***********"; // Password WiFi network const char* token = "***********"; // Telegram token int64_t userid = ***********; // Timezone definition to get properly time from NTP server #define MYTZ "WET0WEST,M3.5.0/1,M10.5.0" AsyncTelegram2 myBot(secure_client); #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 static camera_config_t camera_config = { .pin_pwdn = PWDN_GPIO_NUM, .pin_reset = RESET_GPIO_NUM, .pin_xclk = XCLK_GPIO_NUM, .pin_sscb_sda = SIOD_GPIO_NUM, .pin_sscb_scl = SIOC_GPIO_NUM, .pin_d7 = Y9_GPIO_NUM, .pin_d6 = Y8_GPIO_NUM, .pin_d5 = Y7_GPIO_NUM, .pin_d4 = Y6_GPIO_NUM, .pin_d3 = Y5_GPIO_NUM, .pin_d2 = Y4_GPIO_NUM, .pin_d1 = Y3_GPIO_NUM, .pin_d0 = Y2_GPIO_NUM, .pin_vsync = VSYNC_GPIO_NUM, .pin_href = HREF_GPIO_NUM, .pin_pclk = PCLK_GPIO_NUM, .xclk_freq_hz = 20000000, .ledc_timer = LEDC_TIMER_0, .ledc_channel = LEDC_CHANNEL_0, .pixel_format = PIXFORMAT_JPEG, /* PIXFORMAT_RGB565, // for face detection/recognition */ .frame_size = FRAMESIZE_VGA, .jpeg_quality = 12, .fb_count = 1, .fb_location = CAMERA_FB_IN_PSRAM, .grab_mode = CAMERA_GRAB_WHEN_EMPTY, #if CONFIG_CAMERA_CONVERTER_ENABLED .conv_mode = CONV_DISABLE, /*!< RGB<->YUV Conversion mode */ #endif //.sccb_i2c_port = 1 /*!< If pin_sccb_sda is -1, use the already configured I2C bus by number */ }; static esp_err_t init_camera() { // Best picture quality, but first frame requestes get lost sometimes (comment/uncomment to try) if (psramFound()) { Serial.println("PSRAM found"); camera_config.fb_count = 2; camera_config.grab_mode = CAMERA_GRAB_LATEST; } //initialize the camera Serial.println("Camera init... "); esp_err_t err = esp_camera_init(&camera_config); if (err != ESP_OK) { delay(100); // need a delay here or the next serial o/p gets missed Serial.printf("\n\nCRITICAL FAILURE: Camera sensor failed to initialise.\n\n"); Serial.printf("A full (hard, power off/on) reboot will probably be needed to recover from this.\n"); return err; } else { Serial.println("succeeded"); // Get a reference to the sensor sensor_t* s = esp_camera_sensor_get(); // Dump camera module, warn for unsupported modules. switch (s->id.PID) { case OV9650_PID: Serial.println("WARNING: OV9650 camera module is not properly supported, will fallback to OV2640 operation"); break; case OV7725_PID: Serial.println("WARNING: OV7725 camera module is not properly supported, will fallback to OV2640 operation"); break; case OV2640_PID: Serial.println("OV2640 camera module detected"); break; case OV3660_PID: Serial.println("OV3660 camera module detected"); break; default: Serial.println("WARNING: Camera module is unknown and not properly supported, will fallback to OV2640 operation"); } } return ESP_OK; } size_t sendPicture(int64_t userid) { // Take picture with Camera and send to Telegram Serial.println("Camera capture requested"); // for (int j = 0; j < 4; j++) { // camera_fb_t * newfb = esp_camera_fb_get(); // if (!newfb) { // Serial.println("Camera Capture Failed"); // } else { // //Serial.print("Pic, len="); Serial.print(newfb->len); // //Serial.printf(", new fb %X\n", (long)newfb->buf); // esp_camera_fb_return(newfb); // delay(10); // } // } camera_fb_t* fb = esp_camera_fb_get(); if (!fb) { Serial.println("Camera capture failed"); return 0; } size_t len = fb->len; myBot.sendPhoto(userid, fb->buf, fb->len); // Clear buffer esp_camera_fb_return(fb); return len; } #define THIS_FRAME FRAMESIZE_QVGA // JPEG frames size to be retrieved #define LAMP_PIN 4 bool debug = true; uint8_t fsizePtr = THIS_FRAME; // framesize selection uint8_t lightLevel; // Current ambient light level uint8_t nightSwitch = 10; // white level % for night/day switching uint8_t motionVal = 7; // motion sensitivity difference setting bool haveMotion = false; struct frameStruct { const char* frameSizeStr; const uint16_t frameWidth; const uint16_t frameHeight; const uint16_t defaultFPS; const uint8_t scaleFactor; const uint8_t sampleRate; }; // sample factors, 5th arg is scaling factor (1..N), 6th arg is sample factor (0..3) // indexed by frame size - needs to be consistent with sensor.h enum extern const frameStruct frameData[] = { {"QQVGA", 160, 120, 25, 2, 1}, {"n/a", 0, 0, 0, 0, 1}, {"n/a", 0, 0, 0, 0, 1}, {"HQVGA", 240, 176, 25, 3, 1}, {"QVGA", 320, 240, 25, 3, 1}, {"CIF", 400, 296, 25, 3, 1}, {"VGA", 640, 480, 15, 3, 2}, {"SVGA", 800, 600, 10, 3, 2}, {"XGA", 1024, 768, 5, 3, 3}, {"SXGA", 1280, 1024, 3, 3, 4}, {"UXGA", 1600, 1200, 2, 6, 5} }; bool checkMotion(camera_fb_t* fb, bool motionStatus); bool isNight(uint8_t nightSwitch); void setup_camera() { 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 = 10000000; // https://github.com/esphome/issues/issues/4191 config.pixel_format = PIXFORMAT_JPEG; //init with high specs to pre-allocate larger buffers if (psramFound()) { config.frame_size = FRAMESIZE_VGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA config.jpeg_quality = 10; config.fb_count = 2; } else { config.frame_size = FRAMESIZE_VGA; config.jpeg_quality = 12; config.fb_count = 1; } // camera init esp_err_t err = ESP_FAIL; uint8_t retries = 2; while (retries && err != ESP_OK) { err = esp_camera_init(&config); if (err != ESP_OK) { Serial.printf("Camera init failed with error 0x%x", err); digitalWrite(PWDN_GPIO_NUM, 1); delay(100); digitalWrite(PWDN_GPIO_NUM, 0); // power cycle the camera (OV2640) retries--; } } if (err != ESP_OK) ESP.restart(); } void setup() { Serial.begin(115200); Serial.println(); WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // disable brownout detector // Initiate the camera module // init_camera(); // alternative camera setup routine for testing purposes only setup_camera(); // Start WiFi connection WiFi.begin(ssid, pass); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println(WiFi.localIP()); // Sync time with NTP configTzTime(MYTZ, "time.google.com", "time.windows.com", "pool.ntp.org"); secure_client.setCACert(telegram_cert); myBot.addSentCallback([](bool sent) { const char* res = sent ? "Picture delivered!" : "Error! Picture NOT delivered"; if (!sent) myBot.sendTo(userid, res); }, 3000); // Set the Telegram bot properies myBot.setUpdateTime(1000); myBot.setTelegramToken(token); // Check if all things are ok Serial.print("\nTest Telegram connection... "); myBot.begin() ? Serial.println("OK") : Serial.println("NOK"); // Serial.println("\nSending Photo from CAM"); // if (sendPicture(userid)) // Serial.println("Picture sent successfull"); // else // myBot.sendTo(userid, "Error, picture not sent."); } unsigned long lastPictureTime = 0; const long interval = 10000; // wait 10sec between sending a new photo when there is movement void loop() { camera_fb_t* fb = esp_camera_fb_get(); if (fb) { haveMotion = checkMotion(fb, haveMotion); if (haveMotion) { haveMotion = false; Serial.println("movement detected"); unsigned long currentTime = millis(); if (currentTime - lastPictureTime >= interval) { lastPictureTime = currentTime; Serial.println("\nSending Photo from CAM"); if (sendPicture(userid)) Serial.println("Picture sent successfull"); else myBot.sendTo(userid, "Error, picture not sent."); } } esp_camera_fb_return(fb); } else Serial.println("Failed to get frame"); delay(100); }
Great.
Can we get a 2-3 video with same logic instead of photo.?!
I would adapt the project by jameszah to include something like this:
static unsigned long lastFrameTime = 0;
unsigned long currentFrameTime = millis();
unsigned long lastPictureTime = 0;
const long interval = 30000; // wait 30sec between sending a new photo+video when there is movement
void loop() {
// Capture frame every 100ms
if (currentFrameTime - lastFrameTime >= 100) {
camera_fb_t* fb = esp_camera_fb_get();
if (fb) {
haveMotion = checkMotion(fb, haveMotion);
if (haveMotion) {
haveMotion = false;
Serial.println("movement detected");
unsigned long currentTime = millis();
if (currentTime - lastPictureTime >= interval) {
lastPictureTime = currentTime;
// capture and send photo+video
bot.longPoll = 0;
xTaskCreatePinnedToCore( the_camera_loop, "the_camera_loop", 10000, NULL, 1, &the_camera_loop_task, 1);
}
}
esp_camera_fb_return(fb);
} else Serial.println("Failed to get frame");
lastFrameTime = currentFrameTime;
}
}
Noted. I've started work on a telegram feature, but will be writing my own code as there's no challenge copying someone else.
One thing I haven't found in other Telegram libs: save error messages in RTC (errors from camera or connections), send them as a Telegram message after the camera has power-cycled or restarted or upon we send a message to the bot.
I'd previously thought about using RTC_NOINIT_ATTR for carrying over restart messages then forgot about it, so I'll look again. Only works for s/w reset not power cycle. The sd logs are persistent though.
Telegram & RTC log added to v9.1
Your work is really excellent. Really, I don't have any words to express the gratitude.
Small doubt if possible:
Is it possible to access (open) the SD card files through telegram group.?!
Regards.