Skip to content

Commit 810e98c

Browse files
committed
Add FTP passive mode, server port, remove directory function
Some FTP server doesn't allow files exchange in active mode. Passive mode can solve this problem. Passive mode is enable by default.
1 parent 30de202 commit 810e98c

File tree

4 files changed

+99
-25
lines changed

4 files changed

+99
-25
lines changed

examples/FTP/FTP.ino

+12-10
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ void setup() {
5959
void loop() {
6060

6161
Serial.println("Connect to FTP server.");
62-
if (ftp.connect(SECRET_FTP_HOST, SECRET_FTP_USER, SECRET_FTP_PASSWORD) == false) {
62+
if (ftp.connect(SECRET_FTP_HOST, SECRET_FTP_USER, SECRET_FTP_PASSWORD, SECRET_FTP_PORT) == false) {
6363
Serial.println("Failed to Connect to FTP server.");
6464
}
6565

@@ -71,14 +71,14 @@ void loop() {
7171
Serial.print("Free space ");
7272
Serial.println(fileSystem.freeSpace());
7373

74-
Serial.println("Create remote file : test");
74+
Serial.println("Create remote directory : test");
7575
if (ftp.mkdir("test") == false) {
76-
Serial.println("Failed to create the file.");
76+
Serial.println("Failed to create the directory.");
7777
}
7878

79-
Serial.println("Rename remote file : test to test2");
79+
Serial.println("Rename remote directory : test to test2");
8080
if (ftp.rename("test", "test2") == false) {
81-
Serial.println("Failed to rename the file.");
81+
Serial.println("Failed to rename the directory.");
8282
}
8383

8484
Serial.println("Write a binary file in local memory");
@@ -87,15 +87,17 @@ void loop() {
8787
if (fileSystem.write("myFile", &valueWR, sizeof(valueWR)) == false) {
8888
Serial.println("Failed to write file");
8989
}
90-
90+
9191
Serial.println("Send the file to the server");
9292
if (ftp.upload("myFile", "myFileToServer") == false) {
9393
Serial.println("Failed to upload the file.");
94+
ftp.printError();
9495
}
95-
96+
9697
Serial.println("Retreive the file from the server to local memory");
9798
if (ftp.download("myFileToServer", "myFileToLocalMemory") == false) {
9899
Serial.println("Failed to download the file.");
100+
ftp.printError();
99101
}
100102

101103
Serial.println("Check that the original file is identical to the one that was received");
@@ -129,11 +131,11 @@ void loop() {
129131
Serial.println("Failed to display files.");
130132
}
131133

132-
Serial.println("Delete the created files");
133-
if (ftp.remove("test2") == false) {
134+
Serial.println("Delete the created file and directory");
135+
if (ftp.removeDirectory("test2") == false) {
134136
Serial.println("Failed to remove files : test2.");
135137
}
136-
if (ftp.remove("myFileToServer") == false) {
138+
if (ftp.removeFile("myFileToServer") == false) {
137139
Serial.println("Failed to remove files : myFileToServer.");
138140
}
139141

examples/FTP/arduino_secrets.h

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
#define SECRET_PINNUMBER ""
22
#define SECRET_GPRS_APN "" // replace your GPRS APN
3-
#define SECRET_GPRS_LOGIN "" // replace with your GPRS login
3+
#define SECRET_GPRS_LOGIN "" // replace with your GPRS login
44
#define SECRET_GPRS_PASSWORD "" // replace with your GPRS password
55

6-
#define SECRET_FTP_HOST "" // replace with your FTP host server
7-
#define SECRET_FTP_USER "" // replace with your FTP user
8-
#define SECRET_FTP_PASSWORD "" // replace with your FTP password
9-
#define SECRET_FTP_REMOTE_DIR "/" // replace with your FTP default remote directory
6+
#define SECRET_FTP_HOST "" // replace with your FTP host server
7+
#define SECRET_FTP_USER "" // replace with your FTP user
8+
#define SECRET_FTP_PASSWORD "" // replace with your FTP password
9+
#define SECRET_FTP_PORT 21 // replace with your FTP port (optional)
10+
#define SECRET_FTP_REMOTE_DIR "/" // replace with your FTP default remote directory

src/GSMFTP.cpp

+59-5
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ GSMFTP::~GSMFTP()
3434
_file.clear();
3535
}
3636

37-
bool GSMFTP::connect(String hostname, String user, String password)
37+
bool GSMFTP::connect(String hostname, String user, String password, uint16_t port, bool passiveMode)
3838
{
3939
uint32_t start = millis();
4040
String command;
@@ -57,7 +57,14 @@ bool GSMFTP::connect(String hostname, String user, String password)
5757
return false;
5858
}
5959

60-
MODEM.send("AT+UFTP=6,0");
60+
command = (passiveMode == true) ? "AT+UFTP=6,1" : "AT+UFTP=6,0";
61+
MODEM.send(command);
62+
if (MODEM.waitForResponse(100) != 1) {
63+
return false;
64+
}
65+
66+
command = "AT+UFTP=7," + String(port);
67+
MODEM.send(command);
6168
if (MODEM.waitForResponse(100) != 1) {
6269
return false;
6370
}
@@ -163,7 +170,7 @@ bool GSMFTP::mkdir(const String& name, uint32_t timeout)
163170
return false;
164171
}
165172

166-
bool GSMFTP::remove(const String& name, uint32_t timeout)
173+
bool GSMFTP::removeFile(const String& name, uint32_t timeout)
167174
{
168175
uint32_t start = millis();
169176
if (_connected == false) {
@@ -192,6 +199,36 @@ bool GSMFTP::remove(const String& name, uint32_t timeout)
192199
return false;
193200
}
194201

202+
bool GSMFTP::removeDirectory(const String& name, uint32_t timeout)
203+
{
204+
uint32_t start = millis();
205+
if (_connected == false) {
206+
return false;
207+
}
208+
209+
_dirRemoved = -2;
210+
String command = "AT+UFTPC=11,\"" + name + "\"";
211+
212+
while ((millis() - start) < timeout) {
213+
if (_dirRemoved == -2) {
214+
_dirRemoved = -1;
215+
MODEM.send(command);
216+
if (MODEM.waitForResponse(100) != 1) {
217+
return false;
218+
}
219+
}
220+
MODEM.poll();
221+
if (_dirRemoved == 0) {
222+
_dirRemoved = -2;
223+
MODEM.send(command);
224+
}
225+
else if (_dirRemoved == 1) {
226+
return true;
227+
}
228+
}
229+
return false;
230+
}
231+
195232
bool GSMFTP::rename(const String& oldName, const String& name, uint32_t timeout)
196233
{
197234
uint32_t start = millis();
@@ -241,7 +278,6 @@ bool GSMFTP::download(const String& remoteFileName, const String& localFileName,
241278
MODEM.poll();
242279
if (_fileDownloaded == 0) {
243280
_fileDownloaded = -2;
244-
MODEM.send(command);
245281
}
246282
else if (_fileDownloaded == 1) {
247283
return true;
@@ -270,7 +306,6 @@ bool GSMFTP::upload(const String& localFileName, const String& remoteFileName, u
270306
MODEM.poll();
271307
if (_fileUploaded == 0) {
272308
_fileUploaded = -2;
273-
MODEM.send(command);
274309
}
275310
else if (_fileUploaded == 1) {
276311
return true;
@@ -308,6 +343,22 @@ bool GSMFTP::cd(const String& name, uint32_t timeout)
308343
return false;
309344
}
310345

346+
void GSMFTP::printError()
347+
{
348+
String res = "FTP last error : ";
349+
String response;
350+
351+
MODEM.send("AT+UFTPER");
352+
353+
if ((MODEM.waitForResponse(1000, &response) == 1) &&
354+
(response.startsWith("+UFTPER:"))) {
355+
res += response.substring(8);
356+
}else {
357+
res += "no response";
358+
}
359+
Serial.println(res);
360+
}
361+
311362
GSMFTP::FTPFileElem GSMFTP::file(uint16_t i)
312363
{
313364
if (i < _file.count) {
@@ -452,6 +503,9 @@ void GSMFTP::handleUrc(const String& urc)
452503
else if (urc.startsWith("+UUFTPCR: 2,")) {
453504
_fileRemoved = (urc.charAt(urc.lastIndexOf(",") + 1) == '1') ? 1 : 0;
454505
}
506+
else if (urc.startsWith("+UUFTPCR: 11,")) {
507+
_dirRemoved = (urc.charAt(urc.lastIndexOf(",") + 1) == '1') ? 1 : 0;
508+
}
455509
else if (urc.startsWith("+UUFTPCR: 3,")) {
456510
_fileRenamed = (urc.charAt(urc.lastIndexOf(",") + 1) == '1') ? 1 : 0;
457511
}

src/GSMFTP.h

+22-5
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,11 @@ class GSMFTP : public ModemUrcHandler {
4646
@param hostname FTP server hostname
4747
@param user FTP user name
4848
@param password FTP password
49+
@param port FTP server port
50+
@param passiveMode true if passive mode is active
4951
@return true if no error
5052
*/
51-
bool connect(String hostname, String user, String password);
53+
bool connect(String hostname, String user, String password, uint16_t port, bool passiveMode=true);
5254
/** Disconnect to the FTP server
5355
@return true if no error
5456
*/
@@ -74,12 +76,18 @@ class GSMFTP : public ModemUrcHandler {
7476
@return true if no error
7577
*/
7678
bool mkdir(const String& name, uint32_t timeout=10000);
79+
/** Delete directory on the FTP server
80+
@param name name of the directory to delete
81+
@param timeout maximum time allow to execute the function
82+
@return true if no error
83+
*/
84+
bool removeDirectory(const String&, uint32_t timeout = 10000);
7785
/** Delete file on the FTP server
78-
@param name name of the file to delete
79-
@param timeout maximum time allow to execute the function
80-
@return true if no error
86+
@param name name of the file to delete
87+
@param timeout maximum time allow to execute the function
88+
@return true if no error
8189
*/
82-
bool remove(const String&, uint32_t timeout = 10000);
90+
bool removeFile(const String&, uint32_t timeout = 10000);
8391
/** Rename file on the FTP server
8492
@param oldName name of the file to rename
8593
@param name new name of the file to rename
@@ -108,6 +116,14 @@ class GSMFTP : public ModemUrcHandler {
108116
*/
109117
bool upload(const String& localFileName, const String&remoteFileName, uint32_t timeout = 10000);
110118

119+
/** Print the error class and code of the last FTP operation
120+
@brief
121+
0,0 mean no error otherwise {error class},{error code}.
122+
For the description refer to the documention :
123+
https://www.u-blox.com/sites/default/files/u-blox-CEL_ATCommands_%28UBX-13002752%29.pdf
124+
*/
125+
void printError();
126+
111127
private:
112128
static const uint32_t c_connectionTimeout = 10000;
113129

@@ -132,6 +148,7 @@ class GSMFTP : public ModemUrcHandler {
132148
int _dirCreated;
133149
int _dirChanged;
134150
int _fileRemoved;
151+
int _dirRemoved;
135152
int _fileRenamed;
136153
int _fileDownloaded;
137154
int _fileUploaded;

0 commit comments

Comments
 (0)