witnessmenow / Universal-Arduino-Telegram-Bot

Use Telegram on your Arduino (ESP8266 or Wifi-101 boards)
MIT License
1.11k stars 307 forks source link

Send photo from ESP32-CAM #136

Open array81 opened 4 years ago

array81 commented 4 years ago

Is it possible get JPG from ESP32-CAM and send it to Telegram? Any idea?

D-Paesani commented 4 years ago

of course. Find here an example:

https://dptechnology.jimdofree.com/projects/es32cam1/

witnessmenow commented 4 years ago

I don't see any code here?

On Sat, 8 Feb 2020, 21:39 D-Paesani, notifications@github.com wrote:

of course. Find here an example:

https://dptechnology.jimdofree.com/projects/es32cam1/

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot/issues/136?email_source=notifications&email_token=AAL5PQV7CW6NCJBNWCAUFLDRB4RCBA5CNFSM4KO4PALKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOELF4JOY#issuecomment-583779515, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAL5PQXHUXEZODE44CZTUELRB4RCBANCNFSM4KO4PALA .

D-Paesani commented 4 years ago

To send directly from the camera buffer (without the need for an SD card) I am doing as follows.

define these functions:

bool isMoreDataAvailable() { return ((fb->len) - currentByte); } 

uint8_t photoNextByte() {currentByte++; return (fb->buf[currentByte-1]);}

send the photo with the following code:

fb = esp_camera_fb_get();  

currentByte=0;

String sent = bot.sendPhotoByBinary(chatID, "image/jpeg", fb->len, isMoreDataAvailable, photoNextByte);

esp_camera_fb_return(fb);

(fb and currentByte are global variables)

DP

robotzero1 commented 4 years ago

I'm getting a Guru crash with the code below at line: return ((fb->len) - currentByte);

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include "esp_camera.h"
#include <UniversalTelegramBot.h>

String chat_id;

#define BOTtoken "100etc" 
WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

int Bot_mtbs = 3000; //mean time between scan messages
long Bot_lasttime;   //last time messages' scan has been done

camera_fb_t * fb;
size_t currentByte;
// sensor settings

void setup(){
  Serial.begin(115200);
  // camera setup
  // wi-fi setup
}

bool isMoreDataAvailable() {
  return ((fb->len) - currentByte);
}

uint8_t photoNextByte() {
  currentByte++;
  return (fb->buf[currentByte - 1]);
}

String take_send_photo(String chat_id){
  camera_fb_t * fb = NULL;
  fb = esp_camera_fb_get();
  currentByte = 0;
  String sent = bot.sendPhotoByBinary(chat_id, "image/jpeg", fb->len, isMoreDataAvailable, photoNextByte);
  esp_camera_fb_return(fb);
}

void loop() {
  if (millis() > Bot_lasttime + Bot_mtbs)  {
    int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    while (numNewMessages) {
      Serial.println("got response");
      chat_id = bot.messages[0].chat_id;
      for (int i = 0; i < numNewMessages; i++) {
        //bot.sendMessage(bot.messages[i].chat_id, bot.messages[i].text, "");
        take_send_photo(chat_id);
      }
      numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    }
    Bot_lasttime = millis();
  }
}
robotzero1 commented 4 years ago

OK.. this seems to be working. Dunno why I had to make new variables. I'll make a proper tutorial soon for this.

EDIT: Tutorial here: https://robotzero.one/telegram-bot-esp32cam/

uint8_t* fb_buffer;
size_t fb_length;
int currentByte;

bool isMoreDataAvailable() {
  return (fb_length - currentByte);
}

uint8_t photoNextByte() {
  currentByte++;
  return (fb_buffer[currentByte - 1]);
}

String take_send_photo(String chat_id)
{
  camera_fb_t * fb = NULL;
  fb = esp_camera_fb_get();
  currentByte = 0;
  fb_length = fb->len;
  fb_buffer = fb->buf;
  String sent = bot.sendPhotoByBinary(chat_id, "image/jpeg", fb->len, isMoreDataAvailable, photoNextByte);
  esp_camera_fb_return(fb);
}
gilshahar7 commented 4 years ago

