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
Diff: Cellular/EasyIP.cpp
- Revision:
- 52:2cb58398a4f9
- Parent:
- 51:ffc556ba33f7
- Child:
- 54:a6c738bfc391
diff -r ffc556ba33f7 -r 2cb58398a4f9 Cellular/EasyIP.cpp --- a/Cellular/EasyIP.cpp Tue Aug 05 18:35:22 2014 +0000 +++ b/Cellular/EasyIP.cpp Mon Aug 11 16:03:19 2014 +0000 @@ -6,8 +6,6 @@ using namespace mts; - - EasyIP::EasyIP(Radio type) { this->type = type; @@ -46,7 +44,7 @@ logDebug("radio type: %s", Cellular::getRadioNames(type).c_str()); //Turns on the HW flow control if(sendBasicCommand("AT&K3", 2000) != MTS_SUCCESS) { - logWarning("Failed to set flow control to radio"); + logWarning("Failed to enable serial flow control"); } return true; } @@ -62,21 +60,17 @@ } //Check if socket is open - //flag stored in Cellular.h if(socketOpened) { return true; } //Check if already connected - //by calling the function isConnected() in EasyIP.cpp if(isConnected()) { return true; } - //Create an mbed timer object Timer tmr; //Check Registration: AT+CREG? == 0,1 - //(Does the AT command inside Cellular class) tmr.start(); do { Registration registration = getRegistration(); @@ -89,7 +83,6 @@ } while(tmr.read() < 30); //Check RSSI: AT+CSQ - //Does the command inside Cellular tmr.reset(); do { int rssi = getSignalStrength(); @@ -102,14 +95,12 @@ } } while(tmr.read() < 30); - //Similar to AT#CONNECTIONSTART: Make a PPP connection + //Make PPP connection if (type == MTSMC_H5 || type == MTSMC_G3) { logDebug("Making PPP Connection Attempt. APN[%s]", apn.c_str()); } else { logDebug("Making PPP Connection Attempt"); } - //The main thing going on; Sends the AT command to start a connection - //Assuming context is already stored in the modem std::string pppResult = sendCommand("AT#SGACT=1,1", 5000); std::vector<std::string> parts; if(pppResult.find("OK") != std::string::npos) { @@ -123,15 +114,12 @@ } else { pppResult = sendCommand("AT#SGACT?", 2000); - if(pppResult.empty() || (pppResult.find("ERROR") != std::string::npos)) { - pppConnected = false; + if(pppResult.find("1,1") != std::string::npos) { + logDebug("Radio is already connected"); + pppConnected = true; } else { - if(pppResult.find("1,1") != std::string::npos) { - logDebug("Radio is already connected"); - pppConnected = true; - } else { - pppConnected = false; - } + logError("PPP connection attempt failed"); + pppConnected = false; } } @@ -140,32 +128,27 @@ void EasyIP::disconnect() { - //AT#SGACT=1,0: Close a PPP connection - logDebug("Closing PPP Connection"); - if(socketOpened) { - if(!close()) { //Calls another EasyIP function to close socket before disconnect - logDebug("Failed to close socket for disconnect"); - return; //Can't close connection without AT commands - //(and thus need socket closed) - } - } + //AT#SGACT=1,0: Close PPP connection + logDebug("Closing PPP Connection"); std::string result; Timer tmr; + + if(socketOpened) { + close(); + } + //Sends AT#SGACT=1,0 command if (sendBasicCommand("AT#SGACT=1,0", 1000) == MTS_SUCCESS) { - pppConnected = false; logDebug("Successfully closed PPP Connection"); } - /* Radio was entering unknown state if ping command was sent after calling - * disconnect, due to context being closed between radio sending ping and - * waiting for ping response (which will never occur with connection closed) + /* Ensure PPP link is down, else ping commands will put radio in unknown state + * (Link is not immediate in disconnection, even though OK is returned) */ tmr.start(); while(tmr.read() < 30) { result = sendCommand("AT#SGACT?", 1000); if(result.find("1,0") != std::string::npos) { - pppConnected = false; break; } else if(result.find("ERROR") != std::string::npos) { break; @@ -174,19 +157,13 @@ } } - //If still unable to close PPP connection, wait for 30 seconds to drop connection - if(pppConnected) { - wait(30); - pppConnected = false; - } - + pppConnected = false; return; } bool EasyIP::isConnected() { - std::string stateString; - std::vector<std::string> pieces; + enum RadioState {IDLE, CONNECTING, CONNECTED, DISCONNECTED}; //state flags for various connection components bool signal = false, regist = false, active = false; @@ -199,118 +176,70 @@ } //2) Check that we do not have a live connection up - if(socketOpened) { + if (socketOpened) { logDebug("Socket is opened"); return true; } - //3) Query the radio - //3.a) Check antenna signal - std::string reply = sendCommand("AT+CSQ", 500); - if(reply.empty() || (reply.find("ERROR") != std::string::npos)) { + int rssi = getSignalStrength(); + if (rssi == 99 || rssi == -1) { + //Signal strength is nonexistent signal = false; } else { - pieces = Text::split(reply, "\r\n"); - if(pieces.size() >= 2) { - pieces = Text::split(pieces[1], " "); - if(pieces.size() >= 2) { - if((pieces[1].find("0,0") != std::string::npos) || (pieces[1].find("99,99") != std::string::npos)) { - signal = false; - } else { - signal = true; - } - } - } + signal = true; } - //3.b) Check cell tower registration - reply = sendCommand("AT+CREG?", 500); - if(reply.empty() || (reply.find("ERROR") != std::string::npos)) { - regist = false; + Registration creg = getRegistration(); + if (creg == REGISTERED) { + regist = true; } else { - pieces = Text::split(reply, "\r\n"); - if(pieces.size() >= 2) { - pieces = Text::split(pieces[1], " "); - if(pieces.size() >= 2) { - if((pieces[1].find("0,1") != std::string::npos) || (pieces[1].find("0,5") != std::string::npos)) { - regist = true; //1 for connected, 5 for roaming connected - } else { - regist = false; //Cell tower not registered - } - } - } + regist = false; } - //3.c) Check active context (SGACT = 1,1) - reply = sendCommand("AT#SGACT?", 500); - if(reply.empty() || (reply.find("ERROR") != std::string::npos)) { - active = false; + string reply = sendCommand("AT#SGACT?", 500); + if (reply.find("1,1") != std::string::npos) { + active = true; } else { - pieces = Text::split(reply, "\r\n"); - if(pieces.size() >= 2) { - pieces = Text::split(pieces[1], " "); - if(pieces.size() >= 2) { - if(pieces[1].find("1,1") != std::string::npos) { - active = true; //1 for an active connection mode - } else { - active = false; //0, or unknown value, is an inactive connection mode - } - } - } + active = false; } - //4) Determine radio state - if(regist && signal) { - if(pppConnected) { - if(active) { - if(ping()) { - stateString = "CONNECTED"; - pppConnected = true; - } else { - stateString = "AUTHENTICATING"; - pppConnected = true; - return false; //Return false instead of changing pppConnected due to the fact - //that it is connected to ppp, it just can't ping successfully - } - } else { - stateString = "DISCONNECTING"; - pppConnected = false; - } - } else { - if(active) { - if(ping()) { - pppConnected = true; - stateString = "CONNECTED"; - } else { - stateString = "CONNECTING"; - } - } else { - stateString = "IDLE"; - } - } - } else if(regist != signal) { - stateString = "CHECKING"; - return false; - } else if(!regist && !signal) { - stateString = "DISCONNECTED"; + + RadioState state; + bool ppp = pppConnected; + if (signal && regist && active) { + //Radio connected + state = CONNECTED; + pppConnected = true; + } else if (signal && !regist && !active) { + //Radio idle + state = IDLE; + pppConnected = false; + } else if (active) { + //Radio Connecting + state = CONNECTING; + } else { + //Radio Disconnected + state = DISCONNECTED; pppConnected = false; } - std::string pppStatus = pppConnected ? "CONNECTED" : "DISCONNECTED"; - if(stateString != pppStatus) { - logDebug("Internal PPP state[%s], radio state[%s])",pppStatus.c_str() ,stateString.c_str()); + if (!ppp && state == CONNECTED) { + logWarning("Internal PPP state tracking differs from radio (DISCONNECTED:CONNECTED)"); + } else if (ppp && state != CONNECTED) { + logWarning("Internal PPP state tracking differs from radio (CONNECTED:%s)", state); } + return pppConnected; } -//Resets the radio void EasyIP::reset() { disconnect(); + if(sendBasicCommand("AT#REBOOT", 10000) != MTS_SUCCESS) { - logError("Socket Modem did not accept RESET command\n\r"); + logError("Socket Modem did not accept RESET command"); } else { - logWarning("Socket Modem is resetting, allow 30 seconds for it to come back\n\r"); + logWarning("Socket Modem is resetting, allow 30 seconds for it to come back"); return; } } @@ -417,7 +346,7 @@ bool EasyIP::isOpen() { if(io->readable()) { - logDebug("Assuming open, data available to read.\n\r"); + logDebug("Assuming open, data available to read."); return true; } return socketOpened; @@ -597,7 +526,7 @@ if (address.compare("DHCP") == 0) { return true; } else { - logWarning("Radio does not support static IPs, using DHCP.\n\r"); + logWarning("Radio does not support static IPs, using DHCP."); return false; } } @@ -641,7 +570,6 @@ { char buffer[256] = {0}; std::vector<std::string> parts; - int pingsRec=0; int TTL=0; int Timeout=0; @@ -650,12 +578,7 @@ for(int pngs=0; pngs<PINGNUM; pngs++) { std::string response = sendCommand(buffer, (PINGDELAY*2000)); //Send 1 ping - wait(0.5); //Radio seems to get stuck if no wait is incurred between issuing ping commands - //leads to unknown registration state eventually :( - if(response.empty()) { - continue; //Skip current loop if send command fails - } - if(response.find("ERROR") != std::string::npos) { + if(response.empty() || response.find("ERROR") != std::string::npos) { continue; //Skip current loop if send command fails } parts = Text::split(response, "\r\n"); @@ -671,12 +594,9 @@ TTL = std::atoi(parts[3].c_str()); if((Timeout < 600) && (TTL < 255)) { - pingsRec++; - } - } //Success if less than 50% packet loss - if( ((pingsRec/PINGNUM)>= 0.5) ) { return true; } + } return false; } @@ -706,7 +626,8 @@ return false; } if(!socketOpened) { - logError("Socket is not open. +++ Escape sequence should fail"); + logError("Socket is not open."); + return false; } if(!socketCloseable) { @@ -718,43 +639,40 @@ io->txClear(); std::string result; - unsigned int timeoutMillis = 10000; //time in ms + unsigned int timeoutMillis = 10000; //Attempt to write command - wait(1.2); //Format for +++ command is 1 second wait, send +++, then another second wait - //1s wait after command is implemented as a polling function for 2 seconds - //Option: Could change wait periods to be longer/shorter (0-255)*50ms + //Format for +++ command is 1 second wait, send +++, then another second wait + wait(1.2); if(io->write("+++", 3, timeoutMillis) != 3) { //Failed to write command logError("failed to send command to radio within %d milliseconds", timeoutMillis); return false; } - int timer = 0; + Timer tmr; char tmp[256]; tmp[255] = 0; bool done = false; - io->read(tmp,255,0); bool exitmode = false; - + tmr.start(); do { - wait(0.1); - timer += 100; //Make a non-blocking read call by passing timeout of zero - int size = io->read(tmp,255,0); //1 less than allocated (timeout is instant) - if(size > 0) { - result.append(tmp, size); - } + int size = io->read(tmp,255,0); //1 less than allocated (timeout is instant) + if(size > 0) { + result.append(tmp, size); + } if(result.find("OK") != std::string::npos) { exitmode = true; done = true; } else if(result.find("NO CARRIER") != std::string::npos) { + socketOpened = false; exitmode = true; done = true; } else if(result.find("ERROR") != std::string::npos) { exitmode = false; done = true; } - if(timer >= timeoutMillis) { + if(tmr.read_ms() >= timeoutMillis) { logDebug("Escape sequence [+++] timed out after %d milliseconds", timeoutMillis); exitmode = true; done = true; @@ -766,40 +684,37 @@ bool EasyIP::socketCheck() { bool status = false; - std::string socketInfo = "9"; //9 is unrecognized + int socketInfo = 9; //error + enum SocketStatus {SOCKETCLOSED, SOCKETACTIVEDATA, SOCKETSUSPEND, SOCKETSUSPENDDATA, SOCKETLISTEN, SOCKETINCOMING, ERROR = 9}; std::vector<std::string> params; //Goes from data mode to command mode if(sendEscapeCommand()) { - socketOpened = false; - if(sendBasicCommand("AT", 1000) == MTS_SUCCESS) { - socketInfo = sendCommand("AT#SS=1", 2000); - if(socketInfo.find("OK") != std::string::npos) { - //Found valid response - params = Text::split(socketInfo, "\r\n"); - params = Text::split(params[1], ","); - socketInfo = params[1]; - //Check comparison of params[1] to response codes - } else { - logError("Could not determine socket status[%s]",socketInfo.c_str()); - socketInfo == "9"; //9 is unrecognized - } + std::string reply = sendCommand("AT#SS=1", 2000); + if(reply.find("OK") != std::string::npos) { + //Found valid response + params = Text::split(reply, "\r\n"); + params = Text::split(params[1], ","); + socketInfo = atoi(params[1].c_str()); + } else { + logError("Could not determine socket status[%d]",socketInfo); + socketInfo = 9; //9 is unrecognized } } else { status = false; //Return value of socketOpened when checking } //Check socket status query - if(socketInfo == "2" || socketInfo == "3" || socketInfo == "1" || socketInfo == "4") { - status = true; //2 and 3 are suspended connections - } else if(socketInfo == "0" || socketInfo == "5") { - status = false; //0 is closed socket, probably won't occur + if(socketInfo < 5 && socketInfo > 0) { //Socket opened responses + status = true; + } else if(socketInfo == SOCKETCLOSED || socketInfo == SOCKETINCOMING) { + status = false; } else { logError("Could not determine socket status"); - status = false; //anything else is unknown status + status = false; } - //Reconnects to active socket if able + //Reconnect to active socket if able if(status) { std::string reconnect = sendCommand("AT#SO=1", 2000); if(reconnect.find("CONNECT") != std::string::npos || reconnect.find("OK") != std::string::npos) {