-
-
Notifications
You must be signed in to change notification settings - Fork 26
Expand file tree
/
Copy pathMyFirebase.h
More file actions
263 lines (224 loc) · 10.4 KB
/
MyFirebase.h
File metadata and controls
263 lines (224 loc) · 10.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
#ifndef MY_FIREBASE_H
#define MY_FIREBASE_H
#include <FirebaseClient.h>
/**
* The simple, reliable and efficient Firebase wrapper class example.
*
* Powered by FirebaseClient library.
*/
class MyFirebase
{
public:
MyFirebase()
{
for (int i = 0; i < max_stream_client_num; i++)
stream_client[i] = nullptr;
}
void begin(Client &client, const String &databaseUrl)
{
NoAuth no_auth;
beginInternal(client, getAuth(no_auth), databaseUrl);
}
#if defined(ENABLE_USER_AUTH)
void userBegin(Client &client, const String &databaseUrl, const String &apiKey, const String &email, const String &password)
{
UserAuth user_auth(apiKey, email, password);
beginInternal(client, getAuth(user_auth), databaseUrl);
}
#endif
#if defined(ENABLE_SERVICE_AUTH)
void serviceBegin(Client &client, const String &databaseUrl, uint32_t timestamp, const String &clientEmail, const String &projectId, const String &privateKey)
{
ServiceAuth service_auth(clientEmail, projectId, privateKey, 3000);
service_auth.setTime(timestamp);
beginInternal(client, getAuth(service_auth), databaseUrl);
}
#endif
#if defined(ENABLE_CUSTOM_AUTH)
void customBegin(Client &client, const String &databaseUrl, uint32_t timestamp, const String &apiKey, const String &clientEmail, const String &projectId, const String &privateKey, const String &uid, const String &claims = "", size_t expire = FIREBASE_DEFAULT_TOKEN_TTL)
{
CustomAuth custom_auth(apiKey, clientEmail, projectId, privateKey, uid, claims, 3000);
custom_auth.setTime(timestamp);
beginInternal(client, getAuth(custom_auth), databaseUrl);
}
#endif
#if defined(ENABLE_ACCESS_TOKEN)
void accessBegin(Client &client, const String &databaseUrl, const String &token, size_t expire = FIREBASE_DEFAULT_TOKEN_TTL, const String &refresh = "", const String &client_id = "", const String &client_secret = "")
{
AccessToken access_token(token, expire, refresh, client_id, client_secret);
beginInternal(client, getAuth(access_token), databaseUrl);
}
#endif
#if defined(ENABLE_ID_TOKEN)
void idBegin(Client &client, const String &databaseUrl, const String &api_key, const String &token, size_t expire = FIREBASE_DEFAULT_TOKEN_TTL, const String &refresh = "")
{
IDToken id_token(api_key, token, expire, refresh);
beginInternal(client, getAuth(id_token), databaseUrl);
}
#endif
#if defined(ENABLE_LEGACY_TOKEN)
void legacyBegin(Client &client, const String &databaseUrl, const String &databaseSecret)
{
LegacyToken legacy_token(databaseSecret);
beginInternal(client, getAuth(legacy_token), databaseUrl);
}
#endif
bool ready()
{
if (app.isInitialized())
app.loop();
return app.isInitialized() && app.ready();
}
bool available()
{
clearData();
bool res = availableInternal(authResult);
res |= availableInternal(streamResult);
return res;
}
bool isStream() const { return is_stream; }
bool isEvent() const { return is_event; }
bool isDebug() const { return is_debug; }
bool isError() const { return is_error; }
bool isPayload() const { return is_payload; }
String taskId() const { return task_id; }
String eventString() const { return event_str; }
int eventCode() const { return event_code; }
String debugString() const { return debug_str; }
String errorString() const { return err_str; }
int errorCode() { return err_code; }
String payload() const { return payload_str; }
String StreamData() const { return stream_payload; }
String StreamDataPath() const { return stream_data_path; }
String StreamEvent() const { return stream_event; }
int StreamDataType() const { return stream_data_type; }
String getString(const String &path) { return Database.get<String>(aClient, path); }
int getInt(const String &path) { return Database.get<int>(aClient, path); }
int getBool(const String &path) { return Database.get<bool>(aClient, path); }
float getFloat(const String &path) { return Database.get<float>(aClient, path); }
int getDouble(const String &path) { return Database.get<double>(aClient, path); }
bool setString(const String &path, const String &data) { return Database.set<String>(aClient, path, data); }
bool setInt(const String &path, int data) { return Database.set<int>(aClient, path, data); }
bool setBool(const String &path, bool data) { return Database.set<bool>(aClient, path, data); }
bool setFloat(const String &path, float data, int decimalPlaces = 2) { return Database.set<number_t>(aClient, path, number_t(data, decimalPlaces)); }
bool setDouble(const String &path, double data, int decimalPlaces = 4) { return Database.set<number_t>(aClient, path, number_t(data, decimalPlaces)); }
bool setJson(const String &path, const String &json) { return Database.set<object_t>(aClient, path, object_t(json)); }
String pushString(const String &path, const String &data) { return Database.push<String>(aClient, path, data); }
String pushInt(const String &path, int data) { return Database.push<int>(aClient, path, data); }
String pushBool(const String &path, bool data) { return Database.push<bool>(aClient, path, data); }
String pushFloat(const String &path, float data, int decimalPlaces = 2) { return Database.push<number_t>(aClient, path, number_t(data, decimalPlaces)); }
String pushDouble(const String &path, double data, int decimalPlaces = 4) { return Database.push<number_t>(aClient, path, number_t(data, decimalPlaces)); }
String pushJson(const String &path, const String &json) { return Database.push<object_t>(aClient, path, object_t(json)); }
bool updateNode(const String &path, const String &json) { return Database.update<object_t>(aClient, path, object_t(json)); }
bool exists(const String &path) { return Database.existed(aClient, path); }
bool remove(const String &path) { return Database.remove(aClient, path); }
void beginStream(Client &stream_client, const String &path, const String &filter = "")
{
this->stream_client[current_stream_index] = &stream_client;
Database.setSSEFilters(filter);
// All results will store in one streamResult, the data of one Stream can be replaced by another Stream.
// To avoid this issue, use StreamCallback or define the AsyncResults for each Stream.
Database.get(streamClient[current_stream_index], path, streamResult, true);
current_stream_index++;
if (current_stream_index > max_stream_client_num - 1)
current_stream_index = 0;
}
void pause(bool enable)
{
if (enable)
app.getApp<RealtimeDatabase>(Database);
else
{
Database.resetApp();
aClient.stopAsync(true);
for (int i = 0; i < max_stream_client_num; i++)
streamClient[i].stopAsync(true);
if (client)
client->stop();
for (int i = 0; i < max_stream_client_num; i++)
{
if (stream_client[i])
stream_client[i]->stop();
}
}
}
private:
static const int max_stream_client_num = 2;
Client *client = nullptr, *stream_client[max_stream_client_num];
AsyncClientClass aClient, streamClient[max_stream_client_num];
FirebaseApp app;
RealtimeDatabase Database;
AsyncResult authResult, streamResult;
bool is_event = false, is_debug = false, is_error = false, is_payload = false, is_stream = false;
String task_id, payload_str, stream_payload, stream_event, stream_data_path, debug_str, event_str, err_str;
int event_code = 0, err_code = 0, stream_data_type = 0, current_stream_index = 0;
void beginInternal(Client &client, user_auth_data &auth, const String &databaseUrl)
{
aClient.setClient(client);
this->client = &client;
Database.url(databaseUrl);
initializeApp(aClient, app, auth, authResult);
app.getApp<RealtimeDatabase>(Database);
}
bool availableInternal(AsyncResult &res)
{
// Once AsyncResult::isXXX was called, the information should be kept in
// the temporary buffer because that information is gone
// in the next loop running.
bool event_status = res.isEvent();
if (event_status)
{
event_str = res.appEvent().message();
event_code = res.appEvent().code();
}
bool debug_status = res.isDebug();
if (debug_status)
debug_str = res.debug();
bool error_status = res.isError();
if (error_status)
{
err_str = res.error().message();
err_code = res.error().code();
}
bool payload_status = res.available();
if (payload_status)
payload_str = res.c_str();
is_event |= event_status;
is_debug |= debug_status;
is_error |= error_status;
is_payload |= payload_status;
if (payload_status)
{
RealtimeDatabaseResult &RTDB = res.to<RealtimeDatabaseResult>();
is_stream |= RTDB.isStream();
if (is_stream)
{
stream_payload = RTDB.to<const char *>();
stream_data_type = RTDB.type();
stream_data_path = RTDB.dataPath();
stream_event = RTDB.event();
}
}
if (event_status || debug_status || error_status || payload_status)
task_id = res.uid();
return is_event || is_debug || is_error || is_payload;
}
void clearData()
{
is_stream = false;
is_debug = false;
is_event = false;
is_error = false;
is_payload = false;
stream_data_type = false;
debug_str.remove(0, debug_str.length());
payload_str.remove(0, payload_str.length());
event_str.remove(0, event_str.length());
err_str.remove(0, err_str.length());
stream_payload.remove(0, stream_payload.length());
stream_event.remove(0, stream_event.length());
stream_data_path.remove(0, stream_data_path.length());
task_id.remove(0, task_id.length());
}
};
#endif