amq amq / ublox-at-cellular-interface-ext-add-priority

Dependencies:   ublox-at-cellular-interface

Fork of ublox-at-cellular-interface-ext by u-blox

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers UbloxATCellularInterfaceExt.cpp Source File

UbloxATCellularInterfaceExt.cpp

00001 /* Copyright (c) 2017 ublox Limited
00002  *
00003  * Licensed under the Apache License, Version 2.0 (the "License");
00004  * you may not use this file except in compliance with the License.
00005  * You may obtain a copy of the License at
00006  *
00007  *     http://www.apache.org/licenses/LICENSE-2.0
00008  *
00009  * Unless required by applicable law or agreed to in writing, software
00010  * distributed under the License is distributed on an "AS IS" BASIS,
00011  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012  * See the License for the specific language governing permissions and
00013  * limitations under the License.
00014  */
00015 
00016 #include "UbloxATCellularInterfaceExt.h"
00017 #include "APN_db.h"
00018 #ifdef FEATURE_COMMON_PAL
00019 #include "mbed_trace.h"
00020 #define TRACE_GROUP "UCAD"
00021 #else
00022 #define tr_debug(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__)
00023 #define tr_info(format, ...)  debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__)
00024 #define tr_warn(format, ...)  debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__)
00025 #define tr_error(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__)
00026 #endif
00027 
00028 /**********************************************************************
00029  * PROTECTED METHODS: HTTP
00030  **********************************************************************/
00031 
00032 // Callback for HTTP result code handling.
00033 void UbloxATCellularInterfaceExt::UUHTTPCR_URC()
00034 {
00035     char buf[32];
00036     int a, b, c;
00037 
00038     // Note: not calling _at->recv() from here as we're
00039     // already in an _at->recv()
00040     // +UUHTTPCR: <profile_id>,<op_code>,<param_val>
00041     if (read_at_to_char(buf, sizeof (buf), '\n') > 0) {
00042         if (sscanf(buf, ": %d,%d,%d", &a, &b, &c) == 3) {
00043             _httpProfiles[a].cmd = b;          // Command
00044             _httpProfiles[a].result = c;       // Result
00045             debug_if(_debug_trace_on, "%s on profile %d, result code is %d\n", getHttpCmd((HttpCmd) b), a, c);
00046         }
00047     }
00048 }
00049 
00050 // Find a given profile.  NOTE: LOCK() before calling.
00051 int UbloxATCellularInterfaceExt::findProfile(int modemHandle)
00052 {
00053     for (unsigned int profile = 0; profile < (sizeof(_httpProfiles)/sizeof(_httpProfiles[0]));
00054          profile++) {
00055         if (_httpProfiles[profile].modemHandle == modemHandle) {
00056             return profile;
00057         }
00058     }
00059 
00060     return HTTP_PROF_UNUSED;
00061 }
00062 
00063 // Return a string representing an HTTP AT command.
00064 const char *UbloxATCellularInterfaceExt::getHttpCmd(HttpCmd httpCmd)
00065 {
00066     const char * str = "HTTP command not recognised";
00067 
00068     switch (httpCmd) {
00069         case HTTP_HEAD:
00070             str = "HTTP HEAD command";
00071             break;
00072         case HTTP_GET:
00073             str = "HTTP GET command";
00074             break;
00075         case HTTP_DELETE:
00076             str = "HTTP DELETE command";
00077             break;
00078         case HTTP_PUT:
00079             str = "HTTP PUT command";
00080             break;
00081         case HTTP_POST_FILE:
00082             str = "HTTP POST file command";
00083             break;
00084         case HTTP_POST_DATA:
00085             str = "HTTP POST data command";
00086             break;
00087         default:
00088             break;
00089     }
00090 
00091     return str;
00092 }
00093 
00094 /**********************************************************************
00095  * PROTECTED METHODS: FTP
00096  **********************************************************************/
00097 
00098 // Callback for FTP result code handling.
00099 void UbloxATCellularInterfaceExt::UUFTPCR_URC()
00100 {
00101     char buf[64];
00102     char md5[32];
00103 
00104     // Note: not calling _at->recv() from here as we're
00105     // already in an _at->recv()
00106     // +UUFTPCR: <op_code>,<ftp_result>[,<md5_sum>]
00107     if (read_at_to_char(buf, sizeof (buf), '\n') > 0) {
00108         if (sscanf(buf, ": %d,%d,%32[^\n]\n", &_lastFtpOpCodeResult, &_lastFtpResult, md5) == 3) {
00109             // Store the MD5 sum if we can
00110             if ((_ftpBuf != NULL) && (_ftpBufLen >= 32)) {
00111                 memcpy (_ftpBuf, md5, 32);
00112                 if (_ftpBufLen == 33) {
00113                     *(buf + 32) = 0; // Add a terminator if there's room
00114                 }
00115             }
00116         }
00117         debug_if(_debug_trace_on, "%s result code is %d\n",
00118                  getFtpCmd((FtpCmd) _lastFtpOpCodeResult), _lastFtpResult);
00119     }
00120 }
00121 
00122 // Callback for FTP data handling.
00123 void UbloxATCellularInterfaceExt::UUFTPCD_URC()
00124 {
00125     char buf[32];
00126     char *ftpBufPtr = _ftpBuf;
00127     int ftpDataLen;
00128 
00129     // Note: not calling _at->recv() from here as we're
00130     // already in an _at->recv()
00131     // +UUFTPCD: <op_code>,<ftp_data_len>,<ftp_data_in_quotes>
00132     if (read_at_to_char(buf, sizeof(buf), '\"') > 0) {
00133         if (sscanf(buf, ": %d,%d,\"", &_lastFtpOpCodeData, &ftpDataLen) == 2) {
00134             if ((ftpBufPtr != NULL) && (_ftpBufLen > 0)) {
00135                 if (ftpDataLen + 1 > _ftpBufLen) { // +1 for terminator
00136                     ftpDataLen = _ftpBufLen - 1;
00137                 }
00138                 ftpBufPtr += _at->read(ftpBufPtr, ftpDataLen);
00139                 *ftpBufPtr = 0; // Add terminator
00140             }
00141         }
00142     }
00143 }
00144 
00145 // Return a string representing an FTP AT command.
00146 const char *UbloxATCellularInterfaceExt::getFtpCmd(FtpCmd ftpCmd)
00147 {
00148     const char * str = "FTP command not recognised";
00149 
00150     switch (ftpCmd) {
00151         case FTP_LOGOUT:
00152             str = "FTP log out command";
00153             break;
00154         case FTP_LOGIN:
00155             str = "FTP log in command";
00156             break;
00157         case FTP_DELETE_FILE:
00158             str = "FTP delete file command";
00159             break;
00160         case FTP_RENAME_FILE:
00161             str = "FTP rename file command";
00162             break;
00163         case FTP_GET_FILE:
00164             str = "FTP get file command";
00165             break;
00166         case FTP_PUT_FILE:
00167             str = "FTP put file command";
00168             break;
00169         case FTP_CD:
00170             str = "FTP change directory command";
00171             break;
00172         case FTP_MKDIR:
00173             str = "FTP make directory command";
00174             break;
00175         case FTP_RMDIR:
00176             str = "FTP remove directory command";
00177             break;
00178         case FTP_FILE_INFO:
00179             str = "FTP file info command";
00180             break;
00181         case FTP_LS:
00182             str = "FTP directory list command";
00183             break;
00184         case FTP_FOTA_FILE:
00185             str = "FTP FOTA file command";
00186             break;
00187         default:
00188             break;
00189     }
00190 
00191     return str;
00192 }
00193 
00194 /**********************************************************************
00195  * PROTECTED METHODS: Cell Locate
00196  **********************************************************************/
00197 
00198 // Callback for UULOCIND handling.
00199 void UbloxATCellularInterfaceExt::UULOCIND_URC()
00200 {
00201     char buf[32];
00202     int a, b;
00203 
00204     // Note: not calling _at->recv() from here as we're
00205     // already in an _at->recv()
00206     // +UULOCIND: <step>,<result>
00207     if (read_at_to_char(buf, sizeof (buf), '\n') > 0) {
00208         if (sscanf(buf, " %d,%d", &a, &b) == 2) {
00209             switch (a) {
00210                 case 0:
00211                     debug_if(_debug_trace_on, "Network scan start\n");
00212                     break;
00213                 case 1:
00214                     debug_if(_debug_trace_on, "Network scan end\n");
00215                     break;
00216                 case 2:
00217                     debug_if(_debug_trace_on, "Requesting data from server\n");
00218                     break;
00219                 case 3:
00220                     debug_if(_debug_trace_on, "Received data from server\n");
00221                     break;
00222                 case 4:
00223                     debug_if(_debug_trace_on, "Sending feedback to server\n");
00224                     break;
00225                 default:
00226                     debug_if(_debug_trace_on, "Unknown step\n");
00227                     break;
00228             }
00229             switch (b) {
00230                 case 0:
00231                     // No error
00232                     break;
00233                 case 1:
00234                     debug_if(_debug_trace_on, "Wrong URL!\n");
00235                     break;
00236                 case 2:
00237                     debug_if(_debug_trace_on, "HTTP error!\n");
00238                     break;
00239                 case 3:
00240                     debug_if(_debug_trace_on, "Create socket error!\n");
00241                     break;
00242                 case 4:
00243                     debug_if(_debug_trace_on, "Close socket error!\n");
00244                     break;
00245                 case 5:
00246                     debug_if(_debug_trace_on, "Write to socket error!\n");
00247                     break;
00248                 case 6:
00249                     debug_if(_debug_trace_on, "Read from socket error!\n");
00250                     break;
00251                 case 7:
00252                     debug_if(_debug_trace_on, "Connection/DNS error!\n");
00253                     break;
00254                 case 8:
00255                     debug_if(_debug_trace_on, "Authentication token problem!\n");
00256                     break;
00257                 case 9:
00258                     debug_if(_debug_trace_on, "Generic error!\n");
00259                     break;
00260                 case 10:
00261                     debug_if(_debug_trace_on, "User terminated!\n");
00262                     break;
00263                 case 11:
00264                     debug_if(_debug_trace_on, "No data from server!\n");
00265                     break;
00266                 default:
00267                     debug_if(_debug_trace_on, "Unknown result!\n");
00268                     break;
00269             }
00270         }
00271     }
00272 }
00273 
00274 // Callback for UULOC URC handling.
00275 void UbloxATCellularInterfaceExt::UULOC_URC()
00276 {
00277     int a, b;
00278 
00279     // Note: not calling _at->recv() from here as we're
00280     // already in an _at->recv()
00281 
00282     // +UHTTPCR: <profile_id>,<op_code>,<param_val>
00283     if (read_at_to_char(urcBuf, sizeof (urcBuf), '\n') > 0) {
00284         // Response type 1
00285         // +UULOC: <date>,<time>,<lat>,<long>,<alt>,<uncertainty>,<speed>, <direction>,<vertical_acc>,<sensor_used>,<SV_used>,<antenna_status>, <jamming_status>
00286         if (sscanf(urcBuf, " %d/%d/%d,%d:%d:%d.%*d,%f,%f,%d,%d,%d,%d,%d,%d,%d,%*d,%*d",
00287                    &_loc[0].time.tm_mday, &_loc[0].time.tm_mon,
00288                    &_loc[0].time.tm_year, &_loc[0].time.tm_hour,
00289                    &_loc[0].time.tm_min, &_loc[0].time.tm_sec,
00290                    &_loc[0].latitude, &_loc[0].longitude, &_loc[0].altitude,
00291                    &_loc[0].uncertainty, &_loc[0].speed, &_loc[0].direction,
00292                    &_loc[0].verticalAcc,
00293                    &b, &_loc[0].svUsed) == 15) {
00294             debug_if(_debug_trace_on, "Position found at index 0\n");
00295             _loc[0].sensor = (b == 0) ? CELL_LAST : (b == 1) ? CELL_GNSS :
00296                              (b == 2) ? CELL_LOCATE : (b == 3) ? CELL_HYBRID : CELL_LAST;
00297             _loc[0].time.tm_year -= 1900;
00298             _loc[0].time.tm_mon -= 1;
00299             _loc[0].time.tm_wday = 0;
00300             _loc[0].time.tm_yday = 0;
00301             _loc[0].validData = true;
00302             // Uncertainty can appear as 4294967, which is
00303             // (2^32 - 1) / 1000, or -1.  Since it is confusing
00304             // for the user to get a large positive number instead
00305             // of 0 -1, set it to -1 in th1s case.
00306             if (_loc[0].uncertainty == 4294967) {
00307                 _loc[0].uncertainty = -1;
00308             }
00309             _locExpPos = 1;
00310             _locRcvPos++;
00311         // Response type 2, sensor used 1
00312         // +UULOC: <sol>,<num>,<sensor_used>,<date>,<time>,<lat>,<long>,<alt>,<uncertainty>,<speed>, <direction>,<vertical_acc>,,<SV_used>,<antenna_status>, <jamming_status>
00313         } else if (sscanf(urcBuf, " %d,%d,%d,%d/%d/%d,%d:%d:%d.%*d,%f,%f,%d,%d,%d,%d,%d,%d,%*d,%*d",
00314                    &a, &_locExpPos, &b,
00315                    &_loc[CELL_MAX_HYP - 1].time.tm_mday,
00316                    &_loc[CELL_MAX_HYP - 1].time.tm_mon,
00317                    &_loc[CELL_MAX_HYP - 1].time.tm_year,
00318                    &_loc[CELL_MAX_HYP - 1].time.tm_hour,
00319                    &_loc[CELL_MAX_HYP - 1].time.tm_min,
00320                    &_loc[CELL_MAX_HYP - 1].time.tm_sec,
00321                    &_loc[CELL_MAX_HYP - 1].latitude,
00322                    &_loc[CELL_MAX_HYP - 1].longitude,
00323                    &_loc[CELL_MAX_HYP - 1].altitude,
00324                    &_loc[CELL_MAX_HYP - 1].uncertainty,
00325                    &_loc[CELL_MAX_HYP - 1].speed,
00326                    &_loc[CELL_MAX_HYP - 1].direction,
00327                    &_loc[CELL_MAX_HYP - 1].verticalAcc,
00328                    &_loc[CELL_MAX_HYP - 1].svUsed) == 17) {
00329             if (--a >= 0) {
00330                 debug_if(_debug_trace_on, "Position found at index %d\n", a);
00331 
00332                 memcpy(&_loc[a], &_loc[CELL_MAX_HYP - 1], sizeof(*_loc));
00333 
00334                 _loc[a].sensor = (b == 0) ? CELL_LAST : (b == 1) ? CELL_GNSS :
00335                                  (b == 2) ? CELL_LOCATE : (b == 3) ? CELL_HYBRID : CELL_LAST;
00336                 _loc[a].time.tm_year -= 1900;
00337                 _loc[a].time.tm_mon -= 1;
00338                 _loc[a].time.tm_wday = 0;
00339                 _loc[a].time.tm_yday = 0;
00340                 // Uncertainty can appear as 4294967, which is
00341                 // (2^32 - 1) / 1000, or -1.  Since it is confusing
00342                 // for the user to get a large positive number instead
00343                 // of 0 -1, set it to -1 in th1s case.
00344                 if (_loc[a].uncertainty == 4294967) {
00345                     _loc[a].uncertainty = -1;
00346                 }
00347                 _loc[a].validData = true;
00348                 _locRcvPos++;
00349             }
00350         // Response type 2, sensor used 2
00351         //+UULOC: <sol>,<num>,<sensor_used>,<date>,<time>,<lat>,<long>,<alt>,<lat50>,<long50>,<major50>,<minor50>,<orientation50>,<confidence50>[,<lat95>,<long95>,<major95>,<minor95>,<orientation95>,<confidence95>]
00352         } else if (sscanf(urcBuf, " %d,%d,%d,%d/%d/%d,%d:%d:%d.%*d,%f,%f,%d,%*f,%*f,%d,%*d,%*d,%*d",
00353                    &a, &_locExpPos, &b,
00354                    &_loc[CELL_MAX_HYP - 1].time.tm_mday,
00355                    &_loc[CELL_MAX_HYP - 1].time.tm_mon,
00356                    &_loc[CELL_MAX_HYP - 1].time.tm_year,
00357                    &_loc[CELL_MAX_HYP - 1].time.tm_hour,
00358                    &_loc[CELL_MAX_HYP - 1].time.tm_min,
00359                    &_loc[CELL_MAX_HYP - 1].time.tm_sec,
00360                    &_loc[CELL_MAX_HYP - 1].latitude,
00361                    &_loc[CELL_MAX_HYP - 1].longitude,
00362                    &_loc[CELL_MAX_HYP - 1].altitude,
00363                    &_loc[CELL_MAX_HYP - 1].uncertainty) == 13) {
00364             if (--a >= 0) {
00365 
00366                 debug_if(_debug_trace_on, "Position found at index %d\n", a);
00367 
00368                 memcpy(&_loc[a], &_loc[CELL_MAX_HYP - 1], sizeof(*_loc));
00369 
00370                 _loc[a].sensor = (b == 0) ? CELL_LAST : (b == 1) ? CELL_GNSS :
00371                                  (b == 2) ? CELL_LOCATE : (b == 3) ? CELL_HYBRID : CELL_LAST;
00372                 _loc[a].time.tm_year -= 1900;
00373                 _loc[a].time.tm_mon -= 1;
00374                 _loc[a].time.tm_wday = 0;
00375                 _loc[a].time.tm_yday = 0;
00376                 _loc[a].speed = 0;
00377                 _loc[a].direction = 0;
00378                 _loc[a].verticalAcc = 0;
00379                 _loc[a].svUsed = 0;
00380                 // Uncertainty can appear as 4294967, which is
00381                 // (2^32 - 1) / 1000, or -1.  Since it is confusing
00382                 // for the user to get a large positive number instead
00383                 // of 0 -1, set it to -1 in th1s case.
00384                 if (_loc[a].uncertainty == 4294967) {
00385                     _loc[a].uncertainty = -1;
00386                 }
00387                 _loc[a].validData = true;
00388                 _locRcvPos++;
00389             }
00390         // Response type 2, sensor used 0
00391         //+UULOC: <sol>,<num>,<sensor_used>,<date>,<time>,<lat>,<long>,<alt>,<uncertainty>
00392         } else if (sscanf(urcBuf, " %d,%d,%d,%d/%d/%d,%d:%d:%d.%*d,%f,%f,%d,%d",
00393                    &a, &_locExpPos, &b,
00394                    &_loc[CELL_MAX_HYP - 1].time.tm_mday,
00395                    &_loc[CELL_MAX_HYP - 1].time.tm_mon,
00396                    &_loc[CELL_MAX_HYP - 1].time.tm_year,
00397                    &_loc[CELL_MAX_HYP - 1].time.tm_hour,
00398                    &_loc[CELL_MAX_HYP - 1].time.tm_min,
00399                    &_loc[CELL_MAX_HYP - 1].time.tm_sec,
00400                    &_loc[CELL_MAX_HYP - 1].latitude,
00401                    &_loc[CELL_MAX_HYP - 1].longitude,
00402                    &_loc[CELL_MAX_HYP - 1].altitude,
00403                    &_loc[CELL_MAX_HYP - 1].uncertainty) == 13) {
00404             if (--a >= 0) {
00405 
00406                 debug_if(_debug_trace_on, "Position found at index %d\n", a);
00407 
00408                 memcpy(&_loc[a], &_loc[CELL_MAX_HYP - 1], sizeof(*_loc));
00409 
00410                 _loc[a].sensor = (b == 0) ? CELL_LAST : (b == 1) ? CELL_GNSS :
00411                                  (b == 2) ? CELL_LOCATE : (b == 3) ? CELL_HYBRID : CELL_LAST;
00412                 _loc[a].time.tm_year -= 1900;
00413                 _loc[a].time.tm_mon -= 1;
00414                 _loc[a].time.tm_wday = 0;
00415                 _loc[a].time.tm_yday = 0;
00416                 _loc[a].speed = 0;
00417                 _loc[a].direction = 0;
00418                 _loc[a].verticalAcc = 0;
00419                 _loc[a].svUsed = 0;
00420                 // Uncertainty can appear as 4294967, which is
00421                 // (2^32 - 1) / 1000, or -1.  Since it is confusing
00422                 // for the user to get a large positive number instead
00423                 // of 0 -1, set it to -1 in th1s case.
00424                 if (_loc[a].uncertainty == 4294967) {
00425                     _loc[a].uncertainty = -1;
00426                 }
00427                 _loc[a].validData = true;
00428                 _locRcvPos++;
00429             }
00430         }
00431     }
00432 }
00433 
00434 /**********************************************************************
00435  * PUBLIC METHODS: GENERAL
00436  **********************************************************************/
00437 
00438 // Constructor.
00439 UbloxATCellularInterfaceExt::UbloxATCellularInterfaceExt(PinName tx,
00440                                                          PinName rx,
00441                                                          int baud,
00442                                                          bool debugOn,
00443                                                          osPriority priority):
00444                              UbloxATCellularInterface(tx, rx, baud, debugOn, priority)
00445 {
00446     // Zero HTTP stuff
00447     memset(_httpProfiles, 0, sizeof(_httpProfiles));
00448     for (unsigned int profile = 0; profile < sizeof(_httpProfiles) / sizeof(_httpProfiles[0]);
00449          profile++) {
00450         _httpProfiles[profile].modemHandle = HTTP_PROF_UNUSED;
00451     }
00452 
00453     // Zero FTP stuff
00454     _ftpTimeout = TIMEOUT_BLOCKING;
00455     _lastFtpOpCodeResult = FTP_OP_CODE_UNUSED;
00456     _lastFtpResult = 0;
00457     _lastFtpOpCodeData = FTP_OP_CODE_UNUSED;
00458     _ftpBuf = NULL;
00459     _ftpBufLen = 0;
00460     _ftpError.eClass = 0;
00461     _ftpError.eCode = 0;
00462 
00463     // Zero Cell Locate stuff
00464     _locRcvPos = 0;
00465     _locExpPos = 0;
00466 
00467     // URC handler for HTTP
00468     _at->oob("+UUHTTPCR", callback(this, &UbloxATCellularInterfaceExt::UUHTTPCR_URC));
00469 
00470     // URC handlers for FTP
00471     _at->oob("+UUFTPCR", callback(this, &UbloxATCellularInterfaceExt::UUFTPCR_URC));
00472     _at->oob("+UUFTPCD", callback(this, &UbloxATCellularInterfaceExt::UUFTPCD_URC));
00473 
00474     // URC handlers for Cell Locate
00475     _at->oob("+UULOCIND:", callback(this, &UbloxATCellularInterfaceExt::UULOCIND_URC));
00476     _at->oob("+UULOC:", callback(this, &UbloxATCellularInterfaceExt::UULOC_URC));
00477 }
00478 
00479 // Destructor.
00480 UbloxATCellularInterfaceExt::~UbloxATCellularInterfaceExt()
00481 {
00482 }
00483 
00484 /**********************************************************************
00485  * PUBLIC METHODS: HTTP
00486  **********************************************************************/
00487 
00488 // Find a free profile.
00489 int UbloxATCellularInterfaceExt::httpAllocProfile()
00490 {
00491     int profile = HTTP_PROF_UNUSED;
00492     LOCK();
00493 
00494     // Find a free HTTP profile
00495     profile = findProfile();
00496     debug_if(_debug_trace_on, "httpFindProfile: profile is %d\n", profile);
00497 
00498     if (profile != HTTP_PROF_UNUSED) {
00499         _httpProfiles[profile].modemHandle = 1;
00500         _httpProfiles[profile].timeout     = TIMEOUT_BLOCKING;
00501         _httpProfiles[profile].pending     = false;
00502         _httpProfiles[profile].cmd         = -1;
00503         _httpProfiles[profile].result      = -1;
00504     }
00505 
00506     UNLOCK();
00507     return profile;
00508 }
00509 
00510 // Free a profile.
00511 bool UbloxATCellularInterfaceExt::httpFreeProfile(int profile)
00512 {
00513     bool success = false;
00514     LOCK();
00515 
00516     if (IS_PROFILE(profile)) {
00517         debug_if(_debug_trace_on, "httpFreeProfile(%d)\n", profile);
00518         _httpProfiles[profile].modemHandle = HTTP_PROF_UNUSED;
00519         _httpProfiles[profile].timeout     = TIMEOUT_BLOCKING;
00520         _httpProfiles[profile].pending     = false;
00521         _httpProfiles[profile].cmd         = -1;
00522         _httpProfiles[profile].result      = -1;
00523         success = _at->send("AT+UHTTP=%d", profile) && _at->recv("OK");
00524     }
00525 
00526     UNLOCK();
00527     return success;
00528 }
00529 
00530 // Set the blocking/timeout state of a profile.
00531 bool UbloxATCellularInterfaceExt::httpSetTimeout(int profile, int timeout)
00532 {
00533     bool success = false;
00534     LOCK();
00535 
00536     debug_if(_debug_trace_on, "httpSetTimeout(%d, %d)\n", profile, timeout);
00537 
00538     if (IS_PROFILE(profile)) {
00539         _httpProfiles[profile].timeout = timeout;
00540         success = true;
00541     }
00542 
00543     UNLOCK();
00544     return success;
00545 }
00546 
00547 // Set a profile back to defaults.
00548 bool UbloxATCellularInterfaceExt::httpResetProfile(int httpProfile)
00549 {
00550     bool success = false;
00551     LOCK();
00552 
00553     debug_if(_debug_trace_on, "httpResetProfile(%d)\n", httpProfile);
00554     success = _at->send("AT+UHTTP=%d", httpProfile) && _at->recv("OK");
00555 
00556     UNLOCK();
00557     return success;
00558 }
00559 
00560 // Set HTTP parameters.
00561 bool UbloxATCellularInterfaceExt::httpSetPar(int httpProfile,
00562                                              HttpOpCode httpOpCode,
00563                                              const char * httpInPar)
00564 {
00565     bool success = false;
00566     int httpInParNum = 0;
00567     SocketAddress address;
00568 
00569     debug_if(_debug_trace_on, "httpSetPar(%d, %d, \"%s\")\n", httpProfile, httpOpCode, httpInPar);
00570     if (IS_PROFILE(httpProfile)) {
00571         LOCK();
00572 
00573         switch(httpOpCode) {
00574             case HTTP_IP_ADDRESS:   // 0
00575                 if (gethostbyname(httpInPar, &address) == NSAPI_ERROR_OK) {
00576                     success = _at->send("AT+UHTTP=%d,%d,\"%s\"",
00577                                         httpProfile, httpOpCode, address.get_ip_address()) &&
00578                               _at->recv("OK");
00579                 }
00580                 break;
00581             case HTTP_SERVER_NAME:  // 1
00582             case HTTP_USER_NAME:    // 2
00583             case HTTP_PASSWORD:     // 3
00584                 success = _at->send("AT+UHTTP=%d,%d,\"%s\"", httpProfile, httpOpCode, httpInPar) &&
00585                           _at->recv("OK");
00586                 break;
00587 
00588             case HTTP_AUTH_TYPE:    // 4
00589             case HTTP_SERVER_PORT:  // 5
00590                 httpInParNum = atoi(httpInPar);
00591                 success = _at->send("AT+UHTTP=%d,%d,%d", httpProfile, httpOpCode, httpInParNum) &&
00592                           _at->recv("OK");
00593                 break;
00594 
00595             case HTTP_SECURE:       // 6
00596                 httpInParNum = atoi(httpInPar);
00597                 success = _at->send("AT+UHTTP=%d,%d,%d", httpProfile, httpOpCode, httpInParNum) &&
00598                           _at->recv("OK");
00599                 break;
00600 
00601             default:
00602                 debug_if(_debug_trace_on, "httpSetPar: unknown httpOpCode %d\n", httpOpCode);
00603                 break;
00604         }
00605 
00606         UNLOCK();
00607     }
00608 
00609     return success;
00610 }
00611 
00612 // Perform an HTTP command.
00613 UbloxATCellularInterfaceExt::Error * UbloxATCellularInterfaceExt::httpCommand(int httpProfile,
00614                                                                               HttpCmd httpCmd,
00615                                                                               const char *httpPath,
00616                                                                               const char *rspFile,
00617                                                                               const char *sendStr,
00618                                                                               int httpContentType,
00619                                                                               const char *httpCustomPar,
00620                                                                               char *buf, int len)
00621 {
00622     bool atSuccess = false;
00623     bool success = false;
00624     int at_timeout;
00625     char defaultFilename[] = "http_last_response_x";
00626 
00627     debug_if(_debug_trace_on, "%s\n", getHttpCmd(httpCmd));
00628 
00629     if (IS_PROFILE(httpProfile)) {
00630         LOCK();
00631         at_timeout = _at_timeout; // Has to be inside LOCK()s
00632 
00633         if (rspFile == NULL) {
00634             sprintf(defaultFilename + sizeof (defaultFilename) - 2, "%1d", httpProfile);
00635             rspFile = defaultFilename;
00636         }
00637 
00638         switch (httpCmd) {
00639             case HTTP_HEAD:
00640                 atSuccess = _at->send("AT+UHTTPC=%d,%d,\"%s\",\"%s\"", httpProfile, httpCmd,
00641                                       httpPath, rspFile) &&
00642                             _at->recv("OK");
00643                 break;
00644             case HTTP_GET:
00645                 atSuccess = _at->send("AT+UHTTPC=%d,%d,\"%s\",\"%s\"", httpProfile, httpCmd,
00646                                       httpPath, rspFile) &&
00647                             _at->recv("OK");
00648                 break;
00649             case HTTP_DELETE:
00650                 atSuccess = _at->send("AT+UHTTPC=%d,%d,\"%s\",\"%s\"", httpProfile, httpCmd,
00651                                       httpPath, rspFile) &&
00652                             _at->recv("OK");
00653                 break;
00654             case HTTP_PUT:
00655                 // In this case the parameter sendStr is a filename
00656                 atSuccess = _at->send("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\"", httpProfile, httpCmd,
00657                                       httpPath, rspFile, sendStr) &&
00658                             _at->recv("OK");
00659                 break;
00660             case HTTP_POST_FILE:
00661                 // In this case the parameter sendStr is a filename
00662                 if (httpContentType != 6) {
00663                     atSuccess = _at->send("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d",
00664                                           httpProfile, httpCmd, httpPath, rspFile, sendStr,
00665                                           httpContentType) &&
00666                                 _at->recv("OK");
00667                 } else {
00668                     atSuccess = _at->send("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d,%s",
00669                                           httpProfile, httpCmd, httpPath, rspFile, sendStr,
00670                                           httpContentType,
00671                                           httpCustomPar) &&
00672                                 _at->recv("OK");
00673                 }
00674                 break;
00675             case HTTP_POST_DATA:
00676                 // In this case the parameter sendStr is a string containing data
00677                 if (httpContentType != 6) {
00678                     atSuccess = _at->send("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d",
00679                                           httpProfile, httpCmd, httpPath, rspFile, sendStr,
00680                                           httpContentType) &&
00681                                 _at->recv("OK");
00682                 } else {
00683                     atSuccess = _at->send("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d,%s",
00684                                           httpProfile, httpCmd, httpPath, rspFile, sendStr,
00685                                           httpContentType,
00686                                           httpCustomPar) &&
00687                                 _at->recv("OK");
00688                 }
00689                 break;
00690             default:
00691                 debug_if(_debug_trace_on, "HTTP command not recognised\n");
00692                 break;
00693         }
00694 
00695         if (atSuccess) {
00696             Timer timer;
00697 
00698             at_set_timeout(1000);
00699             _httpProfiles[httpProfile].pending = true;
00700             _httpProfiles[httpProfile].result = -1;
00701 
00702             // Waiting for unsolicited result code
00703             timer.start();
00704             while (_httpProfiles[httpProfile].pending) {
00705                 if (_httpProfiles[httpProfile].result != -1) {
00706                     // Received unsolicited: starting its analysis
00707                     _httpProfiles[httpProfile].pending = false;
00708                     if (_httpProfiles[httpProfile].result == 1) {
00709                         // Leave a short delay to make sure the file has been written
00710                         wait_ms(100);
00711                         // HTTP command successfully executed
00712                         if (readFile(rspFile, buf, len) >= 0) {
00713                             success = true;
00714                         }
00715                     } else {
00716                         // Retrieve the error class and code
00717                         if (_at->send("AT+UHTTPER=%d", httpProfile) &&
00718                             _at->recv("AT+UHTTPER=%*d,%d,%d",
00719                                       &(_httpProfiles[httpProfile].httpError.eClass),
00720                                       &(_httpProfiles[httpProfile].httpError.eCode)) &&
00721                             _at->recv("OK")) {
00722                             debug_if(_debug_trace_on, "HTTP error class %d, code %d\n",
00723                                     _httpProfiles[httpProfile].httpError.eClass,
00724                                     _httpProfiles[httpProfile].httpError.eCode);
00725                         }
00726                     }
00727                 } else if (!TIMEOUT(timer, _httpProfiles[httpProfile].timeout)) {
00728                     // Wait for URCs
00729                     _at->recv(UNNATURAL_STRING);
00730                 } else  {
00731                     _httpProfiles[httpProfile].pending = false;
00732                 }
00733             }
00734             timer.stop();
00735 
00736             at_set_timeout(at_timeout);
00737 
00738             if (!success) {
00739                 debug_if(_debug_trace_on, "%s: ERROR\n", getHttpCmd(httpCmd));
00740             }
00741 
00742         }
00743 
00744         UNLOCK();
00745     }
00746 
00747     return success ? NULL : &(_httpProfiles[httpProfile].httpError);
00748 }
00749 
00750 /**********************************************************************
00751  * PUBLIC METHODS: FTP
00752  **********************************************************************/
00753 
00754 // Set the blocking/timeout for FTP.
00755 bool UbloxATCellularInterfaceExt::ftpSetTimeout(int timeout)
00756 {
00757     LOCK();
00758     debug_if(_debug_trace_on, "ftpSetTimeout(%d)\n", timeout);
00759     _ftpTimeout = timeout;
00760     UNLOCK();
00761 
00762     return true;
00763 }
00764 
00765 // Reset the FTP configuration back to defaults.
00766 // Note: not all modrmd support all parameters,
00767 // hence the void return code.
00768 void UbloxATCellularInterfaceExt::ftpResetPar()
00769 {
00770     LOCK();
00771     debug_if(_debug_trace_on, "ftpResetPar()\n");
00772     for (int x = 0; x < NUM_FTP_OP_CODES; x++) {
00773         if (_at->send("AT+UFTP=%d", x)) {
00774             _at->recv("OK");
00775         }
00776     }
00777     UNLOCK();
00778 }
00779 
00780 // Set FTP parameters.
00781 bool UbloxATCellularInterfaceExt::ftpSetPar(FtpOpCode ftpOpCode,
00782                                             const char * ftpInPar)
00783 {
00784     bool success = false;
00785     int ftpInParNum = 0;
00786     LOCK();
00787 
00788     debug_if(_debug_trace_on, "ftpSetPar(%d, %s)\n", ftpOpCode, ftpInPar);
00789     switch (ftpOpCode) {
00790         case FTP_IP_ADDRESS:         // 0
00791         case FTP_SERVER_NAME:        // 1
00792         case FTP_USER_NAME:          // 2
00793         case FTP_PASSWORD:           // 3
00794         case FTP_ACCOUNT:            // 4
00795             success = _at->send("AT+UFTP=%d,\"%s\"", ftpOpCode, ftpInPar) &&
00796                       _at->recv("OK");
00797             break;
00798         case FTP_INACTIVITY_TIMEOUT: // 5
00799         case FTP_MODE:               // 6
00800         case FTP_SERVER_PORT:        // 7
00801         case FTP_SECURE:             // 8
00802             ftpInParNum = atoi(ftpInPar);
00803             success = _at->send("AT+UFTP=%d,%d", ftpOpCode, ftpInParNum) &&
00804                       _at->recv("OK");
00805             break;
00806         default:
00807             debug_if(_debug_trace_on, "ftpSetPar: unknown ftpOpCode %d\n", ftpOpCode);
00808             break;
00809     }
00810 
00811     UNLOCK();
00812     return success;
00813 }
00814 
00815 // Perform an FTP command.
00816 UbloxATCellularInterfaceExt::Error * UbloxATCellularInterfaceExt::ftpCommand(FtpCmd ftpCmd,
00817                                                                              const char* file1,
00818                                                                              const char* file2,
00819                                                                              char* buf, int len,
00820                                                                              int offset)
00821 {
00822     bool atSuccess = false;
00823     bool success = false;
00824     int at_timeout;
00825     LOCK();
00826     at_timeout = _at_timeout; // Has to be inside LOCK()s
00827 
00828     debug_if(_debug_trace_on, "%s\n", getFtpCmd(ftpCmd));
00829     switch (ftpCmd) {
00830         case FTP_LOGOUT:
00831         case FTP_LOGIN:
00832             atSuccess = _at->send("AT+UFTPC=%d", ftpCmd) && _at->recv("OK");
00833             break;
00834         case FTP_DELETE_FILE:
00835         case FTP_CD:
00836         case FTP_MKDIR:
00837         case FTP_RMDIR:
00838         case FTP_FOTA_FILE:
00839             atSuccess = _at->send("AT+UFTPC=%d,\"%s\"", ftpCmd, file1) &&
00840                         _at->recv("OK");
00841             break;
00842         case FTP_RENAME_FILE:
00843             atSuccess = _at->send("AT+UFTPC=%d,\"%s\",\"%s\"",
00844                                   ftpCmd, file1, file2) &&
00845                         _at->recv("OK");
00846             break;
00847         case FTP_GET_FILE:
00848         case FTP_PUT_FILE:
00849             if (file2 == NULL) {
00850                 file2 = file1;
00851             }
00852             atSuccess = _at->send("AT+UFTPC=%d,\"%s\",\"%s\",%d",
00853                                   ftpCmd, file1, file2, offset) &&
00854                         _at->recv("OK");
00855             
00856             // Not all modules support continuing a GET/PUT (e.g.
00857             // Sara-G350 00S-00 doesn't), so if we receive an error,
00858             // try again without it
00859             if (!atSuccess) {
00860                 atSuccess = _at->send("AT+UFTPC=%d,\"%s\",\"%s\"",
00861                                       ftpCmd, file1, file2) &&
00862                             _at->recv("OK");
00863             }
00864             break;
00865         case FTP_FILE_INFO:
00866         case FTP_LS:
00867             _ftpBuf = buf;
00868             _ftpBufLen = len;
00869             // Add a terminator in case nothing comes back
00870             if (_ftpBufLen > 0) {
00871                 *_ftpBuf = 0;
00872             }
00873             if (file1 == NULL) {
00874                 atSuccess = _at->send("AT+UFTPC=%d", ftpCmd) &&
00875                             _at->recv("OK");
00876             } else {
00877                 atSuccess = _at->send("AT+UFTPC=%d,\"%s\"", ftpCmd, file1) &&
00878                             _at->recv("OK");
00879             }
00880             break;
00881         default:
00882             debug_if(_debug_trace_on, "FTP command not recognised/supported\n");
00883             break;
00884     }
00885 
00886     // Wait for the result to arrive back
00887     if (atSuccess) {
00888         Timer timer;
00889 
00890         at_set_timeout(1000);
00891         _lastFtpOpCodeData = FTP_OP_CODE_UNUSED;
00892         _lastFtpOpCodeResult = FTP_OP_CODE_UNUSED;
00893         _lastFtpResult = -1; // just for safety
00894         // Waiting for result to arrive
00895         timer.start();
00896         while ((_lastFtpOpCodeResult == FTP_OP_CODE_UNUSED) &&
00897                 !TIMEOUT(timer, _ftpTimeout)) {
00898             _at->recv(UNNATURAL_STRING);
00899         }
00900         timer.stop();
00901 
00902         if ((_lastFtpOpCodeResult == ftpCmd) && (_lastFtpResult == 1)) {
00903             // Got a result for our FTP op code and it is good
00904             success = true;
00905         } else {
00906             // Retrieve the error class and code
00907             if (_at->send("AT+UFTPER") &&
00908                 _at->recv("+UFTPER:%d,%d", &(_ftpError.eClass), &(_ftpError.eCode)) &&
00909                 _at->recv("OK")) {
00910                 debug_if(_debug_trace_on, "FTP Error class %d, code %d\n",
00911                          _ftpError.eClass, _ftpError.eCode);
00912             }
00913         }
00914 
00915         at_set_timeout(at_timeout);
00916 
00917         if (!success) {
00918             debug_if(_debug_trace_on, "%s: ERROR\n", getFtpCmd(ftpCmd));
00919         }
00920     }
00921 
00922     // Set these back to nothing to stop the URC splatting
00923     _ftpBuf = NULL;
00924     _ftpBufLen = 0;
00925 
00926     UNLOCK();
00927     return success ? NULL : &_ftpError;
00928 }
00929 
00930 /**********************************************************************
00931  * PUBLIC METHODS: Cell Locate
00932  **********************************************************************/
00933 
00934 // Configure CellLocate TCP Aiding server.
00935 bool UbloxATCellularInterfaceExt::cellLocSrvTcp(const char* token,
00936                                                 const char* server_1,
00937                                                 const char* server_2,
00938                                                 int days, int period,
00939                                                 int resolution)
00940 {
00941     bool success = false;
00942     LOCK();
00943 
00944     if ((_dev_info.dev == DEV_LISA_U2_03S) || (_dev_info.dev  == DEV_SARA_U2)){
00945         success = _at->send("AT+UGSRV=\"%s\",\"%s\",\"%s\",%d,%d,%d",
00946                             server_1, server_2, token, days, period, resolution) &&
00947                   _at->recv("OK");
00948     }
00949 
00950     UNLOCK();
00951     return success;
00952 }
00953 
00954 // Configure CellLocate UDP Aiding server.
00955 bool UbloxATCellularInterfaceExt::cellLocSrvUdp(const char* server_1,
00956                                                 int port, int latency,
00957                                                 int mode)
00958 {
00959 
00960     bool success = false;
00961     LOCK();
00962 
00963     if (_dev_info.dev != DEV_TOBY_L2) {
00964         success = _at->send("AT+UGAOP=\"%s\",%d,%d,%d", server_1, port, latency, mode) &&
00965                   _at->recv("OK");
00966     }
00967 
00968     UNLOCK();
00969     return success;
00970 }
00971 
00972 // Configure Cell Locate location sensor.
00973 bool UbloxATCellularInterfaceExt::cellLocConfig(int scanMode)
00974 {
00975     bool success;
00976     LOCK();
00977 
00978     success = _at->send("AT+ULOCCELL=%d", scanMode) &&
00979               _at->recv("OK");
00980 
00981     UNLOCK();
00982     return success;
00983 }
00984 
00985 // Request CellLocate.
00986 bool UbloxATCellularInterfaceExt::cellLocRequest(CellSensType sensor,
00987                                                  int timeout,
00988                                                  int accuracy,
00989                                                  CellRespType type,
00990                                                  int hypothesis)
00991 {
00992     bool success = false;
00993 
00994     if ((hypothesis <= CELL_MAX_HYP) &&
00995         !((hypothesis > 1) && (type != CELL_MULTIHYP))) {
00996 
00997         LOCK();
00998 
00999         _locRcvPos = 0;
01000         _locExpPos = 0;
01001 
01002         for (int i = 0; i < hypothesis; i++) {
01003             _loc[i].validData = false;
01004         }
01005 
01006         // Switch on the URC but don't error on it as some
01007         // modules (e.g. Sara-G350) don't support it
01008         if (_at->send("AT+ULOCIND=1")) {
01009             _at->recv("OK");
01010         }
01011         // Switch on Cell Locate
01012         success = _at->send("AT+ULOC=2,%d,%d,%d,%d,%d", sensor, type, timeout, accuracy, hypothesis) &&
01013                   _at->recv("OK");
01014         // Answers are picked up by reacting to +ULOC
01015 
01016         UNLOCK();
01017     }
01018 
01019     return success;
01020 }
01021 
01022 // Get a position record.
01023 bool UbloxATCellularInterfaceExt::cellLocGetData(CellLocData *data, int index)
01024 {
01025     bool success = false;
01026 
01027     if (_loc[index].validData) {
01028         LOCK();
01029         memcpy(data, &_loc[index], sizeof(*_loc));
01030         success = true;
01031         UNLOCK();
01032     }
01033 
01034     return success;
01035 }
01036 
01037 // Get number of position records received.
01038 int UbloxATCellularInterfaceExt::cellLocGetRes()
01039 {
01040     int at_timeout;
01041     LOCK();
01042 
01043     at_timeout = _at_timeout; // Has to be inside LOCK()s
01044     at_set_timeout(1000);
01045     // Wait for URCs
01046     _at->recv(UNNATURAL_STRING);
01047     at_set_timeout(at_timeout);
01048 
01049     UNLOCK();
01050     return _locRcvPos;
01051 }
01052 
01053 // Get number of positions records expected to be received.
01054 int UbloxATCellularInterfaceExt::cellLocGetExpRes()
01055 {
01056     int numRecords = 0;
01057     LOCK();
01058 
01059     _at->recv("OK");
01060 
01061     if (_locRcvPos > 0) {
01062         numRecords = _locExpPos;
01063     }
01064 
01065     UNLOCK();
01066     return numRecords;
01067 }
01068 
01069 // End of file
01070