mobizt / Firebase-Arduino-WiFiNINA

Firebase Arduino Library for ARM/AVR WIFI Dev Boards based on WiFiNINA
MIT License
65 stars 12 forks source link

Firebase PushJSON #6

Closed PSKAdam closed 4 years ago

PSKAdam commented 4 years ago

Hi @mobizt , I have a temperature and humidity sensor testing on an Arduino MKR Wifi 1010 board. I got the sensor values stored as float and would like to pushJSON to Firebase and as mentioned in your Readme, you are using the original ArduinoJson library. However, I keep getting bad request and invalid data type. Could you elaborate further how you push a float data type to Firebase via pushJSON?

The following is my code example:

#include <Wire.h>
#include <Adafruit_AM2315.h>
#define ARDUINOJSON_ENABLE_ARDUINO_STRING_1
#include <ArduinoJson.h>
#include <Firebase_Arduino_WiFiNINA.h>

Adafruit_AM2315 am2315;

float temperature, humidity; // declare sensor data type

#define FIREBASE_HOST "***"
#define FIREBASE_AUTH "***"

#define WIFI_SSID "***"
#define WIFI_PASSWORD "***"

//Define Firebase data object
FirebaseData firebaseData;

// Firebase data path
String path = "/UNO_WiFi_REV2_Test";

void setup() {
  Serial.begin(9600);
  delay(100);

  Serial.print("Connecting to Wi-Fi");
  int status = WL_IDLE_STATUS;
  while (status != WL_CONNECTED)
  {
    status = WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
    Serial.print(".");
    delay(300);
  }
  Serial.println();
  Serial.print("Connected with IP: ");
  Serial.println(WiFi.localIP());
  Serial.println();

  // Provide the authentication data
  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH, WIFI_SSID, WIFI_PASSWORD);
  Firebase.reconnectWiFi(true);

  while (!Serial) {
    delay(10);
  }
  Serial.println("AM2315 Test!");

  if (! am2315.begin()) {
     Serial.println("Sensor not found, check wiring & pullups!");
     while (1);
  }
}

void loop() {

  if (! am2315.readTemperatureAndHumidity(&temperature, &humidity)) {
    Serial.println("Failed to read data from AM2315");
    return;
  }
  Serial.print("Temp *C: "); Serial.println(temperature);
  Serial.print("Hum %: "); Serial.println(humidity);

  FirebasePush(); // push to Firebase database

  delay(3000);
}

// Function to push data to database
void FirebasePush() {

  Serial.println("-----------------------------------");
  Serial.println("----------Begin Push Test----------");
  Serial.println("-----------------------------------");
  Serial.println();

  String json2 = "{\"Temperature\":temperature,\"Humidity\":humidity}";

    if (Firebase.pushJSON(firebaseData, path + "/Sensors/Temp&Humid_Sensors", json2))
    {
      Serial.println("----------Push result-----------");
      Serial.println("PATH: " + firebaseData.dataPath());
      Serial.print("PUSH NAME: ");
      Serial.println(firebaseData.pushName());
      Serial.println("--------------------------------");
      Serial.println();
    }
    else
    {
      Serial.println("----------Can't push data--------");
      Serial.println("REASON: " + firebaseData.errorReason());
      Serial.println("--------------------------------");
      Serial.println();
    }
}

Please advise if I am parsing the data into the String json2 in the wrong way. Very much appreciated :)

mobizt commented 4 years ago

The library does not use or rely on ArduinoJson and any third-party library. In the readme, it means if you want to create and parse JSON, you need to handle by yourself by using third party libraries like ArduinoJson.

To create the serialized JSON string yourself, you may need to learn the basics of JSON, the valid data structure, and supported data types.

From your code, the JSON is not a valid format.

String json2 = "{\"Temperature\":temperature,\"Humidity\":humidity}";

The word temperature and humidity are not number, string, boolean, JSON object, JSON array object and null.

The following are valid.

 //The value type of Temperature and Humidity keys are string (text inside double quotes).
String json2 = "{\"Temperature\":\"temperature\",\"Humidity\":\"humidity\"}";

//The value type of Temperature and Humidity keys are number.
String json2 = "{\"Temperature\":25.4,\"Humidity\":56}"; 

//The value type of Temperature and Humidity keys are boolean.
String json2 = "{\"Temperature\":true,\"Humidity\":false}"; 

//The value of Temperature and Humidity keys are JSON objects.
String json2 = "{\"Temperature\":{\"highest\":30},\"Humidity\":{\"highest\":70}}"; 

//The value type of Temperature and Humidity keys are JSON object array.
String json2 = "{\"Temperature\":[\"hello\",true,123],\"Humidity\":[100,200,false]}"; 

//The value type of Temperature and Humidity keys are null.
String json2 = "{\"Temperature\":null,\"Humidity\":null}"; 

The valid JSON in the example. https://github.com/mobizt/Firebase-Arduino-WiFiNINA/blob/master/examples/Basic/Basic.ino#L156

Then for your case, to create the valid JSON.

String json2 = "{\"Temperature\":" + String(temperature) + ",\"Humidity\":" + String(humidity) + "}";
PSKAdam commented 4 years ago

Appreciate your help @mobizt . Could you also advise how to retrieve timestamp through FirebaseData object.payload() instead of directly using setTimestamp or pushTimestamp as mentioned in your ReadMe? I wish to append the timestamp together as one JSON in the following:

String json2 = "{\"Temperature\":" + String(temperature) + ",\"Humidity\":" + String(humidity) + ",\"Timestamp\":" + String(timestamp) + "}";

However, payload API got me nothing from my Serial Monitor:

Serial.println("Timestamp: " + FirebaseData object.payload());

mobizt commented 4 years ago

The payload function returns the payload response from the Firebase server. If the data you send to the server is JSON, the payload returns will be JSON too.

This syntax is not valid. FirebaseData object.payload()

If you use firebaseData to send the data to a server like this. Firebase.pushJSON(firebaseData, path + "/Sensors/Temp&Humid_Sensors", json2)

Then the payload can read and print to serial like this Serial.println(firebaseData.payload());

PSKAdam commented 4 years ago

Hi @mobizt , I've tried what you suggested above but it still prints nothing to the serial. Everything remains the same from my initial post except adding the payload function as follows. I've attached my output for your reference:

String json2 = "{\"Temperature\":" + String(temperature) + ",\"Humidity\":" + String(humidity) + "}";

    if (Firebase.pushJSON(firebaseData, path + "/Sensors/Temp&Humid_Sensors", json2))
    {
      Serial.println("----------Push result-----------");
      Serial.println("Timestamp: " + firebaseData.payload()); // additional line
      Serial.println("PATH: " + firebaseData.dataPath());
      Serial.println("TYPE: " + firebaseData.dataType());
      Serial.print("PUSH NAME: ");
      Serial.println(firebaseData.pushName());
      Serial.println("--------------------------------");
      Serial.println();
    }
    else
    {
      Serial.println("----------Can't push data--------");
      Serial.println("REASON: " + firebaseData.errorReason());
      Serial.println("--------------------------------");
      Serial.println();
    }

image

Is there a bug as the payload function is pretty straightforward? Please advise

mobizt commented 4 years ago

This is the behavior that designed by Google.

The push operation returns an empty payload from its server.

That is why no data print in the push example.

mobizt commented 4 years ago

You can't use these functions to get data from the push operation. The pushName is available.

      Serial.println("Timestamp: " + firebaseData.payload()); 
      Serial.println("PATH: " + firebaseData.dataPath());
      Serial.println("TYPE: " + firebaseData.dataType());