定期从ESP32-CAM发送捕获的图像到Google云端存储吗?

问题描述 投票:0回答:1

我目前正在尝试让我的ESP32-CAM定期将图像发送到Google云端存储,但是它有问题。非常感谢您的帮助。谢谢。我正在尝试让我的esp cam使用oauth2访问google cloud api(谷歌云存储桶)。

这是我的ardide代码:

#include "esp_camera.h"
#define CAMERA_MODEL_AI_THINKER
#include "camera_pins.h"
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>


const char* ssid = "";
const char* password = "";
const unsigned long timeout = 30000; // 30 seconds

const int buttonPin = 4;    // the number of the pushbutton pin
int buttonState;             
int lastButtonState = LOW;   
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers
bool isNormalMode = true;

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

  Serial.println();
  pinMode(buttonPin, INPUT);

  Serial.println("INIT 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;
  config.pixel_format = PIXFORMAT_JPEG;
  //init with high specs to pre-allocate larger buffers
  if(psramFound()){
    config.frame_size = FRAMESIZE_QVGA; // 320x240
    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;
  }
}

bool wifiConnect(){
  unsigned long startingTime = millis();
  WiFi.begin(ssid, password);

  while(WiFi.status() != WL_CONNECTED){
    delay(500);
    if((millis() - startingTime) > timeout){
      return false;
    }
  }
  return true;
}

void buttonEvent(){
  int reading = digitalRead(buttonPin);
  if (reading != lastButtonState) {
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (reading != buttonState) {
      buttonState = reading;

      if (buttonState == HIGH) {
        isNormalMode = !isNormalMode;

        //Additional Code 
        if(!isNormalMode)
          sendingImage();
        //   
      }
    }
  }
  lastButtonState = reading;
}

camera_fb_t* capture(){
  camera_fb_t *fb = NULL;
  esp_err_t res = ESP_OK;
  fb = esp_camera_fb_get();
  return fb;
}

void showingImage(){
  camera_fb_t *fb = capture();
  if(!fb || fb->format != PIXFORMAT_JPEG){
    Serial.println("Camera capture failed");
    esp_camera_fb_return(fb);
    return;
  }else{
    TJpgDec.drawJpg(0,0,(const uint8_t*)fb->buf, fb->len);
    esp_camera_fb_return(fb);
  }
}


