This class adds HTTP, FTP and CellLocate client support for u-blox modules for the C027 and C030 boards (excepting the C030 N2xx flavour) from mbed 5.5 onwards. The HTTP, FTP and CellLocate operations are all hosted on the module, minimizing RAM consumption in the mbed MCU. It also sub-classes ublox-cellular-driver-gen to bring in SMS, USSD and modem file system support if you need to use these functions at the same time as the cellular interface.

Dependencies:   ublox-at-cellular-interface

Dependents:   example-ublox-at-cellular-interface-ext HelloMQTT ublox_new_driver_test example-ublox-at-cellular-interface-ext ... more

Files at this revision

API Documentation at this revision

Comitter:
rob.meades@u-blox.com
Date:
Fri Jun 16 00:55:19 2017 +0100
Parent:
10:3b24bc50cc06
Child:
12:44c7bbc84f42
Commit message:
Remove return code from ftpResetPar() since not all modules support all parameters and hence it's not possible to be certain which are errors and which are normal. Change order of parameters in ftpCommand() as offset is truly optional (it is not supported by Sara-G350). Make switching on of +ULOCIND URC optional (it is only informative and is not supported by Sara-G350). Update UbloxAtCellularInterface library version. Update mbed_app.json templates. Don't run the HTTP TLS test on C027 as Sara-G350 doesn't support it.

Changed in this revision

TESTS/unit_tests/cell-locate/main.cpp Show annotated file Show diff for this revision Revisions of this file
TESTS/unit_tests/cell-locate/template_mbed_app.txt Show annotated file Show diff for this revision Revisions of this file
TESTS/unit_tests/ftp/main.cpp Show annotated file Show diff for this revision Revisions of this file
TESTS/unit_tests/ftp/template_mbed_app.txt Show annotated file Show diff for this revision Revisions of this file
TESTS/unit_tests/http/main.cpp Show annotated file Show diff for this revision Revisions of this file
UbloxATCellularInterfaceExt.cpp Show annotated file Show diff for this revision Revisions of this file
UbloxATCellularInterfaceExt.h Show annotated file Show diff for this revision Revisions of this file
ublox-at-cellular-interface.lib Show annotated file Show diff for this revision Revisions of this file
--- a/TESTS/unit_tests/cell-locate/main.cpp	Tue Jun 13 10:46:08 2017 +0100
+++ b/TESTS/unit_tests/cell-locate/main.cpp	Fri Jun 16 00:55:19 2017 +0100
@@ -36,11 +36,16 @@
 //        }
 //}
 
+// Whether debug trace is on
+#ifndef MBED_CONF_APP_DEBUG_ON
+# define MBED_CONF_APP_DEBUG_ON false
+#endif
+
 // The credentials of the SIM in the board.
 #ifndef MBED_CONF_APP_DEFAULT_PIN
-// Note: this is the PIN for the SIM with ICCID
-// 8944501104169548380.
-# define MBED_CONF_APP_DEFAULT_PIN "5134"
+// Note: if PIN is enabled on your SIM, you must define the PIN
+// for your SIM jere (e.g. using mbed_app.json to do so).
+# define MBED_CONF_APP_DEFAULT_PIN "0000"
 #endif
 
 // Network credentials.
@@ -96,14 +101,14 @@
 #ifdef TARGET_UBLOX_C030
 static DigitalInOut gnssEnable(GNSSEN, PIN_OUTPUT, PushPullNoPull, 1);
 #elif TARGET_UBLOX_C027
-static DigitalOut gnssEnable(GNSSEN, 1);
+static DigitalOut gnssEnable(GPSEN, 1);
 #endif
 
 // An instance of the cellular interface
 static UbloxATCellularInterfaceExt *pDriver =
        new UbloxATCellularInterfaceExt(MDMTXD, MDMRXD,
                                        MBED_CONF_UBLOX_CELL_BAUD_RATE,
-                                       true);
+                                       MBED_CONF_APP_DEBUG_ON);
 
 // ----------------------------------------------------------------
 // PRIVATE FUNCTIONS
