From f0c05263719c54a592083c0474eedd4f96efe6f9 Mon Sep 17 00:00:00 2001 From: suwatchai Date: Sat, 13 Mar 2021 13:46:32 +0700 Subject: [PATCH] Fix the infinite loop, add callback, timeout and retry limit of token generation. --- README.md | 2 +- .../Access_Token_from_File.ino | 88 ++-- .../Custom_Token/Custom_Token.ino | 90 ++-- .../Custom_Token_from_File.ino | 88 ++-- .../Email_Password/Email_Password.ino | 90 ++-- keywords.txt | 1 + library.json | 2 +- library.properties | 2 +- src/FirebaseFS.h | 5 +- src/Firebase_ESP_Client.cpp | 43 +- src/Firebase_ESP_Client.h | 19 +- src/README.md | 45 +- src/Utils.h | 54 ++- src/common.h | 45 +- src/functions/FB_Functions.cpp | 6 +- src/functions/FB_Functions.h | 4 +- src/gcs/GCS.cpp | 10 +- src/gcs/GCS.h | 4 +- src/rtdb/FB_RTDB.cpp | 15 +- src/rtdb/FB_RTDB.h | 4 +- src/session/FB_Session.cpp | 17 +- src/session/FB_Session.h | 6 +- src/signer/Signer.cpp | 398 ++++++++++++++---- src/signer/Signer.h | 20 +- src/storage/FCS.cpp | 43 +- src/storage/FCS.h | 14 +- src/stream/FB_Stream.cpp | 8 +- src/stream/FB_Stream.h | 4 +- src/wcs/HTTPCode.h | 13 +- src/wcs/esp32/FB_HTTPClient32.cpp | 214 +++++----- src/wcs/esp32/FB_HTTPClient32.h | 11 +- src/wcs/esp8266/FB_HTTPClient.cpp | 4 +- src/wcs/esp8266/FB_HTTPClient.h | 9 +- 33 files changed, 925 insertions(+), 453 deletions(-) diff --git a/README.md b/README.md index d35a95fbe..5f83fd049 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Firebase Arduino Client Library for ESP8266 and ESP32 -Google's Firebase Arduino Client Library for ESP8266 and ESP32 v 2.0.5 +Google's Firebase Arduino Client Library for ESP8266 and ESP32 v 2.0.6 This library supports ESP8266 and ESP32 MCU from Espressif. The following are platforms in which the libraries are also available (RTDB only). diff --git a/examples/Authentications/Access_Token_from_File/Access_Token_from_File.ino b/examples/Authentications/Access_Token_from_File/Access_Token_from_File.ino index 4944a2fde..2243b8615 100644 --- a/examples/Authentications/Access_Token_from_File/Access_Token_from_File.ino +++ b/examples/Authentications/Access_Token_from_File/Access_Token_from_File.ino @@ -37,6 +37,9 @@ FirebaseAuth auth; /* 5. Define the FirebaseConfig data for config data */ FirebaseConfig config; +/* The calback function to print the token generation status */ +void tokenStatusCallback(TokenInfo info); + /* The function to print the operating results */ void printResult(FirebaseData &data); @@ -93,6 +96,12 @@ void setup() Firebase.reconnectWiFi(true); + /** Assign the callback function for the long running token generation task */ + config.token_status_callback = tokenStatusCallback; + + /** Assign the maximum retry of token generation */ + config.max_token_generation_retry = 5; + /* Now we start to signin using access token */ /** Initialize the library with the Firebase authen and config. @@ -116,44 +125,58 @@ void loop() dataMillis = millis(); /* Get the token status */ - struct token_info_t info = Firebase.authTokenInfo(); - Serial.println("------------------------------------"); - if (info.status == token_status_error) - { - Serial.printf("Token info: type = %s, status = %s\n", getTokenType(info).c_str(), getTokenStatus(info).c_str()); - Serial.printf("Token error: %s\n\n", getTokenError(info).c_str()); - } - else + TokenInfo info = Firebase.authTokenInfo(); + if (info.status == token_status_ready) { - Serial.printf("Token info: type = %s, status = %s\n\n", getTokenType(info).c_str(), getTokenStatus(info).c_str()); - } - - Serial.println("------------------------------------"); - Serial.println("Set int test..."); + Serial.println("------------------------------------"); + Serial.println("Set int test..."); - String Path = path + "/int"; + String Path = path + "/int"; - if (Firebase.RTDB.set(&fbdo, Path.c_str(), count++)) - { - Serial.println("PASSED"); - Serial.println("PATH: " + fbdo.dataPath()); - Serial.println("TYPE: " + fbdo.dataType()); - Serial.println("ETag: " + fbdo.ETag()); - Serial.print("VALUE: "); - printResult(fbdo); - Serial.println("------------------------------------"); - Serial.println(); - } - else - { - Serial.println("FAILED"); - Serial.println("REASON: " + fbdo.errorReason()); - Serial.println("------------------------------------"); - Serial.println(); + if (Firebase.RTDB.set(&fbdo, Path.c_str(), count++)) + { + Serial.println("PASSED"); + Serial.println("PATH: " + fbdo.dataPath()); + Serial.println("TYPE: " + fbdo.dataType()); + Serial.println("ETag: " + fbdo.ETag()); + Serial.print("VALUE: "); + printResult(fbdo); + Serial.println("------------------------------------"); + Serial.println(); + } + else + { + Serial.println("FAILED"); + Serial.println("REASON: " + fbdo.errorReason()); + Serial.println("------------------------------------"); + Serial.println(); + } } } } +void tokenStatusCallback(TokenInfo info) +{ + /** fb_esp_auth_token_status enum + * token_status_uninitialized, + * token_status_on_initialize, + * token_status_on_signing, + * token_status_on_request, + * token_status_on_refresh, + * token_status_ready, + * token_status_error + */ + if (info.status == token_status_error) + { + Serial.printf("Token info: type = %s, status = %s\n", getTokenType(info).c_str(), getTokenStatus(info).c_str()); + Serial.printf("Token error: %s\n", getTokenError(info).c_str()); + } + else + { + Serial.printf("Token info: type = %s, status = %s\n", getTokenType(info).c_str(), getTokenStatus(info).c_str()); + } +} + void printResult(FirebaseData &data) { @@ -318,6 +341,9 @@ String getTokenStatus(struct token_info_t info) case token_status_uninitialized: return "uninitialized"; + case token_status_on_initialize: + return "on initializing"; + case token_status_on_signing: return "on signing"; diff --git a/examples/Authentications/Custom_Token/Custom_Token.ino b/examples/Authentications/Custom_Token/Custom_Token.ino index d6d16aa6c..b9c3104c9 100644 --- a/examples/Authentications/Custom_Token/Custom_Token.ino +++ b/examples/Authentications/Custom_Token/Custom_Token.ino @@ -102,6 +102,9 @@ FirebaseAuth auth; /* 7. Define the FirebaseConfig data for config data */ FirebaseConfig config; +/* The calback function to print the token generation status */ +void tokenStatusCallback(TokenInfo info); + /* The helper function to modify the database rules (optional) */ void prepareDatabaseRules(const char *path, const char *var, const char *readVal, const char *writeVal); @@ -201,6 +204,12 @@ void setup() String val = "($userId === auth.uid && auth.token.premium_account === true && auth.token.admin === true)"; prepareDatabaseRules(base_path.c_str(), var.c_str(), val.c_str(), val.c_str()); + /** Assign the callback function for the long running token generation task */ + config.token_status_callback = tokenStatusCallback; + + /** Assign the maximum retry of token generation */ + config.max_token_generation_retry = 5; + /* Now we start to signin using custom token */ /** Initialize the library with the Firebase authen and config. @@ -236,41 +245,57 @@ void loop() dataMillis = millis(); /* Get the token status */ - struct token_info_t info = Firebase.authTokenInfo(); - Serial.println("------------------------------------"); - if (info.status == token_status_error) - { - Serial.printf("Token info: type = %s, status = %s\n", getTokenType(info).c_str(), getTokenStatus(info).c_str()); - Serial.printf("Token error: %s\n\n", getTokenError(info).c_str()); - } - else + TokenInfo info = Firebase.authTokenInfo(); + if (info.status == token_status_ready) { - Serial.printf("Token info: type = %s, status = %s\n\n", getTokenType(info).c_str(), getTokenStatus(info).c_str()); - } - - Serial.println("------------------------------------"); - Serial.println("Set int test..."); + Serial.println("------------------------------------"); + Serial.println("Set int test..."); - String Path = path + "/int"; + String Path = path + "/int"; - if (Firebase.RTDB.set(&fbdo, Path.c_str(), count++)) - { - Serial.println("PASSED"); - Serial.println("PATH: " + fbdo.dataPath()); - Serial.println("TYPE: " + fbdo.dataType()); - Serial.println("ETag: " + fbdo.ETag()); - Serial.print("VALUE: "); - printResult(fbdo); - Serial.println("------------------------------------"); - Serial.println(); - } - else - { - Serial.println("FAILED"); - Serial.println("REASON: " + fbdo.errorReason()); - Serial.println("------------------------------------"); - Serial.println(); + if (Firebase.RTDB.set(&fbdo, Path.c_str(), count++)) + { + Serial.println("PASSED"); + Serial.println("PATH: " + fbdo.dataPath()); + Serial.println("TYPE: " + fbdo.dataType()); + Serial.println("ETag: " + fbdo.ETag()); + Serial.print("VALUE: "); + printResult(fbdo); + Serial.println("------------------------------------"); + Serial.println(); + } + else + { + Serial.println("FAILED"); + Serial.println("REASON: " + fbdo.errorReason()); + Serial.println("------------------------------------"); + Serial.println(); + } } + + + } +} + +void tokenStatusCallback(TokenInfo info) +{ + /** fb_esp_auth_token_status enum + * token_status_uninitialized, + * token_status_on_initialize, + * token_status_on_signing, + * token_status_on_request, + * token_status_on_refresh, + * token_status_ready, + * token_status_error + */ + if (info.status == token_status_error) + { + Serial.printf("Token info: type = %s, status = %s\n", getTokenType(info).c_str(), getTokenStatus(info).c_str()); + Serial.printf("Token error: %s\n", getTokenError(info).c_str()); + } + else + { + Serial.printf("Token info: type = %s, status = %s\n", getTokenType(info).c_str(), getTokenStatus(info).c_str()); } } @@ -510,6 +535,9 @@ String getTokenStatus(struct token_info_t info) case token_status_uninitialized: return "uninitialized"; + case token_status_on_initialize: + return "on initializing"; + case token_status_on_signing: return "on signing"; diff --git a/examples/Authentications/Custom_Token_from_File/Custom_Token_from_File.ino b/examples/Authentications/Custom_Token_from_File/Custom_Token_from_File.ino index d01b69d32..e1ee0ced3 100644 --- a/examples/Authentications/Custom_Token_from_File/Custom_Token_from_File.ino +++ b/examples/Authentications/Custom_Token_from_File/Custom_Token_from_File.ino @@ -66,6 +66,9 @@ FirebaseAuth auth; /* 7. Define the FirebaseConfig data for config data */ FirebaseConfig config; +/* The calback function to print the token generation status */ +void tokenStatusCallback(TokenInfo info); + /* The helper function to modify the database rules (optional) */ void prepareDatabaseRules(const char *path, const char *var, const char *readVal, const char *writeVal); @@ -167,6 +170,12 @@ void setup() String val = "($userId === auth.uid && auth.token.premium_account === true && auth.token.admin === true)"; prepareDatabaseRules(base_path.c_str(), var.c_str(), val.c_str(), val.c_str()); + /** Assign the callback function for the long running token generation task */ + config.token_status_callback = tokenStatusCallback; + + /** Assign the maximum retry of token generation */ + config.max_token_generation_retry = 5; + /* Now we start to signin using custom token */ /** Initialize the library with the Firebase authen and config. @@ -202,44 +211,58 @@ void loop() dataMillis = millis(); /* Get the token status */ - struct token_info_t info = Firebase.authTokenInfo(); - Serial.println("------------------------------------"); - if (info.status == token_status_error) - { - Serial.printf("Token info: type = %s, status = %s\n", getTokenType(info).c_str(), getTokenStatus(info).c_str()); - Serial.printf("Token error: %s\n\n", getTokenError(info).c_str()); - } - else + TokenInfo info = Firebase.authTokenInfo(); + if (info.status == token_status_ready) { - Serial.printf("Token info: type = %s, status = %s\n\n", getTokenType(info).c_str(), getTokenStatus(info).c_str()); - } - - Serial.println("------------------------------------"); - Serial.println("Set int test..."); + Serial.println("------------------------------------"); + Serial.println("Set int test..."); - String Path = path + "/int"; + String Path = path + "/int"; - if (Firebase.RTDB.set(&fbdo, Path.c_str(), count++)) - { - Serial.println("PASSED"); - Serial.println("PATH: " + fbdo.dataPath()); - Serial.println("TYPE: " + fbdo.dataType()); - Serial.println("ETag: " + fbdo.ETag()); - Serial.print("VALUE: "); - printResult(fbdo); - Serial.println("------------------------------------"); - Serial.println(); - } - else - { - Serial.println("FAILED"); - Serial.println("REASON: " + fbdo.errorReason()); - Serial.println("------------------------------------"); - Serial.println(); + if (Firebase.RTDB.set(&fbdo, Path.c_str(), count++)) + { + Serial.println("PASSED"); + Serial.println("PATH: " + fbdo.dataPath()); + Serial.println("TYPE: " + fbdo.dataType()); + Serial.println("ETag: " + fbdo.ETag()); + Serial.print("VALUE: "); + printResult(fbdo); + Serial.println("------------------------------------"); + Serial.println(); + } + else + { + Serial.println("FAILED"); + Serial.println("REASON: " + fbdo.errorReason()); + Serial.println("------------------------------------"); + Serial.println(); + } } } } +void tokenStatusCallback(TokenInfo info) +{ + /** fb_esp_auth_token_status enum + * token_status_uninitialized, + * token_status_on_initialize, + * token_status_on_signing, + * token_status_on_request, + * token_status_on_refresh, + * token_status_ready, + * token_status_error + */ + if (info.status == token_status_error) + { + Serial.printf("Token info: type = %s, status = %s\n", getTokenType(info).c_str(), getTokenStatus(info).c_str()); + Serial.printf("Token error: %s\n", getTokenError(info).c_str()); + } + else + { + Serial.printf("Token info: type = %s, status = %s\n", getTokenType(info).c_str(), getTokenStatus(info).c_str()); + } +} + /* The helper function to modify the database rules (optional) */ void prepareDatabaseRules(const char *path, const char *var, const char *readVal, const char *writeVal) { @@ -476,6 +499,9 @@ String getTokenStatus(struct token_info_t info) case token_status_uninitialized: return "uninitialized"; + case token_status_on_initialize: + return "on initializing"; + case token_status_on_signing: return "on signing"; diff --git a/examples/Authentications/Email_Password/Email_Password.ino b/examples/Authentications/Email_Password/Email_Password.ino index d93b845e1..dbbdf0556 100644 --- a/examples/Authentications/Email_Password/Email_Password.ino +++ b/examples/Authentications/Email_Password/Email_Password.ino @@ -72,6 +72,9 @@ FirebaseAuth auth; /* 8. Define the FirebaseConfig data for config data */ FirebaseConfig config; +/* The calback function to print the token generation status */ +void tokenStatusCallback(TokenInfo info); + /* The helper function to modify the database rules (optional) */ void prepareDatabaseRules(const char *path, const char *var, const char *readVal, const char *writeVal); @@ -141,6 +144,12 @@ void setup() String val = "(auth.uid === $user)"; prepareDatabaseRules(base_path.c_str(), var.c_str(), val.c_str(), val.c_str()); + /** Assign the callback function for the long running token generation task */ + config.token_status_callback = tokenStatusCallback; + + /** Assign the maximum retry of token generation */ + config.max_token_generation_retry = 5; + /* Initialize the library with the Firebase authen and config */ Firebase.begin(&config, &auth); @@ -157,41 +166,57 @@ void loop() dataMillis = millis(); /* Get the token status */ - struct token_info_t info = Firebase.authTokenInfo(); - Serial.println("------------------------------------"); - if (info.status == token_status_error) - { - Serial.printf("Token info: type = %s, status = %s\n", getTokenType(info).c_str(), getTokenStatus(info).c_str()); - Serial.printf("Token error: %s\n\n", getTokenError(info).c_str()); - } - else + TokenInfo info = Firebase.authTokenInfo(); + if (info.status == token_status_ready) { - Serial.printf("Token info: type = %s, status = %s\n\n", getTokenType(info).c_str(), getTokenStatus(info).c_str()); - } - - Serial.println("------------------------------------"); - Serial.println("Set int test..."); + Serial.println("------------------------------------"); + Serial.println("Set int test..."); - String Path = path + "/int"; + String Path = path + "/int"; - if (Firebase.RTDB.set(&fbdo, Path.c_str(), count++)) - { - Serial.println("PASSED"); - Serial.println("PATH: " + fbdo.dataPath()); - Serial.println("TYPE: " + fbdo.dataType()); - Serial.println("ETag: " + fbdo.ETag()); - Serial.print("VALUE: "); - printResult(fbdo); - Serial.println("------------------------------------"); - Serial.println(); - } - else - { - Serial.println("FAILED"); - Serial.println("REASON: " + fbdo.errorReason()); - Serial.println("------------------------------------"); - Serial.println(); + if (Firebase.RTDB.set(&fbdo, Path.c_str(), count++)) + { + Serial.println("PASSED"); + Serial.println("PATH: " + fbdo.dataPath()); + Serial.println("TYPE: " + fbdo.dataType()); + Serial.println("ETag: " + fbdo.ETag()); + Serial.print("VALUE: "); + printResult(fbdo); + Serial.println("------------------------------------"); + Serial.println(); + } + else + { + Serial.println("FAILED"); + Serial.println("REASON: " + fbdo.errorReason()); + Serial.println("------------------------------------"); + Serial.println(); + } } + + + } +} + +void tokenStatusCallback(TokenInfo info) +{ + /** fb_esp_auth_token_status enum + * token_status_uninitialized, + * token_status_on_initialize, + * token_status_on_signing, + * token_status_on_request, + * token_status_on_refresh, + * token_status_ready, + * token_status_error + */ + if (info.status == token_status_error) + { + Serial.printf("Token info: type = %s, status = %s\n", getTokenType(info).c_str(), getTokenStatus(info).c_str()); + Serial.printf("Token error: %s\n", getTokenError(info).c_str()); + } + else + { + Serial.printf("Token info: type = %s, status = %s\n", getTokenType(info).c_str(), getTokenStatus(info).c_str()); } } @@ -431,6 +456,9 @@ String getTokenStatus(struct token_info_t info) case token_status_uninitialized: return "uninitialized"; + case token_status_on_initialize: + return "on initializing"; + case token_status_on_signing: return "on signing"; diff --git a/keywords.txt b/keywords.txt index dd7d81af0..00bed4c4b 100644 --- a/keywords.txt +++ b/keywords.txt @@ -271,6 +271,7 @@ FirebaseMethod LITERAL1 QueueStorageType LITERAL1 QueueItem LITERAL1 token_info_t LITERAL1 +TokenInfo LITERAL1 diff --git a/library.json b/library.json index 6583c810f..92d5d1166 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Firebase Arduino Client Library for ESP8266 and ESP32", - "version": "2.0.5", + "version": "2.0.6", "keywords": "communication, REST, esp32, esp8266, arduino", "description": "This client library provides the functions to work with Firebase Realtime database, Firestore, Storage and Cloud messaging.", "repository": { diff --git a/library.properties b/library.properties index f39c5ca23..a32e2a0dd 100644 --- a/library.properties +++ b/library.properties @@ -1,6 +1,6 @@ name=Firebase Arduino Client Library for ESP8266 and ESP32 -version=2.0.5 +version=2.0.6 author=Mobizt diff --git a/src/FirebaseFS.h b/src/FirebaseFS.h index 33121661a..911c0bc23 100644 --- a/src/FirebaseFS.h +++ b/src/FirebaseFS.h @@ -25,4 +25,7 @@ * #define DEFAULT_SD_FS SD_MMC //For ESP32 SDMMC * */ -#define DEFAULT_SD_FS SD \ No newline at end of file +#define DEFAULT_SD_FS SD + +//For ESP32, format SPIFFS or FFat if mounting failed +#define FORMAT_FLASH_IF_MOUNT_FAILED 1 \ No newline at end of file diff --git a/src/Firebase_ESP_Client.cpp b/src/Firebase_ESP_Client.cpp index 43d04c4ee..261f9394a 100644 --- a/src/Firebase_ESP_Client.cpp +++ b/src/Firebase_ESP_Client.cpp @@ -1,9 +1,9 @@ /** - * Google's Firebase ESP Client Main class, Firebase_ESP_Client.h version 2.0.5 + * Google's Firebase ESP Client Main class, Firebase_ESP_Client.h version 2.0.6 * * This library supports Espressif ESP8266 and ESP32 * - * Created March 8, 2021 + * Created March 11, 2021 * * This work is a part of Firebase ESP Client library * Copyright (c) 2020, 2021 K. Suwatchai (Mobizt) @@ -106,21 +106,16 @@ void Firebase_ESP_Client::begin(FirebaseConfig *config, FirebaseAuth *auth) { if (_cfg->cert.file_storage == mem_storage_type_sd && !_cfg->_int.fb_sd_rdy) _cfg->_int.fb_sd_rdy = ut->sdTest(_cfg->_int.fb_file); - else if (_cfg->cert.file_storage == mem_storage_type_flash && !_cfg->_int.fb_flash_rdy) - _cfg->_int.fb_flash_rdy = FLASH_FS.begin(); + else if ((_cfg->cert.file_storage == mem_storage_type_flash) && !_cfg->_int.fb_flash_rdy) + ut->flashTest(); } - Signer.hanldeToken(); + Signer.handleToken(); } struct token_info_t Firebase_ESP_Client::authTokenInfo() { - Signer.checkToken(); - token_info_t info; - info.status = _cfg->signer.tokens.status; - info.type = _cfg->signer.tokens.token_type; - info.error = _cfg->signer.tokens.error; - return info; + return Signer.tokenInfo; } bool Firebase_ESP_Client::signUp(FirebaseConfig *config, FirebaseAuth *auth, const char *email, const char *password) @@ -169,6 +164,32 @@ void Firebase_ESP_Client::setDoubleDigits(uint8_t digits) _cfg->_int.fb_double_digits = digits; } +bool Firebase_ESP_Client::sdBegin(int8_t ss, int8_t sck, int8_t miso, int8_t mosi) +{ + if (Signer.getCfg()) + { + Signer.getCfg()->_int.sd_config.sck = sck; + Signer.getCfg()->_int.sd_config.miso = miso; + Signer.getCfg()->_int.sd_config.mosi = mosi; + Signer.getCfg()->_int.sd_config.ss = ss; + } +#if defined(ESP32) + if (ss > -1) + { + SPI.begin(sck, miso, mosi, ss); + return SD_FS.begin(ss, SPI); + } + else + return SD_FS.begin(); +#elif defined(ESP8266) + if (ss > -1) + return SD_FS.begin(ss); + else + return SD_FS.begin(SD_CS_PIN); +#endif + return false; +} + Firebase_ESP_Client Firebase = Firebase_ESP_Client(); #endif \ No newline at end of file diff --git a/src/Firebase_ESP_Client.h b/src/Firebase_ESP_Client.h index 20de28be1..92f1e2c7f 100644 --- a/src/Firebase_ESP_Client.h +++ b/src/Firebase_ESP_Client.h @@ -1,9 +1,9 @@ /** - * Google's Firebase ESP Client Main class, Firebase_ESP_Client.h version 2.0.5 + * Google's Firebase ESP Client Main class, Firebase_ESP_Client.h version 2.0.6 * * This library supports Espressif ESP8266 and ESP32 * - * Created March 8, 2021 + * Created March 11, 2021 * * This work is a part of Firebase ESP Client library * Copyright (c) 2020, 2021 K. Suwatchai (Mobizt) @@ -52,7 +52,7 @@ class Firebase_ESP_Client public: FB_RTDB RTDB; FB_CM FCM; - FB_CloudStorage Storage; + FB_Storage Storage; FB_Firestore Firestore; FB_Functions Functions; GG_CloudStorage GCStorage; @@ -160,10 +160,17 @@ class Firebase_ESP_Client */ void setDoubleDigits(uint8_t digits); + /** SD card config with GPIO pins. + * + * @param ss - SPI Chip/Slave Select pin. + * @param sck - SPI Clock pin. + * @param miso - SPI MISO pin. + * @param mosi - SPI MOSI pin. + * @return Boolean type status indicates the success of the operation. + */ + bool sdBegin(int8_t ss = -1, int8_t sck = -1, int8_t miso = -1, int8_t mosi = -1); + private: - bool createJWT(int step); - bool getIdToken(bool createUser, const char *email, const char *password); - bool requestTokens(); UtilsClass *ut = nullptr; FirebaseAuth *_auth = nullptr; FirebaseConfig *_cfg = nullptr; diff --git a/src/README.md b/src/README.md index 97e9929e8..3852c82ff 100644 --- a/src/README.md +++ b/src/README.md @@ -1,13 +1,13 @@ # Firebase Arduino Client Library for ESP8266 and ESP32 -Google's Firebase Arduino Client Library for ESP8266 and ESP32 v 2.0.5 +Google's Firebase Arduino Client Library for ESP8266 and ESP32 v 2.0.6 -The default filessystem used in the library is SPIFFS for flash and SD. +The default filessystem used in the library is flash and SD. -To use other flash file systems other than SPIFFS e.g. LittleFS file system, change the config in **FirebaseFS.h** +The file systems for flash and sd memory can be changed in FirebaseFS.h. @@ -180,6 +180,27 @@ void setDoubleDigits(uint8_t digits); + +#### SD card config with GPIO pins. + +param **`ss`** SPI Chip/Slave Select pin. + +param **`sck`** SPI Clock pin. + +param **`miso`** SPI MISO pin. + +param **`mosi`** SPI MOSI pin. + +return **`Boolean`** type status indicates the success of the operation. + +```cpp +bool sdBegin( int8_t ss = -1, int8_t sck = -1, int8_t miso = -1, int8_t mosi = -1); +``` + + + + + ## Realtime database functions These functions can be called directly from RTDB object in the Firebase object e.g. Firebase.RTDB.[Function Name] @@ -712,7 +733,7 @@ bool pushFile(FirebaseData *fbdo, fb_esp_mem_storage_type storageType, const cha bool push(FirebaseData *fbdo, fb_esp_mem_storage_type storageType, const char *path, const char *fileName); ``` -To use LittleFS file system for flash memory instead of SPIFFS (only for ES8266 at this time), add the following macro in **FirebaseFS.h** +To use LittleFS file system for flash memory instead of FLASH (only for ES8266 at this time), add the following macro in **FirebaseFS.h** ```cpp #define USE_LITTLEFS @@ -732,7 +753,7 @@ bool pushFile(FirebaseData *fbdo, fb_esp_mem_storage_type storageType, const cha bool push(FirebaseData *fbdo, fb_esp_mem_storage_type storageType, const char *path, const char *fileName, float priority); ``` -To use LittleFS file system for flash memory instead of SPIFFS (only for ES8266 at this time), add the following macro in **FirebaseFS.h** +To use LittleFS file system for flash memory instead of FLASH (only for ES8266 at this time), add the following macro in **FirebaseFS.h** ```cpp #define USE_LITTLEFS @@ -1474,7 +1495,7 @@ bool setFile(FirebaseData *fbdo, fb_esp_mem_storage_type storageType, const char bool set(FirebaseData *fbdo, fb_esp_mem_storage_type storageType, const char *path, const char *fileName); ``` -To use LittleFS file system for flash memory instead of SPIFFS (only for ESP8266 at this time), add the following macro in **FirebaseFS.h** +To use LittleFS file system for flash memory instead of FLASH (only for ESP8266 at this time), add the following macro in **FirebaseFS.h** ```cpp #define USE_LITTLEFS @@ -1523,7 +1544,7 @@ bool setFile(FirebaseData *fbdo, fb_esp_mem_storage_type storageType, const char bool set(FirebaseData *fbdo, fb_esp_mem_storage_type storageType, const char *path, const char *fileName, const char *ETag); ``` -To use LittleFS file system for flash memory instead of SPIFFS only for ESP8266 at this time), add the following macro in **FirebaseFS.h** +To use LittleFS file system for flash memory instead of FLASH only for ESP8266 at this time), add the following macro in **FirebaseFS.h** ```cpp #define USE_LITTLEFS @@ -2207,7 +2228,7 @@ return **`Boolean`** value, indicates the success of the operation. bool getFile(FirebaseData *fbdo, fb_esp_mem_storage_type storageType, const char *nodePath, const char *fileName); ``` -To use LittleFS file system for flash memory instead of SPIFFS (only for ESP8266 at this time), add the following macro in **FirebaseFS.h** +To use LittleFS file system for flash memory instead of FLASH (only for ESP8266 at this time), add the following macro in **FirebaseFS.h** ```cpp #define USE_LITTLEFS @@ -2459,7 +2480,7 @@ return **`Boolean`** value, indicates the success of the operation. bool backup(FirebaseData *fbdo, fb_esp_mem_storage_type storageType, const char *nodePath, const char *fileName); ``` -To use LittleFS file system for flash memory instead of SPIFFS (only for ESP8266 at this time), add the following macro in **FirebaseFS.h** +To use LittleFS file system for flash memory instead of FLASH (only for ESP8266 at this time), add the following macro in **FirebaseFS.h** ```cpp #define USE_LITTLEFS @@ -2486,7 +2507,7 @@ return **`Boolean`** value, indicates the success of the operation. bool restore(FirebaseData *fbdo, fb_esp_mem_storage_type storageType, const char *nodePath, const char *fileName); ``` -To use LittleFS file system for flash memory instead of SPIFFS (only for ESP8266 at this time), add the following macro in **FirebaseFS.h** +To use LittleFS file system for flash memory instead of FLASH (only for ESP8266 at this time), add the following macro in **FirebaseFS.h** ```cpp #define USE_LITTLEFS @@ -2564,7 +2585,7 @@ The file systems can be changed in FirebaseFS.h. bool deleteStorageFile(const char *filename, fb_esp_mem_storage_type storageType); ``` -To use LittleFS file system for flash memory instead of SPIFFS (only for ESP8266 at this time), add the following macro in **FirebaseFS.h** +To use LittleFS file system for flash memory instead of FLASH (only for ESP8266 at this time), add the following macro in **FirebaseFS.h** ```cpp #define USE_LITTLEFS @@ -4439,7 +4460,7 @@ return **`String`** (String object) of a file name that stores on SD card/flash ```cpp String getBackupFilename(); ``` -To use LittleFS file system for flash memory instead of SPIFFS, add the following macro in **FirebaseFS.h** +To use LittleFS file system for flash memory instead of FLASH, add the following macro in **FirebaseFS.h** ```cpp #define USE_LITTLEFS diff --git a/src/Utils.h b/src/Utils.h index fe64b8337..cc26b9168 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -1,9 +1,9 @@ /** - * Google's Firebase Util class, Utils.h version 1.0.5 + * Google's Firebase Util class, Utils.h version 1.0.6 * * This library supports Espressif ESP8266 and ESP32 * - * Created March 8, 2021 + * Created March 11, 2021 * * This work is a part of Firebase ESP Client library * Copyright (c) 2021, 2021 K. Suwatchai (Mobizt) @@ -43,7 +43,7 @@ class UtilsClass public: long default_ts = ESP_DEFAULT_TS; - uint16_t ntpTimeout = 3000; + uint16_t ntpTimeout = 20; callback_function_t _callback_function = nullptr; FirebaseConfig *config = nullptr; @@ -304,7 +304,7 @@ class UtilsClass { char *host = newS(url.length() + 5); char *uri = newS(url.length() + 5); - char *auth = newS(url.length()+ 5); + char *auth = newS(url.length() + 5); int p1 = 0; char *tmp = strP(fb_esp_pgm_str_441); @@ -345,7 +345,7 @@ class UtilsClass } info.uri = uri; - info.host= host; + info.host = host; info.auth = auth; delS(uri); delS(host); @@ -1264,7 +1264,7 @@ class UtilsClass now = time(nullptr); if (now > default_ts || millis() - timeout > ntpTimeout) break; - delay(200); + delay(10); } delS(server1); @@ -1274,6 +1274,7 @@ class UtilsClass config->_int.fb_clock_rdy = now > default_ts; if (config->_int.fb_clock_rdy) config->_int.fb_gmt_offset = gmtOffset; + return config->_int.fb_clock_rdy; } @@ -1382,11 +1383,50 @@ class UtilsClass return ((len + 2) / 3 * 4) + 1; } + bool sdBegin(int8_t ss, int8_t sck, int8_t miso, int8_t mosi) + { + if (config) + { + config->_int.sd_config.sck = sck; + config->_int.sd_config.miso = miso; + config->_int.sd_config.mosi = mosi; + config->_int.sd_config.ss = ss; + } +#if defined(ESP32) + if (ss > -1) + { + SPI.begin(sck, miso, mosi, ss); + return SD_FS.begin(ss, SPI); + } + else + return SD_FS.begin(); +#elif defined(ESP8266) + if (ss > -1) + return SD_FS.begin(ss); + else + return SD_FS.begin(SD_CS_PIN); +#endif + } + + bool flashTest() + { +#if defined(ESP32) + if (FORMAT_SPIFFS == 1) + config->_int.fb_flash_rdy = FLASH_FS.begin(true); + else + config->_int.fb_flash_rdy = FLASH_FS.begin(); +#elif defined(ESP8266) + config->_int.fb_flash_rdy = FLASH_FS.begin(); +#endif + return config->_int.fb_flash_rdy; + } + bool sdTest(fs::File file) { std::string filepath = "/sdtest01.txt"; - SD_FS.begin(SD_CS_PIN); + if (!sdBegin(config->_int.sd_config.ss, config->_int.sd_config.sck, config->_int.sd_config.miso, config->_int.sd_config.mosi)) + return false; file = SD_FS.open(filepath.c_str(), FILE_WRITE); if (!file) diff --git a/src/common.h b/src/common.h index 02e51fddc..4924f0a84 100644 --- a/src/common.h +++ b/src/common.h @@ -148,6 +148,7 @@ enum fb_esp_settings_provider_type enum fb_esp_auth_token_status { token_status_uninitialized, + token_status_on_initialize, token_status_on_signing, token_status_on_request, token_status_on_refresh, @@ -451,6 +452,7 @@ struct fb_esp_token_signer_resources_t int step = 0; int attempts = 0; bool signup = false; + bool tokenTaskRunning = false; unsigned long lastReqMillis = 0; unsigned long preRefreshMillis = 5 * 60 * 1000; unsigned long reqTO = 2000; @@ -505,6 +507,7 @@ struct fb_esp_stream_info_t struct fb_esp_cfg_int_t { + struct fb_esp_sd_config_info_t sd_config; bool fb_multiple_requests = false; bool fb_processing = false; uint8_t fb_stream_idx = 0; @@ -517,7 +520,7 @@ struct fb_esp_cfg_int_t uint16_t fb_reconnect_tmo = WIFI_RECONNECT_TIMEOUT; bool fb_clock_rdy = false; float fb_gmt_offset = 0; - const char* fb_caCert = nullptr; + const char *fb_caCert = nullptr; uint8_t fb_float_digits = 5; uint8_t fb_double_digits = 9; bool fb_auth_uri = false; @@ -527,20 +530,10 @@ struct fb_esp_cfg_int_t TaskHandle_t resumable_upload_task_handle = NULL; TaskHandle_t functions_check_task_handle = NULL; TaskHandle_t functions_deployment_task_handle = NULL; + TaskHandle_t token_processing_task_handle = NULL; #endif }; -struct fb_esp_cfg_t -{ - struct fb_esp_service_account_t service_account; - std::string host; - std::string api_key; - float time_zone = 0; - struct fb_esp_auth_cert_t cert; - struct fb_esp_token_signer_resources_t signer; - struct fb_esp_cfg_int_t _int; -}; - struct fb_esp_url_info_t { std::string host; @@ -573,11 +566,26 @@ struct fb_esp_fcs_file_list_t std::vector items = std::vector(); }; -struct token_info_t +typedef struct token_info_t { fb_esp_auth_token_type type = token_type_undefined; fb_esp_auth_token_status status = token_status_uninitialized; struct fb_esp_auth_token_error_t error; +} TokenInfo; + +typedef void (*TokenStatusCallback)(TokenInfo); + +struct fb_esp_cfg_t +{ + struct fb_esp_service_account_t service_account; + std::string host; + std::string api_key; + float time_zone = 0; + struct fb_esp_auth_cert_t cert; + struct fb_esp_token_signer_resources_t signer; + struct fb_esp_cfg_int_t _int; + TokenStatusCallback token_status_callback = NULL; + int8_t max_token_generation_retry = MAX_EXCHANGE_TOKEN_ATTEMPTS; }; struct fb_esp_rtdb_info_t @@ -1163,7 +1171,7 @@ static const char fb_esp_pgm_str_54[] PROGMEM = "not found"; static const char fb_esp_pgm_str_55[] PROGMEM = "method not allow"; static const char fb_esp_pgm_str_56[] PROGMEM = "not acceptable"; static const char fb_esp_pgm_str_57[] PROGMEM = "proxy authentication required"; -static const char fb_esp_pgm_str_58[] PROGMEM = "request timeout"; +static const char fb_esp_pgm_str_58[] PROGMEM = "request timed out"; static const char fb_esp_pgm_str_59[] PROGMEM = "length required"; static const char fb_esp_pgm_str_60[] PROGMEM = "too many requests"; static const char fb_esp_pgm_str_61[] PROGMEM = "request header fields too larg"; @@ -1316,7 +1324,7 @@ static const char fb_esp_pgm_str_207[] PROGMEM = "refreshToken"; static const char fb_esp_pgm_str_208[] PROGMEM = "id_token"; static const char fb_esp_pgm_str_209[] PROGMEM = "refresh_token"; static const char fb_esp_pgm_str_210[] PROGMEM = "expires_in"; -static const char fb_esp_pgm_str_211[] PROGMEM = "waiting for token to be ready"; +static const char fb_esp_pgm_str_211[] PROGMEM = "system time was not set"; static const char fb_esp_pgm_str_212[] PROGMEM = "iss"; static const char fb_esp_pgm_str_213[] PROGMEM = "sub"; static const char fb_esp_pgm_str_214[] PROGMEM = "aud"; @@ -1649,6 +1657,13 @@ static const char fb_esp_pgm_str_539[] PROGMEM = "readTime"; static const char fb_esp_pgm_str_540[] PROGMEM = "upload timed out"; static const char fb_esp_pgm_str_541[] PROGMEM = "upload data sent error"; +static const char fb_esp_pgm_str_542[] PROGMEM = "No topic provided"; +static const char fb_esp_pgm_str_543[] PROGMEM = "No device token provided"; +static const char fb_esp_pgm_str_544[] PROGMEM = "The index of recipient device registered token not found"; + +static const char fb_esp_pgm_str_545[] PROGMEM = "create message digest"; +static const char fb_esp_pgm_str_546[] PROGMEM = "tokenProcessingTask"; +static const char fb_esp_pgm_str_547[] PROGMEM = "max token generation retry reached"; static const unsigned char fb_esp_base64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const char fb_esp_boundary_table[] PROGMEM = "=_abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; diff --git a/src/functions/FB_Functions.cpp b/src/functions/FB_Functions.cpp index d5ef9b8fa..13dd30fa4 100644 --- a/src/functions/FB_Functions.cpp +++ b/src/functions/FB_Functions.cpp @@ -1,9 +1,9 @@ /** - * Google's Cloud Functions class, Functions.cpp version 1.0.2 + * Google's Cloud Functions class, Functions.cpp version 1.0.3 * * This library supports Espressif ESP8266 and ESP32 * - * Created February 21, 2021 + * Created March 11, 2021 * * This work is a part of Firebase ESP Client library * Copyright (c) 2020, 2021 K. Suwatchai (Mobizt) @@ -155,7 +155,7 @@ bool FB_Functions::createFunctionInt(FirebaseData *fbdo, const char *functionId, else if (config->_uploadArchiveStorageType == mem_storage_type_flash) { if (!Signer.getCfg()->_int.fb_flash_rdy) - Signer.getCfg()->_int.fb_flash_rdy = FLASH_FS.begin(); + ut->flashTest(); if (!Signer.getCfg()->_int.fb_flash_rdy || !FLASH_FS.exists(config->_uploadArchiveFile.c_str())) { diff --git a/src/functions/FB_Functions.h b/src/functions/FB_Functions.h index 0a9a5c3ad..74f7ca50a 100644 --- a/src/functions/FB_Functions.h +++ b/src/functions/FB_Functions.h @@ -1,9 +1,9 @@ /** - * Google's Cloud Functions class, Functions.h version 1.0.2 + * Google's Cloud Functions class, Functions.h version 1.0.3 * * This library supports Espressif ESP8266 and ESP32 * - * Created February 21, 2021 + * Created March 11, 2021 * * This work is a part of Firebase ESP Client library * Copyright (c) 2020, 2021 K. Suwatchai (Mobizt) diff --git a/src/gcs/GCS.cpp b/src/gcs/GCS.cpp index 96c16273d..5a35349e2 100644 --- a/src/gcs/GCS.cpp +++ b/src/gcs/GCS.cpp @@ -1,9 +1,9 @@ /** - * Google's Cloud Storage class, GCS.cpp version 1.0.2 + * Google's Cloud Storage class, GCS.cpp version 1.0.3 * * This library supports Espressif ESP8266 and ESP32 * - * Created March 5, 2021 + * Created March 11, 2021 * * This work is a part of Firebase ESP Client library * Copyright (c) 2020, 2021 K. Suwatchai (Mobizt) @@ -254,7 +254,7 @@ bool GG_CloudStorage::gcs_sendRequest(FirebaseData *fbdo, struct fb_esp_gcs_req_ std::string token = Signer.getToken(Signer.getTokenType()); if (!Signer.getCfg()->_int.fb_flash_rdy) - Signer.getCfg()->_int.fb_flash_rdy = FLASH_FS.begin(); + ut->flashTest(); if (req->requestType == fb_esp_gcs_request_type_download) { @@ -270,7 +270,7 @@ bool GG_CloudStorage::gcs_sendRequest(FirebaseData *fbdo, struct fb_esp_gcs_req_ else if (req->storageType == mem_storage_type_flash) { if (!Signer.getCfg()->_int.fb_flash_rdy) - Signer.getCfg()->_int.fb_flash_rdy = FLASH_FS.begin(); + ut->flashTest(); Signer.getCfg()->_int.fb_file = FLASH_FS.open(req->localFileName.c_str(), "w"); } } @@ -303,7 +303,7 @@ bool GG_CloudStorage::gcs_sendRequest(FirebaseData *fbdo, struct fb_esp_gcs_req_ else if (req->storageType == mem_storage_type_flash) { if (!Signer.getCfg()->_int.fb_flash_rdy) - Signer.getCfg()->_int.fb_flash_rdy = FLASH_FS.begin(); + ut->flashTest(); if (!Signer.getCfg()->_int.fb_flash_rdy) { diff --git a/src/gcs/GCS.h b/src/gcs/GCS.h index 2e652ee86..c314a8a66 100644 --- a/src/gcs/GCS.h +++ b/src/gcs/GCS.h @@ -1,9 +1,9 @@ /** - * Google's Cloud Storage class, GCS.h version 1.0.2 + * Google's Cloud Storage class, GCS.h version 1.0.3 * * This library supports Espressif ESP8266 and ESP32 * - * Created March 5, 2021 + * Created March 11, 2021 * * This work is a part of Firebase ESP Client library * Copyright (c) 2020, 2021 K. Suwatchai (Mobizt) diff --git a/src/rtdb/FB_RTDB.cpp b/src/rtdb/FB_RTDB.cpp index 5fe7bef34..20037a2ac 100644 --- a/src/rtdb/FB_RTDB.cpp +++ b/src/rtdb/FB_RTDB.cpp @@ -1,9 +1,9 @@ /** - * Google's Firebase Realtime Database class, FB_RTDB.cpp version 1.0.3 + * Google's Firebase Realtime Database class, FB_RTDB.cpp version 1.0.4 * * This library supports Espressif ESP8266 and ESP32 * - * Created February 21, 2021 + * Created March 11, 2021 * * This work is a part of Firebase ESP Client library * Copyright (c) 2020, 2021 K. Suwatchai (Mobizt) @@ -2976,7 +2976,7 @@ bool FB_RTDB::saveErrorQueue(FirebaseData *fbdo, const char *filename, fb_esp_me else if (storageType == mem_storage_type_flash) { if (!Signer.getCfg()->_int.fb_flash_rdy) - Signer.getCfg()->_int.fb_flash_rdy = FLASH_FS.begin(); + ut->flashTest(); Signer.getCfg()->_int.fb_file = FLASH_FS.open(filename, "w"); } @@ -3061,7 +3061,7 @@ bool FB_RTDB::deleteStorageFile(const char *filename, fb_esp_mem_storage_type st else { if (!Signer.getCfg()->_int.fb_flash_rdy) - Signer.getCfg()->_int.fb_flash_rdy = FLASH_FS.begin(); + ut->flashTest(); return FLASH_FS.remove(filename); } } @@ -3080,7 +3080,7 @@ uint8_t FB_RTDB::openErrorQueue(FirebaseData *fbdo, const char *filename, fb_esp else if (storageType == mem_storage_type_flash) { if (!Signer.getCfg()->_int.fb_flash_rdy) - Signer.getCfg()->_int.fb_flash_rdy = FLASH_FS.begin(); + ut->flashTest(); Signer.getCfg()->_int.fb_file = FLASH_FS.open(filename, "r"); } @@ -3499,7 +3499,8 @@ int FB_RTDB::sendRequest(FirebaseData *fbdo, struct fb_esp_rtdb_request_info_t * if (fbdo->_ss.rtdb.storage_type == mem_storage_type_flash) { if (!Signer.getCfg()->_int.fb_flash_rdy) - Signer.getCfg()->_int.fb_flash_rdy = FLASH_FS.begin(); + ut->flashTest(); + if (!Signer.getCfg()->_int.fb_flash_rdy) { ut->appendP(fbdo->_ss.error, fb_esp_pgm_str_164, true); @@ -4073,7 +4074,7 @@ bool FB_RTDB::handleResponse(FirebaseData *fbdo) { tmp = ut->strP(fb_esp_pgm_str_184); if (!Signer.getCfg()->_int.fb_flash_rdy) - Signer.getCfg()->_int.fb_flash_rdy = FLASH_FS.begin(); + ut->flashTest(); Signer.getCfg()->_int.fb_file = FLASH_FS.open(tmp, "w"); ut->delS(tmp); diff --git a/src/rtdb/FB_RTDB.h b/src/rtdb/FB_RTDB.h index faa8c8e73..7c8eeda86 100644 --- a/src/rtdb/FB_RTDB.h +++ b/src/rtdb/FB_RTDB.h @@ -1,9 +1,9 @@ /** - * Google's Firebase Realtime Database class, FB_RTDB.h version 1.0.3 + * Google's Firebase Realtime Database class, FB_RTDB.h version 1.0.4 * * This library supports Espressif ESP8266 and ESP32 * - * Created February 21, 2021 + * Created March 11, 2021 * * This work is a part of Firebase ESP Client library * Copyright (c) 2020, 2021 K. Suwatchai (Mobizt) diff --git a/src/session/FB_Session.cpp b/src/session/FB_Session.cpp index bb89f2453..d73a69538 100644 --- a/src/session/FB_Session.cpp +++ b/src/session/FB_Session.cpp @@ -1,9 +1,9 @@ /** - * Google's Firebase Data class, FB_Session.cpp version 1.0.3 + * Google's Firebase Data class, FB_Session.cpp version 1.0.4 * * This library supports Espressif ESP8266 and ESP32 * - * Created March 8, 2021 + * Created March 11, 2021 * * This work is a part of Firebase ESP Client library * Copyright (c) 2020, 2021 K. Suwatchai (Mobizt) @@ -396,7 +396,9 @@ fs::File FirebaseData::fileStream() { char *tmp = ut->strP(fb_esp_pgm_str_184); - if (FLASH_FS.begin()) + ut->flashTest(); + + if (Signer.getCfg()->_int.fb_flash_rdy) Signer.getCfg()->_int.fb_file = FLASH_FS.open(tmp, "r"); ut->delS(tmp); } @@ -624,7 +626,7 @@ bool FirebaseData::reconnect(unsigned long dataTime) void FirebaseData::setSecure() { - + #if defined(ESP8266) if (time(nullptr) > ESP_DEFAULT_TS) { @@ -662,7 +664,12 @@ void FirebaseData::setSecure() } else { - httpClient.setCACertFile(Signer.getCAFile().c_str(), Signer.getCAFileStorage(), SD_CS_PIN); + +#if defined(ESP8266) + if (Signer.getCfg()->_int.sd_config.ss == -1) + Signer.getCfg()->_int.sd_config.ss = SD_CS_PIN; +#endif + httpClient.setCACertFile(Signer.getCAFile().c_str(), Signer.getCAFileStorage(), Signer.getCfg()->_int.sd_config); } } } diff --git a/src/session/FB_Session.h b/src/session/FB_Session.h index 605b13238..357020bf4 100644 --- a/src/session/FB_Session.h +++ b/src/session/FB_Session.h @@ -1,9 +1,9 @@ /** - * Google's Firebase Data class, FB_Session.h version 1.0.3 + * Google's Firebase Data class, FB_Session.h version 1.0.4 * * This library supports Espressif ESP8266 and ESP32 * - * Created March 8, 2021 + * Created March 11, 2021 * * This work is a part of Firebase ESP Client library * Copyright (c) 2020, 2021 K. Suwatchai (Mobizt) @@ -47,7 +47,7 @@ class FirebaseData friend class FB_CM; friend class FB_RTDB; friend class GG_CloudStorage; - friend class FB_CloudStorage; + friend class FB_Storage; friend class UtilsClass; friend class FB_Firestore; friend class FB_Functions; diff --git a/src/signer/Signer.cpp b/src/signer/Signer.cpp index 1d3d68869..ebdc8c184 100644 --- a/src/signer/Signer.cpp +++ b/src/signer/Signer.cpp @@ -1,9 +1,9 @@ /** - * Google's Firebase Token Generation class, Signer.cpp version 1.0.2 + * Google's Firebase Token Generation class, Signer.cpp version 1.0.3 * * This library supports Espressif ESP8266 and ESP32 * - * Created March 8, 2021 + * Created March 13, 2021 * * This work is a part of Firebase ESP Client library * Copyright (c) 2020, 2021 K. Suwatchai (Mobizt) @@ -57,7 +57,7 @@ bool Firebase_Signer::parseSAFile() if (config->service_account.json.storage_type == mem_storage_type_sd && !config->_int.fb_sd_rdy) config->_int.fb_sd_rdy = ut->sdTest(config->_int.fb_file); else if (config->service_account.json.storage_type == mem_storage_type_flash && !config->_int.fb_flash_rdy) - config->_int.fb_flash_rdy = FLASH_FS.begin(); + ut->flashTest(); if (config->_int.fb_sd_rdy || config->_int.fb_flash_rdy) { @@ -199,7 +199,7 @@ bool Firebase_Signer::userSigninDataReady() return config->api_key.length() > 0 && auth->user.email.length() > 0 && auth->user.password.length() > 0; } -bool Firebase_Signer::hanldeToken() +bool Firebase_Signer::handleToken() { if (!config || !auth) return false; @@ -216,19 +216,22 @@ bool Firebase_Signer::hanldeToken() config->signer.lastReqMillis = millis(); if (config->_int.fb_processing) return false; + config->signer.tokens.status = token_status_on_refresh; + config->signer.tokens.error.code = 0; + config->signer.tokens.error.message.clear(); + sendTokenStatusCB(); return refreshToken(); } return false; } else { - if (config->signer.tokens.token_type == token_type_id_token) { if (millis() - config->signer.lastReqMillis > config->signer.reqTO || config->signer.lastReqMillis == 0) { - config->signer.lastReqMillis = millis(); - return getIdToken(false, "", ""); + _token_processing_task_enable = true; + tokenProcessingTask(); } return false; } @@ -236,45 +239,24 @@ bool Firebase_Signer::hanldeToken() { if (config->signer.step == fb_esp_jwt_generation_step_begin) { - if (config->service_account.json.path.length() > 0 && config->signer.pk.length() == 0) - { - if (!parseSAFile()) - config->signer.tokens.status = token_status_uninitialized; - } - -#if defined(ESP8266) - config->signer.step++; - set_scheduled_callback(std::bind(&Firebase_Signer::runJWT, this)); -#endif - } - if (ut->setClock(config->time_zone)) - { - setTokenError(FIREBASE_ERROR_TOKEN_NOT_READY); -#if defined(ESP32) - config->signer.step++; - createJWT(); -#endif - if (config->signer.step == fb_esp_jwt_generation_step_sign) + if (!config->signer.tokenTaskRunning) { -#if defined(ESP32) - - createJWT(); - if (config->signer.step == fb_esp_jwt_generation_step_exchange) + if (config->service_account.json.path.length() > 0 && config->signer.pk.length() == 0) { - while (config->signer.step == fb_esp_jwt_generation_step_exchange && config->signer.attempts < MAX_EXCHANGE_TOKEN_ATTEMPTS) - requestTokens(); - config->signer.attempts = 0; + if (!parseSAFile()) + config->signer.tokens.status = token_status_uninitialized; } -#elif defined(ESP8266) - set_scheduled_callback(std::bind(&Firebase_Signer::runJWT, this)); -#endif + + config->signer.tokens.status = token_status_on_initialize; + config->signer.tokens.error.code = 0; + config->signer.tokens.error.message.clear(); + sendTokenStatusCB(); + + _token_processing_task_enable = true; + tokenProcessingTask(); } } - else - { - setTokenError(FIREBASE_ERROR_TOKEN_SET_TIME); - } } } } @@ -293,12 +275,199 @@ bool Firebase_Signer::hanldeToken() } } +void Firebase_Signer::tokenProcessingTask() +{ +#if defined(ESP32) + + if (config->signer.tokenTaskRunning) + return; + + static Firebase_Signer *_this = this; + + TaskFunction_t taskCode = [](void *param) { + _this->config->signer.tokenTaskRunning = true; + + while (_this->_token_processing_task_enable) + { + vTaskDelay(20 / portTICK_PERIOD_MS); + + if (_this->config->signer.tokens.token_type == token_type_id_token) + { + _this->config->signer.lastReqMillis = millis(); + if (_this->getIdToken(false, "", "")) + { + _this->_token_processing_task_enable = false; + _this->config->signer.attempts = 0; + break; + } + else + { + if (_this->config->signer.attempts < _this->config->max_token_generation_retry) + _this->config->signer.attempts++; + else + { + _this->config->signer.tokens.error.message.clear(); + _this->setTokenError(FIREBASE_ERROR_TOKEN_EXCHANGE_MAX_RETRY_REACHED); + _this->sendTokenStatusCB(); + _this->_token_processing_task_enable = false; + _this->config->signer.attempts = 0; + break; + } + } + } + else + { + if (_this->config->signer.step == fb_esp_jwt_generation_step_begin) + { + _this->ut->setClock(_this->config->time_zone); + time_t now = time(nullptr); + _this->config->_int.fb_clock_rdy = now > _this->ut->default_ts; + + if (_this->config->_int.fb_clock_rdy) + _this->config->signer.step = fb_esp_jwt_generation_step_encode_header_payload; + } + else if (_this->config->signer.step == fb_esp_jwt_generation_step_encode_header_payload) + { + if (_this->createJWT()) + _this->config->signer.step = fb_esp_jwt_generation_step_sign; + } + else if (_this->config->signer.step == fb_esp_jwt_generation_step_sign) + { + if (_this->createJWT()) + _this->config->signer.step = fb_esp_jwt_generation_step_exchange; + } + else if (_this->config->signer.step == fb_esp_jwt_generation_step_exchange) + { + if (_this->requestTokens()) + { + _this->config->signer.attempts = 0; + _this->_token_processing_task_enable = false; + _this->config->signer.step = fb_esp_jwt_generation_step_begin; + break; + } + else + { + if (_this->config->signer.attempts < _this->config->max_token_generation_retry) + _this->config->signer.attempts++; + else + { + _this->config->signer.tokens.error.message.clear(); + _this->setTokenError(FIREBASE_ERROR_TOKEN_EXCHANGE_MAX_RETRY_REACHED); + _this->sendTokenStatusCB(); + _this->config->signer.attempts = 0; + _this->config->signer.step = fb_esp_jwt_generation_step_begin; + break; + } + } + } + } + + yield(); + } + + vTaskDelete(NULL); + + _this->config->_int.token_processing_task_handle = NULL; + _this->config->signer.tokenTaskRunning = false; + }; + + char *taskname = ut->strP(fb_esp_pgm_str_546); + xTaskCreatePinnedToCore(taskCode, taskname, 12000, NULL, 3, &config->_int.token_processing_task_handle, 1); + ut->delS(taskname); + +#elif defined(ESP8266) + + if (_token_processing_task_enable) + { + if (config->signer.tokens.token_type == token_type_id_token) + { + config->signer.tokenTaskRunning = true; + + config->signer.lastReqMillis = millis(); + if (getIdToken(false, "", "")) + { + _token_processing_task_enable = false; + config->signer.attempts = 0; + config->signer.tokenTaskRunning = false; + return; + } + else + { + if (config->signer.attempts < config->max_token_generation_retry) + config->signer.attempts++; + else + { + config->signer.tokens.error.message.clear(); + setTokenError(FIREBASE_ERROR_TOKEN_EXCHANGE_MAX_RETRY_REACHED); + sendTokenStatusCB(); + _token_processing_task_enable = false; + config->signer.attempts = 0; + config->signer.tokenTaskRunning = false; + return; + } + } + } + else + { + if (config->signer.step == fb_esp_jwt_generation_step_begin) + { + config->signer.tokenTaskRunning = true; + ut->setClock(config->time_zone); + time_t now = time(nullptr); + config->_int.fb_clock_rdy = now > ut->default_ts; + + if (config->_int.fb_clock_rdy) + config->signer.step = fb_esp_jwt_generation_step_encode_header_payload; + } + else if (config->signer.step == fb_esp_jwt_generation_step_encode_header_payload) + { + if (createJWT()) + config->signer.step = fb_esp_jwt_generation_step_sign; + } + else if (config->signer.step == fb_esp_jwt_generation_step_sign) + { + if (createJWT()) + config->signer.step = fb_esp_jwt_generation_step_exchange; + } + else if (config->signer.step == fb_esp_jwt_generation_step_exchange) + { + if (requestTokens()) + { + config->signer.tokenTaskRunning = false; + _token_processing_task_enable = false; + config->signer.attempts = 0; + config->signer.step = fb_esp_jwt_generation_step_begin; + return; + } + else + { + if (config->signer.attempts < config->max_token_generation_retry) + config->signer.attempts++; + else + { + config->signer.tokens.error.message.clear(); + setTokenError(FIREBASE_ERROR_TOKEN_EXCHANGE_MAX_RETRY_REACHED); + sendTokenStatusCB(); + config->signer.tokenTaskRunning = false; + _token_processing_task_enable = false; + config->signer.attempts = 0; + config->signer.step = fb_esp_jwt_generation_step_begin; + return; + } + } + } + } + + set_scheduled_callback(std::bind(&Firebase_Signer::tokenProcessingTask, this)); + } + +#endif +} + bool Firebase_Signer::refreshToken() { if (WiFi.status() != WL_CONNECTED) return false; - - config->signer.attempts++; delay(0); if (auth == nullptr) @@ -459,16 +628,20 @@ void Firebase_Signer::setTokenError(int code) if (config->signer.tokens.error.message.length() == 0) { + config->_int.fb_processing = false; switch (code) { case FIREBASE_ERROR_TOKEN_SET_TIME: ut->appendP(config->signer.tokens.error.message, fb_esp_pgm_str_211, true); break; case FIREBASE_ERROR_TOKEN_PARSE_PK: - //ut->appendP(config->signer.tokens.error.message, fb_esp_pgm_str_179, true); + ut->appendP(config->signer.tokens.error.message, fb_esp_pgm_str_179, true); + break; + case FIREBASE_ERROR_TOKEN_CREATE_HASH: + ut->appendP(config->signer.tokens.error.message, fb_esp_pgm_str_545, true); break; case FIREBASE_ERROR_TOKEN_SIGN: - //ut->appendP(config->signer.tokens.error.message, fb_esp_pgm_str_178, true); + ut->appendP(config->signer.tokens.error.message, fb_esp_pgm_str_178, true); break; case FIREBASE_ERROR_TOKEN_EXCHANGE: ut->appendP(config->signer.tokens.error.message, fb_esp_pgm_str_177, true); @@ -476,6 +649,9 @@ void Firebase_Signer::setTokenError(int code) case FIREBASE_ERROR_TOKEN_NOT_READY: ut->appendP(config->signer.tokens.error.message, fb_esp_pgm_str_252, true); break; + case FIREBASE_ERROR_TOKEN_EXCHANGE_MAX_RETRY_REACHED: + ut->appendP(config->signer.tokens.error.message, fb_esp_pgm_str_547, true); + break; case FIREBASE_ERROR_HTTPC_ERROR_NOT_CONNECTED: ut->appendP(config->signer.tokens.error.message, fb_esp_pgm_str_42); break; @@ -494,20 +670,14 @@ void Firebase_Signer::setTokenError(int code) bool Firebase_Signer::handleSignerError(int code) { - if (code > 0) - { - if (config->signer.attempts >= MAX_EXCHANGE_TOKEN_ATTEMPTS) - { - config->signer.attempts = 0; - config->signer.step = fb_esp_jwt_generation_step_begin; - } - } switch (code) { case 1: + config->signer.tokens.error.message.clear(); setTokenError(FIREBASE_ERROR_HTTPC_ERROR_NOT_CONNECTED); + sendTokenStatusCB(); break; case 2: #if defined(ESP32) @@ -516,7 +686,9 @@ bool Firebase_Signer::handleSignerError(int code) #elif defined(ESP8266) config->signer.wcs->stop(); #endif + config->signer.tokens.error.message.clear(); setTokenError(FIREBASE_ERROR_HTTPC_ERROR_CONNECTION_LOST); + sendTokenStatusCB(); break; case 3: #if defined(ESP32) @@ -525,15 +697,15 @@ bool Firebase_Signer::handleSignerError(int code) #elif defined(ESP8266) config->signer.wcs->stop(); #endif + config->signer.tokens.error.message.clear(); setTokenError(FIREBASE_ERROR_HTTP_CODE_REQUEST_TIMEOUT); + sendTokenStatusCB(); break; default: break; } - std::string().swap(config->signer.tokens.jwt); - if (config->signer.wcs) delete config->signer.wcs; if (config->signer.json) @@ -551,15 +723,27 @@ bool Firebase_Signer::handleSignerError(int code) } else if (code == 0) { + config->signer.tokens.error.message.clear(); config->signer.tokens.status = token_status_ready; config->signer.attempts = 0; config->signer.step = fb_esp_jwt_generation_step_begin; + sendTokenStatusCB(); return true; } return false; } +void Firebase_Signer::sendTokenStatusCB() +{ + tokenInfo.status = config->signer.tokens.status; + tokenInfo.type = config->signer.tokens.token_type; + tokenInfo.error = config->signer.tokens.error; + + if (config->token_status_callback) + config->token_status_callback(tokenInfo); +} + bool Firebase_Signer::handleTokenResponse() { if (WiFi.status() != WL_CONNECTED) @@ -567,6 +751,8 @@ bool Firebase_Signer::handleTokenResponse() struct server_response_data_t response; + unsigned long dataTime = millis(); + int chunkIdx = 0; int pChunkIdx = 0; int payloadLen = 3200; @@ -589,17 +775,19 @@ bool Firebase_Signer::handleTokenResponse() #elif defined(ESP8266) WiFiClient *stream = config->signer.wcs; #endif - while (stream->connected() && stream->available() == 0) { - if (WiFi.status() != WL_CONNECTED) + if (!reconnect(dataTime)) { - stream->stop(); + if (stream) + if (stream->connected()) + stream->stop(); return false; } delay(0); } + bool complete = false; int readLen = 0; unsigned long datatime = millis(); @@ -615,7 +803,9 @@ bool Firebase_Signer::handleTokenResponse() delay(0); if (WiFi.status() != WL_CONNECTED) { - stream->stop(); + if (stream) + if (stream->connected()) + stream->stop(); return false; } chunkBufSize = stream->available(); @@ -721,7 +911,6 @@ bool Firebase_Signer::handleTokenResponse() if (millis() - datatime > 5000) complete = true; } - } } @@ -741,35 +930,15 @@ bool Firebase_Signer::handleTokenResponse() return false; } -#if defined(ESP8266) -void Firebase_Signer::runJWT() -{ - if (config->signer.step > fb_esp_jwt_generation_step_begin && config->signer.step < fb_esp_jwt_generation_step_exchange) - createJWT(); - else if (config->signer.step == fb_esp_jwt_generation_step_exchange) - { - while (config->signer.step == fb_esp_jwt_generation_step_exchange && config->signer.attempts < MAX_EXCHANGE_TOKEN_ATTEMPTS) - requestTokens(); - config->signer.attempts = 0; - } -} -#endif - bool Firebase_Signer::createJWT() { - setTokenError(FIREBASE_ERROR_TOKEN_NOT_READY); - - if (time(nullptr) < ut->default_ts) - { -#if defined(ESP8266) - set_scheduled_callback(std::bind(&Firebase_Signer::runJWT, this)); -#endif - return false; - } if (config->signer.step == fb_esp_jwt_generation_step_encode_header_payload) { config->signer.tokens.status = token_status_on_signing; + config->signer.tokens.error.code = 0; + config->signer.tokens.error.message.clear(); + sendTokenStatusCB(); config->signer.json = new FirebaseJson(); config->signer.data = new FirebaseJsonData(); @@ -885,7 +1054,7 @@ bool Firebase_Signer::createJWT() scopes.clear(); } - tmp = ut->strP(fb_esp_pgm_str_220); + tmp = ut->strP(fb_esp_pgm_str_220); config->signer.json->add(tmp, s.c_str()); ut->delS(tmp); } @@ -930,6 +1099,7 @@ bool Firebase_Signer::createJWT() config->signer.tokens.error.message = tmp; ut->delS(tmp); setTokenError(FIREBASE_ERROR_TOKEN_CREATE_HASH); + sendTokenStatusCB(); delete[] config->signer.hash; return false; } @@ -951,6 +1121,7 @@ bool Firebase_Signer::createJWT() else if (config->signer.step == fb_esp_jwt_generation_step_sign) { config->signer.tokens.status = token_status_on_signing; + #if defined(ESP32) config->signer.pk_ctx = new mbedtls_pk_context(); mbedtls_pk_init(config->signer.pk_ctx); @@ -969,6 +1140,7 @@ bool Firebase_Signer::createJWT() config->signer.tokens.error.message = tmp; ut->delS(tmp); setTokenError(FIREBASE_ERROR_TOKEN_PARSE_PK); + sendTokenStatusCB(); mbedtls_pk_free(config->signer.pk_ctx); delete[] config->signer.hash; delete config->signer.pk_ctx; @@ -992,6 +1164,7 @@ bool Firebase_Signer::createJWT() config->signer.tokens.error.message = tmp; ut->delS(tmp); setTokenError(FIREBASE_ERROR_TOKEN_SIGN); + sendTokenStatusCB(); } else { @@ -1031,12 +1204,14 @@ bool Firebase_Signer::createJWT() if (!pk) { setTokenError(FIREBASE_ERROR_TOKEN_PARSE_PK); + sendTokenStatusCB(); return false; } if (!pk->isRSA()) { setTokenError(FIREBASE_ERROR_TOKEN_PARSE_PK); + sendTokenStatusCB(); delete pk; return false; } @@ -1064,16 +1239,16 @@ bool Firebase_Signer::createJWT() config->signer.tokens.jwt += config->signer.encSignature; std::string().swap(config->signer.pk); std::string().swap(config->signer.encSignature); - set_scheduled_callback(std::bind(&Firebase_Signer::runJWT, this)); } else { setTokenError(FIREBASE_ERROR_TOKEN_SIGN); + sendTokenStatusCB(); + return false; } #endif } - config->signer.step++; return true; } @@ -1082,7 +1257,6 @@ bool Firebase_Signer::getIdToken(bool createUser, const char *email, const char if (WiFi.status() != WL_CONNECTED) return false; - config->signer.attempts++; config->signer.signup = false; delay(0); @@ -1094,8 +1268,9 @@ bool Firebase_Signer::getIdToken(bool createUser, const char *email, const char config->signer.tokens.status = token_status_on_request; config->_int.fb_processing = true; - - setTokenError(FIREBASE_ERROR_TOKEN_NOT_READY); + config->signer.tokens.error.code = 0; + config->signer.tokens.error.message.clear(); + sendTokenStatusCB(); #if defined(ESP32) config->signer.wcs = new FB_HTTPClient32(); @@ -1218,10 +1393,17 @@ bool Firebase_Signer::getIdToken(bool createUser, const char *email, const char if (config->signer.data->success) error.message = config->signer.data->stringValue.c_str(); } + if (createUser) config->signer.signupError = error; else + { config->signer.tokens.error = error; + tokenInfo.status = config->signer.tokens.status; + tokenInfo.type = config->signer.tokens.token_type; + tokenInfo.error = config->signer.tokens.error; + sendTokenStatusCB(); + } if (error.code == 0) { @@ -1265,12 +1447,40 @@ bool Firebase_Signer::getIdToken(bool createUser, const char *email, const char return handleSignerError(3); } +bool Firebase_Signer::reconnect(unsigned long dataTime) +{ + + bool status = WiFi.status() == WL_CONNECTED; + + if (dataTime > 0) + { + if (millis() - dataTime > 30000) + return false; + } + + if (!status) + { + + if (config->_int.fb_reconnect_wifi) + { + if (millis() - config->_int.fb_last_reconnect_millis > config->_int.fb_reconnect_tmo) + { + WiFi.reconnect(); + config->_int.fb_last_reconnect_millis = millis(); + } + } + + status = WiFi.status() == WL_CONNECTED; + } + + return status; +} + bool Firebase_Signer::requestTokens() { if (WiFi.status() != WL_CONNECTED) return false; - config->signer.attempts++; delay(0); if (config->signer.tokens.status == token_status_on_request || config->signer.tokens.status == token_status_on_refresh || time(nullptr) < ut->default_ts || config->_int.fb_processing) @@ -1278,7 +1488,9 @@ bool Firebase_Signer::requestTokens() config->signer.tokens.status = token_status_on_request; config->_int.fb_processing = true; - setTokenError(FIREBASE_ERROR_TOKEN_NOT_READY); + config->signer.tokens.error.code = 0; + config->signer.tokens.error.message.clear(); + sendTokenStatusCB(); #if defined(ESP32) config->signer.wcs = new FB_HTTPClient32(); @@ -1362,6 +1574,7 @@ bool Firebase_Signer::requestTokens() req += s.c_str(); #if defined(ESP32) + config->signer.wcs->setInsecure(); if (config->signer.wcs->send(req.c_str(), "") < 0) return handleSignerError(2); #elif defined(ESP8266) @@ -1376,6 +1589,7 @@ bool Firebase_Signer::requestTokens() if (handleTokenResponse()) { + std::string().swap(config->signer.tokens.jwt); tmp = ut->strP(fb_esp_pgm_str_257); config->signer.json->get(*config->signer.data, tmp); ut->delS(tmp); @@ -1598,7 +1812,7 @@ void Firebase_Signer::checkToken() if (config->host.length() == 0) return; if ((config->signer.tokens.token_type == token_type_id_token || config->signer.tokens.token_type == token_type_custom_token || config->signer.tokens.token_type == token_type_oauth2_access_token) && (millis() > config->signer.tokens.expires - config->signer.preRefreshMillis || config->signer.tokens.expires == 0)) - hanldeToken(); + handleToken(); } bool Firebase_Signer::tokenReady() @@ -1779,7 +1993,7 @@ void Firebase_Signer::errorToString(int httpCode, std::string &buff) case FIREBASE_ERROR_UPLOAD_DATA_ERRROR: ut->appendP(buff, fb_esp_pgm_str_541); return; - default: + default: return; } } diff --git a/src/signer/Signer.h b/src/signer/Signer.h index df425d4c0..e4d1ee5af 100644 --- a/src/signer/Signer.h +++ b/src/signer/Signer.h @@ -1,9 +1,9 @@ /** - * Google's Firebase Token Generation class, Signer.h version 1.0.2 + * Google's Firebase Token Generation class, Signer.h version 1.0.3 * * This library supports Espressif ESP8266 and ESP32 * - * Created March 8, 2021 + * Created March 13, 2021 * * This work is a part of Firebase ESP Client library * Copyright (c) 2020, 2021 K. Suwatchai (Mobizt) @@ -39,12 +39,11 @@ class Firebase_Signer { friend class Firebase_ESP_Client; - friend class FirebaseData; friend class FB_RTDB; friend class FB_CM; + friend class FirebaseData; + friend class FB_Storage; friend class GG_CloudStorage; - friend class FB_CloudStorage; - friend class UtilsClass; friend class FirebaseStream; friend class QueryFilter; friend class MultiPathStream; @@ -65,20 +64,21 @@ class Firebase_Signer FirebaseConfig *config = nullptr; FirebaseAuth *auth = nullptr; callback_function_t _cb = nullptr; + struct token_info_t tokenInfo; + bool _token_processing_task_enable = false; + void begin(UtilsClass *ut, FirebaseConfig *config, FirebaseAuth *auth); bool parseSAFile(); void clearSA(); bool tokenSigninDataReady(); void setTokenType(fb_esp_auth_token_type type); bool userSigninDataReady(); - bool hanldeToken(); + bool handleToken(); bool refreshToken(); void setTokenError(int code); bool handleSignerError(int code); bool handleTokenResponse(); -#if defined(ESP8266) - void runJWT(); -#endif + void tokenProcessingTask(); bool createJWT(); bool getIdToken(bool createUser, const char *email, const char *password); bool requestTokens(); @@ -86,6 +86,8 @@ class Firebase_Signer bool handleEmailSending(const char *payload, fb_esp_user_email_sending_type type); void errorToString(int httpCode, std::string &buff); bool tokenReady(); + bool reconnect(unsigned long dataTime); + void sendTokenStatusCB(); std::string getToken(fb_esp_auth_token_type type); fb_esp_auth_token_type getTokenType(); std::string getCAFile(); diff --git a/src/storage/FCS.cpp b/src/storage/FCS.cpp index 24fc53c11..c63e3e07f 100644 --- a/src/storage/FCS.cpp +++ b/src/storage/FCS.cpp @@ -1,9 +1,9 @@ /** - * Google's Firebase Cloud Storage class, FCS.cpp version 1.0.5 + * Google's Firebase Storage class, FCS.cpp version 1.0.6 * * This library supports Espressif ESP8266 and ESP32 * - * Created February 21, 2021 + * Created March 13, 2021 * * This work is a part of Firebase ESP Client library * Copyright (c) 2020, 2021 K. Suwatchai (Mobizt) @@ -30,24 +30,24 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef FB_CloudStorage_CPP -#define FB_CloudStorage_CPP +#ifndef FB_Storage_CPP +#define FB_Storage_CPP #include "FCS.h" -FB_CloudStorage::FB_CloudStorage() +FB_Storage::FB_Storage() { } -FB_CloudStorage ::~FB_CloudStorage() +FB_Storage ::~FB_Storage() { } -void FB_CloudStorage::begin(UtilsClass *u) +void FB_Storage::begin(UtilsClass *u) { ut = u; } -bool FB_CloudStorage::sendRequest(FirebaseData *fbdo, struct fb_esp_fcs_req_t *req) +bool FB_Storage::sendRequest(FirebaseData *fbdo, struct fb_esp_fcs_req_t *req) { if (fbdo->_ss.rtdb.pause) return true; @@ -103,7 +103,7 @@ bool FB_CloudStorage::sendRequest(FirebaseData *fbdo, struct fb_esp_fcs_req_t *r return fcs_sendRequest(fbdo, req); } -bool FB_CloudStorage::upload(FirebaseData *fbdo, const char *bucketID, const char *localFileName, fb_esp_mem_storage_type storageType, const char *remoteFileName, const char *mime) +bool FB_Storage::upload(FirebaseData *fbdo, const char *bucketID, const char *localFileName, fb_esp_mem_storage_type storageType, const char *remoteFileName, const char *mime) { struct fb_esp_fcs_req_t req; req.localFileName = localFileName; @@ -115,7 +115,7 @@ bool FB_CloudStorage::upload(FirebaseData *fbdo, const char *bucketID, const cha return sendRequest(fbdo, &req); } -bool FB_CloudStorage::upload(FirebaseData *fbdo, const char *bucketID, const uint8_t *data, size_t len, const char *remoteFileName, const char *mime) +bool FB_Storage::upload(FirebaseData *fbdo, const char *bucketID, const uint8_t *data, size_t len, const char *remoteFileName, const char *mime) { struct fb_esp_fcs_req_t req; req.remoteFileName = remoteFileName; @@ -127,7 +127,7 @@ bool FB_CloudStorage::upload(FirebaseData *fbdo, const char *bucketID, const uin return sendRequest(fbdo, &req); } -bool FB_CloudStorage::download(FirebaseData *fbdo, const char *bucketID, const char *remoteFileName, const char *localFileName, fb_esp_mem_storage_type storageType) +bool FB_Storage::download(FirebaseData *fbdo, const char *bucketID, const char *remoteFileName, const char *localFileName, fb_esp_mem_storage_type storageType) { struct fb_esp_fcs_req_t req; req.localFileName = localFileName; @@ -138,7 +138,7 @@ bool FB_CloudStorage::download(FirebaseData *fbdo, const char *bucketID, const c return sendRequest(fbdo, &req); } -bool FB_CloudStorage::getMetadata(FirebaseData *fbdo, const char *bucketID, const char *remoteFileName) +bool FB_Storage::getMetadata(FirebaseData *fbdo, const char *bucketID, const char *remoteFileName) { struct fb_esp_fcs_req_t req; req.remoteFileName = remoteFileName; @@ -147,7 +147,7 @@ bool FB_CloudStorage::getMetadata(FirebaseData *fbdo, const char *bucketID, cons return sendRequest(fbdo, &req); } -bool FB_CloudStorage::deleteFile(FirebaseData *fbdo, const char *bucketID, const char *remoteFileName) +bool FB_Storage::deleteFile(FirebaseData *fbdo, const char *bucketID, const char *remoteFileName) { struct fb_esp_fcs_req_t req; req.requestType = fb_esp_fcs_request_type_delete; @@ -157,7 +157,7 @@ bool FB_CloudStorage::deleteFile(FirebaseData *fbdo, const char *bucketID, const return sendRequest(fbdo, &req); } -bool FB_CloudStorage::listFiles(FirebaseData *fbdo, const char *bucketID) +bool FB_Storage::listFiles(FirebaseData *fbdo, const char *bucketID) { struct fb_esp_fcs_req_t req; req.bucketID = bucketID; @@ -166,7 +166,7 @@ bool FB_CloudStorage::listFiles(FirebaseData *fbdo, const char *bucketID) return sendRequest(fbdo, &req); } -void FB_CloudStorage::rescon(FirebaseData *fbdo, const char *host) +void FB_Storage::rescon(FirebaseData *fbdo, const char *host) { if (!fbdo->_ss.connected || millis() - fbdo->_ss.last_conn_ms > fbdo->_ss.conn_timeout || fbdo->_ss.con_mode != fb_esp_con_mode_storage || strcmp(host, fbdo->_ss.host.c_str()) != 0) { @@ -178,7 +178,7 @@ void FB_CloudStorage::rescon(FirebaseData *fbdo, const char *host) fbdo->_ss.con_mode = fb_esp_con_mode_storage; } -bool FB_CloudStorage::fcs_connect(FirebaseData *fbdo) +bool FB_Storage::fcs_connect(FirebaseData *fbdo) { std::string host; ut->appendP(host, fb_esp_pgm_str_265); @@ -188,7 +188,7 @@ bool FB_CloudStorage::fcs_connect(FirebaseData *fbdo) return true; } -bool FB_CloudStorage::fcs_sendRequest(FirebaseData *fbdo, struct fb_esp_fcs_req_t *req) +bool FB_Storage::fcs_sendRequest(FirebaseData *fbdo, struct fb_esp_fcs_req_t *req) { fbdo->_ss.fcs.requestType = req->requestType; @@ -196,7 +196,7 @@ bool FB_CloudStorage::fcs_sendRequest(FirebaseData *fbdo, struct fb_esp_fcs_req_ std::string token = Signer.getToken(Signer.getTokenType()); if (!Signer.getCfg()->_int.fb_flash_rdy) - Signer.getCfg()->_int.fb_flash_rdy = FLASH_FS.begin(); + ut->flashTest(); if (req->requestType == fb_esp_fcs_request_type_download) { @@ -212,7 +212,8 @@ bool FB_CloudStorage::fcs_sendRequest(FirebaseData *fbdo, struct fb_esp_fcs_req_ else if (req->storageType == mem_storage_type_flash) { if (!Signer.getCfg()->_int.fb_flash_rdy) - Signer.getCfg()->_int.fb_flash_rdy = FLASH_FS.begin(); + ut->flashTest(); + Signer.getCfg()->_int.fb_file = FLASH_FS.open(req->localFileName.c_str(), "w"); } } @@ -245,7 +246,7 @@ bool FB_CloudStorage::fcs_sendRequest(FirebaseData *fbdo, struct fb_esp_fcs_req_ else if (req->storageType == mem_storage_type_flash) { if (!Signer.getCfg()->_int.fb_flash_rdy) - Signer.getCfg()->_int.fb_flash_rdy = FLASH_FS.begin(); + ut->flashTest(); if (!Signer.getCfg()->_int.fb_flash_rdy) { @@ -407,7 +408,7 @@ bool FB_CloudStorage::fcs_sendRequest(FirebaseData *fbdo, struct fb_esp_fcs_req_ return false; } -bool FB_CloudStorage::handleResponse(FirebaseData *fbdo) +bool FB_Storage::handleResponse(FirebaseData *fbdo) { if (fbdo->_ss.rtdb.pause) return true; diff --git a/src/storage/FCS.h b/src/storage/FCS.h index ae64367e9..ad46cb3c0 100644 --- a/src/storage/FCS.h +++ b/src/storage/FCS.h @@ -1,9 +1,9 @@ /** - * Google's Firebase Cloud Storage class, FCS.h version 1.0.5 + * Google's Firebase Storage class, FCS.h version 1.0.6 * * This library supports Espressif ESP8266 and ESP32 * - * Created February 21, 2021 + * Created March 13, 2021 * * This work is a part of Firebase ESP Client library * Copyright (c) 2020, 2021 K. Suwatchai (Mobizt) @@ -30,21 +30,21 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef FB_CloudStorage_H -#define FB_CloudStorage_H +#ifndef FB_Storage_H +#define FB_Storage_H #include #include "Utils.h" #include "session/FB_Session.h" -class FB_CloudStorage +class FB_Storage { friend class Firebase_ESP_Client; public: struct RequestType; - FB_CloudStorage(); - ~FB_CloudStorage(); + FB_Storage(); + ~FB_Storage(); /** Upload file to the Firebase Storage data bucket. * diff --git a/src/stream/FB_Stream.cpp b/src/stream/FB_Stream.cpp index 3890964b1..425a96e91 100644 --- a/src/stream/FB_Stream.cpp +++ b/src/stream/FB_Stream.cpp @@ -1,9 +1,9 @@ /** - * Google's Firebase Stream class, FB_Stream.cpp version 1.0.0 + * Google's Firebase Stream class, FB_Stream.cpp version 1.0.1 * * This library supports Espressif ESP8266 and ESP32 * - * Created January 12, 2021 + * Created March 11, 2021 * * This work is a part of Firebase ESP Client library * Copyright (c) 2020, 2021 K. Suwatchai (Mobizt) @@ -61,7 +61,7 @@ String FirebaseStream::streamPath() int FirebaseStream::intData() { - if (sif->data.length() > 0 && (sif->data_type == fb_esp_data_type::d_integer || sif->data_type == fb_esp_data_type::d_float || sif->data_type== fb_esp_data_type::d_double)) + if (sif->data.length() > 0 && (sif->data_type == fb_esp_data_type::d_integer || sif->data_type == fb_esp_data_type::d_float || sif->data_type == fb_esp_data_type::d_double)) return atoi(sif->data.c_str()); else return 0; @@ -186,7 +186,7 @@ File FirebaseStream::fileStream() if (sif->data_type == fb_esp_data_type::d_file) { char *tmp = ut->strP(fb_esp_pgm_str_184); - if (FLASH_FS.begin()) + if (ut->flashTest()) Signer.getCfg()->_int.fb_file = FLASH_FS.open(tmp, "r"); ut->delS(tmp); } diff --git a/src/stream/FB_Stream.h b/src/stream/FB_Stream.h index bc2c536bc..15f447ed3 100644 --- a/src/stream/FB_Stream.h +++ b/src/stream/FB_Stream.h @@ -1,9 +1,9 @@ /** - * Google's Firebase Stream class, FB_Stream.h version 1.0.0 + * Google's Firebase Stream class, FB_Stream.h version 1.0.1 * * This library supports Espressif ESP8266 and ESP32 * - * Created January 12, 2021 + * Created March 11, 2021 * * This work is a part of Firebase ESP Client library * Copyright (c) 2020, 2021 K. Suwatchai (Mobizt) diff --git a/src/wcs/HTTPCode.h b/src/wcs/HTTPCode.h index 05ce300f7..a004ff960 100644 --- a/src/wcs/HTTPCode.h +++ b/src/wcs/HTTPCode.h @@ -64,10 +64,15 @@ #define FIREBASE_ERROR_TOKEN_PARSE_PK -29 #define FIREBASE_ERROR_TOKEN_SIGN -30 #define FIREBASE_ERROR_TOKEN_EXCHANGE -31 -#define FIREBASE_ERROR_TOKEN_NOT_READY -32 -#define FIREBASE_ERROR_LONG_RUNNING_TASK -33 -#define FIREBASE_ERROR_UPLOAD_TIME_OUT -34 -#define FIREBASE_ERROR_UPLOAD_DATA_ERRROR -35 +#define FIREBASE_ERROR_TOKEN_EXCHANGE_MAX_RETRY_REACHED -32 +#define FIREBASE_ERROR_TOKEN_NOT_READY -33 +#define FIREBASE_ERROR_LONG_RUNNING_TASK -34 +#define FIREBASE_ERROR_UPLOAD_TIME_OUT -35 +#define FIREBASE_ERROR_UPLOAD_DATA_ERRROR -36 + +#define FIREBASE_ERROR_HTTPC_NO_FCM_TOPIC_PROVIDED -37 +#define FIREBASE_ERROR_HTTPC_NO_FCM_DEVICE_TOKEN_PROVIDED -38 +#define FIREBASE_ERROR_HTTPC_NO_FCM_INDEX_NOT_FOUND_IN_DEVICE_TOKEN_PROVIDED -39 /// HTTP codes see RFC7231 diff --git a/src/wcs/esp32/FB_HTTPClient32.cpp b/src/wcs/esp32/FB_HTTPClient32.cpp index fce33834c..046f6253a 100644 --- a/src/wcs/esp32/FB_HTTPClient32.cpp +++ b/src/wcs/esp32/FB_HTTPClient32.cpp @@ -1,18 +1,18 @@ /** - * Customized version of ESP32 HTTPClient Library. + * Customized version of ESP32 HTTPClient Library. * Allow custom header and payload - * + * * v 1.0.7 - * + * * The MIT License (MIT) * Copyright (c) 2021 K. Suwatchai (Mobizt) - * + * * HTTPClient Arduino library for ESP32 * * Copyright (c) 2015 Markus Sattler. All rights reserved. * This file is part of the HTTPClient for Arduino. - * Port to ESP32 by Evandro Luis Copercini (2017), - * changed fingerprints to CA verification. + * Port to ESP32 by Evandro Luis Copercini (2017), + * changed fingerprints to CA verification. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -37,157 +37,167 @@ #include "FB_HTTPClient32.h" -FB_HTTPClient32::FB_HTTPClient32() -{ -} +FB_HTTPClient32::FB_HTTPClient32() {} FB_HTTPClient32::~FB_HTTPClient32() { - if (_wcs) - { - _wcs->stop(); - _wcs.reset(nullptr); - _wcs.release(); - } - std::string().swap(_host); - std::string().swap(_CAFile); + if (_wcs) + { + _wcs->stop(); + _wcs.reset(nullptr); + _wcs.release(); + } + std::string().swap(_host); + std::string().swap(_CAFile); } bool FB_HTTPClient32::begin(const char *host, uint16_t port) { - _host = host; - _port = port; - return true; + _host = host; + _port = port; + return true; } bool FB_HTTPClient32::connected() { - if (_wcs) - return (_wcs->connected()); - return false; + if (_wcs) + return (_wcs->connected()); + return false; } void FB_HTTPClient32::stop() { - if (!connected()) - return; - return _wcs->stop(); + if (!connected()) + return; + return _wcs->stop(); } bool FB_HTTPClient32::send(const char *header) { - if (!connected()) - return false; - return (_wcs->print(header) == strlen(header)); + if (!connected()) + return false; + return (_wcs->print(header) == strlen(header)); } int FB_HTTPClient32::send(const char *header, const char *payload) { - size_t size = strlen(payload); - if (strlen(header) > 0) + size_t size = strlen(payload); + if (strlen(header) > 0) + { + if (!connect()) { - if (!connect()) - { - return FIREBASE_ERROR_HTTPC_ERROR_CONNECTION_REFUSED; - } - - if (!send(header)) - { - return FIREBASE_ERROR_HTTPC_ERROR_SEND_HEADER_FAILED; - } + return FIREBASE_ERROR_HTTPC_ERROR_CONNECTION_REFUSED; } - if (size > 0) + if (!send(header)) { - if (_wcs->print(payload) != size) - { - return FIREBASE_ERROR_HTTPC_ERROR_SEND_PAYLOAD_FAILED; - } + return FIREBASE_ERROR_HTTPC_ERROR_SEND_HEADER_FAILED; } + } - return 0; + if (size > 0) + { + if (_wcs->print(payload) != size) + { + return FIREBASE_ERROR_HTTPC_ERROR_SEND_PAYLOAD_FAILED; + } + } + + return 0; } WiFiClient *FB_HTTPClient32::stream(void) { - if (connected()) - return _wcs.get(); - return nullptr; + if (connected()) + return _wcs.get(); + return nullptr; } bool FB_HTTPClient32::connect(void) { - if (connected()) - { - while (_wcs->available() > 0) - _wcs->read(); - return true; - } + if (connected()) + { + while (_wcs->available() > 0) + _wcs->read(); + return true; + } - if (!_wcs->connect(_host.c_str(), _port)) - return false; + if (!_wcs->connect(_host.c_str(), _port)) + return false; - return connected(); + return connected(); } void FB_HTTPClient32::setInsecure() { #ifdef CONFIG_ARDUINO_IDF_BRANCH - size_t len = strlen_P(esp_idf_branch_str); - char *tmp = new char[len + 1]; - memset(tmp, 0, len + 1); - std::string s = CONFIG_ARDUINO_IDF_BRANCH; - size_t p1 = s.find(tmp, 0); - if (p1 != std::string::npos) - { - float v = atof(s.substr(p1 + len, s.length() - p1 - len).c_str()); - if (v >= 3.3f) - _wcs->setInsecure(); - } - delete[] tmp; + size_t len = strlen_P(esp_idf_branch_str); + char *tmp = new char[len + 1]; + memset(tmp, 0, len + 1); + std::string s = CONFIG_ARDUINO_IDF_BRANCH; + size_t p1 = s.find(tmp, 0); + if (p1 != std::string::npos) + { + float v = atof(s.substr(p1 + len, s.length() - p1 - len).c_str()); + if (v >= 3.3f) + _wcs->setInsecure(); + } + delete[] tmp; #endif } void FB_HTTPClient32::setCACert(const char *caCert) { - _wcs->setCACert(caCert); - if (caCert) - _certType = 1; - else - { - setInsecure(); - _certType = 0; - } - //_wcs->setNoDelay(true); + _wcs->setCACert(caCert); + if (caCert) + _certType = 1; + else + { + setInsecure(); + _certType = 0; + } + //_wcs->setNoDelay(true); } -void FB_HTTPClient32::setCACertFile(const char *caCertFile, uint8_t storageType, uint8_t sdPin) +void FB_HTTPClient32::setCACertFile(const char *caCertFile, uint8_t storageType, struct fb_esp_sd_config_info_t sd_config) { - if (strlen(caCertFile) > 0) + if (strlen(caCertFile) > 0) + { + _certType = 2; + + File f; + if (storageType == 1) + { + if (FORMAT_SPIFFS == 1) + FLASH_FS.begin(true); + else + FLASH_FS.begin(); + if (FLASH_FS.exists(caCertFile)) + f = FLASH_FS.open(caCertFile, FILE_READ); + } + else if (storageType == 2) + { + if (sd_config.ss > -1) + { + SPI.begin(sd_config.sck, sd_config.miso, sd_config.mosi, sd_config.ss); + SD_FS.begin(sd_config.ss, SPI); + } + else + SD_FS.begin(); + + if (SD_FS.exists(caCertFile)) + f = SD_FS.open(caCertFile, FILE_READ); + } + + if (f) { - _certType = 2; - - File f; - if (storageType == 1) - { - if (FLASH_FS.exists(caCertFile)) - f = SPIFFS.open(caCertFile, FILE_READ); - } - else if (storageType == 2) - { - if (SD_FS.exists(caCertFile)) - f = SD_FS.open(caCertFile, FILE_READ); - } - - if (f) - { - size_t len = f.size(); - _wcs->loadCACert(f, len); - f.close(); - } + size_t len = f.size(); + _wcs->loadCACert(f, len); + f.close(); } - //_wcs->setNoDelay(true); + } + //_wcs->setNoDelay(true); } #endif /* ESP32 */ diff --git a/src/wcs/esp32/FB_HTTPClient32.h b/src/wcs/esp32/FB_HTTPClient32.h index 2d1a1f4e9..c89126e20 100644 --- a/src/wcs/esp32/FB_HTTPClient32.h +++ b/src/wcs/esp32/FB_HTTPClient32.h @@ -50,11 +50,20 @@ #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #define FLASH_FS DEFAULT_FLASH_FS #define SD_FS DEFAULT_SD_FS +#define FORMAT_SPIFFS FORMAT_FLASH_IF_MOUNT_FAILED #include "wcs/HTTPCode.h" static const char esp_idf_branch_str[] PROGMEM = "release/v"; +struct fb_esp_sd_config_info_t +{ + int sck = -1; + int miso = -1; + int mosi = -1; + int ss = -1; +}; + class FB_HTTPClient32 { @@ -114,7 +123,7 @@ class FB_HTTPClient32 bool connect(void); void setCACert(const char *caCert); - void setCACertFile(const char *caCertFile, uint8_t storageType, uint8_t sdPin); + void setCACertFile(const char *caCertFile, uint8_t storageType, struct fb_esp_sd_config_info_t sd_config); protected: std::unique_ptr _wcs = std::unique_ptr(new WiFiClientSecure()); diff --git a/src/wcs/esp8266/FB_HTTPClient.cpp b/src/wcs/esp8266/FB_HTTPClient.cpp index 4f406611d..5f81ae423 100644 --- a/src/wcs/esp8266/FB_HTTPClient.cpp +++ b/src/wcs/esp8266/FB_HTTPClient.cpp @@ -155,9 +155,9 @@ void FB_HTTPClient::setCACert(const char *caCert) _wcs->setNoDelay(true); } -void FB_HTTPClient::setCACertFile(const char *caCertFile, uint8_t storageType, uint8_t sdPin) +void FB_HTTPClient::setCACertFile(const char *caCertFile, uint8_t storageType, struct fb_esp_sd_config_info_t sd_config) { - _sdPin = sdPin; + _sdPin = sd_config.ss; _wcs->setBufferSizes(_bsslRxSize, _bsslTxSize); if (_clockReady && strlen(caCertFile) > 0) diff --git a/src/wcs/esp8266/FB_HTTPClient.h b/src/wcs/esp8266/FB_HTTPClient.h index b0534e42f..144d7e3f1 100644 --- a/src/wcs/esp8266/FB_HTTPClient.h +++ b/src/wcs/esp8266/FB_HTTPClient.h @@ -68,6 +68,13 @@ #include "wcs/HTTPCode.h" +struct fb_esp_sd_config_info_t +{ + int sck = -1; + int miso = -1; + int mosi = -1; + int ss = -1; +}; class FB_HTTPClient { @@ -93,7 +100,7 @@ class FB_HTTPClient WiFiClient *stream(void); void setCACert(const char *caCert); - void setCACertFile(const char* caCertFile, uint8_t storageType, uint8_t sdPin); + void setCACertFile(const char* caCertFile, uint8_t storageType, struct fb_esp_sd_config_info_t sd_config); bool connect(void);