Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of MTS-Cellular by
Cellular/EasyIP.cpp@78:fc9d2b983744, 2015-08-17 (annotated)
- Committer:
- mfiore
- Date:
- Mon Aug 17 21:05:41 2015 +0000
- Revision:
- 78:fc9d2b983744
- Parent:
- 76:6eeffc10739d
- Child:
- 81:b0a720f7deae
add GPS support for EasyIP models
Who changed what in which revision?
User | Revision | Line number | New 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 |
Mike Fiore |
76:6eeffc10739d | 55 | snprintf(buf, sizeof(buf), "AT#SCFG=1,%d,300,90,600,1", type == MTSMC_LVW2 ? 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]; |
Mike Fiore |
76:6eeffc10739d | 115 | snprintf(buf, sizeof(buf), "AT#SGACT=%d,1", type == MTSMC_LVW2 ? 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 { |
Mike Fiore |
76:6eeffc10739d | 130 | snprintf(buf, sizeof(buf), "%d,1", type == MTSMC_LVW2 ? 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]; |
Mike Fiore |
76:6eeffc10739d | 158 | snprintf(buf, sizeof(buf), "AT#SGACT=%d,0", type == MTSMC_LVW2 ? 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]; |
Mike Fiore |
76:6eeffc10739d | 172 | snprintf(buf, sizeof(buf), "%d,0", type == MTSMC_LVW2 ? 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); |
Mike Fiore |
76:6eeffc10739d | 225 | snprintf(buf, sizeof(buf), "%d,1", type == MTSMC_LVW2 ? 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; |
Mike Fiore |
76:6eeffc10739d | 529 | } else if (type == MTSMC_LAT1 || type == MTSMC_LEU1) { |
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; |
Vanger | 26:2b769ed8de4f | 537 | } else { |
Vanger | 26:2b769ed8de4f | 538 | logInfo("CDMA radios don't need an APN"); |
Vanger | 26:2b769ed8de4f | 539 | return MTS_SUCCESS; |
Vanger | 26:2b769ed8de4f | 540 | } |
Vanger | 26:2b769ed8de4f | 541 | } |
Vanger | 27:ec44d5a9544f | 542 | |
Vanger | 26:2b769ed8de4f | 543 | bool EasyIP::ping(const std::string& address) |
Vanger | 26:2b769ed8de4f | 544 | { |
Vanger | 26:2b769ed8de4f | 545 | char buffer[256] = {0}; |
Vanger | 27:ec44d5a9544f | 546 | std::vector<std::string> parts; |
Vanger | 27:ec44d5a9544f | 547 | int TTL=0; |
Vanger | 27:ec44d5a9544f | 548 | int Timeout=0; |
Vanger | 27:ec44d5a9544f | 549 | |
Vanger | 27:ec44d5a9544f | 550 | //Format parameters for sending to radio |
Vanger | 30:1326b623919a | 551 | sprintf(buffer, "AT#PING=%s,1,32,%d", address.c_str(), (PINGDELAY*10)); |
Vanger | 26:2b769ed8de4f | 552 | |
Vanger | 27:ec44d5a9544f | 553 | for(int pngs=0; pngs<PINGNUM; pngs++) { |
Vanger | 35:257eb41405e1 | 554 | std::string response = sendCommand(buffer, (PINGDELAY*2000)); //Send 1 ping |
Vanger | 52:2cb58398a4f9 | 555 | if(response.empty() || response.find("ERROR") != std::string::npos) { |
Vanger | 28:f93d7b3f7c2e | 556 | continue; //Skip current loop if send command fails |
Vanger | 28:f93d7b3f7c2e | 557 | } |
Vanger | 27:ec44d5a9544f | 558 | parts = Text::split(response, "\r\n"); |
Vanger | 28:f93d7b3f7c2e | 559 | if(parts.size() < 2) { |
Vanger | 28:f93d7b3f7c2e | 560 | continue; |
Vanger | 28:f93d7b3f7c2e | 561 | } |
Vanger | 27:ec44d5a9544f | 562 | parts = Text::split(parts[1], ","); |
Vanger | 28:f93d7b3f7c2e | 563 | if(parts.size() < 4) { |
Vanger | 28:f93d7b3f7c2e | 564 | continue; |
Vanger | 28:f93d7b3f7c2e | 565 | } |
Vanger | 27:ec44d5a9544f | 566 | //Parse TTL and Timeout values |
Vanger | 27:ec44d5a9544f | 567 | Timeout = std::atoi(parts[2].c_str()); |
Vanger | 27:ec44d5a9544f | 568 | TTL = std::atoi(parts[3].c_str()); |
Vanger | 27:ec44d5a9544f | 569 | |
Vanger | 27:ec44d5a9544f | 570 | if((Timeout < 600) && (TTL < 255)) { |
Vanger | 27:ec44d5a9544f | 571 | return true; |
Vanger | 27:ec44d5a9544f | 572 | } |
Vanger | 52:2cb58398a4f9 | 573 | } |
Vanger | 26:2b769ed8de4f | 574 | return false; |
Vanger | 26:2b769ed8de4f | 575 | } |
Vanger | 26:2b769ed8de4f | 576 | |
Vanger | 33:3b6f3904dde0 | 577 | bool EasyIP::sendEscapeCommand() |
Vanger | 33:3b6f3904dde0 | 578 | { |
Vanger | 33:3b6f3904dde0 | 579 | //string Cellular::sendCommand(const std::string& command, unsigned int timeoutMillis, char esc) |
Vanger | 33:3b6f3904dde0 | 580 | if(io == NULL) { |
Vanger | 33:3b6f3904dde0 | 581 | logError("MTSBufferedIO not set"); |
Vanger | 33:3b6f3904dde0 | 582 | return false; |
Vanger | 33:3b6f3904dde0 | 583 | } |
Vanger | 33:3b6f3904dde0 | 584 | if(!socketOpened) { |
Vanger | 52:2cb58398a4f9 | 585 | logError("Socket is not open."); |
Vanger | 52:2cb58398a4f9 | 586 | return false; |
Vanger | 33:3b6f3904dde0 | 587 | } |
Vanger | 33:3b6f3904dde0 | 588 | |
Vanger | 33:3b6f3904dde0 | 589 | if(!socketCloseable) { |
Vanger | 33:3b6f3904dde0 | 590 | logError("Socket is not closeable"); |
Vanger | 33:3b6f3904dde0 | 591 | return false; |
Vanger | 33:3b6f3904dde0 | 592 | } |
Vanger | 33:3b6f3904dde0 | 593 | |
Vanger | 33:3b6f3904dde0 | 594 | io->rxClear(); |
Vanger | 33:3b6f3904dde0 | 595 | io->txClear(); |
Vanger | 33:3b6f3904dde0 | 596 | |
Vanger | 33:3b6f3904dde0 | 597 | std::string result; |
Vanger | 52:2cb58398a4f9 | 598 | unsigned int timeoutMillis = 10000; |
Vanger | 33:3b6f3904dde0 | 599 | //Attempt to write command |
Vanger | 52:2cb58398a4f9 | 600 | //Format for +++ command is 1 second wait, send +++, then another second wait |
Vanger | 52:2cb58398a4f9 | 601 | wait(1.2); |
Vanger | 49:1fc51c53cebf | 602 | if(io->write("+++", 3, timeoutMillis) != 3) { |
Vanger | 33:3b6f3904dde0 | 603 | //Failed to write command |
Vanger | 33:3b6f3904dde0 | 604 | logError("failed to send command to radio within %d milliseconds", timeoutMillis); |
Vanger | 33:3b6f3904dde0 | 605 | return false; |
Vanger | 33:3b6f3904dde0 | 606 | } |
Vanger | 33:3b6f3904dde0 | 607 | |
Vanger | 52:2cb58398a4f9 | 608 | Timer tmr; |
Vanger | 33:3b6f3904dde0 | 609 | char tmp[256]; |
Vanger | 33:3b6f3904dde0 | 610 | tmp[255] = 0; |
Vanger | 33:3b6f3904dde0 | 611 | bool done = false; |
Vanger | 33:3b6f3904dde0 | 612 | bool exitmode = false; |
Vanger | 52:2cb58398a4f9 | 613 | tmr.start(); |
Vanger | 33:3b6f3904dde0 | 614 | do { |
Vanger | 33:3b6f3904dde0 | 615 | //Make a non-blocking read call by passing timeout of zero |
Vanger | 52:2cb58398a4f9 | 616 | int size = io->read(tmp,255,0); //1 less than allocated (timeout is instant) |
Vanger | 52:2cb58398a4f9 | 617 | if(size > 0) { |
Vanger | 52:2cb58398a4f9 | 618 | result.append(tmp, size); |
Vanger | 52:2cb58398a4f9 | 619 | } |
Vanger | 54:a6c738bfc391 | 620 | if(result.find("OK\r\n") != std::string::npos) { |
Vanger | 33:3b6f3904dde0 | 621 | exitmode = true; |
Vanger | 33:3b6f3904dde0 | 622 | done = true; |
Vanger | 54:a6c738bfc391 | 623 | } else if(result.find("NO CARRIER\r\n") != std::string::npos) { |
Vanger | 52:2cb58398a4f9 | 624 | socketOpened = false; |
Vanger | 33:3b6f3904dde0 | 625 | exitmode = true; |
Vanger | 33:3b6f3904dde0 | 626 | done = true; |
Vanger | 33:3b6f3904dde0 | 627 | } else if(result.find("ERROR") != std::string::npos) { |
Vanger | 33:3b6f3904dde0 | 628 | exitmode = false; |
Vanger | 33:3b6f3904dde0 | 629 | done = true; |
Vanger | 33:3b6f3904dde0 | 630 | } |
Vanger | 52:2cb58398a4f9 | 631 | if(tmr.read_ms() >= timeoutMillis) { |
Vanger | 33:3b6f3904dde0 | 632 | logDebug("Escape sequence [+++] timed out after %d milliseconds", timeoutMillis); |
Vanger | 33:3b6f3904dde0 | 633 | exitmode = true; |
Vanger | 33:3b6f3904dde0 | 634 | done = true; |
Vanger | 33:3b6f3904dde0 | 635 | } |
Vanger | 33:3b6f3904dde0 | 636 | } while (!done); |
Vanger | 33:3b6f3904dde0 | 637 | |
Vanger | 54:a6c738bfc391 | 638 | wait(0.1); //Without a slight wait time after receiving OK, radio would |
Vanger | 54:a6c738bfc391 | 639 | //fail to correctly receive and respond to the next AT command |
Vanger | 33:3b6f3904dde0 | 640 | return exitmode; |
Vanger | 33:3b6f3904dde0 | 641 | } |
Vanger | 33:3b6f3904dde0 | 642 | |
Vanger | 33:3b6f3904dde0 | 643 | bool EasyIP::socketCheck() { |
Vanger | 57:7eb2eb536d4a | 644 | enum SocketStatus {SOCKETCLOSED = 0, SOCKETACTIVEDATA = 1, SOCKETSUSPEND = 2, SOCKETSUSPENDDATA = 3, SOCKETLISTEN = 4, SOCKETINCOMING = 5, ERROR = 9}; |
Vanger | 33:3b6f3904dde0 | 645 | bool status = false; |
Vanger | 56:43205bd2752a | 646 | int socketInfo = ERROR; |
Vanger | 33:3b6f3904dde0 | 647 | std::vector<std::string> params; |
Vanger | 33:3b6f3904dde0 | 648 | |
Vanger | 33:3b6f3904dde0 | 649 | //Goes from data mode to command mode |
Vanger | 33:3b6f3904dde0 | 650 | if(sendEscapeCommand()) { |
Vanger | 52:2cb58398a4f9 | 651 | std::string reply = sendCommand("AT#SS=1", 2000); |
Vanger | 52:2cb58398a4f9 | 652 | if(reply.find("OK") != std::string::npos) { |
Vanger | 52:2cb58398a4f9 | 653 | //Found valid response |
Vanger | 52:2cb58398a4f9 | 654 | params = Text::split(reply, "\r\n"); |
Vanger | 52:2cb58398a4f9 | 655 | params = Text::split(params[1], ","); |
Vanger | 52:2cb58398a4f9 | 656 | socketInfo = atoi(params[1].c_str()); |
Vanger | 52:2cb58398a4f9 | 657 | } else { |
Vanger | 52:2cb58398a4f9 | 658 | logError("Could not determine socket status[%d]",socketInfo); |
Vanger | 56:43205bd2752a | 659 | socketInfo = ERROR; |
Vanger | 33:3b6f3904dde0 | 660 | } |
Vanger | 33:3b6f3904dde0 | 661 | } else { |
Vanger | 33:3b6f3904dde0 | 662 | status = false; //Return value of socketOpened when checking |
Vanger | 33:3b6f3904dde0 | 663 | } |
Vanger | 33:3b6f3904dde0 | 664 | |
Vanger | 33:3b6f3904dde0 | 665 | //Check socket status query |
Vanger | 56:43205bd2752a | 666 | if(socketInfo == SOCKETINCOMING || socketInfo == SOCKETACTIVEDATA || socketInfo == SOCKETSUSPEND || socketInfo == SOCKETSUSPENDDATA || socketInfo == SOCKETLISTEN) { //Socket opened responses |
Vanger | 52:2cb58398a4f9 | 667 | status = true; |
Vanger | 52:2cb58398a4f9 | 668 | } else if(socketInfo == SOCKETCLOSED || socketInfo == SOCKETINCOMING) { |
Vanger | 52:2cb58398a4f9 | 669 | status = false; |
Vanger | 33:3b6f3904dde0 | 670 | } else { |
Vanger | 54:a6c738bfc391 | 671 | logError("Could not determine socket status[%d]",socketInfo); |
Vanger | 52:2cb58398a4f9 | 672 | status = false; |
Vanger | 33:3b6f3904dde0 | 673 | } |
Vanger | 33:3b6f3904dde0 | 674 | |
Vanger | 52:2cb58398a4f9 | 675 | //Reconnect to active socket if able |
Vanger | 33:3b6f3904dde0 | 676 | if(status) { |
Vanger | 33:3b6f3904dde0 | 677 | std::string reconnect = sendCommand("AT#SO=1", 2000); |
Vanger | 33:3b6f3904dde0 | 678 | if(reconnect.find("CONNECT") != std::string::npos || reconnect.find("OK") != std::string::npos) { |
Vanger | 33:3b6f3904dde0 | 679 | } else { |
Vanger | 33:3b6f3904dde0 | 680 | logError("Failed to resume socket connection"); |
Vanger | 33:3b6f3904dde0 | 681 | } |
Vanger | 33:3b6f3904dde0 | 682 | } |
Vanger | 33:3b6f3904dde0 | 683 | return status; |
Vanger | 33:3b6f3904dde0 | 684 | } |
mfiore | 78:fc9d2b983744 | 685 | |
mfiore | 78:fc9d2b983744 | 686 | bool EasyIP::GPSenable() { |
mfiore | 78:fc9d2b983744 | 687 | //The HE910 returns an ERROR if you try to enable when it is already enabled. |
mfiore | 78:fc9d2b983744 | 688 | // That's why we need to check if GPS is enabled before enabling it. |
mfiore | 78:fc9d2b983744 | 689 | if(GPSenabled()) { |
mfiore | 78:fc9d2b983744 | 690 | logInfo("GPS was already enabled."); |
mfiore | 78:fc9d2b983744 | 691 | return true; |
mfiore | 78:fc9d2b983744 | 692 | } |
mfiore | 78:fc9d2b983744 | 693 | //The LE910-NAG requires AT$GPSSLSR=2,3 to enable GPS but can use AT$GPSP=0 to disable it. |
mfiore | 78:fc9d2b983744 | 694 | if(type == MTSMC_LAT1){ |
mfiore | 78:fc9d2b983744 | 695 | Code code = sendBasicCommand("AT$GPSSLSR=2,3", 2000); |
mfiore | 78:fc9d2b983744 | 696 | if (code == MTS_SUCCESS) { |
mfiore | 78:fc9d2b983744 | 697 | gpsEnabled = true; |
mfiore | 78:fc9d2b983744 | 698 | logInfo("GPS enabled."); |
mfiore | 78:fc9d2b983744 | 699 | return true; |
mfiore | 78:fc9d2b983744 | 700 | } else { |
mfiore | 78:fc9d2b983744 | 701 | logError("Enable GPS failed!"); |
mfiore | 78:fc9d2b983744 | 702 | return false; |
mfiore | 78:fc9d2b983744 | 703 | } |
mfiore | 78:fc9d2b983744 | 704 | } else { |
mfiore | 78:fc9d2b983744 | 705 | Code code = sendBasicCommand("AT$GPSP=1", 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 | } |
mfiore | 78:fc9d2b983744 | 715 | } |
mfiore | 78:fc9d2b983744 | 716 | |
mfiore | 78:fc9d2b983744 | 717 | bool EasyIP::GPSdisable() { |
mfiore | 78:fc9d2b983744 | 718 | // The HE910 returns an ERROR if you try to disable when it is already disabled. |
mfiore | 78:fc9d2b983744 | 719 | // That's why we need to check if GPS is disabled before disabling it. |
mfiore | 78:fc9d2b983744 | 720 | if(!GPSenabled()) { |
mfiore | 78:fc9d2b983744 | 721 | logInfo("GPS was already disabled."); |
mfiore | 78:fc9d2b983744 | 722 | return true; |
mfiore | 78:fc9d2b983744 | 723 | } |
mfiore | 78:fc9d2b983744 | 724 | Code code = sendBasicCommand("AT$GPSP=0", 2000); |
mfiore | 78:fc9d2b983744 | 725 | if (code == MTS_SUCCESS) { |
mfiore | 78:fc9d2b983744 | 726 | gpsEnabled = false; |
mfiore | 78:fc9d2b983744 | 727 | logInfo("GPS disabled."); |
mfiore | 78:fc9d2b983744 | 728 | return true; |
mfiore | 78:fc9d2b983744 | 729 | } else { |
mfiore | 78:fc9d2b983744 | 730 | logError("Disable GPS failed."); |
mfiore | 78:fc9d2b983744 | 731 | return false; |
mfiore | 78:fc9d2b983744 | 732 | } |
mfiore | 78:fc9d2b983744 | 733 | } |
mfiore | 78:fc9d2b983744 | 734 | |
mfiore | 78:fc9d2b983744 | 735 | bool EasyIP::GPSenabled() { |
mfiore | 78:fc9d2b983744 | 736 | std::string reply = sendCommand("AT$GPSP?", 1000); |
mfiore | 78:fc9d2b983744 | 737 | if(reply.find("1") != std::string::npos) { |
mfiore | 78:fc9d2b983744 | 738 | gpsEnabled = true; |
mfiore | 78:fc9d2b983744 | 739 | return true; |
mfiore | 78:fc9d2b983744 | 740 | } else { |
mfiore | 78:fc9d2b983744 | 741 | gpsEnabled = false; |
mfiore | 78:fc9d2b983744 | 742 | return false; |
mfiore | 78:fc9d2b983744 | 743 | } |
mfiore | 78:fc9d2b983744 | 744 | } |
mfiore | 78:fc9d2b983744 | 745 | |
mfiore | 78:fc9d2b983744 | 746 | Cellular::gpsData EasyIP::GPSgetPosition(){ |
mfiore | 78:fc9d2b983744 | 747 | enum gpsFields{time, latitude, longitude, hdop, altitude, fix, cog, kmhr, knots, date, satellites, numOfFields }; |
mfiore | 78:fc9d2b983744 | 748 | Cellular::gpsData position; |
mfiore | 78:fc9d2b983744 | 749 | if(!gpsEnabled) { |
mfiore | 78:fc9d2b983744 | 750 | logError("GPS is disabled... can't get position."); |
mfiore | 78:fc9d2b983744 | 751 | position.success = false; |
mfiore | 78:fc9d2b983744 | 752 | return position; |
mfiore | 78:fc9d2b983744 | 753 | } |
mfiore | 78:fc9d2b983744 | 754 | // Get the position information in string format. |
mfiore | 78:fc9d2b983744 | 755 | std::string gps = sendCommand("AT$GPSACP?", 1000); |
mfiore | 78:fc9d2b983744 | 756 | if(gps.find("OK") != std::string::npos) { |
mfiore | 78:fc9d2b983744 | 757 | position.success = true; |
mfiore | 78:fc9d2b983744 | 758 | // Remove echoed AT$GPSACP and leading non position characters. |
mfiore | 78:fc9d2b983744 | 759 | gps.erase(0,22); |
mfiore | 78:fc9d2b983744 | 760 | // Remove trailing CR/LF, CR/LF, OK and CR/LF. |
mfiore | 78:fc9d2b983744 | 761 | gps.erase(gps.end()-8, gps.end()); |
mfiore | 78:fc9d2b983744 | 762 | // Split remaining data and load into corresponding structure fields. |
mfiore | 78:fc9d2b983744 | 763 | std::vector<std::string> gpsParts = Text::split(gps, ','); |
mfiore | 78:fc9d2b983744 | 764 | // Check size. |
mfiore | 78:fc9d2b983744 | 765 | if(gpsParts.size() != numOfFields) { |
mfiore | 78:fc9d2b983744 | 766 | logError("Expected %d fields but there are %d fields in \"%s\"", numOfFields, gpsParts.size(), gps.c_str()); |
mfiore | 78:fc9d2b983744 | 767 | position.success = false; |
mfiore | 78:fc9d2b983744 | 768 | return position; |
mfiore | 78:fc9d2b983744 | 769 | } |
mfiore | 78:fc9d2b983744 | 770 | position.latitude = gpsParts[latitude]; |
mfiore | 78:fc9d2b983744 | 771 | position.longitude = gpsParts[longitude]; |
mfiore | 78:fc9d2b983744 | 772 | position.hdop = atof(gpsParts[hdop].c_str()); |
mfiore | 78:fc9d2b983744 | 773 | position.altitude = atof(gpsParts[altitude].c_str()); |
mfiore | 78:fc9d2b983744 | 774 | position.fix = atoi(gpsParts[fix].c_str()); |
mfiore | 78:fc9d2b983744 | 775 | position.cog = gpsParts[cog]; |
mfiore | 78:fc9d2b983744 | 776 | position.kmhr = atof(gpsParts[kmhr].c_str()); |
mfiore | 78:fc9d2b983744 | 777 | position.knots = atof(gpsParts[knots].c_str()); |
mfiore | 78:fc9d2b983744 | 778 | position.satellites = atoi(gpsParts[satellites].c_str()); |
mfiore | 78:fc9d2b983744 | 779 | if((gpsParts[date].size() == 6) && (gpsParts[time].size() == 10)) { |
mfiore | 78:fc9d2b983744 | 780 | position.timestamp = gpsParts[date].substr(4,2) + "/" + gpsParts[date].substr(2,2) + |
mfiore | 78:fc9d2b983744 | 781 | "/" + gpsParts[date].substr(0,2) + ", " + gpsParts[time].substr(0,2) + |
mfiore | 78:fc9d2b983744 | 782 | ":" + gpsParts[time].substr(2,2) + ":" + gpsParts[time].substr(4,6); |
mfiore | 78:fc9d2b983744 | 783 | } |
mfiore | 78:fc9d2b983744 | 784 | return position; |
mfiore | 78:fc9d2b983744 | 785 | } else { |
mfiore | 78:fc9d2b983744 | 786 | position.success = false; |
mfiore | 78:fc9d2b983744 | 787 | logError("NO \"OK\" returned from GPS position command \"AT$GPSACP?\"."); |
mfiore | 78:fc9d2b983744 | 788 | return position; |
mfiore | 78:fc9d2b983744 | 789 | } |
mfiore | 78:fc9d2b983744 | 790 | } |
mfiore | 78:fc9d2b983744 | 791 | |
mfiore | 78:fc9d2b983744 | 792 | bool EasyIP::GPSgotFix() { |
mfiore | 78:fc9d2b983744 | 793 | if(!gpsEnabled) { |
mfiore | 78:fc9d2b983744 | 794 | logError("GPS is disabled... can't get fix."); |
mfiore | 78:fc9d2b983744 | 795 | return false; |
mfiore | 78:fc9d2b983744 | 796 | } |
mfiore | 78:fc9d2b983744 | 797 | Cellular::gpsData position = GPSgetPosition(); |
mfiore | 78:fc9d2b983744 | 798 | if(!position.success) { |
mfiore | 78:fc9d2b983744 | 799 | return false; |
mfiore | 78:fc9d2b983744 | 800 | } else if(position.fix < 2){ |
mfiore | 78:fc9d2b983744 | 801 | logWarning("No GPS fix. GPS fix can take a few minutes. Check GPS antenna attachment and placement."); |
mfiore | 78:fc9d2b983744 | 802 | return false; |
mfiore | 78:fc9d2b983744 | 803 | } else { |
mfiore | 78:fc9d2b983744 | 804 | logInfo("Got GPS fix."); |
mfiore | 78:fc9d2b983744 | 805 | return true; |
mfiore | 78:fc9d2b983744 | 806 | } |
mfiore | 78:fc9d2b983744 | 807 | } |