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
15131void timeStatusCB (uint32_t &ts);
16132void asyncCB (AsyncResult &aResult);
17133void printResult (AsyncResult &aResult);
18134void 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
27137DefaultNetwork 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
34140ServiceAuth 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
41143FirebaseApp 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
46146WiFiClientSecure 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
53149using AsyncClient = AsyncClientClass;
54150AsyncClient aClient (ssl_client, getNetwork(network));
55151
56- // 8. Define the class that provides the Firebase service API.
57- // ===========================================================
152+ // Step 8
58153RealtimeDatabase Database;
59154Messaging messaging;
60155Firestore::Documents Docs;
61156Storage storage;
62157CloudStorage cstorage;
63158CloudFunctions cfunctions;
64159
160+ // Step 9 (not used in this async with callback usage)
161+ // AsyncResult myResult;
162+
65163bool onetimeTest = false ;
66164
67165void 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
111200void 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- // ========================================================================================================.
170248void 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- // =============================================================================
187262void 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.
192264void 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- // ========================================================
209279void getMsg (Messages::Message &msg)
210280{
211281 msg.topic (" test" );
0 commit comments