ESP32 Google Sheets – Cách ghi dữ liệu thông qua dịch vụ Google

Trong dự án chủ đề ESP32 Google Sheets lần này, mời bạn cùng IoTZone tìm hiểu cách ghi dữ liệu vào Google trang tính, bằng cách sử dụng dịch vụ của Google và API Google Sheets. Chúng ta sẽ sử dụng thư viện Arduino Google Sheets Client.

Trong bài viết này, mình sẽ hướng dẫn bạn cách xây dựng bộ ghi dữ liệu để lưu nhiệt độ, độ ẩm, áp suất và mốc thời gian đo dữ liệu tương ứng lên Google trang tính nhé!

Điều kiện cần thiết để xây dựng dự án ESP32 Google Sheets

Để làm được dự án ESP32 Google Sheets này, bạn cần có:

  • Tài khoản dịch vụ của Google
  • Phần mềm Arduino đã cài tiện ích ESP32, để phục vụ việc lập trình và upload code vào mạch.

Làm việc với tài khoản dịch vụ của Google

Để ghi dữ liệu vào Google Sheets một cách an toàn, chúng ta sẽ dùng tài khoản dịch vụ của Google (tên tiếng Anh là Google Service Account). Tài khoản này được xác định bởi 1 địa chỉ email duy nhất và là một tài khoản đặc biệt. Chúng thường được dùng trong 1 ứng dụng hoặc để phục vụ các công cụ tính toán, ví dụ như Compute Engine instance, thay vì phục vụ và liên kết với 1 cá nhân.

Tạo một dự án Google

Đầu tiên, chúng ta cần tạo 1 dự án trên Google và liên kết tài khoản dịch vụ với dự án đó. Bạn có thể thực hiện việc này trên chính tài khoản Google của mình hoặc một tài khoản phụ khác.

IoTZone khuyến khích bạn nên sử dụng 1 tài khoản email phụ chỉ để phục vụ các dự án IoT ESP32, điều này khiến chúng ta dễ quản lý và tăng tính bảo mật hơn.

Tạo tài khoản dịch vụ

1. Truy cập vào Google Cloud Console qua link sau: https://console.cloud.google.com/projectselector2/iam-admin/settings

2. Tạo 1 dự án mới hoặc chọn mở 1 dự án hiện có. Dưới đây là cách tạo 1 dự án mới: Click vào Create Project:

Tạo tài khoản dịch vụ Google để làm dự án ESP32 Google Sheets

3. Đặt tên cho dự án, và click vào Create, ví dụ như hình:

Tạo tài khoản dịch vụ Google để làm dự án ESP32 Google Sheets

Màn hình hiển thị như bên dưới, chứng tỏ bạn đã tạo thành công dự án:

Tạo tài khoản dịch vụ Google để làm dự án ESP32 Google Sheets

4. Bây giờ, chúng ta cần tạo 1 tài khoản dịch vụ Google cho dự án. Tại thanh bên trái, bạn click vào Service accounts, sau đó click vào +creative service account:

Tạo tài khoản dịch vụ Google để làm dự án ESP32 Google Sheets

5. Paste tên cho tài khoản dịch vụ, sau đó click vào create and continue:

Tạo tài khoản dịch vụ Google để làm dự án ESP32 Google Sheets

6. Chọn vai trò của tài khoản dịch vụ, cụ thể là Owner (chủ sở hữu), sau đó click Continue >> Done để hoàn tất việc tạo tài khoản dịch vụ cho dự án ESP32 Google Sheets lần này:

Hoàn tất việc Tạo tài khoản dịch vụ Google cho dự án ESP32 Google Sheets

Tạo key

Chọn dự án, click vào icon dấu ba chấm ở góc trên bên phải và chọn mục Manage keys:

Tạo key mới cho dự án ESP32 Google Sheets

Sau đó, click vào create new key để tạo khóa mới:

Tạo key mới cho dự án ESP32 Google Sheets

Chọn vào JSON và click vào Create:

Tạo key mới cho dự án ESP32 Google Sheets

Sau đó, hệ thống sẽ tải file JSON xuống kèm theo key của bạn. Sau khi mở file, bạn sẽ nhận được nội dung tương tự bên dưới, nhưng có thông tin chi tiết về khóa của riêng bạn:

{
  "type": "service_account",
  "project_id": "...",
  "private_key_id": "...",
  "private_key": "-----BEGIN PRIVATE KEY----- ...................\n-----END PRIVATE KEY-----\n",
  "client_email": ".....",
  "client_id": "....",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/...",
  "universe_domain": "googleapis.com"
}

