mobizt/Firebase-Arduino-WiFiNINA

Connection refused when using two FirebaseData objects

dgrafov opened this issue · 3 comments

Hi,

I'm trying to use different FirebaseData objects for posting data and reading from a stream not to re-connect stream every
time after posting data, according to comment in Firebase_Arduino_WiFiNINA.h:

 Using the same Firebase Data object for stream read/monitoring associated
 with getXXX, setXXX, pushXXX, updateNode and deleteNode will break or quit
 the current stream connection.

After connecting to the stream I can't push data anymore, and after pushing data I can't read from the stream (depending on what happens first).

Is this use-case supported?

The code (based on Basic and Stream examples):

#include "Firebase_Arduino_WiFiNINA.h"

#define FIREBASE_HOST "crocus-bd208.firebaseio.com"
#define FIREBASE_AUTH "PLMQG02DK1S4muXnxgHuXNnxZRpLXeBw0qFP4LOv"
#define WIFI_SSID "TresspassersW"
#define WIFI_PASSWORD "SayFriendAndEnter"

//Define Firebase data object
FirebaseData firebaseData;
FirebaseData firebaseStream;

String path = "/MKR1010_stream_test";

void setup()
{

  Serial.begin(9600);
  delay(100);
  Serial.println();

  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 autntication data
  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH, WIFI_SSID, WIFI_PASSWORD);
  Firebase.reconnectWiFi(true);

  String jsonStr;


  if (!Firebase.beginStream(firebaseStream, path + "/stream"))
  {
    Serial.println("------Can't begin stream connection------");
    Serial.println("REASON: " + firebaseData.errorReason());
    Serial.println();
  }
}

void loop()
{

  
  if (Firebase.pushInt(firebaseData, path + "/Push/Int", 1))
  {
    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();
  }
  
  
  if (!Firebase.readStream(firebaseStream))
  {
    Serial.println("Can't read stream data");
    Serial.println("REASON: " + firebaseStream.errorReason());
    Serial.println();
  }

  if (firebaseStream.streamTimeout())
  {
    Serial.println("Stream timeout, resume streaming...");
    Serial.println();
  }

  if (firebaseStream.streamAvailable())
  {
    Serial.println("-------Stream Data available-------");
    Serial.println("STREAM PATH: " + firebaseStream.streamPath());
    Serial.println("EVENT PATH: " + firebaseStream.dataPath());
    Serial.println("DATA TYPE: " + firebaseStream.dataType());
    Serial.println("EVENT TYPE: " + firebaseStream.eventType());
    Serial.print("VALUE: ");
    if (firebaseStream.dataType() == "int")
      Serial.println(firebaseStream.intData());
    else if (firebaseStream.dataType() == "float")
      Serial.println(firebaseData.floatData());
    else if (firebaseStream.dataType() == "boolean")
      Serial.println(firebaseStream.boolData() == 1 ? "true" : "false");
    else if (firebaseStream.dataType() == "string")
      Serial.println(firebaseStream.stringData());
    else if (firebaseStream.dataType() == "json")
      Serial.println(firebaseStream.jsonData());
    Serial.println();
  }
 

  delay(1000);
}

The output:

Connected with IP: 192.168.178.132

----------Can't push data--------
REASON: connection refused
--------------------------------

----------Can't push data--------
REASON: connection refused
--------------------------------

Can't read stream data
REASON: not connected

Stream timeout, resume streaming...

You are using the limited memory device which when you use the Firebase Data object, the SSL client instance created internally and use ram for storing SSL resources.

When you define the object global, the memory will will be permanently reserved and left you the lesser free memory to use.

This is importance for speed improvement of subsequence data transmission (without reconnection or redo the SSL handshaking by reuse the current SSL session).

If the Firebase Data object defined locally, stream will not function because it requires the connection to keep alive. The Firebase Data object used in Firebase calls, need to do SSL/TLS handshaking every new request and used memory and time for operation, at least 1-2 seconds for handshaking.

If your other code used the memory until the free memory is not enough for SSL handshaking to be completed, the device will fail to establish connection.

You don't have much memory to use in such device when you define two Firebase Data objects globally.

Consider to change to larger memory device when it's not fit your requirement.

6.1 KB memory on Arduino UNO WiFi Rev.2
32KB on Arduino Nano 33 IoT and Arduino MKR WiFi 1010
8 MB on MKR Vidor 4000

You should consider the device that has enough memory when you're dealing with data not a little sensor value data but database.

Thanks a lot for the answer!