Skip to content
This repository was archived by the owner on Mar 17, 2025. It is now read-only.

Commit cb7f768

Browse files
committed
Merge pull request #83 from ed7coyne/modem-impl2
Merging, was reviewed in other PR, issues have been addressed. Don't want to lose any more time to merging/rebasing.
2 parents 6f1ec7d + ae771d3 commit cb7f768

36 files changed

+1659
-55
lines changed

.gitmodules

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[submodule "test/googletest"]
2+
path = test/googletest
3+
url = https://github.com/google/googletest.git
4+
[submodule "test/arduino-mock"]
5+
path = test/arduino-mock
6+
url = https://github.com/ed7coyne/arduino-mock.git

src/Firebase.cpp

+57-37
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,9 @@
1515
//
1616
#include "Firebase.h"
1717

18-
// Detect whether stable version of HTTP library is installed instead of
19-
// master branch and patch in missing status and methods.
20-
#ifndef HTTP_CODE_TEMPORARY_REDIRECT
21-
#define HTTP_CODE_TEMPORARY_REDIRECT 307
22-
#define USE_ESP_ARDUINO_CORE_2_0_0
23-
#endif
18+
using std::unique_ptr;
2419

2520
namespace {
26-
const char* kFirebaseFingerprint = "7A 54 06 9B DC 7A 25 B3 86 8D 66 53 48 2C 0B 96 42 C7 B3 0A";
27-
const uint16_t kFirebasePort = 443;
28-
2921
String makeFirebaseURL(const String& path, const String& auth) {
3022
String url;
3123
if (path[0] != '/') {
@@ -41,45 +33,75 @@ String makeFirebaseURL(const String& path, const String& auth) {
4133
} // namespace
4234

4335
Firebase::Firebase(const String& host) : host_(host) {
44-
http_.setReuse(true);
36+
http_.reset(FirebaseHttpClient::create());
37+
http_->setReuseConnection(true);
4538
}
4639

4740
Firebase& Firebase::auth(const String& auth) {
4841
auth_ = auth;
4942
return *this;
5043
}
5144

45+
const String& Firebase::auth() {
46+
return auth_;
47+
}
48+
5249
FirebaseGet Firebase::get(const String& path) {
53-
return FirebaseGet(host_, auth_, path, &http_);
50+
return FirebaseGet(host_, auth_, path, http_.get());
51+
}
52+
53+
unique_ptr<FirebaseGet> Firebase::getPtr(const String& path) {
54+
return unique_ptr<FirebaseGet>(new FirebaseGet(host_, auth_, path, http_.get()));
5455
}
5556

5657
FirebaseSet Firebase::set(const String& path, const String& value) {
57-
return FirebaseSet(host_, auth_, path, value, &http_);
58+
return FirebaseSet(host_, auth_, path, value, http_.get());
59+
}
60+
61+
unique_ptr<FirebaseSet> Firebase::setPtr(const String& path,
62+
const String& value) {
63+
return unique_ptr<FirebaseSet>(
64+
new FirebaseSet(host_, auth_, path, value, http_.get()));
5865
}
5966

6067
FirebasePush Firebase::push(const String& path, const String& value) {
61-
return FirebasePush(host_, auth_, path, value, &http_);
68+
return FirebasePush(host_, auth_, path, value, http_.get());
69+
}
70+
unique_ptr<FirebasePush> Firebase::pushPtr(const String& path, const String& value) {
71+
return unique_ptr<FirebasePush>(
72+
new FirebasePush(host_, auth_, path, value, http_.get()));
6273
}
6374

6475
FirebaseRemove Firebase::remove(const String& path) {
65-
return FirebaseRemove(host_, auth_, path, &http_);
76+
return FirebaseRemove(host_, auth_, path, http_.get());
77+
}
78+
79+
unique_ptr<FirebaseRemove> Firebase::removePtr(const String& path) {
80+
return unique_ptr<FirebaseRemove>(
81+
new FirebaseRemove(host_, auth_, path, http_.get()));
6682
}
6783

6884
FirebaseStream Firebase::stream(const String& path) {
6985
// TODO: create new client dedicated to stream.
70-
return FirebaseStream(host_, auth_, path, &http_);
86+
return FirebaseStream(host_, auth_, path, http_.get());
87+
}
88+
89+
unique_ptr<FirebaseStream> Firebase::streamPtr(const String& path) {
90+
// TODO: create new client dedicated to stream.
91+
return unique_ptr<FirebaseStream>(
92+
new FirebaseStream(host_, auth_, path, http_.get()));
7193
}
7294

7395
// FirebaseCall
7496
FirebaseCall::FirebaseCall(const String& host, const String& auth,
7597
const char* method, const String& path,
76-
const String& data, HTTPClient* http) : http_(http) {
77-
String url = makeFirebaseURL(path, auth);
78-
http_->setReuse(true);
79-
http_->begin(host, kFirebasePort, url, true, kFirebaseFingerprint);
98+
const String& data, FirebaseHttpClient* http) : http_(http) {
99+
String path_with_auth = makeFirebaseURL(path, auth);
100+
http_->setReuseConnection(true);
101+
http_->begin(host, path_with_auth);
80102

81103
bool followRedirect = false;
82-
if (method == "STREAM") {
104+
if (String(method) == "STREAM") {
83105
method = "GET";
84106
http_->addHeader("Accept", "text/event-stream");
85107
followRedirect = true;
@@ -90,26 +112,24 @@ FirebaseCall::FirebaseCall(const String& host, const String& auth,
90112
http_->collectHeaders(headers, 1);
91113
}
92114

93-
int status = http_->sendRequest(method, (uint8_t*)data.c_str(), data.length());
115+
int status = http_->sendRequest(method, data);
94116

95117
// TODO: Add a max redirect check
96118
if (followRedirect) {
97-
while (status == HTTP_CODE_TEMPORARY_REDIRECT) {
119+
while (status == HttpStatus::TEMPORARY_REDIRECT) {
98120
String location = http_->header("Location");
99-
http_->setReuse(false);
121+
http_->setReuseConnection(false);
100122
http_->end();
101-
http_->setReuse(true);
102-
http_->begin(location, kFirebaseFingerprint);
103-
status = http_->sendRequest("GET", (uint8_t*)NULL, 0);
123+
http_->setReuseConnection(true);
124+
http_->begin(location);
125+
status = http_->sendRequest("GET", String());
104126
}
105127
}
106128

107129
if (status != 200) {
108-
#ifdef USE_ESP_ARDUINO_CORE_2_0_0
109-
error_ = FirebaseError(status, String(method) + " " + url + ": " + status);
110-
#else
111-
error_ = FirebaseError(status, String(method) + " " + url + ": " + HTTPClient::errorToString(status));
112-
#endif
130+
error_ = FirebaseError(status,
131+
String(method) + " " + path_with_auth +
132+
": " + http_->errorToString(status));
113133
}
114134

115135
// if not streaming.
@@ -128,14 +148,14 @@ const JsonObject& FirebaseCall::json() {
128148
// FirebaseGet
129149
FirebaseGet::FirebaseGet(const String& host, const String& auth,
130150
const String& path,
131-
HTTPClient* http)
151+
FirebaseHttpClient* http)
132152
: FirebaseCall(host, auth, "GET", path, "", http) {
133153
}
134154

135155
// FirebaseSet
136156
FirebaseSet::FirebaseSet(const String& host, const String& auth,
137157
const String& path, const String& value,
138-
HTTPClient* http)
158+
FirebaseHttpClient* http)
139159
: FirebaseCall(host, auth, "PUT", path, value, http) {
140160
if (!error()) {
141161
// TODO: parse json
@@ -145,24 +165,24 @@ FirebaseSet::FirebaseSet(const String& host, const String& auth,
145165
// FirebasePush
146166
FirebasePush::FirebasePush(const String& host, const String& auth,
147167
const String& path, const String& value,
148-
HTTPClient* http)
168+
FirebaseHttpClient* http)
149169
: FirebaseCall(host, auth, "POST", path, value, http) {
150170
if (!error()) {
151-
name_ = json()["name"].as<const char*>();
171+
//name_ = json()["name"].as<const char*>();
152172
}
153173
}
154174

155175
// FirebasePush
156176
FirebaseRemove::FirebaseRemove(const String& host, const String& auth,
157177
const String& path,
158-
HTTPClient* http)
178+
FirebaseHttpClient* http)
159179
: FirebaseCall(host, auth, "DELETE", path, "", http) {
160180
}
161181

162182
// FirebaseStream
163183
FirebaseStream::FirebaseStream(const String& host, const String& auth,
164184
const String& path,
165-
HTTPClient* http)
185+
FirebaseHttpClient* http)
166186
: FirebaseCall(host, auth, "STREAM", path, "", http) {
167187
}
168188

src/Firebase.h

+49-18
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@
2121
#define firebase_h
2222

2323
#include <Arduino.h>
24-
#include <ESP8266WiFi.h>
25-
#include <WiFiClientSecure.h>
26-
#include <ESP8266HTTPClient.h>
24+
#include <memory>
25+
#include "FirebaseHttpClient.h"
26+
// TODO(edcoyne): move this into our mock_arduino fork where we actually do the
27+
// override.
28+
#define ARDUINO_STRING_OVERRIDE
2729
#include "third-party/arduino-json-5.1.1/include/ArduinoJson.h"
2830

2931
class FirebaseGet;
@@ -35,26 +37,41 @@ class FirebaseStream;
3537
// Firebase REST API client.
3638
class Firebase {
3739
public:
38-
Firebase(const String& host);
40+
explicit Firebase(const String& host);
3941
Firebase& auth(const String& auth);
42+
virtual ~Firebase() = default;
43+
44+
Firebase(const Firebase&) = delete;
45+
46+
// Fetch auth string back.
47+
const String& auth();
4048

4149
// Fetch json encoded `value` at `path`.
4250
FirebaseGet get(const String& path);
51+
virtual std::unique_ptr<FirebaseGet> getPtr(const String& path);
4352

4453
// Set json encoded `value` at `path`.
4554
FirebaseSet set(const String& path, const String& json);
55+
virtual std::unique_ptr<FirebaseSet> setPtr(const String& path, const String& json);
4656

4757
// Add new json encoded `value` to list at `path`.
4858
FirebasePush push(const String& path, const String& json);
59+
virtual std::unique_ptr<FirebasePush> pushPtr(const String& path, const String& json);
4960

5061
// Delete value at `path`.
5162
FirebaseRemove remove(const String& path);
63+
virtual std::unique_ptr<FirebaseRemove> removePtr(const String& path);
5264

5365
// Start a stream of events that affect value at `path`.
5466
FirebaseStream stream(const String& path);
67+
virtual std::unique_ptr<FirebaseStream> streamPtr(const String& path);
68+
69+
protected:
70+
// Used for testing.
71+
Firebase() {}
5572

5673
private:
57-
HTTPClient http_;
74+
std::unique_ptr<FirebaseHttpClient> http_;
5875
String host_;
5976
String auth_;
6077
};
@@ -77,20 +94,20 @@ class FirebaseCall {
7794
FirebaseCall() {}
7895
FirebaseCall(const String& host, const String& auth,
7996
const char* method, const String& path,
80-
const String& data = "",
81-
HTTPClient* http = NULL);
82-
const FirebaseError& error() const {
97+
const String& data = "",
98+
FirebaseHttpClient* http = NULL);
99+
virtual const FirebaseError& error() const {
83100
return error_;
84101
}
85102

86-
const String& response() {
103+
virtual const String& response() {
87104
return response_;
88105
}
89106

90107
const JsonObject& json();
91108

92109
protected:
93-
HTTPClient* http_;
110+
FirebaseHttpClient* http_;
94111
FirebaseError error_;
95112
String response_;
96113
DynamicJsonBuffer buffer_;
@@ -100,7 +117,7 @@ class FirebaseGet : public FirebaseCall {
100117
public:
101118
FirebaseGet() {}
102119
FirebaseGet(const String& host, const String& auth,
103-
const String& path, HTTPClient* http = NULL);
120+
const String& path, FirebaseHttpClient* http = NULL);
104121

105122
private:
106123
String json_;
@@ -110,7 +127,8 @@ class FirebaseSet: public FirebaseCall {
110127
public:
111128
FirebaseSet() {}
112129
FirebaseSet(const String& host, const String& auth,
113-
const String& path, const String& value, HTTPClient* http = NULL);
130+
const String& path, const String& value, FirebaseHttpClient* http = NULL);
131+
114132

115133
private:
116134
String json_;
@@ -120,9 +138,9 @@ class FirebasePush : public FirebaseCall {
120138
public:
121139
FirebasePush() {}
122140
FirebasePush(const String& host, const String& auth,
123-
const String& path, const String& value, HTTPClient* http = NULL);
141+
const String& path, const String& value, FirebaseHttpClient* http = NULL);
124142

125-
const String& name() const {
143+
virtual const String& name() const {
126144
return name_;
127145
}
128146

@@ -134,18 +152,18 @@ class FirebaseRemove : public FirebaseCall {
134152
public:
135153
FirebaseRemove() {}
136154
FirebaseRemove(const String& host, const String& auth,
137-
const String& path, HTTPClient* http = NULL);
155+
const String& path, FirebaseHttpClient* http = NULL);
138156
};
139157

140158

141159
class FirebaseStream : public FirebaseCall {
142160
public:
143161
FirebaseStream() {}
144162
FirebaseStream(const String& host, const String& auth,
145-
const String& path, HTTPClient* http = NULL);
163+
const String& path, FirebaseHttpClient* http = NULL);
146164

147165
// Return if there is any event available to read.
148-
bool available();
166+
virtual bool available();
149167

150168
// Event type.
151169
enum Event {
@@ -154,8 +172,21 @@ class FirebaseStream : public FirebaseCall {
154172
PATCH
155173
};
156174

175+
static inline String EventToName(Event event) {
176+
switch(event) {
177+
case UNKNOWN:
178+
return "UNKNOWN";
179+
case PUT:
180+
return "PUT";
181+
case PATCH:
182+
return "PATCH";
183+
default:
184+
return "INVALID_EVENT_" + event;
185+
}
186+
}
187+
157188
// Read next json encoded `event` from stream.
158-
Event read(String& event);
189+
virtual Event read(String& event);
159190

160191
const FirebaseError& error() const {
161192
return _error;

src/FirebaseHttpClient.h

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#ifndef FIREBASE_HTTP_CLIENT_H
2+
#define FIREBASE_HTTP_CLIENT_H
3+
4+
#include "Arduino.h"
5+
#include "Stream.h"
6+
7+
struct HttpStatus {
8+
static const int TEMPORARY_REDIRECT = 307;
9+
};
10+
11+
class FirebaseHttpClient {
12+
public:
13+
static FirebaseHttpClient* create();
14+
15+
virtual void setReuseConnection(bool reuse) = 0;
16+
virtual void begin(const String& url) = 0;
17+
virtual void begin(const String& host, const String& path) = 0;
18+
19+
virtual void end() = 0;
20+
21+
virtual void addHeader(const String& name, const String& value) = 0;
22+
virtual void collectHeaders(const char* header_keys[],
23+
const int header_key_count) = 0;
24+
virtual String header(const String& name) = 0;
25+
26+
virtual int sendRequest(const String& method, const String& data) = 0;
27+
28+
virtual String getString() = 0;
29+
30+
virtual Stream* getStreamPtr() = 0;
31+
32+
virtual String errorToString(int error_code) = 0;
33+
34+
protected:
35+
static const uint16_t kFirebasePort = 443;
36+
};
37+
38+
static const String kFirebaseFingerprint =
39+
"7A 54 06 9B DC 7A 25 B3 86 8D 66 53 48 2C 0B 96 42 C7 B3 0A";
40+
41+
#endif // FIREBASE_HTTP_CLIENT_H

0 commit comments

Comments
 (0)