New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FTP Client library #1183

Open
rudi48 opened this Issue Dec 9, 2015 · 40 comments

Comments

Projects
None yet
@rudi48

rudi48 commented Dec 9, 2015

Hi, I like to adapt http://playground.arduino.cc/Code/FTP to ESP8266.
Most part of the adapted program WiFi_FTP_Client.ino works, but there is a compiler error left,
which I can not resolve.
Most part of the program works, except the file data transfer to the FTP server.
If I declare const char clientBuf[64] = "aa";
instead of byte clientBuf[64];, it works, but that is not what I need.
If I use the library Ethernet.h instead of ESP8266WiFi.h it compiles OK, but no data transfer.
By the way, if I compile the original program FTP.ino with Ethernet.h, I get no compiler error.
Please see the error messages (Arduino 1.6.5 and 1.6.6):

In file included from /Volumes/DAT/Users/rudi/Documents/Arduino/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h:32:0,

                 from /Volumes/DAT/Users/rudi/Documents/Arduino/wifi_FTP_client/wifi_FTP_client.ino:10:
/Volumes/DAT/Users/rudi/Documents/Arduino/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiClient.h: In instantiation of 'size_t WiFiClient::write(T&, size_t) [with T = unsigned char [64]; size_t = unsigned int]':

/Volumes/DAT/Users/rudi/Documents/Arduino/wifi_FTP_client/wifi_FTP_client.ino:285:34:   required from here

/Volumes/DAT/Users/rudi/Documents/Arduino/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiClient.h:119:36: error: request for member 'available' in 'source', which is of non-class type 'unsigned char [64]'

     size_t left = source.available();
                                    ^
/Volumes/DAT/Users/rudi/Documents/Arduino/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiClient.h:123:5: error: request for member 'read' in 'source', which is of non-class type 'unsigned char [64]'
     source.read(buffer.get(), will_send);
     ^

Who can help me to solve that puzzle please?
Regards, Rudolf

The program with the error, the error lines are marked:

/*
   FTP passive client for IDE v1.0.1 and w5100/w5200
   http://playground.arduino.cc/Code/FTP
   Modified 6 June 2015 by SurferTim

   You can pass flash-memory based strings to Serial.print() by wrapping them with F().

   2015-12-09 Rudolf Reuter, adapted to ESP8266 NodeMCU
*/
#include <ESP8266WiFi.h>
// #include <Ethernet.h>
#include <FS.h>

// comment out next line to write to SD from FTP server
#define FTPWRITE

// Set these to your desired softAP credentials. They are not configurable at runtime.
const char *ssid = "FRITZ-7170R";
const char *password = ".............";

boolean debug = false;  // true = more messages
//boolean debug = true;

// LED is needed for failure signalling
const short int BUILTIN_LED2 = 16;  //GPIO16 on NodeMCU (ESP-12)

unsigned long startTime = millis();

// provide text for the WiFi status
const char *str_status[]= {
  "WL_IDLE_STATUS",
  "WL_NO_SSID_AVAIL",
  "WL_SCAN_COMPLETED",
  "WL_CONNECTED",
  "WL_CONNECT_FAILED",
  "WL_CONNECTION_LOST",
  "WL_DISCONNECTED"
};

// provide text for the WiFi mode
const char *str_mode[]= { "WIFI_OFF", "WIFI_STA", "WIFI_AP", "WIFI_AP_STA" };

// this must be unique
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x59, 0x67 };

// change to your network settings
IPAddress ip( 192, 168, 17, 231 );
IPAddress gateway( 192, 168, 17, 1 );
IPAddress subnet( 255, 255, 255, 0 );

// change to your server
IPAddress server( 192, 168, 17, 72 );

WiFiClient client;
WiFiClient dclient;
//EthernetClient client;  // from Arduino FTP.ino
//EthernetClient dclient; // from Arduino FTP.ino

char outBuf[128];
char outCount;

// change fileName to your file (8.3 format!)
String fileName = "TimeTemp.txt";
String  path = "/TimeTemp.txt";

// SPIFFS file handle
File fh;

void signalError() {  // loop endless with LED blinking in case of error
  while(1) {
      digitalWrite(BUILTIN_LED2, LOW);
      delay(300); // ms
      digitalWrite(BUILTIN_LED2, HIGH);
      delay(300); // ms
  }
}

//format bytes
String formatBytes(size_t bytes) {
  if (bytes < 1024) {
    return String(bytes) + "B";
  } else if (bytes < (1024 * 1024)) {
    return String(bytes / 1024.0) + "KB";
  } else if (bytes < (1024 * 1024 * 1024)) {
    return String(bytes / 1024.0 / 1024.0) + "MB";
  } else {
    return String(bytes / 1024.0 / 1024.0 / 1024.0) + "GB";
  }
}

//----------------------- WiFi handling
void connectWifi() {
  Serial.print("Connecting as wifi client to SSID: ");
  Serial.println(ssid);

  // use in case of mode problem
  WiFi.disconnect();
  // switch to Station mode
  if (WiFi.getMode() != WIFI_STA) {
    WiFi.mode(WIFI_STA);
  }

  WiFi.begin ( ssid, password );

  if (debug ) WiFi.printDiag(Serial);

  // ... Give ESP 10 seconds to connect to station.
  unsigned long startTime = millis();
  while (WiFi.status() != WL_CONNECTED && millis() - startTime < 10000) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  // Check connection
  if (WiFi.status() == WL_CONNECTED) {
    Serial.print("WiFi connected; IP address: ");
    Serial.println(WiFi.localIP());
  } else {
    Serial.print("WiFi connect failed to ssid: ");
    Serial.println(ssid);
    Serial.print("WiFi password <");
    Serial.print(password);
    Serial.println(">");
    Serial.println("Check for wrong typing!");
  }
}  // connectWiFi()

//----------------- FTP fail
void efail() {
  byte thisByte = 0;

  client.println(F("QUIT"));

  while (!client.available()) delay(1);

  while (client.available()) {
    thisByte = client.read();
    Serial.write(thisByte);
  }

  client.stop();
  Serial.println(F("Command disconnected"));
  fh.close();
  Serial.println(F("SD closed"));
}  // efail

//-------------- FTP receive
byte eRcv() {
  byte respCode;
  byte thisByte;

  while (!client.available()) delay(1);

  respCode = client.peek();

  outCount = 0;

  while (client.available()) {
    thisByte = client.read();
    Serial.write(thisByte);

    if (outCount < 127) {
      outBuf[outCount] = thisByte;
      outCount++;
      outBuf[outCount] = 0;
    }
  }

  if (respCode >= '4') {
    efail();
    return 0;
  }
  return 1;
}  // eRcv()

//--------------- FTP handling
byte doFTP() {

#ifdef FTPWRITE
  fh = SPIFFS.open(path, "r");
#else
  SPIFFS.remove(path);
  fh = SPIFFS.open(path, "w");
#endif

  if (!fh) {
    Serial.println(F("SPIFFS open fail"));
    return 0;
  }

#ifndef FTPWRITE
  if (!fh.seek(0)) {
    Serial.println(F("Rewind fail"));
    fh.close();
    return 0;
  }
#endif

  Serial.println(F("SPIFFS opened"));

  if (client.connect(server, 21)) {  // 21 = FTP server
    Serial.println(F("Command connected"));
  } else {
    fh.close();
    Serial.println(F("Command connection failed"));
    return 0;
  }

  if (!eRcv()) return 0;
  Serial.println("Send USER");
  client.println(F("USER rudi"));

  if (!eRcv()) return 0;
  Serial.println("Send PASSWORD");
  client.println(F("PASS xxxxxxxx"));

  if (!eRcv()) return 0;
  Serial.println("Send SYST");
  client.println(F("SYST"));

  if (!eRcv()) return 0;
  Serial.println("Send Type I");
  client.println(F("Type I"));

  if (!eRcv()) return 0;
  Serial.println("Send PASV");
  client.println(F("PASV"));

  if (!eRcv()) return 0;

  char *tStr = strtok(outBuf, "(,");
  int array_pasv[6];
  for ( int i = 0; i < 6; i++) {
    tStr = strtok(NULL, "(,");
    array_pasv[i] = atoi(tStr);
    if (tStr == NULL) {
      Serial.println(F("Bad PASV Answer"));
    }
  }
  unsigned int hiPort, loPort;
  hiPort = array_pasv[4] << 8;
  loPort = array_pasv[5] & 255;

  Serial.print(F("Data port: "));
  hiPort = hiPort | loPort;
  Serial.println(hiPort);

  if (dclient.connect(server, hiPort)) {
    Serial.println(F("Data connected"));
  }
  else {
    Serial.println(F("Data connection failed"));
    client.stop();
    fh.close();
    return 0;
  }

#ifdef FTPWRITE
  Serial.println("Send STOR filename");
  client.print(F("STOR "));
  client.println(fileName);
#else
  client.print(F("RETR "));
  client.println(fileName);
#endif

  if (!eRcv()) {
    dclient.stop();
    return 0;
  }

#ifdef FTPWRITE
  Serial.println(F("Writing"));
  //byte clientBuf[64];
  //const char clientBuf[64] = "aa";
  uint8_t clientBuf[64];
  //char clientBuf[64];
  //unsigned int clientCount = 0;
  size_t clientCount = 0;

  while (fh.available()) {
    clientBuf[clientCount] = fh.read();
    clientCount++;
    if (clientCount > 63) {
      dclient.write(clientBuf, 64);  //------------ ERROR
      clientCount = 0;
      delay(1);
    }
  }
  if (clientCount > 0) dclient.write(clientBuf, clientCount); //----- ERROR

#else
  while (dclient.connected()) {
    while (dclient.available()) {
      char c = dclient.read();
      fh.write(c);
      Serial.write(c);
    }
  }
#endif

  dclient.stop();
  Serial.println(F("Data disconnected"));

  if (!eRcv()) return 0;

  client.println(F("QUIT"));

  if (!eRcv()) return 0;

  client.stop();
  Serial.println(F("Command disconnected"));

  fh.close();
  Serial.println(F("SPIFS closed"));
  return 1;
}  // doFTP()


void readSPIFFS() {
  fh = SPIFFS.open(fileName, "r");

  if (!fh) {
    Serial.println(F("SPIFFS open fail"));
    return;
  }

  while (fh.available()) {
    Serial.write(fh.read());
  }

  fh.close();
}  // readSPIFFS()


void setup() {
  delay(1000);
  Serial.begin(115200);
  delay(1000);
  Serial.println("Sync,Sync,Sync,Sync,Sync");
  delay(500);
  Serial.println();
  // signal start
  pinMode(BUILTIN_LED2, OUTPUT);
  digitalWrite(BUILTIN_LED2, LOW);
  delay(100); // ms
  digitalWrite(BUILTIN_LED2, HIGH);
  delay(300); // ms

  Serial.print("Chip ID: 0x");
  Serial.println(ESP.getChipId(), HEX);

  Serial.println ( "Connect to Router requested" );
  connectWifi();
  if (WiFi.status() == WL_CONNECTED) {
    Serial.print("WiFi mode: ");
    Serial.println(str_mode[WiFi.getMode()]);
    Serial.print ( "Status: " );
    Serial.println (str_status[WiFi.status()]);
    // signal WiFi connect
    digitalWrite(BUILTIN_LED2, LOW);
    delay(300); // ms
    digitalWrite(BUILTIN_LED2, HIGH);      
  } else {
    Serial.println("");
    Serial.println("WiFi connect failed, push RESET button.");
    signalError();
  }

  //Ethernet.begin(mac, ip, gateway, gateway, subnet);  // from Arduino FTP.ino

  if (!SPIFFS.begin()) {
     Serial.println("SPIFFS failed, needs formatting");
     signalError();
  }

  fh = SPIFFS.open(path, "r");
  if (!fh) {
    Serial.println(F("SPIFFS open fail"));
    signalError();
  } else fh.close();

  Serial.println(F("Ready. Press f or r"));
}  // setup()


