Can you put ESP32 FTP client constructor in setup()

I have a program working that transfers a file from the SD card of an ESP32S3 to a PC running a FTP server (filezilla) via Wifi.

I want to be able to read the setup from a file on the SD card so that if the WiFi network or PC hosting the FTP server changes you dont have to re-program the ESP32.

I can read the WiFi SSID and password from an SD file just fine, no problems because the WiFi uses a begin();

WiFi.begin(WIFI_SSID, WIFI_PASS );

However the constructor for the FTP connection is at the top of the program, outside of the functions;

char ftp_server[] = "192.168.1.20";
char ftp_user[]   = "Auser";
char ftp_pass[]   = "Hello1234";
ESP32_FTPClient ftp (ftp_server, ftp_user, ftp_pass, 5000, 0);

So I cannot have a bit of program reading the ftp login details from a config file.

Is there a way around this ?

Yes, create the ESP32_FTPClient object dynamically in setup().

ESP32_FTPClient * ftp;
...
void setup() {
  ...
  ftp = new ESP32_FTPClient(ftp_server, ftp_user, ftp_pass, 5000, 0);

Note: ftp is now not the object itself but a pointer/reference to it, so you will need to de-reference the pointer when you use it in your other code:

ftp.doXYZ();

becomes

ftp->doXYZ();
1 Like

Thanks for that, it works.

Its a easy way to get files from an ESP32 or ESP32CAM to a PC. The filezilla FTP server is not difficult to setup on the PC.

If the PC with the FTP server changes you just need to edit the config.txt file on the SD card with the changes.

Here is the code;



/******************************************************************************
  StuartsProjects 02/11/24. 
  Used Arduino IDE 1.8.19. ESP32 core 2.0.14

  For ESP32S3. Loads file from SD card and transfers via FTP to FTP server (filezilla)
  running on PC.

  WiFi and FTP server login details are read from Config.txt file on SD card. 
  The file is in this format;

  WIFI_SSID[] "My-SSID";
  WIFI_PASS[] "My-Pass";
  ftp_server[] = "192.168.1.10";
  ftp_user[] = "User";
  ftp_pass[] = "HelloWorld";

******************************************************************************/

#include <SPI.h>
#include <SD_MMC.h>
File dataFile;
uint16_t filesize;

#define MMCSCK 7                     //SD card MMC pins
#define MMCCMD 9
#define MMCD0 8

#include <WiFi.h>
#include <WiFiClient.h>
#include <ESP32_FTPClient.h>         //get library here > https://github.com/ldab/ESP32_FTPClient

char WIFI_SSID[16];
char WIFI_PASS[16];
char ftp_server[16];
char ftp_user[16];
char ftp_pass[16];
char sendfile[] = "/$50SATL.JPG";    //file to send from SD
char configfile[]  = "/Config.txt";  //config file on SD, has WiFi and FTP login details

ESP32_FTPClient * ftp;


void loop()
{
  ftp->OpenConnection();

  Serial.print("Send file ");
  Serial.println(sendfile);
  readAndSendBigBinFile(SD_MMC, sendfile, *ftp);

  ftp->CloseConnection();

  Serial.println("Finished");

  while (1);                         //halt program   
}


void setup()
{
  Serial.begin(115200);

  Serial.println("Initializing SD card...");
  SD_MMC.setPins(MMCSCK, MMCCMD, MMCD0);

  if (!SD_MMC.begin("/sdcard", true))             //set SD card for 1 bit MMC mode
  {
    Serial.println("Card Mount Failed");
    Serial.println("Program halted");
    while(1);
  }

  uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);

  filesize = SDopenFileRead(configfile);
  dataFile.seek(0);

  readchar_array(WIFI_SSID);
  Serial.print("WIFI_SSID = ");
  Serial.println(WIFI_SSID);

  readchar_array(WIFI_PASS);
  Serial.print("WIFI_PASS = ");
  Serial.println(WIFI_PASS);

  WiFi.begin( (const char*) WIFI_SSID, (const char*) WIFI_PASS );

  Serial.println("Connecting Wifi...");

  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  readchar_array(ftp_server);
  Serial.print("FTP server ");
  Serial.println(ftp_server);

  readchar_array(ftp_user);
  Serial.print("FTP user ");
  Serial.println(ftp_user);

  readchar_array(ftp_pass);
  Serial.print("FTP password ");
  Serial.println(ftp_pass);

  ftp = new ESP32_FTPClient(ftp_server, ftp_user, ftp_pass, 5000, 0);     //ftp client constructor
}


void readchar_array(char *buff)
{
  uint8_t charread, pointer;

  do
  {
    charread = dataFile.read();
  }
  while (charread != '"');

  pointer = 0;

  do
  {
    charread = dataFile.read();
    buff[pointer] = charread;
    pointer++;
  }
  while (charread != '"');

  buff[pointer - 1] = 0;
}


uint32_t SDopenFileRead(char *buff)
{
  uint32_t filesize;

  dataFile = SD_MMC.open(buff);
  filesize = dataFile.size();
  dataFile.seek(0);
  return filesize;
}


void readAndSendBigBinFile(fs::FS& fs, const char* path, ESP32_FTPClient ftpClient)
{
  ftpClient.InitFile("Type I");
  ftpClient.NewFile(path);

  //String fullPath = "/";
  String fullPath = "";
  fullPath.concat(path);
  Serial.printf("Reading file: %s\n", fullPath);

  File file = fs.open(fullPath);
  if (!file)
  {
    Serial.println("Failed to open file for reading");
    return;
  }

  Serial.print("Read from file: ");

  while (file.available())
  {
    // Create and fill a buffer
    unsigned char buf[1024];
    int readVal = file.read(buf, sizeof(buf));
    ftpClient.WriteData(buf, sizeof(buf));
  }
  ftpClient.CloseFile();
  file.close();
}
2 Likes

The same code will work sending files\images to an Android mobile phone running the SWIFTP FTP Server app, also easy to setup.