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
EasyIP.cpp
00001 #include "mbed.h" 00002 #include "EasyIP.h" 00003 #include "MTSText.h" 00004 #include "MTSLog.h" 00005 #include "CellUtils.h" 00006 #include <string> 00007 00008 using namespace mts; 00009 00010 EasyIP::EasyIP(Radio type) 00011 { 00012 this->type = type; 00013 io = NULL; 00014 dcd = NULL; 00015 dtr = NULL; 00016 resetLine = NULL; 00017 echoMode = true; 00018 gpsEnabled = false; 00019 pppConnected = false; 00020 socketMode = TCP; 00021 socketOpened = false; 00022 socketCloseable = true; 00023 local_port = 0; 00024 local_address = ""; 00025 host_port = 0; 00026 } 00027 00028 EasyIP::~EasyIP() 00029 { 00030 if (dtr != NULL) { 00031 dtr->write(1); 00032 } 00033 00034 delete dcd; 00035 delete dtr; 00036 delete resetLine; 00037 } 00038 00039 //Initializes the MTS IO Buffer 00040 bool EasyIP::init(MTSBufferedIO* io) 00041 { 00042 char buf[128]; 00043 00044 if (! Cellular::init(io)) { 00045 return false; 00046 } 00047 00048 logDebug("radio type: %s", Cellular::getRadioNames(type).c_str()); 00049 //Turns on the HW flow control 00050 if(sendBasicCommand("AT+IFC=2,2", 2000) != MTS_SUCCESS) { 00051 logWarning("Failed to enable serial flow control"); 00052 } 00053 // Shorten data sending timeout from 5s to 100ms 00054 // Some servers won't handle a timeout that long 00055 snprintf(buf, sizeof(buf), "AT#SCFG=1,%d,300,90,600,1", type == MTSMC_LVW2 ? 3 : 1); 00056 if (sendBasicCommand(string(buf), 2000) != MTS_SUCCESS) { 00057 logWarning("Failed to reconfigure socket timeout parameters"); 00058 } 00059 return true; 00060 } 00061 00062 bool EasyIP::connect() 00063 { 00064 //Check if APN is not set, if it is not, connect will not work. 00065 if (type == MTSMC_H5_IP || type == MTSMC_H5 || type == MTSMC_G3 || type == MTSMC_LAT1 || type == MTSMC_LEU1) { 00066 if(apn.size() == 0) { 00067 logDebug("APN is not set"); 00068 return false; 00069 } 00070 } 00071 00072 //Check if socket is open 00073 if(socketOpened) { 00074 return true; 00075 } 00076 00077 //Check if already connected 00078 if(isConnected()) { 00079 return true; 00080 } 00081 00082 Timer tmr; 00083 //Check Registration: AT+CREG? == 0,1 00084 tmr.start(); 00085 do { 00086 Registration registration = getRegistration(); 00087 if(registration != REGISTERED && registration != ROAMING) { 00088 logTrace("Not Registered [%d] ... waiting", (int)registration); 00089 wait(1); 00090 } else { 00091 break; 00092 } 00093 } while(tmr.read() < 30); 00094 00095 //Check RSSI: AT+CSQ 00096 tmr.reset(); 00097 do { 00098 int rssi = getSignalStrength(); 00099 logDebug("Signal strength: %d", rssi); 00100 if(rssi == 99 || rssi == -1) { 00101 logTrace("No Signal ... waiting"); 00102 wait(1); 00103 } else { 00104 break; 00105 } 00106 } while(tmr.read() < 30); 00107 00108 //Make PPP connection 00109 if (type == MTSMC_H5 || type == MTSMC_G3 || type == MTSMC_LAT1 || type == MTSMC_LEU1) { 00110 logDebug("Making PPP Connection Attempt. APN[%s]", apn.c_str()); 00111 } else { 00112 logDebug("Making PPP Connection Attempt"); 00113 } 00114 char buf[64]; 00115 snprintf(buf, sizeof(buf), "AT#SGACT=%d,1", type == MTSMC_LVW2 ? 3 : 1); 00116 std::string pppResult = sendCommand(string(buf), 15000); 00117 std::vector<std::string> parts; 00118 if(pppResult.find("OK") != std::string::npos) { 00119 parts = Text::split(pppResult, "\r\n"); 00120 if(parts.size() >= 2) { 00121 parts = Text::split(parts[1], " "); 00122 if (parts.size() >= 2) { 00123 local_address = parts[1]; 00124 } 00125 } 00126 logInfo("PPP Connection Established: IP[%s]", local_address.c_str()); 00127 pppConnected = true; 00128 00129 } else { 00130 snprintf(buf, sizeof(buf), "%d,1", type == MTSMC_LVW2 ? 3 : 1); 00131 pppResult = sendCommand("AT#SGACT?", 2000); 00132 if(pppResult.find(string(buf)) != std::string::npos) { 00133 logDebug("Radio is already connected"); 00134 pppConnected = true; 00135 } else { 00136 logError("PPP connection attempt failed"); 00137 pppConnected = false; 00138 } 00139 } 00140 00141 return pppConnected; 00142 } 00143 00144 void EasyIP::disconnect() 00145 { 00146 //AT#SGACT=1,0: Close PPP connection 00147 logDebug("Closing PPP Connection"); 00148 std::string result; 00149 Timer tmr; 00150 00151 if(socketOpened) { 00152 close(true); 00153 } 00154 00155 //Sends AT#SGACT=1,0 command 00156 for (int y = 0; y < 5; y++) { 00157 char buf[64]; 00158 snprintf(buf, sizeof(buf), "AT#SGACT=%d,0", type == MTSMC_LVW2 ? 3 : 1); 00159 Code code = sendBasicCommand(string(buf), 1000); 00160 if (code == MTS_SUCCESS) { 00161 logDebug("Successfully closed PPP Connection"); 00162 break; 00163 } 00164 } 00165 00166 /* Ensure PPP link is down, else ping commands will put radio in unknown state 00167 * (Link is not immediate in disconnection, even though OK is returned) 00168 */ 00169 tmr.start(); 00170 while(tmr.read() < 30) { 00171 char buf[16]; 00172 snprintf(buf, sizeof(buf), "%d,0", type == MTSMC_LVW2 ? 3 : 1); 00173 result = sendCommand("AT#SGACT?", 1000); 00174 if(result.find(string(buf)) != std::string::npos) { 00175 break; 00176 } else if(result.find("ERROR") != std::string::npos) { 00177 break; 00178 } else { 00179 wait(1); 00180 } 00181 } 00182 00183 pppConnected = false; 00184 return; 00185 } 00186 00187 bool EasyIP::isConnected() 00188 { 00189 enum RadioState {IDLE, CONNECTING, CONNECTED, DISCONNECTED}; 00190 //state flags for various connection components 00191 bool signal = false, regist = false, active = false; 00192 char buf[16]; 00193 00194 //1) Check if APN was set if we're on an HSPA radio 00195 if (type == MTSMC_H5_IP || type == MTSMC_H5 || type == MTSMC_G3 || type == MTSMC_LAT1 || type == MTSMC_LEU1) { 00196 if(apn.size() == 0) { 00197 logDebug("APN is not set"); 00198 return false; 00199 } 00200 } 00201 00202 //2) Check that we do not have a live connection up 00203 if (socketOpened) { 00204 logDebug("Socket is opened"); 00205 return true; 00206 } 00207 00208 //3) Query the radio 00209 int rssi = getSignalStrength(); 00210 if (rssi == 99 || rssi == -1) { 00211 //Signal strength is nonexistent 00212 signal = false; 00213 } else { 00214 signal = true; 00215 } 00216 00217 Registration creg = getRegistration(); 00218 if (creg == REGISTERED) { 00219 regist = true; 00220 } else { 00221 regist = false; 00222 } 00223 00224 string reply = sendCommand("AT#SGACT?", 1000); 00225 snprintf(buf, sizeof(buf), "%d,1", type == MTSMC_LVW2 ? 3 : 1); 00226 if (reply.find(string(buf)) != std::string::npos) { 00227 active = true; 00228 } else { 00229 active = false; 00230 } 00231 00232 //Updates pppConnected to reflect current connection state 00233 RadioState state; 00234 bool ppp = pppConnected; 00235 if (signal && regist && active) { 00236 state = CONNECTED; 00237 pppConnected = true; 00238 } else if (signal && !regist && !active) { 00239 state = IDLE; 00240 pppConnected = false; 00241 } else if (active) { 00242 state = CONNECTING; 00243 } else { 00244 state = DISCONNECTED; 00245 pppConnected = false; 00246 } 00247 00248 //Compares current connection state with previous pppConnected variable state 00249 if (!ppp && state == CONNECTED) { 00250 logWarning("Internal PPP state tracking differs from radio (DISCONNECTED:CONNECTED)"); 00251 } else if (ppp && state != CONNECTED) { 00252 string stateStr; 00253 switch (state) { 00254 case IDLE: 00255 stateStr = "IDLE"; 00256 break; 00257 case CONNECTING: 00258 stateStr = "CONNECTING"; 00259 break; 00260 case DISCONNECTED: 00261 stateStr = "DISCONNECTED"; 00262 break; 00263 case CONNECTED: 00264 stateStr = "CONNECTED"; 00265 break; 00266 default: 00267 stateStr = "UKNOWN"; 00268 break; 00269 } 00270 logWarning("Internal PPP state tracking differs from radio (CONNECTED:%s)", stateStr.c_str()); 00271 } 00272 00273 return pppConnected; 00274 } 00275 00276 void EasyIP::reset() 00277 { 00278 disconnect(); 00279 00280 if(sendBasicCommand("AT#REBOOT", 10000) != MTS_SUCCESS) { 00281 logError("Socket Modem did not accept RESET command"); 00282 } else { 00283 logWarning("Socket Modem is resetting, allow 30 seconds for it to come back"); 00284 return; 00285 } 00286 } 00287 00288 //Opens socket connection 00289 bool EasyIP::open(const std::string& address, unsigned int port, Mode mode) 00290 { 00291 char sOpenSocketCmd[256] = {0}; //String for AT command 00292 std::string sMode = ""; 00293 int typeSocket = 0; 00294 int closeType = 0; 00295 00296 //1) Check that we do not have a live connection up 00297 if(socketOpened) { 00298 //Check that the address, port, and mode match 00299 if(host_address != address || host_port != port || socketMode != mode) { 00300 if(socketMode == TCP) { 00301 logError("TCP socket already opened [%s:%d]", host_address.c_str(), host_port); 00302 } else { 00303 logError("UDP socket already opened [%s:%d]", host_address.c_str(), host_port); 00304 } 00305 return false; 00306 } 00307 00308 logDebug("Socket already opened"); 00309 return true; 00310 } 00311 00312 //2) Check Parameters 00313 if(port > 65535) { 00314 logError("port out of range (0-65535)"); 00315 return false; 00316 } 00317 00318 if(type == MTSMC_EV3 || type == MTSMC_LAT1 || type == MTSMC_LEU1 || type == MTSMC_LVW2) { 00319 if(!local_port) { 00320 logDebug("Local port set to 1, port 0 not supported for %s", getRadioNames(type).c_str()); 00321 local_port = 1; 00322 } 00323 } 00324 00325 //3) Check PPP connection 00326 if(!isConnected()) { 00327 logError("PPP not established. Attempting to connect"); 00328 if(!connect()) { 00329 logError("PPP connection failed"); 00330 return false; 00331 } else { 00332 logDebug("PPP connection established"); 00333 } 00334 } 00335 00336 //4) Set escape sequence to not be transmitted through socket 00337 if(sendBasicCommand("AT#SKIPESC=1", 2000) != MTS_SUCCESS) { 00338 logWarning("Failed to disable escape sequence transmission on data mode suspension"); 00339 } 00340 00341 if(mode == TCP) { 00342 typeSocket = 0; 00343 sMode = "TCP"; 00344 } else { 00345 typeSocket = 1; 00346 sMode = "UDP"; 00347 } 00348 00349 if(socketCloseable) { 00350 closeType = 0; 00351 } else { 00352 closeType = 255; 00353 } 00354 00355 //5) Open Socket 00356 sprintf(sOpenSocketCmd, "AT#SD=1,%d,%d,\"%s\",%d,%d,0", typeSocket, port, address.c_str(), closeType, local_port); 00357 std::string response = sendCommand(sOpenSocketCmd, 60000); 00358 00359 if(response.find("CONNECT") != std::string::npos) { 00360 host_address = address; 00361 host_port = port; 00362 00363 logInfo("Opened %s Socket [%s:%d]", sMode.c_str(), address.c_str(), port); 00364 socketOpened = true; 00365 socketMode = mode; 00366 } else { 00367 logWarning("Unable to open %s Socket [%s:%d]", sMode.c_str(), address.c_str(), port); 00368 socketOpened = false; 00369 } 00370 00371 return socketOpened; 00372 } 00373 00374 //Closes socket connection 00375 bool EasyIP::close(bool shutdown) 00376 { 00377 00378 if(io == NULL) { 00379 logError("MTSBufferedIO not set"); 00380 return false; 00381 } 00382 00383 if(!socketOpened) { 00384 logWarning("Socket close() called, but socket was not open"); 00385 return true; 00386 } 00387 00388 if(!socketCloseable) { 00389 logError("Socket is not closeable"); 00390 return false; 00391 } 00392 00393 if(!sendEscapeCommand()) { 00394 logError("Failed to exit online mode"); 00395 return false; 00396 } else { 00397 socketOpened = false; 00398 } 00399 00400 if (sendBasicCommand("AT#SH=1", 2000) != MTS_SUCCESS) { 00401 logDebug("Failed to close socket connection"); 00402 } 00403 00404 //Clear receive buffer 00405 if (shutdown) { 00406 int counter = 0; 00407 char tmp[256]; 00408 do { 00409 if(socketOpened == false) { 00410 break; 00411 } 00412 read(tmp, 256, 1000); 00413 } while(counter++ < 10); 00414 00415 io->rxClear(); 00416 io->txClear(); 00417 } 00418 00419 return !socketOpened; 00420 } 00421 00422 //Read from socket 00423 int EasyIP::read(char* data, int max, int timeout) 00424 { 00425 if(io == NULL) { 00426 logError("MTSBufferedIO not set"); 00427 return -1; 00428 } 00429 00430 //Check that nothing is in the rx buffer 00431 if(!socketOpened && !io->readable()) { 00432 logError("Socket is not open"); 00433 return -1; 00434 } 00435 00436 int bytesRead = 0; 00437 00438 if(timeout >= 0) { 00439 bytesRead = io->read(data, max, static_cast<unsigned int>(timeout)); 00440 } else { 00441 bytesRead = io->read(data, max); 00442 } 00443 00444 //Scan for socket closed message 00445 if(bytesRead > 0 && socketCloseable) { 00446 for(int i = 0; i < bytesRead; i++) { 00447 if(data[i] == 'N') { 00448 if(strstr(&data[i], "NO CARRIER")) { 00449 logTrace("Found socket closed message. Checking validity"); 00450 //Close socket and Cut Off End of Message 00451 socketOpened = socketCheck(); //Verifies legitimacy of socket disconnect 00452 if(socketOpened) { 00453 logDebug("Socket still open"); 00454 continue; 00455 } else { 00456 logDebug("Socket closed"); 00457 data[i] = '\0'; 00458 bytesRead = i; 00459 break; 00460 } 00461 } 00462 } 00463 } 00464 } 00465 return bytesRead; 00466 } 00467 00468 //Write to socket 00469 int EasyIP::write(const char* data, int length, int timeout) 00470 { 00471 if(io == NULL) { 00472 logError("MTSBufferedIO not set"); 00473 return -1; 00474 } 00475 00476 if(!socketOpened) { 00477 logError("Socket is not open"); 00478 return -1; 00479 } 00480 00481 int bytesWritten = 0; 00482 int size = length; 00483 int failedWrites = 0; 00484 if(timeout >= 0) { 00485 Timer tmr; 00486 tmr.start(); 00487 do { 00488 int available = io->writeable(); 00489 if (available > 0) { 00490 size = mts_min(available, length - bytesWritten); 00491 bytesWritten += io->write(&data[bytesWritten], size); 00492 } else { 00493 wait(0.05); 00494 } 00495 } while (tmr.read_ms() <= timeout && bytesWritten < length); 00496 } else { 00497 //If timeout is -1: 00498 do { 00499 int available = io->writeable(); 00500 if(available > 0) { 00501 size = mts_min(available, length - bytesWritten); 00502 int currentWritten = io->write(&data[bytesWritten], size); 00503 bytesWritten += currentWritten; 00504 if(!currentWritten) { 00505 failedWrites++; 00506 } 00507 if(failedWrites > 10) { 00508 logError("Couldn't write any characters"); 00509 return bytesWritten; 00510 } 00511 } else { 00512 wait(0.05); 00513 } 00514 } while (bytesWritten < length); 00515 } 00516 return bytesWritten; 00517 } 00518 00519 Code EasyIP::setApn(const std::string& apn) 00520 { 00521 if (type == MTSMC_H5 || type == MTSMC_G3) { 00522 //CGDCONT has options: IP,PPP,IPv6 00523 Code code = sendBasicCommand("AT+CGDCONT=1,IP," + apn, 1000); 00524 if (code != MTS_SUCCESS) { 00525 return code; 00526 } 00527 this->apn = apn; 00528 return code; 00529 } else if (type == MTSMC_LAT1 || type == MTSMC_LEU1) { 00530 //CGDCONT has options: IP,PPP,IPv6 00531 Code code = sendBasicCommand("AT+CGDCONT=1,\"IP\",\"" + apn + "\"", 1000); 00532 if (code != MTS_SUCCESS) { 00533 return code; 00534 } 00535 this->apn = apn; 00536 return code; 00537 } else { 00538 logInfo("CDMA radios don't need an APN"); 00539 return MTS_SUCCESS; 00540 } 00541 } 00542 00543 bool EasyIP::ping(const std::string& address) 00544 { 00545 char buffer[256] = {0}; 00546 std::vector<std::string> parts; 00547 int TTL=0; 00548 int Timeout=0; 00549 00550 //Format parameters for sending to radio 00551 sprintf(buffer, "AT#PING=%s,1,32,%d", address.c_str(), (PINGDELAY*10)); 00552 00553 for(int pngs=0; pngs<PINGNUM; pngs++) { 00554 std::string response = sendCommand(buffer, (PINGDELAY*2000)); //Send 1 ping 00555 if(response.empty() || response.find("ERROR") != std::string::npos) { 00556 continue; //Skip current loop if send command fails 00557 } 00558 parts = Text::split(response, "\r\n"); 00559 if(parts.size() < 2) { 00560 continue; 00561 } 00562 parts = Text::split(parts[1], ","); 00563 if(parts.size() < 4) { 00564 continue; 00565 } 00566 //Parse TTL and Timeout values 00567 Timeout = std::atoi(parts[2].c_str()); 00568 TTL = std::atoi(parts[3].c_str()); 00569 00570 if((Timeout < 600) && (TTL < 255)) { 00571 return true; 00572 } 00573 } 00574 return false; 00575 } 00576 00577 bool EasyIP::sendEscapeCommand() 00578 { 00579 //string Cellular::sendCommand(const std::string& command, unsigned int timeoutMillis, char esc) 00580 if(io == NULL) { 00581 logError("MTSBufferedIO not set"); 00582 return false; 00583 } 00584 if(!socketOpened) { 00585 logError("Socket is not open."); 00586 return false; 00587 } 00588 00589 if(!socketCloseable) { 00590 logError("Socket is not closeable"); 00591 return false; 00592 } 00593 00594 io->rxClear(); 00595 io->txClear(); 00596 00597 std::string result; 00598 unsigned int timeoutMillis = 10000; 00599 //Attempt to write command 00600 //Format for +++ command is 1 second wait, send +++, then another second wait 00601 wait(1.2); 00602 if(io->write("+++", 3, timeoutMillis) != 3) { 00603 //Failed to write command 00604 logError("failed to send command to radio within %d milliseconds", timeoutMillis); 00605 return false; 00606 } 00607 00608 Timer tmr; 00609 char tmp[256]; 00610 tmp[255] = 0; 00611 bool done = false; 00612 bool exitmode = false; 00613 tmr.start(); 00614 do { 00615 //Make a non-blocking read call by passing timeout of zero 00616 int size = io->read(tmp,255,0); //1 less than allocated (timeout is instant) 00617 if(size > 0) { 00618 result.append(tmp, size); 00619 } 00620 if(result.find("OK\r\n") != std::string::npos) { 00621 exitmode = true; 00622 done = true; 00623 } else if(result.find("NO CARRIER\r\n") != std::string::npos) { 00624 socketOpened = false; 00625 exitmode = true; 00626 done = true; 00627 } else if(result.find("ERROR") != std::string::npos) { 00628 exitmode = false; 00629 done = true; 00630 } 00631 if(tmr.read_ms() >= timeoutMillis) { 00632 logDebug("Escape sequence [+++] timed out after %d milliseconds", timeoutMillis); 00633 exitmode = true; 00634 done = true; 00635 } 00636 } while (!done); 00637 00638 wait(0.1); //Without a slight wait time after receiving OK, radio would 00639 //fail to correctly receive and respond to the next AT command 00640 return exitmode; 00641 } 00642 00643 bool EasyIP::socketCheck() { 00644 enum SocketStatus {SOCKETCLOSED = 0, SOCKETACTIVEDATA = 1, SOCKETSUSPEND = 2, SOCKETSUSPENDDATA = 3, SOCKETLISTEN = 4, SOCKETINCOMING = 5, ERROR = 9}; 00645 bool status = false; 00646 int socketInfo = ERROR; 00647 std::vector<std::string> params; 00648 00649 //Goes from data mode to command mode 00650 if(sendEscapeCommand()) { 00651 std::string reply = sendCommand("AT#SS=1", 2000); 00652 if(reply.find("OK") != std::string::npos) { 00653 //Found valid response 00654 params = Text::split(reply, "\r\n"); 00655 params = Text::split(params[1], ","); 00656 socketInfo = atoi(params[1].c_str()); 00657 } else { 00658 logError("Could not determine socket status[%d]",socketInfo); 00659 socketInfo = ERROR; 00660 } 00661 } else { 00662 status = false; //Return value of socketOpened when checking 00663 } 00664 00665 //Check socket status query 00666 if(socketInfo == SOCKETINCOMING || socketInfo == SOCKETACTIVEDATA || socketInfo == SOCKETSUSPEND || socketInfo == SOCKETSUSPENDDATA || socketInfo == SOCKETLISTEN) { //Socket opened responses 00667 status = true; 00668 } else if(socketInfo == SOCKETCLOSED || socketInfo == SOCKETINCOMING) { 00669 status = false; 00670 } else { 00671 logError("Could not determine socket status[%d]",socketInfo); 00672 status = false; 00673 } 00674 00675 //Reconnect to active socket if able 00676 if(status) { 00677 std::string reconnect = sendCommand("AT#SO=1", 2000); 00678 if(reconnect.find("CONNECT") != std::string::npos || reconnect.find("OK") != std::string::npos) { 00679 } else { 00680 logError("Failed to resume socket connection"); 00681 } 00682 } 00683 return status; 00684 } 00685 00686 bool EasyIP::GPSenable() { 00687 //The HE910 returns an ERROR if you try to enable when it is already enabled. 00688 // That's why we need to check if GPS is enabled before enabling it. 00689 if(GPSenabled()) { 00690 logInfo("GPS was already enabled."); 00691 return true; 00692 } 00693 //The LE910-NAG requires AT$GPSSLSR=2,3 to enable GPS but can use AT$GPSP=0 to disable it. 00694 if(type == MTSMC_LAT1){ 00695 Code code = sendBasicCommand("AT$GPSSLSR=2,3", 2000); 00696 if (code == MTS_SUCCESS) { 00697 gpsEnabled = true; 00698 logInfo("GPS enabled."); 00699 return true; 00700 } else { 00701 logError("Enable GPS failed!"); 00702 return false; 00703 } 00704 } else { 00705 Code code = sendBasicCommand("AT$GPSP=1", 2000); 00706 if (code == MTS_SUCCESS) { 00707 gpsEnabled = true; 00708 logInfo("GPS enabled."); 00709 return true; 00710 } else { 00711 logError("Enable GPS failed."); 00712 return false; 00713 } 00714 } 00715 } 00716 00717 bool EasyIP::GPSdisable() { 00718 // The HE910 returns an ERROR if you try to disable when it is already disabled. 00719 // That's why we need to check if GPS is disabled before disabling it. 00720 if(!GPSenabled()) { 00721 logInfo("GPS was already disabled."); 00722 return true; 00723 } 00724 Code code = sendBasicCommand("AT$GPSP=0", 2000); 00725 if (code == MTS_SUCCESS) { 00726 gpsEnabled = false; 00727 logInfo("GPS disabled."); 00728 return true; 00729 } else { 00730 logError("Disable GPS failed."); 00731 return false; 00732 } 00733 } 00734 00735 bool EasyIP::GPSenabled() { 00736 std::string reply = sendCommand("AT$GPSP?", 1000); 00737 if(reply.find("1") != std::string::npos) { 00738 gpsEnabled = true; 00739 return true; 00740 } else { 00741 gpsEnabled = false; 00742 return false; 00743 } 00744 } 00745 00746 Cellular::gpsData EasyIP::GPSgetPosition(){ 00747 enum gpsFields{time, latitude, longitude, hdop, altitude, fix, cog, kmhr, knots, date, satellites, numOfFields }; 00748 Cellular::gpsData position; 00749 if(!gpsEnabled) { 00750 logError("GPS is disabled... can't get position."); 00751 position.success = false; 00752 return position; 00753 } 00754 // Get the position information in string format. 00755 std::string gps = sendCommand("AT$GPSACP?", 1000); 00756 if(gps.find("OK") != std::string::npos) { 00757 position.success = true; 00758 // Remove echoed AT$GPSACP and leading non position characters. 00759 gps.erase(0,22); 00760 // Remove trailing CR/LF, CR/LF, OK and CR/LF. 00761 gps.erase(gps.end()-8, gps.end()); 00762 // Split remaining data and load into corresponding structure fields. 00763 std::vector<std::string> gpsParts = Text::split(gps, ','); 00764 // Check size. 00765 if(gpsParts.size() != numOfFields) { 00766 logError("Expected %d fields but there are %d fields in \"%s\"", numOfFields, gpsParts.size(), gps.c_str()); 00767 position.success = false; 00768 return position; 00769 } 00770 position.latitude = gpsParts[latitude]; 00771 position.longitude = gpsParts[longitude]; 00772 position.hdop = atof(gpsParts[hdop].c_str()); 00773 position.altitude = atof(gpsParts[altitude].c_str()); 00774 position.fix = atoi(gpsParts[fix].c_str()); 00775 position.cog = gpsParts[cog]; 00776 position.kmhr = atof(gpsParts[kmhr].c_str()); 00777 position.knots = atof(gpsParts[knots].c_str()); 00778 position.satellites = atoi(gpsParts[satellites].c_str()); 00779 if((gpsParts[date].size() == 6) && (gpsParts[time].size() == 10)) { 00780 position.timestamp = gpsParts[date].substr(4,2) + "/" + gpsParts[date].substr(2,2) + 00781 "/" + gpsParts[date].substr(0,2) + ", " + gpsParts[time].substr(0,2) + 00782 ":" + gpsParts[time].substr(2,2) + ":" + gpsParts[time].substr(4,6); 00783 } 00784 return position; 00785 } else { 00786 position.success = false; 00787 logError("NO \"OK\" returned from GPS position command \"AT$GPSACP?\"."); 00788 return position; 00789 } 00790 } 00791 00792 bool EasyIP::GPSgotFix() { 00793 if(!gpsEnabled) { 00794 logError("GPS is disabled... can't get fix."); 00795 return false; 00796 } 00797 Cellular::gpsData position = GPSgetPosition(); 00798 if(!position.success) { 00799 return false; 00800 } else if(position.fix < 2){ 00801 logWarning("No GPS fix. GPS fix can take a few minutes. Check GPS antenna attachment and placement."); 00802 return false; 00803 } else { 00804 logInfo("Got GPS fix."); 00805 return true; 00806 } 00807 }
Generated on Wed Jul 13 2022 08:05:41 by
1.7.2
