mobizt / Firebase-ESP-Client

[DEPRECATED]🔥Firebase Arduino Client Library for ESP8266, ESP32 and RP2040 Pico. The complete, fast, secured and reliable Firebase Arduino client library that supports RTDB, Cloud Firestore, Firebase and Google Cloud Storage, Cloud Messaging and Cloud Functions for Firebase.
MIT License
471 stars 101 forks source link

"Connection Refused" After a few successful uploads to RTDB #561

Closed Ripwords closed 1 year ago

Ripwords commented 1 year ago

I've tried the examples and have had no issues for the past few months, however recently when running the code, the connection would start getting refused after uploading data for a few attempts and i start getting "connection refused" error.

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>
#include <Keypad.h>
// WiFiManager
#include <WiFi.h>
#include <WiFiManager.h>
// Firebase
#include <Firebase_ESP_Client.h>
#include <addons/TokenHelper.h>
#include <addons/RTDBHelper.h>
// Timestamp
#include <time.h>
// ESP32
#include "soc/rtc_wdt.h"
// Credentials
#include "creds.h"

// Firebase Config
#define FIREBASE_HOST "embedded-iot-7ef1f-default-rtdb.asia-southeast1.firebasedatabase.app"

// LED Config
#define RED 2
#define GREEN 16

// DHT Config
#define DHTPIN 4
#define DHTTYPE DHT11

// OLED Display Config
#define S_W 128
#define S_H 64
#define OLED_RESET -1

// KEYPAD Config
const byte ROWS = 4; 
const byte COLS = 4; 

const char hexaKeys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte rowPins[ROWS] = {16, 17, 5, 18}; 
byte colPins[COLS] = {32, 33, 25, 26}; 

static WiFiManager wm;
static FirebaseData data;
static FirebaseAuth auth;
static FirebaseConfig config;
static DHT dht(DHTPIN, DHTTYPE);
static Adafruit_SSD1306 display(S_W, S_H, &Wire, OLED_RESET);
static Keypad kp = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); 

const unsigned char wifiicon[] PROGMEM  ={ // wifi icon
  0x00, 0xff, 0x00, 0x7e, 0x00, 0x18,0x00, 0x00
};

static volatile unsigned long prev = 0;
static volatile unsigned long prev_2 = 0;
static unsigned long deletePrev = 0;
static unsigned long deleteInterval = 10;
static volatile unsigned long tempLogInterval = 5;
static volatile unsigned long logging_interval = 5;
static volatile bool indexing = false;

static volatile float h, t, tempH, tempT;
struct tm timeinfo;

static char customKey;

static volatile bool autoHeatFail = false;
static volatile bool autoCoolFail = false;

const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 28800;

TaskHandle_t READ_CLOUD;
TaskHandle_t UPLOAD_CLOUD;
TaskHandle_t DHT_UPDATE;
TaskHandle_t KEYPAD_HANDLER;

TickType_t xTicksToWait(float ms) {
  return pdMS_TO_TICKS(ms);
}

void TASK_KEYPAD_HANDLER(void *pvParameters) {
  (void)pvParameters;

  for(;;) {
    customKey = kp.getKey();

    if (customKey){
      Serial.println(customKey);
    }

    vTaskDelay(xTicksToWait(50));
  }
}

void TASK_UPLOAD_CLOUD(void *pvParameters) {
  (void)pvParameters;

  for(;;) {
    bool ready = (millis() / 1000) >= prev + logging_interval;
    bool ready_2 = (millis() / 1000) >= prev_2 + 1;

    static String path = String(ACC) + "/log";
    static FirebaseJson json;

    json.add("ts", (uint32_t)time(nullptr));
    json.add("temp", String(t));
    json.add("humidity", String(h));

    if (Firebase.ready()) {
      if (ready_2 || prev_2 == 0) {
        prev_2 = millis() / 1000;

        if (Firebase.RTDB.getInt(&data, String(ACC) + "/logging_interval")) {
          if (data.dataType() == "int") {
            tempLogInterval = data.intData();
          }
        }

        if (Firebase.RTDB.getBool(&data, String(ACC) + "/heating")) {
            if (data.dataType() == "boolean") {
              digitalWrite(RED, data.boolData());
            }
          }

        if (Firebase.RTDB.getBool(&data, String(ACC) + "/cooling")) {
          if (data.dataType() == "boolean") {
            digitalWrite(GREEN, data.boolData());
          }
        }
      }
      if (ready || prev == 0) {
        prev = millis() / 1000;
        // Upload Data
        if (!getLocalTime(&timeinfo)) {
          Serial.println("Failed (NTP)");
        }
        // Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
        if (Firebase.RTDB.push(&data, path, &json)) {
          Serial.println("Logged data");
        } else {
          Serial.println("Failed (data): " + data.errorReason());
        }
        if (Firebase.RTDB.setFloat(&data, String(ACC) + "/uptime", millis())) {
          Serial.println("Logged UpTime");
        } else {
          Serial.println("Failed (UpTime): " + data.errorReason());
        }
      }
      if (time(nullptr) > 1687614174 && millis() - deletePrev > deleteInterval * 1000) {
        if (!indexing) {
            setFBIndex();
        }
        deletePrev = millis();
        if (Firebase.RTDB.getArray(&data, path)) {
          if (data.dataTypeEnum() == firebase_rtdb_data_type_array) {
            Serial.println(sizeof(data.jsonArray()));
          }
        }
        Serial.println("Delete old data");
        if (Firebase.RTDB.deleteNodesByTimestamp(&data, path, "ts", 15, 45)) {
          Serial.println("Cleared old data");
        } else {
          Serial.println(data.errorReason());
        }
      }

      // checkCond();
    }

    if (logging_interval != tempLogInterval) {
      Serial.println("Logging Interval Updated");
      logging_interval = tempLogInterval;
    }
    vTaskDelay(xTicksToWait(1256));
  }
}

void TASK_DHT_UPDATE(void *pvParameters) {
  (void)pvParameters;

  for(;;) {
    tempH = dht.readHumidity();
    tempT = dht.readTemperature();
    if (!isnan(tempH)) h = tempH;
    if (!isnan(tempT)) t = tempT;

    if (isnan(tempH) || isnan(tempT)) {
      Serial.println(F("Failed (DHT)"));
    }
    display.clearDisplay();
    display.drawBitmap(120, 1, wifiicon,8,8,WHITE);
    display.setTextSize(2);
    display.setTextColor(WHITE);
    display.setCursor(0, 20);
    display.print(F("T: "));
    display.print(t);
    display.println(F("C "));
    display.print(F("H: "));
    display.print(h);    
    display.println("%");
    display.display();
    vTaskDelay(xTicksToWait(2007));
  }
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  displayInit();
  wifiInit();
  pinSetup();
  dhtInit();
  ntpInit();
  connectFirebase();  
  delay(1000);
  logLocalIP();

  xTaskCreatePinnedToCore(TASK_KEYPAD_HANDLER, "KP_UPDATE", 10000, NULL, 4, &KEYPAD_HANDLER, 1);
  xTaskCreatePinnedToCore(TASK_DHT_UPDATE, "DHT_UPDATE", 5000, NULL, 3, &DHT_UPDATE, 1);
  xTaskCreatePinnedToCore(TASK_UPLOAD_CLOUD, "UPLOAD_CLOUD", 36000, NULL, 2, &UPLOAD_CLOUD, 1);
}

void loop() {}

void pinSetup() {
  pinMode(RED, OUTPUT);
  pinMode(GREEN, OUTPUT);
  digitalWrite(RED, LOW);
  digitalWrite(GREEN, LOW);
}

void displayInit() {
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3c)) {
    Serial.println("Allocation Failed");
    for (;;);
  }
  display.display();
  display.clearDisplay();
}

void dhtInit() {
  dht.begin();
}

void wifiInit() {
  WiFi.mode(WIFI_STA);
  wm.setConnectRetries(2);
  wm.setConnectTimeout(10);
  wm.setConfigPortalTimeout(500);
  wm.setConfigPortalBlocking(false);
  wm.autoConnect("Embedded IoT", "14161416");
  while (WiFi.status() != WL_CONNECTED) {
    wm.process();
    vTaskDelay(0);
  }

  prev = millis() / 1000;
}

void ntpInit() {
  configTime(gmtOffset_sec, 0, ntpServer);
}

void connectFirebase() {
  config.api_key = API_KEY;
  config.database_url = FIREBASE_HOST;
  auth.user.email = ACC_EMAIL;
  auth.user.password = ACC_PW;
  config.token_status_callback = tokenStatusCallback;
  config.max_token_generation_retry = 5;
  Firebase.reconnectWiFi(true);
  data.setBSSLBufferSize(15000, 15000);
  Firebase.begin(&config, &auth);
  Serial.println("Firebase Connected");
  setFBIndex();
}

