Manufaktur industri
Industri Internet of Things | bahan industri | Pemeliharaan dan Perbaikan Peralatan | Pemrograman industri |
home  MfgRobots >> Manufaktur industri >  >> Manufacturing Technology >> Proses manufaktur

Arduino Mega: Tangkap Foto dan Unggah Otomatis ke Google Drive

Komponen dan Perlengkapan

Arduino Mega: Tangkap Foto dan Unggah Otomatis ke Google Drive
Arduino Mega 2560
× 1
Arduino Mega: Tangkap Foto dan Unggah Otomatis ke Google Drive
PHPoC WiFi Shield 2 untuk Arduino
× 1
Arduino Mega: Tangkap Foto dan Unggah Otomatis ke Google Drive
Seeed Grove - Kit Kamera Serial
× 1
Seeed Grove base shield
× 1
Tombol
× 1

Tentang Proyek Ini

Jika Anda pemula, Anda dapat mempelajari tentang Arduino di sini.

Demonstrasi

Bagaimana Cara Kerjanya

1. Masuk ke Akun Google melalui OAuth 2.0 untuk perangkat IoT untuk mendapatkan access_token.

Proses masuk dijelaskan dalam proyek ini di Hackster.

2. Ketika tombol ditekan, Arduino mengambil gambar dari kamera, dan kemudian mengunggah ke Google Drive menggunakan access_token melalui Google Drive API.

Google Drive API untuk mengunggah file dijelaskan dalam dokumen Google.

Cara Melakukannya

Platform Hardware Lainnya

Saya membuat proyek yang sama untuk platform hardware lain di sini.

Kit Starter Arduino Terbaik untuk Pemula

Jika Anda mencari kit Arduino, lihat The Best Arduino Kit for Beginners


Referensi Fungsi

Kode