Bạn hãy cop các thông tin project_id , client_email , Private_key_id và Private_key và lưu lại vào đâu đó, sau này chúng ta sẽ cần chúng khi viết code cho dự án ESP32 Google Sheets đó nhé!

Bật API Google Sheets

Bây giờ, chúng ta cần kích hoạt API Google Sheets cho dự án vừa tạo.

Bạn click vào link sau và bật API lên (lưu ý phải dùng cùng 1 tài khoản mà bạn đã tạo dự án): https://console.cloud.google.com/apis/library/sheets.googleapis.com

Bật API Google Sheets

Cài đặt thư viện trên Arduino IDE

Để ghi dữ liệu lên Google trang tính, chúng ta sẽ dùng đến thư viện ESP Google Sheet Client do Mobitz phát triển. Thư viện này hỗ trợ các thao tác như khởi tạo, đọc và xóa bảng tính, cũng như ghi thêm, cập nhật hoặc bổ sung dữ liệu vào Google Sheets.

Để thực hiện cài đặt, bạn mở Arduino IDE, click theo thứ tự Sketch >> Library >Manage Libraries, tìm kiếm tên ESP-Google-Sheet-Client và click vào Install để cài đặt chúng.

Cài đặt thư viện ESP Google Sheet Client trên Arduino IDE

Tạo bảng tính Google

Bạn mở Google trang tính và tạo 1 file Google Sheets mới, sau đó đặt tên phù hợp nhé, ví dụ như ESP32 Datalogging chẳng hạn:

Tạo google sheets với tên ESP32 Datalogging

Sau khi tạo xong, bạn cần chia sẻ file GG Sheets vừa tạo với tài khoản dịch vụ của Google. Cụ thể, chúng ta sẽ chia sẻ bảng tính với email của tài khoản dịch vụ.

Trong file JSON đã tải xuống trước đó, bạn sẽ thấy email tài khoản dịch vụ được lưu trong biến client_email.

Ở file GG Sheets, bạn click vào mục chia sẻ, dán email tài khoản dịch vụ vào và nhấn gửi:

Chia sẻ file google sheets với tài khoản dịch vụ Google

Làm việc với ESP32 và cảm biến BME280

Trong ví dụ về ESP32 Google Sheets lần này, mình sẽ sử dụng cảm biến BME280 để lưu các giá trị nhiệt độ, độ ẩm,… Bạn có thể sử dụng các cảm biến tương tự thay thế cũng được.

Kết nối phần cứng

Kết nối phần cứng cho dự án ESP32 Google Sheets

Chương trình mẫu

Bạn sao chép code sau vào Arduino IDE, và điều chỉnh một số thông tin như hướng dẫn bên dưới đoạn code để chúng chạy được nhé:

#include <Arduino.h>
#include <WiFi.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include "time.h"
#include <ESP_Google_Sheet_Client.h>

// For SD/SD_MMC mounting helper
#include <GS_SDHelper.h>

#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"

// Google Project ID
#define PROJECT_ID "REPLACE_WITH_YOUR_PROJECT_ID"

// Service Account's client email
#define CLIENT_EMAIL "REPLACE_WITH_YOUR_CLIENT_EMAIL"

// Service Account's private key
const char PRIVATE_KEY[] PROGMEM = "-----BEGIN PRIVATE KEY-----\ REPLACE_WITH_YOUR_PRIVATE_KEY\n-----END PRIVATE KEY-----\n";

// The ID of the spreadsheet where you'll publish the data
const char spreadsheetId[] = "YOUR_SPREADSHEET_ID";

// Timer variables
unsigned long lastTime = 0;  
unsigned long timerDelay = 30000;

// Token Callback function
void tokenStatusCallback(TokenInfo info);

// BME280 I2C
Adafruit_BME280 bme;
// Variables to hold sensor readings
float temp;
float hum;
float pres;

// NTP server to request epoch time
const char* ntpServer = "pool.ntp.org";

// Variable to save current epoch time
unsigned long epochTime; 

// Function that gets current epoch time
unsigned long getTime() {
  time_t now;
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    //Serial.println("Failed to obtain time");
    return(0);
  }
  time(&now);
  return now;
}

