GTI GTI / MTS-Cellular

Fork of MTS-Cellular by MultiTech

Committer:
igalt
Date:
Tue Aug 02 16:25:26 2016 +0000
Revision:
82:f6c6e6c07db2
Parent:
81:b0a720f7deae
Child:
83:d250f7f3b8ef
1. Changed timeout for HTTPClient::recv function - BYPASS the latency issue.; 2. Added a function to post at a certain duration and frequency (upto internal delay).

Who changed what in which revision?

UserRevisionLine numberNew contents of line
igalt 81:b0a720f7deae 1 //Debug is disabled by default
igalt 82:f6c6e6c07db2 2 #define DEBUG_ENABLE false
igalt 81:b0a720f7deae 3 #if DEBUG_ENABLE
igalt 81:b0a720f7deae 4 //Enable debug
igalt 81:b0a720f7deae 5 #include <cstdio>
igalt 81:b0a720f7deae 6 #define DBG(x, ...) std::printf("[EasyIP : DBG]"x"\r\n", ##__VA_ARGS__);
igalt 81:b0a720f7deae 7 #define WARN(x, ...) std::printf("[EasyIP : WARN]"x"\r\n", ##__VA_ARGS__);
igalt 81:b0a720f7deae 8 #define ERR(x, ...) std::printf("[EasyIP : ERR]"x"\r\n", ##__VA_ARGS__);
igalt 81:b0a720f7deae 9
igalt 81:b0a720f7deae 10 #else
igalt 81:b0a720f7deae 11 //Disable debug
igalt 81:b0a720f7deae 12 #define DBG(x, ...)
igalt 81:b0a720f7deae 13 #define WARN(x, ...)
igalt 81:b0a720f7deae 14 #define ERR(x, ...)
igalt 81:b0a720f7deae 15
igalt 81:b0a720f7deae 16 #endif
igalt 81:b0a720f7deae 17
Vanger 26:2b769ed8de4f 18 #include "mbed.h"
Vanger 26:2b769ed8de4f 19 #include "EasyIP.h"
Vanger 26:2b769ed8de4f 20 #include "MTSText.h"
Vanger 26:2b769ed8de4f 21 #include "MTSLog.h"
Vanger 26:2b769ed8de4f 22 #include "CellUtils.h"
mfiore 78:fc9d2b983744 23 #include <string>
Vanger 26:2b769ed8de4f 24
Vanger 26:2b769ed8de4f 25 using namespace mts;
Vanger 26:2b769ed8de4f 26
Vanger 26:2b769ed8de4f 27 EasyIP::EasyIP(Radio type)
Vanger 26:2b769ed8de4f 28 {
Vanger 26:2b769ed8de4f 29 this->type = type;
Vanger 26:2b769ed8de4f 30 io = NULL;
Vanger 26:2b769ed8de4f 31 dcd = NULL;
Vanger 26:2b769ed8de4f 32 dtr = NULL;
Vanger 26:2b769ed8de4f 33 resetLine = NULL;
Vanger 26:2b769ed8de4f 34 echoMode = true;
mfiore 78:fc9d2b983744 35 gpsEnabled = false;
Vanger 26:2b769ed8de4f 36 pppConnected = false;
Vanger 26:2b769ed8de4f 37 socketMode = TCP;
Vanger 26:2b769ed8de4f 38 socketOpened = false;
Vanger 26:2b769ed8de4f 39 socketCloseable = true;
Vanger 26:2b769ed8de4f 40 local_port = 0;
Vanger 26:2b769ed8de4f 41 local_address = "";
Vanger 26:2b769ed8de4f 42 host_port = 0;
Vanger 26:2b769ed8de4f 43 }
Vanger 26:2b769ed8de4f 44
Vanger 26:2b769ed8de4f 45 EasyIP::~EasyIP()
Vanger 26:2b769ed8de4f 46 {
Vanger 26:2b769ed8de4f 47 if (dtr != NULL) {
Vanger 26:2b769ed8de4f 48 dtr->write(1);
Vanger 26:2b769ed8de4f 49 }
igalt 81:b0a720f7deae 50
Vanger 26:2b769ed8de4f 51 delete dcd;
Vanger 26:2b769ed8de4f 52 delete dtr;
Vanger 26:2b769ed8de4f 53 delete resetLine;
Vanger 26:2b769ed8de4f 54 }
Vanger 26:2b769ed8de4f 55
Vanger 26:2b769ed8de4f 56 //Initializes the MTS IO Buffer
Vanger 26:2b769ed8de4f 57 bool EasyIP::init(MTSBufferedIO* io)
Vanger 26:2b769ed8de4f 58 {
Mike Fiore 76:6eeffc10739d 59 char buf[128];
Mike Fiore 76:6eeffc10739d 60
Vanger 26:2b769ed8de4f 61 if (! Cellular::init(io)) {
Vanger 26:2b769ed8de4f 62 return false;
Vanger 26:2b769ed8de4f 63 }
Vanger 26:2b769ed8de4f 64
Vanger 26:2b769ed8de4f 65 logDebug("radio type: %s", Cellular::getRadioNames(type).c_str());
Vanger 49:1fc51c53cebf 66 //Turns on the HW flow control
Vanger 56:43205bd2752a 67 if(sendBasicCommand("AT+IFC=2,2", 2000) != MTS_SUCCESS) {
Vanger 52:2cb58398a4f9 68 logWarning("Failed to enable serial flow control");
Vanger 35:257eb41405e1 69 }
mfiore 71:8e8152d955d1 70 // Shorten data sending timeout from 5s to 100ms
mfiore 71:8e8152d955d1 71 // Some servers won't handle a timeout that long
Mike Fiore 76:6eeffc10739d 72 snprintf(buf, sizeof(buf), "AT#SCFG=1,%d,300,90,600,1", type == MTSMC_LVW2 ? 3 : 1);
Mike Fiore 76:6eeffc10739d 73 if (sendBasicCommand(string(buf), 2000) != MTS_SUCCESS) {
mfiore 71:8e8152d955d1 74 logWarning("Failed to reconfigure socket timeout parameters");
mfiore 71:8e8152d955d1 75 }
Vanger 26:2b769ed8de4f 76 return true;
Vanger 26:2b769ed8de4f 77 }
Vanger 26:2b769ed8de4f 78
Vanger 26:2b769ed8de4f 79 bool EasyIP::connect()
Vanger 26:2b769ed8de4f 80 {
Vanger 33:3b6f3904dde0 81 //Check if APN is not set, if it is not, connect will not work.
Mike Fiore 76:6eeffc10739d 82 if (type == MTSMC_H5_IP || type == MTSMC_H5 || type == MTSMC_G3 || type == MTSMC_LAT1 || type == MTSMC_LEU1) {
Vanger 29:edc613ed3f2e 83 if(apn.size() == 0) {
Vanger 29:edc613ed3f2e 84 logDebug("APN is not set");
Vanger 29:edc613ed3f2e 85 return false;
Vanger 29:edc613ed3f2e 86 }
Vanger 29:edc613ed3f2e 87 }
igalt 81:b0a720f7deae 88
Vanger 26:2b769ed8de4f 89 //Check if socket is open
Vanger 26:2b769ed8de4f 90 if(socketOpened) {
Vanger 26:2b769ed8de4f 91 return true;
Vanger 26:2b769ed8de4f 92 }
Vanger 26:2b769ed8de4f 93
Vanger 26:2b769ed8de4f 94 //Check if already connected
Vanger 26:2b769ed8de4f 95 if(isConnected()) {
Vanger 26:2b769ed8de4f 96 return true;
Vanger 26:2b769ed8de4f 97 }
igalt 81:b0a720f7deae 98
Vanger 26:2b769ed8de4f 99 Timer tmr;
Vanger 26:2b769ed8de4f 100 //Check Registration: AT+CREG? == 0,1
Vanger 26:2b769ed8de4f 101 tmr.start();
Vanger 26:2b769ed8de4f 102 do {
Vanger 26:2b769ed8de4f 103 Registration registration = getRegistration();
Vanger 56:43205bd2752a 104 if(registration != REGISTERED && registration != ROAMING) {
Vanger 26:2b769ed8de4f 105 logTrace("Not Registered [%d] ... waiting", (int)registration);
Vanger 26:2b769ed8de4f 106 wait(1);
Vanger 26:2b769ed8de4f 107 } else {
Vanger 26:2b769ed8de4f 108 break;
Vanger 26:2b769ed8de4f 109 }
igalt 81:b0a720f7deae 110 } while(tmr.read() < 30);
igalt 81:b0a720f7deae 111
Vanger 26:2b769ed8de4f 112 //Check RSSI: AT+CSQ
Vanger 26:2b769ed8de4f 113 tmr.reset();
Vanger 26:2b769ed8de4f 114 do {
Vanger 26:2b769ed8de4f 115 int rssi = getSignalStrength();
Vanger 26:2b769ed8de4f 116 logDebug("Signal strength: %d", rssi);
Vanger 51:ffc556ba33f7 117 if(rssi == 99 || rssi == -1) {
Vanger 26:2b769ed8de4f 118 logTrace("No Signal ... waiting");
Vanger 26:2b769ed8de4f 119 wait(1);
Vanger 26:2b769ed8de4f 120 } else {
Vanger 26:2b769ed8de4f 121 break;
Vanger 26:2b769ed8de4f 122 }
Vanger 26:2b769ed8de4f 123 } while(tmr.read() < 30);
Vanger 26:2b769ed8de4f 124
Vanger 52:2cb58398a4f9 125 //Make PPP connection
Mike Fiore 76:6eeffc10739d 126 if (type == MTSMC_H5 || type == MTSMC_G3 || type == MTSMC_LAT1 || type == MTSMC_LEU1) {
Vanger 26:2b769ed8de4f 127 logDebug("Making PPP Connection Attempt. APN[%s]", apn.c_str());
Vanger 26:2b769ed8de4f 128 } else {
Vanger 26:2b769ed8de4f 129 logDebug("Making PPP Connection Attempt");
Vanger 26:2b769ed8de4f 130 }
Mike Fiore 76:6eeffc10739d 131 char buf[64];
Mike Fiore 76:6eeffc10739d 132 snprintf(buf, sizeof(buf), "AT#SGACT=%d,1", type == MTSMC_LVW2 ? 3 : 1);
Mike Fiore 76:6eeffc10739d 133 std::string pppResult = sendCommand(string(buf), 15000);
Vanger 30:1326b623919a 134 std::vector<std::string> parts;
Vanger 26:2b769ed8de4f 135 if(pppResult.find("OK") != std::string::npos) {
Vanger 30:1326b623919a 136 parts = Text::split(pppResult, "\r\n");
Vanger 26:2b769ed8de4f 137 if(parts.size() >= 2) {
Vanger 26:2b769ed8de4f 138 parts = Text::split(parts[1], " ");
Mike Fiore 76:6eeffc10739d 139 if (parts.size() >= 2) {
Mike Fiore 76:6eeffc10739d 140 local_address = parts[1];
Mike Fiore 76:6eeffc10739d 141 }
Vanger 26:2b769ed8de4f 142 }
Vanger 26:2b769ed8de4f 143 logInfo("PPP Connection Established: IP[%s]", local_address.c_str());
Vanger 26:2b769ed8de4f 144 pppConnected = true;
Vanger 26:2b769ed8de4f 145
Vanger 26:2b769ed8de4f 146 } else {
Mike Fiore 76:6eeffc10739d 147 snprintf(buf, sizeof(buf), "%d,1", type == MTSMC_LVW2 ? 3 : 1);
Vanger 30:1326b623919a 148 pppResult = sendCommand("AT#SGACT?", 2000);
Mike Fiore 76:6eeffc10739d 149 if(pppResult.find(string(buf)) != std::string::npos) {
igalt 81:b0a720f7deae 150 logDebug("Radio is already connected");
igalt 81:b0a720f7deae 151 pppConnected = true;
Vanger 30:1326b623919a 152 } else {
Vanger 52:2cb58398a4f9 153 logError("PPP connection attempt failed");
Vanger 52:2cb58398a4f9 154 pppConnected = false;
Vanger 30:1326b623919a 155 }
Vanger 26:2b769ed8de4f 156 }
Vanger 26:2b769ed8de4f 157
Vanger 26:2b769ed8de4f 158 return pppConnected;
Vanger 26:2b769ed8de4f 159 }
Vanger 26:2b769ed8de4f 160
Vanger 26:2b769ed8de4f 161 void EasyIP::disconnect()
Vanger 26:2b769ed8de4f 162 {
Vanger 52:2cb58398a4f9 163 //AT#SGACT=1,0: Close PPP connection
igalt 81:b0a720f7deae 164 logDebug("Closing PPP Connection");
Vanger 35:257eb41405e1 165 std::string result;
Vanger 35:257eb41405e1 166 Timer tmr;
igalt 81:b0a720f7deae 167
Vanger 52:2cb58398a4f9 168 if(socketOpened) {
Vanger 66:8c55e2bf7270 169 close(true);
Vanger 52:2cb58398a4f9 170 }
igalt 81:b0a720f7deae 171
Vanger 26:2b769ed8de4f 172 //Sends AT#SGACT=1,0 command
Vanger 54:a6c738bfc391 173 for (int y = 0; y < 5; y++) {
Mike Fiore 76:6eeffc10739d 174 char buf[64];
Mike Fiore 76:6eeffc10739d 175 snprintf(buf, sizeof(buf), "AT#SGACT=%d,0", type == MTSMC_LVW2 ? 3 : 1);
Mike Fiore 76:6eeffc10739d 176 Code code = sendBasicCommand(string(buf), 1000);
Vanger 54:a6c738bfc391 177 if (code == MTS_SUCCESS) {
Vanger 54:a6c738bfc391 178 logDebug("Successfully closed PPP Connection");
Vanger 54:a6c738bfc391 179 break;
Vanger 54:a6c738bfc391 180 }
Vanger 30:1326b623919a 181 }
igalt 81:b0a720f7deae 182
Vanger 52:2cb58398a4f9 183 /* Ensure PPP link is down, else ping commands will put radio in unknown state
Vanger 52:2cb58398a4f9 184 * (Link is not immediate in disconnection, even though OK is returned)
Vanger 51:ffc556ba33f7 185 */
Vanger 35:257eb41405e1 186 tmr.start();
Vanger 35:257eb41405e1 187 while(tmr.read() < 30) {
Mike Fiore 76:6eeffc10739d 188 char buf[16];
Mike Fiore 76:6eeffc10739d 189 snprintf(buf, sizeof(buf), "%d,0", type == MTSMC_LVW2 ? 3 : 1);
Vanger 35:257eb41405e1 190 result = sendCommand("AT#SGACT?", 1000);
Mike Fiore 76:6eeffc10739d 191 if(result.find(string(buf)) != std::string::npos) {
Vanger 35:257eb41405e1 192 break;
Vanger 35:257eb41405e1 193 } else if(result.find("ERROR") != std::string::npos) {
Vanger 35:257eb41405e1 194 break;
Vanger 35:257eb41405e1 195 } else {
Vanger 35:257eb41405e1 196 wait(1);
Vanger 35:257eb41405e1 197 }
Vanger 35:257eb41405e1 198 }
igalt 81:b0a720f7deae 199
Vanger 52:2cb58398a4f9 200 pppConnected = false;
Vanger 30:1326b623919a 201 return;
Vanger 26:2b769ed8de4f 202 }
Vanger 27:ec44d5a9544f 203
Vanger 26:2b769ed8de4f 204 bool EasyIP::isConnected()
Vanger 26:2b769ed8de4f 205 {
Vanger 52:2cb58398a4f9 206 enum RadioState {IDLE, CONNECTING, CONNECTED, DISCONNECTED};
Vanger 51:ffc556ba33f7 207 //state flags for various connection components
Vanger 30:1326b623919a 208 bool signal = false, regist = false, active = false;
Mike Fiore 76:6eeffc10739d 209 char buf[16];
igalt 81:b0a720f7deae 210
Vanger 29:edc613ed3f2e 211 //1) Check if APN was set if we're on an HSPA radio
Mike Fiore 76:6eeffc10739d 212 if (type == MTSMC_H5_IP || type == MTSMC_H5 || type == MTSMC_G3 || type == MTSMC_LAT1 || type == MTSMC_LEU1) {
Vanger 29:edc613ed3f2e 213 if(apn.size() == 0) {
Vanger 29:edc613ed3f2e 214 logDebug("APN is not set");
Vanger 29:edc613ed3f2e 215 return false;
Vanger 29:edc613ed3f2e 216 }
Vanger 29:edc613ed3f2e 217 }
igalt 81:b0a720f7deae 218
Vanger 29:edc613ed3f2e 219 //2) Check that we do not have a live connection up
Vanger 52:2cb58398a4f9 220 if (socketOpened) {
Vanger 29:edc613ed3f2e 221 logDebug("Socket is opened");
Vanger 29:edc613ed3f2e 222 return true;
Vanger 29:edc613ed3f2e 223 }
igalt 81:b0a720f7deae 224
Vanger 29:edc613ed3f2e 225 //3) Query the radio
Vanger 52:2cb58398a4f9 226 int rssi = getSignalStrength();
Vanger 52:2cb58398a4f9 227 if (rssi == 99 || rssi == -1) {
Vanger 52:2cb58398a4f9 228 //Signal strength is nonexistent
Vanger 29:edc613ed3f2e 229 signal = false;
Vanger 29:edc613ed3f2e 230 } else {
Vanger 52:2cb58398a4f9 231 signal = true;
Vanger 29:edc613ed3f2e 232 }
igalt 81:b0a720f7deae 233
Vanger 52:2cb58398a4f9 234 Registration creg = getRegistration();
Vanger 52:2cb58398a4f9 235 if (creg == REGISTERED) {
Vanger 52:2cb58398a4f9 236 regist = true;
Vanger 29:edc613ed3f2e 237 } else {
Vanger 52:2cb58398a4f9 238 regist = false;
Vanger 29:edc613ed3f2e 239 }
igalt 81:b0a720f7deae 240
Vanger 56:43205bd2752a 241 string reply = sendCommand("AT#SGACT?", 1000);
Mike Fiore 76:6eeffc10739d 242 snprintf(buf, sizeof(buf), "%d,1", type == MTSMC_LVW2 ? 3 : 1);
Mike Fiore 76:6eeffc10739d 243 if (reply.find(string(buf)) != std::string::npos) {
Vanger 52:2cb58398a4f9 244 active = true;
Vanger 29:edc613ed3f2e 245 } else {
Vanger 52:2cb58398a4f9 246 active = false;
Vanger 29:edc613ed3f2e 247 }
igalt 81:b0a720f7deae 248
Vanger 60:250c17af30fb 249 //Updates pppConnected to reflect current connection state
Vanger 52:2cb58398a4f9 250 RadioState state;
Vanger 52:2cb58398a4f9 251 bool ppp = pppConnected;
Vanger 52:2cb58398a4f9 252 if (signal && regist && active) {
Vanger 52:2cb58398a4f9 253 state = CONNECTED;
Vanger 52:2cb58398a4f9 254 pppConnected = true;
Vanger 52:2cb58398a4f9 255 } else if (signal && !regist && !active) {
Vanger 52:2cb58398a4f9 256 state = IDLE;
Vanger 52:2cb58398a4f9 257 pppConnected = false;
Vanger 52:2cb58398a4f9 258 } else if (active) {
Vanger 52:2cb58398a4f9 259 state = CONNECTING;
Vanger 52:2cb58398a4f9 260 } else {
Vanger 52:2cb58398a4f9 261 state = DISCONNECTED;
Vanger 30:1326b623919a 262 pppConnected = false;
Vanger 30:1326b623919a 263 }
igalt 81:b0a720f7deae 264
Vanger 60:250c17af30fb 265 //Compares current connection state with previous pppConnected variable state
Vanger 52:2cb58398a4f9 266 if (!ppp && state == CONNECTED) {
Vanger 52:2cb58398a4f9 267 logWarning("Internal PPP state tracking differs from radio (DISCONNECTED:CONNECTED)");
Vanger 52:2cb58398a4f9 268 } else if (ppp && state != CONNECTED) {
Vanger 56:43205bd2752a 269 string stateStr;
Vanger 56:43205bd2752a 270 switch (state) {
Vanger 56:43205bd2752a 271 case IDLE:
Vanger 56:43205bd2752a 272 stateStr = "IDLE";
Vanger 56:43205bd2752a 273 break;
Vanger 56:43205bd2752a 274 case CONNECTING:
Vanger 56:43205bd2752a 275 stateStr = "CONNECTING";
Vanger 56:43205bd2752a 276 break;
Vanger 56:43205bd2752a 277 case DISCONNECTED:
Vanger 56:43205bd2752a 278 stateStr = "DISCONNECTED";
Vanger 56:43205bd2752a 279 break;
Vanger 56:43205bd2752a 280 case CONNECTED:
Vanger 56:43205bd2752a 281 stateStr = "CONNECTED";
Vanger 56:43205bd2752a 282 break;
Vanger 56:43205bd2752a 283 default:
Vanger 56:43205bd2752a 284 stateStr = "UKNOWN";
Vanger 56:43205bd2752a 285 break;
Vanger 56:43205bd2752a 286 }
Vanger 56:43205bd2752a 287 logWarning("Internal PPP state tracking differs from radio (CONNECTED:%s)", stateStr.c_str());
Vanger 29:edc613ed3f2e 288 }
igalt 81:b0a720f7deae 289
Vanger 26:2b769ed8de4f 290 return pppConnected;
Vanger 26:2b769ed8de4f 291 }
Vanger 30:1326b623919a 292
Vanger 33:3b6f3904dde0 293 void EasyIP::reset()
Vanger 33:3b6f3904dde0 294 {
Vanger 33:3b6f3904dde0 295 disconnect();
igalt 81:b0a720f7deae 296
Vanger 33:3b6f3904dde0 297 if(sendBasicCommand("AT#REBOOT", 10000) != MTS_SUCCESS) {
Vanger 52:2cb58398a4f9 298 logError("Socket Modem did not accept RESET command");
Vanger 33:3b6f3904dde0 299 } else {
Vanger 52:2cb58398a4f9 300 logWarning("Socket Modem is resetting, allow 30 seconds for it to come back");
Vanger 33:3b6f3904dde0 301 return;
Vanger 33:3b6f3904dde0 302 }
Vanger 33:3b6f3904dde0 303 }
Vanger 33:3b6f3904dde0 304
Vanger 60:250c17af30fb 305 //Opens socket connection
Vanger 26:2b769ed8de4f 306 bool EasyIP::open(const std::string& address, unsigned int port, Mode mode)
Vanger 26:2b769ed8de4f 307 {
Vanger 30:1326b623919a 308 char sOpenSocketCmd[256] = {0}; //String for AT command
Vanger 30:1326b623919a 309 std::string sMode = "";
Vanger 31:529db15abda7 310 int typeSocket = 0;
Vanger 31:529db15abda7 311 int closeType = 0;
igalt 81:b0a720f7deae 312
Vanger 30:1326b623919a 313 //1) Check that we do not have a live connection up
Vanger 30:1326b623919a 314 if(socketOpened) {
Vanger 30:1326b623919a 315 //Check that the address, port, and mode match
Vanger 30:1326b623919a 316 if(host_address != address || host_port != port || socketMode != mode) {
Vanger 30:1326b623919a 317 if(socketMode == TCP) {
Vanger 30:1326b623919a 318 logError("TCP socket already opened [%s:%d]", host_address.c_str(), host_port);
Vanger 30:1326b623919a 319 } else {
Vanger 30:1326b623919a 320 logError("UDP socket already opened [%s:%d]", host_address.c_str(), host_port);
Vanger 30:1326b623919a 321 }
Vanger 30:1326b623919a 322 return false;
Vanger 30:1326b623919a 323 }
Vanger 30:1326b623919a 324
Vanger 30:1326b623919a 325 logDebug("Socket already opened");
Vanger 30:1326b623919a 326 return true;
Vanger 30:1326b623919a 327 }
Vanger 30:1326b623919a 328
Vanger 30:1326b623919a 329 //2) Check Parameters
Vanger 30:1326b623919a 330 if(port > 65535) {
Vanger 30:1326b623919a 331 logError("port out of range (0-65535)");
Vanger 30:1326b623919a 332 return false;
Vanger 30:1326b623919a 333 }
igalt 81:b0a720f7deae 334
Mike Fiore 76:6eeffc10739d 335 if(type == MTSMC_EV3 || type == MTSMC_LAT1 || type == MTSMC_LEU1 || type == MTSMC_LVW2) {
Vanger 41:8b9b5098696f 336 if(!local_port) {
Vanger 70:c0c621f88330 337 logDebug("Local port set to 1, port 0 not supported for %s", getRadioNames(type).c_str());
Vanger 69:93dace69ee98 338 local_port = 1;
Vanger 69:93dace69ee98 339 }
Vanger 41:8b9b5098696f 340 }
Vanger 30:1326b623919a 341
Vanger 30:1326b623919a 342 //3) Check PPP connection
Vanger 30:1326b623919a 343 if(!isConnected()) {
Vanger 30:1326b623919a 344 logError("PPP not established. Attempting to connect");
Vanger 30:1326b623919a 345 if(!connect()) {
Vanger 30:1326b623919a 346 logError("PPP connection failed");
Vanger 30:1326b623919a 347 return false;
Vanger 30:1326b623919a 348 } else {
Vanger 30:1326b623919a 349 logDebug("PPP connection established");
Vanger 30:1326b623919a 350 }
Vanger 30:1326b623919a 351 }
igalt 81:b0a720f7deae 352
Vanger 56:43205bd2752a 353 //4) Set escape sequence to not be transmitted through socket
Vanger 30:1326b623919a 354 if(sendBasicCommand("AT#SKIPESC=1", 2000) != MTS_SUCCESS) {
Vanger 30:1326b623919a 355 logWarning("Failed to disable escape sequence transmission on data mode suspension");
Vanger 30:1326b623919a 356 }
igalt 81:b0a720f7deae 357
Vanger 30:1326b623919a 358 if(mode == TCP) {
Vanger 30:1326b623919a 359 typeSocket = 0;
Vanger 30:1326b623919a 360 sMode = "TCP";
Vanger 30:1326b623919a 361 } else {
Vanger 30:1326b623919a 362 typeSocket = 1;
Vanger 30:1326b623919a 363 sMode = "UDP";
Vanger 30:1326b623919a 364 }
igalt 81:b0a720f7deae 365
Vanger 31:529db15abda7 366 if(socketCloseable) {
Vanger 31:529db15abda7 367 closeType = 0;
Vanger 31:529db15abda7 368 } else {
Vanger 31:529db15abda7 369 closeType = 255;
Vanger 31:529db15abda7 370 }
igalt 81:b0a720f7deae 371
igalt 81:b0a720f7deae 372 //5) Open Socket
Vanger 69:93dace69ee98 373 sprintf(sOpenSocketCmd, "AT#SD=1,%d,%d,\"%s\",%d,%d,0", typeSocket, port, address.c_str(), closeType, local_port);
Vanger 38:b2088faa8bfd 374 std::string response = sendCommand(sOpenSocketCmd, 60000);
igalt 81:b0a720f7deae 375
Vanger 30:1326b623919a 376 if(response.find("CONNECT") != std::string::npos) {
Vanger 30:1326b623919a 377 host_address = address;
Vanger 30:1326b623919a 378 host_port = port;
igalt 81:b0a720f7deae 379
Vanger 30:1326b623919a 380 logInfo("Opened %s Socket [%s:%d]", sMode.c_str(), address.c_str(), port);
Vanger 30:1326b623919a 381 socketOpened = true;
Vanger 30:1326b623919a 382 socketMode = mode;
Vanger 30:1326b623919a 383 } else {
Vanger 30:1326b623919a 384 logWarning("Unable to open %s Socket [%s:%d]", sMode.c_str(), address.c_str(), port);
Vanger 30:1326b623919a 385 socketOpened = false;
Vanger 30:1326b623919a 386 }
igalt 81:b0a720f7deae 387
Vanger 26:2b769ed8de4f 388 return socketOpened;
Vanger 26:2b769ed8de4f 389 }
Vanger 27:ec44d5a9544f 390
Vanger 60:250c17af30fb 391 //Closes socket connection
Vanger 67:7c705fe2acec 392 bool EasyIP::close(bool shutdown)
Vanger 26:2b769ed8de4f 393 {
igalt 81:b0a720f7deae 394
Vanger 30:1326b623919a 395 if(io == NULL) {
Vanger 30:1326b623919a 396 logError("MTSBufferedIO not set");
Vanger 30:1326b623919a 397 return false;
Vanger 30:1326b623919a 398 }
Vanger 30:1326b623919a 399
Vanger 30:1326b623919a 400 if(!socketOpened) {
Vanger 30:1326b623919a 401 logWarning("Socket close() called, but socket was not open");
Vanger 30:1326b623919a 402 return true;
Vanger 30:1326b623919a 403 }
Vanger 30:1326b623919a 404
Vanger 30:1326b623919a 405 if(!socketCloseable) {
Vanger 30:1326b623919a 406 logError("Socket is not closeable");
Vanger 30:1326b623919a 407 return false;
Vanger 30:1326b623919a 408 }
igalt 81:b0a720f7deae 409
Vanger 30:1326b623919a 410 if(!sendEscapeCommand()) {
Vanger 30:1326b623919a 411 logError("Failed to exit online mode");
Vanger 30:1326b623919a 412 return false;
Vanger 30:1326b623919a 413 } else {
Vanger 30:1326b623919a 414 socketOpened = false;
Vanger 30:1326b623919a 415 }
igalt 81:b0a720f7deae 416
Vanger 54:a6c738bfc391 417 if (sendBasicCommand("AT#SH=1", 2000) != MTS_SUCCESS) {
Vanger 30:1326b623919a 418 logDebug("Failed to close socket connection");
Vanger 30:1326b623919a 419 }
igalt 81:b0a720f7deae 420
Vanger 60:250c17af30fb 421 //Clear receive buffer
Vanger 67:7c705fe2acec 422 if (shutdown) {
Vanger 66:8c55e2bf7270 423 int counter = 0;
Vanger 66:8c55e2bf7270 424 char tmp[256];
Vanger 66:8c55e2bf7270 425 do {
Vanger 66:8c55e2bf7270 426 if(socketOpened == false) {
Vanger 66:8c55e2bf7270 427 break;
Vanger 66:8c55e2bf7270 428 }
Vanger 66:8c55e2bf7270 429 read(tmp, 256, 1000);
Vanger 66:8c55e2bf7270 430 } while(counter++ < 10);
igalt 81:b0a720f7deae 431
Vanger 66:8c55e2bf7270 432 io->rxClear();
Vanger 66:8c55e2bf7270 433 io->txClear();
Vanger 66:8c55e2bf7270 434 }
Vanger 30:1326b623919a 435
Vanger 30:1326b623919a 436 return !socketOpened;
Vanger 26:2b769ed8de4f 437 }
Vanger 26:2b769ed8de4f 438
Vanger 60:250c17af30fb 439 //Read from socket
Vanger 26:2b769ed8de4f 440 int EasyIP::read(char* data, int max, int timeout)
Vanger 26:2b769ed8de4f 441 {
Vanger 30:1326b623919a 442 if(io == NULL) {
Vanger 30:1326b623919a 443 logError("MTSBufferedIO not set");
Vanger 30:1326b623919a 444 return -1;
Vanger 30:1326b623919a 445 }
Vanger 30:1326b623919a 446
Vanger 30:1326b623919a 447 //Check that nothing is in the rx buffer
Vanger 30:1326b623919a 448 if(!socketOpened && !io->readable()) {
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 bytesRead = 0;
Vanger 30:1326b623919a 454
Vanger 30:1326b623919a 455 if(timeout >= 0) {
Vanger 30:1326b623919a 456 bytesRead = io->read(data, max, static_cast<unsigned int>(timeout));
Vanger 30:1326b623919a 457 } else {
Vanger 30:1326b623919a 458 bytesRead = io->read(data, max);
Vanger 30:1326b623919a 459 }
igalt 81:b0a720f7deae 460
Vanger 35:257eb41405e1 461 //Scan for socket closed message
Vanger 31:529db15abda7 462 if(bytesRead > 0 && socketCloseable) {
Vanger 35:257eb41405e1 463 for(int i = 0; i < bytesRead; i++) {
Vanger 31:529db15abda7 464 if(data[i] == 'N') {
Vanger 31:529db15abda7 465 if(strstr(&data[i], "NO CARRIER")) {
Vanger 31:529db15abda7 466 logTrace("Found socket closed message. Checking validity");
Vanger 31:529db15abda7 467 //Close socket and Cut Off End of Message
Vanger 31:529db15abda7 468 socketOpened = socketCheck(); //Verifies legitimacy of socket disconnect
Vanger 31:529db15abda7 469 if(socketOpened) {
Vanger 31:529db15abda7 470 logDebug("Socket still open");
Vanger 31:529db15abda7 471 continue;
Vanger 31:529db15abda7 472 } else {
Vanger 31:529db15abda7 473 logDebug("Socket closed");
Vanger 31:529db15abda7 474 data[i] = '\0';
Vanger 31:529db15abda7 475 bytesRead = i;
Vanger 31:529db15abda7 476 break;
Vanger 31:529db15abda7 477 }
Vanger 30:1326b623919a 478 }
Vanger 30:1326b623919a 479 }
Vanger 30:1326b623919a 480 }
Vanger 30:1326b623919a 481 }
Vanger 30:1326b623919a 482 return bytesRead;
Vanger 26:2b769ed8de4f 483 }
Vanger 26:2b769ed8de4f 484
Vanger 60:250c17af30fb 485 //Write to socket
Vanger 26:2b769ed8de4f 486 int EasyIP::write(const char* data, int length, int timeout)
Vanger 26:2b769ed8de4f 487 {
Vanger 30:1326b623919a 488 if(io == NULL) {
Vanger 30:1326b623919a 489 logError("MTSBufferedIO not set");
Vanger 30:1326b623919a 490 return -1;
Vanger 30:1326b623919a 491 }
Vanger 30:1326b623919a 492
Vanger 30:1326b623919a 493 if(!socketOpened) {
Vanger 30:1326b623919a 494 logError("Socket is not open");
Vanger 30:1326b623919a 495 return -1;
Vanger 30:1326b623919a 496 }
Vanger 30:1326b623919a 497
Vanger 30:1326b623919a 498 int bytesWritten = 0;
Vanger 31:529db15abda7 499 int size = length;
Vanger 31:529db15abda7 500 int failedWrites = 0;
Vanger 30:1326b623919a 501 if(timeout >= 0) {
Vanger 30:1326b623919a 502 Timer tmr;
Vanger 30:1326b623919a 503 tmr.start();
Vanger 30:1326b623919a 504 do {
Vanger 30:1326b623919a 505 int available = io->writeable();
Vanger 30:1326b623919a 506 if (available > 0) {
Mike Fiore 72:7862171b277d 507 size = mts_min(available, length - bytesWritten);
Vanger 31:529db15abda7 508 bytesWritten += io->write(&data[bytesWritten], size);
Vanger 30:1326b623919a 509 } else {
Vanger 30:1326b623919a 510 wait(0.05);
Vanger 30:1326b623919a 511 }
Vanger 30:1326b623919a 512 } while (tmr.read_ms() <= timeout && bytesWritten < length);
Vanger 30:1326b623919a 513 } else {
Vanger 31:529db15abda7 514 //If timeout is -1:
Vanger 31:529db15abda7 515 do {
Vanger 31:529db15abda7 516 int available = io->writeable();
Vanger 31:529db15abda7 517 if(available > 0) {
Mike Fiore 72:7862171b277d 518 size = mts_min(available, length - bytesWritten);
Vanger 31:529db15abda7 519 int currentWritten = io->write(&data[bytesWritten], size);
Vanger 31:529db15abda7 520 bytesWritten += currentWritten;
Vanger 31:529db15abda7 521 if(!currentWritten) {
Vanger 31:529db15abda7 522 failedWrites++;
Vanger 31:529db15abda7 523 }
Vanger 31:529db15abda7 524 if(failedWrites > 10) {
Vanger 31:529db15abda7 525 logError("Couldn't write any characters");
Vanger 31:529db15abda7 526 return bytesWritten;
Vanger 31:529db15abda7 527 }
Vanger 31:529db15abda7 528 } else {
Vanger 31:529db15abda7 529 wait(0.05);
Vanger 30:1326b623919a 530 }
igalt 81:b0a720f7deae 531 } while (bytesWritten < length);
Vanger 30:1326b623919a 532 }
Vanger 30:1326b623919a 533 return bytesWritten;
Vanger 26:2b769ed8de4f 534 }
Vanger 26:2b769ed8de4f 535
Vanger 26:2b769ed8de4f 536 Code EasyIP::setApn(const std::string& apn)
Vanger 26:2b769ed8de4f 537 {
Vanger 26:2b769ed8de4f 538 if (type == MTSMC_H5 || type == MTSMC_G3) {
igalt 81:b0a720f7deae 539 //CGDCONT has options: IP,PPP,IPv6
Vanger 56:43205bd2752a 540 Code code = sendBasicCommand("AT+CGDCONT=1,IP," + apn, 1000);
Vanger 26:2b769ed8de4f 541 if (code != MTS_SUCCESS) {
Vanger 56:43205bd2752a 542 return code;
Vanger 26:2b769ed8de4f 543 }
Vanger 26:2b769ed8de4f 544 this->apn = apn;
Vanger 56:43205bd2752a 545 return code;
Mike Fiore 76:6eeffc10739d 546 } else if (type == MTSMC_LAT1 || type == MTSMC_LEU1) {
igalt 81:b0a720f7deae 547 //CGDCONT has options: IP,PPP,IPv6
Vanger 69:93dace69ee98 548 Code code = sendBasicCommand("AT+CGDCONT=1,\"IP\",\"" + apn + "\"", 1000);
Vanger 69:93dace69ee98 549 if (code != MTS_SUCCESS) {
Vanger 69:93dace69ee98 550 return code;
Vanger 69:93dace69ee98 551 }
Vanger 69:93dace69ee98 552 this->apn = apn;
Vanger 69:93dace69ee98 553 return code;
Vanger 26:2b769ed8de4f 554 } else {
Vanger 26:2b769ed8de4f 555 logInfo("CDMA radios don't need an APN");
Vanger 26:2b769ed8de4f 556 return MTS_SUCCESS;
Vanger 26:2b769ed8de4f 557 }
Vanger 26:2b769ed8de4f 558 }
Vanger 27:ec44d5a9544f 559
Vanger 26:2b769ed8de4f 560 bool EasyIP::ping(const std::string& address)
Vanger 26:2b769ed8de4f 561 {
Vanger 26:2b769ed8de4f 562 char buffer[256] = {0};
Vanger 27:ec44d5a9544f 563 std::vector<std::string> parts;
Vanger 27:ec44d5a9544f 564 int TTL=0;
Vanger 27:ec44d5a9544f 565 int Timeout=0;
igalt 81:b0a720f7deae 566
Vanger 27:ec44d5a9544f 567 //Format parameters for sending to radio
Vanger 30:1326b623919a 568 sprintf(buffer, "AT#PING=%s,1,32,%d", address.c_str(), (PINGDELAY*10));
igalt 81:b0a720f7deae 569
Vanger 27:ec44d5a9544f 570 for(int pngs=0; pngs<PINGNUM; pngs++) {
Vanger 35:257eb41405e1 571 std::string response = sendCommand(buffer, (PINGDELAY*2000)); //Send 1 ping
Vanger 52:2cb58398a4f9 572 if(response.empty() || response.find("ERROR") != std::string::npos) {
Vanger 28:f93d7b3f7c2e 573 continue; //Skip current loop if send command fails
Vanger 28:f93d7b3f7c2e 574 }
Vanger 27:ec44d5a9544f 575 parts = Text::split(response, "\r\n");
Vanger 28:f93d7b3f7c2e 576 if(parts.size() < 2) {
Vanger 28:f93d7b3f7c2e 577 continue;
Vanger 28:f93d7b3f7c2e 578 }
Vanger 27:ec44d5a9544f 579 parts = Text::split(parts[1], ",");
Vanger 28:f93d7b3f7c2e 580 if(parts.size() < 4) {
Vanger 28:f93d7b3f7c2e 581 continue;
Vanger 28:f93d7b3f7c2e 582 }
Vanger 27:ec44d5a9544f 583 //Parse TTL and Timeout values
Vanger 27:ec44d5a9544f 584 Timeout = std::atoi(parts[2].c_str());
Vanger 27:ec44d5a9544f 585 TTL = std::atoi(parts[3].c_str());
igalt 81:b0a720f7deae 586
Vanger 27:ec44d5a9544f 587 if((Timeout < 600) && (TTL < 255)) {
Vanger 27:ec44d5a9544f 588 return true;
Vanger 27:ec44d5a9544f 589 }
igalt 81:b0a720f7deae 590 }
Vanger 26:2b769ed8de4f 591 return false;
Vanger 26:2b769ed8de4f 592 }
Vanger 26:2b769ed8de4f 593
Vanger 33:3b6f3904dde0 594 bool EasyIP::sendEscapeCommand()
Vanger 33:3b6f3904dde0 595 {
Vanger 33:3b6f3904dde0 596 //string Cellular::sendCommand(const std::string& command, unsigned int timeoutMillis, char esc)
Vanger 33:3b6f3904dde0 597 if(io == NULL) {
Vanger 33:3b6f3904dde0 598 logError("MTSBufferedIO not set");
Vanger 33:3b6f3904dde0 599 return false;
Vanger 33:3b6f3904dde0 600 }
Vanger 33:3b6f3904dde0 601 if(!socketOpened) {
Vanger 52:2cb58398a4f9 602 logError("Socket is not open.");
Vanger 52:2cb58398a4f9 603 return false;
Vanger 33:3b6f3904dde0 604 }
igalt 81:b0a720f7deae 605
Vanger 33:3b6f3904dde0 606 if(!socketCloseable) {
Vanger 33:3b6f3904dde0 607 logError("Socket is not closeable");
Vanger 33:3b6f3904dde0 608 return false;
Vanger 33:3b6f3904dde0 609 }
igalt 81:b0a720f7deae 610
Vanger 33:3b6f3904dde0 611 io->rxClear();
Vanger 33:3b6f3904dde0 612 io->txClear();
igalt 81:b0a720f7deae 613
Vanger 33:3b6f3904dde0 614 std::string result;
Vanger 52:2cb58398a4f9 615 unsigned int timeoutMillis = 10000;
Vanger 33:3b6f3904dde0 616 //Attempt to write command
Vanger 52:2cb58398a4f9 617 //Format for +++ command is 1 second wait, send +++, then another second wait
igalt 81:b0a720f7deae 618 wait(1.2);
Vanger 49:1fc51c53cebf 619 if(io->write("+++", 3, timeoutMillis) != 3) {
Vanger 33:3b6f3904dde0 620 //Failed to write command
Vanger 33:3b6f3904dde0 621 logError("failed to send command to radio within %d milliseconds", timeoutMillis);
Vanger 33:3b6f3904dde0 622 return false;
Vanger 33:3b6f3904dde0 623 }
igalt 81:b0a720f7deae 624
Vanger 52:2cb58398a4f9 625 Timer tmr;
Vanger 33:3b6f3904dde0 626 char tmp[256];
Vanger 33:3b6f3904dde0 627 tmp[255] = 0;
Vanger 33:3b6f3904dde0 628 bool done = false;
Vanger 33:3b6f3904dde0 629 bool exitmode = false;
Vanger 52:2cb58398a4f9 630 tmr.start();
Vanger 33:3b6f3904dde0 631 do {
Vanger 33:3b6f3904dde0 632 //Make a non-blocking read call by passing timeout of zero
Vanger 52:2cb58398a4f9 633 int size = io->read(tmp,255,0); //1 less than allocated (timeout is instant)
Vanger 52:2cb58398a4f9 634 if(size > 0) {
Vanger 52:2cb58398a4f9 635 result.append(tmp, size);
Vanger 52:2cb58398a4f9 636 }
Vanger 54:a6c738bfc391 637 if(result.find("OK\r\n") != std::string::npos) {
Vanger 33:3b6f3904dde0 638 exitmode = true;
Vanger 33:3b6f3904dde0 639 done = true;
Vanger 54:a6c738bfc391 640 } else if(result.find("NO CARRIER\r\n") != std::string::npos) {
Vanger 52:2cb58398a4f9 641 socketOpened = false;
Vanger 33:3b6f3904dde0 642 exitmode = true;
Vanger 33:3b6f3904dde0 643 done = true;
Vanger 33:3b6f3904dde0 644 } else if(result.find("ERROR") != std::string::npos) {
Vanger 33:3b6f3904dde0 645 exitmode = false;
Vanger 33:3b6f3904dde0 646 done = true;
Vanger 33:3b6f3904dde0 647 }
Vanger 52:2cb58398a4f9 648 if(tmr.read_ms() >= timeoutMillis) {
Vanger 33:3b6f3904dde0 649 logDebug("Escape sequence [+++] timed out after %d milliseconds", timeoutMillis);
Vanger 33:3b6f3904dde0 650 exitmode = true;
Vanger 33:3b6f3904dde0 651 done = true;
Vanger 33:3b6f3904dde0 652 }
Vanger 33:3b6f3904dde0 653 } while (!done);
igalt 81:b0a720f7deae 654
Vanger 54:a6c738bfc391 655 wait(0.1); //Without a slight wait time after receiving OK, radio would
igalt 81:b0a720f7deae 656 //fail to correctly receive and respond to the next AT command
Vanger 33:3b6f3904dde0 657 return exitmode;
Vanger 33:3b6f3904dde0 658 }
Vanger 33:3b6f3904dde0 659
igalt 81:b0a720f7deae 660 bool EasyIP::socketCheck()
igalt 81:b0a720f7deae 661 {
Vanger 57:7eb2eb536d4a 662 enum SocketStatus {SOCKETCLOSED = 0, SOCKETACTIVEDATA = 1, SOCKETSUSPEND = 2, SOCKETSUSPENDDATA = 3, SOCKETLISTEN = 4, SOCKETINCOMING = 5, ERROR = 9};
Vanger 33:3b6f3904dde0 663 bool status = false;
Vanger 56:43205bd2752a 664 int socketInfo = ERROR;
Vanger 33:3b6f3904dde0 665 std::vector<std::string> params;
igalt 81:b0a720f7deae 666
Vanger 33:3b6f3904dde0 667 //Goes from data mode to command mode
Vanger 33:3b6f3904dde0 668 if(sendEscapeCommand()) {
Vanger 52:2cb58398a4f9 669 std::string reply = sendCommand("AT#SS=1", 2000);
Vanger 52:2cb58398a4f9 670 if(reply.find("OK") != std::string::npos) {
Vanger 52:2cb58398a4f9 671 //Found valid response
Vanger 52:2cb58398a4f9 672 params = Text::split(reply, "\r\n");
Vanger 52:2cb58398a4f9 673 params = Text::split(params[1], ",");
Vanger 52:2cb58398a4f9 674 socketInfo = atoi(params[1].c_str());
Vanger 52:2cb58398a4f9 675 } else {
Vanger 52:2cb58398a4f9 676 logError("Could not determine socket status[%d]",socketInfo);
Vanger 56:43205bd2752a 677 socketInfo = ERROR;
Vanger 33:3b6f3904dde0 678 }
Vanger 33:3b6f3904dde0 679 } else {
Vanger 33:3b6f3904dde0 680 status = false; //Return value of socketOpened when checking
Vanger 33:3b6f3904dde0 681 }
igalt 81:b0a720f7deae 682
Vanger 33:3b6f3904dde0 683 //Check socket status query
Vanger 56:43205bd2752a 684 if(socketInfo == SOCKETINCOMING || socketInfo == SOCKETACTIVEDATA || socketInfo == SOCKETSUSPEND || socketInfo == SOCKETSUSPENDDATA || socketInfo == SOCKETLISTEN) { //Socket opened responses
Vanger 52:2cb58398a4f9 685 status = true;
Vanger 52:2cb58398a4f9 686 } else if(socketInfo == SOCKETCLOSED || socketInfo == SOCKETINCOMING) {
Vanger 52:2cb58398a4f9 687 status = false;
Vanger 33:3b6f3904dde0 688 } else {
Vanger 54:a6c738bfc391 689 logError("Could not determine socket status[%d]",socketInfo);
Vanger 52:2cb58398a4f9 690 status = false;
Vanger 33:3b6f3904dde0 691 }
igalt 81:b0a720f7deae 692
Vanger 52:2cb58398a4f9 693 //Reconnect to active socket if able
Vanger 33:3b6f3904dde0 694 if(status) {
Vanger 33:3b6f3904dde0 695 std::string reconnect = sendCommand("AT#SO=1", 2000);
Vanger 33:3b6f3904dde0 696 if(reconnect.find("CONNECT") != std::string::npos || reconnect.find("OK") != std::string::npos) {
Vanger 33:3b6f3904dde0 697 } else {
Vanger 33:3b6f3904dde0 698 logError("Failed to resume socket connection");
Vanger 33:3b6f3904dde0 699 }
Vanger 33:3b6f3904dde0 700 }
Vanger 33:3b6f3904dde0 701 return status;
Vanger 33:3b6f3904dde0 702 }
mfiore 78:fc9d2b983744 703
igalt 81:b0a720f7deae 704 bool EasyIP::GPSenable()
igalt 81:b0a720f7deae 705 {
mfiore 78:fc9d2b983744 706 //The HE910 returns an ERROR if you try to enable when it is already enabled.
mfiore 78:fc9d2b983744 707 // That's why we need to check if GPS is enabled before enabling it.
mfiore 78:fc9d2b983744 708 if(GPSenabled()) {
mfiore 78:fc9d2b983744 709 logInfo("GPS was already enabled.");
mfiore 78:fc9d2b983744 710 return true;
mfiore 78:fc9d2b983744 711 }
igalt 81:b0a720f7deae 712 //The LE910-NAG requires AT$GPSSLSR=2,3 to enable GPS but can use AT$GPSP=0 to disable it.
igalt 81:b0a720f7deae 713 if(type == MTSMC_LAT1) {
mfiore 78:fc9d2b983744 714 Code code = sendBasicCommand("AT$GPSSLSR=2,3", 2000);
mfiore 78:fc9d2b983744 715 if (code == MTS_SUCCESS) {
igalt 81:b0a720f7deae 716 gpsEnabled = true;
mfiore 78:fc9d2b983744 717 logInfo("GPS enabled.");
mfiore 78:fc9d2b983744 718 return true;
mfiore 78:fc9d2b983744 719 } else {
igalt 81:b0a720f7deae 720 logError("Enable GPS failed!");
mfiore 78:fc9d2b983744 721 return false;
igalt 81:b0a720f7deae 722 }
mfiore 78:fc9d2b983744 723 } else {
mfiore 78:fc9d2b983744 724 Code code = sendBasicCommand("AT$GPSP=1", 2000);
mfiore 78:fc9d2b983744 725 if (code == MTS_SUCCESS) {
igalt 81:b0a720f7deae 726 gpsEnabled = true;
mfiore 78:fc9d2b983744 727 logInfo("GPS enabled.");
mfiore 78:fc9d2b983744 728 return true;
mfiore 78:fc9d2b983744 729 } else {
mfiore 78:fc9d2b983744 730 logError("Enable GPS failed.");
mfiore 78:fc9d2b983744 731 return false;
mfiore 78:fc9d2b983744 732 }
mfiore 78:fc9d2b983744 733 }
mfiore 78:fc9d2b983744 734 }
mfiore 78:fc9d2b983744 735
igalt 81:b0a720f7deae 736 bool EasyIP::GPSdisable()
igalt 81:b0a720f7deae 737 {
mfiore 78:fc9d2b983744 738 // The HE910 returns an ERROR if you try to disable when it is already disabled.
mfiore 78:fc9d2b983744 739 // That's why we need to check if GPS is disabled before disabling it.
mfiore 78:fc9d2b983744 740 if(!GPSenabled()) {
mfiore 78:fc9d2b983744 741 logInfo("GPS was already disabled.");
mfiore 78:fc9d2b983744 742 return true;
mfiore 78:fc9d2b983744 743 }
mfiore 78:fc9d2b983744 744 Code code = sendBasicCommand("AT$GPSP=0", 2000);
mfiore 78:fc9d2b983744 745 if (code == MTS_SUCCESS) {
igalt 81:b0a720f7deae 746 gpsEnabled = false;
mfiore 78:fc9d2b983744 747 logInfo("GPS disabled.");
mfiore 78:fc9d2b983744 748 return true;
mfiore 78:fc9d2b983744 749 } else {
mfiore 78:fc9d2b983744 750 logError("Disable GPS failed.");
mfiore 78:fc9d2b983744 751 return false;
mfiore 78:fc9d2b983744 752 }
mfiore 78:fc9d2b983744 753 }
mfiore 78:fc9d2b983744 754
igalt 81:b0a720f7deae 755 bool EasyIP::GPSenabled()
igalt 81:b0a720f7deae 756 {
mfiore 78:fc9d2b983744 757 std::string reply = sendCommand("AT$GPSP?", 1000);
mfiore 78:fc9d2b983744 758 if(reply.find("1") != std::string::npos) {
mfiore 78:fc9d2b983744 759 gpsEnabled = true;
mfiore 78:fc9d2b983744 760 return true;
mfiore 78:fc9d2b983744 761 } else {
mfiore 78:fc9d2b983744 762 gpsEnabled = false;
mfiore 78:fc9d2b983744 763 return false;
mfiore 78:fc9d2b983744 764 }
mfiore 78:fc9d2b983744 765 }
mfiore 78:fc9d2b983744 766
igalt 81:b0a720f7deae 767 Cellular::gpsData EasyIP::GPSgetPosition()
igalt 81:b0a720f7deae 768 {
igalt 81:b0a720f7deae 769 enum gpsFields {time, latitude, longitude, hdop, altitude, fix, cog, kmhr, knots, date, satellites, numOfFields };
mfiore 78:fc9d2b983744 770 Cellular::gpsData position;
mfiore 78:fc9d2b983744 771 if(!gpsEnabled) {
mfiore 78:fc9d2b983744 772 logError("GPS is disabled... can't get position.");
mfiore 78:fc9d2b983744 773 position.success = false;
mfiore 78:fc9d2b983744 774 return position;
mfiore 78:fc9d2b983744 775 }
mfiore 78:fc9d2b983744 776 // Get the position information in string format.
mfiore 78:fc9d2b983744 777 std::string gps = sendCommand("AT$GPSACP?", 1000);
mfiore 78:fc9d2b983744 778 if(gps.find("OK") != std::string::npos) {
mfiore 78:fc9d2b983744 779 position.success = true;
mfiore 78:fc9d2b983744 780 // Remove echoed AT$GPSACP and leading non position characters.
mfiore 78:fc9d2b983744 781 gps.erase(0,22);
mfiore 78:fc9d2b983744 782 // Remove trailing CR/LF, CR/LF, OK and CR/LF.
mfiore 78:fc9d2b983744 783 gps.erase(gps.end()-8, gps.end());
mfiore 78:fc9d2b983744 784 // Split remaining data and load into corresponding structure fields.
igalt 81:b0a720f7deae 785
igalt 81:b0a720f7deae 786 // Igal
igalt 81:b0a720f7deae 787 DBG("GPS raw response: %s", gps);
igalt 81:b0a720f7deae 788
mfiore 78:fc9d2b983744 789 std::vector<std::string> gpsParts = Text::split(gps, ',');
mfiore 78:fc9d2b983744 790 // Check size.
mfiore 78:fc9d2b983744 791 if(gpsParts.size() != numOfFields) {
mfiore 78:fc9d2b983744 792 logError("Expected %d fields but there are %d fields in \"%s\"", numOfFields, gpsParts.size(), gps.c_str());
mfiore 78:fc9d2b983744 793 position.success = false;
igalt 81:b0a720f7deae 794 return position;
mfiore 78:fc9d2b983744 795 }
mfiore 78:fc9d2b983744 796 position.latitude = gpsParts[latitude];
igalt 81:b0a720f7deae 797 // (Igal) if received empty gps message return "fail"
igalt 81:b0a720f7deae 798 if ( (0 == position.latitude.compare("")) || (0 == position.latitude.compare("0"))) {
igalt 81:b0a720f7deae 799 logError("GPS returned status OK but data is still invalid (e.g. Gps.latitude = %s).\r\n",position.latitude);
igalt 81:b0a720f7deae 800 position.success = false;
igalt 81:b0a720f7deae 801 return position;
igalt 81:b0a720f7deae 802 }
mfiore 78:fc9d2b983744 803 position.longitude = gpsParts[longitude];
mfiore 78:fc9d2b983744 804 position.hdop = atof(gpsParts[hdop].c_str());
mfiore 78:fc9d2b983744 805 position.altitude = atof(gpsParts[altitude].c_str());
mfiore 78:fc9d2b983744 806 position.fix = atoi(gpsParts[fix].c_str());
mfiore 78:fc9d2b983744 807 position.cog = gpsParts[cog];
mfiore 78:fc9d2b983744 808 position.kmhr = atof(gpsParts[kmhr].c_str());
mfiore 78:fc9d2b983744 809 position.knots = atof(gpsParts[knots].c_str());
mfiore 78:fc9d2b983744 810 position.satellites = atoi(gpsParts[satellites].c_str());
mfiore 78:fc9d2b983744 811 if((gpsParts[date].size() == 6) && (gpsParts[time].size() == 10)) {
igalt 81:b0a720f7deae 812 position.timestamp = gpsParts[date].substr(4,2) + "/" + gpsParts[date].substr(2,2) +
igalt 81:b0a720f7deae 813 "/" + gpsParts[date].substr(0,2) + ", " + gpsParts[time].substr(0,2) +
igalt 81:b0a720f7deae 814 ":" + gpsParts[time].substr(2,2) + ":" + gpsParts[time].substr(4,6);
mfiore 78:fc9d2b983744 815 }
igalt 81:b0a720f7deae 816 return position;
mfiore 78:fc9d2b983744 817 } else {
mfiore 78:fc9d2b983744 818 position.success = false;
mfiore 78:fc9d2b983744 819 logError("NO \"OK\" returned from GPS position command \"AT$GPSACP?\".");
mfiore 78:fc9d2b983744 820 return position;
mfiore 78:fc9d2b983744 821 }
igalt 81:b0a720f7deae 822 }
igalt 81:b0a720f7deae 823
igalt 81:b0a720f7deae 824 bool EasyIP::GPSgotFix()
igalt 81:b0a720f7deae 825 {
mfiore 78:fc9d2b983744 826 if(!gpsEnabled) {
mfiore 78:fc9d2b983744 827 logError("GPS is disabled... can't get fix.");
mfiore 78:fc9d2b983744 828 return false;
mfiore 78:fc9d2b983744 829 }
mfiore 78:fc9d2b983744 830 Cellular::gpsData position = GPSgetPosition();
mfiore 78:fc9d2b983744 831 if(!position.success) {
mfiore 78:fc9d2b983744 832 return false;
igalt 81:b0a720f7deae 833 } else if(position.fix < 2) {
mfiore 78:fc9d2b983744 834 logWarning("No GPS fix. GPS fix can take a few minutes. Check GPS antenna attachment and placement.");
mfiore 78:fc9d2b983744 835 return false;
mfiore 78:fc9d2b983744 836 } else {
mfiore 78:fc9d2b983744 837 logInfo("Got GPS fix.");
mfiore 78:fc9d2b983744 838 return true;
mfiore 78:fc9d2b983744 839 }
mfiore 78:fc9d2b983744 840 }