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

Commit 9ad4b70

Browse files
committed
Merge pull request #90 from ed7coyne/modem-impl3
Implement modem (attempt 3)
2 parents e1bc354 + dcadcc1 commit 9ad4b70

39 files changed

+1654
-53
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

examples/FirebasePush_ESP8266/FirebasePush_ESP8266.ino

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
// FirebasePush_ESP8266 is a sample that push a new timestamp to firebase
1818
// on each reset.
1919

20+
#include <ESP8266WiFi.h>
21+
2022
#include <Firebase.h>
2123

2224
// create firebase client.

examples/FirebaseStream_ESP8266/FirebaseStream_ESP8266.ino

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
// public Firebase and optionally display them on a OLED i2c screen.
1919

2020
#include <Firebase.h>
21+
#include <ESP8266WiFi.h>
2122
#include <Adafruit_GFX.h>
2223
#include <Adafruit_SSD1306.h>
2324
#include <ArduinoJson.h>

examples/Firebase_ESP8266_LEDs/Firebase_ESP8266_Neopixel/Firebase_ESP8266_Neopixel.ino

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
// to set pixel data using a firebase stream.
1919
#include <Firebase.h>
2020
#include <ArduinoJson.h>
21+
#include <ESP8266WiFi.h>
2122

2223
#include <Adafruit_NeoPixel.h>
2324
#include "colors_ext.h"

src/Firebase.cpp

+56-36
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,40 +33,70 @@ String makeFirebaseURL(const String& path, const String& auth) {
4133
} // namespace
4234

4335
Firebase::Firebase(const String& host, const String& auth) : host_(host), auth_(auth) {
44-
http_.setReuse(true);
36+
http_.reset(FirebaseHttpClient::create());
37+
http_->setReuseConnection(true);
38+
}
39+
40+
const String& Firebase::auth() const {
41+
return auth_;
4542
}
4643

4744
FirebaseGet Firebase::get(const String& path) {
48-
return FirebaseGet(host_, auth_, path, &http_);
45+
return FirebaseGet(host_, auth_, path, http_.get());
46+
}
47+
48+
unique_ptr<FirebaseGet> Firebase::getPtr(const String& path) {
49+
return unique_ptr<FirebaseGet>(new FirebaseGet(host_, auth_, path, http_.get()));
4950
}
5051

5152
FirebaseSet Firebase::set(const String& path, const String& value) {
52-
return FirebaseSet(host_, auth_, path, value, &http_);
53+
return FirebaseSet(host_, auth_, path, value, http_.get());
54+
}
55+
56+
unique_ptr<FirebaseSet> Firebase::setPtr(const String& path,
57+
const String& value) {
58+
return unique_ptr<FirebaseSet>(
59+
new FirebaseSet(host_, auth_, path, value, http_.get()));
5360
}
5461

5562
FirebasePush Firebase::push(const String& path, const String& value) {
56-
return FirebasePush(host_, auth_, path, value, &http_);
63+
return FirebasePush(host_, auth_, path, value, http_.get());
64+
}
65+
unique_ptr<FirebasePush> Firebase::pushPtr(const String& path, const String& value) {
66+
return unique_ptr<FirebasePush>(
67+
new FirebasePush(host_, auth_, path, value, http_.get()));
5768
}
5869

5970
FirebaseRemove Firebase::remove(const String& path) {
60-
return FirebaseRemove(host_, auth_, path, &http_);
71+
return FirebaseRemove(host_, auth_, path, http_.get());
72+
}
73+
74+
unique_ptr<FirebaseRemove> Firebase::removePtr(const String& path) {
75+
return unique_ptr<FirebaseRemove>(
76+
new FirebaseRemove(host_, auth_, path, http_.get()));
6177
}
6278

6379
FirebaseStream Firebase::stream(const String& path) {
6480
// TODO: create new client dedicated to stream.
65-
return FirebaseStream(host_, auth_, path, &http_);
81+
return FirebaseStream(host_, auth_, path, http_.get());
82+
}
83+
84+
unique_ptr<FirebaseStream> Firebase::streamPtr(const String& path) {
85+
// TODO: create new client dedicated to stream.
86+
return unique_ptr<FirebaseStream>(
87+
new FirebaseStream(host_, auth_, path, http_.get()));
6688
}
6789

