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

Dependents:   mtsas mtsas mtsas mtsas

Committer:
Vanger
Date:
Tue Oct 21 21:06:53 2014 +0000
Revision:
67:7c705fe2acec
Parent:
66:8c55e2bf7270
Child:
72:7862171b277d
Fixed close() variables to match Mbed socket API (shutdown instead of clearBuffer)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Mike Fiore 3:04046eebaef5 1 #include "mbed.h"
Mike Fiore 3:04046eebaef5 2 #include "UIP.h"
Mike Fiore 1:f155d94d6f3a 3 #include "MTSText.h"
Mike Fiore 4:1f63354b8d1b 4 #include "MTSLog.h"
Mike Fiore 2:10e72dce251d 5 #include "CellUtils.h"
Mike Fiore 1:f155d94d6f3a 6
Mike Fiore 1:f155d94d6f3a 7 using namespace mts;
Mike Fiore 1:f155d94d6f3a 8
Mike Fiore 11:4e428f689069 9 UIP::UIP(Radio type)
Mike Fiore 1:f155d94d6f3a 10 {
Mike Fiore 11:4e428f689069 11 this->type = type;
Mike Fiore 3:04046eebaef5 12 io = NULL;
Mike Fiore 9:1a03e3f3e7fe 13 dcd = NULL;
Mike Fiore 9:1a03e3f3e7fe 14 dtr = NULL;
Mike Fiore 9:1a03e3f3e7fe 15 resetLine = NULL;
Mike Fiore 3:04046eebaef5 16 echoMode = true;
Mike Fiore 3:04046eebaef5 17 pppConnected = false;
mfiore 19:f6261f1c3dd4 18 socketMode = TCP;
Mike Fiore 3:04046eebaef5 19 socketOpened = false;
Mike Fiore 3:04046eebaef5 20 socketCloseable = true;
Mike Fiore 3:04046eebaef5 21 local_port = 0;
Mike Fiore 3:04046eebaef5 22 local_address = "";
Mike Fiore 3:04046eebaef5 23 host_port = 0;
Mike Fiore 1:f155d94d6f3a 24 }
Mike Fiore 1:f155d94d6f3a 25
Mike Fiore 3:04046eebaef5 26 UIP::~UIP()
Mike Fiore 1:f155d94d6f3a 27 {
Mike Fiore 1:f155d94d6f3a 28 if (dtr != NULL) {
Mike Fiore 1:f155d94d6f3a 29 dtr->write(1);
Mike Fiore 1:f155d94d6f3a 30 }
Mike Fiore 1:f155d94d6f3a 31
Mike Fiore 1:f155d94d6f3a 32 delete dcd;
Mike Fiore 1:f155d94d6f3a 33 delete dtr;
Mike Fiore 1:f155d94d6f3a 34 delete resetLine;
Mike Fiore 1:f155d94d6f3a 35 }
Mike Fiore 1:f155d94d6f3a 36
Mike Fiore 3:04046eebaef5 37 bool UIP::init(MTSBufferedIO* io)
Mike Fiore 1:f155d94d6f3a 38 {
Mike Fiore 8:2d7259d244d1 39 if (! Cellular::init(io)) {
Mike Fiore 1:f155d94d6f3a 40 return false;
Mike Fiore 1:f155d94d6f3a 41 }
Mike Fiore 1:f155d94d6f3a 42
mfiore 17:dee902f7d00e 43 logDebug("radio type: %s", Cellular::getRadioNames(type).c_str());
Mike Fiore 8:2d7259d244d1 44 return true;
Mike Fiore 1:f155d94d6f3a 45 }
Mike Fiore 1:f155d94d6f3a 46
Mike Fiore 3:04046eebaef5 47 bool UIP::connect()
Mike Fiore 1:f155d94d6f3a 48 {
Vanger 52:2cb58398a4f9 49 //Check if APN is not set, if it is not, connect will not work.
Vanger 52:2cb58398a4f9 50 if (type == MTSMC_H5_IP || type == MTSMC_H5 || type == MTSMC_G3) {
Vanger 52:2cb58398a4f9 51 if(apn.size() == 0) {
Vanger 52:2cb58398a4f9 52 logDebug("APN is not set");
Vanger 52:2cb58398a4f9 53 return false;
Vanger 52:2cb58398a4f9 54 }
Vanger 52:2cb58398a4f9 55 }
Vanger 52:2cb58398a4f9 56
Mike Fiore 1:f155d94d6f3a 57 //Check if socket is open
Mike Fiore 1:f155d94d6f3a 58 if(socketOpened) {
Mike Fiore 1:f155d94d6f3a 59 return true;
Mike Fiore 1:f155d94d6f3a 60 }
Mike Fiore 1:f155d94d6f3a 61
Mike Fiore 1:f155d94d6f3a 62 //Check if already connected
Mike Fiore 1:f155d94d6f3a 63 if(isConnected()) {
Mike Fiore 1:f155d94d6f3a 64 return true;
Mike Fiore 1:f155d94d6f3a 65 }
Mike Fiore 1:f155d94d6f3a 66
Mike Fiore 1:f155d94d6f3a 67 Timer tmr;
Mike Fiore 1:f155d94d6f3a 68
Mike Fiore 1:f155d94d6f3a 69 //Check Registration: AT+CREG? == 0,1
Mike Fiore 1:f155d94d6f3a 70 tmr.start();
Mike Fiore 1:f155d94d6f3a 71 do {
Mike Fiore 1:f155d94d6f3a 72 Registration registration = getRegistration();
Mike Fiore 1:f155d94d6f3a 73 if(registration != REGISTERED) {
mfiore 15:700a7662c52e 74 logTrace("Not Registered [%d] ... waiting", (int)registration);
Mike Fiore 1:f155d94d6f3a 75 wait(1);
Mike Fiore 1:f155d94d6f3a 76 } else {
Mike Fiore 1:f155d94d6f3a 77 break;
Mike Fiore 1:f155d94d6f3a 78 }
Mike Fiore 1:f155d94d6f3a 79 } while(tmr.read() < 30);
Mike Fiore 1:f155d94d6f3a 80
Mike Fiore 1:f155d94d6f3a 81 //Check RSSI: AT+CSQ
Mike Fiore 1:f155d94d6f3a 82 tmr.reset();
Mike Fiore 1:f155d94d6f3a 83 do {
Mike Fiore 1:f155d94d6f3a 84 int rssi = getSignalStrength();
Mike Fiore 4:1f63354b8d1b 85 logDebug("Signal strength: %d", rssi);
Vanger 51:ffc556ba33f7 86 if(rssi == 99 || rssi == -1) {
mfiore 15:700a7662c52e 87 logTrace("No Signal ... waiting");
Mike Fiore 1:f155d94d6f3a 88 wait(1);
Mike Fiore 1:f155d94d6f3a 89 } else {
Mike Fiore 1:f155d94d6f3a 90 break;
Mike Fiore 1:f155d94d6f3a 91 }
Mike Fiore 1:f155d94d6f3a 92 } while(tmr.read() < 30);
Mike Fiore 1:f155d94d6f3a 93
Mike Fiore 1:f155d94d6f3a 94 //AT#CONNECTIONSTART: Make a PPP connection
Mike Fiore 13:e443e7e2b605 95 if (type == MTSMC_H5_IP) {
Mike Fiore 13:e443e7e2b605 96 logDebug("Making PPP Connection Attempt. APN[%s]", apn.c_str());
Mike Fiore 13:e443e7e2b605 97 } else {
Mike Fiore 13:e443e7e2b605 98 logDebug("Making PPP Connection Attempt");
Mike Fiore 13:e443e7e2b605 99 }
Mike Fiore 1:f155d94d6f3a 100 std::string pppResult = sendCommand("AT#CONNECTIONSTART", 120000);
Vanger 26:2b769ed8de4f 101
Mike Fiore 1:f155d94d6f3a 102 if(pppResult.find("Ok_Info_GprsActivation") != std::string::npos) {
Vanger 26:2b769ed8de4f 103 std::vector<std::string> parts = Text::split(pppResult, "\r\n");
Mike Fiore 1:f155d94d6f3a 104 if(parts.size() >= 2) {
Mike Fiore 1:f155d94d6f3a 105 local_address = parts[1];
Mike Fiore 1:f155d94d6f3a 106 }
Mike Fiore 4:1f63354b8d1b 107 logInfo("PPP Connection Established: IP[%s]", local_address.c_str());
Mike Fiore 1:f155d94d6f3a 108 pppConnected = true;
Mike Fiore 1:f155d94d6f3a 109
Mike Fiore 1:f155d94d6f3a 110 } else {
Mike Fiore 1:f155d94d6f3a 111 pppConnected = false;
Mike Fiore 1:f155d94d6f3a 112 }
Mike Fiore 1:f155d94d6f3a 113
Mike Fiore 1:f155d94d6f3a 114 return pppConnected;
Mike Fiore 1:f155d94d6f3a 115 }
Mike Fiore 1:f155d94d6f3a 116
Mike Fiore 3:04046eebaef5 117 void UIP::disconnect()
Mike Fiore 1:f155d94d6f3a 118 {
Mike Fiore 1:f155d94d6f3a 119 //AT#CONNECTIONSTOP: Close a PPP connection
Mike Fiore 4:1f63354b8d1b 120 logDebug("Closing PPP Connection");
Mike Fiore 1:f155d94d6f3a 121
Mike Fiore 1:f155d94d6f3a 122 if(socketOpened) {
Vanger 66:8c55e2bf7270 123 close(true);
Mike Fiore 1:f155d94d6f3a 124 }
Mike Fiore 1:f155d94d6f3a 125
Mike Fiore 1:f155d94d6f3a 126 Code code = sendBasicCommand("AT#CONNECTIONSTOP", 10000);
mfiore 18:fa0d8120f81f 127 if(code == MTS_SUCCESS) {
Mike Fiore 4:1f63354b8d1b 128 logDebug("Successfully closed PPP Connection");
Mike Fiore 1:f155d94d6f3a 129 } else {
Mike Fiore 4:1f63354b8d1b 130 logError("Closing PPP Connection [%d]. Continuing ...", (int)code);
Mike Fiore 1:f155d94d6f3a 131 }
Mike Fiore 1:f155d94d6f3a 132
Mike Fiore 1:f155d94d6f3a 133 pppConnected = false;
Mike Fiore 1:f155d94d6f3a 134 }
Mike Fiore 1:f155d94d6f3a 135
Mike Fiore 3:04046eebaef5 136 bool UIP::isConnected()
Mike Fiore 1:f155d94d6f3a 137 {
mfiore 22:c1004a807490 138 //1) Check if APN was set if we're on an HSPA radio
mfiore 22:c1004a807490 139 if (type == MTSMC_H5_IP || type == MTSMC_H5 || type == MTSMC_G3) {
Mike Fiore 13:e443e7e2b605 140 if(apn.size() == 0) {
Mike Fiore 13:e443e7e2b605 141 logDebug("APN is not set");
Mike Fiore 13:e443e7e2b605 142 return false;
Mike Fiore 13:e443e7e2b605 143 }
Mike Fiore 1:f155d94d6f3a 144 }
Mike Fiore 1:f155d94d6f3a 145
Mike Fiore 13:e443e7e2b605 146 //2) Check that we do not have a live connection up
Mike Fiore 1:f155d94d6f3a 147 if(socketOpened) {
Mike Fiore 4:1f63354b8d1b 148 logDebug("Socket is opened");
Mike Fiore 1:f155d94d6f3a 149 return true;
Mike Fiore 1:f155d94d6f3a 150 }
Mike Fiore 13:e443e7e2b605 151 //3) Query the radio
Mike Fiore 1:f155d94d6f3a 152 std::string result = sendCommand("AT#VSTATE", 3000);
Mike Fiore 1:f155d94d6f3a 153 if(result.find("CONNECTED") != std::string::npos) {
Mike Fiore 1:f155d94d6f3a 154 if(pppConnected == false) {
Mike Fiore 4:1f63354b8d1b 155 logWarning("Internal PPP state tracking differs from radio (DISCONNECTED:CONNECTED)");
Mike Fiore 1:f155d94d6f3a 156 }
Mike Fiore 1:f155d94d6f3a 157 pppConnected = true;
Mike Fiore 1:f155d94d6f3a 158 } else {
Mike Fiore 1:f155d94d6f3a 159 if(pppConnected == true) {
Mike Fiore 1:f155d94d6f3a 160 //Find out what state is
Mike Fiore 1:f155d94d6f3a 161 size_t pos = result.find("STATE:");
Mike Fiore 1:f155d94d6f3a 162 if(pos != std::string::npos) {
Mike Fiore 1:f155d94d6f3a 163 result = Text::getLine(result, pos + sizeof("STATE:"), pos);
Mike Fiore 4:1f63354b8d1b 164 logWarning("Internal PPP state tracking differs from radio (CONNECTED:%s)", result.c_str());
Mike Fiore 1:f155d94d6f3a 165 } else {
Mike Fiore 4:1f63354b8d1b 166 logError("Unable to parse radio state: [%s]", result.c_str());
Mike Fiore 1:f155d94d6f3a 167 }
Mike Fiore 1:f155d94d6f3a 168
Mike Fiore 1:f155d94d6f3a 169 }
Mike Fiore 1:f155d94d6f3a 170 pppConnected = false;
Mike Fiore 1:f155d94d6f3a 171 }
Mike Fiore 1:f155d94d6f3a 172
Mike Fiore 1:f155d94d6f3a 173 return pppConnected;
Mike Fiore 1:f155d94d6f3a 174 }
Mike Fiore 1:f155d94d6f3a 175
Mike Fiore 3:04046eebaef5 176 bool UIP::open(const std::string& address, unsigned int port, Mode mode)
Mike Fiore 1:f155d94d6f3a 177 {
Mike Fiore 1:f155d94d6f3a 178 char buffer[256] = {0};
Mike Fiore 1:f155d94d6f3a 179 Code portCode, addressCode;
Vanger 43:91c5e53f508f 180
Mike Fiore 1:f155d94d6f3a 181 //1) Check that we do not have a live connection up
Mike Fiore 1:f155d94d6f3a 182 if(socketOpened) {
Mike Fiore 1:f155d94d6f3a 183 //Check that the address, port, and mode match
mfiore 19:f6261f1c3dd4 184 if(host_address != address || host_port != port || socketMode != mode) {
mfiore 19:f6261f1c3dd4 185 if(socketMode == TCP) {
Mike Fiore 4:1f63354b8d1b 186 logError("TCP socket already opened [%s:%d]", host_address.c_str(), host_port);
Mike Fiore 1:f155d94d6f3a 187 } else {
Mike Fiore 4:1f63354b8d1b 188 logError("UDP socket already opened [%s:%d]", host_address.c_str(), host_port);
Mike Fiore 1:f155d94d6f3a 189 }
Mike Fiore 1:f155d94d6f3a 190 return false;
Mike Fiore 1:f155d94d6f3a 191 }
Mike Fiore 1:f155d94d6f3a 192
Mike Fiore 4:1f63354b8d1b 193 logDebug("Socket already opened");
Mike Fiore 1:f155d94d6f3a 194 return true;
Mike Fiore 1:f155d94d6f3a 195 }
Mike Fiore 1:f155d94d6f3a 196
Mike Fiore 1:f155d94d6f3a 197 //2) Check Parameters
Mike Fiore 1:f155d94d6f3a 198 if(port > 65535) {
Mike Fiore 4:1f63354b8d1b 199 logError("port out of range (0-65535)");
Mike Fiore 1:f155d94d6f3a 200 return false;
Mike Fiore 1:f155d94d6f3a 201 }
Mike Fiore 1:f155d94d6f3a 202
Mike Fiore 1:f155d94d6f3a 203 //3) Check PPP connection
Mike Fiore 1:f155d94d6f3a 204 if(!isConnected()) {
Mike Fiore 4:1f63354b8d1b 205 logError("PPP not established. Attempting to connect");
Mike Fiore 1:f155d94d6f3a 206 if(!connect()) {
Mike Fiore 4:1f63354b8d1b 207 logError("PPP connection failed");
Mike Fiore 1:f155d94d6f3a 208 return false;
Mike Fiore 1:f155d94d6f3a 209 } else {
Mike Fiore 4:1f63354b8d1b 210 logDebug("PPP connection established");
Mike Fiore 1:f155d94d6f3a 211 }
Mike Fiore 1:f155d94d6f3a 212 }
Mike Fiore 1:f155d94d6f3a 213
Mike Fiore 1:f155d94d6f3a 214 //Set Local Port
Mike Fiore 1:f155d94d6f3a 215 if(local_port != 0) {
Mike Fiore 1:f155d94d6f3a 216 //Attempt to set local port
Mike Fiore 1:f155d94d6f3a 217 sprintf(buffer, "AT#OUTPORT=%d", local_port);
Mike Fiore 1:f155d94d6f3a 218 Code code = sendBasicCommand(buffer, 1000);
mfiore 18:fa0d8120f81f 219 if(code != MTS_SUCCESS) {
Mike Fiore 4:1f63354b8d1b 220 logWarning("Unable to set local port (%d) [%d]", local_port, (int) code);
Mike Fiore 1:f155d94d6f3a 221 }
Mike Fiore 1:f155d94d6f3a 222 }
Mike Fiore 1:f155d94d6f3a 223
Mike Fiore 1:f155d94d6f3a 224 //Set TCP/UDP parameters
Mike Fiore 1:f155d94d6f3a 225 if(mode == TCP) {
Mike Fiore 1:f155d94d6f3a 226 if(socketCloseable) {
Mike Fiore 1:f155d94d6f3a 227 Code code = sendBasicCommand("AT#DLEMODE=1,1", 1000);
mfiore 18:fa0d8120f81f 228 if(code != MTS_SUCCESS) {
Mike Fiore 4:1f63354b8d1b 229 logWarning("Unable to set socket closeable [%d]", (int) code);
Mike Fiore 1:f155d94d6f3a 230 }
Mike Fiore 1:f155d94d6f3a 231 }
Mike Fiore 1:f155d94d6f3a 232 sprintf(buffer, "AT#TCPPORT=1,%d", port);
Mike Fiore 1:f155d94d6f3a 233 portCode = sendBasicCommand(buffer, 1000);
Mike Fiore 1:f155d94d6f3a 234 addressCode = sendBasicCommand("AT#TCPSERV=1,\"" + address + "\"", 1000);
Mike Fiore 1:f155d94d6f3a 235 } else {
Mike Fiore 1:f155d94d6f3a 236 if(socketCloseable) {
Mike Fiore 1:f155d94d6f3a 237 Code code = sendBasicCommand("AT#UDPDLEMODE=1", 1000);
mfiore 18:fa0d8120f81f 238 if(code != MTS_SUCCESS) {
Mike Fiore 4:1f63354b8d1b 239 logWarning("Unable to set socket closeable [%d]", (int) code);
Mike Fiore 1:f155d94d6f3a 240 }
Mike Fiore 1:f155d94d6f3a 241 }
Mike Fiore 1:f155d94d6f3a 242 sprintf(buffer, "AT#UDPPORT=%d", port);
Mike Fiore 1:f155d94d6f3a 243 portCode = sendBasicCommand(buffer, 1000);
Mike Fiore 1:f155d94d6f3a 244 addressCode = sendBasicCommand("AT#UDPSERV=\"" + address + "\"", 1000);
Mike Fiore 1:f155d94d6f3a 245 }
Mike Fiore 1:f155d94d6f3a 246
mfiore 18:fa0d8120f81f 247 if(portCode == MTS_SUCCESS) {
Mike Fiore 1:f155d94d6f3a 248 host_port = port;
Mike Fiore 1:f155d94d6f3a 249 } else {
Mike Fiore 4:1f63354b8d1b 250 logError("Host port could not be set");
Mike Fiore 1:f155d94d6f3a 251 }
Mike Fiore 1:f155d94d6f3a 252
mfiore 18:fa0d8120f81f 253 if(addressCode == MTS_SUCCESS) {
Mike Fiore 1:f155d94d6f3a 254 host_address = address;
Mike Fiore 1:f155d94d6f3a 255 } else {
Mike Fiore 4:1f63354b8d1b 256 logError("Host address could not be set");
Mike Fiore 1:f155d94d6f3a 257 }
Mike Fiore 1:f155d94d6f3a 258
Mike Fiore 1:f155d94d6f3a 259 // Try and Connect
Mike Fiore 1:f155d94d6f3a 260 std::string sMode;
Mike Fiore 1:f155d94d6f3a 261 std::string sOpenSocketCmd;
Mike Fiore 1:f155d94d6f3a 262 if(mode == TCP) {
Mike Fiore 1:f155d94d6f3a 263 sOpenSocketCmd = "AT#OTCP=1";
Mike Fiore 1:f155d94d6f3a 264 sMode = "TCP";
Mike Fiore 1:f155d94d6f3a 265 } else {
Mike Fiore 1:f155d94d6f3a 266 sOpenSocketCmd = "AT#OUDP";
Mike Fiore 1:f155d94d6f3a 267 sMode = "UDP";
Mike Fiore 1:f155d94d6f3a 268 }
Mike Fiore 1:f155d94d6f3a 269
Mike Fiore 1:f155d94d6f3a 270 string response = sendCommand(sOpenSocketCmd, 30000);
Mike Fiore 1:f155d94d6f3a 271 if (response.find("Ok_Info_WaitingForData") != string::npos) {
Mike Fiore 4:1f63354b8d1b 272 logInfo("Opened %s Socket [%s:%d]", sMode.c_str(), address.c_str(), port);
Mike Fiore 1:f155d94d6f3a 273 socketOpened = true;
mfiore 19:f6261f1c3dd4 274 socketMode = mode;
Mike Fiore 1:f155d94d6f3a 275 } else {
Mike Fiore 4:1f63354b8d1b 276 logWarning("Unable to open %s Socket [%s:%d]", sMode.c_str(), address.c_str(), port);
Mike Fiore 1:f155d94d6f3a 277 socketOpened = false;
Mike Fiore 1:f155d94d6f3a 278 }
Mike Fiore 1:f155d94d6f3a 279
Mike Fiore 1:f155d94d6f3a 280 return socketOpened;
Mike Fiore 1:f155d94d6f3a 281 }
Mike Fiore 1:f155d94d6f3a 282
Vanger 67:7c705fe2acec 283 bool UIP::close(bool shutdown)
Mike Fiore 1:f155d94d6f3a 284 {
Mike Fiore 1:f155d94d6f3a 285 if(io == NULL) {
Mike Fiore 4:1f63354b8d1b 286 logError("MTSBufferedIO not set");
Mike Fiore 1:f155d94d6f3a 287 return false;
Mike Fiore 1:f155d94d6f3a 288 }
Mike Fiore 1:f155d94d6f3a 289
Mike Fiore 1:f155d94d6f3a 290 if(!socketOpened) {
Mike Fiore 4:1f63354b8d1b 291 logWarning("Socket close() called, but socket was not open");
Mike Fiore 1:f155d94d6f3a 292 return true;
Mike Fiore 1:f155d94d6f3a 293 }
Mike Fiore 1:f155d94d6f3a 294
Mike Fiore 1:f155d94d6f3a 295 if(!socketCloseable) {
Mike Fiore 4:1f63354b8d1b 296 logError("Socket is not closeable");
Mike Fiore 1:f155d94d6f3a 297 return false;
Mike Fiore 1:f155d94d6f3a 298 }
Mike Fiore 1:f155d94d6f3a 299
Mike Fiore 1:f155d94d6f3a 300 if(io->write(ETX, 1000) != 1) {
Mike Fiore 4:1f63354b8d1b 301 logError("Timed out attempting to close socket");
Mike Fiore 1:f155d94d6f3a 302 return false;
Mike Fiore 1:f155d94d6f3a 303 }
Mike Fiore 1:f155d94d6f3a 304
Vanger 67:7c705fe2acec 305 if (shutdown) {
Vanger 66:8c55e2bf7270 306 int counter = 0;
Vanger 66:8c55e2bf7270 307 char tmp[256];
Vanger 66:8c55e2bf7270 308 do {
Vanger 66:8c55e2bf7270 309 if(socketOpened == false) {
Vanger 66:8c55e2bf7270 310 break;
Vanger 66:8c55e2bf7270 311 }
Vanger 66:8c55e2bf7270 312 read(tmp, 256, 1000);
Vanger 66:8c55e2bf7270 313 } while(counter++ < 10);
Vanger 66:8c55e2bf7270 314
Vanger 66:8c55e2bf7270 315 io->rxClear();
Vanger 66:8c55e2bf7270 316 io->txClear();
Vanger 66:8c55e2bf7270 317 }
Mike Fiore 1:f155d94d6f3a 318
Mike Fiore 1:f155d94d6f3a 319 socketOpened = false;
Mike Fiore 1:f155d94d6f3a 320 return true;
Mike Fiore 1:f155d94d6f3a 321 }
Mike Fiore 1:f155d94d6f3a 322
Mike Fiore 3:04046eebaef5 323 int UIP::read(char* data, int max, int timeout)
Mike Fiore 1:f155d94d6f3a 324 {
Mike Fiore 1:f155d94d6f3a 325 if(io == NULL) {
Mike Fiore 4:1f63354b8d1b 326 logError("MTSBufferedIO not set");
Mike Fiore 1:f155d94d6f3a 327 return -1;
Mike Fiore 1:f155d94d6f3a 328 }
Mike Fiore 1:f155d94d6f3a 329
Mike Fiore 1:f155d94d6f3a 330 //Check that nothing is in the rx buffer
Mike Fiore 1:f155d94d6f3a 331 if(!socketOpened && !io->readable()) {
Mike Fiore 4:1f63354b8d1b 332 logError("Socket is not open");
Mike Fiore 1:f155d94d6f3a 333 return -1;
Mike Fiore 1:f155d94d6f3a 334 }
Mike Fiore 1:f155d94d6f3a 335
Mike Fiore 1:f155d94d6f3a 336 int bytesRead = 0;
Mike Fiore 1:f155d94d6f3a 337
Mike Fiore 1:f155d94d6f3a 338 if(timeout >= 0) {
Mike Fiore 1:f155d94d6f3a 339 bytesRead = io->read(data, max, static_cast<unsigned int>(timeout));
Mike Fiore 1:f155d94d6f3a 340 } else {
Mike Fiore 1:f155d94d6f3a 341 bytesRead = io->read(data, max);
Mike Fiore 1:f155d94d6f3a 342 }
Mike Fiore 1:f155d94d6f3a 343
Mike Fiore 1:f155d94d6f3a 344 if(bytesRead > 0 && socketCloseable) {
Mike Fiore 1:f155d94d6f3a 345 //Remove escape characters
Mike Fiore 1:f155d94d6f3a 346 int index = 0;
Mike Fiore 1:f155d94d6f3a 347 bool escapeFlag = false;
Mike Fiore 1:f155d94d6f3a 348 for(int i = 0; i < bytesRead; i++) {
Mike Fiore 1:f155d94d6f3a 349 if(data[i] == DLE || data[i] == ETX) {
Mike Fiore 1:f155d94d6f3a 350 if(escapeFlag == true) {
Mike Fiore 1:f155d94d6f3a 351 //This character has been escaped
Mike Fiore 1:f155d94d6f3a 352 escapeFlag = false;
Mike Fiore 1:f155d94d6f3a 353 } else if(data[bytesRead] == DLE) {
Mike Fiore 1:f155d94d6f3a 354 //Found escape character
Mike Fiore 1:f155d94d6f3a 355 escapeFlag = true;
Mike Fiore 1:f155d94d6f3a 356 continue;
Mike Fiore 1:f155d94d6f3a 357 } else {
Mike Fiore 1:f155d94d6f3a 358 //ETX sent without escape -> Socket closed
Mike Fiore 4:1f63354b8d1b 359 logInfo("Read ETX character without DLE escape. Socket closed");
Mike Fiore 1:f155d94d6f3a 360 socketOpened = false;
Mike Fiore 1:f155d94d6f3a 361 continue;
Mike Fiore 1:f155d94d6f3a 362 }
Mike Fiore 1:f155d94d6f3a 363 }
Mike Fiore 1:f155d94d6f3a 364
Mike Fiore 1:f155d94d6f3a 365 if(index != i) {
Mike Fiore 1:f155d94d6f3a 366 data[index] = data[i];
Mike Fiore 1:f155d94d6f3a 367 }
Mike Fiore 1:f155d94d6f3a 368 index++;
Mike Fiore 1:f155d94d6f3a 369 }
Mike Fiore 1:f155d94d6f3a 370 bytesRead = index;
Mike Fiore 1:f155d94d6f3a 371 }
Mike Fiore 1:f155d94d6f3a 372
Mike Fiore 1:f155d94d6f3a 373 //Scan for socket closed message
Mike Fiore 1:f155d94d6f3a 374 for(size_t i = 0; i < bytesRead; i++) {
Mike Fiore 1:f155d94d6f3a 375 if(data[i] == 'O') {
Mike Fiore 1:f155d94d6f3a 376 if(strstr(&data[i], "Ok_Info_SocketClosed")) {
Mike Fiore 4:1f63354b8d1b 377 logInfo("Found socket closed message. Socket closed");
Mike Fiore 1:f155d94d6f3a 378 //Close socket and Cut Off End of Message
Mike Fiore 1:f155d94d6f3a 379 socketOpened = false;
Mike Fiore 1:f155d94d6f3a 380 data[i] = '\0';
Mike Fiore 1:f155d94d6f3a 381 bytesRead = i;
Mike Fiore 1:f155d94d6f3a 382 break;
Mike Fiore 1:f155d94d6f3a 383 }
Mike Fiore 1:f155d94d6f3a 384 }
Mike Fiore 1:f155d94d6f3a 385 }
Mike Fiore 1:f155d94d6f3a 386 return bytesRead;
Mike Fiore 1:f155d94d6f3a 387 }
Mike Fiore 1:f155d94d6f3a 388
Mike Fiore 3:04046eebaef5 389 int UIP::write(const char* data, int length, int timeout)
Mike Fiore 1:f155d94d6f3a 390 {
Mike Fiore 1:f155d94d6f3a 391 if(io == NULL) {
Mike Fiore 4:1f63354b8d1b 392 logError("MTSBufferedIO not set");
Mike Fiore 1:f155d94d6f3a 393 return -1;
Mike Fiore 1:f155d94d6f3a 394 }
Mike Fiore 1:f155d94d6f3a 395
Mike Fiore 1:f155d94d6f3a 396 if(!socketOpened) {
Mike Fiore 4:1f63354b8d1b 397 logError("Socket is not open");
Mike Fiore 1:f155d94d6f3a 398 return -1;
Mike Fiore 1:f155d94d6f3a 399 }
Mike Fiore 1:f155d94d6f3a 400
Mike Fiore 1:f155d94d6f3a 401 //In order to avoid allocating another buffer, capture indices of
Mike Fiore 1:f155d94d6f3a 402 //characters to escape during write
Mike Fiore 1:f155d94d6f3a 403 int specialWritten = 0;
Mike Fiore 1:f155d94d6f3a 404 std::vector<int> vSpecial;
Mike Fiore 1:f155d94d6f3a 405 if(socketCloseable) {
Mike Fiore 1:f155d94d6f3a 406 for(int i = 0; i < length; i++) {
Mike Fiore 1:f155d94d6f3a 407 if(data[i] == ETX || data[i] == DLE) {
Mike Fiore 1:f155d94d6f3a 408 //Push back index of special characters
Mike Fiore 1:f155d94d6f3a 409 vSpecial.push_back(i);
Mike Fiore 1:f155d94d6f3a 410 }
Mike Fiore 1:f155d94d6f3a 411 }
Mike Fiore 1:f155d94d6f3a 412 }
Mike Fiore 1:f155d94d6f3a 413
Mike Fiore 1:f155d94d6f3a 414 int bytesWritten = 0;
Mike Fiore 1:f155d94d6f3a 415 if(timeout >= 0) {
Mike Fiore 1:f155d94d6f3a 416 Timer tmr;
Mike Fiore 1:f155d94d6f3a 417 tmr.start();
Mike Fiore 1:f155d94d6f3a 418 do {
Mike Fiore 1:f155d94d6f3a 419 int available = io->writeable();
Mike Fiore 1:f155d94d6f3a 420 if (available > 0) {
Mike Fiore 1:f155d94d6f3a 421 if(specialWritten < vSpecial.size()) {
Mike Fiore 1:f155d94d6f3a 422 //Check if current index is at a special character
Mike Fiore 1:f155d94d6f3a 423 if(bytesWritten == vSpecial[specialWritten]) {
Mike Fiore 1:f155d94d6f3a 424 if(available < 2) {
Mike Fiore 1:f155d94d6f3a 425 //Requires at least two bytes of space
Mike Fiore 1:f155d94d6f3a 426 wait(0.05);
Mike Fiore 1:f155d94d6f3a 427 continue;
Mike Fiore 1:f155d94d6f3a 428 }
Mike Fiore 1:f155d94d6f3a 429 //Ready to write special character
Mike Fiore 1:f155d94d6f3a 430 if(io->write(DLE)) {
Mike Fiore 1:f155d94d6f3a 431 specialWritten++;
Mike Fiore 1:f155d94d6f3a 432 if(io->write(data[bytesWritten])) {
Mike Fiore 1:f155d94d6f3a 433 bytesWritten++;
Mike Fiore 1:f155d94d6f3a 434 }
Mike Fiore 1:f155d94d6f3a 435 } else {
Mike Fiore 1:f155d94d6f3a 436 //Unable to write escape character, try again next round
Mike Fiore 1:f155d94d6f3a 437 wait(0.05);
Mike Fiore 1:f155d94d6f3a 438 }
Mike Fiore 1:f155d94d6f3a 439 } else {
Mike Fiore 1:f155d94d6f3a 440 //We want to write all the way up to the next special character
Mike Fiore 1:f155d94d6f3a 441 int relativeIndex = vSpecial[specialWritten] - bytesWritten;
Mike Fiore 1:f155d94d6f3a 442 int size = MIN(available, relativeIndex);
Mike Fiore 1:f155d94d6f3a 443 bytesWritten += io->write(&data[bytesWritten], size);
Mike Fiore 1:f155d94d6f3a 444 }
Mike Fiore 1:f155d94d6f3a 445 } else {
Mike Fiore 1:f155d94d6f3a 446 int size = MIN(available, length - bytesWritten);
Mike Fiore 1:f155d94d6f3a 447 bytesWritten += io->write(&data[bytesWritten], size);
Mike Fiore 1:f155d94d6f3a 448 }
Mike Fiore 1:f155d94d6f3a 449 } else {
Mike Fiore 1:f155d94d6f3a 450 wait(0.05);
Mike Fiore 1:f155d94d6f3a 451 }
Mike Fiore 1:f155d94d6f3a 452 } while (tmr.read_ms() <= timeout && bytesWritten < length);
Mike Fiore 1:f155d94d6f3a 453 } else {
Mike Fiore 1:f155d94d6f3a 454 for(int i = 0; i < vSpecial.size(); i++) {
Mike Fiore 1:f155d94d6f3a 455 //Write up to the special character, then write the special character
Mike Fiore 1:f155d94d6f3a 456 int size = vSpecial[i] - bytesWritten;
Mike Fiore 1:f155d94d6f3a 457 int currentWritten = io->write(&data[bytesWritten], size);
Mike Fiore 1:f155d94d6f3a 458 bytesWritten += currentWritten;
Mike Fiore 1:f155d94d6f3a 459 if(currentWritten != size) {
Mike Fiore 1:f155d94d6f3a 460 //Failed to write up to the special character.
Mike Fiore 1:f155d94d6f3a 461 return bytesWritten;
Mike Fiore 1:f155d94d6f3a 462 }
Mike Fiore 1:f155d94d6f3a 463 if(io->write(DLE) && io->write(data[bytesWritten])) {
Mike Fiore 1:f155d94d6f3a 464 bytesWritten++;
Mike Fiore 1:f155d94d6f3a 465 } else {
Mike Fiore 1:f155d94d6f3a 466 //Failed to write the special character.
Mike Fiore 1:f155d94d6f3a 467 return bytesWritten;
Mike Fiore 1:f155d94d6f3a 468 }
Mike Fiore 1:f155d94d6f3a 469 }
Mike Fiore 1:f155d94d6f3a 470
Mike Fiore 1:f155d94d6f3a 471 bytesWritten = io->write(&data[bytesWritten], length - bytesWritten);
Mike Fiore 1:f155d94d6f3a 472 }
Mike Fiore 1:f155d94d6f3a 473
Mike Fiore 1:f155d94d6f3a 474 return bytesWritten;
Mike Fiore 1:f155d94d6f3a 475 }
Mike Fiore 1:f155d94d6f3a 476
Vanger 26:2b769ed8de4f 477 Code UIP::setApn(const std::string& apn)
Vanger 26:2b769ed8de4f 478 {
Vanger 26:2b769ed8de4f 479 if (type == MTSMC_H5_IP) {
Vanger 26:2b769ed8de4f 480 Code code = sendBasicCommand("AT#APNSERV=\"" + apn + "\"", 1000);
Vanger 26:2b769ed8de4f 481 if (code != MTS_SUCCESS) {
Vanger 26:2b769ed8de4f 482 return code;
Vanger 26:2b769ed8de4f 483 }
Vanger 26:2b769ed8de4f 484 this->apn = apn;
Vanger 26:2b769ed8de4f 485 return code; //This will return MTS_SUCCESS
Vanger 26:2b769ed8de4f 486 } else {
Vanger 26:2b769ed8de4f 487 logInfo("CDMA radios don't need an APN");
Vanger 26:2b769ed8de4f 488 return MTS_SUCCESS;
Vanger 26:2b769ed8de4f 489 }
Vanger 26:2b769ed8de4f 490 }
Vanger 26:2b769ed8de4f 491
Mike Fiore 3:04046eebaef5 492 void UIP::reset()
Mike Fiore 1:f155d94d6f3a 493 {
Mike Fiore 1:f155d94d6f3a 494 disconnect();
Mike Fiore 1:f155d94d6f3a 495 Code code = sendBasicCommand("AT#RESET=0", 10000);
mfiore 18:fa0d8120f81f 496 if(code != MTS_SUCCESS) {
Mike Fiore 4:1f63354b8d1b 497 logError("Socket Modem did not accept RESET command\n\r");
Mike Fiore 1:f155d94d6f3a 498 } else {
Mike Fiore 4:1f63354b8d1b 499 logWarning("Socket Modem is resetting, allow 30 seconds for it to come back\n\r");
Mike Fiore 1:f155d94d6f3a 500 }
Mike Fiore 1:f155d94d6f3a 501 }
Mike Fiore 1:f155d94d6f3a 502
Mike Fiore 3:04046eebaef5 503 bool UIP::ping(const std::string& address)
Mike Fiore 1:f155d94d6f3a 504 {
Mike Fiore 1:f155d94d6f3a 505 char buffer[256] = {0};
Mike Fiore 1:f155d94d6f3a 506 Code code;
Mike Fiore 1:f155d94d6f3a 507
Mike Fiore 1:f155d94d6f3a 508 code = sendBasicCommand("AT#PINGREMOTE=\"" + address + "\"", 1000);
mfiore 18:fa0d8120f81f 509 if (code != MTS_SUCCESS) {
Mike Fiore 1:f155d94d6f3a 510 return false;
Mike Fiore 1:f155d94d6f3a 511 }
Mike Fiore 1:f155d94d6f3a 512
Mike Fiore 1:f155d94d6f3a 513 sprintf(buffer, "AT#PINGNUM=%d", 1);
Mike Fiore 1:f155d94d6f3a 514 code = sendBasicCommand(buffer , 1000);
mfiore 18:fa0d8120f81f 515 if (code != MTS_SUCCESS) {
Mike Fiore 1:f155d94d6f3a 516 return false;
Mike Fiore 1:f155d94d6f3a 517 }
Mike Fiore 1:f155d94d6f3a 518
Mike Fiore 1:f155d94d6f3a 519 sprintf(buffer, "AT#PINGDELAY=%d", PINGDELAY);
Mike Fiore 1:f155d94d6f3a 520 code = sendBasicCommand(buffer , 1000);
mfiore 18:fa0d8120f81f 521 if (code != MTS_SUCCESS) {
Mike Fiore 1:f155d94d6f3a 522 return false;
Mike Fiore 1:f155d94d6f3a 523 }
Mike Fiore 1:f155d94d6f3a 524
Mike Fiore 1:f155d94d6f3a 525 std::string response;
Mike Fiore 1:f155d94d6f3a 526 for (int i = 0; i < PINGNUM; i++) {
Vanger 59:5535f14e3cc4 527 response = sendCommand("AT#PING", PINGDELAY * 2000);
Mike Fiore 1:f155d94d6f3a 528 if (response.find("alive") != std::string::npos) {
mfiore 22:c1004a807490 529 /* the "OK" that comes on a new line doesn't come right after this reply
mfiore 22:c1004a807490 530 * wait a couple seconds to make sure we get it here, otherwise it could be read
mfiore 22:c1004a807490 531 * as the response to the next AT command sent
mfiore 22:c1004a807490 532 */
mfiore 22:c1004a807490 533 wait(2);
Mike Fiore 1:f155d94d6f3a 534 return true;
Mike Fiore 1:f155d94d6f3a 535 }
Mike Fiore 1:f155d94d6f3a 536 }
Mike Fiore 1:f155d94d6f3a 537 return false;
Vanger 56:43205bd2752a 538 }