Cellular library for MTS Socket Modem Arduino Shield devices from Multi-Tech Systems

Dependents:   mtsas mtsas mtsas mtsas

Committer:
Vanger
Date:
Wed Aug 13 21:15:05 2014 +0000
Revision:
59:5535f14e3cc4
Parent:
57:7eb2eb536d4a
Child:
60:250c17af30fb
Removed "alive" parsing option from sendCommand() under Cellular.cpp; Doubled timeout for AT#PING command under UIP.cpp; Made AT#SGACT command timeout longer (5s >> 15s) under EasyIP.cpp

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Vanger 26:2b769ed8de4f 1 #include "mbed.h"
Vanger 26:2b769ed8de4f 2 #include "EasyIP.h"
Vanger 26:2b769ed8de4f 3 #include "MTSText.h"
Vanger 26:2b769ed8de4f 4 #include "MTSLog.h"
Vanger 26:2b769ed8de4f 5 #include "CellUtils.h"
Vanger 26:2b769ed8de4f 6
Vanger 26:2b769ed8de4f 7 using namespace mts;
Vanger 26:2b769ed8de4f 8
Vanger 26:2b769ed8de4f 9 EasyIP::EasyIP(Radio type)
Vanger 26:2b769ed8de4f 10 {
Vanger 26:2b769ed8de4f 11 this->type = type;
Vanger 26:2b769ed8de4f 12 io = NULL;
Vanger 26:2b769ed8de4f 13 dcd = NULL;
Vanger 26:2b769ed8de4f 14 dtr = NULL;
Vanger 26:2b769ed8de4f 15 resetLine = NULL;
Vanger 26:2b769ed8de4f 16 echoMode = true;
Vanger 26:2b769ed8de4f 17 pppConnected = false;
Vanger 26:2b769ed8de4f 18 socketMode = TCP;
Vanger 26:2b769ed8de4f 19 socketOpened = false;
Vanger 26:2b769ed8de4f 20 socketCloseable = true;
Vanger 26:2b769ed8de4f 21 local_port = 0;
Vanger 26:2b769ed8de4f 22 local_address = "";
Vanger 26:2b769ed8de4f 23 host_port = 0;
Vanger 26:2b769ed8de4f 24 }
Vanger 26:2b769ed8de4f 25
Vanger 26:2b769ed8de4f 26 EasyIP::~EasyIP()
Vanger 26:2b769ed8de4f 27 {
Vanger 26:2b769ed8de4f 28 if (dtr != NULL) {
Vanger 26:2b769ed8de4f 29 dtr->write(1);
Vanger 26:2b769ed8de4f 30 }
Vanger 26:2b769ed8de4f 31
Vanger 26:2b769ed8de4f 32 delete dcd;
Vanger 26:2b769ed8de4f 33 delete dtr;
Vanger 26:2b769ed8de4f 34 delete resetLine;
Vanger 26:2b769ed8de4f 35 }
Vanger 26:2b769ed8de4f 36
Vanger 26:2b769ed8de4f 37 //Initializes the MTS IO Buffer
Vanger 26:2b769ed8de4f 38 bool EasyIP::init(MTSBufferedIO* io)
Vanger 26:2b769ed8de4f 39 {
Vanger 26:2b769ed8de4f 40 if (! Cellular::init(io)) {
Vanger 26:2b769ed8de4f 41 return false;
Vanger 26:2b769ed8de4f 42 }
Vanger 26:2b769ed8de4f 43
Vanger 26:2b769ed8de4f 44 logDebug("radio type: %s", Cellular::getRadioNames(type).c_str());
Vanger 49:1fc51c53cebf 45 //Turns on the HW flow control
Vanger 56:43205bd2752a 46 if(sendBasicCommand("AT+IFC=2,2", 2000) != MTS_SUCCESS) {
Vanger 52:2cb58398a4f9 47 logWarning("Failed to enable serial flow control");
Vanger 35:257eb41405e1 48 }
Vanger 26:2b769ed8de4f 49 return true;
Vanger 26:2b769ed8de4f 50 }
Vanger 26:2b769ed8de4f 51
Vanger 26:2b769ed8de4f 52 bool EasyIP::connect()
Vanger 26:2b769ed8de4f 53 {
Vanger 33:3b6f3904dde0 54 //Check if APN is not set, if it is not, connect will not work.
Vanger 29:edc613ed3f2e 55 if (type == MTSMC_H5_IP || type == MTSMC_H5 || type == MTSMC_G3) {
Vanger 29:edc613ed3f2e 56 if(apn.size() == 0) {
Vanger 29:edc613ed3f2e 57 logDebug("APN is not set");
Vanger 29:edc613ed3f2e 58 return false;
Vanger 29:edc613ed3f2e 59 }
Vanger 29:edc613ed3f2e 60 }
Vanger 29:edc613ed3f2e 61
Vanger 26:2b769ed8de4f 62 //Check if socket is open
Vanger 26:2b769ed8de4f 63 if(socketOpened) {
Vanger 26:2b769ed8de4f 64 return true;
Vanger 26:2b769ed8de4f 65 }
Vanger 26:2b769ed8de4f 66
Vanger 26:2b769ed8de4f 67 //Check if already connected
Vanger 26:2b769ed8de4f 68 if(isConnected()) {
Vanger 26:2b769ed8de4f 69 return true;
Vanger 26:2b769ed8de4f 70 }
Vanger 51:ffc556ba33f7 71
Vanger 26:2b769ed8de4f 72 Timer tmr;
Vanger 26:2b769ed8de4f 73 //Check Registration: AT+CREG? == 0,1
Vanger 26:2b769ed8de4f 74 tmr.start();
Vanger 26:2b769ed8de4f 75 do {
Vanger 26:2b769ed8de4f 76 Registration registration = getRegistration();
Vanger 56:43205bd2752a 77 if(registration != REGISTERED && registration != ROAMING) {
Vanger 26:2b769ed8de4f 78 logTrace("Not Registered [%d] ... waiting", (int)registration);
Vanger 26:2b769ed8de4f 79 wait(1);
Vanger 26:2b769ed8de4f 80 } else {
Vanger 26:2b769ed8de4f 81 break;
Vanger 26:2b769ed8de4f 82 }
Vanger 30:1326b623919a 83 } while(tmr.read() < 30);
Vanger 51:ffc556ba33f7 84
Vanger 26:2b769ed8de4f 85 //Check RSSI: AT+CSQ
Vanger 26:2b769ed8de4f 86 tmr.reset();
Vanger 26:2b769ed8de4f 87 do {
Vanger 26:2b769ed8de4f 88 int rssi = getSignalStrength();
Vanger 26:2b769ed8de4f 89 logDebug("Signal strength: %d", rssi);
Vanger 51:ffc556ba33f7 90 if(rssi == 99 || rssi == -1) {
Vanger 26:2b769ed8de4f 91 logTrace("No Signal ... waiting");
Vanger 26:2b769ed8de4f 92 wait(1);
Vanger 26:2b769ed8de4f 93 } else {
Vanger 26:2b769ed8de4f 94 break;
Vanger 26:2b769ed8de4f 95 }
Vanger 26:2b769ed8de4f 96 } while(tmr.read() < 30);
Vanger 26:2b769ed8de4f 97
Vanger 52:2cb58398a4f9 98 //Make PPP connection
Vanger 26:2b769ed8de4f 99 if (type == MTSMC_H5 || type == MTSMC_G3) {
Vanger 26:2b769ed8de4f 100 logDebug("Making PPP Connection Attempt. APN[%s]", apn.c_str());
Vanger 26:2b769ed8de4f 101 } else {
Vanger 26:2b769ed8de4f 102 logDebug("Making PPP Connection Attempt");
Vanger 26:2b769ed8de4f 103 }
Vanger 59:5535f14e3cc4 104 std::string pppResult = sendCommand("AT#SGACT=1,1", 15000);
Vanger 30:1326b623919a 105 std::vector<std::string> parts;
Vanger 26:2b769ed8de4f 106 if(pppResult.find("OK") != std::string::npos) {
Vanger 30:1326b623919a 107 parts = Text::split(pppResult, "\r\n");
Vanger 26:2b769ed8de4f 108 if(parts.size() >= 2) {
Vanger 26:2b769ed8de4f 109 parts = Text::split(parts[1], " ");
Vanger 26:2b769ed8de4f 110 local_address = parts[1];
Vanger 26:2b769ed8de4f 111 }
Vanger 26:2b769ed8de4f 112 logInfo("PPP Connection Established: IP[%s]", local_address.c_str());
Vanger 26:2b769ed8de4f 113 pppConnected = true;
Vanger 26:2b769ed8de4f 114
Vanger 26:2b769ed8de4f 115 } else {
Vanger 30:1326b623919a 116 pppResult = sendCommand("AT#SGACT?", 2000);
Vanger 52:2cb58398a4f9 117 if(pppResult.find("1,1") != std::string::npos) {
Vanger 52:2cb58398a4f9 118 logDebug("Radio is already connected");
Vanger 52:2cb58398a4f9 119 pppConnected = true;
Vanger 30:1326b623919a 120 } else {
Vanger 52:2cb58398a4f9 121 logError("PPP connection attempt failed");
Vanger 52:2cb58398a4f9 122 pppConnected = false;
Vanger 30:1326b623919a 123 }
Vanger 26:2b769ed8de4f 124 }
Vanger 26:2b769ed8de4f 125
Vanger 26:2b769ed8de4f 126 return pppConnected;
Vanger 26:2b769ed8de4f 127 }
Vanger 26:2b769ed8de4f 128
Vanger 26:2b769ed8de4f 129 void EasyIP::disconnect()
Vanger 26:2b769ed8de4f 130 {
Vanger 52:2cb58398a4f9 131 //AT#SGACT=1,0: Close PPP connection
Vanger 52:2cb58398a4f9 132 logDebug("Closing PPP Connection");
Vanger 35:257eb41405e1 133 std::string result;
Vanger 35:257eb41405e1 134 Timer tmr;
Vanger 52:2cb58398a4f9 135
Vanger 52:2cb58398a4f9 136 if(socketOpened) {
Vanger 52:2cb58398a4f9 137 close();
Vanger 52:2cb58398a4f9 138 }
Vanger 52:2cb58398a4f9 139
Vanger 26:2b769ed8de4f 140 //Sends AT#SGACT=1,0 command
Vanger 54:a6c738bfc391 141 for (int y = 0; y < 5; y++) {
Vanger 54:a6c738bfc391 142 Code code = sendBasicCommand("AT#SGACT=1,0", 1000);
Vanger 54:a6c738bfc391 143 if (code == MTS_SUCCESS) {
Vanger 54:a6c738bfc391 144 logDebug("Successfully closed PPP Connection");
Vanger 54:a6c738bfc391 145 break;
Vanger 54:a6c738bfc391 146 }
Vanger 30:1326b623919a 147 }
Vanger 35:257eb41405e1 148
Vanger 52:2cb58398a4f9 149 /* Ensure PPP link is down, else ping commands will put radio in unknown state
Vanger 52:2cb58398a4f9 150 * (Link is not immediate in disconnection, even though OK is returned)
Vanger 51:ffc556ba33f7 151 */
Vanger 35:257eb41405e1 152 tmr.start();
Vanger 35:257eb41405e1 153 while(tmr.read() < 30) {
Vanger 35:257eb41405e1 154 result = sendCommand("AT#SGACT?", 1000);
Vanger 35:257eb41405e1 155 if(result.find("1,0") != std::string::npos) {
Vanger 35:257eb41405e1 156 break;
Vanger 35:257eb41405e1 157 } else if(result.find("ERROR") != std::string::npos) {
Vanger 35:257eb41405e1 158 break;
Vanger 35:257eb41405e1 159 } else {
Vanger 35:257eb41405e1 160 wait(1);
Vanger 35:257eb41405e1 161 }
Vanger 35:257eb41405e1 162 }
Vanger 35:257eb41405e1 163
Vanger 52:2cb58398a4f9 164 pppConnected = false;
Vanger 30:1326b623919a 165 return;
Vanger 26:2b769ed8de4f 166 }
Vanger 27:ec44d5a9544f 167
Vanger 26:2b769ed8de4f 168 bool EasyIP::isConnected()
Vanger 26:2b769ed8de4f 169 {
Vanger 52:2cb58398a4f9 170 enum RadioState {IDLE, CONNECTING, CONNECTED, DISCONNECTED};
Vanger 51:ffc556ba33f7 171 //state flags for various connection components
Vanger 30:1326b623919a 172 bool signal = false, regist = false, active = false;
Vanger 26:2b769ed8de4f 173
Vanger 29:edc613ed3f2e 174 //1) Check if APN was set if we're on an HSPA radio
Vanger 29:edc613ed3f2e 175 if (type == MTSMC_H5_IP || type == MTSMC_H5 || type == MTSMC_G3) {
Vanger 29:edc613ed3f2e 176 if(apn.size() == 0) {
Vanger 29:edc613ed3f2e 177 logDebug("APN is not set");
Vanger 29:edc613ed3f2e 178 return false;
Vanger 29:edc613ed3f2e 179 }
Vanger 29:edc613ed3f2e 180 }
Vanger 29:edc613ed3f2e 181
Vanger 29:edc613ed3f2e 182 //2) Check that we do not have a live connection up
Vanger 52:2cb58398a4f9 183 if (socketOpened) {
Vanger 29:edc613ed3f2e 184 logDebug("Socket is opened");
Vanger 29:edc613ed3f2e 185 return true;
Vanger 29:edc613ed3f2e 186 }
Vanger 29:edc613ed3f2e 187
Vanger 29:edc613ed3f2e 188 //3) Query the radio
Vanger 52:2cb58398a4f9 189 int rssi = getSignalStrength();
Vanger 52:2cb58398a4f9 190 if (rssi == 99 || rssi == -1) {
Vanger 52:2cb58398a4f9 191 //Signal strength is nonexistent
Vanger 29:edc613ed3f2e 192 signal = false;
Vanger 29:edc613ed3f2e 193 } else {
Vanger 52:2cb58398a4f9 194 signal = true;
Vanger 29:edc613ed3f2e 195 }
Vanger 27:ec44d5a9544f 196
Vanger 52:2cb58398a4f9 197 Registration creg = getRegistration();
Vanger 52:2cb58398a4f9 198 if (creg == REGISTERED) {
Vanger 52:2cb58398a4f9 199 regist = true;
Vanger 29:edc613ed3f2e 200 } else {
Vanger 52:2cb58398a4f9 201 regist = false;
Vanger 29:edc613ed3f2e 202 }
Vanger 27:ec44d5a9544f 203
Vanger 56:43205bd2752a 204 string reply = sendCommand("AT#SGACT?", 1000);
Vanger 52:2cb58398a4f9 205 if (reply.find("1,1") != std::string::npos) {
Vanger 52:2cb58398a4f9 206 active = true;
Vanger 29:edc613ed3f2e 207 } else {
Vanger 52:2cb58398a4f9 208 active = false;
Vanger 29:edc613ed3f2e 209 }
Vanger 52:2cb58398a4f9 210
Vanger 52:2cb58398a4f9 211 RadioState state;
Vanger 52:2cb58398a4f9 212 bool ppp = pppConnected;
Vanger 52:2cb58398a4f9 213 if (signal && regist && active) {
Vanger 52:2cb58398a4f9 214 state = CONNECTED;
Vanger 52:2cb58398a4f9 215 pppConnected = true;
Vanger 52:2cb58398a4f9 216 } else if (signal && !regist && !active) {
Vanger 52:2cb58398a4f9 217 state = IDLE;
Vanger 52:2cb58398a4f9 218 pppConnected = false;
Vanger 52:2cb58398a4f9 219 } else if (active) {
Vanger 52:2cb58398a4f9 220 state = CONNECTING;
Vanger 52:2cb58398a4f9 221 } else {
Vanger 52:2cb58398a4f9 222 state = DISCONNECTED;
Vanger 30:1326b623919a 223 pppConnected = false;
Vanger 30:1326b623919a 224 }
Vanger 35:257eb41405e1 225
Vanger 52:2cb58398a4f9 226 if (!ppp && state == CONNECTED) {
Vanger 52:2cb58398a4f9 227 logWarning("Internal PPP state tracking differs from radio (DISCONNECTED:CONNECTED)");
Vanger 52:2cb58398a4f9 228 } else if (ppp && state != CONNECTED) {
Vanger 56:43205bd2752a 229 string stateStr;
Vanger 56:43205bd2752a 230 switch (state) {
Vanger 56:43205bd2752a 231 case IDLE:
Vanger 56:43205bd2752a 232 stateStr = "IDLE";
Vanger 56:43205bd2752a 233 break;
Vanger 56:43205bd2752a 234 case CONNECTING:
Vanger 56:43205bd2752a 235 stateStr = "CONNECTING";
Vanger 56:43205bd2752a 236 break;
Vanger 56:43205bd2752a 237 case DISCONNECTED:
Vanger 56:43205bd2752a 238 stateStr = "DISCONNECTED";
Vanger 56:43205bd2752a 239 break;
Vanger 56:43205bd2752a 240 case CONNECTED:
Vanger 56:43205bd2752a 241 stateStr = "CONNECTED";
Vanger 56:43205bd2752a 242 break;
Vanger 56:43205bd2752a 243 default:
Vanger 56:43205bd2752a 244 stateStr = "UKNOWN";
Vanger 56:43205bd2752a 245 break;
Vanger 56:43205bd2752a 246 }
Vanger 56:43205bd2752a 247 logWarning("Internal PPP state tracking differs from radio (CONNECTED:%s)", stateStr.c_str());
Vanger 29:edc613ed3f2e 248 }
Vanger 52:2cb58398a4f9 249
Vanger 26:2b769ed8de4f 250 return pppConnected;
Vanger 26:2b769ed8de4f 251 }
Vanger 30:1326b623919a 252
Vanger 33:3b6f3904dde0 253 void EasyIP::reset()
Vanger 33:3b6f3904dde0 254 {
Vanger 33:3b6f3904dde0 255 disconnect();
Vanger 52:2cb58398a4f9 256
Vanger 33:3b6f3904dde0 257 if(sendBasicCommand("AT#REBOOT", 10000) != MTS_SUCCESS) {
Vanger 52:2cb58398a4f9 258 logError("Socket Modem did not accept RESET command");
Vanger 33:3b6f3904dde0 259 } else {
Vanger 52:2cb58398a4f9 260 logWarning("Socket Modem is resetting, allow 30 seconds for it to come back");
Vanger 33:3b6f3904dde0 261 return;
Vanger 33:3b6f3904dde0 262 }
Vanger 33:3b6f3904dde0 263 }
Vanger 33:3b6f3904dde0 264
Vanger 26:2b769ed8de4f 265 bool EasyIP::open(const std::string& address, unsigned int port, Mode mode)
Vanger 26:2b769ed8de4f 266 {
Vanger 30:1326b623919a 267 char sOpenSocketCmd[256] = {0}; //String for AT command
Vanger 30:1326b623919a 268 std::string sMode = "";
Vanger 31:529db15abda7 269 int typeSocket = 0;
Vanger 31:529db15abda7 270 int closeType = 0;
Vanger 30:1326b623919a 271
Vanger 30:1326b623919a 272 //1) Check that we do not have a live connection up
Vanger 30:1326b623919a 273 if(socketOpened) {
Vanger 30:1326b623919a 274 //Check that the address, port, and mode match
Vanger 30:1326b623919a 275 if(host_address != address || host_port != port || socketMode != mode) {
Vanger 30:1326b623919a 276 if(socketMode == TCP) {
Vanger 30:1326b623919a 277 logError("TCP socket already opened [%s:%d]", host_address.c_str(), host_port);
Vanger 30:1326b623919a 278 } else {
Vanger 30:1326b623919a 279 logError("UDP socket already opened [%s:%d]", host_address.c_str(), host_port);
Vanger 30:1326b623919a 280 }
Vanger 30:1326b623919a 281 return false;
Vanger 30:1326b623919a 282 }
Vanger 30:1326b623919a 283
Vanger 30:1326b623919a 284 logDebug("Socket already opened");
Vanger 30:1326b623919a 285 return true;
Vanger 30:1326b623919a 286 }
Vanger 30:1326b623919a 287
Vanger 30:1326b623919a 288 //2) Check Parameters
Vanger 30:1326b623919a 289 if(port > 65535) {
Vanger 30:1326b623919a 290 logError("port out of range (0-65535)");
Vanger 30:1326b623919a 291 return false;
Vanger 30:1326b623919a 292 }
Vanger 41:8b9b5098696f 293
Vanger 41:8b9b5098696f 294 if(type == MTSMC_EV3) {
Vanger 41:8b9b5098696f 295 if(!local_port) {
Vanger 41:8b9b5098696f 296 logDebug("Local port set to 1, port 0 not supported for MTSMC_EV3");
Vanger 41:8b9b5098696f 297 local_port = 1;
Vanger 41:8b9b5098696f 298 }
Vanger 41:8b9b5098696f 299 }
Vanger 30:1326b623919a 300
Vanger 30:1326b623919a 301 //3) Check PPP connection
Vanger 30:1326b623919a 302 if(!isConnected()) {
Vanger 30:1326b623919a 303 logError("PPP not established. Attempting to connect");
Vanger 30:1326b623919a 304 if(!connect()) {
Vanger 30:1326b623919a 305 logError("PPP connection failed");
Vanger 30:1326b623919a 306 return false;
Vanger 30:1326b623919a 307 } else {
Vanger 30:1326b623919a 308 logDebug("PPP connection established");
Vanger 30:1326b623919a 309 }
Vanger 30:1326b623919a 310 }
Vanger 30:1326b623919a 311
Vanger 56:43205bd2752a 312 //4) Set escape sequence to not be transmitted through socket
Vanger 30:1326b623919a 313 if(sendBasicCommand("AT#SKIPESC=1", 2000) != MTS_SUCCESS) {
Vanger 30:1326b623919a 314 logWarning("Failed to disable escape sequence transmission on data mode suspension");
Vanger 30:1326b623919a 315 }
Vanger 30:1326b623919a 316
Vanger 30:1326b623919a 317 if(mode == TCP) {
Vanger 30:1326b623919a 318 typeSocket = 0;
Vanger 30:1326b623919a 319 sMode = "TCP";
Vanger 30:1326b623919a 320 } else {
Vanger 30:1326b623919a 321 typeSocket = 1;
Vanger 30:1326b623919a 322 sMode = "UDP";
Vanger 30:1326b623919a 323 }
Vanger 31:529db15abda7 324
Vanger 31:529db15abda7 325 if(socketCloseable) {
Vanger 31:529db15abda7 326 closeType = 0;
Vanger 31:529db15abda7 327 } else {
Vanger 31:529db15abda7 328 closeType = 255;
Vanger 31:529db15abda7 329 }
Vanger 31:529db15abda7 330 //5) Open Socket
Vanger 31:529db15abda7 331 sprintf(sOpenSocketCmd, "AT#SD=1,%d,%d,%s,%d,%d,0", typeSocket, port, address.c_str(),closeType , local_port);
Vanger 38:b2088faa8bfd 332 std::string response = sendCommand(sOpenSocketCmd, 60000);
Vanger 30:1326b623919a 333
Vanger 30:1326b623919a 334 if(response.find("CONNECT") != std::string::npos) {
Vanger 30:1326b623919a 335 host_address = address;
Vanger 30:1326b623919a 336 host_port = port;
Vanger 30:1326b623919a 337
Vanger 30:1326b623919a 338 logInfo("Opened %s Socket [%s:%d]", sMode.c_str(), address.c_str(), port);
Vanger 30:1326b623919a 339 socketOpened = true;
Vanger 30:1326b623919a 340 socketMode = mode;
Vanger 30:1326b623919a 341 } else {
Vanger 30:1326b623919a 342 logWarning("Unable to open %s Socket [%s:%d]", sMode.c_str(), address.c_str(), port);
Vanger 30:1326b623919a 343 socketOpened = false;
Vanger 30:1326b623919a 344 }
Vanger 30:1326b623919a 345
Vanger 26:2b769ed8de4f 346 return socketOpened;
Vanger 26:2b769ed8de4f 347 }
Vanger 27:ec44d5a9544f 348
Vanger 26:2b769ed8de4f 349 bool EasyIP::close()
Vanger 26:2b769ed8de4f 350 {
Vanger 26:2b769ed8de4f 351
Vanger 30:1326b623919a 352 if(io == NULL) {
Vanger 30:1326b623919a 353 logError("MTSBufferedIO not set");
Vanger 30:1326b623919a 354 return false;
Vanger 30:1326b623919a 355 }
Vanger 30:1326b623919a 356
Vanger 30:1326b623919a 357 if(!socketOpened) {
Vanger 30:1326b623919a 358 logWarning("Socket close() called, but socket was not open");
Vanger 30:1326b623919a 359 return true;
Vanger 30:1326b623919a 360 }
Vanger 30:1326b623919a 361
Vanger 30:1326b623919a 362 if(!socketCloseable) {
Vanger 30:1326b623919a 363 logError("Socket is not closeable");
Vanger 30:1326b623919a 364 return false;
Vanger 30:1326b623919a 365 }
Vanger 30:1326b623919a 366
Vanger 30:1326b623919a 367 if(!sendEscapeCommand()) {
Vanger 30:1326b623919a 368 logError("Failed to exit online mode");
Vanger 30:1326b623919a 369 return false;
Vanger 30:1326b623919a 370 } else {
Vanger 30:1326b623919a 371 socketOpened = false;
Vanger 30:1326b623919a 372 }
Vanger 30:1326b623919a 373
Vanger 54:a6c738bfc391 374 if (sendBasicCommand("AT#SH=1", 2000) != MTS_SUCCESS) {
Vanger 30:1326b623919a 375 logDebug("Failed to close socket connection");
Vanger 30:1326b623919a 376 }
Vanger 30:1326b623919a 377
Vanger 30:1326b623919a 378 Timer tmr;
Vanger 30:1326b623919a 379 int counter = 0;
Vanger 30:1326b623919a 380 char tmp[256];
Vanger 30:1326b623919a 381 tmr.start();
Vanger 30:1326b623919a 382 do {
Vanger 30:1326b623919a 383 if(socketOpened == false) {
Vanger 30:1326b623919a 384 break;
Vanger 30:1326b623919a 385 }
Vanger 30:1326b623919a 386 read(tmp, 256, 1000);
Vanger 30:1326b623919a 387 } while(counter++ < 10);
Vanger 30:1326b623919a 388
Vanger 30:1326b623919a 389 io->rxClear();
Vanger 30:1326b623919a 390 io->txClear();
Vanger 30:1326b623919a 391
Vanger 30:1326b623919a 392 return !socketOpened;
Vanger 26:2b769ed8de4f 393 }
Vanger 26:2b769ed8de4f 394
Vanger 26:2b769ed8de4f 395 int EasyIP::read(char* data, int max, int timeout)
Vanger 26:2b769ed8de4f 396 {
Vanger 30:1326b623919a 397 if(io == NULL) {
Vanger 30:1326b623919a 398 logError("MTSBufferedIO not set");
Vanger 30:1326b623919a 399 return -1;
Vanger 30:1326b623919a 400 }
Vanger 30:1326b623919a 401
Vanger 30:1326b623919a 402 //Check that nothing is in the rx buffer
Vanger 30:1326b623919a 403 if(!socketOpened && !io->readable()) {
Vanger 30:1326b623919a 404 logError("Socket is not open");
Vanger 30:1326b623919a 405 return -1;
Vanger 30:1326b623919a 406 }
Vanger 30:1326b623919a 407
Vanger 30:1326b623919a 408 int bytesRead = 0;
Vanger 30:1326b623919a 409
Vanger 30:1326b623919a 410
Vanger 30:1326b623919a 411 if(timeout >= 0) {
Vanger 30:1326b623919a 412 bytesRead = io->read(data, max, static_cast<unsigned int>(timeout));
Vanger 30:1326b623919a 413 } else {
Vanger 30:1326b623919a 414 bytesRead = io->read(data, max);
Vanger 30:1326b623919a 415 }
Vanger 35:257eb41405e1 416
Vanger 35:257eb41405e1 417 //Scan for socket closed message
Vanger 31:529db15abda7 418 if(bytesRead > 0 && socketCloseable) {
Vanger 35:257eb41405e1 419 for(int i = 0; i < bytesRead; i++) {
Vanger 31:529db15abda7 420 if(data[i] == 'N') {
Vanger 31:529db15abda7 421 if(strstr(&data[i], "NO CARRIER")) {
Vanger 31:529db15abda7 422 logTrace("Found socket closed message. Checking validity");
Vanger 31:529db15abda7 423 //Close socket and Cut Off End of Message
Vanger 31:529db15abda7 424 socketOpened = socketCheck(); //Verifies legitimacy of socket disconnect
Vanger 31:529db15abda7 425 if(socketOpened) {
Vanger 31:529db15abda7 426 logDebug("Socket still open");
Vanger 31:529db15abda7 427 continue;
Vanger 31:529db15abda7 428 } else {
Vanger 31:529db15abda7 429 logDebug("Socket closed");
Vanger 31:529db15abda7 430 data[i] = '\0';
Vanger 31:529db15abda7 431 bytesRead = i;
Vanger 31:529db15abda7 432 break;
Vanger 31:529db15abda7 433 }
Vanger 30:1326b623919a 434 }
Vanger 30:1326b623919a 435 }
Vanger 30:1326b623919a 436 }
Vanger 30:1326b623919a 437 }
Vanger 30:1326b623919a 438 return bytesRead;
Vanger 26:2b769ed8de4f 439 }
Vanger 26:2b769ed8de4f 440
Vanger 26:2b769ed8de4f 441 int EasyIP::write(const char* data, int length, int timeout)
Vanger 26:2b769ed8de4f 442 {
Vanger 30:1326b623919a 443 if(io == NULL) {
Vanger 30:1326b623919a 444 logError("MTSBufferedIO not set");
Vanger 30:1326b623919a 445 return -1;
Vanger 30:1326b623919a 446 }
Vanger 30:1326b623919a 447
Vanger 30:1326b623919a 448 if(!socketOpened) {
Vanger 30:1326b623919a 449 logError("Socket is not open");
Vanger 30:1326b623919a 450 return -1;
Vanger 30:1326b623919a 451 }
Vanger 30:1326b623919a 452
Vanger 30:1326b623919a 453 int bytesWritten = 0;
Vanger 31:529db15abda7 454 int size = length;
Vanger 31:529db15abda7 455 int failedWrites = 0;
Vanger 30:1326b623919a 456 if(timeout >= 0) {
Vanger 30:1326b623919a 457 Timer tmr;
Vanger 30:1326b623919a 458 tmr.start();
Vanger 30:1326b623919a 459 do {
Vanger 30:1326b623919a 460 int available = io->writeable();
Vanger 30:1326b623919a 461 if (available > 0) {
Vanger 31:529db15abda7 462 size = MIN(available, length - bytesWritten);
Vanger 31:529db15abda7 463 bytesWritten += io->write(&data[bytesWritten], size);
Vanger 30:1326b623919a 464 } else {
Vanger 30:1326b623919a 465 wait(0.05);
Vanger 30:1326b623919a 466 }
Vanger 30:1326b623919a 467 } while (tmr.read_ms() <= timeout && bytesWritten < length);
Vanger 30:1326b623919a 468 } else {
Vanger 31:529db15abda7 469 //If timeout is -1:
Vanger 31:529db15abda7 470 do {
Vanger 31:529db15abda7 471 int available = io->writeable();
Vanger 31:529db15abda7 472 if(available > 0) {
Vanger 31:529db15abda7 473 size = MIN(available, length - bytesWritten);
Vanger 31:529db15abda7 474 int currentWritten = io->write(&data[bytesWritten], size);
Vanger 31:529db15abda7 475 bytesWritten += currentWritten;
Vanger 31:529db15abda7 476 if(!currentWritten) {
Vanger 31:529db15abda7 477 failedWrites++;
Vanger 31:529db15abda7 478 }
Vanger 31:529db15abda7 479 if(failedWrites > 10) {
Vanger 31:529db15abda7 480 logError("Couldn't write any characters");
Vanger 31:529db15abda7 481 return bytesWritten;
Vanger 31:529db15abda7 482 }
Vanger 31:529db15abda7 483 } else {
Vanger 31:529db15abda7 484 wait(0.05);
Vanger 30:1326b623919a 485 }
Vanger 31:529db15abda7 486 } while (bytesWritten < length);
Vanger 30:1326b623919a 487 }
Vanger 30:1326b623919a 488 return bytesWritten;
Vanger 26:2b769ed8de4f 489 }
Vanger 26:2b769ed8de4f 490
Vanger 26:2b769ed8de4f 491 Code EasyIP::setApn(const std::string& apn)
Vanger 26:2b769ed8de4f 492 {
Vanger 26:2b769ed8de4f 493 if (type == MTSMC_H5 || type == MTSMC_G3) {
Vanger 56:43205bd2752a 494 //CGDCONT has options: IP,PPP,IPv6
Vanger 56:43205bd2752a 495 Code code = sendBasicCommand("AT+CGDCONT=1,IP," + apn, 1000);
Vanger 26:2b769ed8de4f 496 if (code != MTS_SUCCESS) {
Vanger 56:43205bd2752a 497 return code;
Vanger 26:2b769ed8de4f 498 }
Vanger 26:2b769ed8de4f 499 this->apn = apn;
Vanger 56:43205bd2752a 500 return code;
Vanger 26:2b769ed8de4f 501 } else {
Vanger 26:2b769ed8de4f 502 logInfo("CDMA radios don't need an APN");
Vanger 26:2b769ed8de4f 503 return MTS_SUCCESS;
Vanger 26:2b769ed8de4f 504 }
Vanger 26:2b769ed8de4f 505 }
Vanger 27:ec44d5a9544f 506
Vanger 26:2b769ed8de4f 507 bool EasyIP::ping(const std::string& address)
Vanger 26:2b769ed8de4f 508 {
Vanger 26:2b769ed8de4f 509 char buffer[256] = {0};
Vanger 27:ec44d5a9544f 510 std::vector<std::string> parts;
Vanger 27:ec44d5a9544f 511 int TTL=0;
Vanger 27:ec44d5a9544f 512 int Timeout=0;
Vanger 27:ec44d5a9544f 513
Vanger 27:ec44d5a9544f 514 //Format parameters for sending to radio
Vanger 30:1326b623919a 515 sprintf(buffer, "AT#PING=%s,1,32,%d", address.c_str(), (PINGDELAY*10));
Vanger 26:2b769ed8de4f 516
Vanger 27:ec44d5a9544f 517 for(int pngs=0; pngs<PINGNUM; pngs++) {
Vanger 35:257eb41405e1 518 std::string response = sendCommand(buffer, (PINGDELAY*2000)); //Send 1 ping
Vanger 52:2cb58398a4f9 519 if(response.empty() || response.find("ERROR") != std::string::npos) {
Vanger 28:f93d7b3f7c2e 520 continue; //Skip current loop if send command fails
Vanger 28:f93d7b3f7c2e 521 }
Vanger 27:ec44d5a9544f 522 parts = Text::split(response, "\r\n");
Vanger 28:f93d7b3f7c2e 523 if(parts.size() < 2) {
Vanger 28:f93d7b3f7c2e 524 continue;
Vanger 28:f93d7b3f7c2e 525 }
Vanger 27:ec44d5a9544f 526 parts = Text::split(parts[1], ",");
Vanger 28:f93d7b3f7c2e 527 if(parts.size() < 4) {
Vanger 28:f93d7b3f7c2e 528 continue;
Vanger 28:f93d7b3f7c2e 529 }
Vanger 27:ec44d5a9544f 530 //Parse TTL and Timeout values
Vanger 27:ec44d5a9544f 531 Timeout = std::atoi(parts[2].c_str());
Vanger 27:ec44d5a9544f 532 TTL = std::atoi(parts[3].c_str());
Vanger 27:ec44d5a9544f 533
Vanger 27:ec44d5a9544f 534 if((Timeout < 600) && (TTL < 255)) {
Vanger 27:ec44d5a9544f 535 return true;
Vanger 27:ec44d5a9544f 536 }
Vanger 52:2cb58398a4f9 537 }
Vanger 26:2b769ed8de4f 538 return false;
Vanger 26:2b769ed8de4f 539 }
Vanger 26:2b769ed8de4f 540
Vanger 33:3b6f3904dde0 541 bool EasyIP::sendEscapeCommand()
Vanger 33:3b6f3904dde0 542 {
Vanger 33:3b6f3904dde0 543 //string Cellular::sendCommand(const std::string& command, unsigned int timeoutMillis, char esc)
Vanger 33:3b6f3904dde0 544 if(io == NULL) {
Vanger 33:3b6f3904dde0 545 logError("MTSBufferedIO not set");
Vanger 33:3b6f3904dde0 546 return false;
Vanger 33:3b6f3904dde0 547 }
Vanger 33:3b6f3904dde0 548 if(!socketOpened) {
Vanger 52:2cb58398a4f9 549 logError("Socket is not open.");
Vanger 52:2cb58398a4f9 550 return false;
Vanger 33:3b6f3904dde0 551 }
Vanger 33:3b6f3904dde0 552
Vanger 33:3b6f3904dde0 553 if(!socketCloseable) {
Vanger 33:3b6f3904dde0 554 logError("Socket is not closeable");
Vanger 33:3b6f3904dde0 555 return false;
Vanger 33:3b6f3904dde0 556 }
Vanger 33:3b6f3904dde0 557
Vanger 33:3b6f3904dde0 558 io->rxClear();
Vanger 33:3b6f3904dde0 559 io->txClear();
Vanger 33:3b6f3904dde0 560
Vanger 33:3b6f3904dde0 561 std::string result;
Vanger 52:2cb58398a4f9 562 unsigned int timeoutMillis = 10000;
Vanger 33:3b6f3904dde0 563 //Attempt to write command
Vanger 52:2cb58398a4f9 564 //Format for +++ command is 1 second wait, send +++, then another second wait
Vanger 52:2cb58398a4f9 565 wait(1.2);
Vanger 49:1fc51c53cebf 566 if(io->write("+++", 3, timeoutMillis) != 3) {
Vanger 33:3b6f3904dde0 567 //Failed to write command
Vanger 33:3b6f3904dde0 568 logError("failed to send command to radio within %d milliseconds", timeoutMillis);
Vanger 33:3b6f3904dde0 569 return false;
Vanger 33:3b6f3904dde0 570 }
Vanger 33:3b6f3904dde0 571
Vanger 52:2cb58398a4f9 572 Timer tmr;
Vanger 33:3b6f3904dde0 573 char tmp[256];
Vanger 33:3b6f3904dde0 574 tmp[255] = 0;
Vanger 33:3b6f3904dde0 575 bool done = false;
Vanger 33:3b6f3904dde0 576 bool exitmode = false;
Vanger 52:2cb58398a4f9 577 tmr.start();
Vanger 33:3b6f3904dde0 578 do {
Vanger 33:3b6f3904dde0 579 //Make a non-blocking read call by passing timeout of zero
Vanger 52:2cb58398a4f9 580 int size = io->read(tmp,255,0); //1 less than allocated (timeout is instant)
Vanger 52:2cb58398a4f9 581 if(size > 0) {
Vanger 52:2cb58398a4f9 582 result.append(tmp, size);
Vanger 52:2cb58398a4f9 583 }
Vanger 54:a6c738bfc391 584 if(result.find("OK\r\n") != std::string::npos) {
Vanger 33:3b6f3904dde0 585 exitmode = true;
Vanger 33:3b6f3904dde0 586 done = true;
Vanger 54:a6c738bfc391 587 } else if(result.find("NO CARRIER\r\n") != std::string::npos) {
Vanger 52:2cb58398a4f9 588 socketOpened = false;
Vanger 33:3b6f3904dde0 589 exitmode = true;
Vanger 33:3b6f3904dde0 590 done = true;
Vanger 33:3b6f3904dde0 591 } else if(result.find("ERROR") != std::string::npos) {
Vanger 33:3b6f3904dde0 592 exitmode = false;
Vanger 33:3b6f3904dde0 593 done = true;
Vanger 33:3b6f3904dde0 594 }
Vanger 52:2cb58398a4f9 595 if(tmr.read_ms() >= timeoutMillis) {
Vanger 33:3b6f3904dde0 596 logDebug("Escape sequence [+++] timed out after %d milliseconds", timeoutMillis);
Vanger 33:3b6f3904dde0 597 exitmode = true;
Vanger 33:3b6f3904dde0 598 done = true;
Vanger 33:3b6f3904dde0 599 }
Vanger 33:3b6f3904dde0 600 } while (!done);
Vanger 33:3b6f3904dde0 601
Vanger 54:a6c738bfc391 602 wait(0.1); //Without a slight wait time after receiving OK, radio would
Vanger 54:a6c738bfc391 603 //fail to correctly receive and respond to the next AT command
Vanger 33:3b6f3904dde0 604 return exitmode;
Vanger 33:3b6f3904dde0 605 }
Vanger 33:3b6f3904dde0 606
Vanger 33:3b6f3904dde0 607 bool EasyIP::socketCheck() {
Vanger 57:7eb2eb536d4a 608 enum SocketStatus {SOCKETCLOSED = 0, SOCKETACTIVEDATA = 1, SOCKETSUSPEND = 2, SOCKETSUSPENDDATA = 3, SOCKETLISTEN = 4, SOCKETINCOMING = 5, ERROR = 9};
Vanger 33:3b6f3904dde0 609 bool status = false;
Vanger 56:43205bd2752a 610 int socketInfo = ERROR;
Vanger 33:3b6f3904dde0 611 std::vector<std::string> params;
Vanger 33:3b6f3904dde0 612
Vanger 33:3b6f3904dde0 613 //Goes from data mode to command mode
Vanger 33:3b6f3904dde0 614 if(sendEscapeCommand()) {
Vanger 52:2cb58398a4f9 615 std::string reply = sendCommand("AT#SS=1", 2000);
Vanger 52:2cb58398a4f9 616 if(reply.find("OK") != std::string::npos) {
Vanger 52:2cb58398a4f9 617 //Found valid response
Vanger 52:2cb58398a4f9 618 params = Text::split(reply, "\r\n");
Vanger 52:2cb58398a4f9 619 params = Text::split(params[1], ",");
Vanger 52:2cb58398a4f9 620 socketInfo = atoi(params[1].c_str());
Vanger 52:2cb58398a4f9 621 } else {
Vanger 52:2cb58398a4f9 622 logError("Could not determine socket status[%d]",socketInfo);
Vanger 56:43205bd2752a 623 socketInfo = ERROR;
Vanger 33:3b6f3904dde0 624 }
Vanger 33:3b6f3904dde0 625 } else {
Vanger 33:3b6f3904dde0 626 status = false; //Return value of socketOpened when checking
Vanger 33:3b6f3904dde0 627 }
Vanger 33:3b6f3904dde0 628
Vanger 33:3b6f3904dde0 629 //Check socket status query
Vanger 56:43205bd2752a 630 if(socketInfo == SOCKETINCOMING || socketInfo == SOCKETACTIVEDATA || socketInfo == SOCKETSUSPEND || socketInfo == SOCKETSUSPENDDATA || socketInfo == SOCKETLISTEN) { //Socket opened responses
Vanger 52:2cb58398a4f9 631 status = true;
Vanger 52:2cb58398a4f9 632 } else if(socketInfo == SOCKETCLOSED || socketInfo == SOCKETINCOMING) {
Vanger 52:2cb58398a4f9 633 status = false;
Vanger 33:3b6f3904dde0 634 } else {
Vanger 54:a6c738bfc391 635 logError("Could not determine socket status[%d]",socketInfo);
Vanger 52:2cb58398a4f9 636 status = false;
Vanger 33:3b6f3904dde0 637 }
Vanger 33:3b6f3904dde0 638
Vanger 52:2cb58398a4f9 639 //Reconnect to active socket if able
Vanger 33:3b6f3904dde0 640 if(status) {
Vanger 33:3b6f3904dde0 641 std::string reconnect = sendCommand("AT#SO=1", 2000);
Vanger 33:3b6f3904dde0 642 if(reconnect.find("CONNECT") != std::string::npos || reconnect.find("OK") != std::string::npos) {
Vanger 33:3b6f3904dde0 643 } else {
Vanger 33:3b6f3904dde0 644 logError("Failed to resume socket connection");
Vanger 33:3b6f3904dde0 645 }
Vanger 33:3b6f3904dde0 646 }
Vanger 33:3b6f3904dde0 647 return status;
Vanger 33:3b6f3904dde0 648 }