Closed sudilacf closed 10 months ago
You should create minimal code that reproduces the issue.
The issue is about the bugs in ESP32 WiFiClient core library when the session was reused while the connection was terminated by server.
fbdo.clear()
after the session was opened (server connected) longer than 50 seconds.so I need to call fbdo.clear() after using get/set function?
No, it's not necessary, it depends on your code which FirebaseData
object may be used incorrectly, and I suggest based on the error.
If FirebaseData
object used for stream with callback, you should not reuse it for other functions.
If you use, xxxAsync
, please avoid using it.
Minimal?
Minimal?
Im using 3 FirebaseData object two for MultiStream and one fbdo
void feedStreamCallback(MultiPathStream data) {
Serial.printf("Feed:\nLength: %d\nMax: %d\n", data.payloadLength(), data.maxPayloadLength());
if(data.get("/now")) {
if(data.value.equals("true")) {
if(Firebase.RTDB.setBool(&fbdo, "/feed/now", false)) {
if(addToHistory(&fbdo)) {
if(Firebase.RTDB.setString(&fbdo, "/settings/push_key", fbdo.pushName())) {
feed();
}
}
}
}
}
if(data.get("/offset")) {
scheduleOffset = data.value.toInt();
}
if(data.get("/on")) {
scheduleOn = data.value;
}
}
void settingsStreamCallback(MultiPathStream data) {
Serial.printf("Settings:\nLength: %d\nMax: %d\n", data.payloadLength(), data.maxPayloadLength());
if(data.get("/push_key")) {
if(Firebase.RTDB.getJSON(&fbdo, "/history/" + data.value)) {
json = fbdo.jsonObject();
} else {
lcd.clear();
lcd.print("Last fed:");
lcd.setCursor(0, 1);
lcd.print("No data to show");
}
}
}
No, minimal does not mean the fraction of code.
You should create minimal, clean without third party libraries but complete that reproduces the issue and post here instead of your code.
I can't verify or debug your complex code.
Did you know this will cause memory leaks?
Firebase.RTDB.setString(new FirebaseData()...
When you dynamically allocated the FirebaseData
with new
without using delete
.
The FirebaseData
object is not only contains data but SSL Client and its resource which you should defined it locally or globally whenever you used it in usage scope.
this is the summarization of my code:
#include <WiFi.h>
#include <TimeLib.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <Firebase_ESP_Client.h>
int scheduleOffset;
String scheduleOn;
FirebaseData fbdo;
FirebaseData feedStream;
FirebaseData settingsStream;
FirebaseAuth auth;
FirebaseConfig config;
FirebaseJson json;
FirebaseJsonData result;
WiFiUDP clientUDP;
NTPClient timeClient(clientUDP, "asia.pool.ntp.org", 3600 * 8);
void feedStreamCallback(MultiPathStream data);
void settingsStreamCallback(MultiPathStream data);
void streamTimeoutCallback(bool);
void setup() {
Serial.begin(115200);
WiFi.begin("WIFISSID", "PASSWORD");
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(500);
}
Serial.println("connected");
config.database_url = "";
config.signer.tokens.legacy_token = "";
Firebase.reconnectNetwork(true);
fbdo.setBSSLBufferSize(2048, 1024);
feedStream.setBSSLBufferSize(2048, 1024);
settingsStream.setBSSLBufferSize(2048, 1024);
Firebase.begin(&config, &auth);
feedStream.keepAlive(5, 5, 1);
settingsStream.keepAlive(5, 5, 1);
if(!Firebase.RTDB.beginMultiPathStream(&feedStream, "/feed")) {
Serial.printf("Failed to begin stream %s\n", feedStream.errorReason().c_str());
return;
}
if(!Firebase.RTDB.beginMultiPathStream(&settingsStream, "/settings")) {
Serial.printf("Failed to begin stream %s\n", settingsStream.errorReason().c_str());
return;
}
Firebase.RTDB.setMultiPathStreamCallback(&feedStream, feedStreamCallback, streamTimeoutCallback);
Firebase.RTDB.setMultiPathStreamCallback(&settingsStream, settingsStreamCallback, streamTimeoutCallback);
}
void loop() {
if (!Firebase.ready())
return;
timeClient.update();
json.get(result, "month");
String monthStr(result.to<int>());
json.get(result, "day");
String dayStr(result.to<int>());
json.get(result, "year");
String yearStr(result.to<int>());
json.get(result, "hour");
String hourStr(result.to<int>());
json.get(result, "minute");
String minuteStr(result.to<int>());
json.get(result, "meridian");
String meridian(result.to<String>());
String lastFed = monthStr + "/" + dayStr + "/" + yearStr + " " + hourStr + ":" + minuteStr + ":00 " + meridian;
if(!scheduleOn.isEmpty() && !scheduleOn.equals(lastFed) && getTimeOffset(0).equals(scheduleOn)) {
if(addToHistory(&fbdo)) {
if(Firebase.RTDB.setString(new FirebaseData(), "/settings/push_key", fbdo.pushName())){
if(Firebase.RTDB.setString(new FirebaseData(), "/feed/on", getTimeOffset(scheduleOffset))) {
feed();
}
}
}
}
}
void feedStreamCallback(MultiPathStream data) {
Serial.printf("Feed:\nLength: %d\nMax: %d\n", data.payloadLength(), data.maxPayloadLength());
if(data.get("/now")) {
if(data.value.equals("true")) {
if(Firebase.RTDB.setBool(&fbdo, "/feed/now", false)) {
if(addToHistory(&fbdo)) {
if(Firebase.RTDB.setString(&fbdo, "/settings/push_key", fbdo.pushName())) {
feed();
}
}
}
}
}
if(data.get("/offset")) {
scheduleOffset = data.value.toInt();
}
if(data.get("/on")) {
scheduleOn = data.value;
}
}
void settingsStreamCallback(MultiPathStream data) {
Serial.printf("Settings:\nLength: %d\nMax: %d\n", data.payloadLength(), data.maxPayloadLength());
if(data.get("/push_key")) {
if(Firebase.RTDB.getJSON(&fbdo, "/history/" + data.value)) {
json = fbdo.jsonObject();
}
}
}
void feed() {
//rotate servo
}
bool addToHistory(FirebaseData *fbdo) {
const char *weekday_names[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
const char *month_names[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
unsigned long epochTime = timeClient.getEpochTime();
const char *meridian = isAM(epochTime) ? "AM" : "PM";
FirebaseJson json;
json.set("week_day_name", weekday_names[weekday(epochTime) - 1]);
json.set("year", year(epochTime));
json.set("month", month(epochTime));
json.set("month_name", month_names[month(epochTime) - 1]);
json.set("day", day(epochTime));
json.set("hour", hourFormat12(epochTime));
json.set("minute", minute(epochTime));
json.set("second", second(epochTime));
json.set("meridian", meridian);
json.set("epoch_time", epochTime);
return Firebase.RTDB.pushJSON(fbdo, "/history", &json);
}
Please read my previous comment, your code causes memory leaks and will not work properly.
The
FirebaseData
object is not only contains data but SSL Client and its resource which you should defined it locally or globally whenever you used it in usage scope.
which FirebaseData do you mean?
Already told in my previous comment.
Did you know this will cause memory leaks?
Firebase.RTDB.setString(new FirebaseData()...
When you dynamically allocated the
FirebaseData
withnew
without usingdelete
.
Did you know this will cause memory leaks?
Firebase.RTDB.setString(new FirebaseData()...
When you dynamically allocated theFirebaseData
withnew
without usingdelete
.
Ow I see, I'll try to remove it and test again. thanks
sir I got another problem
tcpWrite(): fail on fd 51, errno: 128, "Socket is not connected"
what causes this? can I use keepAlive() on my fbdo object and will it fix? cuz I only used keepAlive() on my stream.
The same reason, the connection terminated by server which WiFiClient
does not handle this properly as a bug in ESP32 WiFiClient
library.
To be fix, the WiFiClient
should be closed the connection on its end as server is gone instead of just give the error and still vaiting the data in the infinite loop without closing the session.
Now you should update the library by download the zip file from library repository.
I think I fixed it after removing Firebase.reconnectNetwork(true)
cuz I have code for internet reconnection.
btw, can you send me the link of WiFiClient lib pls, I cant find it.
No, it's internally implemented, and you should update the library.
Anyway, you should follow the example and read the comment first. https://github.com/mobizt/Firebase-ESP-Client/blob/a3701a04f0d1f82955a75140729100554e5fc0a2/examples/RTDB/Basic/Basic.ino#L118-L119
But I'm using the latest version of library 4.4.8, shall I download it here in github instead in platform IO?
And yes, already read that.
I just update the library and it takes several hours for Arduino Library Manager to update.
In PlatformIO, you can update it now.
Thanks bro
tcpWrite(): fail on fd 59, errno: 11, "No more processes
how to fix this problem?