void loop() {
  byte inChar;

  if (Serial.available() > 0) {
    inChar = Serial.read();
  }

  if (inChar == 'f') {
    if (doFTP()) Serial.println(F("FTP OK"));
    else Serial.println(F("FTP FAIL"));
  }

  if (inChar == 'r') {
    String fileNameDir;
    Dir dir = SPIFFS.openDir("/");
    while (dir.next()) {
      fileNameDir = dir.fileName();
      size_t fileSize = dir.fileSize();
      Serial.printf("FS File: %s, size: %s\n", fileNameDir.c_str(), formatBytes(fileSize).c_str());
    }
  }
  delay(10);
}

Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

@Links2004

This comment has been minimized.

Show comment
Hide comment
@Links2004

Links2004 Dec 10, 2015

Collaborator

try to use it like this

dclient.write((const uint8_t *) &clientBuf[0], 64);

for a faster upload you shut increase the 64 to 1460.

Collaborator

Links2004 commented Dec 10, 2015

try to use it like this

dclient.write((const uint8_t *) &clientBuf[0], 64);

for a faster upload you shut increase the 64 to 1460.

@rudi48

This comment has been minimized.

Show comment
Hide comment
@rudi48

rudi48 Dec 10, 2015

Hello Markus,
Thank you very much, now the compiler error is gone :-)
I gnawed already 3 days at that problem.
After the patch the program works as expected.
I could upload my first file (35 KB) to the FTP server. Jubel!

One question of curiosity, how do found out, what to do?
Is there a tutorial describing that?
For me it is still a mystery.
Regards, Rudolf

rudi48 commented Dec 10, 2015

Hello Markus,
Thank you very much, now the compiler error is gone :-)
I gnawed already 3 days at that problem.
After the patch the program works as expected.
I could upload my first file (35 KB) to the FTP server. Jubel!

One question of curiosity, how do found out, what to do?
Is there a tutorial describing that?
For me it is still a mystery.
Regards, Rudolf

@Links2004

This comment has been minimized.

Show comment
Hide comment
@Links2004

Links2004 Dec 10, 2015

Collaborator

I read the error message, then I take a look to the code.
then compare the prototype of "write"
https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/src/WiFiClient.h#L50

size_t write(const uint8_t *buf, size_t size);

with what you try to give in.

uint8_t [64] vs const uint8_t *.
by this i know there only a typecast is needed (uint8_t is compatible to uint8_t).
Its basic C / C++ type conversion.

Collaborator

Links2004 commented Dec 10, 2015

I read the error message, then I take a look to the code.
then compare the prototype of "write"
https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/src/WiFiClient.h#L50

size_t write(const uint8_t *buf, size_t size);

with what you try to give in.

uint8_t [64] vs const uint8_t *.
by this i know there only a typecast is needed (uint8_t is compatible to uint8_t).
Its basic C / C++ type conversion.

@rudi48

This comment has been minimized.

Show comment
Hide comment
@rudi48

rudi48 Dec 10, 2015

Hello Markus,
Thank you very much for the explanation. I have learned something :-)

Unfortunately I looked at line 115 of WiFiClient.h, which was mentioned in the error message:
inline size_t WiFiClient::write(T& source, size_t unitSize) {

The increased buffer size (1460) works also.

Regards, Rudolf

rudi48 commented Dec 10, 2015

Hello Markus,
Thank you very much for the explanation. I have learned something :-)

Unfortunately I looked at line 115 of WiFiClient.h, which was mentioned in the error message:
inline size_t WiFiClient::write(T& source, size_t unitSize) {

The increased buffer size (1460) works also.

Regards, Rudolf

@rudi48

This comment has been minimized.

Show comment
Hide comment
@rudi48

rudi48 Dec 10, 2015

Hello Markus,
Does it make sense to place this FTP program to the ESP8266WiFi examples?
Regards, Rudolf

rudi48 commented Dec 10, 2015

Hello Markus,
Does it make sense to place this FTP program to the ESP8266WiFi examples?
Regards, Rudolf

@igrr

This comment has been minimized.

Show comment
Hide comment
@igrr

igrr Dec 10, 2015

Member

It would be very useful for others to create a library from this example.

Member

igrr commented Dec 10, 2015

It would be very useful for others to create a library from this example.

@rudi48

This comment has been minimized.

Show comment
Hide comment
@rudi48

rudi48 Dec 10, 2015

Hello Ivan,
Who can make such a library?
I am more or less a copy&paste programmer ;-)
My final source code of the example file is documented on
http://www.rudiswiki.de/wiki9/WiFiFTPServer

Regards, Rudolf

rudi48 commented Dec 10, 2015

Hello Ivan,
Who can make such a library?
I am more or less a copy&paste programmer ;-)
My final source code of the example file is documented on
http://www.rudiswiki.de/wiki9/WiFiFTPServer

Regards, Rudolf

@rudi48

This comment has been minimized.

Show comment
Hide comment
@rudi48

rudi48 Dec 10, 2015

I have added an upload / download flag to the program:
http://www.rudiswiki.de/wiki9/WiFiFTPServer

Regards, Rudolf

rudi48 commented Dec 10, 2015

I have added an upload / download flag to the program:
http://www.rudiswiki.de/wiki9/WiFiFTPServer

Regards, Rudolf

@igrr igrr changed the title from Compiler error at FTP Client program, help needed to Add FTP Client library Dec 13, 2015

@danbicks

This comment has been minimized.

Show comment
Hide comment
@danbicks

danbicks Feb 14, 2016

Rudi, must say awesome work. I have tried example with my server it starts all good asks for user
then password which is sent, then just sits there. Any ideas anyone?

Here is serial log:

WiFi connected; IP address: 192.168.0.11
WiFi mode: WIFI_STA
Status: WL_CONNECTED
Ready. Press d, u or r
SPIFFS opened
Command connected
220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
220-You are user number 8 of 1000 allowed.
220-Local time is now 08:55. Server port: 21.
220-This is a private system - No anonymous login
220-IPv6 connections are also welcome on this server.
220 You will be disconnected after 15 minutes of inactivity.
Return DB Ok..
Send USER
331 User SESP@dbtec.org OK. Password required
Return DB Ok..
Send PASSWORD

Thanks Dans

danbicks commented Feb 14, 2016

Rudi, must say awesome work. I have tried example with my server it starts all good asks for user
then password which is sent, then just sits there. Any ideas anyone?

Here is serial log:

WiFi connected; IP address: 192.168.0.11
WiFi mode: WIFI_STA
Status: WL_CONNECTED
Ready. Press d, u or r
SPIFFS opened
Command connected
220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
220-You are user number 8 of 1000 allowed.
220-Local time is now 08:55. Server port: 21.
220-This is a private system - No anonymous login
220-IPv6 connections are also welcome on this server.
220 You will be disconnected after 15 minutes of inactivity.
Return DB Ok..
Send USER
331 User SESP@dbtec.org OK. Password required
Return DB Ok..
Send PASSWORD

Thanks Dans

@danbicks

This comment has been minimized.

Show comment
Hide comment
@danbicks

danbicks Feb 14, 2016

PS my server is a just host one, account works fine tested with FTP client.

Dans

danbicks commented Feb 14, 2016

PS my server is a just host one, account works fine tested with FTP client.

Dans

@danbicks

This comment has been minimized.

Show comment
Hide comment
@danbicks

danbicks Feb 15, 2016

Rudi Update.

All working, I removed from the client.print lines the F pointer to store string in ram. All works perfect without it on ESP :)

Superb work, finally can FTP files to a server brilliant work. Would be nice to wrap this lot up in a library.

Dans

danbicks commented Feb 15, 2016

Rudi Update.

All working, I removed from the client.print lines the F pointer to store string in ram. All works perfect without it on ESP :)

Superb work, finally can FTP files to a server brilliant work. Would be nice to wrap this lot up in a library.

Dans

@rudi48

This comment has been minimized.

Show comment
Hide comment
@rudi48

rudi48 Feb 15, 2016

Hello Dans,
Thank you very much for finding the F pointer problem. However, from the specification:
http://arduino.esp8266.com/versions/1.6.5-947-g39819f0/doc/reference.html
the Program Memory feature "F" should work.
So, I am not sure that this was the cause of your problem.
Regards, Rudolf

rudi48 commented Feb 15, 2016

Hello Dans,
Thank you very much for finding the F pointer problem. However, from the specification:
http://arduino.esp8266.com/versions/1.6.5-947-g39819f0/doc/reference.html
the Program Memory feature "F" should work.
So, I am not sure that this was the cause of your problem.
Regards, Rudolf

@danbicks

This comment has been minimized.

Show comment
Hide comment
@danbicks

danbicks Feb 15, 2016

Hi Rudi,

Really strange I am using 1.6.5 with latest staging version and your example sketch.

First of all would sit there after sending password and wait 15 mins for FTP server disconnection. I added to your ercv() routine a ten second time-out and tried again, timed out after every attempt so I knew it was just waiting for response from ftp server. Just as a try I removed the F pointer from password and username, tried again and it proceeded further. I then removed all of them from the doFtp routine and hey presto works like a treat.

Maybe Igrr could shed some light on this. I am very happy, have tested it today solidly and works every time.

A big thanks again for all your hard work.

Dans

danbicks commented Feb 15, 2016

Hi Rudi,

Really strange I am using 1.6.5 with latest staging version and your example sketch.

First of all would sit there after sending password and wait 15 mins for FTP server disconnection. I added to your ercv() routine a ten second time-out and tried again, timed out after every attempt so I knew it was just waiting for response from ftp server. Just as a try I removed the F pointer from password and username, tried again and it proceeded further. I then removed all of them from the doFtp routine and hey presto works like a treat.

Maybe Igrr could shed some light on this. I am very happy, have tested it today solidly and works every time.

A big thanks again for all your hard work.

Dans

@rudi48

This comment has been minimized.

Show comment
Hide comment
@rudi48

rudi48 Feb 15, 2016

Hello Dans,
I believe in what you tested.
I have first tested with Arduino version 1.6.6 and then 1.6.7, but not very intensive.
That may be the difference.
It is very mysterious, but on the other hand the Program Memory feature "F" came from the Atmel Mega chips, where RAM memory is very limited. Fortunately with the ESP8266 it is not so needed.
Regards, Rudolf

rudi48 commented Feb 15, 2016

Hello Dans,
I believe in what you tested.
I have first tested with Arduino version 1.6.6 and then 1.6.7, but not very intensive.
That may be the difference.
It is very mysterious, but on the other hand the Program Memory feature "F" came from the Atmel Mega chips, where RAM memory is very limited. Fortunately with the ESP8266 it is not so needed.
Regards, Rudolf

@danbicks

This comment has been minimized.

Show comment
Hide comment
@danbicks

danbicks Feb 19, 2016

Hi Rudi,

I have had great success with this and am in the process of wrapping it all up in a library with additional functionality added.

Can you give me a list of all the credits to include within my library. Version history amendments etc.

Big thanks again

Dans

danbicks commented Feb 19, 2016

Hi Rudi,

I have had great success with this and am in the process of wrapping it all up in a library with additional functionality added.

Can you give me a list of all the credits to include within my library. Version history amendments etc.

Big thanks again

Dans

@rudi48

This comment has been minimized.

Show comment
Hide comment
@rudi48

rudi48 Feb 21, 2016

Hello Dans,
The credit goes to SurferTim, please see the link on top of my listing:
http://playground.arduino.cc/Code/FTP
It was my pleasure, to do something useful for the ESP8266 community.
Thank you very much for providing the program as a library.
Regards, Rudolf

rudi48 commented Feb 21, 2016

Hello Dans,
The credit goes to SurferTim, please see the link on top of my listing:
http://playground.arduino.cc/Code/FTP
It was my pleasure, to do something useful for the ESP8266 community.
Thank you very much for providing the program as a library.
Regards, Rudolf

@fendrbendr87

This comment has been minimized.

Show comment
Hide comment
@fendrbendr87

fendrbendr87 May 13, 2016