void logLocalIP() {
  if (Firebase.ready()) {
    if (Firebase.RTDB.setString(&data, String(ACC) + "/localip", WiFi.localIP().toString().c_str())) {
      Serial.println("Logged Local IP");
    } else {
      Serial.println("Failed (IP): " + data.errorReason());
    }
  }
}

void checkCond() {
  if (t < 30) {
    digitalWrite(RED, HIGH);
    digitalWrite(GREEN, LOW);
    if (Firebase.ready()) {
      if (Firebase.RTDB.setBoolAsync(&data, String(ACC) + "/heating", true)) {
        Serial.println("Temp Low, heating activated");
      } else {
        Serial.println("Failed (Heating): " + data.errorReason());
      }

      if (Firebase.RTDB.setBoolAsync(&data, String(ACC) + "/cooling", false)) {
        Serial.println("Temp Low, cooling deactivated");
      } else {
        Serial.println("Failed (Cooling): " + data.errorReason());
      }
    }
  }

  if (t > 35) {
    digitalWrite(RED, LOW);
    digitalWrite(GREEN, HIGH);
    if (Firebase.ready()) {
      if (Firebase.RTDB.setBoolAsync(&data, String(ACC) + "/heating", false)) {
        Serial.println("Temp High, heating deactivated");
      } else {
        Serial.println("Failed (!Heating): " + data.errorReason());
      }

      if (Firebase.RTDB.setBoolAsync(&data, String(ACC) + "/cooling", true)) {
        Serial.println("Temp High, cooling activated");
      } else {
        Serial.println("Failed (!Cooling): " + data.errorReason());
      }
    }
  }
}

void setFBIndex() {
  if (Firebase.ready()) {
    if (!indexing) {
      Serial.print("Setting query index in database rules... ");
      // If sign in with OAuth2.0 token, the database secret pass to this function can be empty string
      if (Firebase.RTDB.setQueryIndex(&data, String(ACC) + "/log", "ts", DB_SECRET)) {
        Serial.println("ok");
        indexing = true;
      }
      else {
        Serial.println(data.errorReason());
      }
    }
  }
}

image

As you can see in this image, the data is logged and then suddenly the connection starts getting refused. There is a Failed (DHT) error but that's my sensor error unrelated to the Firebase logic.

Thanks in advance, let me know if there's any information more that you require. I am using an ESP32 DOIT Devkit

Ripwords commented 1 year ago

Just a note: I have credentials saved in a different file, DB_SECRET, API_KEY and such, so that's not the problem as the data is uploaded successfully for a few attempts, before connection refused starts

mobizt commented 1 year ago

First, update the library.

I see that you are using Async function, please avoid using it if you are using it together with other functions as I already noted in the example comment (at the bottom of basic example).

The library data transfer is fast enough which async is not needed.

Ripwords commented 1 year ago

I've updated to the latest version uploaded a few hours ago, and changed the WiFi network to my mobile network and also removed use of async. The behaviour has improved, but after awhile it still returns me "connection refused" i've already set the BSSL size to maximum as well

mobizt commented 1 year ago

It is your network issue that resists for internet access.

mobizt commented 1 year ago

It's not necessary to set SSL buffer size as much, 2048 is ok for general use.

I see you reserved the stack for some FreeRTOS task as much as 36k which is not necessary too.

You should debug your code which memory allocation failure can be a problem in your case.

Note that, library was intensively test 24/7 with WiFI, Ethernet and GSM network and it works fine.

Ripwords commented 1 year ago

Okay thanks for the suggestions, I will try to debug

Ripwords commented 1 year ago

[170621][E][WiFiClientImpl.h:468] tcpWrite(): fail on fd 48, errno: 104, "Connection reset by peer"

I turned on Core Debuggin and received this error message

mobizt commented 1 year ago

That is because server denied to connect or your network interruption.

Another possible issue, when you use WiFiManger to control your WiFi, you should set reconnect WiFi option to false to prevent network reconnection conflicts.

Firebase.reconnectWiFi(false);

Ripwords commented 1 year ago

I think that may be my problem, thanks again, i have also turned on TCP fbdo.keepAlive not sure if that will help

Ripwords commented 1 year ago

This seems to have solved my issue for now. Thanks again for your help

mobizt commented 1 year ago

Thanks for feedback and I will update the document too.