--- a/TESTS/unit_tests/cell-locate/template_mbed_app.txt	Tue Jun 13 10:46:08 2017 +0100
+++ b/TESTS/unit_tests/cell-locate/template_mbed_app.txt	Fri Jun 16 00:55:19 2017 +0100
@@ -1,8 +1,5 @@
 {
     "config": {
-        "buffer-size": { "value": 0 },
-        "platform": { "help": "Options: UBLOX, MTS_DRAGONFLY",
-                      "value": "UBLOX"},
         "cell-locate-mga-token": {
             "help": "Your Cell Locate MGA token, required for TCP testing.  A tokane can be obtained from https://www.u-blox.com/en/assistnow-service-registration-form",
             "value": "\"mymgatoken\""
@@ -14,19 +11,8 @@
      },
     "target_overrides": {
         "*": {
-            "lwip.ipv4-enabled": true,
-            "lwip.ipv6-enabled": false,
-            "lwip.ethernet-enabled": false,
-            "lwip.ppp-enabled": true,
-            "lwip.tcp-enabled": true,
-            "target.features_add": ["LWIP", "COMMON_PAL"],
-            "platform.stdio-convert-newlines": true,
-            "platform.stdio-baud-rate": 9600,
-            "platform.default-serial-baud-rate": 115200, 
-            "lwip.debug-enabled": false,
-            "lwip.enable-ppp-trace": false,
-            "lwip.use-mbed-trace": false,
-            "mbed-trace.enable": 1
+            "target.features_add": ["COMMON_PAL"],
+            "platform.stdio-convert-newlines": true
         }
     }
 }
--- a/TESTS/unit_tests/ftp/main.cpp	Tue Jun 13 10:46:08 2017 +0100
+++ b/TESTS/unit_tests/ftp/main.cpp	Fri Jun 16 00:55:19 2017 +0100
@@ -51,11 +51,16 @@
 //      }
 //}
 
+// Whether debug trace is on
+#ifndef MBED_CONF_APP_DEBUG_ON
+# define MBED_CONF_APP_DEBUG_ON false
+#endif
+
 // The credentials of the SIM in the board.
 #ifndef MBED_CONF_APP_DEFAULT_PIN
-// Note: this is the PIN for the SIM with ICCID
-// 8944501104169548380.
-# define MBED_CONF_APP_DEFAULT_PIN "5134"
+// Note: if PIN is enabled on your SIM, you must define the PIN
+// for your SIM jere (e.g. using mbed_app.json to do so).
+# define MBED_CONF_APP_DEFAULT_PIN "0000"
 #endif
 
 // Network credentials.
@@ -116,6 +121,7 @@
 #  define MBED_CONF_APP_FTP_FILENAME "test_file_delete_me"
 # endif
 // The name of the directory to create, CD to and then remove
+// Must not be a substring of MBED_CONF_APP_FTP_FILENAME.
 # ifndef MBED_CONF_APP_FTP_DIRNAME
 #  define MBED_CONF_APP_FTP_DIRNAME "test_dir_delete_me"
 # endif
@@ -132,7 +138,7 @@
 
 // The size of file when testing PUT/GET
 #ifndef MBED_CONF_APP_FTP_FILE_SIZE
-#  define MBED_CONF_APP_FTP_FILE_SIZE 42000
+#  define MBED_CONF_APP_FTP_FILE_SIZE 1200
 #endif
 
 // ----------------------------------------------------------------
@@ -148,7 +154,7 @@
 static UbloxATCellularInterfaceExt *pDriver =
        new UbloxATCellularInterfaceExt(MDMTXD, MDMRXD,
                                        MBED_CONF_UBLOX_CELL_BAUD_RATE,
-                                       true);
+                                       MBED_CONF_APP_DEBUG_ON);
 // A buffer for general use
 static char buf[MBED_CONF_APP_FTP_FILE_SIZE];
 
@@ -209,7 +215,7 @@
     TEST_ASSERT(pDriver->init(MBED_CONF_APP_DEFAULT_PIN));
 
     // Reset parameters to default to begin with
-    TEST_ASSERT(pDriver->ftpResetPar());
+    pDriver->ftpResetPar();
 
     // Set a timeout for FTP commands
     TEST_ASSERT(pDriver->ftpSetTimeout(60000));
