diff --git a/contrib/src/modem/command.h b/contrib/src/modem/command.h index 89aaee1a..bc5bde8c 100644 --- a/contrib/src/modem/command.h +++ b/contrib/src/modem/command.h @@ -1,7 +1,7 @@ #ifndef MODEM_COMMAND_H #define MODEM_COMMAND_H -#include "Firebase.h" +#include "FirebaseArduino.h" #include "modem/output-stream.h" #include "modem/input-stream.h" @@ -10,19 +10,19 @@ namespace modem { class Command { public: - Command(Firebase* fbase) : fbase_(fbase) {} + Command(FirebaseArduino* fbase) : fbase_(fbase) {} // Execute command, reading any additional data needed from stream. // Return false if execution failed. virtual bool execute(const String& command, InputStream* in, OutputStream* out) = 0; protected: - Firebase& fbase() { + FirebaseArduino& fbase() { return *fbase_; } private: - Firebase* fbase_; + FirebaseArduino* fbase_; }; } // modem diff --git a/contrib/src/modem/db/DatabaseProtocol.cpp b/contrib/src/modem/db/DatabaseProtocol.cpp index 338daf82..8a053ebb 100644 --- a/contrib/src/modem/db/DatabaseProtocol.cpp +++ b/contrib/src/modem/db/DatabaseProtocol.cpp @@ -42,7 +42,7 @@ void DatabaseProtocol::Execute(const String& command_name, InputStream* in, } std::unique_ptr DatabaseProtocol::CreateCommand(const String& text, - Firebase* fbase) { + FirebaseArduino* fbase) { std::unique_ptr command; if (text == "GET") { command.reset(new GetCommand(fbase)); diff --git a/contrib/src/modem/db/DatabaseProtocol.h b/contrib/src/modem/db/DatabaseProtocol.h index dec7fad5..8da8ed62 100644 --- a/contrib/src/modem/db/DatabaseProtocol.h +++ b/contrib/src/modem/db/DatabaseProtocol.h @@ -13,9 +13,9 @@ class DatabaseProtocol : public SerialProtocol { const std::vector& commands() const override; void Execute(const String& command, InputStream* in, OutputStream* out) override; private: - std::unique_ptr CreateCommand(const String& text, Firebase* fbase); + std::unique_ptr CreateCommand(const String& text, FirebaseArduino* fbase); - std::unique_ptr fbase_; + std::unique_ptr fbase_; }; diff --git a/contrib/src/modem/db/begin-command.cpp b/contrib/src/modem/db/begin-command.cpp index 9658815d..9950f8e7 100644 --- a/contrib/src/modem/db/begin-command.cpp +++ b/contrib/src/modem/db/begin-command.cpp @@ -33,13 +33,14 @@ bool BeginCommand::execute(const String& command, return false; } - new_firebase_.reset(new Firebase(host.c_str(), auth.c_str())); + new_firebase_.reset(new FirebaseArduino()); + new_firebase_.get()->begin(host.c_str(), auth.c_str()); out->println("+OK"); return true; } -std::unique_ptr BeginCommand::firebase() { +std::unique_ptr BeginCommand::firebase() { return std::move(new_firebase_); } diff --git a/contrib/src/modem/db/commands.h b/contrib/src/modem/db/commands.h index f6808024..2bb6bb71 100644 --- a/contrib/src/modem/db/commands.h +++ b/contrib/src/modem/db/commands.h @@ -1,7 +1,7 @@ #ifndef MODEM_DB_COMMANDS_H #define MODEM_DB_COMMANDS_H -#include "Firebase.h" +#include "FirebaseArduino.h" #include "modem/command.h" #include "modem/output-stream.h" #include "modem/input-stream.h" @@ -11,28 +11,28 @@ namespace modem { class GetCommand : public Command { public: - GetCommand(Firebase* fbase) : Command(fbase) {} + GetCommand(FirebaseArduino* fbase) : Command(fbase) {} bool execute(const String& command, InputStream* in, OutputStream* out); }; class SetCommand : public Command { public: - SetCommand(Firebase* fbase) : Command(fbase) {} + SetCommand(FirebaseArduino* fbase) : Command(fbase) {} bool execute(const String& command, InputStream* in, OutputStream* out); }; class RemoveCommand : public Command { public: - RemoveCommand(Firebase* fbase) : Command(fbase) {} + RemoveCommand(FirebaseArduino* fbase) : Command(fbase) {} bool execute(const String& command, InputStream* in, OutputStream* out); }; class PushCommand : public Command { public: - PushCommand(Firebase* fbase) : Command(fbase) {} + PushCommand(FirebaseArduino* fbase) : Command(fbase) {} bool execute(const String& command, InputStream* in, OutputStream* out); }; @@ -44,15 +44,15 @@ class BeginCommand : public Command { bool execute(const String& command, InputStream* in, OutputStream* out); // This can only be called once. - std::unique_ptr firebase(); + std::unique_ptr firebase(); private: - std::unique_ptr new_firebase_; + std::unique_ptr new_firebase_; }; class StreamCommand : public Command { public: - StreamCommand(Firebase* fbase) : Command(fbase) {} + StreamCommand(FirebaseArduino* fbase) : Command(fbase) {} bool execute(const String& command, InputStream* in, OutputStream* out); }; diff --git a/contrib/src/modem/db/get-command.cpp b/contrib/src/modem/db/get-command.cpp index f7c7c7ef..0fb2c478 100644 --- a/contrib/src/modem/db/get-command.cpp +++ b/contrib/src/modem/db/get-command.cpp @@ -13,16 +13,14 @@ bool GetCommand::execute(const String& command, return false; } - std::string path = in->readLine().c_str(); - std::unique_ptr get(fbase().getPtr(path)); - - if (get->error()) { + String path = in->readLine(); + String value = fbase().getString(path); + if (fbase().error().length() != 0) { out->print("-FAIL "); - out->println(get->error().message().c_str()); + out->println(fbase().error().c_str()); return false; } - String value(get->response().c_str()); // TODO implement json parsing to pull and process value. out->print("+"); out->println(value); diff --git a/contrib/src/modem/db/push-command.cpp b/contrib/src/modem/db/push-command.cpp index 8ceb33b7..0ed420e5 100644 --- a/contrib/src/modem/db/push-command.cpp +++ b/contrib/src/modem/db/push-command.cpp @@ -14,15 +14,14 @@ bool PushCommand::execute(const String& command, return false; } - std::string path(in->readStringUntil(' ').c_str()); - std::string data(in->readLine().c_str()); + String path = in->readStringUntil(' '); + String data = in->readLine(); - std::unique_ptr push( - fbase().pushPtr(path, EncodeForJson(data))); + fbase().pushString(path, data); - if (push->error()) { + if (fbase().error().length() != 0) { out->print("-FAIL "); - out->println(push->error().message().c_str()); + out->println(fbase().error().c_str()); return false; } else { out->println("+OK"); diff --git a/contrib/src/modem/db/remove-command.cpp b/contrib/src/modem/db/remove-command.cpp index a144de23..3e17ce56 100644 --- a/contrib/src/modem/db/remove-command.cpp +++ b/contrib/src/modem/db/remove-command.cpp @@ -14,11 +14,11 @@ bool RemoveCommand::execute(const String& command, } String path = in->readLine(); - std::unique_ptr get(fbase().removePtr(path.c_str())); + fbase().remove(path); - if (get->error()) { + if (fbase().error().length() != 0) { out->print("-FAIL "); - out->println(get->error().message().c_str()); + out->println(fbase().error().c_str()); return false; } diff --git a/contrib/src/modem/db/set-command.cpp b/contrib/src/modem/db/set-command.cpp index 71530539..c91821e1 100644 --- a/contrib/src/modem/db/set-command.cpp +++ b/contrib/src/modem/db/set-command.cpp @@ -14,15 +14,14 @@ bool SetCommand::execute(const String& command, return false; } - std::string path(in->readStringUntil(' ').c_str()); - std::string data(in->readLine().c_str()); + String path = in->readStringUntil(' '); + String data = in->readLine(); - std::unique_ptr set(fbase().setPtr(path, - EncodeForJson(data))); + fbase().setString(path, data); - if (set->error()) { + if (fbase().error().length() != 0) { out->print("-FAIL "); - out->println(set->error().message().c_str()); + out->println(fbase().error().c_str()); return false; } else { out->println("+OK"); diff --git a/contrib/src/modem/db/stream-command.cpp b/contrib/src/modem/db/stream-command.cpp index f8259bc6..69e5bd33 100644 --- a/contrib/src/modem/db/stream-command.cpp +++ b/contrib/src/modem/db/stream-command.cpp @@ -13,27 +13,24 @@ bool StreamCommand::execute(const String& command, return false; } - std::string path = in->readLine().c_str(); - std::unique_ptr stream(fbase().streamPtr(path)); + String path = in->readLine().c_str(); + fbase().stream(path); - if (stream->error()) { + if (fbase().error().length() != 0) { out->print("-FAIL "); - out->println(stream->error().message().c_str()); + out->println(fbase().error().c_str()); return false; } - bool running = true; DynamicJsonBuffer buffer; while(running) { - if (stream->available()) { - std::string json; - FirebaseStream::Event event = stream->read(json); + if (fbase().available()) { + FirebaseObject event = fbase().readEvent(); out->print("+"); - out->print(FirebaseStream::EventToName(event).c_str()); + out->print(event.getString("type").c_str()); out->print(" "); - const auto& object = buffer.parseObject(json.c_str()); - String data = object["data"].asString(); - out->println(object["path"].asString()); + String data = event.getString("data"); + out->println(event.getString("path")); out->println(data.length()); out->println(data); } else if (in->available()) { diff --git a/contrib/test/mock-firebase.h b/contrib/test/mock-firebase.h index 92f1e9fa..916f4d00 100644 --- a/contrib/test/mock-firebase.h +++ b/contrib/test/mock-firebase.h @@ -3,48 +3,22 @@ #include #include "gtest/gtest.h" -#include "Firebase.h" +#include "FirebaseArduino.h" namespace firebase { namespace modem { -class MockFirebase : public Firebase { +class MockFirebase : public FirebaseArduino { public: - MOCK_METHOD1(getPtr, std::unique_ptr(const std::string&)); - MOCK_METHOD2(setPtr, std::unique_ptr(const std::string&, const std::string&)); - MOCK_METHOD2(pushPtr, std::unique_ptr(const std::string&, const std::string&)); - MOCK_METHOD1(removePtr, std::unique_ptr(const std::string&)); - MOCK_METHOD1(streamPtr, std::unique_ptr(const std::string&)); -}; - -class MockFirebaseGet : public FirebaseGet { - public: - MOCK_CONST_METHOD0(response, const std::string&()); - MOCK_CONST_METHOD0(error, const FirebaseError&()); -}; - -class MockFirebaseSet : public FirebaseSet { - public: - MOCK_CONST_METHOD0(json, const std::string&()); - MOCK_CONST_METHOD0(error, const FirebaseError&()); -}; - -class MockFirebasePush : public FirebasePush { - public: - MOCK_CONST_METHOD0(name, const std::string&()); - MOCK_CONST_METHOD0(error, const FirebaseError&()); -}; - -class MockFirebaseRemove : public FirebaseRemove { - public: - MOCK_CONST_METHOD0(error, const FirebaseError&()); -}; - -class MockFirebaseStream : public FirebaseStream { - public: - MOCK_METHOD0(available, bool()); - MOCK_METHOD1(read, Event(std::string& event)); - MOCK_CONST_METHOD0(error, const FirebaseError&()); + MOCK_METHOD0(error, const String &()); + MOCK_METHOD1(getString, String (const String& path)); + MOCK_METHOD2(pushString, String (const String& path, const String& data)); + MOCK_METHOD1(remove, void(const String& path)); + MOCK_METHOD2(setString, void(const String& path, const String& data)); + MOCK_METHOD0(available, bool ()); + MOCK_METHOD0(readEvent, FirebaseObject ()); + MOCK_METHOD2(begin, void (const String& host, const String& auth)); + MOCK_METHOD1(stream, void (const String& path)); }; } // modem diff --git a/contrib/test/modem/Makefile b/contrib/test/modem/Makefile index 06b07175..bda22d32 100644 --- a/contrib/test/modem/Makefile +++ b/contrib/test/modem/Makefile @@ -55,8 +55,8 @@ CXXFLAGS += -g -Wall -Wextra -pthread -std=c++11 # All tests produced by this Makefile. Remember to add new tests you # created to the list. TESTS = get-command_test set-command_test remove-command_test \ - push-command_test begin-command_test stream-command_test \ - serial-transceiver_test + push-command_test begin-command_test \ + serial-transceiver_test stream-command_test # All Google Test headers. Usually you shouldn't change this # definition. @@ -130,6 +130,12 @@ arduino_mock_all.a : ArduinoMockAll.o # Builds shared objects. +FirebaseArduino.o : $(FIREBASE_SRC_ROOT)/FirebaseArduino.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(FIREBASE_SRC_ROOT)/FirebaseArduino.cpp + +FirebaseObject.o : $(FIREBASE_SRC_ROOT)/FirebaseObject.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(FIREBASE_SRC_ROOT)/FirebaseObject.cpp + Firebase.o : $(FIREBASE_SRC_ROOT)/Firebase.cpp $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(FIREBASE_SRC_ROOT)/Firebase.cpp @@ -144,7 +150,7 @@ get-command.o : $(SRC_ROOT)/modem/db/get-command.cpp get-command_test.o : $(TEST_DIR)/get-command_test.cpp $(GMOCK_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(TEST_DIR)/get-command_test.cpp -get-command_test : get-command_test.o Firebase.o FirebaseHttpClient_dummy.o get-command.o gmock_main.a \ +get-command_test : get-command_test.o FirebaseArduino.o Firebase.o FirebaseObject.o FirebaseHttpClient_dummy.o get-command.o gmock_main.a \ arduino_mock_all.a $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -155,7 +161,7 @@ set-command.o : $(SRC_ROOT)/modem/db/set-command.cpp set-command_test.o : $(TEST_DIR)/set-command_test.cpp $(GMOCK_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(TEST_DIR)/set-command_test.cpp -set-command_test : set-command.o set-command_test.o Firebase.o FirebaseHttpClient_dummy.o gmock_main.a \ +set-command_test : set-command.o set-command_test.o FirebaseArduino.o Firebase.o FirebaseObject.o FirebaseHttpClient_dummy.o gmock_main.a \ arduino_mock_all.a $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -166,7 +172,7 @@ remove-command.o : $(SRC_ROOT)/modem/db/remove-command.cpp remove-command_test.o : $(TEST_DIR)/remove-command_test.cpp $(GMOCK_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(TEST_DIR)/remove-command_test.cpp -remove-command_test : remove-command.o remove-command_test.o Firebase.o FirebaseHttpClient_dummy.o gmock_main.a \ +remove-command_test : remove-command.o remove-command_test.o FirebaseArduino.o Firebase.o FirebaseObject.o FirebaseHttpClient_dummy.o gmock_main.a \ arduino_mock_all.a $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -177,7 +183,7 @@ push-command.o : $(SRC_ROOT)/modem/db/push-command.cpp push-command_test.o : $(TEST_DIR)/push-command_test.cpp $(GMOCK_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(TEST_DIR)/push-command_test.cpp -push-command_test : push-command.o push-command_test.o Firebase.o FirebaseHttpClient_dummy.o gmock_main.a \ +push-command_test : push-command.o push-command_test.o FirebaseArduino.o Firebase.o FirebaseObject.o FirebaseHttpClient_dummy.o gmock_main.a \ arduino_mock_all.a $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -188,7 +194,7 @@ begin-command.o : $(SRC_ROOT)/modem/db/begin-command.cpp begin-command_test.o : $(TEST_DIR)/begin-command_test.cpp $(GMOCK_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(TEST_DIR)/begin-command_test.cpp -begin-command_test : begin-command.o begin-command_test.o Firebase.o FirebaseHttpClient_dummy.o gmock_main.a \ +begin-command_test : begin-command.o begin-command_test.o FirebaseArduino.o Firebase.o FirebaseObject.o FirebaseHttpClient_dummy.o gmock_main.a \ arduino_mock_all.a $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -199,7 +205,7 @@ stream-command.o : $(SRC_ROOT)/modem/db/stream-command.cpp stream-command_test.o : $(TEST_DIR)/stream-command_test.cpp $(GMOCK_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(TEST_DIR)/stream-command_test.cpp -stream-command_test : stream-command.o stream-command_test.o Firebase.o FirebaseHttpClient_dummy.o gmock_main.a \ +stream-command_test : stream-command.o stream-command_test.o FirebaseArduino.o Firebase.o FirebaseObject.o FirebaseHttpClient_dummy.o gmock_main.a \ arduino_mock_all.a $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ diff --git a/contrib/test/modem/begin-command_test.cpp b/contrib/test/modem/begin-command_test.cpp index e8682cfe..c5700d4f 100644 --- a/contrib/test/modem/begin-command_test.cpp +++ b/contrib/test/modem/begin-command_test.cpp @@ -1,4 +1,4 @@ -#include "Firebase.h" +#include "FirebaseArduino.h" #include "gtest/gtest.h" #include "modem/db/commands.h" #include "test/modem/mock-input-stream.h" @@ -52,8 +52,7 @@ TEST_F(BeginCommandTest, hostOnly) { BeginCommand command; ASSERT_TRUE(command.execute("BEGIN_DB", &in_, &out_)); - std::unique_ptr firebase(command.firebase()); - EXPECT_EQ("", firebase->auth()); + std::unique_ptr firebase(command.firebase()); } TEST_F(BeginCommandTest, hostAndAuth) { @@ -66,8 +65,7 @@ TEST_F(BeginCommandTest, hostAndAuth) { BeginCommand command; ASSERT_TRUE(command.execute("BEGIN_DB", &in_, &out_)); - std::unique_ptr firebase(command.firebase()); - EXPECT_EQ(auth, firebase->auth()); + std::unique_ptr firebase(command.firebase()); } TEST_F(BeginCommandTest, neitherHostNorAuth) { @@ -77,7 +75,7 @@ TEST_F(BeginCommandTest, neitherHostNorAuth) { BeginCommand command; ASSERT_FALSE(command.execute("BEGIN_DB", &in_, &out_)); - std::unique_ptr firebase(command.firebase()); + std::unique_ptr firebase(command.firebase()); EXPECT_FALSE(firebase); } } // modem diff --git a/contrib/test/modem/get-command_test.cpp b/contrib/test/modem/get-command_test.cpp index 7372c79e..813fad2f 100644 --- a/contrib/test/modem/get-command_test.cpp +++ b/contrib/test/modem/get-command_test.cpp @@ -1,4 +1,4 @@ -#include "Firebase.h" +#include "FirebaseArduino.h" #include "gtest/gtest.h" #include "modem/db/commands.h" #include "test/modem/mock-input-stream.h" @@ -16,22 +16,15 @@ using ::testing::_; class GetCommandTest : public ::testing::Test { protected: void SetUp() override { - get_.reset(new MockFirebaseGet()); } void FeedCommand(const String& path) { const String command_fragment(String(" ") + path); - EXPECT_CALL(in_, readLine()) + EXPECT_CALL(in_, readLine()) .WillOnce(Return(command_fragment)); } bool RunCommand(const FirebaseError& error) { - EXPECT_CALL(*get_, error()) - .WillRepeatedly(ReturnRef(error)); - - EXPECT_CALL(fbase_, getPtr(_)) - .WillOnce(Return(ByMove(std::move(get_)))); - GetCommand getCmd(&fbase_); return getCmd.execute("GET", &in_, &out_); } @@ -39,16 +32,18 @@ class GetCommandTest : public ::testing::Test { MockInputStream in_; MockOutputStream out_; MockFirebase fbase_; - std::unique_ptr get_; }; TEST_F(GetCommandTest, gets) { const String path("/test/path"); + const String command_fragment(" /test/path"); FeedCommand(path); const String value("Test value"); - EXPECT_CALL(*get_, response()) - .WillOnce(ReturnRef(value)); + EXPECT_CALL(fbase_, getString(command_fragment)).WillOnce(Return("Test value")); + + const String no_error = ""; + EXPECT_CALL(fbase_, error()).WillOnce(ReturnRef(no_error)); EXPECT_CALL(out_, print(String("+"))) .WillOnce(Return(1)); @@ -61,13 +56,19 @@ TEST_F(GetCommandTest, gets) { TEST_F(GetCommandTest, handlesError) { FirebaseError error(-200, "Test Error."); + const String command_fragment(" /test/path"); const String path("/test/path"); FeedCommand(path); + const String error_value = "Test Error."; + EXPECT_CALL(fbase_, error()).WillRepeatedly(ReturnRef(error_value)); + + EXPECT_CALL(fbase_, getString(command_fragment)).WillOnce(Return("")); + EXPECT_CALL(out_, print(String("-FAIL "))) .WillOnce(Return(1)); - EXPECT_CALL(out_, println(String(error.message().c_str()))) + EXPECT_CALL(out_, println(error_value)) .WillOnce(Return(1)); ASSERT_FALSE(RunCommand(error)); diff --git a/contrib/test/modem/push-command_test.cpp b/contrib/test/modem/push-command_test.cpp index 0b2a1d63..2f2ff82e 100644 --- a/contrib/test/modem/push-command_test.cpp +++ b/contrib/test/modem/push-command_test.cpp @@ -1,4 +1,4 @@ -#include "Firebase.h" +#include "FirebaseArduino.h" #include "gtest/gtest.h" #include "modem/db/commands.h" #include "modem/json_util.h" @@ -17,7 +17,6 @@ using ::testing::_; class PushCommandTest : public ::testing::Test { protected: void SetUp() override { - push_.reset(new MockFirebasePush()); } void FeedCommand(const String& path, const String& data) { @@ -40,13 +39,7 @@ class PushCommandTest : public ::testing::Test { .WillOnce(Return(error_message.length())); } - bool RunExpectingData(const String& data, const FirebaseError& error) { - EXPECT_CALL(*push_, error()) - .WillRepeatedly(ReturnRef(error)); - - EXPECT_CALL(fbase_, pushPtr(_, EncodeForJson(data))) - .WillOnce(Return(ByMove(std::move(push_)))); - + bool RunCommand() { PushCommand pushCmd(&fbase_); return pushCmd.execute("PUSH", &in_, &out_); } @@ -54,7 +47,6 @@ class PushCommandTest : public ::testing::Test { MockInputStream in_; MockOutputStream out_; MockFirebase fbase_; - std::unique_ptr push_; }; TEST_F(PushCommandTest, sendsData) { @@ -62,22 +54,26 @@ TEST_F(PushCommandTest, sendsData) { const String data("This is a test payload."); FeedCommand(path, data); + const String no_error = ""; + EXPECT_CALL(fbase_, error()).WillOnce(ReturnRef(no_error)); + ExpectOutput("+OK"); - ASSERT_TRUE(RunExpectingData(data, FirebaseError())); + ASSERT_TRUE(RunCommand()); } TEST_F(PushCommandTest, HandlesError) { const String path("/test/path"); const String data("This is a test payload."); - FirebaseError error(-200, "Test error."); FeedCommand(path, data); - ExpectErrorOutput(error.message()); + const String error = "Test Error."; + EXPECT_CALL(fbase_, error()).WillRepeatedly(ReturnRef(error)); - ASSERT_FALSE(RunExpectingData(data, error)); + ExpectErrorOutput(error); + + ASSERT_FALSE(RunCommand()); } } // modem } // firebase - diff --git a/contrib/test/modem/remove-command_test.cpp b/contrib/test/modem/remove-command_test.cpp index 8f71903b..e60f0524 100644 --- a/contrib/test/modem/remove-command_test.cpp +++ b/contrib/test/modem/remove-command_test.cpp @@ -2,7 +2,7 @@ #include "test/modem/mock-output-stream.h" #include "test/modem/mock-input-stream.h" #include "test/mock-firebase.h" -#include "Firebase.h" +#include "FirebaseArduino.h" #include "modem/db/commands.h" namespace firebase { @@ -16,7 +16,6 @@ using ::testing::_; class RemoveCommandTest : public ::testing::Test { protected: void SetUp() override { - remove_.reset(new MockFirebaseRemove()); } void FeedCommand(const String& path) { @@ -25,13 +24,7 @@ class RemoveCommandTest : public ::testing::Test { .WillOnce(Return(command_fragment)); } - bool RunCommand(const FirebaseError& error) { - EXPECT_CALL(*remove_, error()) - .WillRepeatedly(ReturnRef(error)); - - EXPECT_CALL(fbase_, removePtr(_)) - .WillOnce(Return(ByMove(std::move(remove_)))); - + bool RunCommand() { RemoveCommand command(&fbase_); return command.execute("REMOVE", &in_, &out_); } @@ -39,30 +32,34 @@ class RemoveCommandTest : public ::testing::Test { MockInputStream in_; MockOutputStream out_; MockFirebase fbase_; - std::unique_ptr remove_; }; TEST_F(RemoveCommandTest, success) { const String path("/test/path"); FeedCommand(path); + const String no_error = ""; + EXPECT_CALL(fbase_, error()).WillOnce(ReturnRef(no_error)); + EXPECT_CALL(out_, println(String("+OK"))) .WillOnce(Return(3)); - ASSERT_TRUE(RunCommand(FirebaseError())); + ASSERT_TRUE(RunCommand()); } TEST_F(RemoveCommandTest, handlesError) { - FirebaseError error(-200, "Test Error."); const String path("/test/path"); FeedCommand(path); EXPECT_CALL(out_, print(String("-FAIL "))) .WillOnce(Return(1)); - EXPECT_CALL(out_, println(String(error.message().c_str()))) + const String error = "Test Error."; + EXPECT_CALL(fbase_, error()).WillRepeatedly(ReturnRef(error)); + + EXPECT_CALL(out_, println(String(error.c_str()))) .WillOnce(Return(1)); - ASSERT_FALSE(RunCommand(error)); + ASSERT_FALSE(RunCommand()); } } // modem diff --git a/contrib/test/modem/serial-transceiver_test.cpp b/contrib/test/modem/serial-transceiver_test.cpp index bcbed2a1..c5328612 100644 --- a/contrib/test/modem/serial-transceiver_test.cpp +++ b/contrib/test/modem/serial-transceiver_test.cpp @@ -1,6 +1,6 @@ #include -#include "Firebase.h" +#include "FirebaseArduino.h" #include "gtest/gtest.h" #include "modem/SerialTransceiver.h" diff --git a/contrib/test/modem/set-command_test.cpp b/contrib/test/modem/set-command_test.cpp index 3bbe4747..99004581 100644 --- a/contrib/test/modem/set-command_test.cpp +++ b/contrib/test/modem/set-command_test.cpp @@ -1,4 +1,4 @@ -#include "Firebase.h" +#include "FirebaseArduino.h" #include "gtest/gtest.h" #include "modem/db/commands.h" #include "modem/json_util.h" @@ -17,7 +17,6 @@ using ::testing::_; class SetCommandTest : public ::testing::Test { protected: void SetUp() override { - set_.reset(new MockFirebaseSet()); } void FeedCommand(const String& path, const String& data) { @@ -40,13 +39,7 @@ class SetCommandTest : public ::testing::Test { .WillOnce(Return(error_message.length())); } - bool RunExpectingData(const String& data, const FirebaseError& error) { - EXPECT_CALL(*set_, error()) - .WillRepeatedly(ReturnRef(error)); - - EXPECT_CALL(fbase_, setPtr(_, EncodeForJson(data))) - .WillOnce(Return(ByMove(std::move(set_)))); - + bool RunCommand() { SetCommand setCmd(&fbase_); return setCmd.execute("SET", &in_, &out_); } @@ -54,28 +47,30 @@ class SetCommandTest : public ::testing::Test { MockInputStream in_; MockOutputStream out_; MockFirebase fbase_; - std::unique_ptr set_; }; TEST_F(SetCommandTest, sendsData) { const String path("/test/path"); const String data("This is a test payload."); + const String no_error = ""; + EXPECT_CALL(fbase_, error()).WillOnce(ReturnRef(no_error)); FeedCommand(path, data); ExpectOutput("+OK"); - ASSERT_TRUE(RunExpectingData(data, FirebaseError())); + ASSERT_TRUE(RunCommand()); } TEST_F(SetCommandTest, HandlesError) { const String path("/test/path"); const String data("This is a test payload."); - FirebaseError error(-200, "Test error."); + const String error = "TestError"; + EXPECT_CALL(fbase_, error()).WillRepeatedly(ReturnRef(error)); FeedCommand(path, data); - ExpectErrorOutput(error.message()); + ExpectErrorOutput(error); - ASSERT_FALSE(RunExpectingData(data, error)); + ASSERT_FALSE(RunCommand()); } } // modem } // firebase diff --git a/contrib/test/modem/stream-command_test.cpp b/contrib/test/modem/stream-command_test.cpp index 752a01a4..783a24f7 100644 --- a/contrib/test/modem/stream-command_test.cpp +++ b/contrib/test/modem/stream-command_test.cpp @@ -1,4 +1,4 @@ -#include "Firebase.h" +#include "FirebaseArduino.h" #include "gtest/gtest.h" #include "modem/db/commands.h" #include "test/modem/mock-input-stream.h" @@ -17,16 +17,9 @@ using ::testing::_; class StreamCommandTest : public ::testing::Test { protected: void SetUp() override { - stream_.reset(new MockFirebaseStream()); } - bool RunCommand(const FirebaseError& error) { - EXPECT_CALL(*stream_, error()) - .WillRepeatedly(ReturnRef(error)); - - EXPECT_CALL(fbase_, streamPtr(_)) - .WillOnce(Return(ByMove(std::move(stream_)))); - + bool RunCommand() { StreamCommand cmd(&fbase_); return cmd.execute("BEGIN_STREAM", &in_, &out_); } @@ -34,11 +27,20 @@ class StreamCommandTest : public ::testing::Test { MockInputStream in_; MockOutputStream out_; MockFirebase fbase_; - std::unique_ptr stream_; }; TEST_F(StreamCommandTest, streams) { const String path("/test/path"); + + const String no_error = ""; + EXPECT_CALL(fbase_, error()).WillRepeatedly(ReturnRef(no_error)); + + const String data = "TestValue"; + const String value(String("{\"path\":\"/test/path\",\"data\":\"") + data + "\",\"type\":\"PUT\"}"); + + const FirebaseObject fo = FirebaseObject(value.c_str()); + EXPECT_CALL(fbase_, readEvent()).WillRepeatedly(Return(fo)); + EXPECT_CALL(in_, available()) .WillRepeatedly(Return(true)); @@ -46,17 +48,10 @@ TEST_F(StreamCommandTest, streams) { .WillOnce(Return(path)) .WillOnce(Return("END_STREAM")); - const String data = "Test Value"; - const String value(String("{\"path\" : \"/test/path\", \"data\" : \"") + data + "\"}"); - EXPECT_CALL(*stream_, available()) - .WillOnce(Return(true)) - .WillRepeatedly(Return(false)); - - EXPECT_CALL(*stream_, read(_)) - .WillOnce(Invoke([&value](std::string& json) { - json = value.c_str(); - return FirebaseStream::PUT; - })); + EXPECT_CALL(fbase_, available()) + .WillOnce(Return(true)) + .WillRepeatedly(Return(false)); + EXPECT_CALL(fbase_, stream(path)); EXPECT_CALL(out_, print(String("+"))) .WillOnce(Return(1)); @@ -75,21 +70,23 @@ TEST_F(StreamCommandTest, streams) { EXPECT_CALL(out_, println(String("+OK"))) .WillOnce(Return(1)); - ASSERT_TRUE(RunCommand(FirebaseError())); + ASSERT_TRUE(RunCommand()); } TEST_F(StreamCommandTest, handlesError) { - FirebaseError error(-200, "Test Error."); + const String error("Test Error."); const String path("/test/path"); EXPECT_CALL(in_, readLine()) .WillOnce(Return(path)); + EXPECT_CALL(fbase_, error()).WillRepeatedly(ReturnRef(error)); + EXPECT_CALL(out_, print(String("-FAIL "))) .WillOnce(Return(1)); - EXPECT_CALL(out_, println(String(error.message().c_str()))) + EXPECT_CALL(out_, println(String(error.c_str()))) .WillOnce(Return(1)); - ASSERT_FALSE(RunCommand(error)); + ASSERT_FALSE(RunCommand()); } } // modem diff --git a/src/Firebase.cpp b/src/Firebase.cpp index fe8e13c3..b6c10043 100644 --- a/src/Firebase.cpp +++ b/src/Firebase.cpp @@ -42,115 +42,16 @@ const std::string& Firebase::auth() const { return auth_; } -FirebaseGet Firebase::get(const std::string& path) { - return FirebaseGet(host_, auth_, path, http_); -} - -unique_ptr Firebase::getPtr(const std::string& path) { - return unique_ptr(new FirebaseGet(host_, auth_, path, http_)); -} - -FirebaseSet Firebase::set(const std::string& path, const std::string& value) { - return FirebaseSet(host_, auth_, path, value, http_); -} - -unique_ptr Firebase::setPtr(const std::string& path, - const std::string& value) { - return unique_ptr( - new FirebaseSet(host_, auth_, path, value, http_)); -} - -FirebasePush Firebase::push(const std::string& path, const std::string& value) { - return FirebasePush(host_, auth_, path, value, http_); -} - -unique_ptr Firebase::pushPtr(const std::string& path, const std::string& value) { - return unique_ptr( - new FirebasePush(host_, auth_, path, value, http_)); -} - -FirebaseRemove Firebase::remove(const std::string& path) { - return FirebaseRemove(host_, auth_, path, http_); -} - -unique_ptr Firebase::removePtr(const std::string& path) { - return unique_ptr( - new FirebaseRemove(host_, auth_, path, http_)); -} - -FirebaseStream Firebase::stream(const std::string& path) { - // TODO: create new client dedicated to stream. - return FirebaseStream(host_, auth_, path, http_); -} - -unique_ptr Firebase::streamPtr(const std::string& path) { - // TODO: create new client dedicated to stream. - return unique_ptr( - new FirebaseStream(host_, auth_, path, http_)); -} - -// FirebaseCall -FirebaseCall::FirebaseCall(const std::string& host, const std::string& auth, - const char* method, const std::string& path, - const std::string& data, const std::shared_ptr http) : http_(http) { - std::string path_with_auth = makeFirebaseURL(path, auth); - if ((method == "STREAM") && (path == http->getStreamingPath())){ - // already streaming requested path. - return; - } - if (http_->isStreaming()) { - // closing streaming connection. - http_->setReuseConnection(false); - http_->end(); - } - http_->setReuseConnection(true); - http_->begin(host, path_with_auth); - - bool followRedirect = false; - if (std::string(method) == "STREAM") { - method = "GET"; - http_->addHeader("Accept", "text/event-stream"); - followRedirect = true; - } - - if (followRedirect) { - const char* headers[] = {"Location"}; - http_->collectHeaders(headers, 1); - } - - int status = http_->sendRequest(method, data); - - // TODO: Add a max redirect check - if (followRedirect) { - while (status == HttpStatus::TEMPORARY_REDIRECT) { - std::string location = http_->header("Location"); - http_->setReuseConnection(false); - http_->end(); - http_->setReuseConnection(true); - http_->begin(location); - status = http_->sendRequest("GET", std::string()); - } - } - - if (status != 200) { +void FirebaseCall::analyzeError(char* method, int status, const std::string& path_with_auth) { + if (status != 200) { error_ = FirebaseError(status, std::string(method) + " " + path_with_auth + ": " + http_->errorToString(status)); } - - // if not streaming. - if (!followRedirect) { - response_ = http_->getString(); - http_->setStreaming(""); - } else { - http_->setStreaming(path); - } } FirebaseCall::~FirebaseCall() { - if (http_ && !http_->isStreaming()) { - http_->end(); - } + http_->end(); } const JsonObject& FirebaseCall::json() { @@ -162,68 +63,37 @@ const JsonObject& FirebaseCall::json() { return buffer_.get()->parseObject(response().c_str()); } -// FirebaseGet -FirebaseGet::FirebaseGet(const std::string& host, const std::string& auth, - const std::string& path, - const std::shared_ptr http) - : FirebaseCall(host, auth, "GET", path, "", http) { -} - -// FirebaseSet -FirebaseSet::FirebaseSet(const std::string& host, const std::string& auth, - const std::string& path, const std::string& value, - const std::shared_ptr http) - : FirebaseCall(host, auth, "PUT", path, value, http) { - if (!error()) { - // TODO: parse json - json_ = response(); - } -} - -// FirebasePush -FirebasePush::FirebasePush(const std::string& host, const std::string& auth, - const std::string& path, const std::string& value, - const std::shared_ptr http) - : FirebaseCall(host, auth, "POST", path, value, http) { - if (!error()) { - name_ = json()["name"].as(); - } -} - -// FirebaseRemove -FirebaseRemove::FirebaseRemove(const std::string& host, const std::string& auth, - const std::string& path, - const std::shared_ptr http) - : FirebaseCall(host, auth, "DELETE", path, "", http) { +// FirebaseRequest +int FirebaseRequest::sendRequest( + const std::string& host, const std::string& auth, + char* method, const std::string& path, const std::string& data) { + std::string path_with_auth = makeFirebaseURL(path, auth); + http_->setReuseConnection(true); + http_->begin(host, path_with_auth); + int status = http_->sendRequest(method, data); + analyzeError(method, status, path_with_auth); + response_ = http_->getString(); } // FirebaseStream -FirebaseStream::FirebaseStream(const std::string& host, const std::string& auth, - const std::string& path, - const std::shared_ptr http) - : FirebaseCall(host, auth, "STREAM", path, "", http) { -} +void FirebaseStream::startStreaming(const std::string& host, const std::string& auth, const std::string& path) { + std::string path_with_auth = makeFirebaseURL(path, auth); + http_->setReuseConnection(true); + http_->begin(host, path_with_auth); -bool FirebaseStream::available() { - auto client = http_->getStreamPtr(); - return (client == nullptr) ? false : client->available(); -} + http_->addHeader("Accept", "text/event-stream"); + const char* headers[] = {"Location"}; + http_->collectHeaders(headers, 1); + + int status = http_->sendRequest("GET", ""); + analyzeError("STREAM", status, path_with_auth); -FirebaseStream::Event FirebaseStream::read(std::string& event) { - auto client = http_->getStreamPtr(); - if (client == nullptr) { - return Event(); - } - Event type; - std::string typeStr = client->readStringUntil('\n').substring(7).c_str(); - if (typeStr == "put") { - type = Event::PUT; - } else if (typeStr == "patch") { - type = Event::PATCH; - } else { - type = Event::UNKNOWN; + while (status == HttpStatus::TEMPORARY_REDIRECT) { + std::string location = http_->header("Location"); + http_->setReuseConnection(false); + http_->end(); + http_->setReuseConnection(true); + http_->begin(location); + status = http_->sendRequest("GET", std::string()); } - event = client->readStringUntil('\n').substring(6).c_str(); - client->readStringUntil('\n'); // consume separator - return type; } diff --git a/src/Firebase.h b/src/Firebase.h index f0943f12..44450557 100644 --- a/src/Firebase.h +++ b/src/Firebase.h @@ -29,12 +29,6 @@ #include "FirebaseError.h" #include "FirebaseObject.h" -class FirebaseGet; -class FirebaseSet; -class FirebasePush; -class FirebaseRemove; -class FirebaseStream; - // Firebase REST API client. class Firebase { public: @@ -43,24 +37,19 @@ class Firebase { const std::string& auth() const; // Fetch json encoded `value` at `path`. - FirebaseGet get(const std::string& path); - virtual std::unique_ptr getPtr(const std::string& path); + void get(const std::string& path); // Set json encoded `value` at `path`. - FirebaseSet set(const std::string& path, const std::string& json); - virtual std::unique_ptr setPtr(const std::string& path, const std::string& json); + void set(const std::string& path, const std::string& json); // Add new json encoded `value` to list at `path`. - FirebasePush push(const std::string& path, const std::string& json); - virtual std::unique_ptr pushPtr(const std::string& path, const std::string& json); + void push(const std::string& path, const std::string& json); // Delete value at `path`. - FirebaseRemove remove(const std::string& path); - virtual std::unique_ptr removePtr(const std::string& path); + void remove(const std::string& path); // Start a stream of events that affect value at `path`. - FirebaseStream stream(const std::string& path); - virtual std::unique_ptr streamPtr(const std::string& path); + void stream(const std::string& path); protected: // Used for testing. @@ -72,20 +61,19 @@ class Firebase { std::string auth_; }; + class FirebaseCall { public: - FirebaseCall() {} - FirebaseCall(const std::string& host, const std::string& auth, - const char* method, const std::string& path, - const std::string& data = "", - const std::shared_ptr http = NULL); + FirebaseCall(const std::shared_ptr http = NULL) : http_(http) {} virtual ~FirebaseCall(); - virtual const FirebaseError& error() const { + const FirebaseError& error() const { return error_; } - virtual const std::string& response() const { + void analyzeError(char* method, int status, const std::string & path_with_auth); + + const std::string& response() const { return response_; } @@ -98,89 +86,20 @@ class FirebaseCall { std::shared_ptr> buffer_; }; -class FirebaseGet : public FirebaseCall { - public: - FirebaseGet() {} - FirebaseGet(const std::string& host, const std::string& auth, - const std::string& path, const std::shared_ptr http = NULL); - - private: - std::string json_; -}; - -class FirebaseSet: public FirebaseCall { - public: - FirebaseSet() {} - FirebaseSet(const std::string& host, const std::string& auth, - const std::string& path, const std::string& value, const std::shared_ptr http = NULL); - - - private: - std::string json_; +class FirebaseRequest : public FirebaseCall { + public: + FirebaseRequest(const std::shared_ptr http = NULL) : FirebaseCall(http) { } + virtual ~FirebaseRequest() {} + int sendRequest(const std::string& host, const std::string& auth, + char* method, const std::string& path, const std::string& data = ""); }; -class FirebasePush : public FirebaseCall { - public: - FirebasePush() {} - FirebasePush(const std::string& host, const std::string& auth, - const std::string& path, const std::string& value, const std::shared_ptr http = NULL); - virtual ~FirebasePush() {} - - virtual const std::string& name() const { - return name_; - } - - private: - std::string name_; -}; - -class FirebaseRemove : public FirebaseCall { - public: - FirebaseRemove() {} - FirebaseRemove(const std::string& host, const std::string& auth, - const std::string& path, const std::shared_ptr http = NULL); -}; - - class FirebaseStream : public FirebaseCall { public: - FirebaseStream() {} - FirebaseStream(const std::string& host, const std::string& auth, - const std::string& path, const std::shared_ptr http = NULL); + FirebaseStream(const std::shared_ptr http = NULL) : FirebaseCall(http) { } virtual ~FirebaseStream() {} - // Return if there is any event available to read. - virtual bool available(); - - // Event type. - enum Event { - UNKNOWN, - PUT, - PATCH - }; - - static inline std::string EventToName(Event event) { - switch(event) { - case UNKNOWN: - return "UNKNOWN"; - case PUT: - return "PUT"; - case PATCH: - return "PATCH"; - default: - return "INVALID_EVENT_" + event; - } - } - - // Read next json encoded `event` from stream. - virtual Event read(std::string& event); - - const FirebaseError& error() const { - return _error; - } - - private: - FirebaseError _error; + void startStreaming(const std::string& host, const std::string& auth, const std::string& path); }; #endif // firebase_h diff --git a/src/FirebaseArduino.cpp b/src/FirebaseArduino.cpp index d2c9ed8a..4ab93f0e 100644 --- a/src/FirebaseArduino.cpp +++ b/src/FirebaseArduino.cpp @@ -20,12 +20,26 @@ template class std::basic_string; void FirebaseArduino::begin(const String& host, const String& auth) { - http_.reset(FirebaseHttpClient::create()); - http_->setReuseConnection(true); host_ = host.c_str(); auth_ = auth.c_str(); } +void FirebaseArduino::initStream() { + if (stream_http_.get() == nullptr) { + stream_http_.reset(FirebaseHttpClient::create()); + stream_http_->setReuseConnection(true); + stream_.reset(new FirebaseStream(stream_http_)); + } +} + +void FirebaseArduino::initRequest() { + if (req_http_.get() == nullptr) { + req_http_.reset(FirebaseHttpClient::create()); + req_http_->setReuseConnection(true); + req_.reset(new FirebaseRequest(req_http_)); + } +} + String FirebaseArduino::pushInt(const String& path, int value) { return push(path, value); } @@ -44,11 +58,15 @@ String FirebaseArduino::pushString(const String& path, const String& value) { } String FirebaseArduino::push(const String& path, const JsonVariant& value) { - String buf; - value.printTo(buf); - auto push = FirebasePush(host_, auth_, path.c_str(), buf.c_str(), http_); - error_ = push.error(); - return push.name().c_str(); + int size = value.measureLength()+1; + char * buf = new char[size]; + value.printTo(buf, size); + initRequest(); + int status = req_.get()->sendRequest(host_, auth_, "POST", path.c_str(), buf); + error_ = req_.get()->error(); + const char* name = req_.get()->json()["name"].as(); + delete buf; + return name; } void FirebaseArduino::setInt(const String& path, int value) { @@ -69,82 +87,94 @@ void FirebaseArduino::setString(const String& path, const String& value) { } void FirebaseArduino::set(const String& path, const JsonVariant& value) { - String buf; - value.printTo(buf); - auto set = FirebaseSet(host_, auth_, path.c_str(), buf.c_str(), http_); - error_ = set.error(); + int size = value.measureLength()+1; + char* buf= new char[size]; + value.printTo(buf, size); + initRequest(); + req_.get()->sendRequest(host_, auth_, "PUT", path.c_str(), buf); + error_ = req_.get()->error(); + delete buf; +} + +void FirebaseArduino::getRequest(const String& path) { + initRequest(); + req_.get()->sendRequest(host_, auth_, "GET", path.c_str()); + error_ = req_.get()->error(); } FirebaseObject FirebaseArduino::get(const String& path) { - auto get = FirebaseGet(host_, auth_, path.c_str(), http_); - error_ = get.error(); + getRequest(path); if (failed()) { return FirebaseObject{""}; } - return FirebaseObject(get.response().c_str()); + return FirebaseObject(req_.get()->response().c_str()); } int FirebaseArduino::getInt(const String& path) { - auto get = FirebaseGet(host_, auth_, path.c_str(), http_); - error_ = get.error(); + getRequest(path); if (failed()) { return 0; } - return FirebaseObject(get.response().c_str()).getInt(); + return FirebaseObject(req_.get()->response().c_str()).getInt(); } float FirebaseArduino::getFloat(const String& path) { - auto get = FirebaseGet(host_, auth_, path.c_str(), http_); - error_ = get.error(); + getRequest(path); if (failed()) { return 0.0f; } - return FirebaseObject(get.response().c_str()).getFloat(); + return FirebaseObject(req_.get()->response().c_str()).getFloat(); } String FirebaseArduino::getString(const String& path) { - auto get = FirebaseGet(host_, auth_, path.c_str(), http_); - error_ = get.error(); + getRequest(path); if (failed()) { return ""; } - return FirebaseObject(get.response().c_str()).getString(); + return FirebaseObject(req_.get()->response().c_str()).getString(); } bool FirebaseArduino::getBool(const String& path) { - auto get = FirebaseGet(host_, auth_, path.c_str(), http_); - error_ = get.error(); + getRequest(path); if (failed()) { return ""; } - return FirebaseObject(get.response().c_str()).getBool(); + return FirebaseObject(req_.get()->response().c_str()).getBool(); } void FirebaseArduino::remove(const String& path) { - auto remove = FirebaseRemove(host_, auth_, path.c_str(), http_); - error_ = remove.error(); + initRequest(); + req_.get()->sendRequest(host_, auth_, "DELETE", path.c_str()); + error_ = req_.get()->error(); } void FirebaseArduino::stream(const String& path) { - auto stream = FirebaseStream(host_, auth_, path.c_str(), http_); - error_ = stream.error(); + initStream(); + stream_.get()->startStreaming(host_, auth_, path.c_str()); + error_ = stream_.get()->error(); } bool FirebaseArduino::available() { - auto client = http_->getStreamPtr(); + if (stream_http_.get() == nullptr) { + return 0; + } + auto client = stream_http_.get()->getStreamPtr(); return (client == nullptr) ? false : client->available(); } FirebaseObject FirebaseArduino::readEvent() { - auto client = http_->getStreamPtr(); - if (client == nullptr) { + if (stream_http_.get() == nullptr) { + return FirebaseObject(""); + } + auto client = stream_http_.get()->getStreamPtr(); + if (client == nullptr) { return FirebaseObject(""); - } + } String type = client->readStringUntil('\n').substring(7);; String event = client->readStringUntil('\n').substring(6); client->readStringUntil('\n'); // consume separator FirebaseObject obj = FirebaseObject(event.c_str()); - obj.getJsonVariant().asObject()["type"] = type; + obj.getJsonVariant().asObject()["type"] = type.c_str(); return obj; } diff --git a/src/FirebaseArduino.h b/src/FirebaseArduino.h index 4d962b1b..e2f264e1 100644 --- a/src/FirebaseArduino.h +++ b/src/FirebaseArduino.h @@ -37,7 +37,7 @@ class FirebaseArduino { * \param host Your firebase db host, usually X.firebaseio.com. * \param auth Optional credentials for the db, a secret or token. */ - void begin(const String& host, const String& auth = ""); + virtual void begin(const String& host, const String& auth = ""); /** * Appends the integer value to the node at path. @@ -77,7 +77,7 @@ class FirebaseArduino { * \param value String value that you wish to append to the node. * \return The unique key of the new child node. */ - String pushString(const String& path, const String& value); + virtual String pushString(const String& path, const String& value); /** * Appends the JSON data to the node at path. @@ -123,7 +123,7 @@ class FirebaseArduino { * \param path The path inside of your db to the node you wish to update. * \param value String value that you wish to write. */ - void setString(const String& path, const String& value); + virtual void setString(const String& path, const String& value); /** * Writes the JSON data to the node located at path. @@ -157,7 +157,7 @@ class FirebaseArduino { * \param path The path to the node you wish to retrieve. * \return The string value located at that path. Will only be populated if success() is true. */ - String getString(const String& path); + virtual String getString(const String& path); /** * Gets the boolean value located at path. @@ -181,7 +181,7 @@ class FirebaseArduino { * \param path The path to the node you wish to remove, * including all of its children. */ - void remove(const String& path); + virtual void remove(const String& path); /** * Starts streaming any changes made to the node located at path, including @@ -191,14 +191,14 @@ class FirebaseArduino { * monitoring available() and calling readEvent() to get new events. * \param path The path inside of your db to the node you wish to monitor. */ - void stream(const String& path); + virtual void stream(const String& path); /** * Checks if there are new events available. This is only meaningful once * stream() has been called. * \return If a new event is ready. */ - bool available(); + virtual bool available(); /** * Reads the next event in a stream. This is only meaningful once stream() has @@ -206,7 +206,7 @@ class FirebaseArduino { * \return FirebaseObject will have ["type"] that describes the event type, ["path"] * that describes the effected path and ["data"] that was updated. */ - FirebaseObject readEvent(); + virtual FirebaseObject readEvent(); /** * \return Whether the last command was successful. @@ -221,12 +221,19 @@ class FirebaseArduino { /** * \return Error message from last command if failed() is true. */ - const String& error(); + virtual const String& error(); private: std::string host_; std::string auth_; FirebaseError error_; - std::shared_ptr http_; + std::shared_ptr req_http_; + std::shared_ptr req_; + std::shared_ptr stream_http_; + std::shared_ptr stream_; + + void initStream(); + void initRequest(); + void getRequest(const String& path); }; extern FirebaseArduino Firebase; diff --git a/src/FirebaseHttpClient.h b/src/FirebaseHttpClient.h index 1752ba2f..055699c7 100644 --- a/src/FirebaseHttpClient.h +++ b/src/FirebaseHttpClient.h @@ -33,18 +33,7 @@ class FirebaseHttpClient { virtual std::string errorToString(int error_code) = 0; - bool isStreaming() const { - return _streaming != ""; - } - std::string getStreamingPath() const { - return _streaming; - } - void setStreaming(const std::string& path) { - _streaming = path; - } protected: - std::string _streaming = ""; - static const uint16_t kFirebasePort = 443; };