6890
// FirebaseCall
6991
FirebaseCall::FirebaseCall(const String& host, const String& auth,
7092
const char* method, const String& path,
71-
const String& data, HTTPClient* http) : http_(http) {
72-
String url = makeFirebaseURL(path, auth);
73-
http_->setReuse(true);
74-
http_->begin(host, kFirebasePort, url, true, kFirebaseFingerprint);
93+
const String& data, FirebaseHttpClient* http) : http_(http) {
94+
String path_with_auth = makeFirebaseURL(path, auth);
95+
http_->setReuseConnection(true);
96+
http_->begin(host, path_with_auth);
7597

7698
bool followRedirect = false;
77-
if (method == "STREAM") {
99+
if (String(method) == "STREAM") {
78100
method = "GET";
79101
http_->addHeader("Accept", "text/event-stream");
80102
followRedirect = true;
@@ -85,26 +107,24 @@ FirebaseCall::FirebaseCall(const String& host, const String& auth,
85107
http_->collectHeaders(headers, 1);
86108
}
87109

88-
int status = http_->sendRequest(method, (uint8_t*)data.c_str(), data.length());
110+
int status = http_->sendRequest(method, data);
89111

90112
// TODO: Add a max redirect check
91113
if (followRedirect) {
92-
while (status == HTTP_CODE_TEMPORARY_REDIRECT) {
114+
while (status == HttpStatus::TEMPORARY_REDIRECT) {
93115
String location = http_->header("Location");
94-
http_->setReuse(false);
116+
http_->setReuseConnection(false);
95117
http_->end();
96-
http_->setReuse(true);
97-
http_->begin(location, kFirebaseFingerprint);
98-
status = http_->sendRequest("GET", (uint8_t*)NULL, 0);
118+
http_->setReuseConnection(true);
119+
http_->begin(location);
120+
status = http_->sendRequest("GET", String());
99121
}
100122
}
101123

102124
if (status != 200) {
103-
#ifdef USE_ESP_ARDUINO_CORE_2_0_0
104-
error_ = FirebaseError(status, String(method) + " " + url + ": " + status);
105-
#else
106-
error_ = FirebaseError(status, String(method) + " " + url + ": " + HTTPClient::errorToString(status));
107-
#endif
125+
error_ = FirebaseError(status,
126+
String(method) + " " + path_with_auth +
127+
": " + http_->errorToString(status));
108128
}
109129

110130
// if not streaming.
@@ -123,14 +143,14 @@ const JsonObject& FirebaseCall::json() {
123143
// FirebaseGet
124144
FirebaseGet::FirebaseGet(const String& host, const String& auth,
125145
const String& path,
126-
HTTPClient* http)
146+
FirebaseHttpClient* http)
127147
: FirebaseCall(host, auth, "GET", path, "", http) {
128148
}
129149

130150
// FirebaseSet
131151
FirebaseSet::FirebaseSet(const String& host, const String& auth,
132152
const String& path, const String& value,
133-
HTTPClient* http)
153+
FirebaseHttpClient* http)
134154
: FirebaseCall(host, auth, "PUT", path, value, http) {
135155
if (!error()) {
136156
// TODO: parse json
@@ -140,7 +160,7 @@ FirebaseSet::FirebaseSet(const String& host, const String& auth,
140160
// FirebasePush
141161
FirebasePush::FirebasePush(const String& host, const String& auth,
142162
const String& path, const String& value,
143-
HTTPClient* http)
163+
FirebaseHttpClient* http)
144164
: FirebaseCall(host, auth, "POST", path, value, http) {
145165
if (!error()) {
146166
name_ = json()["name"].as<const char*>();
@@ -150,14 +170,14 @@ FirebasePush::FirebasePush(const String& host, const String& auth,
150170
// FirebasePush
151171
FirebaseRemove::FirebaseRemove(const String& host, const String& auth,
152172
const String& path,
153-
HTTPClient* http)
173+
FirebaseHttpClient* http)
154174
: FirebaseCall(host, auth, "DELETE", path, "", http) {
155175
}
156176

157177
// FirebaseStream
158178
FirebaseStream::FirebaseStream(const String& host, const String& auth,
159179
const String& path,
160-
HTTPClient* http)
180+
FirebaseHttpClient* http)
161181
: FirebaseCall(host, auth, "STREAM", path, "", http) {
162182
}
163183

src/Firebase.h

+44-17
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;
@@ -37,23 +39,34 @@ class Firebase {
3739
public:
3840
Firebase(const String& host, const String& auth = "");
3941

42+
const String& auth() const;
43+
4044
// Fetch json encoded `value` at `path`.
4145
FirebaseGet get(const String& path);
46+
virtual std::unique_ptr<FirebaseGet> getPtr(const String& path);
4247

4348
// Set json encoded `value` at `path`.
4449
FirebaseSet set(const String& path, const String& json);
50+
virtual std::unique_ptr<FirebaseSet> setPtr(const String& path, const String& json);
4551

4652
// Add new json encoded `value` to list at `path`.
4753
FirebasePush push(const String& path, const String& json);
54+
virtual std::unique_ptr<FirebasePush> pushPtr(const String& path, const String& json);
4855

4956
// Delete value at `path`.
5057
FirebaseRemove remove(const String& path);
58+
virtual std::unique_ptr<FirebaseRemove> removePtr(const String& path);
5159

5260
// Start a stream of events that affect value at `path`.
5361
FirebaseStream stream(const String& path);
62+
virtual std::unique_ptr<FirebaseStream> streamPtr(const String& path);
63+
64+
protected:
65+
// Used for testing.
66+
Firebase() {}
5467

5568
private:
56-
HTTPClient http_;
69+
std::unique_ptr<FirebaseHttpClient> http_;
5770
String host_;
5871
String auth_;
5972
};
@@ -76,20 +89,20 @@ class FirebaseCall {
7689
FirebaseCall() {}
7790
FirebaseCall(const String& host, const String& auth,
7891
const char* method, const String& path,
79-
const String& data = "",
80-
HTTPClient* http = NULL);
81-
const FirebaseError& error() const {
92+
const String& data = "",
93+
FirebaseHttpClient* http = NULL);
94+
virtual const FirebaseError& error() const {
8295
return error_;
8396
}
8497

85-
const String& response() {
98+
virtual const String& response() {
8699
return response_;
87100
}
88101

89102
const JsonObject& json();
90103

91104
protected:
92-
HTTPClient* http_;
105+
FirebaseHttpClient* http_;
93106
FirebaseError error_;
94107
String response_;
95108
DynamicJsonBuffer buffer_;
@@ -99,7 +112,7 @@ class FirebaseGet : public FirebaseCall {
99112
public:
100113
FirebaseGet() {}
101114
FirebaseGet(const String& host, const String& auth,
102-
const String& path, HTTPClient* http = NULL);
115+
const String& path, FirebaseHttpClient* http = NULL);
103116

104117
private:
105118
String json_;
@@ -109,7 +122,8 @@ class FirebaseSet: public FirebaseCall {
109122
public:
110123
FirebaseSet() {}
111124
FirebaseSet(const String& host, const String& auth,
112-
const String& path, const String& value, HTTPClient* http = NULL);
125+
const String& path, const String& value, FirebaseHttpClient* http = NULL);
126+
113127

114128
private:
115129
String json_;
@@ -119,9 +133,9 @@ class FirebasePush : public FirebaseCall {
119133
public:
120134
FirebasePush() {}
121135
FirebasePush(const String& host, const String& auth,
122-
const String& path, const String& value, HTTPClient* http = NULL);
136+
const String& path, const String& value, FirebaseHttpClient* http = NULL);
123137

124-
const String& name() const {
138+
virtual const String& name() const {
125139
return name_;
126140
}
127141

@@ -133,18 +147,18 @@ class FirebaseRemove : public FirebaseCall {
133147
public:
134148
FirebaseRemove() {}
135149
FirebaseRemove(const String& host, const String& auth,
136-
const String& path, HTTPClient* http = NULL);
150+
const String& path, FirebaseHttpClient* http = NULL);
137151
};
138152

139153

140154
class FirebaseStream : public FirebaseCall {
141155
public:
142156
FirebaseStream() {}
143157
FirebaseStream(const String& host, const String& auth,
144-
const String& path, HTTPClient* http = NULL);
158+
const String& path, FirebaseHttpClient* http = NULL);
145159

146160
// Return if there is any event available to read.
147-
bool available();
161+
virtual bool available();
148162

149163
// Event type.
150164
enum Event {
@@ -153,8 +167,21 @@ class FirebaseStream : public FirebaseCall {
153167
PATCH
154168
};
155169

170+
static inline String EventToName(Event event) {
171+
switch(event) {
172+
case UNKNOWN:
173+
return "UNKNOWN";
174+
case PUT:
175+
return "PUT";
176+
case PATCH:
177+
return "PATCH";
178+
default:
179+
return "INVALID_EVENT_" + event;
180+
}
181+
}
182+
156183
// Read next json encoded `event` from stream.
157-
Event read(String& event);
184+
virtual Event read(String& event);
158185

159186
const FirebaseError& error() const {
160187
return _error;

0 commit comments

Comments
 (0)