void setup(){

    Serial.begin(115200);
    Serial.println();
    Serial.println();

    //Configure time
    configTime(0, 0, ntpServer);

    // Initialize BME280 sensor 
    if (!bme.begin(0x76)) {
      Serial.println("Could not find a valid BME280 sensor, check wiring!");
      while (1);
    }

    GSheet.printf("ESP Google Sheet Client v%s\n\n", ESP_GOOGLE_SHEET_CLIENT_VERSION);

    // Connect to Wi-Fi
    WiFi.setAutoReconnect(true);
    WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  
    Serial.print("Connecting to Wi-Fi");
    while (WiFi.status() != WL_CONNECTED) {
      Serial.print(".");
      delay(1000);
    }
    Serial.println();
    Serial.print("Connected with IP: ");
    Serial.println(WiFi.localIP());
    Serial.println();

    // Set the callback for Google API access token generation status (for debug only)
    GSheet.setTokenCallback(tokenStatusCallback);

    // Set the seconds to refresh the auth token before expire (60 to 3540, default is 300 seconds)
    GSheet.setPrerefreshSeconds(10 * 60);

    // Begin the access token generation for Google API authentication
    GSheet.begin(CLIENT_EMAIL, PROJECT_ID, PRIVATE_KEY);
}

void loop(){
    // Call ready() repeatedly in loop for authentication checking and processing
    bool ready = GSheet.ready();

    if (ready && millis() - lastTime > timerDelay){
        lastTime = millis();

        FirebaseJson response;

        Serial.println("\nAppend spreadsheet values...");
        Serial.println("----------------------------");

        FirebaseJson valueRange;

        // New BME280 sensor readings
        temp = bme.readTemperature();
        //temp = 1.8*bme.readTemperature() + 32;
        hum = bme.readHumidity();
        pres = bme.readPressure()/100.0F;
        // Get timestamp
        epochTime = getTime();

        valueRange.add("majorDimension", "COLUMNS");
        valueRange.set("values/[0]/[0]", epochTime);
        valueRange.set("values/[1]/[0]", temp);
        valueRange.set("values/[2]/[0]", hum);
        valueRange.set("values/[3]/[0]", pres);

        // For Google Sheet API ref doc, go to https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/append
        // Append values to the spreadsheet
        bool success = GSheet.values.append(&response /* returned response */, spreadsheetId /* spreadsheet Id to append */, "Sheet1!A1" /* range to append */, &valueRange /* data range to append */);
        if (success){
            response.toString(Serial, true);
            valueRange.clear();
        }
        else{
            Serial.println(GSheet.errorReason());
        }
        Serial.println();
        Serial.println(ESP.getFreeHeap());
    }
}

void tokenStatusCallback(TokenInfo info){
    if (info.status == token_status_error){
        GSheet.printf("Token info: type = %s, status = %s\n", GSheet.getTokenType(info).c_str(), GSheet.getTokenStatus(info).c_str());
        GSheet.printf("Token error: %s\n", GSheet.getTokenError(info).c_str());
    }
    else{
        GSheet.printf("Token info: type = %s, status = %s\n", GSheet.getTokenType(info).c_str(), GSheet.getTokenStatus(info).c_str());
    }
}

Trước khi nạp code vào để chạy dự án ESP32 Google Sheets, bạn cần:

1. Điền thông tin tên và mật khẩu WiFi vào đoạn code:

#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"

2. Chèn các thông tin ID dự án, Client Email và Private Key mà bạn tìm thấy trong file JSON bạn đã tải về ở bước trước:

// Google Project ID
#define PROJECT_ID "REPLACE_WITH_YOUR_PROJECT_ID"

// Service Account's client email
#define CLIENT_EMAIL "REPLACE_WITH_YOUR_CLIENT_EMAIL"

// Service Account's private key
const char PRIVATE_KEY[] PROGMEM = "-----BEGIN PRIVATE KEY-----\ REPLACE_WITH_YOUR_PRIVATE_KEY\n-----END PRIVATE KEY-----\n";

3. Cuối cùng, chèn ID của file Google Sheets mà bạn muốn ghi dữ liệu lên:

// The ID of the spreadsheet where you'll publish the data
const char spreadsheetId[] = "YOUR_SPREADSHEET_ID";

Lưu ý: Nếu file Google Sheet đang có tên khác ngoài chữ Sheet1, chúng ta cần thay đổi Sheet1 thành ngôn ngữ tiếng Việt tương ứng ở dòng bên dưới:

bool success = GSheet.values.append(&response /* returned response */, spreadsheetId /* spreadsheet Id to append */, "Sheet1!A1" /* range to append */, &valueRange /* data range to append */);

Vậy là chúng ta đã hoàn thành dự án ESP32 Google Sheets! Bạn hãy nạp code vào mạch ESP32 và quan sát kết quả nhé, chúc bạn thành công!

IoTZone – Chuyên cung cấp thiết bị điện tử & tài liệu cho Makers

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *