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.
Fork of MTS-Cellular by
UIP.cpp
00001 #include "mbed.h" 00002 #include "UIP.h" 00003 #include "MTSText.h" 00004 #include "MTSLog.h" 00005 #include "CellUtils.h" 00006 00007 using namespace mts; 00008 00009 UIP::UIP(Radio type) 00010 { 00011 this->type = type; 00012 io = NULL; 00013 dcd = NULL; 00014 dtr = NULL; 00015 resetLine = NULL; 00016 echoMode = true; 00017 pppConnected = false; 00018 socketMode = TCP; 00019 socketOpened = false; 00020 socketCloseable = true; 00021 local_port = 0; 00022 local_address = ""; 00023 host_port = 0; 00024 } 00025 00026 UIP::~UIP() 00027 { 00028 if (dtr != NULL) { 00029 dtr->write(1); 00030 } 00031 00032 delete dcd; 00033 delete dtr; 00034 delete resetLine; 00035 } 00036 00037 bool UIP::init(MTSBufferedIO* io) 00038 { 00039 if (! Cellular::init(io)) { 00040 return false; 00041 } 00042 00043 logDebug("radio type: %s", Cellular::getRadioNames(type).c_str()); 00044 return true; 00045 } 00046 00047 bool UIP::connect() 00048 { 00049 //Check if APN is not set, if it is not, connect will not work. 00050 if (type == MTSMC_H5_IP || type == MTSMC_H5 || type == MTSMC_G3) { 00051 if(apn.size() == 0) { 00052 logDebug("APN is not set"); 00053 return false; 00054 } 00055 } 00056 00057 //Check if socket is open 00058 if(socketOpened) { 00059 return true; 00060 } 00061 00062 //Check if already connected 00063 if(isConnected()) { 00064 return true; 00065 } 00066 00067 Timer tmr; 00068 00069 //Check Registration: AT+CREG? == 0,1 00070 tmr.start(); 00071 do { 00072 Registration registration = getRegistration(); 00073 if(registration != REGISTERED) { 00074 logTrace("Not Registered [%d] ... waiting", (int)registration); 00075 wait(1); 00076 } else { 00077 break; 00078 } 00079 } while(tmr.read() < 30); 00080 00081 //Check RSSI: AT+CSQ 00082 tmr.reset(); 00083 do { 00084 int rssi = getSignalStrength(); 00085 logDebug("Signal strength: %d", rssi); 00086 if(rssi == 99 || rssi == -1) { 00087 logTrace("No Signal ... waiting"); 00088 wait(1); 00089 } else { 00090 break; 00091 } 00092 } while(tmr.read() < 30); 00093 00094 //AT#CONNECTIONSTART: Make a PPP connection 00095 if (type == MTSMC_H5_IP) { 00096 logDebug("Making PPP Connection Attempt. APN[%s]", apn.c_str()); 00097 } else { 00098 logDebug("Making PPP Connection Attempt"); 00099 } 00100 std::string pppResult = sendCommand("AT#CONNECTIONSTART", 120000); 00101 00102 if(pppResult.find("Ok_Info_GprsActivation") != std::string::npos) { 00103 std::vector<std::string> parts = Text::split(pppResult, "\r\n"); 00104 if(parts.size() >= 2) { 00105 local_address = parts[1]; 00106 } 00107 logInfo("PPP Connection Established: IP[%s]", local_address.c_str()); 00108 pppConnected = true; 00109 00110 } else { 00111 pppConnected = false; 00112 } 00113 00114 return pppConnected; 00115 } 00116 00117 void UIP::disconnect() 00118 { 00119 //AT#CONNECTIONSTOP: Close a PPP connection 00120 logDebug("Closing PPP Connection"); 00121 00122 if(socketOpened) { 00123 close(true); 00124 } 00125 00126 Code code = sendBasicCommand("AT#CONNECTIONSTOP", 10000); 00127 if(code == MTS_SUCCESS) { 00128 logDebug("Successfully closed PPP Connection"); 00129 } else { 00130 logError("Closing PPP Connection [%d]. Continuing ...", (int)code); 00131 } 00132 00133 pppConnected = false; 00134 } 00135 00136 bool UIP::isConnected() 00137 { 00138 //1) Check if APN was set if we're on an HSPA radio 00139 if (type == MTSMC_H5_IP || type == MTSMC_H5 || type == MTSMC_G3) { 00140 if(apn.size() == 0) { 00141 logDebug("APN is not set"); 00142 return false; 00143 } 00144 } 00145 00146 //2) Check that we do not have a live connection up 00147 if(socketOpened) { 00148 logDebug("Socket is opened"); 00149 return true; 00150 } 00151 //3) Query the radio 00152 std::string result = sendCommand("AT#VSTATE", 3000); 00153 if(result.find("CONNECTED") != std::string::npos) { 00154 if(pppConnected == false) { 00155 logWarning("Internal PPP state tracking differs from radio (DISCONNECTED:CONNECTED)"); 00156 } 00157 pppConnected = true; 00158 } else { 00159 if(pppConnected == true) { 00160 //Find out what state is 00161 size_t pos = result.find("STATE:"); 00162 if(pos != std::string::npos) { 00163 result = Text::getLine(result, pos + sizeof("STATE:"), pos); 00164 logWarning("Internal PPP state tracking differs from radio (CONNECTED:%s)", result.c_str()); 00165 } else { 00166 logError("Unable to parse radio state: [%s]", result.c_str()); 00167 } 00168 00169 } 00170 pppConnected = false; 00171 } 00172 00173 return pppConnected; 00174 } 00175 00176 bool UIP::open(const std::string& address, unsigned int port, Mode mode) 00177 { 00178 char buffer[256] = {0}; 00179 Code portCode, addressCode; 00180 00181 //1) Check that we do not have a live connection up 00182 if(socketOpened) { 00183 //Check that the address, port, and mode match 00184 if(host_address != address || host_port != port || socketMode != mode) { 00185 if(socketMode == TCP) { 00186 logError("TCP socket already opened [%s:%d]", host_address.c_str(), host_port); 00187 } else { 00188 logError("UDP socket already opened [%s:%d]", host_address.c_str(), host_port); 00189 } 00190 return false; 00191 } 00192 00193 logDebug("Socket already opened"); 00194 return true; 00195 } 00196 00197 //2) Check Parameters 00198 if(port > 65535) { 00199 logError("port out of range (0-65535)"); 00200 return false; 00201 } 00202 00203 //3) Check PPP connection 00204 if(!isConnected()) { 00205 logError("PPP not established. Attempting to connect"); 00206 if(!connect()) { 00207 logError("PPP connection failed"); 00208 return false; 00209 } else { 00210 logDebug("PPP connection established"); 00211 } 00212 } 00213 00214 //Set Local Port 00215 if(local_port != 0) { 00216 //Attempt to set local port 00217 sprintf(buffer, "AT#OUTPORT=%d", local_port); 00218 Code code = sendBasicCommand(buffer, 1000); 00219 if(code != MTS_SUCCESS) { 00220 logWarning("Unable to set local port (%d) [%d]", local_port, (int) code); 00221 } 00222 } 00223 00224 //Set TCP/UDP parameters 00225 if(mode == TCP) { 00226 if(socketCloseable) { 00227 Code code = sendBasicCommand("AT#DLEMODE=1,1", 1000); 00228 if(code != MTS_SUCCESS) { 00229 logWarning("Unable to set socket closeable [%d]", (int) code); 00230 } 00231 } 00232 sprintf(buffer, "AT#TCPPORT=1,%d", port); 00233 portCode = sendBasicCommand(buffer, 1000); 00234 addressCode = sendBasicCommand("AT#TCPSERV=1,\"" + address + "\"", 1000); 00235 } else { 00236 if(socketCloseable) { 00237 Code code = sendBasicCommand("AT#UDPDLEMODE=1", 1000); 00238 if(code != MTS_SUCCESS) { 00239 logWarning("Unable to set socket closeable [%d]", (int) code); 00240 } 00241 } 00242 sprintf(buffer, "AT#UDPPORT=%d", port); 00243 portCode = sendBasicCommand(buffer, 1000); 00244 addressCode = sendBasicCommand("AT#UDPSERV=\"" + address + "\"", 1000); 00245 } 00246 00247 if(portCode == MTS_SUCCESS) { 00248 host_port = port; 00249 } else { 00250 logError("Host port could not be set"); 00251 } 00252 00253 if(addressCode == MTS_SUCCESS) { 00254 host_address = address; 00255 } else { 00256 logError("Host address could not be set"); 00257 } 00258 00259 // Try and Connect 00260 std::string sMode; 00261 std::string sOpenSocketCmd; 00262 if(mode == TCP) { 00263 sOpenSocketCmd = "AT#OTCP=1"; 00264 sMode = "TCP"; 00265 } else { 00266 sOpenSocketCmd = "AT#OUDP"; 00267 sMode = "UDP"; 00268 } 00269 00270 string response = sendCommand(sOpenSocketCmd, 30000); 00271 if (response.find("Ok_Info_WaitingForData") != string::npos) { 00272 logInfo("Opened %s Socket [%s:%d]", sMode.c_str(), address.c_str(), port); 00273 socketOpened = true; 00274 socketMode = mode; 00275 } else { 00276 logWarning("Unable to open %s Socket [%s:%d]", sMode.c_str(), address.c_str(), port); 00277 socketOpened = false; 00278 } 00279 00280 return socketOpened; 00281 } 00282 00283 bool UIP::close(bool shutdown) 00284 { 00285 if(io == NULL) { 00286 logError("MTSBufferedIO not set"); 00287 return false; 00288 } 00289 00290 if(!socketOpened) { 00291 logWarning("Socket close() called, but socket was not open"); 00292 return true; 00293 } 00294 00295 if(!socketCloseable) { 00296 logError("Socket is not closeable"); 00297 return false; 00298 } 00299 00300 if(io->write(ETX, 1000) != 1) { 00301 logError("Timed out attempting to close socket"); 00302 return false; 00303 } 00304 00305 if (shutdown) { 00306 int counter = 0; 00307 char tmp[256]; 00308 do { 00309 if(socketOpened == false) { 00310 break; 00311 } 00312 read(tmp, 256, 1000); 00313 } while(counter++ < 10); 00314 00315 io->rxClear(); 00316 io->txClear(); 00317 } 00318 00319 socketOpened = false; 00320 return true; 00321 } 00322 00323 int UIP::read(char* data, int max, int timeout) 00324 { 00325 if(io == NULL) { 00326 logError("MTSBufferedIO not set"); 00327 return -1; 00328 } 00329 00330 //Check that nothing is in the rx buffer 00331 if(!socketOpened && !io->readable()) { 00332 logError("Socket is not open"); 00333 return -1; 00334 } 00335 00336 int bytesRead = 0; 00337 00338 if(timeout >= 0) { 00339 bytesRead = io->read(data, max, static_cast<unsigned int>(timeout)); 00340 } else { 00341 bytesRead = io->read(data, max); 00342 } 00343 00344 if(bytesRead > 0 && socketCloseable) { 00345 //Remove escape characters 00346 int index = 0; 00347 bool escapeFlag = false; 00348 for(int i = 0; i < bytesRead; i++) { 00349 if(data[i] == DLE || data[i] == ETX) { 00350 if(escapeFlag == true) { 00351 //This character has been escaped 00352 escapeFlag = false; 00353 } else if(data[bytesRead] == DLE) { 00354 //Found escape character 00355 escapeFlag = true; 00356 continue; 00357 } else { 00358 //ETX sent without escape -> Socket closed 00359 logInfo("Read ETX character without DLE escape. Socket closed"); 00360 socketOpened = false; 00361 continue; 00362 } 00363 } 00364 00365 if(index != i) { 00366 data[index] = data[i]; 00367 } 00368 index++; 00369 } 00370 bytesRead = index; 00371 } 00372 00373 //Scan for socket closed message 00374 for(size_t i = 0; i < bytesRead; i++) { 00375 if(data[i] == 'O') { 00376 if(strstr(&data[i], "Ok_Info_SocketClosed")) { 00377 logInfo("Found socket closed message. Socket closed"); 00378 //Close socket and Cut Off End of Message 00379 socketOpened = false; 00380 data[i] = '\0'; 00381 bytesRead = i; 00382 break; 00383 } 00384 } 00385 } 00386 return bytesRead; 00387 } 00388 00389 int UIP::write(const char* data, int length, int timeout) 00390 { 00391 if(io == NULL) { 00392 logError("MTSBufferedIO not set"); 00393 return -1; 00394 } 00395 00396 if(!socketOpened) { 00397 logError("Socket is not open"); 00398 return -1; 00399 } 00400 00401 //In order to avoid allocating another buffer, capture indices of 00402 //characters to escape during write 00403 int specialWritten = 0; 00404 std::vector<int> vSpecial; 00405 if(socketCloseable) { 00406 for(int i = 0; i < length; i++) { 00407 if(data[i] == ETX || data[i] == DLE) { 00408 //Push back index of special characters 00409 vSpecial.push_back(i); 00410 } 00411 } 00412 } 00413 00414 int bytesWritten = 0; 00415 if(timeout >= 0) { 00416 Timer tmr; 00417 tmr.start(); 00418 do { 00419 int available = io->writeable(); 00420 if (available > 0) { 00421 if(specialWritten < vSpecial.size()) { 00422 //Check if current index is at a special character 00423 if(bytesWritten == vSpecial[specialWritten]) { 00424 if(available < 2) { 00425 //Requires at least two bytes of space 00426 wait(0.05); 00427 continue; 00428 } 00429 //Ready to write special character 00430 if(io->write(DLE)) { 00431 specialWritten++; 00432 if(io->write(data[bytesWritten])) { 00433 bytesWritten++; 00434 } 00435 } else { 00436 //Unable to write escape character, try again next round 00437 wait(0.05); 00438 } 00439 } else { 00440 //We want to write all the way up to the next special character 00441 int relativeIndex = vSpecial[specialWritten] - bytesWritten; 00442 int size = mts_min(available, relativeIndex); 00443 bytesWritten += io->write(&data[bytesWritten], size); 00444 } 00445 } else { 00446 int size = mts_min(available, length - bytesWritten); 00447 bytesWritten += io->write(&data[bytesWritten], size); 00448 } 00449 } else { 00450 wait(0.05); 00451 } 00452 } while (tmr.read_ms() <= timeout && bytesWritten < length); 00453 } else { 00454 for(int i = 0; i < vSpecial.size(); i++) { 00455 //Write up to the special character, then write the special character 00456 int size = vSpecial[i] - bytesWritten; 00457 int currentWritten = io->write(&data[bytesWritten], size); 00458 bytesWritten += currentWritten; 00459 if(currentWritten != size) { 00460 //Failed to write up to the special character. 00461 return bytesWritten; 00462 } 00463 if(io->write(DLE) && io->write(data[bytesWritten])) { 00464 bytesWritten++; 00465 } else { 00466 //Failed to write the special character. 00467 return bytesWritten; 00468 } 00469 } 00470 00471 bytesWritten = io->write(&data[bytesWritten], length - bytesWritten); 00472 } 00473 00474 return bytesWritten; 00475 } 00476 00477 Code UIP::setApn(const std::string& apn) 00478 { 00479 if (type == MTSMC_H5_IP) { 00480 Code code = sendBasicCommand("AT#APNSERV=\"" + apn + "\"", 1000); 00481 if (code != MTS_SUCCESS) { 00482 return code; 00483 } 00484 this->apn = apn; 00485 return code; //This will return MTS_SUCCESS 00486 } else { 00487 logInfo("CDMA radios don't need an APN"); 00488 return MTS_SUCCESS; 00489 } 00490 } 00491 00492 void UIP::reset() 00493 { 00494 disconnect(); 00495 Code code = sendBasicCommand("AT#RESET=0", 10000); 00496 if(code != MTS_SUCCESS) { 00497 logError("Socket Modem did not accept RESET command\n\r"); 00498 } else { 00499 logWarning("Socket Modem is resetting, allow 30 seconds for it to come back\n\r"); 00500 } 00501 } 00502 00503 bool UIP::ping(const std::string& address) 00504 { 00505 char buffer[256] = {0}; 00506 Code code; 00507 00508 code = sendBasicCommand("AT#PINGREMOTE=\"" + address + "\"", 1000); 00509 if (code != MTS_SUCCESS) { 00510 return false; 00511 } 00512 00513 sprintf(buffer, "AT#PINGNUM=%d", 1); 00514 code = sendBasicCommand(buffer , 1000); 00515 if (code != MTS_SUCCESS) { 00516 return false; 00517 } 00518 00519 sprintf(buffer, "AT#PINGDELAY=%d", PINGDELAY); 00520 code = sendBasicCommand(buffer , 1000); 00521 if (code != MTS_SUCCESS) { 00522 return false; 00523 } 00524 00525 std::string response; 00526 for (int i = 0; i < PINGNUM; i++) { 00527 response = sendCommand("AT#PING", PINGDELAY * 2000); 00528 if (response.find("alive") != std::string::npos) { 00529 /* the "OK" that comes on a new line doesn't come right after this reply 00530 * wait a couple seconds to make sure we get it here, otherwise it could be read 00531 * as the response to the next AT command sent 00532 */ 00533 wait(2); 00534 return true; 00535 } 00536 } 00537 return false; 00538 }
Generated on Wed Jul 13 2022 08:05:41 by
1.7.2
