From 84df631c35fbf1126b0f97fc12ec62b110d685ce Mon Sep 17 00:00:00 2001 From: Johan Euphrosine Date: Wed, 27 Apr 2016 00:08:13 -0700 Subject: [PATCH 1/5] FirebaseArduino: simpler Arduino wrapper Fixes: #95 Replaces: #80 #81 --- .travis.yml | 2 + .../FirebasePush_ESP8266.ino | 35 +++----- src/FirebaseArduino.cpp | 86 +++++++++++++++++++ src/FirebaseArduino.h | 49 +++++++++++ src/FirebaseObject.cpp | 72 ++++++++++++++++ src/FirebaseObject.h | 41 +++++++++ test/FirebaseArduino_test.cpp | 43 ++++++++++ test/Makefile | 54 ++++++++++++ 8 files changed, 358 insertions(+), 24 deletions(-) create mode 100644 src/FirebaseArduino.cpp create mode 100644 src/FirebaseArduino.h create mode 100644 src/FirebaseObject.cpp create mode 100644 src/FirebaseObject.h create mode 100644 test/FirebaseArduino_test.cpp create mode 100644 test/Makefile diff --git a/.travis.yml b/.travis.yml index f7e7ec9a..d64c3442 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,3 +13,5 @@ before_script: - ( cd ${ARDUINO_HOME}/libraries && ln -s ${TRAVIS_BUILD_DIR} firebase-arduino && ln -s ${TRAVIS_BUILD_DIR}/src/third-party/arduino-json-5.2 ArduinoJson ) script: - ${ARDUINO_ROOT}/arduino-builder -verbose -hardware ${ARDUINO_ROOT}/hardware/ -tools ${ARDUINO_ESP8266_ROOT}/tools/ -tools ${ARDUINO_ROOT}/tools-builder/ -fqbn esp8266com:esp8266:nodemcuv2 -libraries ${ARDUINO_HOME}/libraries/ -prefs build.flash_ld=${ARDUINO_ESP8266_ROOT}/tools/sdk/ld/eagle.flash.4m.ld -prefs build.flash_freq=40 -prefs build.flash_size=4M examples/FirebasePush_ESP8266/FirebasePush_ESP8266.ino +- cd test && make check + diff --git a/examples/FirebasePush_ESP8266/FirebasePush_ESP8266.ino b/examples/FirebasePush_ESP8266/FirebasePush_ESP8266.ino index c4ae78df..0c676954 100644 --- a/examples/FirebasePush_ESP8266/FirebasePush_ESP8266.ino +++ b/examples/FirebasePush_ESP8266/FirebasePush_ESP8266.ino @@ -19,10 +19,7 @@ #include -#include - -// create firebase client. -Firebase fbase("example.firebaseio.com", "secret_or_token"); +#include void setup() { Serial.begin(9600); @@ -37,28 +34,18 @@ void setup() { Serial.println(); Serial.print("connected: "); Serial.println(WiFi.localIP()); - - // add a new entry. - FirebasePush push = fbase.push("/logs", "{\".sv\": \"timestamp\"}"); - if (push.error()) { - Serial.println("Firebase push failed"); - Serial.println(push.error().message()); - return; - } - - // print key. - Serial.println("Name: " + push.name()); - - // get all entries. - FirebaseGet get = fbase.get("/logs"); - if (get.error()) { - Serial.println("Firebase get failed"); - Serial.println(push.error().message()); + + Firebase.begin("example.firebaseio.com", "auth_or_token"); + + // add a new entry. + String name = Firebase.push("/logs", "{\".sv\": \"timestamp\"}"); + if (Firebase.failed()) { + Serial.println(" push failed"); + Serial.println(Firebase.error()); return; } - // Print written timestamp. - String data = get.json()[push.name()]; - Serial.println("Timestamp:" + data); + Serial.print("pushed: "); + Serial.println(name); } void loop() { diff --git a/src/FirebaseArduino.cpp b/src/FirebaseArduino.cpp new file mode 100644 index 00000000..fd55e15d --- /dev/null +++ b/src/FirebaseArduino.cpp @@ -0,0 +1,86 @@ +// +// Copyright 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include "FirebaseArduino.h" + +void FirebaseArduino::begin(const char* host, const char* auth) { + http_.reset(FirebaseHttpClient::create()); + http_->setReuseConnection(true); + host_ = host; + auth_ = auth; +} + +String FirebaseArduino::FirebaseArduino::push(const String& path, const JsonVariant& value) { + String buf; + value.printTo(buf); + auto push = FirebasePush(host_, auth_, path, buf, http_.get()); + error_ = push.error(); + return push.name(); +} + +void FirebaseArduino::set(const String& path, const JsonVariant& value) { + String buf; + value.printTo(buf); + auto set = FirebaseSet(host_, auth_, path, buf, http_.get()); + error_ = set.error(); +} + +FirebaseObject FirebaseArduino::get(const char* path) { + auto get = FirebaseGet(host_, auth_, path, http_.get()); + error_ = get.error(); + if (!error_) { + return FirebaseObject{""}; + } + return FirebaseObject(get.response()); +} + +void FirebaseArduino::remove(const char* path) { + auto remove = FirebaseRemove(host_, auth_, path, http_.get()); + error_ = remove.error(); +} + +void FirebaseArduino::stream(const char* path) { + auto stream = FirebaseStream(host_, auth_, path, http_.get()); + error_ = stream.error(); +} + +bool FirebaseArduino::available() { + return http_->getStreamPtr()->available(); +} + +FirebaseObject FirebaseArduino::readEvent() { + auto client = http_->getStreamPtr(); + String type = client->readStringUntil('\n').substring(7);; + String event = client->readStringUntil('\n').substring(6); + client->readStringUntil('\n'); // consume separator + FirebaseObject obj = FirebaseObject(event); + obj["type"] = type; + return obj; +} + +bool FirebaseArduino::success() { + return error_; +} + +bool FirebaseArduino::failed() { + return !error_; +} + +const String& FirebaseArduino::error() { + return error_.message(); +} + +FirebaseArduino Firebase; diff --git a/src/FirebaseArduino.h b/src/FirebaseArduino.h new file mode 100644 index 00000000..c22b7594 --- /dev/null +++ b/src/FirebaseArduino.h @@ -0,0 +1,49 @@ +// +// Copyright 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef FIREBASE_ARDUINO_H +#define FIREBASE_ARDUINO_H + +#include "Firebase.h" +#include "FirebaseObject.h" + +#ifndef FIREBASE_JSONBUFFER_SIZE +#define FIREBASE_JSONBUFFER_SIZE 200 +#endif // FIREBASE_JSONBUFFER_SIZE + +class FirebaseArduino { + public: + void begin(const char* host, const char* auth = ""); + String push(const String& path, const JsonVariant& value); + void set(const String& path, const JsonVariant& value); + FirebaseObject get(const char* path); + void remove(const char* path); + void stream(const char* path); + bool available(); + FirebaseObject readEvent(); + bool success(); + bool failed(); + const String& error(); + private: + String host_; + String auth_; + FirebaseError error_; + std::unique_ptr http_; +}; + +extern FirebaseArduino Firebase; + +#endif // FIREBASE_ARDUINO_H diff --git a/src/FirebaseObject.cpp b/src/FirebaseObject.cpp new file mode 100644 index 00000000..a9745690 --- /dev/null +++ b/src/FirebaseObject.cpp @@ -0,0 +1,72 @@ +// +// Copyright 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include "FirebaseObject.h" + +namespace { +template +T decodeJsonLiteral(const String& json) { + return JsonVariant{ArduinoJson::RawJson{json.c_str()}}; +} + +// ugly workaround to https://github.com/bblanchon/ArduinoJson/issues/265 +template<> +String decodeJsonLiteral(const String& json) { + StaticJsonBuffer buf; + String array = "[" + json + "]"; + return buf.parseArray(&array[0])[0]; +} +} // namespace + +FirebaseObject::FirebaseObject(const String& data) : data_{data} { + if (data_[0] == '{') { + json_ = &buffer_.parseObject(&data_[0]); + } else if (data_[0] == '"') { + data_ = decodeJsonLiteral(data_); + } +} + +FirebaseObject::operator bool() { + return decodeJsonLiteral(data_); +} + +FirebaseObject::operator int() { + return decodeJsonLiteral(data_); +} + +FirebaseObject::operator float() { + return decodeJsonLiteral(data_); +} + +FirebaseObject::operator const String&() { + return data_; +} + +FirebaseObject::operator const JsonObject&() { + return *json_; +} + +JsonObjectSubscript FirebaseObject::operator[](const char* key) { + return json_->operator[](key); +} + +JsonObjectSubscript FirebaseObject::operator[](const String& key) { + return json_->operator[](key); +} + +JsonVariant FirebaseObject::operator[](JsonObjectKey key) const { + return json_->operator[](key); +} diff --git a/src/FirebaseObject.h b/src/FirebaseObject.h new file mode 100644 index 00000000..b8b4261d --- /dev/null +++ b/src/FirebaseObject.h @@ -0,0 +1,41 @@ +// +// Copyright 2015 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef FIREBASE_OBJECT_H +#define FIREBASE_OBJECT_H + +#include "third-party/arduino-json-5.2/include/ArduinoJson.h" + +#define FIREBASE_JSONBUFFER_SIZE 200 + +class FirebaseObject { + public: + FirebaseObject(const String& data); + operator bool(); + operator int(); + operator float(); + operator const String&(); + operator const JsonObject&(); + JsonObjectSubscript operator[](const char* key); + JsonObjectSubscript operator[](const String& key); + JsonVariant operator[](JsonObjectKey key) const; + private: + String data_; + StaticJsonBuffer buffer_; + JsonObject* json_; +}; + +#endif // FIREBASE_OBJECT_H diff --git a/test/FirebaseArduino_test.cpp b/test/FirebaseArduino_test.cpp new file mode 100644 index 00000000..97e4bebe --- /dev/null +++ b/test/FirebaseArduino_test.cpp @@ -0,0 +1,43 @@ +// +// Copyright 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include "FirebaseObject.h" +#include "gtest/gtest.h" + +TEST(FirebaseObjectTest, JsonLiteral) { + EXPECT_EQ(bool(FirebaseObject("true")), true); + EXPECT_EQ(bool(FirebaseObject("false")), false); + EXPECT_EQ(int(FirebaseObject("42")), 42); + EXPECT_EQ(float(FirebaseObject("43.0")), 43.0); + EXPECT_EQ(String(FirebaseObject("\"foo\"")), "foo"); +} + +TEST(FirebaseObjectTest, JsonObject) { + { + const JsonObject& obj = FirebaseObject("{\"foo\":\"bar\"}"); + String foo = obj["foo"]; + EXPECT_EQ(foo, "bar"); + } + { + String foo = FirebaseObject("{\"foo\":\"bar\"}")["foo"]; + EXPECT_EQ(foo, "bar"); + } +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 00000000..6461c30d --- /dev/null +++ b/test/Makefile @@ -0,0 +1,54 @@ +# +# Copyright 2016 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +FIREBASE_DIR=.. +GTEST_DIR=googletest/googletest +ARDUINOJSON_DIR=../src/third-party/arduino-json-5.2 + +FIREBASE_SRCS=${FIREBASE_DIR}/src/FirebaseObject.cpp +GTEST_SRCS=${GTEST_DIR}/src/gtest-all.cpp +ARDUINOJSON_SRCS=${ARDUINOJSON_DIR}/src/JsonBuffer.cpp\ + ${ARDUINOJSON_DIR}/src/JsonObject.cpp\ + ${ARDUINOJSON_DIR}/src/Internals/JsonParser.cpp\ + ${ARDUINOJSON_DIR}/src/Internals/Encoding.cpp\ + ${ARDUINOJSON_DIR}/src/Internals/Comments.cpp\ + ${ARDUINOJSON_DIR}/src/Internals/IndentedPrint.cpp\ + ${ARDUINOJSON_DIR}/src/Internals/StaticStringBuilder.cpp\ + ${ARDUINOJSON_DIR}/src/Internals/Prettyfier.cpp\ + ${ARDUINOJSON_DIR}/src/Internals/List.cpp\ + ${ARDUINOJSON_DIR}/src/JsonVariant.cpp\ + ${ARDUINOJSON_DIR}/src/JsonArray.cpp + +SRCS=FirebaseArduino_test.cpp\ + ${FIREBASE_SRCS}\ + ${GTEST_SRCS}\ + ${ARDUINOJSON_SRCS} + +OBJS=${SRCS:.cpp=.o} + +CXXFLAGS=-I../src -Igoogletest/googletest/include -Igoogletest/googletest -std=c++11 +LDFLAGS=-lpthread + +all: check + +firebase-test: ${OBJS} + ${CXX} -o $@ ${OBJS} ${LDFLAGS} + +check: firebase-test + ./firebase-test + +clean: + rm -f ${OBJS} firebase-test From 11b148f2a8964bd743805399cbd4c734d2305b0d Mon Sep 17 00:00:00 2001 From: Johan Euphrosine Date: Wed, 27 Apr 2016 00:13:26 -0700 Subject: [PATCH 2/5] travis: g++-4.8 --- .travis.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d64c3442..b85d7fd4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,11 @@ language: c sudo: false +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-4.8 env: - ARDUINO_VERSION=1.6.8 ARDUINO_ESP8266_VERSION=2.1.0 ARDUINO_ROOT=${HOME}/arduino-${ARDUINO_VERSION} ARDUINO_ESP8266_ROOT=${ARDUINO_ROOT}/hardware/esp8266com/esp8266 ARDUINO_HOME=${HOME}/Arduino - ARDUINO_VERSION=1.6.8 ARDUINO_ESP8266_VERSION=2.2.0-rc1 ARDUINO_ROOT=${HOME}/arduino-${ARDUINO_VERSION} ARDUINO_ESP8266_ROOT=${ARDUINO_ROOT}/hardware/esp8266com/esp8266 ARDUINO_HOME=${HOME}/Arduino @@ -14,4 +20,3 @@ before_script: script: - ${ARDUINO_ROOT}/arduino-builder -verbose -hardware ${ARDUINO_ROOT}/hardware/ -tools ${ARDUINO_ESP8266_ROOT}/tools/ -tools ${ARDUINO_ROOT}/tools-builder/ -fqbn esp8266com:esp8266:nodemcuv2 -libraries ${ARDUINO_HOME}/libraries/ -prefs build.flash_ld=${ARDUINO_ESP8266_ROOT}/tools/sdk/ld/eagle.flash.4m.ld -prefs build.flash_freq=40 -prefs build.flash_size=4M examples/FirebasePush_ESP8266/FirebasePush_ESP8266.ino - cd test && make check - From 2f9b0ca06aee02b19e7dd852369fe8e1dd93baf4 Mon Sep 17 00:00:00 2001 From: Johan Euphrosine Date: Wed, 27 Apr 2016 00:17:47 -0700 Subject: [PATCH 3/5] travis: force CXX to g++-4.8 --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index b85d7fd4..cf3a4628 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,9 +7,9 @@ addons: packages: - g++-4.8 env: -- ARDUINO_VERSION=1.6.8 ARDUINO_ESP8266_VERSION=2.1.0 ARDUINO_ROOT=${HOME}/arduino-${ARDUINO_VERSION} ARDUINO_ESP8266_ROOT=${ARDUINO_ROOT}/hardware/esp8266com/esp8266 ARDUINO_HOME=${HOME}/Arduino -- ARDUINO_VERSION=1.6.8 ARDUINO_ESP8266_VERSION=2.2.0-rc1 ARDUINO_ROOT=${HOME}/arduino-${ARDUINO_VERSION} ARDUINO_ESP8266_ROOT=${ARDUINO_ROOT}/hardware/esp8266com/esp8266 ARDUINO_HOME=${HOME}/Arduino -- ARDUINO_VERSION=nightly ARDUINO_ESP8266_VERSION=master ARDUINO_ROOT=${HOME}/arduino-${ARDUINO_VERSION} ARDUINO_ESP8266_ROOT=${ARDUINO_ROOT}/hardware/esp8266com/esp8266 ARDUINO_HOME=${HOME}/Arduino +- ARDUINO_VERSION=1.6.8 ARDUINO_ESP8266_VERSION=2.1.0 GCC_VERSION=4.8 ARDUINO_ROOT=${HOME}/arduino-${ARDUINO_VERSION} ARDUINO_ESP8266_ROOT=${ARDUINO_ROOT}/hardware/esp8266com/esp8266 ARDUINO_HOME=${HOME}/Arduino CXX=g++-${GCC_VERSION} +- ARDUINO_VERSION=1.6.8 ARDUINO_ESP8266_VERSION=2.2.0-rc1 GCC_VERSION=4.8 ARDUINO_ROOT=${HOME}/arduino-${ARDUINO_VERSION} ARDUINO_ESP8266_ROOT=${ARDUINO_ROOT}/hardware/esp8266com/esp8266 ARDUINO_HOME=${HOME}/Arduino CXX=g++-${GCC_VERSION} +- ARDUINO_VERSION=nightly ARDUINO_ESP8266_VERSION=master GCC_VERSION=4.8 ARDUINO_ROOT=${HOME}/arduino-${ARDUINO_VERSION} ARDUINO_ESP8266_ROOT=${ARDUINO_ROOT}/hardware/esp8266com/esp8266 ARDUINO_HOME=${HOME}/Arduino CXX=g++-${GCC_VERSION} install: - ( cd ${HOME} && curl -O https://downloads.arduino.cc/arduino-${ARDUINO_VERSION}-linux64.tar.xz && tar xvf arduino-${ARDUINO_VERSION}-linux64.tar.xz ) - git clone --branch ${ARDUINO_ESP8266_VERSION} https://github.com/esp8266/Arduino.git ${ARDUINO_ESP8266_ROOT} From be1a7da5ab8abe90b3923984ff33c33838dda09c Mon Sep 17 00:00:00 2001 From: Johan Euphrosine Date: Wed, 27 Apr 2016 14:54:07 -0700 Subject: [PATCH 4/5] FirebaseArduino: fix error check --- src/FirebaseArduino.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/FirebaseArduino.cpp b/src/FirebaseArduino.cpp index fd55e15d..3dd65788 100644 --- a/src/FirebaseArduino.cpp +++ b/src/FirebaseArduino.cpp @@ -72,11 +72,11 @@ FirebaseObject FirebaseArduino::readEvent() { } bool FirebaseArduino::success() { - return error_; + return error_.code() == 0; } bool FirebaseArduino::failed() { - return !error_; + return error_.code() != 0; } const String& FirebaseArduino::error() { From 13ce95139be94a3fda42a02e0445934ca3fee269 Mon Sep 17 00:00:00 2001 From: Johan Euphrosine Date: Wed, 27 Apr 2016 14:54:33 -0700 Subject: [PATCH 5/5] example/FirebasePush: update example to loop --- .../FirebasePush_ESP8266.ino | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/examples/FirebasePush_ESP8266/FirebasePush_ESP8266.ino b/examples/FirebasePush_ESP8266/FirebasePush_ESP8266.ino index 0c676954..34c5eb5c 100644 --- a/examples/FirebasePush_ESP8266/FirebasePush_ESP8266.ino +++ b/examples/FirebasePush_ESP8266/FirebasePush_ESP8266.ino @@ -14,11 +14,10 @@ // limitations under the License. // -// FirebasePush_ESP8266 is a sample that push a new timestamp to firebase -// on each reset. +// FirebasePush_ESP8266 is a sample that push a new value to Firebase +// every seconds. #include - #include void setup() { @@ -36,17 +35,19 @@ void setup() { Serial.println(WiFi.localIP()); Firebase.begin("example.firebaseio.com", "auth_or_token"); +} - // add a new entry. - String name = Firebase.push("/logs", "{\".sv\": \"timestamp\"}"); +int n = 0; + +void loop() { + // push a new value. + String name = Firebase.push("/logs", n++); if (Firebase.failed()) { - Serial.println(" push failed"); + Serial.print("push failed: "); Serial.println(Firebase.error()); return; } Serial.print("pushed: "); Serial.println(name); -} - -void loop() { + delay(1000); }