Simple detection for LE910-NA1 modules
Fork of MTS-Cellular by
Diff: Cellular/EasyIP.cpp
- Revision:
- 52:2cb58398a4f9
- Parent:
- 51:ffc556ba33f7
- Child:
- 54:a6c738bfc391
--- 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) {