From 60b3d7a2ca416181e7d2a4ccc11682009e996ab8 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 22 Jan 2023 08:09:16 +0700 Subject: [PATCH] Fix NTP and network management issues. --- library.json | 2 +- library.properties | 2 +- src/FB_Utils.h | 78 ++++++++++++++++++++++++++++----------- src/Firebase_ESP_Client.h | 18 +++------ src/MB_NTP.h | 31 ++++++++++------ src/signer/Signer.cpp | 49 ++++++++---------------- src/signer/Signer.h | 3 +- 7 files changed, 100 insertions(+), 83 deletions(-) diff --git a/library.json b/library.json index 75c98e7c9..f5ff6233a 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Firebase Arduino Client Library for ESP8266 and ESP32", - "version": "4.3.3", + "version": "4.3.4", "keywords": "communication, REST, esp32, esp8266, arduino", "description": "The library supports Firebase products e.g. Realtime database, Cloud Firestore database, Firebase Storage and Google Cloud Storage, Cloud Functions for Firebase and Cloud Messaging. The library also supported other Arduino devices using Clients interfaces e.g. WiFiClient, EthernetClient, and GSMClient.", "repository": { diff --git a/library.properties b/library.properties index 67c77d297..681fb74d5 100644 --- a/library.properties +++ b/library.properties @@ -1,6 +1,6 @@ name=Firebase Arduino Client Library for ESP8266 and ESP32 -version=4.3.3 +version=4.3.4 author=Mobizt diff --git a/src/FB_Utils.h b/src/FB_Utils.h index 7cbfd50d3..8a725e014 100644 --- a/src/FB_Utils.h +++ b/src/FB_Utils.h @@ -2,7 +2,7 @@ * * This library supports Espressif ESP8266, ESP32 and Raspberry Pi Pico (RP2040) * - * Created January 17, 2023 + * Created January 21, 2023 * * This work is a part of Firebase ESP Client library * Copyright (c) 2023 K. Suwatchai (Mobizt) @@ -54,7 +54,7 @@ namespace Utils inline void idle() { #if defined(ARDUINO_ESP8266_MAJOR) && defined(ARDUINO_ESP8266_MINOR) && defined(ARDUINO_ESP8266_REVISION) && ((ARDUINO_ESP8266_MAJOR == 3 && ARDUINO_ESP8266_MINOR >= 1) || ARDUINO_ESP8266_MAJOR > 3) - esp_yield(); + esp_yield(); #else delay(0); #endif @@ -1705,14 +1705,58 @@ namespace TimeHelper inline time_t getTime(uint32_t *mb_ts, uint32_t *mb_ts_offset) { uint32_t &tm = *mb_ts; - -#if !defined(FB_ENABLE_EXTERNAL_CLIENT) && (defined(ESP8266) || defined(ESP32) || defined(PICO_RP2040)) +#if defined(FB_ENABLE_EXTERNAL_CLIENT) || defined(PICO_RP2040) + tm = *mb_ts_offset + millis() / 1000; +#elif defined(ESP32) || defined(ESP8266) tm = time(nullptr); +#endif + return tm; + } + + inline int setTimestamp(time_t ts) + { +#if defined(ESP32) || defined(ESP8266) + struct timeval tm = {ts, 0}; // sec, us + return settimeofday((const timeval *)&tm, 0); +#endif + return -1; + } + + inline bool setTime(time_t ts, uint32_t *mb_ts, uint32_t *mb_ts_offset) + { + bool ret = false; + +#if defined(ESP32) || defined(ESP8266) + ret = TimeHelper::setTimestamp(ts) == 0; + *mb_ts = time(nullptr); #else - tm = *mb_ts_offset + millis() / 1000; + if (ts > ESP_DEFAULT_TS) + { + *mb_ts_offset = ts - millis() / 1000; + *mb_ts = ts; + ret = true; + } #endif - return tm; + return ret; + } + + inline bool updateClock(MB_NTP *ntp, uint32_t *mb_ts, uint32_t *mb_ts_offset) + { + uint32_t ts = ntp->getTime(2000 /* wait 10000 ms */); + if (ts > 0) + *mb_ts_offset = ts - millis() / 1000; + + time_t now = getTime(mb_ts, mb_ts_offset); + + bool rdy = now > ESP_DEFAULT_TS; + +#if defined(ESP32) || defined(ESP8266) + if (rdy && time(nullptr) < now) + setTime(now, mb_ts, mb_ts_offset); +#endif + + return rdy; } inline bool syncClock(MB_NTP *ntp, uint32_t *mb_ts, uint32_t *mb_ts_offset, float gmtOffset, FirebaseConfig *config) @@ -1739,19 +1783,20 @@ namespace TimeHelper #if defined(FB_ENABLE_EXTERNAL_CLIENT) - if (*mb_ts_offset == 0) - { - *mb_ts_offset = ntp->getTime(2000 /* wait 2000 ms */); - if (*mb_ts_offset > 0) - *mb_ts_offset = *mb_ts_offset - millis() / 1000; - } + updateClock(ntp, mb_ts, mb_ts_offset); #else + #if defined(ESP32) || defined(ESP8266) || defined(PICO_RP2040) #if defined(PICO_RP2040) NTP.begin("pool.ntp.org", "time.nist.gov"); NTP.waitSet(); + + now = time(nullptr); + if (now > ESP_DEFAULT_TS) + *mb_ts_offset = now - millis() / 1000; + #else configTime(gmtOffset * 3600, 0, "pool.ntp.org", "time.nist.gov"); #endif @@ -1771,15 +1816,6 @@ namespace TimeHelper return config->internal.fb_clock_rdy; } - inline int setTimestamp(time_t ts) - { -#if defined(ESP32) || defined(ESP8266) - struct timeval tm = {ts, 0}; // sec, us - return settimeofday((const timeval *)&tm, 0); -#endif - return -1; - } - }; namespace Utils diff --git a/src/Firebase_ESP_Client.h b/src/Firebase_ESP_Client.h index 3b7f776ff..026f36336 100644 --- a/src/Firebase_ESP_Client.h +++ b/src/Firebase_ESP_Client.h @@ -1,25 +1,17 @@ #ifndef FIREBASE_CLIENT_VERSION -#define FIREBASE_CLIENT_VERSION "4.3.3" +#define FIREBASE_CLIENT_VERSION "4.3.4" #endif /** - * Google's Firebase ESP Client Main class, Firebase_ESP_Client.h v4.3.3 + * Google's Firebase ESP Client Main class, Firebase_ESP_Client.h v4.3.4 * * This library supports Espressif ESP8266 and ESP32 MCUs and Raspberry Pi RP2040 Pico MCUs. * - * Created January 19, 2023 + * Created January 22, 2023 * * Updates: - * - Fix Firestore incomplete chunked response issue. - * - Fix chunked response handling issue for authentications. - * - Fix FCM HTTPv1 invalid message issue. - * - Fix Storage file openning locked issue. - * - Fix NTP client issue. - * - Fix Firebase.ready returns true when network disconnected. - * - Fix wdt reset in ESP8266 core v3.1.1 as delay(0) replaced by esp suspend. - * - Improve network (WiFi) resume task. - * - Add support non-ESP device WiFi resume. - * - Add support SDFS (ESP8266SdFat) filesystem for RP2040/Pico. + * - Fix NTP issue and update. + * - Fix netwok management task issue. * * * This work is a part of Firebase ESP Client library diff --git a/src/MB_NTP.h b/src/MB_NTP.h index 77af80405..a6cd9047c 100644 --- a/src/MB_NTP.h +++ b/src/MB_NTP.h @@ -1,5 +1,5 @@ /** - * Mobizt's UDP NTP Time Client, version 1.0.2 + * Mobizt's UDP NTP Time Client, version 1.0.3 * * The MIT License (MIT) * Copyright (c) 2023 K. Suwatchai (Mobizt) @@ -50,7 +50,6 @@ class MB_NTP this->host = host; this->port = port; this->timeZoneOffset = timeZoneOffset; - return this->begin(); } @@ -58,7 +57,7 @@ class MB_NTP { if (!this->udp || this->host.length() == 0 || this->port == 0) return false; - + if (!udpStarted) udpStarted = udp->begin(intPort) > 0; @@ -67,18 +66,23 @@ class MB_NTP uint32_t getTime(uint16_t waitMillisec = 0) { + if (ts == 0) + { + if (!udp) + return 0; - if (getResponse()) - return ts; + if (getResponse()) + return ts; - if (!sendRequest()) - return 0; + if (!sendRequest()) + return 0; - if (waitMillisec > 0) - delay(waitMillisec); + if (waitMillisec > 0) + delay(waitMillisec); - if (!getResponse()) - return 0; + if (!getResponse()) + return 0; + } return ts; } @@ -98,7 +102,7 @@ class MB_NTP bool sendRequest() { - if (!udpStarted) + if (!udpStarted || !udp) return false; if (lastRequestMs == 0 || millis() - lastRequestMs > timeout) @@ -136,6 +140,9 @@ class MB_NTP bool getResponse() { + if (!udp) + return false; + if (!udpStarted) { // We call begin again if network may not ready (e.g., WiFi) diff --git a/src/signer/Signer.cpp b/src/signer/Signer.cpp index 554aebebb..a36fe4d0c 100644 --- a/src/signer/Signer.cpp +++ b/src/signer/Signer.cpp @@ -283,33 +283,7 @@ time_t Firebase_Signer::getTime() bool Firebase_Signer::setTime(time_t ts) { - -#if !defined(FB_ENABLE_EXTERNAL_CLIENT) && (defined(ESP8266) || defined(ESP32) || defined(PICO_RP2040)) - - if (TimeHelper::setTimestamp(ts) == 0) - { - this->ts = time(nullptr); - *mb_ts = this->ts; - return true; - } - else - { - this->ts = time(nullptr); - *mb_ts = this->ts; - } - -#else - - if (ts > ESP_DEFAULT_TS) - { - *mb_ts_offset = ts - millis() / 1000; - this->ts = ts; - *mb_ts = this->ts; - } - -#endif - - return false; + return TimeHelper::setTime(ts, mb_ts, mb_ts_offset); } bool Firebase_Signer::isExpired() @@ -585,12 +559,12 @@ void Firebase_Signer::freeJson() resultPtr = nullptr; } -bool Firebase_Signer::checkUDP(UDP *udp, bool &ret, bool &_token_processing_task_enable) +bool Firebase_Signer::checkUDP(UDP *udp, bool &ret, bool &_token_processing_task_enable, float gmtOffset) { #if defined(FB_ENABLE_EXTERNAL_CLIENT) if (udp) - ntpClient.begin(udp, "pool.ntp.org" /* NTP host */, 123 /* NTP port */, gmtOffset /* timezone offset in seconds */); + ntpClient.begin(udp, "pool.ntp.org" /* NTP host */, 123 /* NTP port */, gmtOffset * 3600 /* timezone offset in seconds */); else { config->signer.tokens.error.message.clear(); @@ -633,7 +607,7 @@ void Firebase_Signer::tokenProcessingTask() while (!ret && config->signer.tokens.status != token_status_ready) { - Utils::idle(); + Utils::idle(); // check time if clock synching once set in the JWT token generating process (during beginning step) // or valid time required for SSL handshake in ESP8266 if (!config->internal.fb_clock_rdy && (config->internal.fb_clock_synched || sslValidTime)) @@ -657,7 +631,7 @@ void Firebase_Signer::tokenProcessingTask() // check or set time again - if (!checkUDP(udp, ret, _token_processing_task_enable)) + if (!checkUDP(udp, ret, _token_processing_task_enable, config->time_zone)) continue; TimeHelper::syncClock(&ntpClient, mb_ts, mb_ts_offset, config->time_zone, config); @@ -695,7 +669,7 @@ void Firebase_Signer::tokenProcessingTask() config->internal.fb_last_jwt_begin_step_millis == 0)) { // time must be set first - if (!checkUDP(udp, ret, _token_processing_task_enable)) + if (!checkUDP(udp, ret, _token_processing_task_enable, config->time_zone)) continue; TimeHelper::syncClock(&ntpClient, mb_ts, mb_ts_offset, config->time_zone, config); @@ -973,7 +947,7 @@ bool Firebase_Signer::handleTokenResponse(int &httpCode) while (tcpClient->connected() && tcpClient->available() == 0) { - Utils::idle(); + Utils::idle(); if (!reconnect(tcpClient, nullptr, tcpHandler.dataTime)) return false; } @@ -986,7 +960,7 @@ bool Firebase_Signer::handleTokenResponse(int &httpCode) while (tcpHandler.available() || !complete) { - Utils::idle(); + Utils::idle(); if (!reconnect(tcpClient, nullptr, tcpHandler.dataTime)) return false; @@ -1803,6 +1777,11 @@ void Firebase_Signer::resumeWiFi(FB_TCP_CLIENT *client, bool &net_once_connected bool Firebase_Signer::reconnect() { + if (networkChecking) + return networkStatus; + + networkChecking = true; + bool noClient = tcpClient == nullptr; if (noClient) newClient(&tcpClient); @@ -1812,6 +1791,8 @@ bool Firebase_Signer::reconnect() if (noClient) freeClient(&tcpClient); + networkChecking = false; + return networkStatus; } diff --git a/src/signer/Signer.h b/src/signer/Signer.h index 91d09fad4..ef6200c62 100644 --- a/src/signer/Signer.h +++ b/src/signer/Signer.h @@ -98,6 +98,7 @@ class Firebase_Signer uint16_t wifi_reconnect_tmo = MIN_WIFI_RECONNECT_TIMEOUT; volatile bool networkStatus = false; + bool networkChecking = false; /* intitialize the class */ void begin(FirebaseConfig *config, FirebaseAuth *auth, MB_FS *mbfs, uint32_t *mb_ts, uint32_t *mb_ts_offset); @@ -149,7 +150,7 @@ class Firebase_Signer bool handleTokenResponse(int &httpCode); /* process the tokens (generation, signing, request and refresh) */ void tokenProcessingTask(); - bool checkUDP(UDP *udp, bool &ret, bool &_token_processing_task_enable); + bool checkUDP(UDP *udp, bool &ret, bool &_token_processing_task_enable, float gmtOffset); /* encode and sign the JWT token */ bool createJWT(); /* verifying the user with email/passwod to get id token */