OK.. this seems to be working. Dunno why I had to make new variables. I'll make a proper tutorial soon for this.

uint8_t* fb_buffer;
size_t fb_length;
int currentByte;

bool isMoreDataAvailable() {
  return (fb_length - currentByte);
}

uint8_t photoNextByte() {
  currentByte++;
  return (fb_buffer[currentByte - 1]);
}

String take_send_photo(String chat_id)
{
  camera_fb_t * fb = NULL;
  fb = esp_camera_fb_get();
  currentByte = 0;
  fb_length = fb->len;
  fb_buffer = fb->buf;
  String sent = bot.sendPhotoByBinary(chat_id, "image/jpeg", fb->len, isMoreDataAvailable, photoNextByte);
  esp_camera_fb_return(fb);
}

Hey, i am also trying to send an image through the telegram bot but its always crashing.

did you make the toturial?

gilshahar7 commented 4 years ago

This is the code that i am using (the ChannelPost example with your code added):

/*******************************************************************
*  An example of bot that echos back any messages received,
*  including ones from channels
*
*  written by Brian Lough
*******************************************************************/
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>

#include "esp_camera.h"

// Initialize Wifi connection to the router
char ssid[] = "XXX";     // your network SSID (name)
char password[] = "XXX"; // your network key

// Initialize Telegram BOT
#define BOTtoken "XXXXX:XXXX"  // your Bot Token (Get from Botfather)

WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

int Bot_mtbs = 1000; //mean time between scan messages
long Bot_lasttime;   //last time messages' scan has been done

uint8_t* fb_buffer;
size_t fb_length;
int currentByte;

void setup() {
  Serial.begin(115200);

  // Attempt to connect to Wifi network:
  Serial.print("Connecting Wifi: ");
  Serial.println(ssid);

  // Set WiFi to station mode and disconnect from an AP if it was Previously
  // connected
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  if (millis() > Bot_lasttime + Bot_mtbs)  {
    int numNewMessages = bot.getUpdates(bot.last_message_received + 1);

    while(numNewMessages) {
      Serial.println("got response");
      for (int i=0; i<numNewMessages; i++) {
        if(bot.messages[i].type == "channel_post") {
          bot.sendMessage(bot.messages[i].chat_id, bot.messages[i].chat_title + " " + bot.messages[i].text, "");
        } else {
          bot.sendMessage(bot.messages[i].chat_id, bot.messages[i].text, "");
          take_send_photo(bot.messages[i].chat_id);
        }
      }

      numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    }

    Bot_lasttime = millis();
  }
}

bool isMoreDataAvailable() {
  return (fb_length - currentByte);
}

uint8_t photoNextByte() {
  currentByte++;
  return (fb_buffer[currentByte - 1]);
}

String take_send_photo(String chat_id)
{
  camera_fb_t * fb = NULL;
  fb = esp_camera_fb_get();
  currentByte = 0;
  fb_length = fb->len;
  fb_buffer = fb->buf;
  String sent = bot.sendPhotoByBinary(chat_id, "image/jpeg", fb->len, isMoreDataAvailable, photoNextByte);
  esp_camera_fb_return(fb);
}
Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x400d1abb  PS      : 0x00060430  A0      : 0x800d1cac  A1      : 0x3ffb1ef0  
A2      : 0x3ffc16f4  A3      : 0x3ffc16f4  A4      : 0x00000000  A5      : 0x3ffb1f80  
A6      : 0x3ffcc1ec  A7      : 0x3ffcc1ec  A8      : 0x3ffc10d4  A9      : 0x00000000  
A10     : 0x00000000  A11     : 0x3ffb1f74  A12     : 0x3ffc10f0  A13     : 0x87d32310  
A14     : 0x00004466  A15     : 0x3ffc116c  SAR     : 0x00000010  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00000004  LBEG    : 0x4000c46c  LEND    : 0x4000c477  LCOUNT  : 0x00000000  

Backtrace: 0x400d1abb:0x3ffb1ef0 0x400d1ca9:0x3ffb1f50 0x400d7799:0x3ffb1fb0 0x4008bd65:0x3ffb1fd0

Rebooting...
robotzero1 commented 4 years ago

