GSM Shield and FTP

Hello,
I am currently working on a project that requires me to send a file to a server using the GSM shield. I am using an Arduino Mega 2560 with a Sparkfun SD shield, and Arduino GSM shield (found here http://arduino.cc/en/Main/ArduinoGSMShield.) I tried combining the GSM Webclient code (which is included as an example with the Arduino IDE) and the FTP Code (found here Arduino Playground - FTP) for use with the GSM shield, but was unable to establish a data connection. I established a connection to the server at port 21 and went through the FTP commands getting the server to enter passive mode and assign a data port, I just cannot connect to this port. The serial monitor outputs "Command Connected" followed by all successful FTP status codes (200 level,) the Data port number, and finally "Data Connection Failed" and "FTP FAIL." How can I get the GSM shield to establish two connections? Does the GSM shield support multiple connections? Is there another way to transfer a file using the GSM shield?

Here is my code:

/*
   FTP passive client for IDE v1.0.1 and w5100/w5200
   Posted October 2012 by SurferTim
*/

#include <SD.h>
#include <SPI.h>
#include <GSM.h>
// comment out next line to write to SD from FTP server
#define FTPWRITE

// PIN Number
#define PINNUMBER ""

// APN data
#define GPRS_APN       "bluevia.movistar.es" // replace your GPRS APN
#define GPRS_LOGIN     ""    // replace with your GPRS login
#define GPRS_PASSWORD  "" // replace with your GPRS password

// initialize the library instance
GPRS gprs;
GSM gsmAccess; 
GSMClient client;
GSMClient dclient;

// URL, path & port (for example: arduino.cc)
//char server[] = "arduino.cc";
byte server[]= {xxx, xxx, xxx, xxx};
char path[] = "/";
int port = 21; // port 80 is the default for HTTP

char outBuf[128];
char outCount;

// change fileName to your file (8.3 format!)
char fileName[13] = "test.txt";

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

  pinMode(53,OUTPUT);
  digitalWrite(53,HIGH);

  if(SD.begin(53) == 0) //changed to 53 for use with mega
  {
    Serial.println(F("SD init fail"));          
  }

Serial.println("Starting Arduino web client.");
  // connection state
  boolean notConnected = true;
  
  // After starting the modem with GSM.begin()
  // attach the shield to the GPRS network with the APN, login and password
  while(notConnected)
  {
    if((gsmAccess.begin(PINNUMBER)==GSM_READY) &
        (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD)==GPRS_READY))
      notConnected = false;
    else
    {
      Serial.println("Not connected");
      delay(1000);
    }
  }

  Serial.println("connecting...");

  // if you get a connection, report back via serial:
 /* if (client.connect(server, port))
  {
    Serial.println("connected");
  } 
  else
  {
    // if you didn't get a connection to the server:
    Serial.println("connection failed");
  }*/
  
  digitalWrite(53,HIGH);
  delay(2000);
  Serial.println(F("Ready. Press f or r"));
}

void loop()
{
  byte inChar;

  inChar = Serial.read();

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

  if(inChar == 'r')
  {
    readSD();    
  }

}

File fh;

byte doFTP()
{
#ifdef FTPWRITE
  fh = SD.open(fileName,FILE_READ);
#else
  SD.remove(fileName);
  fh = SD.open(fileName,FILE_WRITE);
#endif

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

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

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

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

  if(!eRcv()) return 0;

  client.println(F("USER xxxxxx")); 

  if(!eRcv()) return 0;

  client.println(F("PASS xxxxxx")); 

  if(!eRcv()) return 0;

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

  if(!eRcv()) return 0;

  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 
  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];
  int clientCount = 0;

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

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

  if(clientCount > 0) dclient.write(clientBuf,clientCount);

#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("SD closed"));
  return 1;
}

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;
}


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"));
}

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

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

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

  fh.close();
}

I was able to download a file from the server using FTP commands from a computer, so I think the server is functioning just fine. Thanks for your help.

I have the same problem.
Have u fixed it?
Maybe we can use the AT commands directly(http://pandatron.it/shop2/files/QuectelM10.zip).

I manage to solve it!

What was the solution?

Hi
I wonder if anybody does have an answer to this (see first post) ?

The issue is that, using the GSM shield and GSM library, you can successfully connect to the FTP site (password etc is OK) but adding the data connection on the port returned by PASV, always fails.

Using surferTims code adapted for GSM (rather than Ethernet) the point of failure is highlighted below...

Any thoughts would be appreciated.

Cheers

Paul

extract from modified surferTim code:

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);

// always fails below - firewall protecting the data port??????
if (dclient.connect(server,hiPort)) {
Serial.println(F("Data connected"));
}
else {
Serial.println(F("Data connection failed"));
client.stop();

return 0;
}

If the data connection fails, it may be the device cannot open two connections (sockets) simultaneously. I believe the WiFi shield has the same problem.
http://forum.arduino.cc/index.php?topic=225734.msg1633820#msg1633820

Thanks for the quick reply. Looks like I had better use HTTP.

Cheers

Paul

Hello Paul,

I realise this is an old thread but I have come down the same path in wanting to send a file from my Mega to a server using the GSM Shield. I'm going crazy reading all the Google hits without success.

Did you manage to use HTTP and if you did do you mind sharing your experience? I have no knowledge of using HTTP POST but if it works would love to try it. I need to understand both elements - the Arduino and the remote server.

Many thanks,

Dave.

Hello all!

Like RoffyJoff, I read a lot of forums and tutorials, and tried a bunch of strategy but still no results. I'm trying to transfer some batches of data from my data logger to my web server, with my GSM module. (ftp, http, mysql with php, every working solution would be great..). The reason I want to transfer my logs in batches is I have a current consumption concern. I cannot push one data after the other with a GET/POST strategy as my system would be almost always powered on (logger is set to gather one data each 20 seconds).

I also tried to loop and send batches of data with POST request, but each POST takes like 30 seconds to send so... not sure if I do something wrong or if it's just a speed limitation of the GSM Shield..

Anyone got some good path to follow on this ?

Thanks in advance :slight_smile:

Ben

Hello,

I have to same problem as Ben as I'm trying to send every minute / 5 minutes a very small amount of data via GSM module to an ftp server.

Was anybody successful in establishing this connection with an Arduino device ?

Thanks for your replay !

Maro

I have written code to do exactly that, using a SIMCom 800L module and SoftwareSerial.

http://people.exeter.ac.uk/tamitche/arduino/