Core 2 connecting with W5500 LAN to Firebase RTDB
- 
					
					
					
					
 I have a Core 2 with W5500 LAN module. For 10 days I have been trying in vain to connect to Firebase RTDB. With WLAN I managed it 5 days ago... but that doesn't work now either! No idea why. Both WIFI and Ethernet I tried the following templates: https://github.com/mobizt/Firebase-ESP-Client Ethernet and WIFI work in simple tests. 
- 
					
					
					
					
 WIFI works now again.. Firebase.reconnectWiFi(true); must be called AFTER Firebase.begin(&config, &auth);. With me this was somehow suddenly no longer so... probably because of a copy/paste error..` so here my working WIFI code: /** - Created by K. Suwatchai (Mobizt)
- Email: k_suwatchai@hotmail.com
- Github: https://github.com/mobizt/Firebase-ESP-Client
- Copyright (c) 2022 mobizt
 */ /** This example will show how to authenticate as a user with Email and password. 
 *- You need to enable Email/Password provider.
- In Firebase console, select Authentication, select Sign-in method tab,
- under the Sign-in providers list, enable Email/Password provider.
- From this example, the user will be granted to access the specific location that matches
- the user uid.
- This example will modify the database rules to set up the security rule which need to
- guard the unauthorized access with the user Email.
 */
 #include <M5Core2.h> 
 #include <WiFi.h>
 #include <Firebase_ESP_Client.h>// Provide the token generation process info. 
 #include <addons/TokenHelper.h>// Provide the RTDB payload printing info and other helper functions. 
 #include <addons/RTDBHelper.h>/* 1. Define the WiFi credentials */ 
 #define WIFI_SSID "WIFI_SSID"
 #define WIFI_PASSWORD "WIFI_PASSWORD"/** 2. Define the API key 
 *- The API key (required) can be obtained since you created the project and set up
- the Authentication in Firebase console. Then you will get the API key from
- Firebase project Web API key in Project settings, on General tab should show the
- Web API Key.
- You may need to enable the Identity provider at https://console.cloud.google.com/customer-identity/providers
- Select your project, click at ENABLE IDENTITY PLATFORM button.
- The API key also available by click at the link APPLICATION SETUP DETAILS.
 */ 
 #define API_KEY "API_KEY"/* 3. Define the user Email and password that already registerd or added in your project */ 
 #define USER_EMAIL "USER_EMAIL"
 #define USER_PASSWORD "USER_PASSWORD"/* 4. If work with RTDB, define the RTDB URL */ 
 #define DATABASE_URL "DATABASE_URL" //<databaseName>.firebaseio.com or <databaseName>.<region>.firebasedatabase.app/** 5. Define the database secret (optional) 
 *- This database secret needed only for this example to modify the database rules
- If you edit the database rules yourself, this is not required.
 */
 #define DATABASE_SECRET "DATABASE_SECRET"
 /* 6. Define the Firebase Data object */ 
 FirebaseData fbdo;/* 7. Define the FirebaseAuth data for authentication data */ 
 FirebaseAuth auth;/* 8. Define the FirebaseConfig data for config data */ 
 FirebaseConfig config;unsigned long dataMillis = 0; 
 int count = 0;void setup() 
 {
 //M5.begin();
 Serial.begin(115200);WiFi.begin(WIFI_SSID, WIFI_PASSWORD); Serial.print("Connecting to Wi-Fi"); while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(300); } Serial.println(); Serial.print("Connected with IP: "); Serial.println(WiFi.localIP()); Serial.println(); Serial.printf("Firebase Client v%s\n\n", FIREBASE_CLIENT_VERSION); //config.signer.test_mode = true; /* Assign the api key (required) */ config.api_key = API_KEY; /* Assign the user sign in credentials */ auth.user.email = USER_EMAIL; auth.user.password = USER_PASSWORD; /* Assign the RTDB URL */ config.database_url = DATABASE_URL; /* In case the certificate data was used */ //config.cert.data = rootCACert; // Or custom set the root certificate for each FirebaseData object //fbdo.setCert(rootCACert); /* Or assign the certificate file */ /** From the test as of July 2021, GlobalSign Root CA was missing from Google server * as described above, GTS Root R1 (gsr1.pem or gsr1.der) can be used instead. * ESP32 Arduino SDK supports PEM format only even mBedTLS supports DER format too. * ESP8266 SDK supports both PEM and DER format certificates. */ //config.cert.file = "/gtsr1.pem"; //config.cert.file_storage = mem_storage_type_flash; // or mem_storage_type_sd fbdo.setResponseSize(4096); String base_path = "/UsersData/"; /* Assign the callback function for the long running token generation task */ config.token_status_callback = tokenStatusCallback; // see addons/TokenHelper.h /* Initialize the library with the Firebase authen and config */ Firebase.begin(&config, &auth); Firebase.reconnectWiFi(true); /** Now modify the database rules (if not yet modified) * * The user, <user uid> in this case will be granted to read and write * at the certain location i.e. "/UsersData/<user uid>". * * If you database rules has been modified, please comment this code out. * * The character $ is to make a wildcard variable (can be any name) represents any node key * which located at some level in the rule structure and use as reference variable * in .read, .write and .validate rules * * For this case $userId represents any <user uid> node that places under UsersData node i.e. * /UsersData/<user uid> which <user uid> is user UID. * * Please check your the database rules to see the changes after run the below code. */ String var = "$userId"; String val = "($userId === auth.uid)"; Firebase.RTDB.setReadWriteRules(&fbdo, base_path, var, val, val, DATABASE_SECRET); /** path for user data is now "/UsersData/<user uid>" * * The id token can be accessed from Firebase.getToken(). * * The refresh token can be accessed from Firebase.getRefreshToken(). */} void loop() 
 {// Firebase.ready() should be called repeatedly to handle authentication tasks. if (millis() - dataMillis > 5000 && Firebase.ready()) { dataMillis = millis(); String path = "/UsersData/"; path += auth.token.uid.c_str(); //<- user uid of current user that sign in with Emal/Password path += "/test/int"; Serial.printf("Set int... %s\n", Firebase.RTDB.setInt(&fbdo, path, count++) ? "ok" : fbdo.errorReason().c_str()); // You can use refresh token from Firebase.getRefreshToken() to sign in next time without providing Email and Password. // See SignInWithRefreshIDToken example. }} Now i will try again to connect with Ethernet W5500.. i come back later with more infos.. 
- 
					
					
					
					
 Ethernet still not working. I used the following code: /** - Created by K. Suwatchai (Mobizt)
- Email: k_suwatchai@hotmail.com
- Github: https://github.com/mobizt/Firebase-ESP-Client
- Copyright (c) 2022 mobizt
 */ /** This example shows the basic RTDB usage with external Client. - This example used ESP32 and WIZnet W5500 (Etherner) devices which built-in SSL Client will be used as the external Client.
- For other non-espressif (ESP32 and ESP8266) devices, this SSL Client library can be used
- https://github.com/OPEnSLab-OSU/SSLClient
- Don't gorget to define this in FirebaseFS.h
- #define FB_ENABLE_EXTERNAL_CLIENT
 */
 #include <WiFi.h> 
 #include <M5Core2.h>
 #include <Firebase_ESP_Client.h>
 #include "time.h"
 #include <ESP32Time.h>//ESP32Time rtc; 
 ESP32Time rtc(3600); // offset in seconds GMT+1// Provide the token generation process info. 
 #include <addons/TokenHelper.h>// Provide the RTDB payload printing info and other helper functions. 
 #include <addons/RTDBHelper.h>//https://github.com/arduino-libraries/Ethernet 
 #include <Ethernet.h>// Include built-in SSL Client which supports other network interfaces 
 #include "sslclient/esp32/MB_ESP32_SSLClient.h"// You can use MB_ESP32_SSLClient.h in your ESP32 project in the same way as normal WiFiClientSecure // For NTP time client 
 #include "MB_NTP.h"// For the following credentials, see examples/Authentications/SignInAsUser/EmailPassword/EmailPassword.ino /* 1. Define the API Key */ 
 #define API_KEY "KEY"/* 2. Define the RTDB URL */ 
 #define DATABASE_URL "URL" //<databaseName>.firebaseio.com or <databaseName>.<region>.firebasedatabase.app/* 3. Define the user Email and password that alreadey registerd or added in your project */ 
 #define USER_EMAIL "EMAIL"
 #define USER_PASSWORD "PASSWORD"/* 4. Defined the Ethernet module connection */ 
 //#define WIZNET_RESET_PIN 26 // Connect W5500 Reset pin to GPIO 26 of ESP32
 #define WIZNET_CS_PIN 26 // Connect W5500 CS pin to GPIO 5 of ESP32
 #define WIZNET_MISO_PIN 38 // Connect W5500 MISO pin to GPIO 19 of ESP32
 #define WIZNET_MOSI_PIN 23 // Connect W5500 MOSI pin to GPIO 23 of ESP32
 #define WIZNET_SCLK_PIN 18 // Connect W5500 SCLK pin to GPIO 18 of ESP32//WLAN 
 const char* ssid = "ssid";
 const char* password = "password";/* 5. Define MAC */ 
 uint8_t MAC[] = { 0x12, 0x12, 0x12, 0x12, 0x12, 0x12 };/* 6. Define IP (Optional) */ 
 IPAddress IP(192, 168, 1, 233);
 IPAddress DNS(8, 8, 8, 8);// Define Firebase Data object 
 FirebaseData fbdo;FirebaseAuth auth; 
 FirebaseConfig config;unsigned long sendDataPrevMillis = 0; int count = 0; volatile bool dataChanged = false; EthernetClient basic_client; 
 MB_ESP32_SSLClient ssl_client;// For NTP client 
 EthernetUDP udpClient;MB_NTP ntpClient(&udpClient, "ch.pool.ntp.org" /* NTP host /, 123 / NTP port /, 0 / timezone offset in seconds */); uint32_t timestamp = 0; const char* ntpServer = "ch.pool.ntp.org"; 
 const long gmtOffset_sec = 3600;
 const int daylightOffset_sec = 3600;
 int second;
 int minute;
 int hour;
 int day;
 int month;
 int year;
 struct tm timeinfo;void printLocalTime() { 
 if (!getLocalTime(&timeinfo)) {
 Serial.println("Failed to obtain time");
 M5.Lcd.print("Failed to obtain time");
 return;
 }
 second = timeinfo.tm_sec;
 minute = timeinfo.tm_min;
 hour = timeinfo.tm_hour;
 day = timeinfo.tm_mday;
 month = timeinfo.tm_mon + 1;
 year = timeinfo.tm_year + 1900;
 weekday = timeinfo.tm_wday + 1;
 rtc.setTime(second, minute, hour, day, month, year);
 }void wifiNtpSetup() { 
 M5.Lcd.setTextSize(2); //Set the font size to 2. 设置字号大小为2
 M5.Lcd.printf("\nConnecting to %s", ssid);
 WiFi.begin(
 ssid,
 password); //Connect wifi and return connection status. 连接wifi并返回连接状态
 while (WiFi.status() != WL_CONNECTED) { //If the wifi connection fails. 若wifi未连接成功
 delay(500); //delay 0.5s. 延迟0.5s
 M5.Lcd.print(".");
 }
 M5.Lcd.println("\nCONNECTED!");
 configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); //init and get the time. 初始化并设置NTP
 printLocalTime();if (timestamp == 0) { 
 timestamp = ntpClient.getTime(2000 /* wait 2000 ms */);if (timestamp > 0) { Serial.print("timestamp:"); Serial.print(timestamp); } else { Serial.println("NTP Server via Ethernet nicht erreichbar !"); }} 
 WiFi.disconnect(true); //Disconnect wifi. 断开wifi连接
 WiFi.mode(WIFI_OFF); //Set the wifi mode to off. 设置wifi模式为关闭
 delay(20);
 M5.Lcd.println("\nWIFI OFF!");
 }/* 
 void ResetEthernet()
 {
 Serial.println("Resetting WIZnet W5500 Ethernet Board... ");
 pinMode(WIZNET_RESET_PIN, OUTPUT);
 digitalWrite(WIZNET_RESET_PIN, HIGH);
 delay(200);
 digitalWrite(WIZNET_RESET_PIN, LOW);
 delay(50);
 digitalWrite(WIZNET_RESET_PIN, HIGH);
 delay(200);
 }
 */void networkConnection() { SPI.begin(WIZNET_SCLK_PIN, WIZNET_MISO_PIN, WIZNET_MOSI_PIN, -1); Ethernet.init(WIZNET_CS_PIN); 
 //Serial.begin(115200);//ResetEthernet(); Serial.println("Starting Ethernet connection..."); 
 Ethernet.begin(MAC, IP, DNS);unsigned long to = millis(); while (Ethernet.linkStatus() == LinkOFF || millis() - to < 2000) { 
 delay(100);
 }if (Ethernet.linkStatus() == LinkON) { 
 Serial.print("Connected with IP ");
 Serial.println(Ethernet.localIP());
 } else {
 Serial.println("Can't connect");
 }
 }// Define the callback function to handle server status acknowledgement 
 void networkStatusRequestCallback() {// Set the network status 
 fbdo.setNetworkStatus(Ethernet.linkStatus() == LinkON);
 }// Define the callback function to handle server connection 
 void tcpConnectionRequestCallback(const char* host, int port) {// You may need to set the system timestamp to use for 
 // auth token expiration checking.
 Firebase.setSystemTime(rtc.getLocalEpoch());Serial.print("Connecting to server via external Client... "); 
 if (!ssl_client.connect(host, port)) {
 Serial.println("Connection failed !");
 return;
 }
 Serial.println("Connection established !");
 }void setup() { M5.begin(); 
 wifiNtpSetup();
 networkConnection();Serial_Printf("Firebase Client v%s\n\n", FIREBASE_CLIENT_VERSION); /* Assign the basic Client (Ethernet) pointer to the basic Client */ 
 ssl_client.setClient(&basic_client);/* Similar to WiFiClientSecure */ 
 ssl_client.setInsecure();config.cert.file = "/gtsr1.pem"; 
 config.cert.file_storage = mem_storage_type_flash;/* Assign the api key (required) */ 
 config.api_key = API_KEY;/* Assign the user sign in credentials */ 
 auth.user.email = USER_EMAIL;
 auth.user.password = USER_PASSWORD;/* Assign the RTDB URL (required) */ 
 config.database_url = DATABASE_URL;/* Assign the callback function for the long running token generation task */ 
 config.token_status_callback = tokenStatusCallback; // see addons/TokenHelper.h/* fbdo.setExternalClient and fbdo.setExternalClientCallbacks must be called before Firebase.begin */ /* Assign the pointer to global defined external SSL Client object */ 
 fbdo.setExternalClient(&ssl_client);/* Assign the required callback functions */ 
 fbdo.setExternalClientCallbacks(tcpConnectionRequestCallback, networkConnection, networkStatusRequestCallback);Firebase.setDoubleDigits(5); Firebase.begin(&config, &auth); // Comment or pass false value when WiFi reconnection will control by your code or third party library 
 //Firebase.reconnectWiFi(true);
 }void loop() { // Firebase.ready() should be called repeatedly to handle authentication tasks. if (Firebase.ready() && (millis() - sendDataPrevMillis > 15000 || sendDataPrevMillis == 0)) { 
 sendDataPrevMillis = millis();Serial_Printf("Set bool... %s\n", Firebase.RTDB.setBool(&fbdo, F("/test/bool"), count % 2 == 0) ? "ok" : fbdo.errorReason().c_str()); count++;} 
 }Excerpt from Serial Monitor: 
 "
 Token info: type = id token (GITKit token), status = on request
 [V][ESP32_SSL_Client.cpp:402] stop_tcp_connection(): Cleaning SSL connection.
 Connecting to server via external Client... [V][ESP32_SSL_Client.cpp:173] connect_ssl(): Seeding the random number generator
 [V][ESP32_SSL_Client.cpp:185] connect_ssl(): Setting up the SSL/TLS structure...
 [I][ESP32_SSL_Client.cpp:201] connect_ssl(): WARNING: Skipping SSL Verification. INSECURE!
 [V][ESP32_SSL_Client.cpp:313] connect_ssl(): Setting hostname for TLS session...
 [V][ESP32_SSL_Client.cpp:334] connect_ssl(): Performing the SSL/TLS handshake...
 [E][ESP32_SSL_Client.cpp:61] _esp32_ssl_handle_error(): [connect_ssl():341]: (-1) UNKNOWN ERROR CODE (0001)
 [E][MB_ESP32_SSLClient.cpp:217] connect(): MB_ESP32_SSLClient Error: upgrade connection, -1
 [V][ESP32_SSL_Client.cpp:402] stop_tcp_connection(): Cleaning SSL connection.
 Connection failed !
 "This error indicates that there was an issue with the SSL/TLS handshake when trying to connect to an external server. The exact cause of this error is unknown, but it could be due to an incorrect SSL configuration, an expired/invalid certificate, or an issue with the network connection. 
 The NTP server is also not accessible via Ethernet. Therefore I connected the NTP with WLAN and synchronized timestamp with Firebase. The SSL/TLS connection still failed. I am running out of ideas.
- 
					
					
					
					
 I have downloaded again the above code for a WLAN connection. It did not work! 
 The following error message appeared:
 Token info: type = id token (GITKit token), status = on request
 Token info: type = id token (GITKit token), status = error
 Token error: code: -105, message: Client is not yet initializedAfter that i downgraded the library "Firebase Arduino Client Library for ESP8266 and ESP32" to 2.3.7 and after that i reinstalled 4.2.7 and it worked again. Why do i need to reinstall the lib to get it working? 
- 
					
					
					
					
 
- 
					
					
					
					
 Thanks to your steep pass it IT finally WORKS !!! Here are a few more stumbling blocks to be aware of: - 
#define FB_ENABLE_EXTERNAL_CLIENT must be set for Ethernet connection. For WLAN it must be deactivated. Therefore WLAN worked again after reinstalling the lib as described above. 
- 
you need to define the GPIO´s for Core 2 as following in the code 
- 
trust_anchors URL => www.google.com seems to work as Firebase is a google product 
- 
#include <M5Core2.h> is NOT necessary => if you use it with M5.begin you need to delete Serial.begin(115200) => otherwise your CPU will crash => known issue also thanks to felmue 
- 
NTP server is not working => always returns 0 => seems to work without NTP 
 Here is the working code i use: /** - Created by K. Suwatchai (Mobizt)
- Email: k_suwatchai@hotmail.com
- Github: https://github.com/mobizt/Firebase-ESP-Client
- Copyright (c) 2022 mobizt
 */ /** This example shows the basic RTDB usage with external Client. - This example used your Arduino device and WIZnet W5500 (Ethernet) device which SSLClient https://github.com/OPEnSLab-OSU/SSLClient
- will be used as the external Client.
- This SSLClient, https://github.com/OPEnSLab-OSU/SSLClient can't use in ESP8266 device due to wdt reset error.
- Don't gorget to define this in FirebaseFS.h
- #define FB_ENABLE_EXTERNAL_CLIENT
 */
 #include <Firebase_ESP_Client.h> // Provide the token generation process info. 
 #include <addons/TokenHelper.h>// Provide the RTDB payload printing info and other helper functions. 
 #include <addons/RTDBHelper.h>#include <Ethernet.h> /* 1. Install SSLClient library */ 
 // https://github.com/OPEnSLab-OSU/SSLClient
 #include <SSLClient.h>/* 2. Create Trus anchors for the server i.e. www.google.com */ 
 // https://github.com/OPEnSLab-OSU/SSLClient/blob/master/TrustAnchors.md
 // or generate using this site https://openslab-osu.github.io/bearssl-certificate-utility/
 #include "trust_anchors.h"// For NTP time client 
 #include "MB_NTP.h"// For the following credentials, see examples/Authentications/SignInAsUser/EmailPassword/EmailPassword.ino /* 3. Define the API Key */ 
 #define API_KEY "Key"/* 4. Define the RTDB URL */ 
 #define DATABASE_URL "URL" //<databaseName>.firebaseio.com or <databaseName>.<region>.firebasedatabase.app/* 5. Define the user Email and password that alreadey registerd or added in your project */ 
 #define USER_EMAIL "Email"
 #define USER_PASSWORD "password"/* 6. Defined the Ethernet module connection */ 
 #define WIZNET_RESET_PIN 19 // Connect W5500 Reset pin to GPIO 19 for Core 2
 #define WIZNET_CS_PIN 26 // Connect W5500 CS pin to GPIO 26 for Core 2
 #define WIZNET_MISO_PIN 38 // Connect W5500 MISO pin to GPIO 38 for Core 2
 #define WIZNET_MOSI_PIN 23 // Connect W5500 MOSI pin to GPIO 23 for Core 2
 #define WIZNET_SCLK_PIN 18 // Connect W5500 SCLK pin to GPIO 18 for Core 2/* 7. Define the analog GPIO pin to pull random bytes from, used in seeding the RNG for SSLClient */ 
 const int analog_pin = 27; // Core 2 => GPIO 27 (Analog pin)/* 8. Define MAC */ 
 uint8_t mac[] = { 0x12, 0x12, 0x12, 0x12, 0x12, 0x12 };/* 9. Define IP (Optional) */ 
 IPAddress ip(192, 168, 1, 50);
 IPAddress myDns(8, 8, 8, 8);// Define Firebase Data object 
 FirebaseData fbdo;FirebaseAuth auth; 
 FirebaseConfig config;unsigned long sendDataPrevMillis = 0; int count = 0; volatile bool dataChanged = false; EthernetClient basic_client; SSLClient ssl_client(basic_client, TAs, (size_t)TAs_NUM, analog_pin); // For NTP client 
 EthernetUDP udpClient;MB_NTP ntpClient(&udpClient, "pool.ntp.org" /* NTP host /, 123 / NTP port /, 0 / timezone offset in seconds */); uint32_t timestamp = 0; void ResetEthernet() { 
 Serial.println("Resetting WIZnet W5500 Ethernet Board... ");
 pinMode(WIZNET_RESET_PIN, OUTPUT);
 digitalWrite(WIZNET_RESET_PIN, HIGH);
 delay(200);
 digitalWrite(WIZNET_RESET_PIN, LOW);
 delay(50);
 digitalWrite(WIZNET_RESET_PIN, HIGH);
 delay(200);
 }void networkConnection() { Ethernet.init(WIZNET_CS_PIN); ResetEthernet(); Serial.println("Starting Ethernet connection..."); Ethernet.begin(mac); unsigned long to = millis(); while (Ethernet.linkStatus() == LinkOFF || millis() - to < 2000) { 
 delay(100);
 }if (Ethernet.linkStatus() == LinkON) { 
 Serial.print("Connected with IP ");
 Serial.println(Ethernet.localIP());
 } else {
 Serial.println("Can't connect");
 }
 }// Define the callback function to handle server status acknowledgement 
 void networkStatusRequestCallback() {
 // Set the network statusfbdo.setNetworkStatus(Ethernet.linkStatus() == LinkON); 
 }// Define the callback function to handle server connection 
 void tcpConnectionRequestCallback(const char *host, int port) {// You may need to set the system timestamp to use for 
 // auth token expiration checking.if (timestamp == 0) { 
 timestamp = ntpClient.getTime(2000 /* wait 2000 ms */);
 Serial.print("timestamp from NTP: ");
 Serial.println(timestamp);if (timestamp > 0) { Firebase.setSystemTime(timestamp); Serial.print("Firebase => setSystemTime done"); }} Serial.print("Connecting to server via external Client... "); 
 if (!ssl_client.connect(host, port)) {
 Serial.println("failed.");
 return;
 }
 Serial.println("success.");
 }void setup() { SPI.begin(WIZNET_SCLK_PIN, WIZNET_MISO_PIN, WIZNET_MOSI_PIN, -1); 
 Serial.begin(115200);networkConnection(); Serial_Printf("Firebase Client v%s\n\n", FIREBASE_CLIENT_VERSION); /* Assign the api key (required) */ 
 config.api_key = API_KEY;/* Assign the user sign in credentials */ 
 auth.user.email = USER_EMAIL;
 auth.user.password = USER_PASSWORD;/* Assign the RTDB URL (required) */ 
 config.database_url = DATABASE_URL;/* Assign the callback function for the long running token generation task */ 
 config.token_status_callback = tokenStatusCallback; // see addons/TokenHelper.h/* fbdo.setExternalClient and fbdo.setExternalClientCallbacks must be called before Firebase.begin */ /* Assign the pointer to global defined external SSL Client object */ 
 fbdo.setExternalClient(&ssl_client);/* Assign the required callback functions */ 
 fbdo.setExternalClientCallbacks(tcpConnectionRequestCallback, networkConnection, networkStatusRequestCallback);Firebase.setDoubleDigits(5); Firebase.begin(&config, &auth); 
 }void loop() { // Firebase.ready() should be called repeatedly to handle authentication tasks. if (Firebase.ready() && (millis() - sendDataPrevMillis > 15000 || sendDataPrevMillis == 0)) { 
 sendDataPrevMillis = millis();Serial_Printf("Set bool... %s\n", Firebase.RTDB.setBool(&fbdo, F("/test/bool"), count % 2 == 0) ? "ok" : fbdo.errorReason().c_str()); count++;} 
 }
- 
