Skip to content

Commit

Permalink
Add tasks concurentcy usage example
Browse files Browse the repository at this point in the history
  • Loading branch information
mobizt committed Apr 21, 2024
1 parent ebae08a commit 5bbe058
Show file tree
Hide file tree
Showing 10 changed files with 242 additions and 10 deletions.
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@

- [Optional Options](#optional-options)

[11. Frequently Asked Questions](#frequently-asked-questions)
[11. Frequently Asked Questions](/FAQ.md)

[12. License](#license)

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*
* <local_ip>, <subnet>, <gateway> and <dns_server> - The static IP, subnet, default gateway and dns server IPs.
* <optional> - The boolean option to force use static ip only (not use DHCP)
*
*
* The complete usage guidelines, please visit https://github.com/mobizt/FirebaseClient
*/

Expand Down Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion examples/App/NetworkInterfaces/GSMNetwork/GSMNetwork.ino
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* <apn> - The GPRS APN (Access Point Name).
* <user> - The GPRS user.
* <password> - The GPRS password.
*
*
* The complete usage guidelines, please visit https://github.com/mobizt/FirebaseClient
*
*/
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions examples/RealtimeDatabase/Async/Stream/Stream.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
/**
* SYNTAX:
*
* RealtimeDatabase::get(<AsyncClient>, <path>, <AsyncResult>, <SSE>);
* RealtimeDatabase::get(<AsyncClient>, <path>, <AsyncResultCallback>, <SSE>, <uid>);
*
* RealtimeDatabase::get(<AsyncClient>, <path>, <DatabaseOption>, <AsyncResult>);
* RealtimeDatabase::get(<AsyncClient>, <path>, <DatabaseOption>, <AsyncResultCallback>, <uid>);
*
* <AsyncClient> - The async client.
* <path> - The node path to get/watch the value.
* <DatabaseOption> - The database options (DatabaseOptions).
* <AsyncResult> - The async result (AsyncResult).
* <AsyncResultCallback> - The async result callback (AsyncResultCallback).
* <uid> - The user specified UID of async result (optional).
* <SSE> - The Server-sent events (HTTP Streaming) mode.
*
* The complete usage guidelines, please visit https://github.com/mobizt/FirebaseClient
*/

#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif

#include <FirebaseClient.h>

#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<RealtimeDatabase>(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<object_t>(aClient3, "/test/stream/path1/number", json, asyncCB, "setTask");

Database.set<object_t>(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<RealtimeDatabaseResult>();
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<const char *>());
Firebase.printf("type: %d\n", RTDB.type());

// The stream event from RealtimeDatabaseResult can be converted to the values as following.
bool v1 = RTDB.to<bool>();
int v2 = RTDB.to<int>();
float v3 = RTDB.to<float>();
double v4 = RTDB.to<double>();
String v5 = RTDB.to<String>();
}
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());
}
}
5 changes: 4 additions & 1 deletion examples/RealtimeDatabase/Async/StreamGSM/StreamGSM.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -113,7 +115,7 @@ void setup()
{
ESP.getMaxAllocHeap()

Serial.begin(115200);
Serial.begin(115200);
Serial.begin(115200);

delay(10);
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
@@ -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": {
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name=FirebaseClient

version=1.1.2
version=1.1.3

author=Mobizt

Expand Down
4 changes: 2 additions & 2 deletions src/FirebaseClient.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Created April 19, 2024
* Created April 21, 2024
*
* The MIT License (MIT)
* Copyright (c) 2024 K. Suwatchai (Mobizt)
Expand Down Expand Up @@ -30,7 +30,7 @@
#undef FIREBASE_CLIENT_VERSION
#endif

#define FIREBASE_CLIENT_VERSION "1.1.2"
#define FIREBASE_CLIENT_VERSION "1.1.3"

#include <Arduino.h>
#include "./core/FirebaseApp.h"
Expand Down
2 changes: 1 addition & 1 deletion src/core/AsyncClient/AsyncClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 5bbe058

Please sign in to comment.