Cellular library for MTS Socket Modem Arduino Shield devices from Multi-Tech Systems
Dependents: mtsas mtsas mtsas mtsas
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 || type == MTQ_LVW3) ? 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 || type == MTQ_LVW3) ? 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 || type == MTQ_LVW3) ? 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 || type == MTQ_LVW3) ? 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 || type == MTQ_LVW3) ? 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 || type == MTQ_LVW3) ? 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 || type == MTQ_LAT3) { 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 if (type == MTQ_MAT1) { 00538 Code code = sendBasicCommand("AT+CGDCONT=1,\"IPV4V6\",\"" + apn + "\"", 1000); 00539 if (code != MTS_SUCCESS) { 00540 return code; 00541 } 00542 this->apn = apn; 00543 return code; 00544 } else if (type == MTQ_MVW1 || type == MTQ_LVW3) { 00545 logInfo("Radio does not need an APN"); 00546 return MTS_SUCCESS; 00547 } else { 00548 logInfo("CDMA radios do not need an APN"); 00549 return MTS_SUCCESS; 00550 } 00551 } 00552 00553 bool EasyIP::ping(const std::string& address) 00554 { 00555 char buffer[256] = {0}; 00556 std::vector<std::string> parts; 00557 int TTL=0; 00558 int Timeout=0; 00559 00560 //Format parameters for sending to radio 00561 sprintf(buffer, "AT#PING=%s,1,32,%d", address.c_str(), (PINGDELAY*10)); 00562 00563 for(int pngs=0; pngs<PINGNUM; pngs++) { 00564 std::string response = sendCommand(buffer, (PINGDELAY*2000)); //Send 1 ping 00565 if(response.empty() || response.find("ERROR") != std::string::npos) { 00566 continue; //Skip current loop if send command fails 00567 } 00568 parts = Text::split(response, "\r\n"); 00569 if(parts.size() < 2) { 00570 continue; 00571 } 00572 parts = Text::split(parts[1], ","); 00573 if(parts.size() < 4) { 00574 continue; 00575 } 00576 //Parse TTL and Timeout values 00577 Timeout = std::atoi(parts[2].c_str()); 00578 TTL = std::atoi(parts[3].c_str()); 00579 00580 if((Timeout < 600) && (TTL < 255)) { 00581 return true; 00582 } 00583 } 00584 return false; 00585 } 00586 00587 bool EasyIP::sendEscapeCommand() 00588 { 00589 //string Cellular::sendCommand(const std::string& command, unsigned int timeoutMillis, char esc) 00590 if(io == NULL) { 00591 logError("MTSBufferedIO not set"); 00592 return false; 00593 } 00594 if(!socketOpened) { 00595 logError("Socket is not open."); 00596 return false; 00597 } 00598 00599 if(!socketCloseable) { 00600 logError("Socket is not closeable"); 00601 return false; 00602 } 00603 00604 io->rxClear(); 00605 io->txClear(); 00606 00607 std::string result; 00608 unsigned int timeoutMillis = 10000; 00609 //Attempt to write command 00610 //Format for +++ command is 1 second wait, send +++, then another second wait 00611 wait(1.2); 00612 if(io->write("+++", 3, timeoutMillis) != 3) { 00613 //Failed to write command 00614 logError("failed to send command to radio within %d milliseconds", timeoutMillis); 00615 return false; 00616 } 00617 00618 Timer tmr; 00619 char tmp[256]; 00620 tmp[255] = 0; 00621 bool done = false; 00622 bool exitmode = false; 00623 tmr.start(); 00624 do { 00625 //Make a non-blocking read call by passing timeout of zero 00626 int size = io->read(tmp,255,0); //1 less than allocated (timeout is instant) 00627 if(size > 0) { 00628 result.append(tmp, size); 00629 } 00630 if(result.find("OK\r\n") != std::string::npos) { 00631 exitmode = true; 00632 done = true; 00633 } else if(result.find("NO CARRIER\r\n") != std::string::npos) { 00634 socketOpened = false; 00635 exitmode = true; 00636 done = true; 00637 } else if(result.find("ERROR") != std::string::npos) { 00638 exitmode = false; 00639 done = true; 00640 } 00641 if(tmr.read_ms() >= timeoutMillis) { 00642 logDebug("Escape sequence [+++] timed out after %d milliseconds", timeoutMillis); 00643 exitmode = true; 00644 done = true; 00645 } 00646 } while (!done); 00647 00648 wait(0.1); //Without a slight wait time after receiving OK, radio would 00649 //fail to correctly receive and respond to the next AT command 00650 return exitmode; 00651 } 00652 00653 bool EasyIP::socketCheck() { 00654 enum SocketStatus {SOCKETCLOSED = 0, SOCKETACTIVEDATA = 1, SOCKETSUSPEND = 2, SOCKETSUSPENDDATA = 3, SOCKETLISTEN = 4, SOCKETINCOMING = 5, ERROR = 9}; 00655 bool status = false; 00656 int socketInfo = ERROR; 00657 std::vector<std::string> params; 00658 00659 //Goes from data mode to command mode 00660 if(sendEscapeCommand()) { 00661 std::string reply = sendCommand("AT#SS=1", 2000); 00662 if(reply.find("OK") != std::string::npos) { 00663 //Found valid response 00664 params = Text::split(reply, "\r\n"); 00665 params = Text::split(params[1], ","); 00666 socketInfo = atoi(params[1].c_str()); 00667 } else { 00668 logError("Could not determine socket status[%d]",socketInfo); 00669 socketInfo = ERROR; 00670 } 00671 } else { 00672 status = false; //Return value of socketOpened when checking 00673 } 00674 00675 //Check socket status query 00676 if(socketInfo == SOCKETINCOMING || socketInfo == SOCKETACTIVEDATA || socketInfo == SOCKETSUSPEND || socketInfo == SOCKETSUSPENDDATA || socketInfo == SOCKETLISTEN) { //Socket opened responses 00677 status = true; 00678 } else if(socketInfo == SOCKETCLOSED || socketInfo == SOCKETINCOMING) { 00679 status = false; 00680 } else { 00681 logError("Could not determine socket status[%d]",socketInfo); 00682 status = false; 00683 } 00684 00685 //Reconnect to active socket if able 00686 if(status) { 00687 std::string reconnect = sendCommand("AT#SO=1", 2000); 00688 if(reconnect.find("CONNECT") != std::string::npos || reconnect.find("OK") != std::string::npos) { 00689 } else { 00690 logError("Failed to resume socket connection"); 00691 } 00692 } 00693 return status; 00694 } 00695 00696 bool EasyIP::GPSenable() { 00697 //The HE910 returns an ERROR if you try to enable when it is already enabled. 00698 // That's why we need to check if GPS is enabled before enabling it. 00699 if(GPSenabled()) { 00700 logInfo("GPS was already enabled."); 00701 return true; 00702 } 00703 //The LE910-NAG requires AT$GPSSLSR=2,3 to enable GPS but can use AT$GPSP=0 to disable it. 00704 if(type == MTSMC_LAT1){ 00705 Code code = sendBasicCommand("AT$GPSSLSR=2,3", 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 } else { 00715 Code code = sendBasicCommand("AT$GPSP=1", 2000); 00716 if (code == MTS_SUCCESS) { 00717 gpsEnabled = true; 00718 logInfo("GPS enabled."); 00719 return true; 00720 } else { 00721 logError("Enable GPS failed."); 00722 return false; 00723 } 00724 } 00725 } 00726 00727 bool EasyIP::GPSdisable() { 00728 // The HE910 returns an ERROR if you try to disable when it is already disabled. 00729 // That's why we need to check if GPS is disabled before disabling it. 00730 if(!GPSenabled()) { 00731 logInfo("GPS was already disabled."); 00732 return true; 00733 } 00734 Code code = sendBasicCommand("AT$GPSP=0", 2000); 00735 if (code == MTS_SUCCESS) { 00736 gpsEnabled = false; 00737 logInfo("GPS disabled."); 00738 return true; 00739 } else { 00740 logError("Disable GPS failed."); 00741 return false; 00742 } 00743 } 00744 00745 bool EasyIP::GPSenabled() { 00746 std::string reply = sendCommand("AT$GPSP?", 1000); 00747 if(reply.find("1") != std::string::npos) { 00748 gpsEnabled = true; 00749 return true; 00750 } else { 00751 gpsEnabled = false; 00752 return false; 00753 } 00754 } 00755 00756 Cellular::gpsData EasyIP::GPSgetPosition(){ 00757 enum gpsFields{time, latitude, longitude, hdop, altitude, fix, cog, kmhr, knots, date, satellites, numOfFields }; 00758 Cellular::gpsData position; 00759 if(!gpsEnabled) { 00760 logError("GPS is disabled... can't get position."); 00761 position.success = false; 00762 return position; 00763 } 00764 // Get the position information in string format. 00765 std::string gps = sendCommand("AT$GPSACP?", 1000); 00766 if(gps.find("OK") != std::string::npos) { 00767 position.success = true; 00768 // Remove echoed AT$GPSACP and leading non position characters. 00769 gps.erase(0,22); 00770 // Remove trailing CR/LF, CR/LF, OK and CR/LF. 00771 gps.erase(gps.end()-8, gps.end()); 00772 // Split remaining data and load into corresponding structure fields. 00773 std::vector<std::string> gpsParts = Text::split(gps, ','); 00774 // Check size. 00775 if(gpsParts.size() != numOfFields) { 00776 logError("Expected %d fields but there are %d fields in \"%s\"", numOfFields, gpsParts.size(), gps.c_str()); 00777 position.success = false; 00778 return position; 00779 } 00780 position.latitude = gpsParts[latitude]; 00781 position.longitude = gpsParts[longitude]; 00782 position.hdop = atof(gpsParts[hdop].c_str()); 00783 position.altitude = atof(gpsParts[altitude].c_str()); 00784 position.fix = atoi(gpsParts[fix].c_str()); 00785 position.cog = gpsParts[cog]; 00786 position.kmhr = atof(gpsParts[kmhr].c_str()); 00787 position.knots = atof(gpsParts[knots].c_str()); 00788 position.satellites = atoi(gpsParts[satellites].c_str()); 00789 if((gpsParts[date].size() == 6) && (gpsParts[time].size() == 10)) { 00790 position.timestamp = gpsParts[date].substr(4,2) + "/" + gpsParts[date].substr(2,2) + 00791 "/" + gpsParts[date].substr(0,2) + ", " + gpsParts[time].substr(0,2) + 00792 ":" + gpsParts[time].substr(2,2) + ":" + gpsParts[time].substr(4,6); 00793 } 00794 return position; 00795 } else { 00796 position.success = false; 00797 logError("NO \"OK\" returned from GPS position command \"AT$GPSACP?\"."); 00798 return position; 00799 } 00800 } 00801 00802 bool EasyIP::GPSgotFix() { 00803 if(!gpsEnabled) { 00804 logError("GPS is disabled... can't get fix."); 00805 return false; 00806 } 00807 Cellular::gpsData position = GPSgetPosition(); 00808 if(!position.success) { 00809 return false; 00810 } else if(position.fix < 2){ 00811 logWarning("No GPS fix. GPS fix can take a few minutes. Check GPS antenna attachment and placement."); 00812 return false; 00813 } else { 00814 logInfo("Got GPS fix."); 00815 return true; 00816 } 00817 }
Generated on Tue Jul 12 2022 21:59:41 by 1.7.2