@@ -251,7 +257,7 @@
 void test_ftp_dir() {
     // Get a directory listing
     TEST_ASSERT(pDriver->ftpCommand(UbloxATCellularInterfaceExt::FTP_LS,
-                                    NULL, NULL, 0, buf, sizeof (buf)) == NULL);
+                                    NULL, NULL, buf, sizeof (buf)) == NULL);
     tr_debug("Listing:\n%s", buf);
 
     // The file we will GET should appear in the directory listing
@@ -264,7 +270,7 @@
 void test_ftp_fileinfo() {
     // Get the info
     TEST_ASSERT(pDriver->ftpCommand(UbloxATCellularInterfaceExt::FTP_FILE_INFO,
-                                    MBED_CONF_APP_FTP_FILENAME, NULL, 0,
+                                    MBED_CONF_APP_FTP_FILENAME, NULL,
                                     buf, sizeof (buf)) == NULL);
     tr_debug("File info:\n%s", buf);
 
@@ -310,7 +316,7 @@
 void test_ftp_rename() {
     // Get a directory listing
     TEST_ASSERT(pDriver->ftpCommand(UbloxATCellularInterfaceExt::FTP_LS,
-                                    NULL, NULL, 0, buf, sizeof (buf)) == NULL);
+                                    NULL, NULL, buf, sizeof (buf)) == NULL);
     tr_debug("Listing:\n%s", buf);
 
     // The file we are renaming to should not appear
@@ -323,7 +329,7 @@
 
     // Get a directory listing
     TEST_ASSERT(pDriver->ftpCommand(UbloxATCellularInterfaceExt::FTP_LS,
-                                    NULL, NULL, 0, buf, sizeof (buf)) == NULL);
+                                    NULL, NULL, buf, sizeof (buf)) == NULL);
     tr_debug("Listing:\n%s", buf);
 
     // The new file should now exist
@@ -335,7 +341,7 @@
 void test_ftp_delete() {
     // Get a directory listing
     TEST_ASSERT(pDriver->ftpCommand(UbloxATCellularInterfaceExt::FTP_LS,
-                                    NULL, NULL, 0, buf, sizeof (buf)) == NULL);
+                                    NULL, NULL, buf, sizeof (buf)) == NULL);
     tr_debug("Listing:\n%s", buf);
 
     // The file we are to delete should appear in the list
@@ -347,7 +353,7 @@
 
     // Get a directory listing
     TEST_ASSERT(pDriver->ftpCommand(UbloxATCellularInterfaceExt::FTP_LS,
-                                    NULL, NULL, 0, buf, sizeof (buf)) == NULL);
+                                    NULL, NULL, buf, sizeof (buf)) == NULL);
     tr_debug("Listing:\n%s", buf);
 
     // The file we deleted should no longer appear in the list
@@ -358,7 +364,7 @@
 void test_ftp_mkdir() {
     // Get a directory listing
     TEST_ASSERT(pDriver->ftpCommand(UbloxATCellularInterfaceExt::FTP_LS,
-                                    NULL, NULL, 0, buf, sizeof (buf)) == NULL);
+                                    NULL, NULL, buf, sizeof (buf)) == NULL);
     tr_debug("Listing:\n%s", buf);
 
     // The directory we are to create should not appear in the list
@@ -370,7 +376,7 @@
 
     // Get a directory listing
     TEST_ASSERT(pDriver->ftpCommand(UbloxATCellularInterfaceExt::FTP_LS,
-                                    NULL, NULL, 0, buf, sizeof (buf)) == NULL);
+                                    NULL, NULL, buf, sizeof (buf)) == NULL);
     tr_debug("Listing:\n%s", buf);
 
     // The directory we created should now appear in the list
@@ -381,7 +387,7 @@
 void test_ftp_rmdir() {
     // Get a directory listing
     TEST_ASSERT(pDriver->ftpCommand(UbloxATCellularInterfaceExt::FTP_LS,
-                                    NULL, NULL, 0, buf, sizeof (buf)) == NULL);
+                                    NULL, NULL, buf, sizeof (buf)) == NULL);
     tr_debug("Listing:\n%s", buf);
 
     // The directory we are to remove should appear in the list
