Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: ublox-at-cellular-interface
Fork of ublox-at-cellular-interface-ext by
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
Generated on Wed Jul 13 2022 00:36:15 by
1.7.2