void postingImage(camera_fb_t *fb){
  HTTPClient client;
  client.begin("http://xx.xx.xx.xx:8888/imageUpdate");
  client.addHeader("Content-Type", "image/jpeg");
  int httpResponseCode = client.POST(fb->buf, fb->len);
  if(httpResponseCode == 200){
    String response = client.getString();
    parsingResult(response);
  }else{
    //Error
    tft.drawString("Check Your Server!!!", 8, 4, GFXFF);
  }

  client.end();
  WiFi.disconnect();
}
void googleDeviceOAuthLogin(){
  PhpocClient client;

  // Step 1: Request device and user codes
  if(client.connectSSL("accounts.google.com", 443)){
    Serial.println(F("Connected to server"));

    String body = F("client_id=");
    body += GOOGLE_CLIENT_ID;
    body += F("&scope=https://www.googleapis.com/auth/drive.file");

    client.println(F("POST /o/oauth2/device/code HTTP/1.1"));
    client.println(F("Host: accounts.google.com"));
    client.println(F("Connection: close"));
    client.println(F("Accept: */*"));
    client.println(F("Content-Type: application/x-www-form-urlencoded"));
    client.print(F("Content-Length: ")); client.println(body.length());
    client.println();

    client.print(body);

    String response_hearder = http_resp_hearder(client);
    String response_body = http_resp_body(client);
    //Serial.println(response_hearder);
    //Serial.println(response_body);

    JSONVar body_json = JSON.parse(response_body);
    if(JSON.typeof(body_json) == "undefined"){
      Serial.println("Parsing input failed!");
      return;
    }

    // Step 2: Handle the authorization server response
    String device_code      = "";
    String user_code        = "";
    long expires_in          = 0;
    int interval            = 0;
    String verification_url = "";
    bool is_valid = true;

    if(body_json.hasOwnProperty("device_code"))
      device_code = body_json["device_code"];
    else
      is_valid = false;

    if(body_json.hasOwnProperty("user_code"))
      user_code = body_json["user_code"];
    else
      is_valid = false;

    if(body_json.hasOwnProperty("expires_in"))
      expires_in = (long) body_json["expires_in"];
    else
      is_valid = false;

    if(body_json.hasOwnProperty("interval"))
      interval = (int) body_json["interval"];
    else
      is_valid = false;

    if(body_json.hasOwnProperty("verification_url"))
      verification_url = body_json["verification_url"];
    else
      is_valid = false;

    if(is_valid){
      // Step 3: Display the user code
      Serial.print(F("Next, visit "));
      Serial.print(verification_url);
      Serial.print(F(" on your desktop or smartphone and enter this code: "));
      Serial.println(user_code);
      String msg;

      msg  = "{\"provider\": \"google\",";
      msg += "\"action\": \"LOGIN\",";
      msg += "\"verification_url\": \"" + verification_url + "\",";
      msg += "\"user_code\": \"" + user_code + "\"}";
      websocket_send(msg);

      // Step 5: Poll authorization server
      int poll_max = expires_in / interval;

      body = F("client_id=");
      body += GOOGLE_CLIENT_ID;
      body += F("&client_secret=");
      body += GOOGLE_CLIENT_SECRET;
      body += F("&code=");
      body += device_code;
      body += F("&grant_type=http://oauth.net/grant_type/device/1.0");

      for(int poll_count = 0; poll_count < poll_max; poll_count++){
        if(client.connectSSL("www.googleapis.com", 443)){
          client.println(F("POST /oauth2/v4/token HTTP/1.1"));
          client.println(F("Host: www.googleapis.com"));
          client.println(F("Connection: close"));
          client.println(F("Accept: */*"));
          client.println(F("Content-Type: application/x-www-form-urlencoded"));
          client.print(F("Content-Length: ")); client.println(body.length());
          client.println();

          client.print(body);

          response_hearder = http_resp_hearder(client);
          response_body = http_resp_body(client);
          //Serial.println(response_hearder);
          //Serial.println(response_body);

          body_json = JSON.parse(response_body);
          if(JSON.typeof(body_json) == "undefined"){
            Serial.println("Parsing input failed!");
            return;
          }

          long token_expires_in = 0;
          bool is_authorized = true;

          if(body_json.hasOwnProperty("access_token"))
            access_token = body_json["access_token"];
          else
            is_authorized = false;

          if(body_json.hasOwnProperty("expires_in"))
            token_expires_in = (long) body_json["expires_in"];
          else
            is_authorized = false;

          if(body_json.hasOwnProperty("refresh_token"))
            refresh_token = body_json["refresh_token"];
          else
            is_authorized = false;

          if(is_authorized){
            access_token_expire_at = millis() + token_expires_in * 1000;
            Serial.print("access_token:");
            //Serial.println(access_token);

            // send success message to web
            msg  = "{\"provider\": \"google\",";
            msg += "\"action\": \"SUCCESS\"}";
            websocket_send(msg);
            break;
          }
        }

        delay(interval * 1000);
      }
    }
    else
      Serial.println(F("Invalid resonse from Google"));
  }
  else
    Serial.println(F("NOT Connected to server"));
}
void sendingImage(){
  camera_fb_t *fb = capture();
  if(!fb || fb->format != PIXFORMAT_JPEG){
    Serial.println("Camera capture failed");
    esp_camera_fb_return(fb);
    return;
  }else{
    TJpgDec.drawJpg(0,0,(const uint8_t*)fb->buf, fb->len);

    tft.drawString("Wifi Connecting!", 8, 4, GFXFF);

    if(wifiConnect()){
      //tft.drawString("Wifi Connected!", 8, 4, GFXFF);
      TJpgDec.drawJpg(0,0,(const uint8_t*)fb->buf, fb->len);
      postingImage(fb);
    }else{
      tft.drawString("Check Wifi credential!", 8, 4, GFXFF);
    }
    esp_camera_fb_return(fb);
  }
}

void loop() {
  buttonEvent();

  if(isNormalMode)
    showingImage();

}
google-cloud-platform google-cloud-storage arduino-ide esp32 google-vision
1个回答
0
投票

一个更简单的答案是使用IoT Core:https://cloud.google.com/iot-core

本文:http://nilhcem.com/iot/cloud-iot-core-with-the-esp32-and-arduino

讨论了如何连接ESP32以发送温度数据,但是可以很容易地对其进行修改以发送图像数据。然后,一旦将图像数据输入Pub / Sub(它从IoT Core最终发布),就可以很容易地编写一个快速的Cloud Function(https://cloud.google.com/functions)来订阅Pub / Sub主题并推送到Cloud Storage。

[如果您DID想直接进入Cloud Storage,则可以,但是我没有创建oAuth路由,而是创建了一个服务帐户,并使用C ++ API:https://googleapis.dev/cpp/google-cloud-storage/latest/

© www.soinside.com 2019 - 2024. All rights reserved.