我目前正在尝试让我的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();
}
一个更简单的答案是使用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/。