Hey rudi48,

I am trying to do something similar but keep running into roadblocks. I am trying to just simply write a "hello" onto a text file on an ftp server. The Arduino with the ESP8266 chip is communicating just fine with the FTP server through the Serial Monitor AT commands, but I am having trouble applying your code. I don't have an SD card reader / writer. Would you be able to help me with developing a code that simply writes "hello" onto a text file on an ftp server? Once I can do that, I can figure out how to transmit the data from multiple sensors onto the ftp server, and access it remotely from another location, which is my main goal.

Any assistance would be greatly appreciated.

Thank you!

-Gene

fendrbendr87 commented May 13, 2016

Hey rudi48,

I am trying to do something similar but keep running into roadblocks. I am trying to just simply write a "hello" onto a text file on an ftp server. The Arduino with the ESP8266 chip is communicating just fine with the FTP server through the Serial Monitor AT commands, but I am having trouble applying your code. I don't have an SD card reader / writer. Would you be able to help me with developing a code that simply writes "hello" onto a text file on an ftp server? Once I can do that, I can figure out how to transmit the data from multiple sensors onto the ftp server, and access it remotely from another location, which is my main goal.

Any assistance would be greatly appreciated.

Thank you!

-Gene

@rudi48

This comment has been minimized.

Show comment
Hide comment
@rudi48

rudi48 May 13, 2016

Hello Gene,
I have build end of 2015 a temperature measurement with an ESP8266 Module, with WiFi connection
to a Raspberry Pi as an Web Server. Please have a look at
http://www.rudiswiki.de/wiki9/WiFiLoggerOneWire
This may be an example for your project.
Also http://thingspeak.com/ could be used.
Regards, rudi48

rudi48 commented May 13, 2016

Hello Gene,
I have build end of 2015 a temperature measurement with an ESP8266 Module, with WiFi connection
to a Raspberry Pi as an Web Server. Please have a look at
http://www.rudiswiki.de/wiki9/WiFiLoggerOneWire
This may be an example for your project.
Also http://thingspeak.com/ could be used.
Regards, rudi48

@Clemzo

This comment has been minimized.

Show comment
Hide comment
@Clemzo

Clemzo commented Jun 9, 2016

..

@akashboghani

This comment has been minimized.

Show comment
Hide comment
@akashboghani

akashboghani Jun 28, 2016

Hi,
how can I do this while the ESP8266 is connected to the Arduino?

I need the ESP/Arduino setup to act as a client and upload a text file periodically to the ftp server.

akashboghani commented Jun 28, 2016

Hi,
how can I do this while the ESP8266 is connected to the Arduino?

I need the ESP/Arduino setup to act as a client and upload a text file periodically to the ftp server.

@BinarySurfer

This comment has been minimized.

Show comment
Hide comment
@BinarySurfer

BinarySurfer Jul 8, 2016

Hi akashboghani,

Did you solve the problem?

I assume you have the ESP8266 module wired to an Arduino board?

I connect successfully to my FTP server & I am able to manipulate the directories etc

I am also able to get my Dataport but I have no idea how to connect to it.

The ESP8266wifi.h seems to only allow one client connection at a time........I must be missing something very simple!

Thanks

BinarySurfer commented Jul 8, 2016

Hi akashboghani,

Did you solve the problem?

I assume you have the ESP8266 module wired to an Arduino board?

I connect successfully to my FTP server & I am able to manipulate the directories etc

I am also able to get my Dataport but I have no idea how to connect to it.

The ESP8266wifi.h seems to only allow one client connection at a time........I must be missing something very simple!

Thanks

@istabraqmahmood

This comment has been minimized.

Show comment
Hide comment
@istabraqmahmood

istabraqmahmood Nov 2, 2016

the code is not working, the SPIFFS open fail !
any help, please ?

istabraqmahmood commented Nov 2, 2016

the code is not working, the SPIFFS open fail !
any help, please ?

@rudi48

This comment has been minimized.

Show comment
Hide comment
@rudi48

rudi48 Nov 3, 2016

@stabraqmahmood
Some important informations are missing:

  1. What ESP8266 module is used?
  2. What Arduino version is used?
  3. What is the error message?

rudi48 commented Nov 3, 2016

@stabraqmahmood
Some important informations are missing:

  1. What ESP8266 module is used?
  2. What Arduino version is used?
  3. What is the error message?
@istabraqmahmood

This comment has been minimized.

Show comment
Hide comment
@istabraqmahmood

istabraqmahmood Nov 4, 2016

@rudi48
the serial monitor show:
WiFi connected; IP address: 192.168.0.183
WiFi mode: WIFI_STA
Status: WL_CONNECTED
................................
SPIFFS open fail


i`m using nodemcu v 1.0 (esp12-e) on arduino IDE v 1.6.12
please help
thanks

istabraqmahmood commented Nov 4, 2016

@rudi48
the serial monitor show:
WiFi connected; IP address: 192.168.0.183
WiFi mode: WIFI_STA
Status: WL_CONNECTED
................................
SPIFFS open fail


i`m using nodemcu v 1.0 (esp12-e) on arduino IDE v 1.6.12
please help
thanks

@rudi48

This comment has been minimized.

Show comment
Hide comment
@rudi48

rudi48 Nov 4, 2016

@stabraqmahmood
It may be that your SPIFFS file system is not yet formatted, please see for details:
arduino-esp8266fs-plugin
you may also have a look at my wiki:
NodeMCU

rudi48 commented Nov 4, 2016

@stabraqmahmood
It may be that your SPIFFS file system is not yet formatted, please see for details:
arduino-esp8266fs-plugin
you may also have a look at my wiki:
NodeMCU

@MajedRayan

This comment has been minimized.

Show comment
Hide comment
@MajedRayan

MajedRayan Nov 13, 2016

Hi rudi48
great work
but can I use SD card instead of SPIFFS
I replace FS.h with SD.h
`
#include <ESP8266WiFi.h>
#include <SPI.h>
#include <SD.h>
// comment out next line to write to SD from FTP server
#define FTPWRITE

// Set these to your desired softAP credentials. They are not configurable at runtime.
const char *ssid = "SSID";
const char *password = "PASSWORD";

//boolean debug = false; // true = more messages
boolean debug = true;
//start using SD
//static bool hasSD = false;

// LED is needed for failure signalling
const short int BUILTIN_LED2 = 16; //GPIO16 on NodeMCU (ESP-12)

unsigned long startTime = millis();

// provide text for the WiFi status
const char *str_status[]= {
"WL_IDLE_STATUS",
"WL_NO_SSID_AVAIL",
"WL_SCAN_COMPLETED",
"WL_CONNECTED",
"WL_CONNECT_FAILED",
"WL_CONNECTION_LOST",
"WL_DISCONNECTED"
};

// provide text for the WiFi mode
const char *str_mode[]= { "WIFI_OFF", "WIFI_STA", "WIFI_AP", "WIFI_AP_STA" };

// change to your server
IPAddress server(185,27,134,11);

WiFiClient client;
WiFiClient dclient;

char outBuf[128];
char outCount;

// change fileName to your file (8.3 format!)
String fileName = "test.txt";
String path = "/test.txt";
// SD file handle
File myFile;

void signalError() { // loop endless with LED blinking in case of error
while(1) {
digitalWrite(BUILTIN_LED2, LOW);
delay(300); // ms
digitalWrite(BUILTIN_LED2, HIGH);
delay(100); // ms
}
}

//format bytes

String formatBytes(size_t bytes) {
if (bytes < 1024) {
return String(bytes) + "B";
} else if (bytes < (1024 * 1024)) {
return String(bytes / 1024.0) + "KB";
} else if (bytes < (1024 * 1024 * 1024)) {
return String(bytes / 1024.0 / 1024.0) + "MB";
} else {
return String(bytes / 1024.0 / 1024.0 / 1024.0) + "GB";
}
}

//----------------------- WiFi handling
void connectWifi() {
Serial.print("Connecting as wifi client to SSID: ");
Serial.println(ssid);
Serial.println("CONECTED");
// use in case of mode problem
WiFi.disconnect();
// switch to Station mode
if (WiFi.getMode() != WIFI_STA) {
WiFi.mode(WIFI_STA);
}

WiFi.begin ( ssid, password );

if (debug ) WiFi.printDiag(Serial);

// ... Give ESP 10 seconds to connect to station.
unsigned long startTime = millis();
while (WiFi.status() != WL_CONNECTED && millis() - startTime < 10000) {
delay(500);
Serial.print(".");
}
Serial.println("");
// Check connection
if (WiFi.status() == WL_CONNECTED) {
Serial.print("WiFi connected; IP address: ");
Serial.println(WiFi.localIP());
} else {
Serial.print("WiFi connect failed to ssid: ");
Serial.println(ssid);
Serial.print("WiFi password <");
Serial.print(password);
Serial.println(">");
Serial.println("Check for wrong typing!");
}
} // connectWiFi()

//----------------- FTP fail
void efail() {
byte thisByte = 0;

client.println(F("QUIT"));

while (!client.available()) delay(1);

while (client.available()) {
thisByte = client.read();
Serial.write(thisByte);
}

client.stop();
Serial.println(F("Command disconnected"));
myFile.close();
Serial.println(F("SD closed"));
} // efail

//-------------- FTP receive
byte eRcv() {
byte respCode;
byte thisByte;

while (!client.available()) delay(1);

respCode = client.peek();

outCount = 0;

while (client.available()) {
thisByte = client.read();
Serial.write(thisByte);

if (outCount < 127) {
  outBuf[outCount] = thisByte;
  outCount++;
  outBuf[outCount] = 0;
}

}

if (respCode >= '4') {
efail();
return 0;
}
return 1;
} // eRcv()

//--------------- FTP handling
byte doFTP(boolean upload) {

if (upload) {
myFile = SD.open(fileName,FILE_READ);
// myFile = SD.open(path, "r");
} else {
SD.remove(path);
myFile = SD.open(fileName,FILE_READ);
// myFile = SD.open(path, "w");
}

if (!myFile) {
Serial.println(F("SD open fail"));
return 0;
}

if (upload) {
if (!myFile.seek(0)) {
Serial.println(F("Rewind fail"));
myFile.close();
return 0;
}
}

if (debug) Serial.println(F("SD opened"));

if (client.connect(server, 21)) { // 21 = FTP server
Serial.println(F("Command connected"));
} else {
myFile.close();
Serial.println(F("Command connection failed"));
return 0;
}

if (!eRcv()) return 0;
if (debug) Serial.println("Send USER");
client.println(F("USER USER"));

if (!eRcv()) return 0;
if (debug) Serial.println("Send PASSWORD");
client.println(F("PASS PASSWORD"));

if (!eRcv()) return 0;
if (debug) Serial.println("Send SYST");
client.println(F("SYST"));

if (!eRcv()) return 0;
if (debug) Serial.println("Send Type I");
client.println(F("Type I"));

if (!eRcv()) return 0;
if (debug) Serial.println("Send PASV");
client.println(F("PASV"));

if (!eRcv()) return 0;

char *tStr = strtok(outBuf, "(,");
int array_pasv[6];
for ( int i = 0; i < 6; i++) {
tStr = strtok(NULL, "(,");
array_pasv[i] = atoi(tStr);
if (tStr == NULL) {
Serial.println(F("Bad PASV Answer"));
}
}
unsigned int hiPort, loPort;
hiPort = array_pasv[4] << 8;
loPort = array_pasv[5] & 255;

if (debug) Serial.print(F("Data port: "));
hiPort = hiPort | loPort;
if (debug) Serial.println(hiPort);

if (dclient.connect(server, hiPort)) {
Serial.println(F("Data connected"));
}
else {
Serial.println(F("Data connection failed"));
client.stop();
myFile.close();
return 0;
}

if (upload) {
if (debug) Serial.println("Send STOR filename");
client.print(F("STOR "));
client.println(fileName);
} else {
if (debug) Serial.println("Send RETR filename");
client.print(F("RETR "));
client.println(fileName);
}

if (!eRcv()) {
dclient.stop();
return 0;
}

if (upload) {
if (debug) Serial.println(F("Writing"));
// for faster upload increase buffer size to 1460
//#define bufSizeFTP 64
#define bufSizeFTP 1460
uint8_t clientBuf[bufSizeFTP];
//unsigned int clientCount = 0;
size_t clientCount = 0;

while (myFile.available()) {
  clientBuf[clientCount] = myFile.read();
  clientCount++;
  if (clientCount > (bufSizeFTP - 1)) {
    dclient.write((const uint8_t *) &clientBuf[0], bufSizeFTP);
    clientCount = 0;
    delay(1);
  }
}
if (clientCount > 0) dclient.write((const uint8_t *) &clientBuf[0], clientCount);

} else {
while (dclient.connected()) {
while (dclient.available()) {
char c = dclient.read();
myFile.write(c);
if (debug) Serial.write(c);
}
}
}

dclient.stop();
Serial.println(F("Data disconnected"));

if (!eRcv()) return 0;

client.println(F("QUIT"));

if (!eRcv()) return 0;

client.stop();
Serial.println(F("Command disconnected"));

myFile.close();
if (debug) Serial.println(F("SPIFS closed"));
return 1;
} // doFTP()

void readSD()
{
myFile = SD.open(fileName,FILE_READ);

if(!myFile)
{
Serial.println(F("SD open fail"));
return;
}

while(myFile.available())
{
Serial.write(myFile.read());
}

myFile.close();
}// read SD card
void setup() {
delay(1000);
Serial.begin(115200);
delay(1000);
Serial.println("Sync,Sync,Sync,Sync,Sync");
delay(500);
Serial.println();
// signal start
pinMode(BUILTIN_LED2, OUTPUT);
digitalWrite(BUILTIN_LED2, LOW);
delay(400); // ms
digitalWrite(BUILTIN_LED2, HIGH);
delay(400); // ms

Serial.print("Chip ID: 0x");
Serial.println(ESP.getChipId(), HEX);

Serial.println ( "Connect to Router requested" );
connectWifi();
if (WiFi.status() == WL_CONNECTED) {
Serial.print("WiFi mode: ");
Serial.println(str_mode[WiFi.getMode()]);
Serial.print ( "Status: " );
Serial.println (str_status[WiFi.status()]);
// signal WiFi connect
digitalWrite(BUILTIN_LED2, LOW);
delay(300); // ms
digitalWrite(BUILTIN_LED2, HIGH);
} else {
Serial.println("");
Serial.println("WiFi connect failed, push RESET button.");
signalError();
}
Serial.print("Initializing SD card...");

if (!SD.begin(4) == 0) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
if (SD.exists("test.txt")) {
Serial.println("test.txt exists.");
}
else {
Serial.println("test.txt doesn't exist.");
}
Serial.println("Creating example.txt...");
myFile = SD.open("example.txt", FILE_WRITE);
myFile.close();

// Check to see if the file exists:

/*
if (SD.exists("example.txt")) {
Serial.println("example.txt exists.");
}
else {
Serial.println("example.txt doesn't exist.");
}
*/
Serial.println(F("Ready. Press d, u or r"));
} // setup()

void loop() {
byte inChar;

if (Serial.available() > 0) {
inChar = Serial.read();
}

boolean upload = true; // false = download

if (inChar == 'd') {
upload = false;
if (doFTP(upload)) Serial.println(F("FTP OK"));
else Serial.println(F("FTP FAIL"));
}

if (inChar == 'u') {
upload = true;
if (doFTP(upload)) Serial.println(F("FTP OK"));
else Serial.println(F("FTP FAIL"));
}

if (inChar == 'r') {
readSD();
}
delay(10); // give time to the WiFi handling in the background
}

`

