Skip to content

Commit 764af2e

Browse files
committed
Update examples and documentation
1 parent 23f3de7 commit 764af2e

File tree

7 files changed

+827
-400
lines changed

7 files changed

+827
-400
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
[![GitHub Sponsors](https://img.shields.io/github/sponsors/mobizt?logo=github)](https://github.com/sponsors/mobizt)
88

9-
Revision `2025-01-22T03:55:52Z`
9+
Revision `2025-01-23T06:30:53Z`
1010

1111
## Table of Contents
1212

@@ -361,6 +361,8 @@ For the concept and basic usage understanding, you should read this documentatio
361361
> [!IMPORTANT]
362362
> For new `Firebase` users, please read the [Project Preparation and Setup](#project-preparation-and-setup) section.
363363
364+
The [beare minimun examples](https://github.com/mobizt/FirebaseClient/blob/main/examples/BareMinimum/) provides the minimum code that requires by this library.
365+
364366
- ### Authentication
365367

366368
The authentication classes provide the authentication data for authentication and authorization using service account, sign-in credentials and auth tokens.
@@ -378,7 +380,7 @@ The authorization token will be refreshed or re-created automatically as long as
378380
>
379381
> Anyway, library also provides the option for less or non-secure usage which no authorization tokens are involved i.e. using database secret (`LegacyToken`) for Realtime database and using no authorization token (`NoAuth`) if the security rules are allowed (see the [Project Preparation and Setup](#project-preparation-and-setup) section).
380382
>
381-
> You can get started using this library with these [simple Realtime database examples](https://github.com/mobizt/FirebaseClient/blob/main/examples/RealtimeDatabase/Simple) which using database secret and no token, which are similar to the other legacy Firebase library usage.
383+
> You can get started using this library with these [beare minimun examples](https://github.com/mobizt/FirebaseClient/blob/main/examples/BareMinimum/) or these [simple Realtime database examples](https://github.com/mobizt/FirebaseClient/blob/main/examples/RealtimeDatabase/Simple) which using database secret and no token, which are similar to the other legacy Firebase library usage.
382384
>
383385
> For secure and more elaborate usages, you have to read the documentation thouroughly and follow the library provided examples to get familiar with the library usage.
384386

examples/BareMinimum/Async/Callback/AllServices/AllServices.ino

Lines changed: 139 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,171 @@
11
/**
22
* ABOUT:
3+
*
34
* The beare minimum code example for all Firebase services in async mode with callback function.
5+
*
6+
* The steps which are generally required and explained below.
7+
*
8+
* Step 1. Include the network, SSL client and Firebase libraries.
9+
* ===============================================================
10+
*
11+
* Step 2. Define the user functions that requred for the library usage.
12+
* =====================================================================
13+
*
14+
* Step 3. Define the network config (identifier) class.
15+
* =====================================================
16+
* Why this is existed and Is it used for?
17+
*
18+
* This library supports many types of network interfaces.
19+
* Then we have to know which type of network is currently inused and how to check the connection status
20+
* and how to re-connect the network.
21+
*
22+
* This reduces the user code to maintain the network connection and management and also provides
23+
* the networks switching or bridge usage.
24+
*
25+
* Step 4. Define the authentication config (identifier) class.
26+
* ============================================================
27+
* In the Firebase/Google Cloud services REST APIs, the auth tokens are used for authentication/authorization.
28+
*
29+
* The auth token is a short-lived token that will be expired in 60 minutes and need to be refreshed or re-created when it expired.
30+
*
31+
* There can be some special use case that some services provided the non-authentication usages e.g. using database secret
32+
* in Realtime Database, setting the security rules in Realtime Database, Firestore and Firebase Storage to allow public read/write access.
33+
*
34+
* The UserAuth (user authentication with email/password) is the basic authentication for Realtime Database,
35+
* Firebase Storage and Firestore services except for some Firestore services that involved with the Google Cloud services.
36+
*
37+
* It stores the email, password and API keys for authentication process.
38+
*
39+
* In Google Cloud services e.g. Cloud Storage and Cloud Functions, the higest authentication level is required and
40+
* the ServiceAuth class (OAuth2.0 authen) and AccessToken class will be use for this case.
41+
*
42+
* While the CustomAuth provides the same authentication level as user authentication unless it allows the custom UID, scopes and claims.
43+
*
44+
* The internal process of some authentication types e.g. ServiceAuth and CustomAuth, requires the signed JWT token generation process.
45+
* Because of it uses large memory and high cpu usage while signing the JWT token, this process requires another class to work
46+
* called JWT processor which defined as a static object for global usage to use Heap instead of stack memory.
47+
*
48+
* As the valid timestamp is required in JWT token signing process, the time status callback function is required
49+
* and assigned to the ServiceAuth and CustomAuth classes constructors.
50+
*
51+
* Step 5. Define the authentication handler class.
52+
* ================================================
53+
* The FirebaseApp actually works as authentication handler.
54+
* It also maintains the authentication or re-authentication when you place the FirebaseApp::loop() inside the main loop.
55+
*
56+
* Step 6. Define the SSL client.
57+
* ==============================
58+
* It handles server connection and data transfer.
59+
*
60+
* In this beare minimum examples we use only one SSL client for all process.
61+
* In some use cases e.g. Realtime Database Stream connection, you may have to define the SSL client for it separately.
62+
*
63+
* Step 7. Define the Async Client.
64+
* ================================
65+
* This is the class that is used with the functions where the server data transfer is involved.
66+
* It stores all sync/async taks in its queue.
67+
*
68+
* It requires the SSL client and network config (identifier) data for its class constructor for
69+
* server connection and data transfer.
70+
*
71+
* Step 8. Define the class that provides the Firebase/Google Cloud services.
72+
* ==========================================================================
73+
* The Firebase/Google Cloud services classes provide the member functions that works with AsyncClient.
74+
*
75+
* Step 9. Define the AsyncResult class
76+
* ====================================
77+
* This keeps the processing result when it assigned to any sync/async w/o callback functions.
78+
*
79+
* Step 10. Start the authenticate process.
80+
* ========================================
81+
* In this step, it actually adds the authentication task to the AsyncClient queue which will be processed later.
82+
* The result/status will send to the callback function in case of async with callback usage or stores in the AsyncResult object
83+
* in case asynce without callback and sync usages.
84+
*
85+
* This allows us to use different authentications for each Firebase/Google Cloud services with different
86+
* FirebaseApp (authentication handler).
87+
*
88+
* Please avoid placing your code that uses large memory and cpu time inside the callback function to prevent the stack overflow and
89+
* nested callback calls.
90+
*
91+
* Step 11. Bind the FirebaseApp (authentication handler) with your Firebase/Google Cloud services classes.
92+
* ========================================================================================================
93+
* This allows us to use different authentications for each Firebase/Google Cloud services.
94+
*
95+
* It is easy to bind/unbind/chanhe the authentication for authentication for different Firebase/Google Cloud services APIs.
96+
*
97+
* Step 12. Set the Realtime Database URL (for Realtime Database only)
98+
* ===================================================================
99+
*
100+
* Step 13. Maintain the authentication (async) task in the loop.
101+
* ==============================================================
102+
* This is required for authentication/re-authentication process.
103+
*
104+
* When the UserAuth and CustomAuth classes are used, the JWT.loop() will be required to run in the loop().
105+
*
106+
* Step 14. Maintain the Firebase/Google Cloud services async tasks in the loop.
107+
* =============================================================================
108+
* This depends on how the AsyncClient class was used.
109+
*
110+
* If only one AsyncClient object was used in all tasks i.e.authentication and
111+
* Firbase/Google Cloud services tasks, then these tasks stored in
112+
* only one AsyncClient's queue then the Step 13 is enough and Step 14 is not necessary.
113+
*
114+
* Step 15. Checking the authentication status before use.
115+
* =======================================================
116+
* Before calling the Firebase/Google Cloud services functions, the FirebaseApp::ready() of authentication handler that bined to it
117+
* should return true.
118+
*
119+
* Step 16. Process the sync/async w/o callback results in the end of the loop.
120+
* ============================================================================
121+
* This requires only when using library in sync/async w/o callback modes to process the information in its AsyncResult.
4122
*/
5123

6-
// 1. Include the network, SSL client and Firebase libraries.
7-
// ==========================================================
124+
// Step 1
8125
#include <Arduino.h>
9126
#include <WiFi.h>
10127
#include <WiFiClientSecure.h>
11128
#include <FirebaseClient.h>
12129

13-
// 2. Define the function prototypes of functions we will use.
14-
// ===========================================================
130+
// Step 2
15131
void timeStatusCB(uint32_t &ts);
16132
void asyncCB(AsyncResult &aResult);
17133
void printResult(AsyncResult &aResult);
18134
void getMsg(Messages::Message &msg);
19135

20-
// 3. Define the network config (identifier) class.
21-
// ================================================
22-
// The DefaultNetwork class object will provide the WiFi network identifier for ESP32/ESP8266 and
23-
// any WiFi capable devices.
24-
// Why we have to define this? It is because this library supports many types of network interfaces.
25-
// The library have to know which type of network you are using and used for connecting status checking and
26-
// performs network re-connection if neccessary.
136+
// Step 3
27137
DefaultNetwork network;
28138

29-
// 4. Define the authentication config (identifier) class.
30-
// =======================================================
31-
// In this case the ServiceAuth class (OAuth2.0 authen) can be used for all services
32-
// especially Cloud Storage and Cloud Functions required this authentication type.
33-
// The timeStatusCB is the callback function to set the library timestamp for internal process.
139+
// Step 4
34140
ServiceAuth sa_auth(timeStatusCB, "CLIENT_EMAIL", "PROJECT_ID", "PRIVATE_KEY", 3000);
35141

36-
// 5. Define the authentication handler class.
37-
// ===========================================
38-
// It handles and maintains (re-authenticate in case auth token was expired in 60 min)
39-
// the Firebase authentication process for you.
40-
// Actually you can define different FirebaseApps for each Firebase/Google Cloud services.
142+
// Step 5
41143
FirebaseApp app;
42144

43-
// 6. Define the SSL client.
44-
// =========================
45-
// In this case we use only one SSL client for all process.
145+
// Step 6
46146
WiFiClientSecure ssl_client;
47147

48-
// 7. Define the Async Client.
49-
// ===========================
50-
// We have to use it for all processes.
51-
// The getNetwork(network) in Step 3 and SSL client in Step 6 are required for Async Client
52-
// for server connection and data transfer.
148+
// Step 7
53149
using AsyncClient = AsyncClientClass;
54150
AsyncClient aClient(ssl_client, getNetwork(network));
55151

56-
// 8. Define the class that provides the Firebase service API.
57-
// ===========================================================
152+
// Step 8
58153
RealtimeDatabase Database;
59154
Messaging messaging;
60155
Firestore::Documents Docs;
61156
Storage storage;
62157
CloudStorage cstorage;
63158
CloudFunctions cfunctions;
64159

160+
// Step 9 (not used in this async with callback usage)
161+
// AsyncResult myResult;
162+
65163
bool onetimeTest = false;
66164

67165
void setup()
68166
{
69167
Serial.begin(115200);
70168

71-
// 9. Setup network and connect
72-
// ============================
73169
WiFi.begin("WIFI_AP", "WIFI_PASSWORD");
74170

75171
Serial.print("Connecting to Wi-Fi");
@@ -86,55 +182,36 @@ void setup()
86182
// Skip certificate verification
87183
ssl_client.setInsecure();
88184

89-
// 10. Start authenticate process.
90-
// ===============================
91-
// It actually adds the authentication task to the AsyncClient queue which will be processed later.
92-
// The result/status will send to the callback function "asyncCB".
185+
// Step 10
93186
initializeApp(aClient, app, getAuth(sa_auth), asyncCB, "authTask");
94187

95-
// 11. Transfer or bind the authentication credentials
96-
// ====================================================
97-
// The auth credentials from FirebaseApp will be applied to the Firebase/Google Cloud services classes
98-
// that defined in Step 8.
188+
// Step 11
99189
app.getApp<RealtimeDatabase>(Database);
100190
app.getApp<Messaging>(messaging);
101191
app.getApp<Firestore::Documents>(Docs);
102192
app.getApp<Storage>(storage);
103193
app.getApp<CloudStorage>(cstorage);
104194
app.getApp<CloudFunctions>(cfunctions);
105195

106-
// 12. Set your database URL (requires only for Realtime Database)
107-
// ===============================================================
196+
// Step 12
108197
Database.url("DATABASE_URL");
109198
}
110199

111200
void loop()
112201
{
113-
// 13. Calling the JWT token processor in the loop
114-
// ===============================================
115-
// This handles the internal processes (JWT token generation) for ServiceAuth
116-
// and CustomAuth authentications.
202+
// Step 13
117203
JWT.loop(app.getAuth());
118-
119-
// 14. Maintain the authentication (async) task in the loop
120-
// ========================================================
121-
// This required for authentication/re-authentication.
122204
app.loop();
123205

124-
// 15. Maintain the Firebase service async tasks in the loop.
125-
// ==========================================================
126-
// This is not neccessary if the same AsyncClient or aClient provided for
127-
// all authentication processes and Firebase services functions, calling app.loop()
128-
// is enough.
206+
// Step 14
129207
Database.loop();
130208
messaging.loop();
131209
Docs.loop();
132210
storage.loop();
133211
cstorage.loop();
134212
cfunctions.loop();
135213

136-
// 16. Checking the authentication status before calling Firebase services API.
137-
// ============================================================================
214+
// Step 15
138215
if (app.ready() && !onetimeTest)
139216
{
140217
onetimeTest = true;
@@ -163,15 +240,16 @@ void loop()
163240
// Cloud Functions call function.
164241
cfunctions.call(aClient, GoogleCloudFunctions::Parent("PROJECT_ID", "PROJECT_LOCATION"), "helloWorld", "test", asyncCB, "Functions_CallTask");
165242
}
243+
244+
// Step 16 (not used in this async with callback usage)
245+
// printResult(myResult);
166246
}
167247

168-
// 17. Defined the auxiliary function required to get the timestamp for internal JWT token signing process.
169-
// ========================================================================================================.
170248
void timeStatusCB(uint32_t &ts)
171249
{
250+
// The valid timestamp is needed for signed JWT token process when ServiceAuth and CustomAuth classes are used.
172251
if (time(nullptr) < FIREBASE_DEFAULT_TS)
173252
{
174-
175253
configTime(3 * 3600, 0, "pool.ntp.org");
176254
while (time(nullptr) < FIREBASE_DEFAULT_TS)
177255
{
@@ -181,14 +259,8 @@ void timeStatusCB(uint32_t &ts)
181259
ts = time(nullptr);
182260
}
183261

184-
// 18. The callback function that will be called when the information/error/data
185-
// from the auth and Firebase processes are available.
186-
// =============================================================================
187262
void asyncCB(AsyncResult &aResult) { printResult(aResult); }
188263

189-
// 19. Optional for debugging.
190-
// ===========================
191-
// The auxiliary function that we will print all information that obtained from the processes.
192264
void printResult(AsyncResult &aResult)
193265
{
194266
if (aResult.isEvent())
@@ -204,8 +276,6 @@ void printResult(AsyncResult &aResult)
204276
Firebase.printf("task: %s, payload: %s\n", aResult.uid().c_str(), aResult.c_str());
205277
}
206278

207-
// 20 The auxiliary function to create the message to send.
208-
// ========================================================
209279
void getMsg(Messages::Message &msg)
210280
{
211281
msg.topic("test");

0 commit comments

Comments
 (0)