@@ -393,7 +399,7 @@
 
     // Get a directory listing
     TEST_ASSERT(pDriver->ftpCommand(UbloxATCellularInterfaceExt::FTP_LS,
-                                    NULL, NULL, 0, buf, sizeof (buf)) == NULL);
+                                    NULL, NULL, buf, sizeof (buf)) == NULL);
     tr_debug("Listing:\n%s", buf);
 
     // The directory we removed should no longer appear in the list
@@ -422,7 +428,7 @@
     // Get a directory listing
     *buf = 0;
     TEST_ASSERT(pDriver->ftpCommand(UbloxATCellularInterfaceExt::FTP_LS,
-                                    NULL, NULL, 0, buf, sizeof (buf)) == NULL);
+                                    NULL, NULL, buf, sizeof (buf)) == NULL);
 
     tr_debug("Listing:\n%s", buf);
 
@@ -435,7 +441,7 @@
     // Get a directory listing
     *buf = 0;
     TEST_ASSERT(pDriver->ftpCommand(UbloxATCellularInterfaceExt::FTP_LS,
-                                    NULL, NULL, 0, buf, sizeof (buf)) == NULL);
+                                    NULL, NULL, buf, sizeof (buf)) == NULL);
     tr_debug("Listing:\n%s", buf);
 
     // The listing should no longer include the directory name we have moved
@@ -448,7 +454,7 @@
     // Get a directory listing
     *buf = 0;
     TEST_ASSERT(pDriver->ftpCommand(UbloxATCellularInterfaceExt::FTP_LS,
-                                    NULL, NULL, 0, buf, sizeof (buf)) == NULL);
+                                    NULL, NULL, buf, sizeof (buf)) == NULL);
     tr_debug("Listing:\n%s", buf);
 
     // The listing should include the directory name we went to once more
@@ -463,7 +469,7 @@
     // Do FOTA on a file
     TEST_ASSERT(pDriver->ftpCommand(UbloxATCellularInterfaceExt::FTP_FOTA_FILE,
                                     MBED_CONF_APP_FTP_FOTA_FILENAME, NULL,
-                                    0, buf, sizeof (buf)) == NULL);
+                                    buf, sizeof (buf)) == NULL);
     tr_debug("MD5 sum: %s\n", buf);
 
     // Check that the 128 bit MD5 sum is now there
@@ -502,8 +508,7 @@
     Case("FTP file info", test_ftp_fileinfo),
     Case("FTP rename", test_ftp_rename),
     Case("FTP make directory", test_ftp_mkdir),
-    Case("FTP directory list", test_ftp_dir),
-    Case("FTP delete", test_ftp_delete),
+    Case("FTP directory list", test_ftp_dir),    Case("FTP delete", test_ftp_delete),
     Case("FTP change directory", test_ftp_cd),
     Case("FTP delete directory", test_ftp_rmdir),
 #else
--- a/TESTS/unit_tests/ftp/template_mbed_app.txt	Tue Jun 13 10:46:08 2017 +0100
+++ b/TESTS/unit_tests/ftp/template_mbed_app.txt	Fri Jun 16 00:55:19 2017 +0100
@@ -1,8 +1,5 @@
 {
     "config": {
-        "buffer-size": { "value": 0 },
-        "platform": { "help": "Options: UBLOX, MTS_DRAGONFLY",
-                      "value": "UBLOX"},
         "ftp-server": {
             "help": "An FTP server to use when running the FTP tests",
             "value": "\"test.rebex.net\""
@@ -28,25 +25,14 @@
             "value": "\"readme.txt\""
         },
         "ftp-dirname": {
-            "help": "A directory name to yse during FTP tests.  This directory must already exist on the server if the server does not support write",
+            "help": "A directory name to use during FTP tests.  This directory must already exist on the server if the server does not support write. If the server does support write, this must not be a substring of ftp-filename.  ",
             "value": "\"pub\""
         }
      },
     "target_overrides": {
         "*": {
-            "lwip.ipv4-enabled": true,
-            "lwip.ipv6-enabled": false,
-            "lwip.ethernet-enabled": false,
-            "lwip.ppp-enabled": true,
-            "lwip.tcp-enabled": true,
-            "target.features_add": ["LWIP", "COMMON_PAL"],
-            "platform.stdio-convert-newlines": true,
-            "platform.stdio-baud-rate": 9600,
-            "platform.default-serial-baud-rate": 115200, 
-            "lwip.debug-enabled": false,
-            "lwip.enable-ppp-trace": false,
-            "lwip.use-mbed-trace": false,
-            "mbed-trace.enable": 1
+            "target.features_add": ["COMMON_PAL"],
+            "platform.stdio-convert-newlines": true
         }
     }
 }