I've not finished the tutorial yet. I need to work out how to manage the memory a bit better because after while there's not enough continuous space to store the SSL data and it crashes.

For you problem, I'm not sure. Try this to get more info about your crash - https://github.com/me-no-dev/EspExceptionDecoder

gilshahar7 commented 4 years ago

I've not finished the tutorial yet. I need to work out how to manage the memory a bit better because after while there's not enough continuous space to store the SSL data and it crashes.

For you problem, I'm not sure. Try this to get more info about your crash - https://github.com/me-no-dev/EspExceptionDecoder

Thanks for the quick reply, i have decoded the crash using the tool you provided.

PC: 0x400d1abb: take_send_photo(String) at C:\Users\gilshahar7\Documents\Arduino\sketch_feb24a/sketch_feb24a.ino line 91
EXCVADDR: 0x00000004

Decoding stack results
0x400d1abb: take_send_photo(String) at C:\Users\gilshahar7\Documents\Arduino\sketch_feb24a/sketch_feb24a.ino line 91
0x400d1ca9: loop() at C:\Users\gilshahar7\Documents\Arduino\sketch_feb24a/sketch_feb24a.ino line 65
0x400d7799: loopTask(void*) at C:\Users\gilshahar7\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\cores\esp32\main.cpp line 19
0x4008bd65: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 143

Does it say anything usefull? i dont see anything..

Edit: This is line 91: 91. fb_length = fb->len;

robotzero1 commented 4 years ago

Are you setting up the camera somewhere? Something like...

#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

void setup()
{
  Serial.begin(115200);

  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_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;
  }

  sensor_t * s = esp_camera_sensor_get();

  s->set_framesize(s, FRAMESIZE_XGA);

etc...
gilshahar7 commented 4 years ago

Nope, i am extremley noob with the ESP32-cam. just got it in the mail an hour ago.

Will try right now, sorry for this

robotzero1 commented 4 years ago

I have a bunch of tutorials on this on my blog (click link in profile). I think Brian (library author) has at least one video on it as well.

gilshahar7 commented 4 years ago

I have a bunch of tutorials on this on my blog (click link in profile). I think Brian (library author) has at least one video on it as well.

I have visited your blog but i couldnt find the exact code that i need to initialize the camera.

I found this toturial: https://robotzero.one/esp32-face-door-entry/

But i dont want to copy any unnecessary code..

robotzero1 commented 4 years ago

Check out the CameraWebServer example in the Arduino IDE. You can use that as a basis for your sketch. Remove void startCameraServer(); and startCameraServer(); lines. You don't need app_httpd file but the other two are needed. More info here: https://robotzero.one/esp32-cam-arduino-ide/

gilshahar7 commented 4 years ago

Check out the CameraWebServer example in the Arduino IDE. You can use that as a basis for your sketch. Remove void startCameraServer(); and startCameraServer(); lines. You don't need app_httpd file but the other two are needed. More info here: https://robotzero.one/esp32-cam-arduino-ide/

I got it to send the image to telegram but right after it sends i get a reboot with this error

assertion "heap != NULL && "free() target pointer is outside heap areas"" failed: file "/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/heap_caps.c", line 267, function: heap_caps_free
abort() was called at PC 0x40124e53 on core 1

Backtrace: 0x40091604:0x3ffb1d40 0x40091835:0x3ffb1d60 0x40124e53:0x3ffb1d80 0x4008782b:0x3ffb1db0 0x40087cf9:0x3ffb1dd0 0x4000bec7:0x3ffb1df0 0x400d8d6b:0x3ffb1e10 0x400d8d79:0x3ffb1e30 0x400d374e:0x3ffb1e50 0x400d25b5:0x3ffb1e90 0x400d2965:0x3ffb1ef0 0x400d2c3d:0x3ffb1f60 0x400d3ec4:0x3ffb1f90 0x400d92e1:0x3ffb1fb0 0x4008dd4d:0x3ffb1fd0

Rebooting...

It does send the image though, not sure whats going on.

Edit: seems like after i changed the String take_send_photo(String chat_id) to a void it no longer crashes.. does it make any sense?

robotzero1 commented 4 years ago

