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 100 forks source link

Storage.download function corrupts memory and clears file list #582

Closed Legolor closed 11 months ago

Legolor commented 11 months ago

Variables are getting corrupted from the Firebase.Storage.download or Firebase.Storage.deleteFile functions or both.

The code should find all files in the directory. Then it should loop through and one at a time download them to the sd card and then delete the file from firebase.

In the code the download function successfully downloads the first file. However, it corrupts the firebase filename variable "firebaseObject" preventing the file from being deleted (the delete function normally works for me). The file list is also cleared and (files->items.size()) returns "0". This prevents the for loop from continuing. The interesting part of the code is "downloadFilesFromFirebase()"

#include "Arduino.h"
#include "WiFi.h"
#include <SPI.h>
#include <SD.h>
#include <Firebase_ESP_Client.h>
#include <addons/TokenHelper.h>

#define SD_CS 26
#define SD_SCK  14
#define SD_MISO  27
#define SD_MOSI  13 

SPIClass spiSD(HSPI);

const char* ssid = "ssid";
const char* password = "psw";

#define API_KEY "key"
#define USER_EMAIL "email"
#define USER_PASSWORD "emailpsw"
#define STORAGE_BUCKET_ID "myBucket.appspot.com"

FirebaseData fbdo;
FirebaseAuth auth;
FirebaseConfig configF;

void fcsDownloadCallback(FCS_DownloadStatusInfo info);
void downloadFilesFromFirebase();

bool taskCompleted = false;

void initWiFi() {
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
}

void initSDCard() {
  if (!SD.begin(SD_CS,spiSD)) {
    Serial.println("An error occurred while initializing the SD card");
    delay(5000);
    ESP.restart();
  } else {
    Serial.println("SD card initialized successfully");
  }
}

void setup() {
  // Serial port for debugging purposes
  Serial.begin(115200);
  spiSD.begin(SD_SCK, SD_MISO, SD_MOSI, SD_CS);

  initWiFi();
  initSDCard();

  configF.api_key = API_KEY;
  auth.user.email = USER_EMAIL;
  auth.user.password = USER_PASSWORD;
  configF.token_status_callback = tokenStatusCallback; // see addons/TokenHelper.h

  Firebase.reconnectWiFi(true);
  fbdo.setBSSLBufferSize(4096, 1024);
  configF.fcs.download_buffer_size = 2048;
  Firebase.begin(&configF, &auth);
}

void loop() {
  delay(1);
  if (Firebase.ready() && !taskCompleted) {
    taskCompleted = true;
    Serial.println("Storage Functions... ");

    downloadFilesFromFirebase();
  }
}

void downloadFilesFromFirebase() {

  Serial.printf("List files... %s\n", Firebase.Storage.listFiles(&fbdo, STORAGE_BUCKET_ID) ? "ok" : fbdo.errorReason().c_str());

  FileList *files = fbdo.fileList();
  if (fbdo.httpCode() == FIREBASE_ERROR_HTTP_CODE_OK)
  {
    for (size_t i = 0; i < files->items.size(); i++)
      Serial.printf("name: %s\n", files->items[i].name.c_str());
  }
  Serial.println("Number of Files Found: " + String(files->items.size()));

  for (size_t i = 0; i < files->items.size(); i++) {
    const char* firebaseObject = files->items[i].name.c_str();
    Serial.println("Current file: " + String(firebaseObject));
    String downloadFileName = "/" + String(firebaseObject);

    if (Firebase.Storage.download(&fbdo, STORAGE_BUCKET_ID, firebaseObject, downloadFileName, mem_storage_type_sd, fcsDownloadCallback)) {
      Serial.println("Current file 2: " + String(firebaseObject));

      if (Firebase.Storage.deleteFile(&fbdo, STORAGE_BUCKET_ID, files->items[i].name.c_str())) {
        Serial.printf("Deleted file: %s\n", firebaseObject);
      } else {
        Serial.printf("Failed to delete file: %s\n", firebaseObject);
      }
      Serial.println("Current file 3: " + String(firebaseObject));
      Serial.println("Number of Files Found: " + String(files->items.size()));
    } else {
      Serial.printf("Failed to download file: %s\n", firebaseObject);
    }
  }
}

void fcsDownloadCallback(FCS_DownloadStatusInfo info){
  //delay(50);
    if (info.status == firebase_fcs_download_status_init)
    {
        Serial.printf("\nDownloading file %s (%d) to %s\n", info.remoteFileName.c_str(), info.fileSize, info.localFileName.c_str());
    }
    else if (info.status == firebase_fcs_download_status_download)
    {
        Serial.printf("Downloaded %d%s, Elapsed time %d ms\n", (int)info.progress, "%", info.elapsedTime);
    }
    else if (info.status == firebase_fcs_download_status_complete)
    {
        Serial.println("Download completed\n");
    }
    else if (info.status == firebase_fcs_download_status_error)
    {
        Serial.printf("Download failed, %s\n", info.errorMsg.c_str());
    }
}

Example Serial Monitor:

Storage Functions...
List files... ok
name: box1/file.txt
name: data
name: data/downloaded_photo.jpg
Number of Files Found: 3
Current file: box1/file.txt

Downloading file box1/file.txt (13) to /box1/file.txt
Downloaded 100%, Elapsed time 8695 ms
Download completed

Current file 2: l��?l��?/box1/file.txt
Failed to delete file:
Current file 3:
Number of Files Found: 0

Note messed up "Current file 2:", different "Current file 3:", and "Number of Files Found:" at 0.

IDE and its version:

ESP32 Arduino Core SDK version

Additional context I have tried increasing and decreasing the buffer sizes in startup. I have added delays. I have uploaded in both arduinoIDE and PlatformIO. I have tried different partition schemes. I have used the sdHelper addon.

I'm not really sure what the issue could be so I think it might be a bug? Any help would be great! I'm happy to test any suggestions.

mobizt commented 11 months ago

It is normal as the file list and all temporary data in FilebaseData object will be cleared when it was re-used for another request.

mobizt commented 11 months ago

You should keep the file paths in String array to use it later.

mobizt commented 11 months ago

This is not a corrupt memory but the const char (char pointer) now points to somewhere in memory that does not exist as it has been deallocated already.