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
Cellular/EasyIP.cpp@30:1326b623919a, 2014-07-14 (annotated)
- Committer:
- Vanger
- Date:
- Mon Jul 14 17:33:24 2014 +0000
- Revision:
- 30:1326b623919a
- Parent:
- 29:edc613ed3f2e
- Child:
- 31:529db15abda7
For EasyIP.cpp:; Made sendEscapeCommand() and socketCheck() socket closed verification; connect(), disconnect(), and isConnected() were tweaked; IMPL. bind(),open(),isOpen(),close(),read(),write(),readable(),writeable(),reset(); Fixed bug in CellUtils.h;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Vanger | 26:2b769ed8de4f | 1 | // This is a template from UIP.cpp for now, will modify code and implement it as I go |
Vanger | 26:2b769ed8de4f | 2 | |
Vanger | 26:2b769ed8de4f | 3 | |
Vanger | 26:2b769ed8de4f | 4 | |
Vanger | 26:2b769ed8de4f | 5 | #include "mbed.h" |
Vanger | 26:2b769ed8de4f | 6 | #include "EasyIP.h" |
Vanger | 26:2b769ed8de4f | 7 | #include "MTSText.h" |
Vanger | 26:2b769ed8de4f | 8 | #include "MTSLog.h" |
Vanger | 26:2b769ed8de4f | 9 | #include "CellUtils.h" |
Vanger | 26:2b769ed8de4f | 10 | |
Vanger | 26:2b769ed8de4f | 11 | |
Vanger | 26:2b769ed8de4f | 12 | |
Vanger | 26:2b769ed8de4f | 13 | using namespace mts; |
Vanger | 26:2b769ed8de4f | 14 | |
Vanger | 30:1326b623919a | 15 | bool EasyIP::sendEscapeCommand() |
Vanger | 30:1326b623919a | 16 | { |
Vanger | 30:1326b623919a | 17 | //string Cellular::sendCommand(const std::string& command, unsigned int timeoutMillis, char esc) |
Vanger | 30:1326b623919a | 18 | if(io == NULL) { |
Vanger | 30:1326b623919a | 19 | logError("MTSBufferedIO not set"); |
Vanger | 30:1326b623919a | 20 | return false; |
Vanger | 30:1326b623919a | 21 | } |
Vanger | 30:1326b623919a | 22 | if(!socketOpened) { |
Vanger | 30:1326b623919a | 23 | logError("Socket is not open. Can not send AT escape sequence (+++)"); |
Vanger | 30:1326b623919a | 24 | return false; |
Vanger | 30:1326b623919a | 25 | } |
Vanger | 30:1326b623919a | 26 | |
Vanger | 30:1326b623919a | 27 | io->rxClear(); |
Vanger | 30:1326b623919a | 28 | io->txClear(); |
Vanger | 30:1326b623919a | 29 | |
Vanger | 30:1326b623919a | 30 | std::string result; |
Vanger | 30:1326b623919a | 31 | unsigned int timeoutMillis = 2000; |
Vanger | 30:1326b623919a | 32 | const int size_cmd = 3; |
Vanger | 30:1326b623919a | 33 | //Attempt to write command |
Vanger | 30:1326b623919a | 34 | wait(1); //Format for +++ command is 1 second wait, send +++, then another second wait |
Vanger | 30:1326b623919a | 35 | //1s wait after command is implemented as a polling function for 2 seconds |
Vanger | 30:1326b623919a | 36 | //Option: Could change wait periods to be longer/shorter (0-255)*50ms |
Vanger | 30:1326b623919a | 37 | if(io->write("+++", size_cmd, timeoutMillis) != size_cmd) { |
Vanger | 30:1326b623919a | 38 | //Failed to write command |
Vanger | 30:1326b623919a | 39 | logError("failed to send command to radio within %d milliseconds", timeoutMillis); |
Vanger | 30:1326b623919a | 40 | return false; |
Vanger | 30:1326b623919a | 41 | } |
Vanger | 30:1326b623919a | 42 | |
Vanger | 30:1326b623919a | 43 | int timer = 0; |
Vanger | 30:1326b623919a | 44 | char tmp[256]; |
Vanger | 30:1326b623919a | 45 | tmp[255] = 0; |
Vanger | 30:1326b623919a | 46 | bool done = false; |
Vanger | 30:1326b623919a | 47 | io->read(tmp,255,0); |
Vanger | 30:1326b623919a | 48 | bool exitmode = false; |
Vanger | 30:1326b623919a | 49 | |
Vanger | 30:1326b623919a | 50 | do { |
Vanger | 30:1326b623919a | 51 | wait(0.1); |
Vanger | 30:1326b623919a | 52 | timer += 100; |
Vanger | 30:1326b623919a | 53 | //Make a non-blocking read call by passing timeout of zero |
Vanger | 30:1326b623919a | 54 | int size = io->read(tmp,255,0); //1 less than allocated (timeout is instant) |
Vanger | 30:1326b623919a | 55 | if(size > 0) { |
Vanger | 30:1326b623919a | 56 | result.append(tmp, size); |
Vanger | 30:1326b623919a | 57 | } |
Vanger | 30:1326b623919a | 58 | if(result.find("OK") != std::string::npos) { |
Vanger | 30:1326b623919a | 59 | exitmode = true; |
Vanger | 30:1326b623919a | 60 | done = true; |
Vanger | 30:1326b623919a | 61 | } else if(result.find("NO CARRIER") != std::string::npos) { |
Vanger | 30:1326b623919a | 62 | exitmode = true; |
Vanger | 30:1326b623919a | 63 | done = true; |
Vanger | 30:1326b623919a | 64 | } else if(result.find("ERROR") != std::string::npos) { |
Vanger | 30:1326b623919a | 65 | exitmode = false; |
Vanger | 30:1326b623919a | 66 | done = true; |
Vanger | 30:1326b623919a | 67 | } |
Vanger | 30:1326b623919a | 68 | if(timer >= timeoutMillis) { |
Vanger | 30:1326b623919a | 69 | logDebug("Escape sequence [+++] timed out after %d milliseconds", timeoutMillis); |
Vanger | 30:1326b623919a | 70 | exitmode = true; |
Vanger | 30:1326b623919a | 71 | done = true; |
Vanger | 30:1326b623919a | 72 | } |
Vanger | 30:1326b623919a | 73 | } while (!done); |
Vanger | 30:1326b623919a | 74 | |
Vanger | 30:1326b623919a | 75 | return exitmode; |
Vanger | 30:1326b623919a | 76 | } |
Vanger | 30:1326b623919a | 77 | |
Vanger | 30:1326b623919a | 78 | bool EasyIP::socketCheck() { |
Vanger | 30:1326b623919a | 79 | bool status = false; |
Vanger | 30:1326b623919a | 80 | std::string socketInfo = "9"; //9 is unrecognized |
Vanger | 30:1326b623919a | 81 | std::vector<std::string> params; |
Vanger | 30:1326b623919a | 82 | |
Vanger | 30:1326b623919a | 83 | if(sendEscapeCommand()) { |
Vanger | 30:1326b623919a | 84 | socketOpened = false; |
Vanger | 30:1326b623919a | 85 | if(sendBasicCommand("AT", 1000) == MTS_SUCCESS) { |
Vanger | 30:1326b623919a | 86 | socketInfo = sendCommand("AT#SS=1", 2000); |
Vanger | 30:1326b623919a | 87 | if(socketInfo.find("OK") != std::string::npos) { |
Vanger | 30:1326b623919a | 88 | //Found valid response |
Vanger | 30:1326b623919a | 89 | params = Text::split(socketInfo, "\r\n"); |
Vanger | 30:1326b623919a | 90 | params = Text::split(params[1], ","); |
Vanger | 30:1326b623919a | 91 | socketInfo = params[1]; |
Vanger | 30:1326b623919a | 92 | //Check comparison of params[1] to response codes |
Vanger | 30:1326b623919a | 93 | } else { |
Vanger | 30:1326b623919a | 94 | logError("Could not determine socket status[%s]",socketInfo.c_str()); |
Vanger | 30:1326b623919a | 95 | socketInfo == "9"; //9 is unrecognized |
Vanger | 30:1326b623919a | 96 | } |
Vanger | 30:1326b623919a | 97 | } |
Vanger | 30:1326b623919a | 98 | } else { |
Vanger | 30:1326b623919a | 99 | status = false; //Return value of socketOpened when checking |
Vanger | 30:1326b623919a | 100 | } |
Vanger | 30:1326b623919a | 101 | //Check socket status query |
Vanger | 30:1326b623919a | 102 | if(socketInfo == "2" || socketInfo == "3" || socketInfo == "1" || socketInfo == "4") { |
Vanger | 30:1326b623919a | 103 | status = true; //2 and 3 are suspended connections |
Vanger | 30:1326b623919a | 104 | } else if(socketInfo == "0" || socketInfo == "5") { |
Vanger | 30:1326b623919a | 105 | status = false; //0 is closed socket, probably won't occur |
Vanger | 30:1326b623919a | 106 | } else { |
Vanger | 30:1326b623919a | 107 | logError("Could not determine socket status"); |
Vanger | 30:1326b623919a | 108 | status = false; //anything else is unknown status |
Vanger | 30:1326b623919a | 109 | } |
Vanger | 30:1326b623919a | 110 | |
Vanger | 30:1326b623919a | 111 | if(status) { |
Vanger | 30:1326b623919a | 112 | std::string reconnect = sendCommand("AT#SO=1", 2000); |
Vanger | 30:1326b623919a | 113 | if(reconnect.find("CONNECT") != std::string::npos || reconnect.find("OK") != std::string::npos) { |
Vanger | 30:1326b623919a | 114 | } else { |
Vanger | 30:1326b623919a | 115 | logError("Failed to resume socket connection"); |
Vanger | 30:1326b623919a | 116 | } |
Vanger | 30:1326b623919a | 117 | } |
Vanger | 30:1326b623919a | 118 | return status; |
Vanger | 30:1326b623919a | 119 | } |
Vanger | 30:1326b623919a | 120 | |
Vanger | 26:2b769ed8de4f | 121 | EasyIP::EasyIP(Radio type) |
Vanger | 26:2b769ed8de4f | 122 | { |
Vanger | 26:2b769ed8de4f | 123 | //Not sure how the construction process is done, |
Vanger | 26:2b769ed8de4f | 124 | //but assuming it works for both EasyIP and UIP the same way. |
Vanger | 26:2b769ed8de4f | 125 | this->type = type; |
Vanger | 26:2b769ed8de4f | 126 | io = NULL; |
Vanger | 26:2b769ed8de4f | 127 | dcd = NULL; |
Vanger | 26:2b769ed8de4f | 128 | dtr = NULL; |
Vanger | 26:2b769ed8de4f | 129 | resetLine = NULL; |
Vanger | 26:2b769ed8de4f | 130 | echoMode = true; |
Vanger | 26:2b769ed8de4f | 131 | pppConnected = false; |
Vanger | 26:2b769ed8de4f | 132 | socketMode = TCP; |
Vanger | 26:2b769ed8de4f | 133 | socketOpened = false; |
Vanger | 26:2b769ed8de4f | 134 | socketCloseable = true; |
Vanger | 26:2b769ed8de4f | 135 | local_port = 0; |
Vanger | 26:2b769ed8de4f | 136 | local_address = ""; |
Vanger | 26:2b769ed8de4f | 137 | host_port = 0; |
Vanger | 26:2b769ed8de4f | 138 | } |
Vanger | 26:2b769ed8de4f | 139 | |
Vanger | 26:2b769ed8de4f | 140 | EasyIP::~EasyIP() |
Vanger | 26:2b769ed8de4f | 141 | { |
Vanger | 26:2b769ed8de4f | 142 | //Same reasoning for the destructor as the constructor, |
Vanger | 26:2b769ed8de4f | 143 | //assuming it works for UIP, it will work for EasyIP |
Vanger | 26:2b769ed8de4f | 144 | if (dtr != NULL) { |
Vanger | 26:2b769ed8de4f | 145 | dtr->write(1); |
Vanger | 26:2b769ed8de4f | 146 | } |
Vanger | 26:2b769ed8de4f | 147 | |
Vanger | 26:2b769ed8de4f | 148 | delete dcd; |
Vanger | 26:2b769ed8de4f | 149 | delete dtr; |
Vanger | 26:2b769ed8de4f | 150 | delete resetLine; |
Vanger | 26:2b769ed8de4f | 151 | } |
Vanger | 26:2b769ed8de4f | 152 | |
Vanger | 26:2b769ed8de4f | 153 | //Initializes the MTS IO Buffer |
Vanger | 26:2b769ed8de4f | 154 | bool EasyIP::init(MTSBufferedIO* io) |
Vanger | 26:2b769ed8de4f | 155 | { |
Vanger | 26:2b769ed8de4f | 156 | if (! Cellular::init(io)) { |
Vanger | 26:2b769ed8de4f | 157 | return false; |
Vanger | 26:2b769ed8de4f | 158 | } |
Vanger | 26:2b769ed8de4f | 159 | |
Vanger | 26:2b769ed8de4f | 160 | logDebug("radio type: %s", Cellular::getRadioNames(type).c_str()); |
Vanger | 26:2b769ed8de4f | 161 | return true; |
Vanger | 26:2b769ed8de4f | 162 | } |
Vanger | 26:2b769ed8de4f | 163 | |
Vanger | 26:2b769ed8de4f | 164 | bool EasyIP::connect() |
Vanger | 26:2b769ed8de4f | 165 | { |
Vanger | 29:edc613ed3f2e | 166 | //Check if APN is not set, if so, connect will not work. |
Vanger | 29:edc613ed3f2e | 167 | if (type == MTSMC_H5_IP || type == MTSMC_H5 || type == MTSMC_G3) { |
Vanger | 29:edc613ed3f2e | 168 | if(apn.size() == 0) { |
Vanger | 29:edc613ed3f2e | 169 | logDebug("APN is not set"); |
Vanger | 29:edc613ed3f2e | 170 | return false; |
Vanger | 29:edc613ed3f2e | 171 | } |
Vanger | 29:edc613ed3f2e | 172 | } |
Vanger | 29:edc613ed3f2e | 173 | |
Vanger | 26:2b769ed8de4f | 174 | //Check if socket is open |
Vanger | 26:2b769ed8de4f | 175 | //flag stored in Cellular.h |
Vanger | 26:2b769ed8de4f | 176 | if(socketOpened) { |
Vanger | 26:2b769ed8de4f | 177 | return true; |
Vanger | 26:2b769ed8de4f | 178 | } |
Vanger | 26:2b769ed8de4f | 179 | |
Vanger | 26:2b769ed8de4f | 180 | //Check if already connected |
Vanger | 26:2b769ed8de4f | 181 | //by calling the function isConnected() in EasyIP.cpp |
Vanger | 26:2b769ed8de4f | 182 | if(isConnected()) { |
Vanger | 26:2b769ed8de4f | 183 | return true; |
Vanger | 26:2b769ed8de4f | 184 | } |
Vanger | 26:2b769ed8de4f | 185 | //Create an mbed timer object |
Vanger | 26:2b769ed8de4f | 186 | Timer tmr; |
Vanger | 26:2b769ed8de4f | 187 | //Check Registration: AT+CREG? == 0,1 |
Vanger | 26:2b769ed8de4f | 188 | //(Does the AT command inside Cellular class) |
Vanger | 26:2b769ed8de4f | 189 | tmr.start(); |
Vanger | 26:2b769ed8de4f | 190 | do { |
Vanger | 26:2b769ed8de4f | 191 | Registration registration = getRegistration(); |
Vanger | 26:2b769ed8de4f | 192 | if(registration != REGISTERED) { |
Vanger | 26:2b769ed8de4f | 193 | logTrace("Not Registered [%d] ... waiting", (int)registration); |
Vanger | 26:2b769ed8de4f | 194 | wait(1); |
Vanger | 26:2b769ed8de4f | 195 | } else { |
Vanger | 26:2b769ed8de4f | 196 | break; |
Vanger | 26:2b769ed8de4f | 197 | } |
Vanger | 30:1326b623919a | 198 | } while(tmr.read() < 30); |
Vanger | 26:2b769ed8de4f | 199 | //Check RSSI: AT+CSQ |
Vanger | 26:2b769ed8de4f | 200 | //Does the command inside Cellular |
Vanger | 26:2b769ed8de4f | 201 | tmr.reset(); |
Vanger | 26:2b769ed8de4f | 202 | do { |
Vanger | 26:2b769ed8de4f | 203 | int rssi = getSignalStrength(); |
Vanger | 26:2b769ed8de4f | 204 | logDebug("Signal strength: %d", rssi); |
Vanger | 30:1326b623919a | 205 | if((rssi == 99) || (rssi == -1)) { |
Vanger | 26:2b769ed8de4f | 206 | logTrace("No Signal ... waiting"); |
Vanger | 26:2b769ed8de4f | 207 | wait(1); |
Vanger | 26:2b769ed8de4f | 208 | } else { |
Vanger | 26:2b769ed8de4f | 209 | break; |
Vanger | 26:2b769ed8de4f | 210 | } |
Vanger | 26:2b769ed8de4f | 211 | } while(tmr.read() < 30); |
Vanger | 26:2b769ed8de4f | 212 | |
Vanger | 27:ec44d5a9544f | 213 | //Similar to AT#CONNECTIONSTART: Make a PPP connection |
Vanger | 26:2b769ed8de4f | 214 | if (type == MTSMC_H5 || type == MTSMC_G3) { |
Vanger | 26:2b769ed8de4f | 215 | logDebug("Making PPP Connection Attempt. APN[%s]", apn.c_str()); |
Vanger | 26:2b769ed8de4f | 216 | } else { |
Vanger | 26:2b769ed8de4f | 217 | logDebug("Making PPP Connection Attempt"); |
Vanger | 26:2b769ed8de4f | 218 | } |
Vanger | 26:2b769ed8de4f | 219 | //The main thing going on; Sends the AT command to start a connection |
Vanger | 30:1326b623919a | 220 | //Assuming context is already stored in the modem |
Vanger | 30:1326b623919a | 221 | std::string pppResult = sendCommand("AT#SGACT=1,1", 2000); |
Vanger | 30:1326b623919a | 222 | std::vector<std::string> parts; |
Vanger | 26:2b769ed8de4f | 223 | if(pppResult.find("OK") != std::string::npos) { |
Vanger | 30:1326b623919a | 224 | parts = Text::split(pppResult, "\r\n"); |
Vanger | 26:2b769ed8de4f | 225 | if(parts.size() >= 2) { |
Vanger | 26:2b769ed8de4f | 226 | parts = Text::split(parts[1], " "); |
Vanger | 26:2b769ed8de4f | 227 | local_address = parts[1]; |
Vanger | 26:2b769ed8de4f | 228 | } |
Vanger | 26:2b769ed8de4f | 229 | logInfo("PPP Connection Established: IP[%s]", local_address.c_str()); |
Vanger | 26:2b769ed8de4f | 230 | pppConnected = true; |
Vanger | 26:2b769ed8de4f | 231 | |
Vanger | 26:2b769ed8de4f | 232 | } else { |
Vanger | 30:1326b623919a | 233 | pppResult = sendCommand("AT#SGACT?", 2000); |
Vanger | 30:1326b623919a | 234 | if(pppResult.empty() || (pppResult.find("ERROR") != std::string::npos)) { |
Vanger | 30:1326b623919a | 235 | pppConnected = false; |
Vanger | 30:1326b623919a | 236 | } else { |
Vanger | 30:1326b623919a | 237 | if(pppResult.find("1,1") != std::string::npos) { |
Vanger | 30:1326b623919a | 238 | pppConnected = true; |
Vanger | 30:1326b623919a | 239 | } else { |
Vanger | 30:1326b623919a | 240 | pppConnected = false; |
Vanger | 30:1326b623919a | 241 | } |
Vanger | 30:1326b623919a | 242 | } |
Vanger | 26:2b769ed8de4f | 243 | } |
Vanger | 26:2b769ed8de4f | 244 | |
Vanger | 26:2b769ed8de4f | 245 | return pppConnected; |
Vanger | 26:2b769ed8de4f | 246 | } |
Vanger | 26:2b769ed8de4f | 247 | |
Vanger | 26:2b769ed8de4f | 248 | void EasyIP::disconnect() |
Vanger | 26:2b769ed8de4f | 249 | { |
Vanger | 26:2b769ed8de4f | 250 | //AT#SGACT=1,0: Close a PPP connection |
Vanger | 28:f93d7b3f7c2e | 251 | logDebug("Closing PPP Connection"); |
Vanger | 26:2b769ed8de4f | 252 | if(socketOpened) { |
Vanger | 30:1326b623919a | 253 | if(!close()) { //Calls another EasyIP function to close socket before disconnect |
Vanger | 30:1326b623919a | 254 | logDebug("Failed to close socket for disconnect"); |
Vanger | 30:1326b623919a | 255 | return; //Can't close connection without AT commands |
Vanger | 30:1326b623919a | 256 | //(and thus need socket closed) |
Vanger | 30:1326b623919a | 257 | } |
Vanger | 26:2b769ed8de4f | 258 | } |
Vanger | 26:2b769ed8de4f | 259 | //Sends AT#SGACT=1,0 command |
Vanger | 30:1326b623919a | 260 | if(sendBasicCommand("AT#SGACT=1,0", 1000) == MTS_SUCCESS) { |
Vanger | 30:1326b623919a | 261 | pppConnected = false; |
Vanger | 30:1326b623919a | 262 | logDebug("Successfully closed PPP Connection"); |
Vanger | 30:1326b623919a | 263 | } |
Vanger | 28:f93d7b3f7c2e | 264 | pppConnected = false; //Cell will drop connection if we go silent |
Vanger | 30:1326b623919a | 265 | return; |
Vanger | 26:2b769ed8de4f | 266 | } |
Vanger | 27:ec44d5a9544f | 267 | |
Vanger | 26:2b769ed8de4f | 268 | bool EasyIP::isConnected() |
Vanger | 26:2b769ed8de4f | 269 | { |
Vanger | 29:edc613ed3f2e | 270 | std::string stateString; |
Vanger | 29:edc613ed3f2e | 271 | std::vector<std::string> pieces; |
Vanger | 30:1326b623919a | 272 | //state flags for various connection checks |
Vanger | 30:1326b623919a | 273 | bool signal = false, regist = false, active = false; |
Vanger | 26:2b769ed8de4f | 274 | |
Vanger | 29:edc613ed3f2e | 275 | //1) Check if APN was set if we're on an HSPA radio |
Vanger | 29:edc613ed3f2e | 276 | if (type == MTSMC_H5_IP || type == MTSMC_H5 || type == MTSMC_G3) { |
Vanger | 29:edc613ed3f2e | 277 | if(apn.size() == 0) { |
Vanger | 29:edc613ed3f2e | 278 | logDebug("APN is not set"); |
Vanger | 29:edc613ed3f2e | 279 | return false; |
Vanger | 29:edc613ed3f2e | 280 | } |
Vanger | 29:edc613ed3f2e | 281 | } |
Vanger | 29:edc613ed3f2e | 282 | |
Vanger | 29:edc613ed3f2e | 283 | //2) Check that we do not have a live connection up |
Vanger | 29:edc613ed3f2e | 284 | if(socketOpened) { |
Vanger | 29:edc613ed3f2e | 285 | logDebug("Socket is opened"); |
Vanger | 29:edc613ed3f2e | 286 | return true; |
Vanger | 29:edc613ed3f2e | 287 | } |
Vanger | 29:edc613ed3f2e | 288 | |
Vanger | 30:1326b623919a | 289 | |
Vanger | 29:edc613ed3f2e | 290 | //3) Query the radio |
Vanger | 29:edc613ed3f2e | 291 | //Check antenna signal |
Vanger | 30:1326b623919a | 292 | std::string reply = sendCommand("AT+CSQ", 500); |
Vanger | 29:edc613ed3f2e | 293 | if(reply.empty() || (reply.find("ERROR") != std::string::npos)) { |
Vanger | 29:edc613ed3f2e | 294 | signal = false; |
Vanger | 29:edc613ed3f2e | 295 | } else { |
Vanger | 29:edc613ed3f2e | 296 | pieces = Text::split(reply, "\r\n"); |
Vanger | 29:edc613ed3f2e | 297 | if(pieces.size() >= 2) { |
Vanger | 29:edc613ed3f2e | 298 | pieces = Text::split(pieces[1], " "); |
Vanger | 29:edc613ed3f2e | 299 | if(pieces.size() >= 2) { |
Vanger | 29:edc613ed3f2e | 300 | if((pieces[1].find("0,0") != std::string::npos) || (pieces[1].find("99,99") != std::string::npos)) { |
Vanger | 29:edc613ed3f2e | 301 | signal = false; |
Vanger | 29:edc613ed3f2e | 302 | } else { |
Vanger | 29:edc613ed3f2e | 303 | signal = true; |
Vanger | 29:edc613ed3f2e | 304 | } |
Vanger | 29:edc613ed3f2e | 305 | } |
Vanger | 29:edc613ed3f2e | 306 | } |
Vanger | 29:edc613ed3f2e | 307 | } |
Vanger | 27:ec44d5a9544f | 308 | |
Vanger | 29:edc613ed3f2e | 309 | //Check cell tower registration |
Vanger | 30:1326b623919a | 310 | reply = sendCommand("AT+CREG?", 500); |
Vanger | 29:edc613ed3f2e | 311 | if(reply.empty() || (reply.find("ERROR") != std::string::npos)) { |
Vanger | 29:edc613ed3f2e | 312 | regist = false; |
Vanger | 29:edc613ed3f2e | 313 | } else { |
Vanger | 29:edc613ed3f2e | 314 | pieces = Text::split(reply, "\r\n"); |
Vanger | 29:edc613ed3f2e | 315 | if(pieces.size() >= 2) { |
Vanger | 29:edc613ed3f2e | 316 | pieces = Text::split(pieces[1], " "); |
Vanger | 29:edc613ed3f2e | 317 | if(pieces.size() >= 2) { |
Vanger | 29:edc613ed3f2e | 318 | if((pieces[1].find("0,1") != std::string::npos) || (pieces[1].find("0,5") != std::string::npos)) { |
Vanger | 29:edc613ed3f2e | 319 | regist = true; //1 for connected, 5 for roaming connected |
Vanger | 29:edc613ed3f2e | 320 | } else { |
Vanger | 29:edc613ed3f2e | 321 | regist = false; //Cell tower not registered |
Vanger | 29:edc613ed3f2e | 322 | } |
Vanger | 29:edc613ed3f2e | 323 | } |
Vanger | 29:edc613ed3f2e | 324 | } |
Vanger | 29:edc613ed3f2e | 325 | } |
Vanger | 27:ec44d5a9544f | 326 | |
Vanger | 29:edc613ed3f2e | 327 | //Check active mode (SGACT = 1,1) |
Vanger | 30:1326b623919a | 328 | reply = sendCommand("AT#SGACT?", 500); |
Vanger | 29:edc613ed3f2e | 329 | if(reply.empty() || (reply.find("ERROR") != std::string::npos)) { |
Vanger | 29:edc613ed3f2e | 330 | active = false; |
Vanger | 29:edc613ed3f2e | 331 | } else { |
Vanger | 29:edc613ed3f2e | 332 | pieces = Text::split(reply, "\r\n"); |
Vanger | 29:edc613ed3f2e | 333 | if(pieces.size() >= 2) { |
Vanger | 29:edc613ed3f2e | 334 | pieces = Text::split(pieces[1], " "); |
Vanger | 29:edc613ed3f2e | 335 | if(pieces.size() >= 2) { |
Vanger | 29:edc613ed3f2e | 336 | if(pieces[1].find("1,1") != std::string::npos) { |
Vanger | 29:edc613ed3f2e | 337 | active = true; //1 for an active connection mode |
Vanger | 29:edc613ed3f2e | 338 | } else { |
Vanger | 29:edc613ed3f2e | 339 | active = false; //0, or unknown value, is an inactive connection mode |
Vanger | 29:edc613ed3f2e | 340 | } |
Vanger | 29:edc613ed3f2e | 341 | } |
Vanger | 29:edc613ed3f2e | 342 | } |
Vanger | 29:edc613ed3f2e | 343 | } |
Vanger | 30:1326b623919a | 344 | //4) Determine radio state |
Vanger | 30:1326b623919a | 345 | if(regist && signal) { |
Vanger | 29:edc613ed3f2e | 346 | if(pppConnected) { |
Vanger | 30:1326b623919a | 347 | if(active) { |
Vanger | 30:1326b623919a | 348 | if(ping()) { |
Vanger | 30:1326b623919a | 349 | stateString = "CONNECTED"; |
Vanger | 30:1326b623919a | 350 | pppConnected = true; |
Vanger | 29:edc613ed3f2e | 351 | } else { |
Vanger | 30:1326b623919a | 352 | stateString = "AUTHENTICATING"; |
Vanger | 30:1326b623919a | 353 | pppConnected = true; |
Vanger | 30:1326b623919a | 354 | return false; //Return false instead of changing pppConnected due to the fact |
Vanger | 30:1326b623919a | 355 | //that it is connected to ppp, it just can't ping successfully |
Vanger | 29:edc613ed3f2e | 356 | } |
Vanger | 30:1326b623919a | 357 | } else { |
Vanger | 30:1326b623919a | 358 | stateString = "DISCONNECTING"; |
Vanger | 30:1326b623919a | 359 | pppConnected = false; |
Vanger | 30:1326b623919a | 360 | } |
Vanger | 30:1326b623919a | 361 | } else { |
Vanger | 30:1326b623919a | 362 | if(active) { |
Vanger | 30:1326b623919a | 363 | if(ping()) { |
Vanger | 30:1326b623919a | 364 | pppConnected = true; |
Vanger | 30:1326b623919a | 365 | logWarning("Internal PPP state tracking differs from radio (DISCONNECTED:CONNECTED)"); |
Vanger | 30:1326b623919a | 366 | stateString = "CONNECTED"; |
Vanger | 30:1326b623919a | 367 | } else { |
Vanger | 30:1326b623919a | 368 | stateString = "CONNECTING"; |
Vanger | 30:1326b623919a | 369 | } |
Vanger | 30:1326b623919a | 370 | } else { |
Vanger | 30:1326b623919a | 371 | stateString = "IDLE"; |
Vanger | 30:1326b623919a | 372 | } |
Vanger | 29:edc613ed3f2e | 373 | } |
Vanger | 30:1326b623919a | 374 | } else if(regist != signal) { |
Vanger | 30:1326b623919a | 375 | stateString = "CHECKING"; |
Vanger | 29:edc613ed3f2e | 376 | pppConnected = false; |
Vanger | 30:1326b623919a | 377 | } else if(!regist && !signal) { |
Vanger | 30:1326b623919a | 378 | stateString = "DISCONNECTED"; |
Vanger | 30:1326b623919a | 379 | pppConnected = false; |
Vanger | 30:1326b623919a | 380 | } |
Vanger | 30:1326b623919a | 381 | //Log results if necessary |
Vanger | 30:1326b623919a | 382 | if(stateString != "CONNECTED") { |
Vanger | 30:1326b623919a | 383 | logWarning("Internal PPP state tracking differs from radio (CONNECTED:%s)",stateString.c_str()); |
Vanger | 29:edc613ed3f2e | 384 | } |
Vanger | 26:2b769ed8de4f | 385 | return pppConnected; |
Vanger | 26:2b769ed8de4f | 386 | } |
Vanger | 30:1326b623919a | 387 | |
Vanger | 26:2b769ed8de4f | 388 | //Binds the socket to a specific port if able |
Vanger | 26:2b769ed8de4f | 389 | bool EasyIP::bind(unsigned int port) |
Vanger | 26:2b769ed8de4f | 390 | { |
Vanger | 30:1326b623919a | 391 | if(socketOpened) { |
Vanger | 30:1326b623919a | 392 | logError("socket is open. Can not set local port"); |
Vanger | 30:1326b623919a | 393 | return false; |
Vanger | 30:1326b623919a | 394 | } |
Vanger | 30:1326b623919a | 395 | if(port > 65535) { |
Vanger | 30:1326b623919a | 396 | logError("port out of range (0-65535)"); |
Vanger | 30:1326b623919a | 397 | return false; |
Vanger | 30:1326b623919a | 398 | } |
Vanger | 30:1326b623919a | 399 | local_port = port; |
Vanger | 26:2b769ed8de4f | 400 | return true; |
Vanger | 26:2b769ed8de4f | 401 | } |
Vanger | 27:ec44d5a9544f | 402 | |
Vanger | 26:2b769ed8de4f | 403 | bool EasyIP::open(const std::string& address, unsigned int port, Mode mode) |
Vanger | 26:2b769ed8de4f | 404 | { |
Vanger | 30:1326b623919a | 405 | char sOpenSocketCmd[256] = {0}; //String for AT command |
Vanger | 30:1326b623919a | 406 | std::string sMode = ""; |
Vanger | 30:1326b623919a | 407 | int typeSocket; |
Vanger | 30:1326b623919a | 408 | |
Vanger | 30:1326b623919a | 409 | //1) Check that we do not have a live connection up |
Vanger | 30:1326b623919a | 410 | if(socketOpened) { |
Vanger | 30:1326b623919a | 411 | //Check that the address, port, and mode match |
Vanger | 30:1326b623919a | 412 | if(host_address != address || host_port != port || socketMode != mode) { |
Vanger | 30:1326b623919a | 413 | if(socketMode == TCP) { |
Vanger | 30:1326b623919a | 414 | logError("TCP socket already opened [%s:%d]", host_address.c_str(), host_port); |
Vanger | 30:1326b623919a | 415 | } else { |
Vanger | 30:1326b623919a | 416 | logError("UDP socket already opened [%s:%d]", host_address.c_str(), host_port); |
Vanger | 30:1326b623919a | 417 | } |
Vanger | 30:1326b623919a | 418 | return false; |
Vanger | 30:1326b623919a | 419 | } |
Vanger | 30:1326b623919a | 420 | |
Vanger | 30:1326b623919a | 421 | logDebug("Socket already opened"); |
Vanger | 30:1326b623919a | 422 | return true; |
Vanger | 30:1326b623919a | 423 | } |
Vanger | 30:1326b623919a | 424 | |
Vanger | 30:1326b623919a | 425 | //2) Check Parameters |
Vanger | 30:1326b623919a | 426 | if(port > 65535) { |
Vanger | 30:1326b623919a | 427 | logError("port out of range (0-65535)"); |
Vanger | 30:1326b623919a | 428 | return false; |
Vanger | 30:1326b623919a | 429 | } |
Vanger | 30:1326b623919a | 430 | |
Vanger | 30:1326b623919a | 431 | //3) Check PPP connection |
Vanger | 30:1326b623919a | 432 | if(!isConnected()) { |
Vanger | 30:1326b623919a | 433 | logError("PPP not established. Attempting to connect"); |
Vanger | 30:1326b623919a | 434 | if(!connect()) { |
Vanger | 30:1326b623919a | 435 | logError("PPP connection failed"); |
Vanger | 30:1326b623919a | 436 | return false; |
Vanger | 30:1326b623919a | 437 | } else { |
Vanger | 30:1326b623919a | 438 | logDebug("PPP connection established"); |
Vanger | 30:1326b623919a | 439 | } |
Vanger | 30:1326b623919a | 440 | } |
Vanger | 30:1326b623919a | 441 | //No way to "set" port except on socket call; |
Vanger | 30:1326b623919a | 442 | //Going to need to warn if local_port was not set. |
Vanger | 30:1326b623919a | 443 | if(!local_port) { |
Vanger | 30:1326b623919a | 444 | logDebug("No local port was set: 0"); |
Vanger | 30:1326b623919a | 445 | } |
Vanger | 30:1326b623919a | 446 | |
Vanger | 30:1326b623919a | 447 | //4) Set escape sequence to not be transmitted |
Vanger | 30:1326b623919a | 448 | if(sendBasicCommand("AT#SKIPESC=1", 2000) != MTS_SUCCESS) { |
Vanger | 30:1326b623919a | 449 | logWarning("Failed to disable escape sequence transmission on data mode suspension"); |
Vanger | 30:1326b623919a | 450 | } |
Vanger | 30:1326b623919a | 451 | |
Vanger | 30:1326b623919a | 452 | if(mode == TCP) { |
Vanger | 30:1326b623919a | 453 | typeSocket = 0; |
Vanger | 30:1326b623919a | 454 | sMode = "TCP"; |
Vanger | 30:1326b623919a | 455 | } else { |
Vanger | 30:1326b623919a | 456 | typeSocket = 1; |
Vanger | 30:1326b623919a | 457 | sMode = "UDP"; |
Vanger | 30:1326b623919a | 458 | } |
Vanger | 30:1326b623919a | 459 | //4) Close Socket |
Vanger | 30:1326b623919a | 460 | sprintf(sOpenSocketCmd, "AT#SD=1,%d,%d,%s,0,%d,0", typeSocket, port, address.c_str(), local_port); |
Vanger | 30:1326b623919a | 461 | std::string response = sendCommand(sOpenSocketCmd, 5000); |
Vanger | 30:1326b623919a | 462 | |
Vanger | 30:1326b623919a | 463 | if(response.find("CONNECT") != std::string::npos) { |
Vanger | 30:1326b623919a | 464 | host_address = address; |
Vanger | 30:1326b623919a | 465 | host_port = port; |
Vanger | 30:1326b623919a | 466 | |
Vanger | 30:1326b623919a | 467 | logInfo("Opened %s Socket [%s:%d]", sMode.c_str(), address.c_str(), port); |
Vanger | 30:1326b623919a | 468 | socketOpened = true; |
Vanger | 30:1326b623919a | 469 | socketMode = mode; |
Vanger | 30:1326b623919a | 470 | } else { |
Vanger | 30:1326b623919a | 471 | logWarning("Unable to open %s Socket [%s:%d]", sMode.c_str(), address.c_str(), port); |
Vanger | 30:1326b623919a | 472 | socketOpened = false; |
Vanger | 30:1326b623919a | 473 | } |
Vanger | 30:1326b623919a | 474 | |
Vanger | 26:2b769ed8de4f | 475 | return socketOpened; |
Vanger | 26:2b769ed8de4f | 476 | } |
Vanger | 27:ec44d5a9544f | 477 | |
Vanger | 26:2b769ed8de4f | 478 | bool EasyIP::isOpen() |
Vanger | 26:2b769ed8de4f | 479 | { |
Vanger | 30:1326b623919a | 480 | if(io->readable()) { |
Vanger | 30:1326b623919a | 481 | logDebug("Assuming open, data available to read.\n\r"); |
Vanger | 30:1326b623919a | 482 | return true; |
Vanger | 30:1326b623919a | 483 | } |
Vanger | 26:2b769ed8de4f | 484 | return socketOpened; |
Vanger | 26:2b769ed8de4f | 485 | } |
Vanger | 27:ec44d5a9544f | 486 | |
Vanger | 26:2b769ed8de4f | 487 | bool EasyIP::close() |
Vanger | 26:2b769ed8de4f | 488 | { |
Vanger | 26:2b769ed8de4f | 489 | |
Vanger | 30:1326b623919a | 490 | if(io == NULL) { |
Vanger | 30:1326b623919a | 491 | logError("MTSBufferedIO not set"); |
Vanger | 30:1326b623919a | 492 | return false; |
Vanger | 30:1326b623919a | 493 | } |
Vanger | 30:1326b623919a | 494 | |
Vanger | 30:1326b623919a | 495 | if(!socketOpened) { |
Vanger | 30:1326b623919a | 496 | logWarning("Socket close() called, but socket was not open"); |
Vanger | 30:1326b623919a | 497 | return true; |
Vanger | 30:1326b623919a | 498 | } |
Vanger | 30:1326b623919a | 499 | |
Vanger | 30:1326b623919a | 500 | if(!socketCloseable) { |
Vanger | 30:1326b623919a | 501 | logError("Socket is not closeable"); |
Vanger | 30:1326b623919a | 502 | return false; |
Vanger | 30:1326b623919a | 503 | } |
Vanger | 30:1326b623919a | 504 | |
Vanger | 30:1326b623919a | 505 | if(!sendEscapeCommand()) { |
Vanger | 30:1326b623919a | 506 | logError("Failed to exit online mode"); |
Vanger | 30:1326b623919a | 507 | return false; |
Vanger | 30:1326b623919a | 508 | } else { |
Vanger | 30:1326b623919a | 509 | socketOpened = false; |
Vanger | 30:1326b623919a | 510 | } |
Vanger | 30:1326b623919a | 511 | |
Vanger | 30:1326b623919a | 512 | if(sendBasicCommand("AT#SH=1", 2000) != MTS_SUCCESS) { |
Vanger | 30:1326b623919a | 513 | logDebug("Failed to close socket connection"); |
Vanger | 30:1326b623919a | 514 | } |
Vanger | 30:1326b623919a | 515 | |
Vanger | 30:1326b623919a | 516 | Timer tmr; |
Vanger | 30:1326b623919a | 517 | int counter = 0; |
Vanger | 30:1326b623919a | 518 | char tmp[256]; |
Vanger | 30:1326b623919a | 519 | tmr.start(); |
Vanger | 30:1326b623919a | 520 | do { |
Vanger | 30:1326b623919a | 521 | if(socketOpened == false) { |
Vanger | 30:1326b623919a | 522 | break; |
Vanger | 30:1326b623919a | 523 | } |
Vanger | 30:1326b623919a | 524 | read(tmp, 256, 1000); |
Vanger | 30:1326b623919a | 525 | } while(counter++ < 10); |
Vanger | 30:1326b623919a | 526 | |
Vanger | 30:1326b623919a | 527 | io->rxClear(); |
Vanger | 30:1326b623919a | 528 | io->txClear(); |
Vanger | 30:1326b623919a | 529 | |
Vanger | 30:1326b623919a | 530 | return !socketOpened; |
Vanger | 26:2b769ed8de4f | 531 | } |
Vanger | 26:2b769ed8de4f | 532 | |
Vanger | 26:2b769ed8de4f | 533 | int EasyIP::read(char* data, int max, int timeout) |
Vanger | 26:2b769ed8de4f | 534 | { |
Vanger | 30:1326b623919a | 535 | if(io == NULL) { |
Vanger | 30:1326b623919a | 536 | logError("MTSBufferedIO not set"); |
Vanger | 30:1326b623919a | 537 | return -1; |
Vanger | 30:1326b623919a | 538 | } |
Vanger | 30:1326b623919a | 539 | |
Vanger | 30:1326b623919a | 540 | //Check that nothing is in the rx buffer |
Vanger | 30:1326b623919a | 541 | if(!socketOpened && !io->readable()) { |
Vanger | 30:1326b623919a | 542 | logError("Socket is not open"); |
Vanger | 30:1326b623919a | 543 | return -1; |
Vanger | 30:1326b623919a | 544 | } |
Vanger | 30:1326b623919a | 545 | |
Vanger | 30:1326b623919a | 546 | int bytesRead = 0; |
Vanger | 30:1326b623919a | 547 | |
Vanger | 30:1326b623919a | 548 | |
Vanger | 30:1326b623919a | 549 | if(timeout >= 0) { |
Vanger | 30:1326b623919a | 550 | bytesRead = io->read(data, max, static_cast<unsigned int>(timeout)); |
Vanger | 30:1326b623919a | 551 | } else { |
Vanger | 30:1326b623919a | 552 | bytesRead = io->read(data, max); |
Vanger | 30:1326b623919a | 553 | } |
Vanger | 30:1326b623919a | 554 | |
Vanger | 30:1326b623919a | 555 | //Scan for socket closed message |
Vanger | 30:1326b623919a | 556 | for(size_t i = 0; i < bytesRead; i++) { |
Vanger | 30:1326b623919a | 557 | if(data[i] == 'N') { |
Vanger | 30:1326b623919a | 558 | if(strstr(&data[i], "NO CARRIER")) { |
Vanger | 30:1326b623919a | 559 | logTrace("Found socket closed message. Checking validity"); |
Vanger | 30:1326b623919a | 560 | //Close socket and Cut Off End of Message |
Vanger | 30:1326b623919a | 561 | socketOpened = socketCheck(); //Verifies legitimacy of socket disconnect |
Vanger | 30:1326b623919a | 562 | if(socketOpened) { |
Vanger | 30:1326b623919a | 563 | logDebug("Socket still open"); |
Vanger | 30:1326b623919a | 564 | continue; |
Vanger | 30:1326b623919a | 565 | } else { |
Vanger | 30:1326b623919a | 566 | logDebug("Socket closed"); |
Vanger | 30:1326b623919a | 567 | data[i] = '\0'; |
Vanger | 30:1326b623919a | 568 | bytesRead = i; |
Vanger | 30:1326b623919a | 569 | break; |
Vanger | 30:1326b623919a | 570 | } |
Vanger | 30:1326b623919a | 571 | } |
Vanger | 30:1326b623919a | 572 | } |
Vanger | 30:1326b623919a | 573 | } |
Vanger | 30:1326b623919a | 574 | return bytesRead; |
Vanger | 26:2b769ed8de4f | 575 | } |
Vanger | 26:2b769ed8de4f | 576 | |
Vanger | 26:2b769ed8de4f | 577 | int EasyIP::write(const char* data, int length, int timeout) |
Vanger | 26:2b769ed8de4f | 578 | { |
Vanger | 30:1326b623919a | 579 | if(io == NULL) { |
Vanger | 30:1326b623919a | 580 | logError("MTSBufferedIO not set"); |
Vanger | 30:1326b623919a | 581 | return -1; |
Vanger | 30:1326b623919a | 582 | } |
Vanger | 30:1326b623919a | 583 | |
Vanger | 30:1326b623919a | 584 | if(!socketOpened) { |
Vanger | 30:1326b623919a | 585 | logError("Socket is not open"); |
Vanger | 30:1326b623919a | 586 | return -1; |
Vanger | 30:1326b623919a | 587 | } |
Vanger | 30:1326b623919a | 588 | |
Vanger | 30:1326b623919a | 589 | //In order to avoid allocating another buffer, capture indices of |
Vanger | 30:1326b623919a | 590 | //characters to escape during write |
Vanger | 30:1326b623919a | 591 | int specialWritten = 0; |
Vanger | 30:1326b623919a | 592 | std::vector<int> vSpecial; |
Vanger | 30:1326b623919a | 593 | if(socketCloseable) { |
Vanger | 30:1326b623919a | 594 | for(int i = 0; i < length; i++) { |
Vanger | 30:1326b623919a | 595 | if(data[i] == ETX || data[i] == DLE) { |
Vanger | 30:1326b623919a | 596 | //Push back index of special characters |
Vanger | 30:1326b623919a | 597 | vSpecial.push_back(i); |
Vanger | 30:1326b623919a | 598 | } |
Vanger | 30:1326b623919a | 599 | } |
Vanger | 30:1326b623919a | 600 | } |
Vanger | 30:1326b623919a | 601 | |
Vanger | 30:1326b623919a | 602 | int bytesWritten = 0; |
Vanger | 30:1326b623919a | 603 | if(timeout >= 0) { |
Vanger | 30:1326b623919a | 604 | Timer tmr; |
Vanger | 30:1326b623919a | 605 | tmr.start(); |
Vanger | 30:1326b623919a | 606 | do { |
Vanger | 30:1326b623919a | 607 | int available = io->writeable(); |
Vanger | 30:1326b623919a | 608 | if (available > 0) { |
Vanger | 30:1326b623919a | 609 | if(specialWritten < vSpecial.size()) { |
Vanger | 30:1326b623919a | 610 | //Check if current index is at a special character |
Vanger | 30:1326b623919a | 611 | if(bytesWritten == vSpecial[specialWritten]) { |
Vanger | 30:1326b623919a | 612 | if(available < 2) { |
Vanger | 30:1326b623919a | 613 | //Requires at least two bytes of space |
Vanger | 30:1326b623919a | 614 | wait(0.05); |
Vanger | 30:1326b623919a | 615 | continue; |
Vanger | 30:1326b623919a | 616 | } |
Vanger | 30:1326b623919a | 617 | //Ready to write special character |
Vanger | 30:1326b623919a | 618 | if(io->write(DLE)) { |
Vanger | 30:1326b623919a | 619 | specialWritten++; |
Vanger | 30:1326b623919a | 620 | if(io->write(data[bytesWritten])) { |
Vanger | 30:1326b623919a | 621 | bytesWritten++; |
Vanger | 30:1326b623919a | 622 | } |
Vanger | 30:1326b623919a | 623 | } else { |
Vanger | 30:1326b623919a | 624 | //Unable to write escape character, try again next round |
Vanger | 30:1326b623919a | 625 | wait(0.05); |
Vanger | 30:1326b623919a | 626 | } |
Vanger | 30:1326b623919a | 627 | } else { |
Vanger | 30:1326b623919a | 628 | //We want to write all the way up to the next special character |
Vanger | 30:1326b623919a | 629 | int relativeIndex = vSpecial[specialWritten] - bytesWritten; |
Vanger | 30:1326b623919a | 630 | int size = MIN(available, relativeIndex); |
Vanger | 30:1326b623919a | 631 | bytesWritten += io->write(&data[bytesWritten], size); |
Vanger | 30:1326b623919a | 632 | } |
Vanger | 30:1326b623919a | 633 | } else { |
Vanger | 30:1326b623919a | 634 | int size = MIN(available, length - bytesWritten); |
Vanger | 30:1326b623919a | 635 | bytesWritten += io->write(&data[bytesWritten], size); |
Vanger | 30:1326b623919a | 636 | } |
Vanger | 30:1326b623919a | 637 | } else { |
Vanger | 30:1326b623919a | 638 | wait(0.05); |
Vanger | 30:1326b623919a | 639 | } |
Vanger | 30:1326b623919a | 640 | } while (tmr.read_ms() <= timeout && bytesWritten < length); |
Vanger | 30:1326b623919a | 641 | } else { |
Vanger | 30:1326b623919a | 642 | for(int i = 0; i < vSpecial.size(); i++) { |
Vanger | 30:1326b623919a | 643 | //Write up to the special character, then write the special character |
Vanger | 30:1326b623919a | 644 | int size = vSpecial[i] - bytesWritten; |
Vanger | 30:1326b623919a | 645 | int currentWritten = io->write(&data[bytesWritten], size); |
Vanger | 30:1326b623919a | 646 | bytesWritten += currentWritten; |
Vanger | 30:1326b623919a | 647 | if(currentWritten != size) { |
Vanger | 30:1326b623919a | 648 | //Failed to write up to the special character. |
Vanger | 30:1326b623919a | 649 | return bytesWritten; |
Vanger | 30:1326b623919a | 650 | } |
Vanger | 30:1326b623919a | 651 | if(io->write(DLE) && io->write(data[bytesWritten])) { |
Vanger | 30:1326b623919a | 652 | bytesWritten++; |
Vanger | 30:1326b623919a | 653 | } else { |
Vanger | 30:1326b623919a | 654 | //Failed to write the special character. |
Vanger | 30:1326b623919a | 655 | return bytesWritten; |
Vanger | 30:1326b623919a | 656 | } |
Vanger | 30:1326b623919a | 657 | } |
Vanger | 30:1326b623919a | 658 | |
Vanger | 30:1326b623919a | 659 | bytesWritten = io->write(&data[bytesWritten], length - bytesWritten); |
Vanger | 30:1326b623919a | 660 | } |
Vanger | 30:1326b623919a | 661 | |
Vanger | 30:1326b623919a | 662 | return bytesWritten; |
Vanger | 26:2b769ed8de4f | 663 | } |
Vanger | 26:2b769ed8de4f | 664 | |
Vanger | 26:2b769ed8de4f | 665 | unsigned int EasyIP::readable() |
Vanger | 26:2b769ed8de4f | 666 | { |
Vanger | 30:1326b623919a | 667 | if(io == NULL) { |
Vanger | 30:1326b623919a | 668 | logWarning("MTSBufferedIO not set"); |
Vanger | 30:1326b623919a | 669 | return 0; |
Vanger | 30:1326b623919a | 670 | } |
Vanger | 30:1326b623919a | 671 | if(!socketOpened && !io->readable()) { |
Vanger | 30:1326b623919a | 672 | logWarning("Socket is not open"); |
Vanger | 30:1326b623919a | 673 | return 0; |
Vanger | 30:1326b623919a | 674 | } |
Vanger | 26:2b769ed8de4f | 675 | return io->readable(); |
Vanger | 26:2b769ed8de4f | 676 | } |
Vanger | 26:2b769ed8de4f | 677 | |
Vanger | 26:2b769ed8de4f | 678 | unsigned int EasyIP::writeable() |
Vanger | 26:2b769ed8de4f | 679 | { |
Vanger | 30:1326b623919a | 680 | if(io == NULL) { |
Vanger | 30:1326b623919a | 681 | logWarning("MTSBufferedIO not set"); |
Vanger | 30:1326b623919a | 682 | return 0; |
Vanger | 30:1326b623919a | 683 | } |
Vanger | 30:1326b623919a | 684 | if(!socketOpened) { |
Vanger | 30:1326b623919a | 685 | logWarning("Socket is not open"); |
Vanger | 30:1326b623919a | 686 | return 0; |
Vanger | 30:1326b623919a | 687 | } |
Vanger | 26:2b769ed8de4f | 688 | |
Vanger | 26:2b769ed8de4f | 689 | return io->writeable(); |
Vanger | 26:2b769ed8de4f | 690 | } |
Vanger | 26:2b769ed8de4f | 691 | |
Vanger | 26:2b769ed8de4f | 692 | bool EasyIP::setDeviceIP(std::string address) |
Vanger | 26:2b769ed8de4f | 693 | { |
Vanger | 26:2b769ed8de4f | 694 | if (address.compare("DHCP") == 0) { |
Vanger | 26:2b769ed8de4f | 695 | return true; |
Vanger | 26:2b769ed8de4f | 696 | } else { |
Vanger | 26:2b769ed8de4f | 697 | logWarning("Radio does not support static IPs, using DHCP.\n\r"); |
Vanger | 26:2b769ed8de4f | 698 | return false; |
Vanger | 26:2b769ed8de4f | 699 | } |
Vanger | 26:2b769ed8de4f | 700 | } |
Vanger | 26:2b769ed8de4f | 701 | |
Vanger | 26:2b769ed8de4f | 702 | Code EasyIP::setApn(const std::string& apn) |
Vanger | 26:2b769ed8de4f | 703 | { |
Vanger | 26:2b769ed8de4f | 704 | if (type == MTSMC_H5 || type == MTSMC_G3) { |
Vanger | 26:2b769ed8de4f | 705 | //Set IP,PPP,IPv6 |
Vanger | 26:2b769ed8de4f | 706 | Code code = sendBasicCommand("AT+CGDCONT=1,PPP," + apn, 1000); |
Vanger | 26:2b769ed8de4f | 707 | if (code != MTS_SUCCESS) { |
Vanger | 26:2b769ed8de4f | 708 | return code; |
Vanger | 26:2b769ed8de4f | 709 | } |
Vanger | 26:2b769ed8de4f | 710 | this->apn = apn; |
Vanger | 26:2b769ed8de4f | 711 | return code; //This will return MTS_SUCCESS |
Vanger | 26:2b769ed8de4f | 712 | } else { |
Vanger | 26:2b769ed8de4f | 713 | logInfo("CDMA radios don't need an APN"); |
Vanger | 26:2b769ed8de4f | 714 | return MTS_SUCCESS; |
Vanger | 26:2b769ed8de4f | 715 | } |
Vanger | 26:2b769ed8de4f | 716 | } |
Vanger | 27:ec44d5a9544f | 717 | |
Vanger | 26:2b769ed8de4f | 718 | void EasyIP::reset() |
Vanger | 26:2b769ed8de4f | 719 | { |
Vanger | 30:1326b623919a | 720 | disconnect(); |
Vanger | 30:1326b623919a | 721 | if(sendBasicCommand("AT#REBOOT", 10000) != MTS_SUCCESS) { |
Vanger | 30:1326b623919a | 722 | logError("Socket Modem did not accept RESET command\n\r"); |
Vanger | 30:1326b623919a | 723 | } else { |
Vanger | 30:1326b623919a | 724 | logWarning("Socket Modem is resetting, allow 30 seconds for it to come back\n\r"); |
Vanger | 30:1326b623919a | 725 | return; |
Vanger | 30:1326b623919a | 726 | } |
Vanger | 26:2b769ed8de4f | 727 | } |
Vanger | 26:2b769ed8de4f | 728 | |
Vanger | 26:2b769ed8de4f | 729 | std::string EasyIP::getDeviceIP() |
Vanger | 26:2b769ed8de4f | 730 | { |
Vanger | 26:2b769ed8de4f | 731 | return local_address; |
Vanger | 26:2b769ed8de4f | 732 | } |
Vanger | 26:2b769ed8de4f | 733 | |
Vanger | 26:2b769ed8de4f | 734 | //Turns off echo when it receives a 1, turns on when it receives anything else |
Vanger | 26:2b769ed8de4f | 735 | Code EasyIP::echo(bool state) |
Vanger | 26:2b769ed8de4f | 736 | { |
Vanger | 27:ec44d5a9544f | 737 | Code code; |
Vanger | 27:ec44d5a9544f | 738 | if (state) { |
Vanger | 27:ec44d5a9544f | 739 | code = sendBasicCommand("ATE0", 1000); |
Vanger | 27:ec44d5a9544f | 740 | echoMode = (code == MTS_SUCCESS) ? false : echoMode; |
Vanger | 27:ec44d5a9544f | 741 | } else { |
Vanger | 27:ec44d5a9544f | 742 | code = sendBasicCommand("ATE1", 1000); |
Vanger | 27:ec44d5a9544f | 743 | echoMode = (code == MTS_SUCCESS) ? true : echoMode; |
Vanger | 27:ec44d5a9544f | 744 | } |
Vanger | 27:ec44d5a9544f | 745 | return code; |
Vanger | 26:2b769ed8de4f | 746 | } |
Vanger | 26:2b769ed8de4f | 747 | |
Vanger | 26:2b769ed8de4f | 748 | bool EasyIP::ping(const std::string& address) |
Vanger | 26:2b769ed8de4f | 749 | { |
Vanger | 26:2b769ed8de4f | 750 | char buffer[256] = {0}; |
Vanger | 27:ec44d5a9544f | 751 | std::vector<std::string> parts; |
Vanger | 27:ec44d5a9544f | 752 | int pingsRec=0; |
Vanger | 27:ec44d5a9544f | 753 | int TTL=0; |
Vanger | 27:ec44d5a9544f | 754 | int Timeout=0; |
Vanger | 27:ec44d5a9544f | 755 | |
Vanger | 27:ec44d5a9544f | 756 | //Format parameters for sending to radio |
Vanger | 30:1326b623919a | 757 | sprintf(buffer, "AT#PING=%s,1,32,%d", address.c_str(), (PINGDELAY*10)); |
Vanger | 26:2b769ed8de4f | 758 | |
Vanger | 27:ec44d5a9544f | 759 | for(int pngs=0; pngs<PINGNUM; pngs++) { |
Vanger | 30:1326b623919a | 760 | std::string response = sendCommand(buffer, (PINGDELAY*1010)); //Send 1 ping |
Vanger | 28:f93d7b3f7c2e | 761 | if(response.empty()) { |
Vanger | 28:f93d7b3f7c2e | 762 | continue; //Skip current loop if send command fails |
Vanger | 28:f93d7b3f7c2e | 763 | } |
Vanger | 28:f93d7b3f7c2e | 764 | if(response.find("ERROR") != std::string::npos) { |
Vanger | 28:f93d7b3f7c2e | 765 | continue; //Skip current loop if send command fails |
Vanger | 28:f93d7b3f7c2e | 766 | } |
Vanger | 27:ec44d5a9544f | 767 | parts = Text::split(response, "\r\n"); |
Vanger | 28:f93d7b3f7c2e | 768 | if(parts.size() < 2) { |
Vanger | 28:f93d7b3f7c2e | 769 | continue; |
Vanger | 28:f93d7b3f7c2e | 770 | } |
Vanger | 27:ec44d5a9544f | 771 | parts = Text::split(parts[1], ","); |
Vanger | 28:f93d7b3f7c2e | 772 | if(parts.size() < 4) { |
Vanger | 28:f93d7b3f7c2e | 773 | continue; |
Vanger | 28:f93d7b3f7c2e | 774 | } |
Vanger | 27:ec44d5a9544f | 775 | //Parse TTL and Timeout values |
Vanger | 27:ec44d5a9544f | 776 | Timeout = std::atoi(parts[2].c_str()); |
Vanger | 27:ec44d5a9544f | 777 | TTL = std::atoi(parts[3].c_str()); |
Vanger | 27:ec44d5a9544f | 778 | |
Vanger | 27:ec44d5a9544f | 779 | if((Timeout < 600) && (TTL < 255)) { |
Vanger | 27:ec44d5a9544f | 780 | pingsRec++; |
Vanger | 27:ec44d5a9544f | 781 | } |
Vanger | 27:ec44d5a9544f | 782 | } //Success if less than 50% packet loss |
Vanger | 27:ec44d5a9544f | 783 | if( ((pingsRec/PINGNUM)>= 0.5) ) { |
Vanger | 27:ec44d5a9544f | 784 | return true; |
Vanger | 27:ec44d5a9544f | 785 | } |
Vanger | 26:2b769ed8de4f | 786 | return false; |
Vanger | 26:2b769ed8de4f | 787 | } |
Vanger | 26:2b769ed8de4f | 788 | |
Vanger | 27:ec44d5a9544f | 789 | //Pass 1 to enable socket closeable |
Vanger | 27:ec44d5a9544f | 790 | //Pass 0 to disable socket closeable |
Vanger | 26:2b769ed8de4f | 791 | Code EasyIP::setSocketCloseable(bool enabled) |
Vanger | 26:2b769ed8de4f | 792 | { |
Vanger | 30:1326b623919a | 793 | |
Vanger | 26:2b769ed8de4f | 794 | return MTS_SUCCESS; |
Vanger | 26:2b769ed8de4f | 795 | } |