Ah.. good point, that's wrong. It should be Void because nothing is returned by the function. It worked for me but maybe it's another C memory thing when you declare a function as a type. I'm still learning this stuff! What did the backtrace say in the decoder?

gilshahar7 commented 4 years ago

hat's wrong. It should be Void because nothing is returned by the function. It worked for me but maybe it's another C memory thing when you declare a function as a type. I'm still learning this stuff! What did the backtrace say

Well it just pointed out some files and the loop function. nothing useful.

I was just surprised that it compiled without a return at the end, so i wasnt sure what is going on.. it seems to work great without crashes so far.

I am using this funtion for my automatic pet feeder outside the house, it was set up using esp8266 and the "blynk" app. i wanted to add a camera so i bought the ESP32cam, changed all of the libraries to support ESP32 and added a button to the blynk interface to grab an image and send it to my chat_id.

Its all 3d printed, here is the model: https://www.thingiverse.com/thing:4013543

Now i designed a mount for the ESP32Cam to be aimed at the food bowl. Here are some images if you are interested: https://imgur.com/gallery/IyrXSOf

Now i can feed my cat and check if she is there eating using the picture :)

robotzero1 commented 4 years ago

Cool! What are the pins connected to?

gilshahar7 commented 4 years ago

Cool! What are the pins connected to?

I have a servo motor on gpio 12 to drop food, push button on gpio 2 to manualy feed and a DHT22 on gpio 13 with a long cable to monitor my cat's "dog house" temp to see when she is inside during the night.

Its a full system for my cat, im really exited to have the camera integrated in all of that. thanks :)

mugginsjm commented 4 years ago

Hi can ayone advise please. I want to split the function take_send_photo into 2 functions: take_photo and send_photo. I have an external trigger which captures a photo to the buffer. Each time it triggers I want to clear the buffer and overwrite with the new photo. Only when another condition is met will I actually send to Telegram. Ihave tried this with no success... void takePhoto(){ fb_length = NULL; fb_buffer = NULL; camera_fb_t * fb = NULL; fb = esp_camera_fb_get(); currentByte = 0; fb_length = fb->len; fb_buffer = fb->buf; } void sendPhoto(String chat_id){ bot->sendPhotoByBinary(chat_id, "image/jpeg", fb_length, isMoreDataAvailable, photoNextByte, nullptr, nullptr);

esp_camera_fb_return(fb); fb_length = NULL; fb_buffer = NULL; }

array81 commented 3 years ago

Is this work again?

From about may/june I cannot receive more photo from my device and I don't have edit code.

robotzero1 commented 3 years ago

The new release of this library has an example for this - https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot/tree/master/examples/ESP32/SendPhoto/ESP32-Cam

array81 commented 3 years ago

Yes, I know. I just tested it. It works only if you set quality image to FRAMESIZE_QVGA, if you try to set other (high) quality I cannot see image to my telegram chat and there is not error.

robotzero1 commented 3 years ago

Possibly a timeout at Telegram's end waiting for the file. If you set logging to verbose in the Arduino IDE do you see anything? You could try my script - https://robotzero.one/telegram-bot-esp32cam/ which is based on 1.3 of this library. I don't remember now what changes I made.

robotzero1 commented 3 years ago

Oh.. I used 1.2 which I think was when Brian moved to ArduinoJson 6. I don't know what differences 1.3 has.

array81 commented 3 years ago

I tested robotzero1 version, it works also with big resolution photo. I have compare official 1.2 and robotzero1 and there are very similar (there are few differences), so I like to edit official 1.3 but this is very different from official 1.2. Is it possible fix official 1.3 version?

FBMinis commented 3 years ago

Possibly a timeout at Telegram's end waiting for the file. If you set logging to verbose in the Arduino IDE do you see anything? You could try my script - https://robotzero.one/telegram-bot-esp32cam/ which is based on 1.3 of this library. I don't remember now what changes I made.

Your script allowed me to send images in UXGA, quality = 10, thank you. Is there a way to adapt your method to send a photo to Google Drive?

I have been using this sketch but images over VGA show a grey area:

https://github.com/fustyles/Arduino/tree/master/ESP32-CAM_PIR_GoogleDrive

premnair77 commented 3 years ago

It's very late getting response from Esp32 to telegram..