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

Commit 7d476b8

Browse files
committed
Merge pull request #136 from proppy/firebase-object
FirebaseObject: simplify API
2 parents a516bb2 + e4898ed commit 7d476b8

File tree

8 files changed

+269
-100
lines changed

8 files changed

+269
-100
lines changed

examples/FirebaseDemo_ESP8266/FirebaseDemo_ESP8266.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ void loop() {
5656

5757
// get value
5858
Serial.print("number: ");
59-
Serial.println((float)Firebase.get("number"));
59+
Serial.println(Firebase.getFloat("number"));
6060
delay(1000);
6161

6262
// remove value

examples/FirebaseRoom_ESP8266/FirebaseRoom_ESP8266.ino

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,24 @@
2020
#include <ESP8266WiFi.h>
2121
#include <FirebaseArduino.h>
2222

23-
const int pinGrove = 15;
24-
const int pinVibrator = 5;
25-
const int pinLightSensor = A0;
26-
const int pinLed = 12;
27-
const int pinButton = 14;
28-
const int pinFan = 13;
23+
const int grovePowerPin = 15;
24+
const int vibratorPin = 5;
25+
const int lightSensorPin = A0;
26+
const int ledPin = 12;
27+
const int buttonPin = 14;
28+
const int fanPin = 13;
2929

3030
void setup() {
3131
Serial.begin(9600);
3232

33-
pinMode(pinGrove, OUTPUT);
34-
digitalWrite(pinGrove, HIGH);
33+
pinMode(grovePowerPin, OUTPUT);
34+
digitalWrite(grovePowerPin, HIGH);
3535

36-
pinMode(pinVibrator, OUTPUT);
37-
pinMode(pinLightSensor, INPUT);
38-
pinMode(pinLed, OUTPUT);
39-
pinMode(pinButton, INPUT);
40-
pinMode(pinFan, OUTPUT);
36+
pinMode(vibratorPin, OUTPUT);
37+
pinMode(lightSensorPin, INPUT);
38+
pinMode(ledPin, OUTPUT);
39+
pinMode(buttonPin, INPUT);
40+
pinMode(fanPin, OUTPUT);
4141

4242
// connect to wifi.
4343
WiFi.begin("SSID", "PASSWORD");
@@ -62,15 +62,15 @@ int button = 0;
6262
float light = 0.0;
6363

6464
void loop() {
65-
digitalWrite(pinLed, (int)Firebase.get("redlight"));
66-
digitalWrite(pinFan, (int)Firebase.get("cooldown"));
67-
digitalWrite(pinVibrator, (int)Firebase.get("brrr"));
68-
int newButton = digitalRead(pinButton);
65+
digitalWrite(ledPin, Firebase.getInt("redlight"));
66+
digitalWrite(fanPin, Firebase.getInt("cooldown"));
67+
digitalWrite(vibratorPin, Firebase.getInt("brrr"));
68+
int newButton = digitalRead(buttonPin);
6969
if (newButton != button) {
7070
button = newButton;
7171
Firebase.set("pushbutton", button);
7272
}
73-
float newLight = analogRead(pinLightSensor);
73+
float newLight = analogRead(lightSensorPin);
7474
if (abs(newLight - light) > 100) {
7575
light = newLight;
7676
Firebase.set("sunlight", light);

examples/FirebaseStream_ESP8266/FirebaseStream_ESP8266.ino

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,16 @@ void loop() {
5555

5656
if (Firebase.available()) {
5757
FirebaseObject event = Firebase.readEvent();
58-
String event_type = event["type"];
59-
event_type.toLowerCase();
58+
String eventType = event.getString("type");
59+
eventType.toLowerCase();
6060

6161
Serial.print("event: ");
62-
Serial.println(event_type);
63-
if (event_type == "put") {
62+
Serial.println(eventType);
63+
if (eventType == "put") {
6464
Serial.print("data: ");
65-
Serial.println(event["data"].asString());
66-
String path = event["path"];
67-
float data = event["data"];
65+
Serial.println(event.getString("data"));
66+
String path = event.getString("path");
67+
float data = event.getFloat("data");
6868

6969
display.clearDisplay();
7070
display.setTextSize(2);

src/FirebaseArduino.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,43 @@ FirebaseObject FirebaseArduino::get(const char* path) {
4747
return FirebaseObject(get.response());
4848
}
4949

50+
int FirebaseArduino::getInt(const char* path) {
51+
auto get = FirebaseGet(host_, auth_, path, http_.get());
52+
error_ = get.error();
53+
if (failed()) {
54+
return 0;
55+
}
56+
return FirebaseObject(get.response()).getInt();
57+
}
58+
59+
60+
float FirebaseArduino::getFloat(const char* path) {
61+
auto get = FirebaseGet(host_, auth_, path, http_.get());
62+
error_ = get.error();
63+
if (failed()) {
64+
return 0.0f;
65+
}
66+
return FirebaseObject(get.response()).getFloat();
67+
}
68+
69+
String FirebaseArduino::getString(const char* path) {
70+
auto get = FirebaseGet(host_, auth_, path, http_.get());
71+
error_ = get.error();
72+
if (failed()) {
73+
return "";
74+
}
75+
return FirebaseObject(get.response()).getString();
76+
}
77+
78+
bool FirebaseArduino::getBool(const char* path) {
79+
auto get = FirebaseGet(host_, auth_, path, http_.get());
80+
error_ = get.error();
81+
if (failed()) {
82+
return "";
83+
}
84+
return FirebaseObject(get.response()).getBool();
85+
}
86+
5087
void FirebaseArduino::remove(const char* path) {
5188
auto remove = FirebaseRemove(host_, auth_, path, http_.get());
5289
error_ = remove.error();
@@ -67,7 +104,7 @@ FirebaseObject FirebaseArduino::readEvent() {
67104
String event = client->readStringUntil('\n').substring(6);
68105
client->readStringUntil('\n'); // consume separator
69106
FirebaseObject obj = FirebaseObject(event);
70-
obj["type"] = type;
107+
obj.getJsonVariant().asObject()["type"] = type;
71108
return obj;
72109
}
73110

src/FirebaseArduino.h

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,42 @@ class FirebaseArduino {
5858

5959

6060
/**
61-
* Gets the value located at path.
61+
* Gets the integer value located at path.
6262
* You should check success() after calling.
6363
* \param path The path to the node you wish to retrieve.
64-
* \return The data located at that path. This may either be a single element
65-
* or it may be a json structure. Will only be populated if success() is true.
64+
* \return The integer value located at that path. Will only be populated if success() is true.
65+
*/
66+
int getInt(const char* path);
67+
68+
/**
69+
* Gets the float value located at path.
70+
* You should check success() after calling.
71+
* \param path The path to the node you wish to retrieve.
72+
* \return The float value located at that path. Will only be populated if success() is true.
73+
*/
74+
float getFloat(const char* path);
75+
76+
/**
77+
* Gets the string value located at path.
78+
* You should check success() after calling.
79+
* \param path The path to the node you wish to retrieve.
80+
* \return The string value located at that path. Will only be populated if success() is true.
81+
*/
82+
String getString(const char* path);
83+
84+
/**
85+
* Gets the boolean value located at path.
86+
* You should check success() after calling.
87+
* \param path The path to the node you wish to retrieve.
88+
* \return The boolean value located at that path. Will only be populated if success() is true.
89+
*/
90+
bool getBool(const char* path);
91+
92+
/**
93+
* Gets the json object value located at path.
94+
* You should check success() after calling.
95+
* \param path The path to the node you wish to retrieve.
96+
* \return a FirebaseObject value located at that path. Will only be populated if success() is true.
6697
*/
6798
FirebaseObject get(const char* path);
6899

@@ -94,7 +125,7 @@ class FirebaseArduino {
94125
/**
95126
* Reads the next event in a stream. This is only meaningful once stream() has
96127
* been called.
97-
* \return Object will have ["type"] that describes the event type, ["path"]
128+
* \return FirebaseObject will have ["type"] that describes the event type, ["path"]
98129
* that describes the effected path and ["data"] that was updated.
99130
*/
100131
FirebaseObject readEvent();

src/FirebaseObject.cpp

Lines changed: 60 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -16,57 +16,81 @@
1616

1717
#include "FirebaseObject.h"
1818

19-
namespace {
20-
template<typename T>
21-
T decodeJsonLiteral(const String& json) {
22-
return JsonVariant{ArduinoJson::RawJson{json.c_str()}};
23-
}
24-
25-
// ugly workaround to https://github.com/bblanchon/ArduinoJson/issues/265
26-
template<>
27-
String decodeJsonLiteral<String>(const String& json) {
28-
StaticJsonBuffer<JSON_ARRAY_SIZE(1)> buf;
29-
String array = "[" + json + "]";
30-
return buf.parseArray(&array[0])[0];
31-
}
32-
} // namespace
33-
3419
FirebaseObject::FirebaseObject(const String& data) : data_{data} {
35-
if (data_[0] == '{') {
36-
json_ = &buffer_.parseObject(&data_[0]);
37-
} else if (data_[0] == '"') {
38-
data_ = decodeJsonLiteral<String>(data_);
39-
}
20+
json_ = buffer_.parse(&data_[0]);
21+
// TODO(proppy): find a way to check decoding error, tricky because
22+
// ArduinoJson doesn't surface error for variant parsing.
23+
// See: https://github.com/bblanchon/ArduinoJson/issues/279
4024
}
4125

42-
FirebaseObject::operator bool() {
43-
return decodeJsonLiteral<bool>(data_);
26+
bool FirebaseObject::getBool(const String& path) {
27+
JsonVariant variant = getJsonVariant(path);
28+
if (!variant.is<bool>()) {
29+
error_ = "failed to convert to bool";
30+
return 0;
31+
}
32+
return static_cast<bool>(variant);
4433
}
4534

46-
FirebaseObject::operator int() {
47-
return decodeJsonLiteral<int>(data_);
35+
int FirebaseObject::getInt(const String& path) {
36+
JsonVariant variant = getJsonVariant(path);
37+
if (!variant.is<int>()) {
38+
error_ = "failed to convert to int";
39+
return 0;
40+
}
41+
return static_cast<int>(variant);
4842
}
4943

50-
FirebaseObject::operator float() {
51-
return decodeJsonLiteral<float>(data_);
44+
float FirebaseObject::getFloat(const String& path) {
45+
JsonVariant variant = getJsonVariant(path);
46+
if (!variant.is<float>()) {
47+
error_ = "failed to convert to float";
48+
return 0;
49+
}
50+
return static_cast<float>(variant);
5251
}
5352

54-
FirebaseObject::operator const String&() {
55-
return data_;
53+
String FirebaseObject::getString(const String& path) {
54+
JsonVariant variant = getJsonVariant(path);
55+
if (!variant.is<const char *>()) {
56+
error_ = "failed to convert to string";
57+
return "";
58+
}
59+
return static_cast<const char*>(variant);
5660
}
5761

58-
FirebaseObject::operator const JsonObject&() {
59-
return *json_;
62+
JsonVariant FirebaseObject::getJsonVariant(const String& path) {
63+
String key(path);
64+
char* start = &key[0];
65+
char* end = start + key.length();
66+
// skip first `/`.
67+
if (*start == '/') {
68+
start++;
69+
}
70+
JsonVariant json = json_;
71+
while (start < end) {
72+
// TODO(proppy) split in a separate function.
73+
char* p = start;
74+
// advance to next `/`.
75+
while (*p && (*p != '/')) p++;
76+
// make `start` a C string.
77+
*p = 0;
78+
// return json variant at `start`.
79+
json = json.asObject().get(start);
80+
// advance to next path element.
81+
start = p + 1;
82+
}
83+
return json;
6084
}
6185

62-
JsonObjectSubscript<const char*> FirebaseObject::operator[](const char* key) {
63-
return json_->operator[](key);
86+
bool FirebaseObject::failed() const {
87+
return error_.length() > 0;
6488
}
6589

66-
JsonObjectSubscript<const String&> FirebaseObject::operator[](const String& key) {
67-
return json_->operator[](key);
90+
bool FirebaseObject::success() const {
91+
return error_.length() == 0;
6892
}
6993

70-
JsonVariant FirebaseObject::operator[](JsonObjectKey key) const {
71-
return json_->operator[](key);
94+
const String& FirebaseObject::error() const {
95+
return error_;
7296
}

0 commit comments

Comments
 (0)