From 76fa10e0bf415409cd485e8e134019f7a6c418d8 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 1 Feb 2023 12:52:21 +0700 Subject: [PATCH] Add support Service Account JSON file for authentication. --- README.md | 10 ++ examples/Ethernet/ESP8266/ESP8266.ino | 18 +++ examples/Ethernet/Pico/Pico.ino | 7 + .../ServiceAccountFile/ServiceAccountFile.ino | 137 +++++++++++++++++ examples/ServiceAccountFile/data/gtsr1.pem | 31 ++++ examples/Sheets/CopyTo/CopyTo.ino | 47 +++++- examples/Spreadsheets/Create/Create.ino | 44 ++++++ examples/Spreadsheets/Delete/Delete.ino | 44 ++++++ examples/Spreadsheets/Get/Get.ino | 44 ++++++ examples/Spreadsheets/List/List.ino | 45 ++++++ examples/Values/Append/Append.ino | 11 +- examples/Values/Clear/Clear.ino | 45 ++++++ .../Create_Update_Read/Create_Update_Read.ino | 45 ++++++ examples/Values/Read/Read.ino | 11 +- examples/Values/Update/Update.ino | 11 +- library.json | 2 +- library.properties | 2 +- src/ESP_Google_Sheet_Client.cpp | 40 +++-- src/ESP_Google_Sheet_Client.h | 37 +++-- src/ESP_Google_Sheet_Client_FS_Config.h | 3 + src/GS_Const.h | 11 +- src/GS_Error.h | 5 +- src/GS_SDHelper.h | 145 ++++++++++++++++++ src/auth/GAuthManager.cpp | 47 ++++-- 24 files changed, 795 insertions(+), 47 deletions(-) create mode 100644 examples/ServiceAccountFile/ServiceAccountFile.ino create mode 100644 examples/ServiceAccountFile/data/gtsr1.pem create mode 100644 src/GS_SDHelper.h diff --git a/README.md b/README.md index 9cbe813..3da2438 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,10 @@ Go to [Google Cloud Console](https://console.cloud.google.com/projectselector2/i ![Create SA9](/media/images/GC_Create_SA9.png) +In the following stepts (15-16) for saving the Service Account Credential in flash memory at compile time. + +If you want to allow library to read the Service Account JSON key file directly at run time, skip these steps. + 15. Open the .json file that is already downloaded with text editor. ```json @@ -268,6 +272,12 @@ void setup() //Begin the access token generation for Google API authentication GSheet.begin(CLIENT_EMAIL, PROJECT_ID, PRIVATE_KEY); + + // In case SD/SD_MMC storage file access, mount the SD/SD_MMC card. + // SD_Card_Mounting(); // See src/GS_SDHelper.h + + // Or begin with the Service Account JSON file that uploaded to the Filesystem image or stored in SD memory card. + // GSheet.begin("path/to/serviceaccount/json/file", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); } diff --git a/examples/Ethernet/ESP8266/ESP8266.ino b/examples/Ethernet/ESP8266/ESP8266.ino index 65813ad..3c41ec9 100644 --- a/examples/Ethernet/ESP8266/ESP8266.ino +++ b/examples/Ethernet/ESP8266/ESP8266.ino @@ -29,6 +29,23 @@ * */ +/** + * Do not forget to defines the following macros in ESP_Google_Sheet_Client_FS_Config.h + * + * #define ESP_GOOGLE_SHEET_CLIENT_ENABLE_EXTERNAL_CLIENT + * + * For ESP8266 ENC28J60 Ethernet module + * #define ENABLE_ESP8266_ENC28J60_ETH + * + * For ESP8266 W5100 Ethernet module + * #define ENABLE_ESP8266_W5100_ETH + * + * For ESP8266 W5500 Ethernet module + * #define ENABLE_ESP8266_W5500_ETH + * + */ + + #include #if defined(ESP8266) #include @@ -62,6 +79,7 @@ ENC28J60lwIP eth(ETH_CS_PIN); //Wiznet5100lwIP eth(ETH_CS_PIN); //Wiznet5500lwIP eth(ETH_CS_PIN); + // UDP Client for NTP Time synching EthernetUDP udpClient; diff --git a/examples/Ethernet/Pico/Pico.ino b/examples/Ethernet/Pico/Pico.ino index 111bd4f..c8934d1 100644 --- a/examples/Ethernet/Pico/Pico.ino +++ b/examples/Ethernet/Pico/Pico.ino @@ -32,6 +32,13 @@ * */ +/** + * Do not forget to defines the following macro in ESP_Google_Sheet_Client_FS_Config.h + * + * #define ESP_GOOGLE_SHEET_CLIENT_ENABLE_EXTERNAL_CLIENT + * + */ + #include #include diff --git a/examples/ServiceAccountFile/ServiceAccountFile.ino b/examples/ServiceAccountFile/ServiceAccountFile.ino new file mode 100644 index 0000000..41d90cb --- /dev/null +++ b/examples/ServiceAccountFile/ServiceAccountFile.ino @@ -0,0 +1,137 @@ + +/** + * Created by K. Suwatchai (Mobizt) + * + * Email: k_suwatchai@hotmail.com + * + * Github: https://github.com/mobizt + * + * Copyright (c) 2023 mobizt + * + */ + +/** This example will show how to authenticate using the Service Account file. */ + +#include +#if defined(ESP32) || defined(PICO_RP2040) +#include +#elif defined(ESP8266) +#include +#endif +#include + +// For SD/SD_MMC mounting helper +#include + +#define WIFI_SSID "WIFI_AP" +#define WIFI_PASSWORD "WIFI_PASSWORD" + +/** +const char rootCACert[] PROGMEM = "-----BEGIN CERTIFICATE-----\n" + "MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw\n" + "CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU\n" + "MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw\n" + "MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp\n" + "Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA\n" + "A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo\n" + "27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w\n" + "Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw\n" + "TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl\n" + "qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH\n" + "szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8\n" + "Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk\n" + "MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92\n" + "wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p\n" + "aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN\n" + "VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID\n" + "AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E\n" + "FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb\n" + "C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe\n" + "QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy\n" + "h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4\n" + "7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J\n" + "ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef\n" + "MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/\n" + "Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT\n" + "6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ\n" + "0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm\n" + "2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb\n" + "bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c\n" + "-----END CERTIFICATE-----\n"; +*/ + +#if defined(ARDUINO_RASPBERRY_PI_PICO_W) +WiFiMulti multi; +#endif + +void tokenStatusCallback(TokenInfo info); + +void setup() +{ + + Serial.begin(115200); + Serial.println(); + Serial.println(); + + Serial.printf("ESP Google Sheet Client v%s\n\n", ESP_GOOGLE_SHEET_CLIENT_VERSION); + +#if defined(ESP32) || defined(ESP8266) + WiFi.setAutoReconnect(true); +#endif + +#if defined(ARDUINO_RASPBERRY_PI_PICO_W) + multi.addAP(WIFI_SSID, WIFI_PASSWORD); + multi.run(); +#else + WiFi.begin(WIFI_SSID, WIFI_PASSWORD); +#endif + + Serial.print("Connecting to Wi-Fi"); + unsigned long ms = millis(); + while (WiFi.status() != WL_CONNECTED) + { + Serial.print("."); + delay(300); +#if defined(ARDUINO_RASPBERRY_PI_PICO_W) + if (millis() - ms > 10000) + break; +#endif + } + Serial.println(); + Serial.print("Connected with IP: "); + Serial.println(WiFi.localIP()); + Serial.println(); + + // In case SD/SD_MMC storage file access, mount the SD/SD_MMC card. + // SD_Card_Mounting(); // See src/GS_SDHelper.h + + GSheet.setCertFile("/gtsr1.pem", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); + + // Set the callback for Google API access token generation status (for debug only) + GSheet.setTokenCallback(tokenStatusCallback); + + // The WiFi credentials are required for Pico W + // due to it does not have reconnect feature. +#if defined(ARDUINO_RASPBERRY_PI_PICO_W) + GSheet.clearAP(); + GSheet.addAP(WIFI_SSID, WIFI_PASSWORD); +#endif + + // 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("path/to/serviceaccount/json/file", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); +} + +void loop() +{ + + bool ready = GSheet.ready(); + + if (ready) + { + + // Google sheet code here + } +} \ No newline at end of file diff --git a/examples/ServiceAccountFile/data/gtsr1.pem b/examples/ServiceAccountFile/data/gtsr1.pem new file mode 100644 index 0000000..a13aa05 --- /dev/null +++ b/examples/ServiceAccountFile/data/gtsr1.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo +27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w +Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw +TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl +qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH +szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8 +Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk +MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92 +wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p +aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN +VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID +AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb +C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe +QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy +h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4 +7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J +ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef +MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/ +Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT +6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ +0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm +2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb +bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c +-----END CERTIFICATE----- diff --git a/examples/Sheets/CopyTo/CopyTo.ino b/examples/Sheets/CopyTo/CopyTo.ino index fd9b5f2..c25ac90 100644 --- a/examples/Sheets/CopyTo/CopyTo.ino +++ b/examples/Sheets/CopyTo/CopyTo.ino @@ -20,6 +20,9 @@ #endif #include +// For SD/SD_MMC mounting helper +#include + #define WIFI_SSID "WIFI_AP" #define WIFI_PASSWORD "WIFI_PASSWORD" @@ -33,6 +36,40 @@ // Service Account's private key const char PRIVATE_KEY[] PROGMEM = "-----BEGIN PRIVATE KEY-----XXXXXXXXXXXX-----END PRIVATE KEY-----\n"; +/** +const char rootCACert[] PROGMEM = "-----BEGIN CERTIFICATE-----\n" + "MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw\n" + "CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU\n" + "MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw\n" + "MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp\n" + "Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA\n" + "A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo\n" + "27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w\n" + "Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw\n" + "TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl\n" + "qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH\n" + "szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8\n" + "Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk\n" + "MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92\n" + "wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p\n" + "aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN\n" + "VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID\n" + "AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E\n" + "FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb\n" + "C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe\n" + "QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy\n" + "h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4\n" + "7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J\n" + "ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef\n" + "MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/\n" + "Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT\n" + "6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ\n" + "0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm\n" + "2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb\n" + "bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c\n" + "-----END CERTIFICATE-----\n"; +*/ + bool taskComplete = false; #if defined(ARDUINO_RASPBERRY_PI_PICO_W) @@ -77,6 +114,11 @@ void setup() Serial.println(WiFi.localIP()); Serial.println(); + // In case SD/SD_MMC storage file access, mount the SD/SD_MMC card. + // SD_Card_Mounting(); // See src/GS_SDHelper.h + + // GSheet.setCert(rootCACert); // or GSheet.setCertFile("path/to/certificate/file.pem", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); + // Set the callback for Google API access token generation status (for debug only) GSheet.setTokenCallback(tokenStatusCallback); @@ -90,8 +132,11 @@ void setup() // 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 + // Begin the access token generation for Google API authentication GSheet.begin(CLIENT_EMAIL, PROJECT_ID, PRIVATE_KEY); + + // Or begin with the Service Account JSON file + // GSheet.begin("path/to/serviceaccount/json/file", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); } void loop() diff --git a/examples/Spreadsheets/Create/Create.ino b/examples/Spreadsheets/Create/Create.ino index a283e6b..176b95b 100644 --- a/examples/Spreadsheets/Create/Create.ino +++ b/examples/Spreadsheets/Create/Create.ino @@ -20,6 +20,9 @@ #endif #include +// For SD/SD_MMC mounting helper +#include + #define WIFI_SSID "WIFI_AP" #define WIFI_PASSWORD "WIFI_PASSWORD" @@ -36,6 +39,40 @@ // Service Account's private key const char PRIVATE_KEY[] PROGMEM = "-----BEGIN PRIVATE KEY-----XXXXXXXXXXXX-----END PRIVATE KEY-----\n"; +/** +const char rootCACert[] PROGMEM = "-----BEGIN CERTIFICATE-----\n" + "MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw\n" + "CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU\n" + "MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw\n" + "MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp\n" + "Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA\n" + "A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo\n" + "27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w\n" + "Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw\n" + "TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl\n" + "qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH\n" + "szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8\n" + "Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk\n" + "MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92\n" + "wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p\n" + "aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN\n" + "VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID\n" + "AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E\n" + "FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb\n" + "C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe\n" + "QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy\n" + "h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4\n" + "7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J\n" + "ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef\n" + "MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/\n" + "Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT\n" + "6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ\n" + "0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm\n" + "2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb\n" + "bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c\n" + "-----END CERTIFICATE-----\n"; +*/ + bool taskComplete = false; #if defined(ARDUINO_RASPBERRY_PI_PICO_W) @@ -80,6 +117,11 @@ void setup() Serial.println(WiFi.localIP()); Serial.println(); + // In case SD/SD_MMC storage file access, mount the SD/SD_MMC card. + // SD_Card_Mounting(); // See src/GS_SDHelper.h + + // GSheet.setCert(rootCACert); // or GSheet.setCertFile("path/to/certificate/file.pem", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); + // Set the callback for Google API access token generation status (for debug only) GSheet.setTokenCallback(tokenStatusCallback); @@ -96,6 +138,8 @@ void setup() // Begin the access token generation for Google API authentication GSheet.begin(CLIENT_EMAIL, PROJECT_ID, PRIVATE_KEY); + // Or begin with the Service Account JSON file + // GSheet.begin("path/to/serviceaccount/json/file", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); } void loop() diff --git a/examples/Spreadsheets/Delete/Delete.ino b/examples/Spreadsheets/Delete/Delete.ino index a787f05..2ace7f5 100644 --- a/examples/Spreadsheets/Delete/Delete.ino +++ b/examples/Spreadsheets/Delete/Delete.ino @@ -20,6 +20,9 @@ #endif #include +// For SD/SD_MMC mounting helper +#include + #define WIFI_SSID "WIFI_AP" #define WIFI_PASSWORD "WIFI_PASSWORD" @@ -33,6 +36,40 @@ // Service Account's private key const char PRIVATE_KEY[] PROGMEM = "-----BEGIN PRIVATE KEY-----XXXXXXXXXXXX-----END PRIVATE KEY-----\n"; +/** +const char rootCACert[] PROGMEM = "-----BEGIN CERTIFICATE-----\n" + "MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw\n" + "CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU\n" + "MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw\n" + "MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp\n" + "Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA\n" + "A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo\n" + "27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w\n" + "Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw\n" + "TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl\n" + "qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH\n" + "szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8\n" + "Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk\n" + "MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92\n" + "wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p\n" + "aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN\n" + "VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID\n" + "AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E\n" + "FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb\n" + "C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe\n" + "QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy\n" + "h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4\n" + "7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J\n" + "ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef\n" + "MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/\n" + "Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT\n" + "6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ\n" + "0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm\n" + "2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb\n" + "bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c\n" + "-----END CERTIFICATE-----\n"; +*/ + bool taskComplete = false; #if defined(ARDUINO_RASPBERRY_PI_PICO_W) @@ -78,6 +115,11 @@ void setup() Serial.println(WiFi.localIP()); Serial.println(); + // In case SD/SD_MMC storage file access, mount the SD/SD_MMC card. + // SD_Card_Mounting(); // See src/GS_SDHelper.h + + // GSheet.setCert(rootCACert); // or GSheet.setCertFile("path/to/certificate/file.pem", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); + // Set the callback for Google API access token generation status (for debug only) GSheet.setTokenCallback(tokenStatusCallback); @@ -93,6 +135,8 @@ void setup() // Begin the access token generation for Google API authentication GSheet.begin(CLIENT_EMAIL, PROJECT_ID, PRIVATE_KEY); + // Or begin with the Service Account JSON file + // GSheet.begin("path/to/serviceaccount/json/file", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); } void loop() diff --git a/examples/Spreadsheets/Get/Get.ino b/examples/Spreadsheets/Get/Get.ino index 3e10e3c..7fc03c1 100644 --- a/examples/Spreadsheets/Get/Get.ino +++ b/examples/Spreadsheets/Get/Get.ino @@ -20,6 +20,9 @@ #endif #include +// For SD/SD_MMC mounting helper +#include + #define WIFI_SSID "WIFI_AP" #define WIFI_PASSWORD "WIFI_PASSWORD" @@ -33,6 +36,40 @@ // Service Account's private key const char PRIVATE_KEY[] PROGMEM = "-----BEGIN PRIVATE KEY-----XXXXXXXXXXXX-----END PRIVATE KEY-----\n"; +/** +const char rootCACert[] PROGMEM = "-----BEGIN CERTIFICATE-----\n" + "MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw\n" + "CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU\n" + "MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw\n" + "MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp\n" + "Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA\n" + "A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo\n" + "27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w\n" + "Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw\n" + "TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl\n" + "qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH\n" + "szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8\n" + "Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk\n" + "MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92\n" + "wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p\n" + "aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN\n" + "VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID\n" + "AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E\n" + "FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb\n" + "C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe\n" + "QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy\n" + "h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4\n" + "7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J\n" + "ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef\n" + "MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/\n" + "Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT\n" + "6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ\n" + "0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm\n" + "2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb\n" + "bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c\n" + "-----END CERTIFICATE-----\n"; +*/ + bool taskComplete = false; #if defined(ARDUINO_RASPBERRY_PI_PICO_W) @@ -77,6 +114,11 @@ void setup() Serial.println(WiFi.localIP()); Serial.println(); + // In case SD/SD_MMC storage file access, mount the SD/SD_MMC card. + // SD_Card_Mounting(); // See src/GS_SDHelper.h + + // GSheet.setCert(rootCACert); // or GSheet.setCertFile("path/to/certificate/file.pem", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); + // Set the callback for Google API access token generation status (for debug only) GSheet.setTokenCallback(tokenStatusCallback); @@ -93,6 +135,8 @@ void setup() // Begin the access token generation for Google API authentication GSheet.begin(CLIENT_EMAIL, PROJECT_ID, PRIVATE_KEY); + // Or begin with the Service Account JSON file + // GSheet.begin("path/to/serviceaccount/json/file", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); } void loop() diff --git a/examples/Spreadsheets/List/List.ino b/examples/Spreadsheets/List/List.ino index 2709943..de3b0a1 100644 --- a/examples/Spreadsheets/List/List.ino +++ b/examples/Spreadsheets/List/List.ino @@ -20,6 +20,9 @@ #endif #include +// For SD/SD_MMC mounting helper +#include + #define WIFI_SSID "WIFI_AP" #define WIFI_PASSWORD "WIFI_PASSWORD" @@ -33,6 +36,40 @@ // Service Account's private key const char PRIVATE_KEY[] PROGMEM = "-----BEGIN PRIVATE KEY-----XXXXXXXXXXXX-----END PRIVATE KEY-----\n"; +/** +const char rootCACert[] PROGMEM = "-----BEGIN CERTIFICATE-----\n" + "MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw\n" + "CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU\n" + "MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw\n" + "MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp\n" + "Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA\n" + "A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo\n" + "27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w\n" + "Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw\n" + "TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl\n" + "qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH\n" + "szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8\n" + "Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk\n" + "MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92\n" + "wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p\n" + "aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN\n" + "VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID\n" + "AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E\n" + "FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb\n" + "C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe\n" + "QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy\n" + "h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4\n" + "7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J\n" + "ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef\n" + "MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/\n" + "Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT\n" + "6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ\n" + "0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm\n" + "2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb\n" + "bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c\n" + "-----END CERTIFICATE-----\n"; +*/ + bool taskComplete = false; #if defined(ARDUINO_RASPBERRY_PI_PICO_W) @@ -77,6 +114,11 @@ void setup() Serial.println(WiFi.localIP()); Serial.println(); + // In case SD/SD_MMC storage file access, mount the SD/SD_MMC card. + // SD_Card_Mounting(); // See src/GS_SDHelper.h + + // GSheet.setCert(rootCACert); // or GSheet.setCertFile("path/to/certificate/file.pem", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); + // Set the callback for Google API access token generation status (for debug only) GSheet.setTokenCallback(tokenStatusCallback); @@ -92,6 +134,9 @@ void setup() // Begin the access token generation for Google API authentication GSheet.begin(CLIENT_EMAIL, PROJECT_ID, PRIVATE_KEY); + + // Or begin with the Service Account JSON file + // GSheet.begin("path/to/serviceaccount/json/file", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); } void loop() diff --git a/examples/Values/Append/Append.ino b/examples/Values/Append/Append.ino index 3d2893d..5aaad95 100644 --- a/examples/Values/Append/Append.ino +++ b/examples/Values/Append/Append.ino @@ -20,6 +20,9 @@ #endif #include +// For SD/SD_MMC mounting helper +#include + #define WIFI_SSID "WIFI_AP" #define WIFI_PASSWORD "WIFI_PASSWORD" @@ -111,7 +114,10 @@ void setup() Serial.println(WiFi.localIP()); Serial.println(); - // GSheet.setCert(rootCACert); // or GSheet.setCertFile("<.pem cert file name>", esP_google_sheet_file_storage_type_flash /* or esP_google_sheet_file_storage_type_sd */); + // In case SD/SD_MMC storage file access, mount the SD/SD_MMC card. + // SD_Card_Mounting(); // See src/GS_SDHelper.h + + // GSheet.setCert(rootCACert); // or GSheet.setCertFile("path/to/certificate/file.pem", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); // Set the callback for Google API access token generation status (for debug only) GSheet.setTokenCallback(tokenStatusCallback); @@ -128,6 +134,9 @@ void setup() // Begin the access token generation for Google API authentication GSheet.begin(CLIENT_EMAIL, PROJECT_ID, PRIVATE_KEY); + + // Or begin with the Service Account JSON file + // GSheet.begin("path/to/serviceaccount/json/file", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); } void loop() diff --git a/examples/Values/Clear/Clear.ino b/examples/Values/Clear/Clear.ino index f75c353..5e17261 100644 --- a/examples/Values/Clear/Clear.ino +++ b/examples/Values/Clear/Clear.ino @@ -20,6 +20,9 @@ #endif #include +// For SD/SD_MMC mounting helper +#include + #define WIFI_SSID "WIFI_AP" #define WIFI_PASSWORD "WIFI_PASSWORD" @@ -33,6 +36,40 @@ // Service Account's private key const char PRIVATE_KEY[] PROGMEM = "-----BEGIN PRIVATE KEY-----XXXXXXXXXXXX-----END PRIVATE KEY-----\n"; +/** +const char rootCACert[] PROGMEM = "-----BEGIN CERTIFICATE-----\n" + "MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw\n" + "CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU\n" + "MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw\n" + "MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp\n" + "Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA\n" + "A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo\n" + "27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w\n" + "Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw\n" + "TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl\n" + "qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH\n" + "szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8\n" + "Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk\n" + "MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92\n" + "wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p\n" + "aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN\n" + "VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID\n" + "AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E\n" + "FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb\n" + "C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe\n" + "QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy\n" + "h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4\n" + "7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J\n" + "ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef\n" + "MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/\n" + "Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT\n" + "6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ\n" + "0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm\n" + "2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb\n" + "bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c\n" + "-----END CERTIFICATE-----\n"; +*/ + bool taskComplete = false; #if defined(ARDUINO_RASPBERRY_PI_PICO_W) @@ -77,6 +114,11 @@ void setup() Serial.println(WiFi.localIP()); Serial.println(); + // In case SD/SD_MMC storage file access, mount the SD/SD_MMC card. + // SD_Card_Mounting(); // See src/GS_SDHelper.h + + // GSheet.setCert(rootCACert); // or GSheet.setCertFile("path/to/certificate/file.pem", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); + // Set the callback for Google API access token generation status (for debug only) GSheet.setTokenCallback(tokenStatusCallback); @@ -92,6 +134,9 @@ void setup() // Begin the access token generation for Google API authentication GSheet.begin(CLIENT_EMAIL, PROJECT_ID, PRIVATE_KEY); + + // Or begin with the Service Account JSON file + // GSheet.begin("path/to/serviceaccount/json/file", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); } void loop() diff --git a/examples/Values/Create_Update_Read/Create_Update_Read.ino b/examples/Values/Create_Update_Read/Create_Update_Read.ino index d548a98..eb2c5ec 100644 --- a/examples/Values/Create_Update_Read/Create_Update_Read.ino +++ b/examples/Values/Create_Update_Read/Create_Update_Read.ino @@ -20,6 +20,9 @@ #endif #include +// For SD/SD_MMC mounting helper +#include + #define WIFI_SSID "WIFI_AP" #define WIFI_PASSWORD "WIFI_PASSWORD" @@ -36,6 +39,40 @@ // Service Account's private key const char PRIVATE_KEY[] PROGMEM = "-----BEGIN PRIVATE KEY-----XXXXXXXXXXXX-----END PRIVATE KEY-----\n"; +/** +const char rootCACert[] PROGMEM = "-----BEGIN CERTIFICATE-----\n" + "MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw\n" + "CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU\n" + "MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw\n" + "MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp\n" + "Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA\n" + "A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo\n" + "27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w\n" + "Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw\n" + "TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl\n" + "qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH\n" + "szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8\n" + "Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk\n" + "MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92\n" + "wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p\n" + "aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN\n" + "VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID\n" + "AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E\n" + "FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb\n" + "C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe\n" + "QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy\n" + "h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4\n" + "7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J\n" + "ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef\n" + "MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/\n" + "Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT\n" + "6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ\n" + "0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm\n" + "2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb\n" + "bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c\n" + "-----END CERTIFICATE-----\n"; +*/ + bool taskComplete = false; #if defined(ARDUINO_RASPBERRY_PI_PICO_W) @@ -80,6 +117,11 @@ void setup() Serial.println(WiFi.localIP()); Serial.println(); + // In case SD/SD_MMC storage file access, mount the SD/SD_MMC card. + // SD_Card_Mounting(); // See src/GS_SDHelper.h + + // GSheet.setCert(rootCACert); // or GSheet.setCertFile("path/to/certificate/file.pem", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); + // Set the callback for Google API access token generation status (for debug only) GSheet.setTokenCallback(tokenStatusCallback); @@ -95,6 +137,9 @@ void setup() // Begin the access token generation for Google API authentication GSheet.begin(CLIENT_EMAIL, PROJECT_ID, PRIVATE_KEY); + + // Or begin with the Service Account JSON file + // GSheet.begin("path/to/serviceaccount/json/file", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); } void loop() diff --git a/examples/Values/Read/Read.ino b/examples/Values/Read/Read.ino index 9a59249..12c8caf 100644 --- a/examples/Values/Read/Read.ino +++ b/examples/Values/Read/Read.ino @@ -20,6 +20,9 @@ #endif #include +// For SD/SD_MMC mounting helper +#include + #define WIFI_SSID "WIFI_AP" #define WIFI_PASSWORD "WIFI_PASSWORD" @@ -111,7 +114,10 @@ void setup() Serial.println(WiFi.localIP()); Serial.println(); - // GSheet.setCert(rootCACert); // or GSheet.setCertFile("<.pem cert file name>", esP_google_sheet_file_storage_type_flash /* or esP_google_sheet_file_storage_type_sd */); + // In case SD/SD_MMC storage file access, mount the SD/SD_MMC card. + // SD_Card_Mounting(); // See src/GS_SDHelper.h + + // GSheet.setCert(rootCACert); // or GSheet.setCertFile("path/to/certificate/file.pem", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); // Set the callback for Google API access token generation status (for debug only) GSheet.setTokenCallback(tokenStatusCallback); @@ -128,6 +134,9 @@ void setup() // Begin the access token generation for Google API authentication GSheet.begin(CLIENT_EMAIL, PROJECT_ID, PRIVATE_KEY); + + // Or begin with the Service Account JSON file + // GSheet.begin("path/to/serviceaccount/json/file", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); } void loop() diff --git a/examples/Values/Update/Update.ino b/examples/Values/Update/Update.ino index 147ca9c..aab6c82 100644 --- a/examples/Values/Update/Update.ino +++ b/examples/Values/Update/Update.ino @@ -20,6 +20,9 @@ #endif #include +// For SD/SD_MMC mounting helper +#include + #define WIFI_SSID "WIFI_AP" #define WIFI_PASSWORD "WIFI_PASSWORD" @@ -111,7 +114,10 @@ void setup() Serial.println(WiFi.localIP()); Serial.println(); - // GSheet.setCert(rootCACert); // or GSheet.setCertFile("<.pem cert file name>", esP_google_sheet_file_storage_type_flash /* or esP_google_sheet_file_storage_type_sd */); + // In case SD/SD_MMC storage file access, mount the SD/SD_MMC card. + // SD_Card_Mounting(); // See src/GS_SDHelper.h + + // GSheet.setCert(rootCACert); // or GSheet.setCertFile("path/to/certificate/file.pem", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); // Set the callback for Google API access token generation status (for debug only) GSheet.setTokenCallback(tokenStatusCallback); @@ -128,6 +134,9 @@ void setup() // Begin the access token generation for Google API authentication GSheet.begin(CLIENT_EMAIL, PROJECT_ID, PRIVATE_KEY); + + // Or begin with the Service Account JSON file + // GSheet.begin("path/to/serviceaccount/json/file", esp_google_sheet_file_storage_type_flash /* or esp_google_sheet_file_storage_type_sd */); } void loop() diff --git a/library.json b/library.json index de6ad76..647be5c 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "ESP-Google-Sheet-Client", - "version": "1.3.1", + "version": "1.3.2", "keywords": "communication, REST, esp32, esp8266, raspberrypi, arduino", "description": "Arduino Google Sheet REST client library for ESP8266, ESP32 and Raspberry Pi Pico (RP2040). This library allows devices to communicate with Google Sheet API to read, edit and delete the spreadsheets", "repository": { diff --git a/library.properties b/library.properties index 7fab495..aa5c08c 100644 --- a/library.properties +++ b/library.properties @@ -1,6 +1,6 @@ name=ESP-Google-Sheet-Client -version=1.3.1 +version=1.3.2 author=Mobizt diff --git a/src/ESP_Google_Sheet_Client.cpp b/src/ESP_Google_Sheet_Client.cpp index 5c89086..0a6f088 100644 --- a/src/ESP_Google_Sheet_Client.cpp +++ b/src/ESP_Google_Sheet_Client.cpp @@ -1,9 +1,9 @@ /** - * Google Sheet Client, GS_Google_Sheet_Client.cpp v1.3.1 + * Google Sheet Client, GS_Google_Sheet_Client.cpp v1.3.2 * * This library supports Espressif ESP8266 and ESP32 MCUs * - * Created January 24, 2023 + * Created February 1, 2023 * * The MIT License (MIT) * Copyright (c) 2022 K. Suwatchai (Mobizt) @@ -43,12 +43,16 @@ GSheetClass::~GSheetClass() authMan.end(); } -void GSheetClass::auth(const char *client_email, const char *project_id, const char *private_key, ESP8266_SPI_ETH_MODULE *eth) +void GSheetClass::auth(const char *client_email, const char *project_id, const char *private_key, const char *sa_key_file, esp_google_sheet_file_storage_type storage_type, ESP8266_SPI_ETH_MODULE *eth) { config.service_account.data.client_email = client_email; config.service_account.data.project_id = project_id; config.service_account.data.private_key = private_key; config.signer.expiredSeconds = 3600; + + config.service_account.json.path = sa_key_file; + config.service_account.json.storage_type = (mb_fs_mem_storage_type)storage_type; + if (eth) { #if defined(ESP8266) && defined(ESP8266_CORE_SDK_V3_X_X) @@ -69,8 +73,6 @@ void GSheetClass::auth(const char *client_email, const char *project_id, const c #endif config.signer.tokens.token_type = token_type_oauth2_access_token; - gauth_auth_token_type type = config.signer.tokens.token_type; - authMan.begin(&config, &mbfs, &mb_ts, &mb_ts_offset); } @@ -179,6 +181,16 @@ void GSheetClass::addHeader(MB_String &req, host_type_t host_type, int len) req += FPSTR("Accept-Encoding: identity;q=1,chunked;q=0.1,*;q=0\r\n"); } +bool GSheetClass::waitClockReady() +{ + unsigned long ms = millis(); + while (!setClock(config.internal.gmt_offset) && millis() - ms < 3000) + { + Utils::idle(); + } + return config.internal.clock_rdy; +} + void GSheetClass::setCert(const char *ca) { int addr = reinterpret_cast(ca); @@ -186,15 +198,25 @@ void GSheetClass::setCert(const char *ca) { cert_updated = true; cert_addr = addr; +#if defined(ESP8266) || defined(PICO_RP2040) + waitClockReady(); +#endif } } void GSheetClass::setCertFile(const char *filename, esp_google_sheet_file_storage_type type) { - certFile = filename; - certFileStorageType = type; + config.cert.file = filename; + config.cert.file_storage = (mb_fs_mem_storage_type)type; cert_addr = 0; - cert_updated = false; + if (config.cert.file.length() > 0) + { + cert_updated = true; + +#if defined(ESP8266) || defined(PICO_RP2040) + waitClockReady(); +#endif + } } void GSheetClass::reset() @@ -250,7 +272,7 @@ bool GSheetClass::setSecure() } else { - if (!client->setCertFile(config.cert.file.c_str(), certFileStorageType == esP_google_sheet_file_storage_type_flash ? mb_fs_mem_storage_type_flash : mb_fs_mem_storage_type_sd)) + if (!client->setCertFile(config.cert.file.c_str(), config.cert.file_storage)) client->setCACert(NULL); } cert_updated = false; diff --git a/src/ESP_Google_Sheet_Client.h b/src/ESP_Google_Sheet_Client.h index f5a55c7..50528ef 100644 --- a/src/ESP_Google_Sheet_Client.h +++ b/src/ESP_Google_Sheet_Client.h @@ -1,13 +1,13 @@ #ifndef ESP_GOOGLE_SHEET_CLIENT_VERSION -#define ESP_GOOGLE_SHEET_CLIENT_VERSION "1.3.1" +#define ESP_GOOGLE_SHEET_CLIENT_VERSION "1.3.2" #endif /** - * Google Sheet Client, ESP_Google_Sheet_Client.h v1.3.1 + * Google Sheet Client, ESP_Google_Sheet_Client.h v1.3.2 * * This library supports Espressif ESP8266 and ESP32 MCUs * - * Created January 24, 2023 + * Created February 1, 2023 * * The MIT License (MIT) * Copyright (c) 2022 K. Suwatchai (Mobizt) @@ -38,12 +38,6 @@ #include "auth/GAuthManager.h" -enum esp_google_sheet_file_storage_type -{ - esP_google_sheet_file_storage_type_flash, - esP_google_sheet_file_storage_type_sd -}; - class GSheetClass { friend class ESP_Google_Sheet_Client; @@ -79,10 +73,8 @@ class GSheetClass int cert_addr = 0; bool cert_updated = false; - MB_String certFile; - esp_google_sheet_file_storage_type certFileStorageType; - void auth(const char *client_email, const char *project_id, const char *private_key, ESP8266_SPI_ETH_MODULE *eth = nullptr); + void auth(const char *client_email, const char *project_id, const char *private_key, const char *sa_key_file, esp_google_sheet_file_storage_type storage_type, ESP8266_SPI_ETH_MODULE *eth = nullptr); void setTokenCallback(TokenStatusCallback callback); void addAP(const char *ssid, const char *password); void clearAP(); @@ -132,6 +124,7 @@ class GSheetClass const String &refreshToken, gauth_auth_token_type type, const String &clientId, const String &clientSecret); void reset(); + bool waitClockReady(); }; class GSheet_Values @@ -1402,6 +1395,8 @@ class ESP_Google_Sheet_Client * @param client_email (string) The Service Account's client email. * @param project_id (string) The project ID. * @param private_key (string) The Service Account's private key. + * @param eth (optional for ESP8266 only) The pointer to ESP8266 lwIP network class + * e.g. ENC28J60lwIP, Wiznet5100lwIP and Wiznet5500lwIP. * */ template @@ -1410,7 +1405,23 @@ class ESP_Google_Sheet_Client values.init(gsheet); sheets.init(gsheet); developerMetadata.init(gsheet); - gsheet->auth(toString(client_email), toString(project_id), toString(private_key), eth); + gsheet->auth(toString(client_email), toString(project_id), toString(private_key), "", esp_google_sheet_file_storage_type_undefined, eth); + } + + /** Begin the Google API authentication. + * + * @param service_account_file (string) The Service Account's JSON key file. + * @param storage_type (esp_google_sheet_file_storage_type) The JSON key file storage type e.g. esp_google_sheet_file_storage_type_flash and esp_google_sheet_file_storage_type_sd. + * @param eth (optional for ESP8266 only) The pointer to ESP8266 lwIP network class + * e.g. ENC28J60lwIP, Wiznet5100lwIP and Wiznet5500lwIP. + */ + template + void begin(T1 service_account_file, esp_google_sheet_file_storage_type storage_type, ESP8266_SPI_ETH_MODULE *eth = nullptr) + { + values.init(gsheet); + sheets.init(gsheet); + developerMetadata.init(gsheet); + gsheet->auth("", "", "", toString(service_account_file), storage_type, eth); } /** Set the Root certificate data for server authorization. diff --git a/src/ESP_Google_Sheet_Client_FS_Config.h b/src/ESP_Google_Sheet_Client_FS_Config.h index bf7f7f7..eafdf62 100644 --- a/src/ESP_Google_Sheet_Client_FS_Config.h +++ b/src/ESP_Google_Sheet_Client_FS_Config.h @@ -65,6 +65,9 @@ // To use external Client. // #define ESP_GOOGLE_SHEET_CLIENT_ENABLE_EXTERNAL_CLIENT +// For ESP8266 ENC28J60 Ethernet module +// #define ENABLE_ESP8266_ENC28J60_ETH + // For ESP8266 W5100 Ethernet module // #define ENABLE_ESP8266_W5100_ETH diff --git a/src/GS_Const.h b/src/GS_Const.h index c442854..864267f 100644 --- a/src/GS_Const.h +++ b/src/GS_Const.h @@ -53,12 +53,10 @@ #endif #endif - #if __has_include() #include #endif - #endif #if defined __has_include @@ -67,7 +65,7 @@ #include #endif -#if __has_include() +#if __has_include() && defined(ENABLE_ESP8266_ENC28J60_ETH) #define INC_ENC28J60_LWIP #include #define ESP8266_SPI_ETH_MODULE ENC28J60lwIP @@ -89,6 +87,12 @@ #endif +typedef enum +{ + esp_google_sheet_file_storage_type_undefined, + esp_google_sheet_file_storage_type_flash, + esp_google_sheet_file_storage_type_sd +} esp_google_sheet_file_storage_type; typedef enum { @@ -459,7 +463,6 @@ typedef void (*GS_NetworkConnectionRequestCallback)(void); typedef void (*GS_NetworkStatusRequestCallback)(void); typedef void (*GS_ResponseCallback)(const char *); - static const unsigned char gs_base64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const char gauth_pgm_str_1[] PROGMEM = "type"; diff --git a/src/GS_Error.h b/src/GS_Error.h index 2a777fc..e886d4e 100644 --- a/src/GS_Error.h +++ b/src/GS_Error.h @@ -1,5 +1,5 @@ /** - * Created Janaury 10, 2023 + * Created February 1, 2023 */ #ifndef GS_Error_H @@ -77,5 +77,6 @@ #define GS_ERROR_TOKEN_COMPLETE_UNNOTIFY /* */ (GS_ERROR_RANGE - 15) #define GS_ERROR_TOKEN_ERROR_UNNOTIFY /* */ (GS_ERROR_RANGE - 16) #define GS_ERROR_UDP_CLIENT_REQUIRED /* */ (GS_ERROR_RANGE - 17) - +#define GS_ERROR_MISSING_SERVICE_ACCOUNT_CREDENTIALS /* */ (GS_ERROR_RANGE - 18) +#define GS_ERROR_SERVICE_ACCOUNT_JSON_FILE_PARSING_ERROR /* */ (GS_ERROR_RANGE - 19) #endif \ No newline at end of file diff --git a/src/GS_SDHelper.h b/src/GS_SDHelper.h new file mode 100644 index 0000000..03b21b8 --- /dev/null +++ b/src/GS_SDHelper.h @@ -0,0 +1,145 @@ + +#ifndef SD_HELPER_H_ +#define SD_HELPER_H_ + +#include +#include "ESP_Google_Sheet_Client.h" + +// If SD Card used for storage, assign SD card type and FS used in src/GSheetFS.h and +// change the config for that card interfaces in this file (src/addons/SDHelper.h) + +#if defined(DEFAULT_SD_FS) && defined(CARD_TYPE_SD) + +#if defined(ESP32) +#define SPI_CS_PIN 13 +#define SPI_SCK_PIN 14 +#define SPI_MISO_PIN 2 +#define SPI_MOSI_PIN 15 +#define SPI_CLOCK_IN_MHz 16 +#elif defined(ESP8266) +#define SPI_CS_PIN 15 +#elif defined(PICO_RP2040) +// Use SPI 1's SS (GPIO 13) port as CS for SPI +#define SPI_CS_PIN PIN_SPI1_SS +#endif + +// if SdFat library installed and GSheetFS.h was set to use it (for ESP32 only) +#if defined(USE_SD_FAT_ESP32) + +// https://github.com/greiman/SdFat +SdSpiConfig sdFatSPIConfig(SPI_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(SPI_CLOCK_IN_MHz)); + +#elif defined(ESP32) // if ESP32 and no SdFat library installed + +SPIClass spi; + +#elif defined(ESP8266) + +SDFSConfig sdFSConfig(SPI_CS_PIN, SPI_HALF_SPEED); + +#elif defined(PICO_RP2040) + +/** Use Pico SPI 1 for SPI + * MISO GPIO 12 + * MOSI GPIO 15 + * SCK GPIO 14 + * SS GPIO 13 + */ +SDFSConfig sdFSConfig(SPI_CS_PIN, SPI_HALF_SPEED, SPI1); + +#endif + +#endif + +bool SD_Card_Mounting() +{ + +#if defined(DEFAULT_SD_FS) && defined(CARD_TYPE_SD) + +#if defined(USE_SD_FAT_ESP32) + + Serial.print("\nMounting SD Card... "); + + if (!GSheet.sdBegin(&sdFatSPIConfig, SPI_CS_PIN, SPI_SCK_PIN, SPI_MISO_PIN, SPI_MOSI_PIN)) // pointer to SdSpiConfig, SS, SCK,MISO, MOSI + { + Serial.println("failed\n"); + return false; + } + else + { + Serial.println("success\n"); + return true; + } + +#elif defined(ESP32) // if ESP32 and no SdFat library installed + + Serial.print("\nMounting SD Card... "); + + spi.begin(SPI_SCK_PIN, SPI_MISO_PIN, SPI_MOSI_PIN, SPI_CS_PIN); // SPI pins config -> SCK,MISO, MOSI, SS + if (!GSheet.sdBegin(SPI_CS_PIN, &spi)) // SS, pointer to SPIClass <- SPIClass object should defined as static or global + { + Serial.println("failed\n"); + return false; + } + else + { + Serial.println("success\n"); + return true; + } + +#elif defined(ESP8266) + + Serial.print("\nMounting SD Card... "); + + if (!GSheet.sdBegin(SPI_CS_PIN)) // or GSheet.sdBegin(&sdFSConfig) + { + Serial.println("failed\n"); + return false; + } + else + { + Serial.println("success\n"); + return true; + } + +#elif defined(PICO_RP2040) + + Serial.print("\nMounting SD Card... "); + + if (!GSheet.sdBegin(&sdFSConfig)) // We begin with the SDFSConfig to use SPI 1 port + { + Serial.println("failed\n"); + return false; + } + else + { + Serial.println("success\n"); + return true; + } + +#endif + +#endif + +#if defined(DEFAULT_SD_FS) && defined(CARD_TYPE_SD_MMC) + + Serial.print("\nMounting SD_MMC Card... "); + + if (!GSheet.sdMMCBegin("/sdcard", false, true)) + { + Serial.println("failed\n"); + return false; + } + else + { + Serial.println("success\n"); + return true; + } + +#endif + + Serial.println("\nSD filesystem was not setup yet."); + return false; +} + +#endif \ No newline at end of file diff --git a/src/auth/GAuthManager.cpp b/src/auth/GAuthManager.cpp index 4c98d83..2af5e38 100644 --- a/src/auth/GAuthManager.cpp +++ b/src/auth/GAuthManager.cpp @@ -285,28 +285,43 @@ bool GAuthManager::handleToken() // Handle the signed jwt token generation, request and refresh the token - // if expiry time is up or reset/unset, start the process + // If expiry time is up or reset/unset, start the process if (exp) { - // refresh the token when refresh token was assigned via setAccessToken (fourth argument) - if (config->internal.refresh_token.length() > 0) - return requestTokens(true); + // Handle the jwt token processing - // handle the jwt token processing - - // if it is the first step and no task is currently running + // If it is the first step and no task is currently running if (config->signer.step == gauth_jwt_generation_step_begin && !config->signer.tokenTaskRunning) { - // if service account key json file assigned and no private key parsing data + bool use_sa_key_file = false, valid_key_file = false; + // If service account key json file assigned and no private key parsing data if (config->service_account.json.path.length() > 0 && config->signer.pk.length() == 0) { - // if fail to parse the private key from service account json file, reset the token status - if (!parseSAFile()) - config->signer.tokens.status = token_status_uninitialized; + use_sa_key_file = true; + // Parse the private key from service account json file + valid_key_file = parseSAFile(); + } + + // Check the SA creds + if (!serviceAccountCredsReady()) + { + config->signer.tokens.status = token_status_error; + if (use_sa_key_file && !valid_key_file) + { + errorToString(GS_ERROR_SERVICE_ACCOUNT_JSON_FILE_PARSING_ERROR, config->signer.tokens.error.message); + config->signer.tokens.error.code = GS_ERROR_SERVICE_ACCOUNT_JSON_FILE_PARSING_ERROR; + } + else + { + errorToString(GS_ERROR_MISSING_SERVICE_ACCOUNT_CREDENTIALS, config->signer.tokens.error.message); + config->signer.tokens.error.code = GS_ERROR_MISSING_SERVICE_ACCOUNT_CREDENTIALS; + } + sendTokenStatusCB(); + return false; } - // if no token status set, set the states + // If no token status set, set the states if (config->signer.tokens.status != token_status_on_initialize) { config->signer.tokens.status = token_status_on_initialize; @@ -316,7 +331,7 @@ bool GAuthManager::handleToken() sendTokenStatusCB(); } - // set the token processing task started flag and run the task + // If service account creds are ready, set the token processing task started flag and run the task _token_processing_task_enable = true; tokenProcessingTask(); } @@ -1557,6 +1572,12 @@ void GAuthManager::errorToString(int httpCode, MB_String &buff) buff += F("UDP client is required for NTP server time synching based on your network type \ne.g. WiFiUDP or EthernetUDP. Please call GSheet.setUDPClient(&udpClient, gmtOffset); to assign the UDP client."); return; + case GS_ERROR_MISSING_SERVICE_ACCOUNT_CREDENTIALS: + buff += F("The Service Account Credentials are missing."); + return; + case GS_ERROR_SERVICE_ACCOUNT_JSON_FILE_PARSING_ERROR: + buff += F("Unable to parse Service Account JSON file. Please check file name, storage type and its content."); + return; default: buff += F("unknown error"); return;