ArduinoGoogleDriveArduino
Ini adalah kode Arduino utama.
#include <Phpoc.h> #include <Arduino_JSON.h> #include "grove_camera.h" // Replace your GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET here String GOOGLE_CLIENT_ID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com"; String GOOGLE_CLIENT_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxx"; PhpocServer websocket_server(80); String http_resp_hearder(PhpocClient &client){ String hearder = ""; while(1){ if(client.available()){ String line = client.readLine(); if(line == "\r\n") break; else hearder += line; } if(!client.connected()){ client.stop(); break; } } return hearder; } String http_resp_body(PhpocClient &client){ String body = ""; while(1){ if(client.available()){ char c = client.read(); body += c; } if(!client.connected()){ client.stop(); break; } } return body; } String access_token = ""; String refresh_token = ""; unsigned long access_token_expire_at = 0; void websocket_send(String msg) { char wbuf[256]; msg.toCharArray(wbuf, msg.length() + 1); websocket_server.write(wbuf, msg.length()); } 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=https://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 cameraToGoogleDrive() { if(access_token == ""){ Serial.println(F("access_token is invalid")); return; } long picture_len = cameraGetPicture(); if(picture_len) { PhpocDateTime datetime; PhpocClient client; String file_name; String metadata; String jpeg_boundary; String end_boundary; datetime.date(F("YmdHis")); file_name = datetime.date(); metadata = F("--foo_bar_baz\r\n"); metadata += F("Content-Type: application/json; charset=UTF-8\r\n\r\n"); metadata += "{\"title\": \"ARDUINO_" + file_name + "\"}\r\n\r\n"; jpeg_boundary = F("--foo_bar_baz\r\n"); jpeg_boundary += F("Content-Type: image/jpeg\r\n\r\n"); end_boundary = F("\r\n--foo_bar_baz--"); unsigned long body_len =metadata.length() + jpeg_boundary.length() + picture_len + end_boundary.length(); int total = 0; if(client.connectSSL("www.googleapis.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 /upload/drive/v2/files?uploadType=multipart HTTP/1.1")); client.println(F("Host: www.googleapis.com")); client.println(F("Connection: close")); client.println(F("Accept: */*")); client.println(F("Content-Type: multipart/related; boundary=foo_bar_baz")); client.print(F("Content-Length: ")); client.println(body_len); client.print(F("Authorization: Bearer ")); client.println(access_token); client.println(); client.print(metadata); client.print(jpeg_boundary); int i; int packet_num = cameraPacketNum(); char packet[PIC_PKT_LEN] = {0}; for(i = 0; i < packet_num; i++) { long packet_len = cameraGetPacket(i, packet); client.write((const uint8_t *)&packet[4], packet_len - 6); total += packet_len - 6; } cameraGetPacket(i, packet); client.print(end_boundary); String response_hearder = http_resp_hearder(client); String response_body = http_resp_body(client); //Serial.println(response_hearder); Serial.println(response_body); } } else { Serial.print("picture_len:"); Serial.println(picture_len); } } int buttonState; int lastButtonState = LOW; unsigned long lastDebounceTime = 0; unsigned long debounceDelay = 50; bool isButtonPressed(int pin) { int reading = digitalRead(pin); if (reading != lastButtonState) lastDebounceTime = millis(); if ((millis() - lastDebounceTime) > debounceDelay) { if (reading != buttonState) { buttonState = reading; if (buttonState == HIGH) { return true; } } } lastButtonState = reading; return false; } void setup(){ Serial.begin(115200); while(!Serial) ; Phpoc.begin(PF_LOG_SPI | PF_LOG_NET); websocket_server.beginWebSocket("login"); Serial.print("WebSocket server address : "); Serial.println(Phpoc.localIP()); pinMode(2, INPUT); cameraInit(CT_JPEG, PR_160x120, JR_640x480); } void loop(){ PhpocClient client = websocket_server.available(); if (client) { String ws_str = client.readLine(); if(ws_str == "google\r\n") { googleDeviceOAuthLogin(); } } if(isButtonPressed(2)) { if(access_token != "" && access_token_expire_at > millis()) cameraToGoogleDrive(); else Serial.println("access_token is invalid, please login again"); } } 
login.phpPHP
File ini diunggah ke PHPoC Shield. Ini menyediakan Antarmuka Pengguna Web untuk proses Masuk Google
<html> <head> <title>PHPoC / <?echo system("uname -i")?></title> <meta content="initial-scale=1.0, maximum-scale=1.0, minimum-scale=0.5, width=device-width, user-scalable=yes" name="viewport"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto" type="text/css"> <style> body { text-align:center; } .center { margin: auto; position: absolute; -webkit-backface-visibility: hidden; left:0; right:0; text-align: center; top: 20%; } .hearder { width: 100%; max-width:400px; color: #008B8B; padding: 5px; border-bottom: solid; margin-bottom: 5px; font-size: 200%; display: inline-block; } .wc_text, .loader { display: inline-block; width: 100%; max-width:300px; line-height: 150%; } .code { font-family: "Courier New", Courier, monospace; font-size: 150%; font-weight: bold; color: #A52A2A; } .success {font-weight: bold; color: #A52A2A;} /*loading icon*/ .lds-roller { display: inline-block; position: relative; width: 64px; height: 64px; } .lds-roller div { animation: lds-roller 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite; transform-origin: 32px 32px; } .lds-roller div:after { content: " "; display: block; position: absolute; width: 6px; height: 6px; border-radius: 50%; background: #A52A2A; margin: -3px 0 0 -3px; } .lds-roller div:nth-child(1) {animation-delay: -0.036s;} .lds-roller div:nth-child(1):after {top: 50px;left: 50px;} .lds-roller div:nth-child(2) {animation-delay: -0.072s;} .lds-roller div:nth-child(2):after {top: 54px;left: 45px;} .lds-roller div:nth-child(3) {animation-delay: -0.108s;} .lds-roller div:nth-child(3):after {top: 57px;left: 39px;} .lds-roller div:nth-child(4) {animation-delay: -0.144s;} .lds-roller div:nth-child(4):after {top: 58px;left: 32px;} .lds-roller div:nth-child(5) {animation-delay: -0.18s;} .lds-roller div:nth-child(5):after {top: 57px;left: 25px;} .lds-roller div:nth-child(6) {animation-delay: -0.216s;} .lds-roller div:nth-child(6):after {top: 54px;left: 19px;} .lds-roller div:nth-child(7) {animation-delay: -0.252s;} .lds-roller div:nth-child(7):after {top: 50px;left: 14px;} .lds-roller div:nth-child(8) {animation-delay: -0.288s;} .lds-roller div:nth-child(8):after {top: 45px;left: 10px;} @keyframes lds-roller {0% {transform: rotate(0deg);}100% {transform: rotate(360deg);}} </style> <script> var ws; function init() { ws = new WebSocket("ws://<?echo _SERVER("HTTP_HOST")?>/login", "text.phpoc"); ws.onopen = ws_onopen; ws.onclose = ws_onclose; ws.onmessage = ws_onmessage; } function ws_onopen() { if(ws && (ws.readyState == 1)) ws.send('google\r\n'); } function ws_onclose() { alert('CANNOT connect to device. Please reload webpage'); ws.onopen = null; ws.onclose = null; ws.onmessage = null; ws = null; } function ws_onmessage(e_msg) { e_msg = e_msg || window.event; // MessageEvent var obj = JSON.parse(e_msg.data); var wc_text = document.getElementById('wc_text'); if(obj.action == 'LOGIN') { wc_text.innerHTML = 'Next, visit <a href="' + obj.verification_url + '" target="_blank">' + obj.verification_url + '</a> and enter this code:<br>'; wc_text.innerHTML += '<span class="code">' + obj.user_code + '</span>'; } else if(obj.action == 'SUCCESS') { document.getElementById('loader').style.display = 'none'; wc_text.innerHTML = '<span class="success">Success!</span><br>'; wc_text.innerHTML += 'You are now logged in from Arduino via PHPoC Shield'; } } window.onload = init; </script> </head> <body> <div class="center"> <div class="hearder"> <div style="font-size: 150%"> <span style="color:#4285F4">G</span> <span style="color:#EA4335;">o</span> <span style="color:#FBBC05;">o</span> <span style="color:#4285F4;">g</span> <span style="color:#34A853;">l</span> <span style="color:#EA4335;">e</span> </div> Login for Arduino </div> <br><br> <div class="wc_text" id="wc_text"></div><br><br> <div class="loader" id="loader"> <div class="lds-roller"><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div> </div> </div> </body> </html> 
grove_camera.hC/C++
Library untuk Kamera Grove
#define PIC_PKT_LEN 512 //data length of each read, dont set this too big because ram is limited #define CAM_ADDR 0 //Color Type #define CT_GRAYSCALE_2 0x01 #define CT_GRAYSCALE_4 0x02 #define CT_GRAYSCALE_8 0x03 #define CT_COLOR_12 0x05 #define CT_COLOR_16 0x06 #define CT_JPEG 0x07 //Preview Resolution #define PR_80x60 0x01 #define PR_160x120 0x03 // JPEG Resolution #define JR_80x64 0x01 #define JR_160x128 0x03 #define JR_320x240 0x05 #define JR_640x480 0x07 const byte camera_address = (CAM_ADDR << 5); // address unsigned int camera_packet_num; unsigned int camera_last_packet_len; void cameraClearRxBuf(){ while (Serial.available()){ Serial.read(); } } void cameraSendCmd(char cmd[], int cmd_len){ for (char i = 0; i < cmd_len; i++) Serial.print(cmd[i]); } unsigned int cameraPacketNum(){ return camera_packet_num; } void cameraInit(int color_type, int preview_resolution, int jpeg_resolution){ char cmd[] = {0xaa,0x0d|camera_address,0x00,0x00,0x00,0x00} ; unsigned char resp[6]; Serial.setTimeout(500); while (1){ cameraSendCmd(cmd,6); if(Serial.readBytes((char *)resp, 6) != 6) continue; if(resp[0] == 0xaa && resp[1] == (0x0e | camera_address) && resp[2] == 0x0d && resp[4] == 0 && resp[5] == 0) { if(Serial.readBytes((char *)resp, 6) != 6) continue; if(resp[0] == 0xaa && resp[1] == (0x0d | camera_address) && resp[2] == 0 && resp[3] == 0 && resp[4] == 0 && resp[5] == 0) break; } } cmd[1] = 0x0e | camera_address; cmd[2] = 0x0d; cameraSendCmd(cmd, 6); char cmd2[] = { 0xaa, 0x01 | camera_address, 0x00, color_type, preview_resolution, jpeg_resolution}; Serial.setTimeout(100); while (1){ cameraClearRxBuf(); cameraSendCmd(cmd2, 6); if(Serial.readBytes((char *)resp, 6) != 6) continue; if(resp[0] == 0xaa && resp[1] == (0x0e | camera_address) && resp[2] == 0x01 && resp[4] == 0 && resp[5] == 0) break; } char cmd3[] = { 0xaa, 0x06 | camera_address, 0x08, PIC_PKT_LEN & 0xff, (PIC_PKT_LEN>>8) & 0xff ,0}; while (1) { cameraClearRxBuf(); cameraSendCmd(cmd3, 6); if(Serial.readBytes((char *)resp, 6) != 6) continue; if(resp[0] == 0xaa && resp[1] == (0x0e | camera_address) && resp[2] == 0x06 && resp[4] == 0 && resp[5] == 0) break; } } long cameraGetPicture(){ char cmd[] = { 0xaa, 0x04 | camera_address, 0x01, 0x00, 0x00, 0x00 }; unsigned char resp[6]; unsigned long picTotalLen = 0; // picture length while (1){ cameraClearRxBuf(); cameraSendCmd(cmd, 6); if(Serial.readBytes((char *)resp, 6) != 6) continue; if(resp[0] == 0xaa && resp[1] == (0x0e | camera_address) && resp[2] == 0x04 && resp[4] == 0 && resp[5] == 0){ Serial.setTimeout(1000); if(Serial.readBytes((char *)resp, 6) != 6) continue; if(resp[0] == 0xaa && resp[1] == (0x0a | camera_address) && resp[2] == 0x01){ picTotalLen = (resp[3]) | (resp[4] << 8) | (resp[5] << 16); break; } } } camera_packet_num = (picTotalLen) / (PIC_PKT_LEN - 6); camera_last_packet_len = PIC_PKT_LEN; if((picTotalLen % (PIC_PKT_LEN-6)) != 0){ camera_packet_num += 1; camera_last_packet_len = picTotalLen % (PIC_PKT_LEN - 6) + 6; } return picTotalLen; } long cameraGetPacket(unsigned int i, char* buf){ char cmd[] = { 0xaa, 0x0e | camera_address, 0x00, 0x00, 0x00, 0x00 }; Serial.setTimeout(100); if(i < camera_packet_num) { cmd[4] = i & 0xff; cmd[5] = (i >> 8) & 0xff; cameraClearRxBuf(); cameraSendCmd(cmd, 6); int pkt_len; if(i < (camera_packet_num - 1)) pkt_len = PIC_PKT_LEN ; else pkt_len = camera_last_packet_len; uint16_t cnt = Serial.readBytes((char *)buf, pkt_len); return cnt; } else { cmd[4] = 0xf0; cmd[5] = 0xf0; cameraSendCmd(cmd, 6); } return ""; } 

Skema Rangkaian

Arduino Mega: Tangkap Foto dan Unggah Otomatis ke Google Drive

Proses manufaktur

  1. Membuat Spybot Arduino yang Dikontrol melalui Bluetooth
  2. FlickMote: Remote IR Kendali Gestur untuk Rumah Cerdas
  3. DIY Arduino TV B-Gone: Remote Universal untuk Semua TV
  4. Bangun Jam Master LED Kustom dengan Alarm – Terlihat dari Jarak 12 Meter
  5. Find Me: Pelacak Item Cerdas dengan Arduino dan Bluetooth
  6. Solusi Daya Teroptimasi untuk Proyek Arduino
  7. Tic Tac Toe Arduino dengan Matriks LED MAX7219 dan Kotak Kardus
  8. Membuat Robot Quadruped Arduino Cerdas: Panduan Langkah demi Langkah
  9. Peralatan Rumah Tangga Diaktifkan Suara: Kontrol Bluetooth dengan Google Assistant
  10. Investasi $450M Google di ADT Mempercepat Adopsi Keamanan IoT