--- a/TESTS/unit_tests/http/main.cpp	Tue Jun 13 10:46:08 2017 +0100
+++ b/TESTS/unit_tests/http/main.cpp	Fri Jun 16 00:55:19 2017 +0100
@@ -30,11 +30,16 @@
 //        }
 //}
 
+// Whether debug trace is on
+#ifndef MBED_CONF_APP_DEBUG_ON
+# define MBED_CONF_APP_DEBUG_ON false
+#endif
+
 // The credentials of the SIM in the board.
 #ifndef MBED_CONF_APP_DEFAULT_PIN
-// Note: this is the PIN for the SIM with ICCID
-// 8944501104169548380.
-# define MBED_CONF_APP_DEFAULT_PIN "5134"
+// Note: if PIN is enabled on your SIM, you must define the PIN
+// for your SIM jere (e.g. using mbed_app.json to do so).
+# define MBED_CONF_APP_DEFAULT_PIN "0000"
 #endif
 
 // Network credentials.
@@ -76,7 +81,7 @@
 static UbloxATCellularInterfaceExt *pDriver =
        new UbloxATCellularInterfaceExt(MDMTXD, MDMRXD,
                                        MBED_CONF_UBLOX_CELL_BAUD_RATE,
-                                       true);
+                                       MBED_CONF_APP_DEBUG_ON);
 // A few buffers for general use
 static char buf[1024];
 static char buf1[sizeof(buf)];
@@ -321,7 +326,10 @@
 // Test cases
 Case cases[] = {
     Case("HTTP commands", test_http_cmd),
+#ifndef TARGET_UBLOX_C027
+    // C027 doesn't support TLS
     Case("HTTP with TLS", test_http_tls),
+#endif
     Case("Alloc max profiles", test_alloc_profiles)
 };
 