I can't compile the code it give me error
`
C:\Users\Black\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\SD\src/SD.h:68:5: error: request for member 'read' in 'src', which is of non-class type 'char'

 src.read(obuf, leftLen);

`

MajedRayan commented Nov 13, 2016

Hi rudi48
great work
but can I use SD card instead of SPIFFS
I replace FS.h with SD.h
`
#include <ESP8266WiFi.h>
#include <SPI.h>
#include <SD.h>
// comment out next line to write to SD from FTP server
#define FTPWRITE

// Set these to your desired softAP credentials. They are not configurable at runtime.
const char *ssid = "SSID";
const char *password = "PASSWORD";

//boolean debug = false; // true = more messages
boolean debug = true;
//start using SD
//static bool hasSD = false;

// LED is needed for failure signalling
const short int BUILTIN_LED2 = 16; //GPIO16 on NodeMCU (ESP-12)

unsigned long startTime = millis();

// provide text for the WiFi status
const char *str_status[]= {
"WL_IDLE_STATUS",
"WL_NO_SSID_AVAIL",
"WL_SCAN_COMPLETED",
"WL_CONNECTED",
"WL_CONNECT_FAILED",
"WL_CONNECTION_LOST",
"WL_DISCONNECTED"
};

// provide text for the WiFi mode
const char *str_mode[]= { "WIFI_OFF", "WIFI_STA", "WIFI_AP", "WIFI_AP_STA" };

// change to your server
IPAddress server(185,27,134,11);

WiFiClient client;
WiFiClient dclient;

char outBuf[128];
char outCount;

// change fileName to your file (8.3 format!)
String fileName = "test.txt";
String path = "/test.txt";
// SD file handle
File myFile;

void signalError() { // loop endless with LED blinking in case of error
while(1) {
digitalWrite(BUILTIN_LED2, LOW);
delay(300); // ms
digitalWrite(BUILTIN_LED2, HIGH);
delay(100); // ms
}
}

//format bytes

String formatBytes(size_t bytes) {
if (bytes < 1024) {
return String(bytes) + "B";
} else if (bytes < (1024 * 1024)) {
return String(bytes / 1024.0) + "KB";
} else if (bytes < (1024 * 1024 * 1024)) {
return String(bytes / 1024.0 / 1024.0) + "MB";
} else {
return String(bytes / 1024.0 / 1024.0 / 1024.0) + "GB";
}
}

//----------------------- WiFi handling
void connectWifi() {
Serial.print("Connecting as wifi client to SSID: ");
Serial.println(ssid);
Serial.println("CONECTED");
// use in case of mode problem
WiFi.disconnect();
// switch to Station mode
if (WiFi.getMode() != WIFI_STA) {
WiFi.mode(WIFI_STA);
}

WiFi.begin ( ssid, password );

if (debug ) WiFi.printDiag(Serial);

// ... Give ESP 10 seconds to connect to station.
unsigned long startTime = millis();
while (WiFi.status() != WL_CONNECTED && millis() - startTime < 10000) {
delay(500);
Serial.print(".");
}
Serial.println("");
// Check connection
if (WiFi.status() == WL_CONNECTED) {
Serial.print("WiFi connected; IP address: ");
Serial.println(WiFi.localIP());
} else {
Serial.print("WiFi connect failed to ssid: ");
Serial.println(ssid);
Serial.print("WiFi password <");
Serial.print(password);
Serial.println(">");
Serial.println("Check for wrong typing!");
}
} // connectWiFi()

//----------------- FTP fail
void efail() {
byte thisByte = 0;

client.println(F("QUIT"));

while (!client.available()) delay(1);

while (client.available()) {
thisByte = client.read();
Serial.write(thisByte);
}

client.stop();
Serial.println(F("Command disconnected"));
myFile.close();
Serial.println(F("SD closed"));
} // efail

//-------------- FTP receive
byte eRcv() {
byte respCode;
byte thisByte;

while (!client.available()) delay(1);

respCode = client.peek();

outCount = 0;

while (client.available()) {
thisByte = client.read();
Serial.write(thisByte);

if (outCount < 127) {
  outBuf[outCount] = thisByte;
  outCount++;
  outBuf[outCount] = 0;
}

}

if (respCode >= '4') {
efail();
return 0;
}
return 1;
} // eRcv()

//--------------- FTP handling
byte doFTP(boolean upload) {

if (upload) {
myFile = SD.open(fileName,FILE_READ);
// myFile = SD.open(path, "r");
} else {
SD.remove(path);
myFile = SD.open(fileName,FILE_READ);
// myFile = SD.open(path, "w");
}

if (!myFile) {
Serial.println(F("SD open fail"));
return 0;
}

if (upload) {
if (!myFile.seek(0)) {
Serial.println(F("Rewind fail"));
myFile.close();
return 0;
}
}

if (debug) Serial.println(F("SD opened"));

if (client.connect(server, 21)) { // 21 = FTP server
Serial.println(F("Command connected"));
} else {
myFile.close();
Serial.println(F("Command connection failed"));
return 0;
}

if (!eRcv()) return 0;
if (debug) Serial.println("Send USER");
client.println(F("USER USER"));

if (!eRcv()) return 0;
if (debug) Serial.println("Send PASSWORD");
client.println(F("PASS PASSWORD"));

if (!eRcv()) return 0;
if (debug) Serial.println("Send SYST");
client.println(F("SYST"));

if (!eRcv()) return 0;
if (debug) Serial.println("Send Type I");
client.println(F("Type I"));

if (!eRcv()) return 0;
if (debug) Serial.println("Send PASV");
client.println(F("PASV"));

if (!eRcv()) return 0;

char *tStr = strtok(outBuf, "(,");
int array_pasv[6];
for ( int i = 0; i < 6; i++) {
tStr = strtok(NULL, "(,");
array_pasv[i] = atoi(tStr);
if (tStr == NULL) {
Serial.println(F("Bad PASV Answer"));
}
}
unsigned int hiPort, loPort;
hiPort = array_pasv[4] << 8;
loPort = array_pasv[5] & 255;

if (debug) Serial.print(F("Data port: "));
hiPort = hiPort | loPort;
if (debug) Serial.println(hiPort);

if (dclient.connect(server, hiPort)) {
Serial.println(F("Data connected"));
}
else {
Serial.println(F("Data connection failed"));
client.stop();
myFile.close();
return 0;
}

if (upload) {
if (debug) Serial.println("Send STOR filename");
client.print(F("STOR "));
client.println(fileName);
} else {
if (debug) Serial.println("Send RETR filename");
client.print(F("RETR "));
client.println(fileName);
}

if (!eRcv()) {
dclient.stop();
return 0;
}

if (upload) {
if (debug) Serial.println(F("Writing"));
// for faster upload increase buffer size to 1460
//#define bufSizeFTP 64
#define bufSizeFTP 1460
uint8_t clientBuf[bufSizeFTP];
//unsigned int clientCount = 0;
size_t clientCount = 0;

while (myFile.available()) {
  clientBuf[clientCount] = myFile.read();
  clientCount++;
  if (clientCount > (bufSizeFTP - 1)) {
    dclient.write((const uint8_t *) &clientBuf[0], bufSizeFTP);
    clientCount = 0;
    delay(1);
  }
}
if (clientCount > 0) dclient.write((const uint8_t *) &clientBuf[0], clientCount);

} else {
while (dclient.connected()) {
while (dclient.available()) {
char c = dclient.read();
myFile.write(c);
if (debug) Serial.write(c);
}
}
}

dclient.stop();
Serial.println(F("Data disconnected"));

if (!eRcv()) return 0;

client.println(F("QUIT"));

if (!eRcv()) return 0;

client.stop();
Serial.println(F("Command disconnected"));

myFile.close();
if (debug) Serial.println(F("SPIFS closed"));
return 1;
} // doFTP()

void readSD()
{
myFile = SD.open(fileName,FILE_READ);

if(!myFile)
{
Serial.println(F("SD open fail"));
return;
}

while(myFile.available())
{
Serial.write(myFile.read());
}

myFile.close();
}// read SD card
void setup() {
delay(1000);
Serial.begin(115200);
delay(1000);
Serial.println("Sync,Sync,Sync,Sync,Sync");
delay(500);
Serial.println();
// signal start
pinMode(BUILTIN_LED2, OUTPUT);
digitalWrite(BUILTIN_LED2, LOW);
delay(400); // ms
digitalWrite(BUILTIN_LED2, HIGH);
delay(400); // ms

Serial.print("Chip ID: 0x");
Serial.println(ESP.getChipId(), HEX);

Serial.println ( "Connect to Router requested" );
connectWifi();
if (WiFi.status() == WL_CONNECTED) {
Serial.print("WiFi mode: ");
Serial.println(str_mode[WiFi.getMode()]);
Serial.print ( "Status: " );
Serial.println (str_status[WiFi.status()]);
// signal WiFi connect
digitalWrite(BUILTIN_LED2, LOW);
delay(300); // ms
digitalWrite(BUILTIN_LED2, HIGH);
} else {
Serial.println("");
Serial.println("WiFi connect failed, push RESET button.");
signalError();
}
Serial.print("Initializing SD card...");

if (!SD.begin(4) == 0) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
if (SD.exists("test.txt")) {
Serial.println("test.txt exists.");
}
else {
Serial.println("test.txt doesn't exist.");
}
Serial.println("Creating example.txt...");
myFile = SD.open("example.txt", FILE_WRITE);
myFile.close();

// Check to see if the file exists:

/*
if (SD.exists("example.txt")) {
Serial.println("example.txt exists.");
}
else {
Serial.println("example.txt doesn't exist.");
}
*/
Serial.println(F("Ready. Press d, u or r"));
} // setup()

void loop() {
byte inChar;

if (Serial.available() > 0) {
inChar = Serial.read();
}

boolean upload = true; // false = download

if (inChar == 'd') {
upload = false;
if (doFTP(upload)) Serial.println(F("FTP OK"));
else Serial.println(F("FTP FAIL"));
}

if (inChar == 'u') {
upload = true;
if (doFTP(upload)) Serial.println(F("FTP OK"));
else Serial.println(F("FTP FAIL"));
}

if (inChar == 'r') {
readSD();
}
delay(10); // give time to the WiFi handling in the background
}

`

