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

Dependents:   mtsas mtsas mtsas mtsas

Committer:
Leon Lindenfelser
Date:
Mon Feb 19 14:25:58 2018 -0600
Revision:
82:5b33b670adb7
Parent:
81:2e12915f892e
Add support for MTQ-LAT3(LE910-NA1) adn MTQ-LVW3(LE910-sv1)

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