--- a/UbloxATCellularInterfaceExt.cpp	Tue Jun 13 10:46:08 2017 +0100
+++ b/UbloxATCellularInterfaceExt.cpp	Fri Jun 16 00:55:19 2017 +0100
@@ -705,6 +705,8 @@
                     // Received unsolicited: starting its analysis
                     _httpProfiles[httpProfile].pending = false;
                     if (_httpProfiles[httpProfile].result == 1) {
+                        // Leave a short delay to make sure the file has been written
+                        wait_ms(100);
                         // HTTP command successfully executed
                         if (readFile(rspFile, buf, len) >= 0) {
                             success = true;
@@ -760,18 +762,18 @@
 }
 
 // Reset the FTP configuration back to defaults.
-bool UbloxATCellularInterfaceExt::ftpResetPar()
+// Note: not all modrmd support all parameters,
+// hence the void return code.
+void UbloxATCellularInterfaceExt::ftpResetPar()
 {
-    bool success = true;
     LOCK();
-
     debug_if(_debug_trace_on, "ftpResetPar()\n");
-    for (int x = 0; success && (x < NUM_FTP_OP_CODES); x++) {
-        success = _at->send("AT+UFTP=%d", x) && _at->recv("OK");
+    for (int x = 0; x < NUM_FTP_OP_CODES; x++) {
+        if (_at->send("AT+UFTP=%d", x)) {
+            _at->recv("OK");
+        }
     }
-
     UNLOCK();
-    return success;
 }
 
 // Set FTP parameters.
@@ -813,8 +815,8 @@
 UbloxATCellularInterfaceExt::Error * UbloxATCellularInterfaceExt::ftpCommand(FtpCmd ftpCmd,
                                                                              const char* file1,
                                                                              const char* file2,
-                                                                             int offset,
-                                                                             char* buf, int len)
+                                                                             char* buf, int len,
+                                                                             int offset)
 {
     bool atSuccess = false;
     bool success = false;
@@ -849,6 +851,15 @@
             atSuccess = _at->send("AT+UFTPC=%d,\"%s\",\"%s\",%d",
                                   ftpCmd, file1, file2, offset) &&
                         _at->recv("OK");
+            
+            // Not all modules support continuing a GET/PUT (e.g.
+            // Sara-G350 00S-00 doesn't), so if we receive an error,
+            // try again without it
+            if (!atSuccess) {
+                atSuccess = _at->send("AT+UFTPC=%d,\"%s\",\"%s\"",
+                                      ftpCmd, file1, file2) &&
+                            _at->recv("OK");
+            }
             break;
         case FTP_FILE_INFO:
         case FTP_LS:
@@ -991,13 +1002,15 @@
             _loc[i].validData = false;
         }
 
-        // Switch on the URC
-        if (_at->send("AT+ULOCIND=1") && _at->recv("OK")) {
-            // Switch on Cell Locate
-            success = _at->send("AT+ULOC=2,%d,%d,%d,%d,%d", sensor, type, timeout, accuracy, hypothesis) &&
-                      _at->recv("OK");
-            // Answers are picked up by the URC
+        // Switch on the URC but don't error on it as some
+        // modules (e.g. Sara-G350) don't support it
+        if (_at->send("AT+ULOCIND=1")) {
+            _at->recv("OK");
         }
+        // Switch on Cell Locate
+        success = _at->send("AT+ULOC=2,%d,%d,%d,%d,%d", sensor, type, timeout, accuracy, hypothesis) &&
+                  _at->recv("OK");
+        // Answers are picked up by reacting to +ULOC
 
         UNLOCK();
     }
--- a/UbloxATCellularInterfaceExt.h	Tue Jun 13 10:46:08 2017 +0100
+++ b/UbloxATCellularInterfaceExt.h	Fri Jun 16 00:55:19 2017 +0100
@@ -157,7 +157,8 @@
      * HTTP_AUTH_TYPE      "0" for no authentication, "1" for username/password
      *                     authentication (the default is 0)
      * HTTP_SERVER_PORT    "81" (default is port 80)
-     * HTTP_SECURE         "0" for no security, "1" for TLS (the default is 0)
+     * HTTP_SECURE         "0" for no security, "1" for TLS (the default is 0),
+     *                     not all modems support this parameter
      *
      * @param httpProfile the HTTP profile identifier.
      * @param httpOpCode  the HTTP operation code.
@@ -257,10 +258,8 @@
     bool ftpSetTimeout(int timeout);
 
     /** Reset the FTP configuration back to defaults.
-     *
-     * @return   true if successful, false otherwise.
      */
-    bool ftpResetPar();
+    void ftpResetPar();
     
     /** Set FTP parameters.
      *
@@ -295,19 +294,19 @@
      * See section 27.2 of u-blox-ATCommands_Manual(UBX-13002752).pdf
      * for full details.  By example, it works like this:
      *
-     * ftpCmd               file1      file2     offset    buf     len
-     * FTP_LOGOUT            N/A        N/A       N/A      N/A     N/A 
-     * FTP_LOGIN             N/A        N/A       N/A      N/A     N/A 
-     * FTP_DELETE_FILE   "the_file"     N/A       N/A      N/A     N/A 
-     * FTP_RENAME_FILE   "old_name"  "new_name"   N/A      N/A     N/A 
-     * FTP_GET_FILE      "the_file"    Note 1  0 - 65535   N/A     N/A (Notes 2)
-     * FTP_PUT_FILE      "the_file"    Note 1  0 - 65535   N/A     N/A (Note 2)
-     * FTP_CD            "dir1\dir2"    N/A       N/A      N/A     N/A 
-     * FTP_MKDIR         "newdir"       N/A       N/A      N/A     N/A 
-     * FTP_RMDIR         "dir"          N/A       N/A      N/A     N/A 
-     * FTP_FILE_INFO     "the_path"     N/A       N/A         Note 3
-     * FTP_LS            "the_path"     N/A       N/A         Note 3
-     * FTP_FOTA_FILE     "the_file"     N/A       N/A         Note 4
+     * ftpCmd               file1      file2    buf     len  offset
+     * FTP_LOGOUT            N/A        N/A     N/A     N/A    N/A 
+     * FTP_LOGIN             N/A        N/A     N/A     N/A    N/A 
+     * FTP_DELETE_FILE   "the_file"     N/A     N/A     N/A    N/A
+     * FTP_RENAME_FILE   "old_name"  "new_name" N/A     N/A    N/A 
+     * FTP_GET_FILE      "the_file"    Note 1   N/A     N/A   0 - 1    (Notes 2 & 3)
+     * FTP_PUT_FILE      "the_file"    Note 1   N/A     N/A  0 - 65535 (Notes 2 & 4 & 5)
+     * FTP_CD            "dir1\dir2"    N/A     N/A     N/A    N/A 
+     * FTP_MKDIR         "newdir"       N/A     N/A     N/A    N/A 
+     * FTP_RMDIR         "dir"          N/A     N/A     N/A    N/A 
+     * FTP_FILE_INFO     "the_path"     N/A        Note 6      N/A
+     * FTP_LS            "the_path"     N/A        Note 6      N/A
+     * FTP_FOTA_FILE     "the_file"     N/A        Note 7      N/A
      *
      * Note 1: for this case, file2 is the name that the file should be
      * given when it arrives (in the modem file system for a GET, at the FTP
@@ -315,30 +314,37 @@
      * Note 2: the file will placed into the modem file system for the
      * GET case (and can be read with readFile()), or must already be in the
      * modem file system, (can be written using writeFile()) for the PUT case.
-     * Note 3: buf should point to the location where the file info
+     * Note 3: if offset is 1 then, where supported, the FTP GET
+     * will be continued from the point it previously stopped.
+     * Note 4: if the file already exists in the modem file system some
+     * modems will return an error.  It is up to the caller to ensure that
+     * the file does not exist before the FTP PUT operation.
+     * Note 5: where supported, offset is the position in the file to continue
+     * the FTP PUT from.
+     * Note 6: buf should point to the location where the file info
      * or directory listing is to be stored and len should be the maximum
      * length that can be stored.
-     * Note 4: a hex string representing the MD5 sum of the FOTA file will be
+     * Note 7: a hex string representing the MD5 sum of the FOTA file will be
      * stored at buf; len must be at least 32 as an MD5 sum is 16 bytes.
      * FTP_FOTA_FILE is not supported on SARA-U2.
-     * Note 5: FTP_GET_DIRECT and FTP_PUT_DIRECT are not supported by
+     * Note 8: FTP_GET_DIRECT and FTP_PUT_DIRECT are not supported by
      * this driver.
      *
      * @param ftpCmd     the FTP command.
      * @param file1      the first file name if required (NULL otherwise).
      * @param file2      the second file name if required (NULL otherwise).
-     * @param offset     the offset (in bytes) at which to begin the get
-     *                   or put operation within the file.
      * @param buf        pointer to a buffer, required for FTP_DIRECT mode
      *                   and FTP_LS only.
      * @param len        the size of buf.
+     * @param continue   if true then attempt to continue a download that
+     *                   was previously interrupted.
      * @return           NULL if successful, otherwise a pointer to
      *                   a Error struct containing the error class and error
      *                   code, see section Appendix A.B of
      *                   u-blox-ATCommands_Manual(UBX-13002752).pdf for details.
      */
     Error *ftpCommand(FtpCmd ftpCmd, const char* file1 = NULL, const char* file2 = NULL,
-                      int offset = 0, char* buf = NULL, int len = 0);
+                      char* buf = NULL, int len = 0, int offset = 0);
 
     /**********************************************************************
      * PUBLIC: Cell Locate
--- a/ublox-at-cellular-interface.lib	Tue Jun 13 10:46:08 2017 +0100
+++ b/ublox-at-cellular-interface.lib	Fri Jun 16 00:55:19 2017 +0100
@@ -1,1 +1,1 @@
-https://developer.mbed.org/teams/ublox/code/ublox-at-cellular-interface/#c89190eda594
+https://developer.mbed.org/teams/ublox/code/ublox-at-cellular-interface/#63dad754c267