I can't compile the code it give me error
`
C:\Users\Black\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\SD\src/SD.h:68:5: error: request for member 'read' in 'src', which is of non-class type 'char'

 src.read(obuf, leftLen);

`

@cow77

This comment has been minimized.

Show comment
Hide comment
@cow77

cow77 Nov 14, 2016

If in doFTP you change:
while (dclient.connected()) {
while (dclient.available()) {
char c = dclient.read();
myFile.write(c);
if (debug) Serial.write(c);
}
}

to

while (dclient.connected()) {
  while (dclient.available()) {
    byte c = dclient.read();
    myFile.write(c);
    if (debug) Serial.write(c);
  }
}

(char changed to byte), at least it compiles error-free.

cow77 commented Nov 14, 2016

If in doFTP you change:
while (dclient.connected()) {
while (dclient.available()) {
char c = dclient.read();
myFile.write(c);
if (debug) Serial.write(c);
}
}

to

while (dclient.connected()) {
  while (dclient.available()) {
    byte c = dclient.read();
    myFile.write(c);
    if (debug) Serial.write(c);
  }
}

(char changed to byte), at least it compiles error-free.

@Stangl1

This comment has been minimized.

Show comment
Hide comment
@Stangl1

Stangl1 Jul 15, 2017

Hallo Rudi,
schönes Projekt, läuft bei mir soweit.
Nun habe ich die Sache auf meinen Webserver (ESP8266) versucht, da bekomme ich keine Verbindung.
Läuft die ganze Sache nur als Client?
Möchte von meinem Server (ESP8266) Daten auf einen WebSpace (WWW) speichern.
Wie gesagt als Client schaffe ich das mit einem Testprogamm.
Ist sowas grundsätzlich möglich?
Danke.

Stangl1 commented Jul 15, 2017

Hallo Rudi,
schönes Projekt, läuft bei mir soweit.
Nun habe ich die Sache auf meinen Webserver (ESP8266) versucht, da bekomme ich keine Verbindung.
Läuft die ganze Sache nur als Client?
Möchte von meinem Server (ESP8266) Daten auf einen WebSpace (WWW) speichern.
Wie gesagt als Client schaffe ich das mit einem Testprogamm.
Ist sowas grundsätzlich möglich?
Danke.

@Stangl1

This comment has been minimized.

Show comment
Hide comment
@Stangl1

Stangl1 Jul 15, 2017

Hier der Code, funktionier leider nur als Client.

/*
This file modifies SurferTim's FTP code (http://playground.arduino.cc/Code/FTP)
to work with the esp8266 chip.This only contains the functionality to upload
a file to your server but additional functionality could easily be added by
modifying the code starting at line 202. Functionality would be implemented using
raw FTP commands. A list of such commands can be found at: http://www.nsftools.com/tips/RawFTP.htm

#1183
http://www.esp8266.com/viewtopic.php?f=29&t=13956

The HTML files are dummys, they are created by my ESP8266 WiFi Server.
This is just do test FTP-Upload and see if the external Web-Server (apache) works.
*/

//#define FORMAT // To format the SPIFFS if needed
#define DEBUG // Use this for DEBUG-Mode

#include <ESP8266WiFi.h>
#include <FS.h>

const char* VERSION = "Easy-Pool VX.17.07.15";

// Toggle LED_BUILTIN without delay
unsigned long LedDelta_ms = 750; // distance to next toggle time 750 ms
unsigned long LedNext_ms; // next toggle time

//Change these variables to meet your needs
const char* ssid = "3370";
const char *wpwd = "xxx";

// FTP stuff
const char* host = "v45858.1blu.de"; // External Server, try out :-)
const char* userName = "xxx";
const char* password = "xxx";

// FTP upload Interval without delay
unsigned long ftpDelta_ms = 60000 * 2; // distance to next Upload
unsigned long ftpNext_ms; // next Upload-Time

// File Operation
String ftpFile = "";
char ftpPath[20] = "/var/www"; // Path to the Apache-Webserver on my external Web-Space

// DO NOT CHANGE THESE
char outBuf[128];
char outCount;

extern "C" { // needed to avoid link error on ram check
#include "user_interface.h"
}

#define LED_PIN LED_BUILTIN

IPAddress ip(192, 168, 1, 115);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);

WiFiClient client;
WiFiClient dclient;

void setup() {
pinMode(LED_PIN, OUTPUT);

#ifdef DEBUG // If DEBUG is defined you will see something on your Serial-Screen, this is not to save Memmory
// Serial Setup
Serial.begin(19200);
#endif

//WiFi Setup
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.config(ip, gateway, subnet);
WiFi.begin ( ssid, wpwd );
while (WiFi.status() != WL_CONNECTED) {
delay(250);
Serial.print(".");
}

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

#ifdef FORMAT
// Next lines have to be done ONLY ONCE!!!!!When SPIFFS is formatted ONCE you can comment these lines out!!
Serial.println(F("Please wait 30 secs for SPIFFS to be formatted"));
SPIFFS.format();
Serial.println(F("Spiffs formatted"));
listFileSystem();
#endif

SPIFFS.begin();

Serial.println(F("Setup done..."));
yield();
}

void loop() {
if (millis() >= LedNext_ms) { // Toggle LED_BUILTIN without delay
LedNext_ms = millis() + LedDelta_ms;
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
}

if (millis() >= ftpNext_ms) { // Toggle LED_BUILTIN without delay
ftpNext_ms = millis() + ftpDelta_ms;

ftpFile = "/index.html";
FTPUpload(1);

ftpFile = "/dayly.html";
FTPUpload(2);

ftpFile = "/monthly.html";
FTPUpload(3);

}
yield();
}// END loop

void FTPUpload(int var) {
File f = SPIFFS.open(ftpFile, "w");
if (!f) {
Serial.println("File open failed");
}
else {
Serial.println("Writing file...");

switch (var) {
  case 1:
    //do something when var equals 1
    f.print(MakeIndexHtml());
    break;
  case 2:
    //do something when var equals 2
    f.print(MakeDaylyHtml());
    break;
  case 3:
    //do something when var equals 2
    f.print(MakeMonthlyHtml());
    break;
}
f.close();

Serial.println();
listFileSystem();

if (doFTP()) Serial.println(F("FTP OK"));
else Serial.println(F("FTP FAIL"));

}
yield();
}

void listFileSystem() {
String str = "";
Dir dir = SPIFFS.openDir("/");
while (dir.next()) {
str += dir.fileName();
str += " / ";
str += dir.fileSize();
str += "\n";
}
Serial.println(str); // See more at: http://www.esp8266.com/viewtopic.php?f=32&t=8459#sthash.WhKhnV58.dpuf
yield();
}

