diff --git a/README.md b/README.md index 45c59f47..8ed88b67 100644 --- a/README.md +++ b/README.md @@ -133,7 +133,7 @@ - [Optional Options](#optional-options) -[11. Frequently Asked Questions](#frequently-asked-questions) +[11. Frequently Asked Questions](/FAQ.md) [12. License](#license) @@ -174,6 +174,9 @@ When this library was used together with my other library e.g. [ESP-Mail-Client] You have to remove the folder `src/client/SSLClient` in the subsequent included library. For example if `ESP_Mail_Client.h` was included after `FirebaseClient.h`, the folder [`src/client/SSLClient`](https://github.com/mobizt/ESP-Mail-Client/tree/master/src/client/SSLClient) in the `ESP-Mail-Client` library installation folder should be removed. +The useful of using `ESP_SSLClient` library is it uses `PSRAM` by default, you can use it in ESP32 and ESP8266 modules that have `PSRAM` or connected to external `PSRAM`. + +For using `PSRAM`, see [Memory Options for ESP8266](#memory-options-for-esp8266) section. ## Features @@ -529,7 +532,13 @@ In Raspberry Pi Pico W, its `WiFiClientSecure` memory used for the transmit and In ESP32 device, its `WiFiClientSecure` memory usage cannot be adjusted, it requires at least 50 k per connection and only three `WiFiClientSecure`(s) can be defined. -Alternatively, for ESP32 device, you can use `ESP_SSLClient` that was included in this library. It works in the same way as ESP8266's `WiFiClientSecure` and the memory used for the transmit and receive buffers are adjustable (512 to 16384). This is the [example](/examples/App/NetworkInterfaces/EthernetNetwork/EthernetNetwork.ino) for how to use `ESP_SSLClient` with this library. +Alternatively, for ESP32 device, you can use `ESP_SSLClient` that was included in this library. It works in the same way as ESP8266's `WiFiClientSecure` and the memory used for the transmit and receive buffers are adjustable (512 to 16384). This is the [StreamCon curentcy example](/examples/RealtimeDatabase/Async/StreamConcurentcy/StreamConcurentcy.ino) for how to use `ESP_SSLClient` with this library. + +The useful of using `ESP_SSLClient` is it uses `PSRAM` by default, you can use it in ESP32 and ESP8266 modules that have `PSRAM` or connected to external `PSRAM`. + +In case of ESP8266 that connected to external `PSRAM`, you have enough RAM for running many tasks concurrency, and you can run [Stream Concurentcy example](/examples/RealtimeDatabase/Async/StreamConcurentcy/StreamConcurentcy.ino) without memory problem. + +For how to use `PSRAM` in ESP32 and ESP8266 devices, see [Memory Options](#memory-options) section. - ### Async Client diff --git a/examples/App/NetworkInterfaces/EthernetNetwork/EthernetNetwork.ino b/examples/App/NetworkInterfaces/EthernetNetwork/EthernetNetwork.ino index fafa780b..f668a807 100644 --- a/examples/App/NetworkInterfaces/EthernetNetwork/EthernetNetwork.ino +++ b/examples/App/NetworkInterfaces/EthernetNetwork/EthernetNetwork.ino @@ -13,7 +13,7 @@ * * , , and - The static IP, subnet, default gateway and dns server IPs. * - The boolean option to force use static ip only (not use DHCP) - * + * * The complete usage guidelines, please visit https://github.com/mobizt/FirebaseClient */ @@ -58,6 +58,8 @@ FirebaseApp app; // This is a library internal SSL client. // You can use any SSL Client that works with Ethernet library. +// The ESP_SSLClient uses PSRAM by default (if it is available), for PSRAM usage, see https://github.com/mobizt/FirebaseClient#memory-options +// For ESP_SSLClient documentation, see https://github.com/mobizt/ESP_SSLClient ESP_SSLClient ssl_client; // In case the keyword AsyncClient using in this example was ambigous and used by other library, you can change diff --git a/examples/App/NetworkInterfaces/GSMNetwork/GSMNetwork.ino b/examples/App/NetworkInterfaces/GSMNetwork/GSMNetwork.ino index e91dd6c6..3ac9967a 100644 --- a/examples/App/NetworkInterfaces/GSMNetwork/GSMNetwork.ino +++ b/examples/App/NetworkInterfaces/GSMNetwork/GSMNetwork.ino @@ -8,7 +8,7 @@ * - The GPRS APN (Access Point Name). * - The GPRS user. * - The GPRS password. - * + * * The complete usage guidelines, please visit https://github.com/mobizt/FirebaseClient * */ @@ -80,6 +80,8 @@ TinyGsmClient gsm_client(modem); // This is a library internal SSL client. // You can use any SSL Client that works with GSM library. +// The ESP_SSLClient uses PSRAM by default (if it is available), for PSRAM usage, see https://github.com/mobizt/FirebaseClient#memory-options +// For ESP_SSLClient documentation, see https://github.com/mobizt/ESP_SSLClient ESP_SSLClient ssl_client; GSMNetwork gsm_network(&modem, GSM_PIN, apn, gprsUser, gprsPass); diff --git a/examples/RealtimeDatabase/Async/Stream/Stream.ino b/examples/RealtimeDatabase/Async/Stream/Stream.ino index 7c9a8c96..db7baafd 100644 --- a/examples/RealtimeDatabase/Async/Stream/Stream.ino +++ b/examples/RealtimeDatabase/Async/Stream/Stream.ino @@ -116,6 +116,7 @@ void setup() app.setCallback(asyncCB); + // The async client used for auth task should not use for stream task initializeApp(aClient2, app, getAuth(user_auth)); // Waits for app to be authenticated. diff --git a/examples/RealtimeDatabase/Async/StreamConcurentcy/StreamConcurentcy.ino b/examples/RealtimeDatabase/Async/StreamConcurentcy/StreamConcurentcy.ino new file mode 100644 index 00000000..c6485357 --- /dev/null +++ b/examples/RealtimeDatabase/Async/StreamConcurentcy/StreamConcurentcy.ino @@ -0,0 +1,215 @@ +/** + * SYNTAX: + * + * RealtimeDatabase::get(, , , ); + * RealtimeDatabase::get(, , , , ); + * + * RealtimeDatabase::get(, , , ); + * RealtimeDatabase::get(, , , , ); + * + * - The async client. + * - The node path to get/watch the value. + * - The database options (DatabaseOptions). + * - The async result (AsyncResult). + * - The async result callback (AsyncResultCallback). + * - The user specified UID of async result (optional). + * - The Server-sent events (HTTP Streaming) mode. + * + * The complete usage guidelines, please visit https://github.com/mobizt/FirebaseClient + */ + +#include +#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W) +#include +#elif defined(ESP8266) +#include +#elif __has_include() +#include +#elif __has_include() +#include +#elif __has_include() +#include +#endif + +#include + +#define WIFI_SSID "WIFI_AP" +#define WIFI_PASSWORD "WIFI_PASSWORD" + +// The API key can be obtained from Firebase console > Project Overview > Project settings. +#define API_KEY "Web_API_KEY" + +// User Email and password that already registerd or added in your project. +#define USER_EMAIL "USER_EMAIL" +#define USER_PASSWORD "USER_PASSWORD" +#define DATABASE_URL "URL" + +void asyncCB(AsyncResult &aResult); + +void printResult(AsyncResult &aResult); + +DefaultNetwork network; // initilize with boolean parameter to enable/disable network reconnection + +UserAuth user_auth(API_KEY, USER_EMAIL, USER_PASSWORD); + +FirebaseApp app; + +WiFiClient basic_client1, basic_client2, basic_client3; + +// The ESP_SSLClient uses PSRAM by default (if it is available), for PSRAM usage, see https://github.com/mobizt/FirebaseClient#memory-options +// For ESP_SSLClient documentation, see https://github.com/mobizt/ESP_SSLClient +ESP_SSLClient ssl_client1, ssl_client2, ssl_client3; + +// In case the keyword AsyncClient using in this example was ambigous and used by other library, you can change +// it with other name with keyword "using" or use the class name AsyncClientClass directly. + +using AsyncClient = AsyncClientClass; + +AsyncClient aClient1(ssl_client1, getNetwork(network)); + +AsyncClient aClient2(ssl_client2, getNetwork(network)); + +AsyncClient aClient3(ssl_client3, getNetwork(network)); + +RealtimeDatabase Database; + +AsyncResult aResult_no_callback; + +unsigned long ms = 0; + +void setup() +{ + + Serial.begin(115200); + WiFi.begin(WIFI_SSID, WIFI_PASSWORD); + + Serial.print("Connecting to Wi-Fi"); + unsigned long ms = millis(); + while (WiFi.status() != WL_CONNECTED) + { + Serial.print("."); + delay(300); + } + Serial.println(); + Serial.print("Connected with IP: "); + Serial.println(WiFi.localIP()); + Serial.println(); + + Firebase.printf("Firebase Client v%s\n", FIREBASE_CLIENT_VERSION); + + Serial.println("Initializing app..."); + + ssl_client1.setClient(&basic_client1); + ssl_client2.setClient(&basic_client2); + ssl_client3.setClient(&basic_client3); + + ssl_client1.setInsecure(); + ssl_client2.setInsecure(); + ssl_client3.setInsecure(); + + ssl_client1.setBufferSizes(2048, 1024); + ssl_client2.setBufferSizes(2048, 1024); + ssl_client3.setBufferSizes(2048, 1024); + + ssl_client1.setDebugLevel(1); + ssl_client2.setDebugLevel(1); + ssl_client3.setDebugLevel(1); + + app.setCallback(asyncCB); + + // The async client used for auth task should not use for stream task + initializeApp(aClient3, app, getAuth(user_auth)); + + // Waits for app to be authenticated. + // For asynchronous operation, this blocking wait can be ignored by calling app.loop() in loop(). + ms = millis(); + while (app.isInitialized() && !app.ready() && millis() - ms < 120 * 1000) + ; + + app.getApp(Database); + + Database.url(DATABASE_URL); + + Database.get(aClient1, "/test/stream/path1", asyncCB, true /* SSE mode (HTTP Streaming) */, "streamTask1"); + + Database.get(aClient2, "/test/stream/path2", asyncCB, true /* SSE mode (HTTP Streaming) */, "streamTask2"); +} + +void loop() +{ + // This function is required for handling async operations and maintaining the authentication tasks. + app.loop(); + + // This required when different AsyncClients than used in FirebaseApp assigned to the Realtime database functions. + Database.loop(); + + if (millis() - ms > 20000 && app.ready()) + { + ms = millis(); + + JsonWriter writer; + + object_t json, obj1, obj2; + + writer.create(obj1, "ms", ms); + writer.create(obj2, "rand", random(10000, 30000)); + writer.join(json, 2, obj1, obj2); + + Database.set(aClient3, "/test/stream/path1/number", json, asyncCB, "setTask"); + + Database.set(aClient3, "/test/stream/path2/number", random(100000, 200000), asyncCB, "setTask"); + } +} + +void asyncCB(AsyncResult &aResult) +{ + printResult(aResult); +} + +void printResult(AsyncResult &aResult) +{ + if (aResult.appEvent().code() > 0) + { + Firebase.printf("Event task: %s, msg: %s, code: %d\n", aResult.uid().c_str(), aResult.appEvent().message().c_str(), aResult.appEvent().code()); + } + + if (aResult.isDebug()) + { + Firebase.printf("Debug task: %s, msg: %s\n", aResult.uid().c_str(), aResult.debug().c_str()); + } + + if (aResult.isError()) + { + Firebase.printf("Error task: %s, msg: %s, code: %d\n", aResult.uid().c_str(), aResult.error().message().c_str(), aResult.error().code()); + } + + if (aResult.available()) + { + // To get the UID (string) from async result + // aResult.uid(); + + RealtimeDatabaseResult &RTDB = aResult.to(); + if (RTDB.isStream()) + { + Serial.println("----------------------------"); + Firebase.printf("task: %s\n", aResult.uid().c_str()); + Firebase.printf("event: %s\n", RTDB.event().c_str()); + Firebase.printf("path: %s\n", RTDB.dataPath().c_str()); + Firebase.printf("data: %s\n", RTDB.to()); + Firebase.printf("type: %d\n", RTDB.type()); + + // The stream event from RealtimeDatabaseResult can be converted to the values as following. + bool v1 = RTDB.to(); + int v2 = RTDB.to(); + float v3 = RTDB.to(); + double v4 = RTDB.to(); + String v5 = RTDB.to(); + } + else + { + Serial.println("----------------------------"); + Firebase.printf("task: %s, payload: %s\n", aResult.uid().c_str(), aResult.c_str()); + } + Firebase.printf("Free Heap: %d\n", ESP.getFreeHeap()); + } +} diff --git a/examples/RealtimeDatabase/Async/StreamGSM/StreamGSM.ino b/examples/RealtimeDatabase/Async/StreamGSM/StreamGSM.ino index 23b9d9a0..697107c8 100644 --- a/examples/RealtimeDatabase/Async/StreamGSM/StreamGSM.ino +++ b/examples/RealtimeDatabase/Async/StreamGSM/StreamGSM.ino @@ -84,6 +84,8 @@ TinyGsmClient gsm_client2(modem, 1); // This is the library internal SSL clients. // You can use any SSL Client that works with Ethernet library. +// The ESP_SSLClient uses PSRAM by default (if it is available), for PSRAM usage, see https://github.com/mobizt/FirebaseClient#memory-options +// For ESP_SSLClient documentation, see https://github.com/mobizt/ESP_SSLClient ESP_SSLClient ssl_client1, ssl_client2; GSMNetwork gsm_network(&modem, GSM_PIN, apn, gprsUser, gprsPass); @@ -113,7 +115,7 @@ void setup() { ESP.getMaxAllocHeap() - Serial.begin(115200); + Serial.begin(115200); Serial.begin(115200); delay(10); @@ -184,6 +186,7 @@ void setup() app.setCallback(asyncCB); + // The async client used for auth task should not use for stream task initializeApp(aClient1, app, getAuth(user_auth)); // Waits for app to be authenticated. diff --git a/library.json b/library.json index cb6a368e..792d0466 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "FirebaseClient", - "version": "1.1.2", + "version": "1.1.3", "keywords": "communication, REST, esp32, esp8266, arduino", "description": "Async Firebase Client library for Arduino.", "repository": { diff --git a/library.properties b/library.properties index 813a4ed9..7e96ebb3 100644 --- a/library.properties +++ b/library.properties @@ -1,6 +1,6 @@ name=FirebaseClient -version=1.1.2 +version=1.1.3 author=Mobizt diff --git a/src/FirebaseClient.h b/src/FirebaseClient.h index 1ef9a744..61267c31 100644 --- a/src/FirebaseClient.h +++ b/src/FirebaseClient.h @@ -1,5 +1,5 @@ /** - * Created April 19, 2024 + * Created April 21, 2024 * * The MIT License (MIT) * Copyright (c) 2024 K. Suwatchai (Mobizt) @@ -30,7 +30,7 @@ #undef FIREBASE_CLIENT_VERSION #endif -#define FIREBASE_CLIENT_VERSION "1.1.2" +#define FIREBASE_CLIENT_VERSION "1.1.3" #include #include "./core/FirebaseApp.h" diff --git a/src/core/AsyncClient/AsyncClient.h b/src/core/AsyncClient/AsyncClient.h index ccbb80b9..ee03e0b0 100644 --- a/src/core/AsyncClient/AsyncClient.h +++ b/src/core/AsyncClient/AsyncClient.h @@ -1910,7 +1910,7 @@ class AsyncClientClass if (uid.length() == 0) { - sData->aResult.val[ares_ns::res_uid] = sData->auth_used ? FPSTR("auth_ms_") : FPSTR("task_ms_"); + sData->aResult.val[ares_ns::res_uid] = FPSTR("task_ms_"); sData->aResult.val[ares_ns::res_uid] += String(millis()); } else