String MakeIndexHtml() {
String sResponse1;
sResponse1 = "";

sResponse1 = F("\n");
sResponse1 += F("\n");
sResponse1 += F("<title>Easy-Pool</title>\n");
//sResponse1 += F("<meta http-equiv="refresh" content="30">\n"); // Auto-Refresh every XX sec.
sResponse1 += F("\n");
sResponse1 += F("<body bgcolor="FFCC99">\n");
sResponse1 += F("<h1 align="center">Easy-Pool\n");
sResponse1 += F("<table border ="1" width="50%" align="center" bgcolor="E0D0F0">\n");

sResponse1 += F("<th colspan="2"><font size="7">");
sResponse1 += F("Luft: ");
sResponse1 += "23.23";
sResponse1 += F("&degC");
sResponse1 += F("\n");

sResponse1 += F("<th colspan="2"><font size="7">");
sResponse1 += F("Coll: ");
sResponse1 += "24.24";
sResponse1 += F("&degC");
sResponse1 += F("\n");

sResponse1 += F("<th colspan="2"><font size="7">");
sResponse1 += F("Pump: ");
sResponse1 += F("OFF");
sResponse1 += F("\n");

sResponse1 += F("<td align="center"><font size="6">");
sResponse1 += "23.01.1968";
sResponse1 += F("<td align="center"><font size="6">");
sResponse1 += "23:01";
sResponse1 += F("\n");

sResponse1 += F("<td align="center" colspan="2">");
sResponse1 += F("<a href="/dayly">Grafik\n");
sResponse1 += F("\n");
sResponse1 += F("
\n");
sResponse1 += F("

\nFreies RAM=");
sResponse1 += (uint32_t)system_get_free_heap_size();
sResponse1 += F("
\nC. Stanglmeier ");
sResponse1 += VERSION;
sResponse1 += F("\n");
sResponse1 += F("\n\n");
sResponse1 += F("");

return sResponse1;
yield();
}

String MakeDaylyHtml() {
String sResponse1;
sResponse1 = "";

sResponse1 = F("\n");
sResponse1 += F("\n");
sResponse1 += F("<title>Easy-Pool - Grafik</title>\n");

sResponse1 += F("<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js\"></script>\n");
sResponse1 += F("<script type="text/javascript">\n");
sResponse1 += F("google.charts.load('current', {'packages':['corechart']});\n");
sResponse1 += F("google.charts.setOnLoadCallback(drawChart);\n");
sResponse1 += F("function drawChart() {\n");
sResponse1 += F("var data = google.visualization.arrayToDataTable([\n");
sResponse1 += F("['Zeit', 'Luft', 'Coll'],\n");
// here the big list
sResponse1 += F("['15.07.2017-00:06',15.56,14.69],\n");
sResponse1 += F("['15.07.2017-00:13',15.56,14.50],\n");
sResponse1 += F("['15.07.2017-00:20',15.44,14.31],\n");
sResponse1 += F("['15.07.2017-00:27',15.38,14.19],\n");
sResponse1 += F("['15.07.2017-00:34',15.44,14.06],\n");
sResponse1 += F("['15.07.2017-00:41',15.19,14.06],\n");
sResponse1 += F("['15.07.2017-00:48',15.25,14.19],\n");
sResponse1 += F("['15.07.2017-00:55',13.69,14.19],\n");
sResponse1 += F("['15.07.2017-01:02',13.25,13.88],\n");
sResponse1 += F("['15.07.2017-01:09',13.38,13.50],\n");
sResponse1 += F("['15.07.2017-01:16',13.25,13.31],\n");
sResponse1 += F("['15.07.2017-01:23',13.06,13.25],\n");
sResponse1 += F("['15.07.2017-01:30',13.31,13.13],\n");
sResponse1 += F("['15.07.2017-01:37',13.25,13.06],\n");
sResponse1 += F("['15.07.2017-01:44',13.38,12.94],\n");
sResponse1 += F("['15.07.2017-01:51',13.50,12.88],\n");
sResponse1 += F("['15.07.2017-01:58',13.13,12.94],\n");
sResponse1 += F("['15.07.2017-02:05',13.19,12.88],\n");
sResponse1 += F("['15.07.2017-02:12',13.38,12.81],\n");
sResponse1 += F("['15.07.2017-02:19',13.38,12.75],\n");
// part 2 of response - after the big list
sResponse1 += F("]);\n");
sResponse1 += F("var options = {\n");

sResponse1 += F("title: 'Tagesverlauf', curveType: 'function', legend:{position: 'bottom'}}\n");

sResponse1 += F("var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));\n");
sResponse1 += F("chart.draw(data, options)};\n");
sResponse1 += F("</script>\n\n\n");
sResponse1 += F("<font color="#000000"><body bgcolor="#FFCC99"><meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">\n");
sResponse1 += F("

Easy-Pool - Grafik

\n");
sResponse1 += F("\n");
sResponse1 += F("<a href="/">Startseite

\n");

sResponse1 += F("<div id="curve_chart" style="width: 800px; height: 400px">
\n");

sResponse1 += F("<a href="monthly">Monat
\n");

sResponse1 += F("
\n");
sResponse1 += F("Freies RAM=");
sResponse1 += (uint32_t)system_get_free_heap_size();
sResponse1 += F("
\nC. Stanglmeier ");
sResponse1 += VERSION;
sResponse1 += F("\n");
sResponse1 += F("

\n\n");
sResponse1 += F("");

return sResponse1;
yield();
}

String MakeMonthlyHtml() {
String sResponse1;
sResponse1 = "";

sResponse1 = F("\n");
sResponse1 += F("\n");
sResponse1 += F("<title>Easy-Pool - Grafik</title>\n");

sResponse1 += F("<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js\"></script>\n");
sResponse1 += F("<script type="text/javascript">\n");
sResponse1 += F("google.charts.load('current', {'packages':['corechart']});\n");
sResponse1 += F("google.charts.setOnLoadCallback(drawChart);\n");
sResponse1 += F("function drawChart() {\n");
sResponse1 += F("var data = google.visualization.arrayToDataTable([\n");
sResponse1 += F("['Zeit', 'Luft', 'Coll'],\n");
// here the big list
sResponse1 += F("['13.07.2017-18:44',23.94,24.25],\n");
sResponse1 += F("['13.07.2017-18:46',23.88,24.25],\n");
sResponse1 += F("['13.07.2017-18:49',23.81,24.25],\n");
sResponse1 += F("['13.07.2017-18:56',23.13,22.25],\n");
sResponse1 += F("['13.07.2017-19:10',21.06,33.25],\n");
sResponse1 += F("['13.07.2017-19:55',20.38,26.44],\n");
sResponse1 += F("['13.07.2017-20:40',19.44,21.31],\n");
sResponse1 += F("['13.07.2017-21:25',18.19,17.94],\n");
sResponse1 += F("['13.07.2017-22:10',17.31,15.69],\n");
sResponse1 += F("['13.07.2017-22:55',16.44,14.56],\n");
sResponse1 += F("['13.07.2017-23:40',15.94,13.50],\n");
sResponse1 += F("['14.07.2017-00:25',15.06,12.81],\n");
sResponse1 += F("['14.07.2017-01:10',14.38,12.06],\n");
sResponse1 += F("['14.07.2017-01:55',14.50,11.88],\n");
sResponse1 += F("['14.07.2017-02:40',14.88,13.00],\n");
sResponse1 += F("['14.07.2017-03:25',15.06,13.75],\n");
sResponse1 += F("['14.07.2017-04:10',14.31,13.13],\n");
sResponse1 += F("['14.07.2017-04:55',14.13,12.25],\n");
sResponse1 += F("['14.07.2017-05:40',14.13,12.63],\n");
sResponse1 += F("['14.07.2017-06:25',12.63,13.31],\n");
sResponse1 += F("['14.07.2017-07:10',13.00,14.31],\n");
sResponse1 += F("['14.07.2017-07:55',13.38,16.00],\n");
sResponse1 += F("['14.07.2017-08:40',13.75,19.69],\n");
sResponse1 += F("['14.07.2017-09:25',14.75,35.00],\n");
sResponse1 += F("['14.07.2017-10:10',16.13,48.44],\n");
// part 2 of response - after the big list
sResponse1 += F("]);\n");
sResponse1 += F("var options = {\n");

sResponse1 += F("title: 'Tagesverlauf', curveType: 'function', legend:{position: 'bottom'}}\n");

sResponse1 += F("var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));\n");
sResponse1 += F("chart.draw(data, options)};\n");
sResponse1 += F("</script>\n\n\n");
sResponse1 += F("<font color="#000000"><body bgcolor="#FFCC99"><meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">\n");
sResponse1 += F("

Easy-Pool - Grafik

\n");
sResponse1 += F("\n");
sResponse1 += F("<a href="/">Startseite

\n");

sResponse1 += F("<div id="curve_chart" style="width: 800px; height: 400px">
\n");

sResponse1 += F("<a href="dayly">Heute
\n");

sResponse1 += F("
\n");
sResponse1 += F("Freies RAM=");
sResponse1 += (uint32_t)system_get_free_heap_size();
sResponse1 += F("
\nC. Stanglmeier ");
sResponse1 += VERSION;
sResponse1 += F("\n");
sResponse1 += F("

\n\n");
sResponse1 += F("");

return sResponse1;
yield();
}
/*
This is the function where the magic happens.
all credit goes to SurferTim. This will open
and write the file to your FTP server
*/
byte doFTP() {
File fh = SPIFFS.open(ftpFile, "r");
if (!fh) {
Serial.println("file open failed");
}
if (client.connect(host, 21)) {
Serial.println(F("Command connected"));
}
else {
fh.close();
Serial.println(F("Command connection failed"));
return 0;
}

if (!eRcv()) return 0;

client.print("USER ");
client.println(userName);

if (!eRcv()) return 0;

client.print("PASS ");
client.println(password);

if (!eRcv()) return 0;

client.println("SYST");

if (!eRcv()) return 0;

client.println("Type I");

if (!eRcv()) return 0;

client.println("PASV");

if (!eRcv()) return 0;

char *tStr = strtok(outBuf, "(,");
int array_pasv[6];
for ( int i = 0; i < 6; i++) {
tStr = strtok(NULL, "(,");
array_pasv[i] = atoi(tStr);
if (tStr == NULL) {
Serial.println(F("Bad PASV Answer"));
}
}

unsigned int hiPort, loPort;
hiPort = array_pasv[4] << 8;
loPort = array_pasv[5] & 255;
Serial.print(F("Data port: "));
hiPort = hiPort | loPort;
Serial.println(hiPort);
if (dclient.connect(host, hiPort)) {
Serial.println("Data connected");
}
else {
Serial.println("Data connection failed");
client.stop();
fh.close();
}

client.print("STOR ");
client.print(ftpPath); client.println(ftpFile);
if (!eRcv()) {
dclient.stop();
return 0;
}
Serial.println(F("Writing"));

byte clientBuf[64];
int clientCount = 0;

while (fh.available()) {
clientBuf[clientCount] = fh.read();
clientCount++;

if (clientCount > 63)    {
  dclient.write((const uint8_t *)clientBuf, 64);
  clientCount = 0;
}

}
if (clientCount > 0) dclient.write((const uint8_t *)clientBuf, clientCount);

dclient.stop();
Serial.println(F("Data disconnected"));
client.println();
if (!eRcv()) return 0;

client.println("QUIT");

if (!eRcv()) return 0;

client.stop();
Serial.println(F("Command disconnected"));

fh.close();
Serial.println(F("File closed"));
return 1;
yield();
}

byte eRcv() {
byte respCode;
byte thisByte;

while (!client.available()) delay(1);
respCode = client.peek();
outCount = 0;
while (client.available()) {
thisByte = client.read();
Serial.write(thisByte);
if (outCount < 127) {
outBuf[outCount] = thisByte;
outCount++;
outBuf[outCount] = 0;
}
}
if (respCode >= '4') {
efail();
return 0;
}
return 1;
yield();
}

void efail() {
byte thisByte = 0;
client.println(F("QUIT"));
while (!client.available()) delay(1);
while (client.available()) {
thisByte = client.read();
Serial.write(thisByte);
}
client.stop();
Serial.println(F("Command disconnected"));
yield();
}

Stangl1 commented Jul 15, 2017

Hier der Code, funktionier leider nur als Client.

/*
This file modifies SurferTim's FTP code (http://playground.arduino.cc/Code/FTP)
to work with the esp8266 chip.This only contains the functionality to upload
a file to your server but additional functionality could easily be added by
modifying the code starting at line 202. Functionality would be implemented using
raw FTP commands. A list of such commands can be found at: http://www.nsftools.com/tips/RawFTP.htm

#1183
http://www.esp8266.com/viewtopic.php?f=29&t=13956

The HTML files are dummys, they are created by my ESP8266 WiFi Server.
This is just do test FTP-Upload and see if the external Web-Server (apache) works.
*/

//#define FORMAT // To format the SPIFFS if needed
#define DEBUG // Use this for DEBUG-Mode

#include <ESP8266WiFi.h>
#include <FS.h>

const char* VERSION = "Easy-Pool VX.17.07.15";

// Toggle LED_BUILTIN without delay
unsigned long LedDelta_ms = 750; // distance to next toggle time 750 ms
unsigned long LedNext_ms; // next toggle time

//Change these variables to meet your needs
const char* ssid = "3370";
const char *wpwd = "xxx";

// FTP stuff
const char* host = "v45858.1blu.de"; // External Server, try out :-)
const char* userName = "xxx";
const char* password = "xxx";

// FTP upload Interval without delay
unsigned long ftpDelta_ms = 60000 * 2; // distance to next Upload
unsigned long ftpNext_ms; // next Upload-Time

// File Operation
String ftpFile = "";
char ftpPath[20] = "/var/www"; // Path to the Apache-Webserver on my external Web-Space

// DO NOT CHANGE THESE
char outBuf[128];
char outCount;

extern "C" { // needed to avoid link error on ram check
#include "user_interface.h"
}

#define LED_PIN LED_BUILTIN

IPAddress ip(192, 168, 1, 115);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);

WiFiClient client;
WiFiClient dclient;

void setup() {
pinMode(LED_PIN, OUTPUT);

#ifdef DEBUG // If DEBUG is defined you will see something on your Serial-Screen, this is not to save Memmory
// Serial Setup
Serial.begin(19200);
#endif

//WiFi Setup
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.config(ip, gateway, subnet);
WiFi.begin ( ssid, wpwd );
while (WiFi.status() != WL_CONNECTED) {
delay(250);
Serial.print(".");
}

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

#ifdef FORMAT
// Next lines have to be done ONLY ONCE!!!!!When SPIFFS is formatted ONCE you can comment these lines out!!
Serial.println(F("Please wait 30 secs for SPIFFS to be formatted"));
SPIFFS.format();
Serial.println(F("Spiffs formatted"));
listFileSystem();
#endif

SPIFFS.begin();

Serial.println(F("Setup done..."));
yield();
}

void loop() {
if (millis() >= LedNext_ms) { // Toggle LED_BUILTIN without delay
LedNext_ms = millis() + LedDelta_ms;
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
}

if (millis() >= ftpNext_ms) { // Toggle LED_BUILTIN without delay
ftpNext_ms = millis() + ftpDelta_ms;

ftpFile = "/index.html";
FTPUpload(1);

ftpFile = "/dayly.html";
FTPUpload(2);

ftpFile = "/monthly.html";
FTPUpload(3);

}
yield();
}// END loop

void FTPUpload(int var) {
File f = SPIFFS.open(ftpFile, "w");
if (!f) {
Serial.println("File open failed");
}
else {
Serial.println("Writing file...");

switch (var) {
  case 1:
    //do something when var equals 1
    f.print(MakeIndexHtml());
    break;
  case 2:
    //do something when var equals 2
    f.print(MakeDaylyHtml());
    break;
  case 3:
    //do something when var equals 2
    f.print(MakeMonthlyHtml());
    break;
}
f.close();

Serial.println();
listFileSystem();

if (doFTP()) Serial.println(F("FTP OK"));
else Serial.println(F("FTP FAIL"));

}
yield();
}

void listFileSystem() {
String str = "";
Dir dir = SPIFFS.openDir("/");
while (dir.next()) {
str += dir.fileName();
str += " / ";
str += dir.fileSize();
str += "\n";
}
Serial.println(str); // See more at: http://www.esp8266.com/viewtopic.php?f=32&t=8459#sthash.WhKhnV58.dpuf
yield();
}

String MakeIndexHtml() {
String sResponse1;
sResponse1 = "";

sResponse1 = F("\n");
sResponse1 += F("\n");
sResponse1 += F("<title>Easy-Pool</title>\n");
//sResponse1 += F("<meta http-equiv="refresh" content="30">\n"); // Auto-Refresh every XX sec.
sResponse1 += F("\n");
sResponse1 += F("<body bgcolor="FFCC99">\n");
sResponse1 += F("<h1 align="center">Easy-Pool\n");
sResponse1 += F("<table border ="1" width="50%" align="center" bgcolor="E0D0F0">\n");

sResponse1 += F("<th colspan="2"><font size="7">");
sResponse1 += F("Luft: ");
sResponse1 += "23.23";
sResponse1 += F("&degC");
sResponse1 += F("\n");

sResponse1 += F("<th colspan="2"><font size="7">");
sResponse1 += F("Coll: ");
sResponse1 += "24.24";
sResponse1 += F("&degC");
sResponse1 += F("\n");

sResponse1 += F("<th colspan="2"><font size="7">");
sResponse1 += F("Pump: ");
sResponse1 += F("OFF");
sResponse1 += F("\n");

sResponse1 += F("<td align="center"><font size="6">");
sResponse1 += "23.01.1968";
sResponse1 += F("<td align="center"><font size="6">");
sResponse1 += "23:01";
sResponse1 += F("\n");

sResponse1 += F("<td align="center" colspan="2">");
sResponse1 += F("<a href="/dayly">Grafik\n");
sResponse1 += F("\n");
sResponse1 += F("
\n");
sResponse1 += F("

\nFreies RAM=");
sResponse1 += (uint32_t)system_get_free_heap_size();
sResponse1 += F("
\nC. Stanglmeier ");
sResponse1 += VERSION;
sResponse1 += F("\n");
sResponse1 += F("\n\n");
sResponse1 += F("");

return sResponse1;
yield();
}

String MakeDaylyHtml() {
String sResponse1;
sResponse1 = "";

sResponse1 = F("\n");
sResponse1 += F("\n");
sResponse1 += F("<title>Easy-Pool - Grafik</title>\n");

sResponse1 += F("<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js\"></script>\n");
sResponse1 += F("<script type="text/javascript">\n");
sResponse1 += F("google.charts.load('current', {'packages':['corechart']});\n");
sResponse1 += F("google.charts.setOnLoadCallback(drawChart);\n");
sResponse1 += F("function drawChart() {\n");
sResponse1 += F("var data = google.visualization.arrayToDataTable([\n");
sResponse1 += F("['Zeit', 'Luft', 'Coll'],\n");
// here the big list
sResponse1 += F("['15.07.2017-00:06',15.56,14.69],\n");
sResponse1 += F("['15.07.2017-00:13',15.56,14.50],\n");
sResponse1 += F("['15.07.2017-00:20',15.44,14.31],\n");
sResponse1 += F("['15.07.2017-00:27',15.38,14.19],\n");
sResponse1 += F("['15.07.2017-00:34',15.44,14.06],\n");
sResponse1 += F("['15.07.2017-00:41',15.19,14.06],\n");
sResponse1 += F("['15.07.2017-00:48',15.25,14.19],\n");
sResponse1 += F("['15.07.2017-00:55',13.69,14.19],\n");
sResponse1 += F("['15.07.2017-01:02',13.25,13.88],\n");
sResponse1 += F("['15.07.2017-01:09',13.38,13.50],\n");
sResponse1 += F("['15.07.2017-01:16',13.25,13.31],\n");
sResponse1 += F("['15.07.2017-01:23',13.06,13.25],\n");
sResponse1 += F("['15.07.2017-01:30',13.31,13.13],\n");
sResponse1 += F("['15.07.2017-01:37',13.25,13.06],\n");
sResponse1 += F("['15.07.2017-01:44',13.38,12.94],\n");
sResponse1 += F("['15.07.2017-01:51',13.50,12.88],\n");
sResponse1 += F("['15.07.2017-01:58',13.13,12.94],\n");
sResponse1 += F("['15.07.2017-02:05',13.19,12.88],\n");
sResponse1 += F("['15.07.2017-02:12',13.38,12.81],\n");
sResponse1 += F("['15.07.2017-02:19',13.38,12.75],\n");
// part 2 of response - after the big list
sResponse1 += F("]);\n");
sResponse1 += F("var options = {\n");

sResponse1 += F("title: 'Tagesverlauf', curveType: 'function', legend:{position: 'bottom'}}\n");

sResponse1 += F("var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));\n");
sResponse1 += F("chart.draw(data, options)};\n");
sResponse1 += F("</script>\n\n\n");
sResponse1 += F("<font color="#000000"><body bgcolor="#FFCC99"><meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">\n");
sResponse1 += F("

Easy-Pool - Grafik

\n");
sResponse1 += F("\n");
sResponse1 += F("<a href="/">Startseite

\n");

sResponse1 += F("<div id="curve_chart" style="width: 800px; height: 400px">
\n");

sResponse1 += F("<a href="monthly">Monat
\n");

sResponse1 += F("
\n");
sResponse1 += F("Freies RAM=");
sResponse1 += (uint32_t)system_get_free_heap_size();
sResponse1 += F("
\nC. Stanglmeier ");
sResponse1 += VERSION;
sResponse1 += F("\n");
sResponse1 += F("

\n\n");
sResponse1 += F("");

return sResponse1;
yield();
}

String MakeMonthlyHtml() {
String sResponse1;
sResponse1 = "";

sResponse1 = F("\n");
sResponse1 += F("\n");
sResponse1 += F("<title>Easy-Pool - Grafik</title>\n");

sResponse1 += F("<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js\"></script>\n");
sResponse1 += F("<script type="text/javascript">\n");
sResponse1 += F("google.charts.load('current', {'packages':['corechart']});\n");
sResponse1 += F("google.charts.setOnLoadCallback(drawChart);\n");
sResponse1 += F("function drawChart() {\n");
sResponse1 += F("var data = google.visualization.arrayToDataTable([\n");
sResponse1 += F("['Zeit', 'Luft', 'Coll'],\n");
// here the big list
sResponse1 += F("['13.07.2017-18:44',23.94,24.25],\n");
sResponse1 += F("['13.07.2017-18:46',23.88,24.25],\n");
sResponse1 += F("['13.07.2017-18:49',23.81,24.25],\n");
sResponse1 += F("['13.07.2017-18:56',23.13,22.25],\n");
sResponse1 += F("['13.07.2017-19:10',21.06,33.25],\n");
sResponse1 += F("['13.07.2017-19:55',20.38,26.44],\n");
sResponse1 += F("['13.07.2017-20:40',19.44,21.31],\n");
sResponse1 += F("['13.07.2017-21:25',18.19,17.94],\n");
sResponse1 += F("['13.07.2017-22:10',17.31,15.69],\n");
sResponse1 += F("['13.07.2017-22:55',16.44,14.56],\n");
sResponse1 += F("['13.07.2017-23:40',15.94,13.50],\n");
sResponse1 += F("['14.07.2017-00:25',15.06,12.81],\n");
sResponse1 += F("['14.07.2017-01:10',14.38,12.06],\n");
sResponse1 += F("['14.07.2017-01:55',14.50,11.88],\n");
sResponse1 += F("['14.07.2017-02:40',14.88,13.00],\n");
sResponse1 += F("['14.07.2017-03:25',15.06,13.75],\n");
sResponse1 += F("['14.07.2017-04:10',14.31,13.13],\n");
sResponse1 += F("['14.07.2017-04:55',14.13,12.25],\n");
sResponse1 += F("['14.07.2017-05:40',14.13,12.63],\n");
sResponse1 += F("['14.07.2017-06:25',12.63,13.31],\n");
sResponse1 += F("['14.07.2017-07:10',13.00,14.31],\n");
sResponse1 += F("['14.07.2017-07:55',13.38,16.00],\n");
sResponse1 += F("['14.07.2017-08:40',13.75,19.69],\n");
sResponse1 += F("['14.07.2017-09:25',14.75,35.00],\n");
sResponse1 += F("['14.07.2017-10:10',16.13,48.44],\n");
// part 2 of response - after the big list
sResponse1 += F("]);\n");
sResponse1 += F("var options = {\n");

sResponse1 += F("title: 'Tagesverlauf', curveType: 'function', legend:{position: 'bottom'}}\n");

sResponse1 += F("var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));\n");
sResponse1 += F("chart.draw(data, options)};\n");
sResponse1 += F("</script>\n\n\n");
sResponse1 += F("<font color="#000000"><body bgcolor="#FFCC99"><meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">\n");
sResponse1 += F("

Easy-Pool - Grafik

\n");
sResponse1 += F("\n");
sResponse1 += F("<a href="/">Startseite

\n");

sResponse1 += F("<div id="curve_chart" style="width: 800px; height: 400px">
\n");

sResponse1 += F("<a href="dayly">Heute
\n");

sResponse1 += F("
\n");
sResponse1 += F("Freies RAM=");
sResponse1 += (uint32_t)system_get_free_heap_size();
sResponse1 += F("
\nC. Stanglmeier ");
sResponse1 += VERSION;
sResponse1 += F("\n");
sResponse1 += F("

\n\n");
sResponse1 += F("");

return sResponse1;
yield();
}
/*
This is the function where the magic happens.
all credit goes to SurferTim. This will open
and write the file to your FTP server
*/
byte doFTP() {
File fh = SPIFFS.open(ftpFile, "r");
if (!fh) {
Serial.println("file open failed");
}
if (client.connect(host, 21)) {
Serial.println(F("Command connected"));
}
else {
fh.close();
Serial.println(F("Command connection failed"));
return 0;
}

if (!eRcv()) return 0;

client.print("USER ");
client.println(userName);

if (!eRcv()) return 0;

client.print("PASS ");
client.println(password);

if (!eRcv()) return 0;

client.println("SYST");

if (!eRcv()) return 0;

client.println("Type I");

if (!eRcv()) return 0;

client.println("PASV");

if (!eRcv()) return 0;

char *tStr = strtok(outBuf, "(,");
int array_pasv[6];
for ( int i = 0; i < 6; i++) {
tStr = strtok(NULL, "(,");
array_pasv[i] = atoi(tStr);
if (tStr == NULL) {
Serial.println(F("Bad PASV Answer"));
}
}

unsigned int hiPort, loPort;
hiPort = array_pasv[4] << 8;
loPort = array_pasv[5] & 255;
Serial.print(F("Data port: "));
hiPort = hiPort | loPort;
Serial.println(hiPort);
if (dclient.connect(host, hiPort)) {
Serial.println("Data connected");
}
else {
Serial.println("Data connection failed");
client.stop();
fh.close();
}

client.print("STOR ");
client.print(ftpPath); client.println(ftpFile);
if (!eRcv()) {
dclient.stop();
return 0;
}
Serial.println(F("Writing"));

byte clientBuf[64];
int clientCount = 0;

while (fh.available()) {
clientBuf[clientCount] = fh.read();
clientCount++;

if (clientCount > 63)    {
  dclient.write((const uint8_t *)clientBuf, 64);
  clientCount = 0;
}

}
if (clientCount > 0) dclient.write((const uint8_t *)clientBuf, clientCount);

dclient.stop();
Serial.println(F("Data disconnected"));
client.println();
if (!eRcv()) return 0;

client.println("QUIT");

if (!eRcv()) return 0;

client.stop();
Serial.println(F("Command disconnected"));

fh.close();
Serial.println(F("File closed"));
return 1;
yield();
}

byte eRcv() {
byte respCode;
byte thisByte;

while (!client.available()) delay(1);
respCode = client.peek();
outCount = 0;
while (client.available()) {
thisByte = client.read();
Serial.write(thisByte);
if (outCount < 127) {
outBuf[outCount] = thisByte;
outCount++;
outBuf[outCount] = 0;
}
}
if (respCode >= '4') {
efail();
return 0;
}
return 1;
yield();
}

void efail() {
byte thisByte = 0;
client.println(F("QUIT"));
while (!client.available()) delay(1);
while (client.available()) {
thisByte = client.read();
Serial.write(thisByte);
}
client.stop();
Serial.println(F("Command disconnected"));
yield();
}

@rudi48

This comment has been minimized.

Show comment
Hide comment
@rudi48

rudi48 Jul 16, 2017

@Stangl1
This is a FTP client only, because a FTP server is already contained in the ESP8266 examples. Just the FTP client was missing.

rudi48 commented Jul 16, 2017

@Stangl1
This is a FTP client only, because a FTP server is already contained in the ESP8266 examples. Just the FTP client was missing.

@Stangl1

This comment has been minimized.

Show comment
Hide comment
@Stangl1

Stangl1 Jul 16, 2017

Hallo Rudi,

erst mal danke für die Antwort, hoffe du spricht deutsch, mein Englisch ist nicht so tolle.

FTP Client ist klar, dachte mir schon das das verwirrt.

Das Problem ist wenn mein ESP, sprich WiFI, also die Anwendung als Client läuft ist alles gut.

Der ESP soll jedoch als Webserver laufen, nicht der FTP.

Läuft der ESP als Webserver bekomme ich per FTP jedoch keine Daten raus, nur wenn der ESP als Client läuft.

Danke für mögliche Hilfe.

Diese Sachen müssen raus, dann funktioniert der FTP Client, aber dann habe ich keinen Webserver mehr:

// Create an instance of the server on Port 80
WiFiServer server(80);
// Start the server
server.begin();
Serial.println(F("Server started"));

Stangl1 commented Jul 16, 2017

Hallo Rudi,

erst mal danke für die Antwort, hoffe du spricht deutsch, mein Englisch ist nicht so tolle.

FTP Client ist klar, dachte mir schon das das verwirrt.

Das Problem ist wenn mein ESP, sprich WiFI, also die Anwendung als Client läuft ist alles gut.

Der ESP soll jedoch als Webserver laufen, nicht der FTP.

Läuft der ESP als Webserver bekomme ich per FTP jedoch keine Daten raus, nur wenn der ESP als Client läuft.

Danke für mögliche Hilfe.

Diese Sachen müssen raus, dann funktioniert der FTP Client, aber dann habe ich keinen Webserver mehr:

// Create an instance of the server on Port 80
WiFiServer server(80);
// Start the server
server.begin();
Serial.println(F("Server started"));

@Stangl1

This comment has been minimized.

Show comment
Hide comment
@Stangl1

Stangl1 Jul 16, 2017

Hallo zusammen,
hier die Lösung, einfach Server stoppen und wieder starten, manchmal ist es wirklich einfach, man muss nur drauf kommen.

Hier das Ergebnis:
v45858.1blu.de

if (millis() >= ftpNextMeas_ms) { // FTP Upload to v45858.1blu.de
ftpNextMeas_ms = millis() + ftpMeasDelta_ms;
Serial.println(F("FTP-Upload started..."));

// Stop the Server
server.stop();

ftpFile = "/index.html";
FTPUpload(1);

ftpFile = "/dayly.html";
FTPUpload(2);

ftpFile = "/monthly.html";
FTPUpload(3);

// Start the Server
server.begin();

}

Stangl1 commented Jul 16, 2017

Hallo zusammen,
hier die Lösung, einfach Server stoppen und wieder starten, manchmal ist es wirklich einfach, man muss nur drauf kommen.

Hier das Ergebnis:
v45858.1blu.de

if (millis() >= ftpNextMeas_ms) { // FTP Upload to v45858.1blu.de
ftpNextMeas_ms = millis() + ftpMeasDelta_ms;
Serial.println(F("FTP-Upload started..."));

// Stop the Server
server.stop();

ftpFile = "/index.html";
FTPUpload(1);

ftpFile = "/dayly.html";
FTPUpload(2);

ftpFile = "/monthly.html";
FTPUpload(3);

// Start the Server
server.begin();

}

@rudi48

This comment has been minimized.

Show comment
Hide comment
@rudi48

rudi48 Jul 16, 2017

@Stangl1
Congratulations that you found a solution. I was reading yout question.

rudi48 commented Jul 16, 2017

@Stangl1
Congratulations that you found a solution. I was reading yout question.

@devyte

This comment has been minimized.

Show comment
Hide comment
@devyte

devyte Oct 19, 2017

Collaborator

@rudi48 this is pretty cool. Was it ever turned into a library?

Collaborator

devyte commented Oct 19, 2017

@rudi48 this is pretty cool. Was it ever turned into a library?

@rudi48

This comment has been minimized.

Show comment
Hide comment
@rudi48

rudi48 Oct 19, 2017

No, I do not have the expertise to do so.

rudi48 commented Oct 19, 2017

No, I do not have the expertise to do so.

@TomElectronic

This comment has been minimized.

Show comment
Hide comment
@TomElectronic

TomElectronic Feb 28, 2018

Hello rudi or everybody who can help.
I am writing source code for ESP8266 with Kinetis MCU.
I don't use Arduino library, I am writing all low level code.

Wifi is working fine. I added FTP client functionality, it works fine (I can connect to Filezilla Server) but I can't send "data" of my ASCII file.
I understand with wireshark and your code that after STOR command, I must read new port number and send the content of my file to this port.
But I don't know how to change this port because I am already connected at port 21 (with AT+CIPSTART="TCP","192.168.0.1",21\r\n").
And visibly, when ESP8266 is connected to one port, he refused to connect to another port without disconnect before.

I supposed that I would create 2 FTP clients (as your code with "client" and "dclient") but it don't work.
I tried :
AT+CIPMUX=1\r\n; // multiple connections allowed
OK
AT+CIPSTART=0,"TCP","192.128.0.1",21\r\n // create Client0 and connect to server on port 21
Link type ERROR

Do you have an idea to help me, pls ?
Regards,
Thomas.

TomElectronic commented Feb 28, 2018

Hello rudi or everybody who can help.
I am writing source code for ESP8266 with Kinetis MCU.
I don't use Arduino library, I am writing all low level code.

Wifi is working fine. I added FTP client functionality, it works fine (I can connect to Filezilla Server) but I can't send "data" of my ASCII file.
I understand with wireshark and your code that after STOR command, I must read new port number and send the content of my file to this port.
But I don't know how to change this port because I am already connected at port 21 (with AT+CIPSTART="TCP","192.168.0.1",21\r\n").
And visibly, when ESP8266 is connected to one port, he refused to connect to another port without disconnect before.

I supposed that I would create 2 FTP clients (as your code with "client" and "dclient") but it don't work.
I tried :
AT+CIPMUX=1\r\n; // multiple connections allowed
OK
AT+CIPSTART=0,"TCP","192.128.0.1",21\r\n // create Client0 and connect to server on port 21
Link type ERROR

Do you have an idea to help me, pls ?
Regards,
Thomas.

@devyte

This comment has been minimized.

Show comment
Hide comment
@devyte

devyte Feb 28, 2018

Collaborator

@TomElectronic you're in the wrong place, you're talking about the AT firmware, but this is the Arduino firmware.

Collaborator

devyte commented Feb 28, 2018

@TomElectronic you're in the wrong place, you're talking about the AT firmware, but this is the Arduino firmware.

@TomElectronic

This comment has been minimized.

Show comment
Hide comment
@TomElectronic

TomElectronic Feb 28, 2018

Yes, you're right, I'm sorry...

But this is the only code that I found who use 2 client with ESP8266.
And I don't understand how to do that at AT command level.

I just wrote a message on espressif forum that I found after that post.
I hope someone read this and know AT programming for this module so he can give me advices...

Thanks,
Thomas.

TomElectronic commented Feb 28, 2018

Yes, you're right, I'm sorry...

But this is the only code that I found who use 2 client with ESP8266.
And I don't understand how to do that at AT command level.

I just wrote a message on espressif forum that I found after that post.
I hope someone read this and know AT programming for this module so he can give me advices...

Thanks,
Thomas.

@Skm1982

This comment has been minimized.

Show comment
Hide comment
@Skm1982

Skm1982 Mar 10, 2018

Hello everybody. Is there a way to realize a secure ftp connection with esp8266 and this client? I mean FTPS one. I used WiFiClientSecure to open control socket and plain WiFiClient for data - it works fine. Unfortunately client can not make secure connection on data. And as far as I understand it is not 'lack of memory' problem - I tried to open secure control connections on two independent servers, worked too. Is it possible to make data connection secured too? Thanks.

Skm1982 commented Mar 10, 2018

Hello everybody. Is there a way to realize a secure ftp connection with esp8266 and this client? I mean FTPS one. I used WiFiClientSecure to open control socket and plain WiFiClient for data - it works fine. Unfortunately client can not make secure connection on data. And as far as I understand it is not 'lack of memory' problem - I tried to open secure control connections on two independent servers, worked too. Is it possible to make data connection secured too? Thanks.

@topnotchrally

This comment has been minimized.

Show comment
Hide comment
@topnotchrally

topnotchrally Jun 30, 2018

I have this code working on my ESP8255. It will connect and transfer a file to my Mac but will not do so to my Raspberry Pi, with ProFTPD server. I can connect/transfer to the RPi using Filezilla.

Can someone please help. I wish to FTP from the ESP to the RPi.
Here is what I see on the ESP

WiFi connected; IP address: 192.168.2.100
WiFi mode: WIFI_STA
Status: WL_CONNECTED
Ready. Press d, u or r
SPIFFS opened
Command connected
220 ProFTPD 1.3.5 Server (Debian) [::ffff:192.168.2.148]
Send USER
331 Password required for pi
Send PASSWORD
230 User pi logged in
Send SYST
215 UNIX Type: L8
Send Type I
200 Type set to I
Send PASV
227 Entering Passive Mode (192,168,2,148,176,83).
Data port: 45139
Data connection failed
FTP FAIL

Thanks.

topnotchrally commented Jun 30, 2018

I have this code working on my ESP8255. It will connect and transfer a file to my Mac but will not do so to my Raspberry Pi, with ProFTPD server. I can connect/transfer to the RPi using Filezilla.

Can someone please help. I wish to FTP from the ESP to the RPi.
Here is what I see on the ESP

WiFi connected; IP address: 192.168.2.100
WiFi mode: WIFI_STA
Status: WL_CONNECTED
Ready. Press d, u or r
SPIFFS opened
Command connected
220 ProFTPD 1.3.5 Server (Debian) [::ffff:192.168.2.148]
Send USER
331 Password required for pi
Send PASSWORD
230 User pi logged in
Send SYST
215 UNIX Type: L8
Send Type I
200 Type set to I
Send PASV
227 Entering Passive Mode (192,168,2,148,176,83).
Data port: 45139
Data connection failed
FTP FAIL

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment