A library for talking to Multi-Tech's Cellular SocketModem Devices.

Dependents:   M2X_dev axeda_wrapper_dev MTS_M2x_Example1 MTS_Cellular_Connect_Example ... more

Committer:
sgodinez
Date:
Tue Dec 31 17:30:07 2013 +0000
Revision:
110:8f3149c99112
Parent:
101:27bb34e23304
Child:
122:5f95f81a8b03
Improved robustness of close() call

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jengbrecht 0:563b70517320 1 #include "Cellular.h"
sgodinez 4:6561c9128c6f 2 #include "MTSText.h"
sgodinez 19:38794784e009 3 #include "MTSSerial.h"
jengbrecht 0:563b70517320 4
mfiore 39:6e94520a3217 5 using namespace mts;
mfiore 39:6e94520a3217 6
sgodinez 19:38794784e009 7 Cellular* Cellular::instance = NULL;
sgodinez 19:38794784e009 8
jengbrecht 82:5aa75004e553 9 Cellular* Cellular::getInstance()
jengbrecht 82:5aa75004e553 10 {
sgodinez 19:38794784e009 11 if(instance == NULL) {
sgodinez 19:38794784e009 12 instance = new Cellular(NULL);
sgodinez 19:38794784e009 13 }
sgodinez 19:38794784e009 14 return instance;
sgodinez 19:38794784e009 15 }
sgodinez 19:38794784e009 16
sgodinez 96:27bdf4aa3a31 17 Cellular::Cellular(MTSBufferedIO* io)
sgodinez 96:27bdf4aa3a31 18 : io(io)
sgodinez 96:27bdf4aa3a31 19 , echoMode(true)
sgodinez 96:27bdf4aa3a31 20 , pppConnected(false)
sgodinez 96:27bdf4aa3a31 21 , mode(TCP)
sgodinez 96:27bdf4aa3a31 22 , socketOpened(false)
sgodinez 96:27bdf4aa3a31 23 , socketCloseable(true)
sgodinez 96:27bdf4aa3a31 24 , local_port(0)
sgodinez 96:27bdf4aa3a31 25 , host_port(0)
sgodinez 96:27bdf4aa3a31 26 , dcd(NULL)
sgodinez 96:27bdf4aa3a31 27 , dtr(NULL)
sgodinez 96:27bdf4aa3a31 28 {
sgodinez 96:27bdf4aa3a31 29 }
sgodinez 96:27bdf4aa3a31 30
sgodinez 96:27bdf4aa3a31 31 Cellular::~Cellular()
sgodinez 96:27bdf4aa3a31 32 {
sgodinez 96:27bdf4aa3a31 33 if (dtr != NULL) {
sgodinez 96:27bdf4aa3a31 34 dtr->write(1);
sgodinez 96:27bdf4aa3a31 35 }
sgodinez 96:27bdf4aa3a31 36
sgodinez 96:27bdf4aa3a31 37 delete dcd;
sgodinez 96:27bdf4aa3a31 38 delete dtr;
sgodinez 96:27bdf4aa3a31 39 }
sgodinez 19:38794784e009 40
jengbrecht 82:5aa75004e553 41 bool Cellular::init(MTSBufferedIO* io, PinName DCD, PinName DTR)
jengbrecht 82:5aa75004e553 42 {
jengbrecht 56:e5e5351f14b3 43 if (io == NULL) {
jengbrecht 56:e5e5351f14b3 44 return false;
sgodinez 19:38794784e009 45 }
sgodinez 96:27bdf4aa3a31 46
sgodinez 96:27bdf4aa3a31 47 if(dcd) {
sgodinez 96:27bdf4aa3a31 48 delete dcd;
sgodinez 96:27bdf4aa3a31 49 dcd = NULL;
sgodinez 96:27bdf4aa3a31 50 }
sgodinez 96:27bdf4aa3a31 51 if(dtr) {
sgodinez 96:27bdf4aa3a31 52 delete dtr;
sgodinez 96:27bdf4aa3a31 53 dtr = NULL;
sgodinez 96:27bdf4aa3a31 54 }
sgodinez 96:27bdf4aa3a31 55
jengbrecht 82:5aa75004e553 56 if (DCD != NC) {
jengbrecht 82:5aa75004e553 57 // the radio will raise and lower this line
jengbrecht 82:5aa75004e553 58 dcd = new DigitalIn(DCD); //PTA4 - KL46
jengbrecht 82:5aa75004e553 59 }
jengbrecht 82:5aa75004e553 60 if (DTR != NC) {
jengbrecht 82:5aa75004e553 61 dtr = new DigitalOut(DTR); //PTC9 - KL46
jengbrecht 82:5aa75004e553 62 /* This line should be lowered when we want to talk to the radio and raised when we're done
jengbrecht 82:5aa75004e553 63 for now we will lower it in the constructor and raise it in the destructor
jengbrecht 82:5aa75004e553 64 */
jengbrecht 82:5aa75004e553 65 dtr->write(0);
jengbrecht 82:5aa75004e553 66 }
jengbrecht 56:e5e5351f14b3 67 instance->io = io;
sgodinez 96:27bdf4aa3a31 68
sgodinez 96:27bdf4aa3a31 69 return (test() == SUCCESS);
sgodinez 19:38794784e009 70 }
sgodinez 19:38794784e009 71
jengbrecht 0:563b70517320 72
jengbrecht 82:5aa75004e553 73 bool Cellular::connect()
jengbrecht 82:5aa75004e553 74 {
sgodinez 13:0af863114629 75 //Check if socket is open
sgodinez 13:0af863114629 76 if(socketOpened) {
jengbrecht 82:5aa75004e553 77 return true;
sgodinez 13:0af863114629 78 }
jengbrecht 82:5aa75004e553 79
sgodinez 96:27bdf4aa3a31 80 //Check if already connected
sgodinez 13:0af863114629 81 if(isConnected()) {
sgodinez 13:0af863114629 82 return true;
sgodinez 13:0af863114629 83 }
sgodinez 96:27bdf4aa3a31 84
sgodinez 96:27bdf4aa3a31 85 Timer tmr;
sgodinez 96:27bdf4aa3a31 86
sgodinez 96:27bdf4aa3a31 87 //Check Registration: AT+CREG? == 0,1
sgodinez 96:27bdf4aa3a31 88 tmr.start();
sgodinez 96:27bdf4aa3a31 89 do {
sgodinez 96:27bdf4aa3a31 90 Registration registration = getRegistration();
sgodinez 96:27bdf4aa3a31 91 if(registration != REGISTERED) {
sgodinez 96:27bdf4aa3a31 92 printf("[WARNING] Not Registered [%d] ... waiting\r\n", (int)registration);
sgodinez 96:27bdf4aa3a31 93 wait(1);
sgodinez 96:27bdf4aa3a31 94 } else {
sgodinez 96:27bdf4aa3a31 95 break;
sgodinez 96:27bdf4aa3a31 96 }
sgodinez 96:27bdf4aa3a31 97 } while(tmr.read() < 30);
jengbrecht 82:5aa75004e553 98
jengbrecht 82:5aa75004e553 99 //Check RSSI: AT+CSQ
sgodinez 96:27bdf4aa3a31 100 tmr.reset();
sgodinez 96:27bdf4aa3a31 101 do {
sgodinez 96:27bdf4aa3a31 102 int rssi = getSignalStrength();
sgodinez 96:27bdf4aa3a31 103 printf("[DEBUG] Signal strength: %d\r\n", rssi);
sgodinez 96:27bdf4aa3a31 104 if(rssi == 99) {
sgodinez 96:27bdf4aa3a31 105 printf("[WARNING] No Signal ... waiting\r\n");
sgodinez 96:27bdf4aa3a31 106 wait(1);
sgodinez 96:27bdf4aa3a31 107 } else {
sgodinez 96:27bdf4aa3a31 108 break;
sgodinez 96:27bdf4aa3a31 109 }
sgodinez 96:27bdf4aa3a31 110 } while(tmr.read() < 30);
jengbrecht 82:5aa75004e553 111
sgodinez 11:134435d8a2d5 112 //AT#CONNECTIONSTART: Make a PPP connection
sgodinez 17:2d7c4ea7491b 113 printf("[DEBUG] Making PPP Connection Attempt. APN[%s]\r\n", apn.c_str());
sgodinez 13:0af863114629 114 std::string pppResult = sendCommand("AT#CONNECTIONSTART", 120000);
sgodinez 17:2d7c4ea7491b 115 std::vector<std::string> parts = Text::split(pppResult, "\r\n");
jengbrecht 82:5aa75004e553 116
sgodinez 13:0af863114629 117 if(pppResult.find("Ok_Info_GprsActivation") != std::string::npos) {
sgodinez 13:0af863114629 118 if(parts.size() >= 2) {
jengbrecht 82:5aa75004e553 119 local_address = parts[1];
sgodinez 13:0af863114629 120 }
sgodinez 17:2d7c4ea7491b 121 printf("[INFO] PPP Connection Established: IP[%s]\r\n", local_address.c_str());
sgodinez 13:0af863114629 122 pppConnected = true;
jengbrecht 82:5aa75004e553 123
sgodinez 13:0af863114629 124 } else {
jengbrecht 82:5aa75004e553 125 pppConnected = false;
sgodinez 13:0af863114629 126 }
jengbrecht 82:5aa75004e553 127
sgodinez 13:0af863114629 128 return pppConnected;
sgodinez 11:134435d8a2d5 129 }
sgodinez 11:134435d8a2d5 130
jengbrecht 82:5aa75004e553 131 void Cellular::disconnect()
jengbrecht 82:5aa75004e553 132 {
sgodinez 17:2d7c4ea7491b 133 //AT#CONNECTIONSTOP: Close a PPP connection
sgodinez 17:2d7c4ea7491b 134 printf("[DEBUG] Closing PPP Connection\r\n");
jengbrecht 82:5aa75004e553 135
jengbrecht 82:5aa75004e553 136 if(socketOpened) {
jengbrecht 82:5aa75004e553 137 close();
sgodinez 17:2d7c4ea7491b 138 }
jengbrecht 82:5aa75004e553 139
sgodinez 17:2d7c4ea7491b 140 Code code = sendBasicCommand("AT#CONNECTIONSTOP", 10000);
sgodinez 71:82205735732b 141 if(code == SUCCESS) {
sgodinez 17:2d7c4ea7491b 142 printf("[DEBUG] Successfully closed PPP Connection\r\n");
sgodinez 17:2d7c4ea7491b 143 } else {
jengbrecht 82:5aa75004e553 144 printf("[ERROR] Closing PPP Connection [%d]. Continuing ...\r\n", (int)code);
sgodinez 17:2d7c4ea7491b 145 }
jengbrecht 82:5aa75004e553 146
sgodinez 17:2d7c4ea7491b 147 pppConnected = false;
sgodinez 11:134435d8a2d5 148 }
sgodinez 11:134435d8a2d5 149
jengbrecht 82:5aa75004e553 150 bool Cellular::isConnected()
jengbrecht 82:5aa75004e553 151 {
sgodinez 11:134435d8a2d5 152 //1) Check if APN was set
sgodinez 11:134435d8a2d5 153 if(apn.size() == 0) {
sgodinez 17:2d7c4ea7491b 154 printf("[DEBUG] APN is not set\r\n");
sgodinez 11:134435d8a2d5 155 return false;
sgodinez 11:134435d8a2d5 156 }
jengbrecht 82:5aa75004e553 157
sgodinez 11:134435d8a2d5 158 //1) Check that we do not have a live connection up
sgodinez 11:134435d8a2d5 159 if(socketOpened) {
sgodinez 17:2d7c4ea7491b 160 printf("[DEBUG] Socket is opened\r\n");
sgodinez 11:134435d8a2d5 161 return true;
sgodinez 11:134435d8a2d5 162 }
sgodinez 11:134435d8a2d5 163 //2) Query the radio
sgodinez 110:8f3149c99112 164 std::string result = sendCommand("AT#VSTATE", 3000);
sgodinez 11:134435d8a2d5 165 if(result.find("CONNECTED") != std::string::npos) {
sgodinez 110:8f3149c99112 166 if(pppConnected == false) {
sgodinez 110:8f3149c99112 167 printf("[WARNING] Internal PPP state tracking differs from radio (DISCONNECTED:CONNECTED)\r\n");
sgodinez 110:8f3149c99112 168 }
sgodinez 11:134435d8a2d5 169 pppConnected = true;
sgodinez 110:8f3149c99112 170 } else {
sgodinez 110:8f3149c99112 171 if(pppConnected == true) {
sgodinez 110:8f3149c99112 172 //Find out what state is
sgodinez 110:8f3149c99112 173 size_t pos = result.find("STATE:");
sgodinez 110:8f3149c99112 174 if(pos != std::string::npos) {
sgodinez 110:8f3149c99112 175 result = Text::getLine(result, pos + sizeof("STATE:"), pos);
sgodinez 110:8f3149c99112 176 printf("[WARNING] Internal PPP state tracking differs from radio (CONNECTED:%s)\r\n", result.c_str());
sgodinez 110:8f3149c99112 177 } else {
sgodinez 110:8f3149c99112 178 printf("[ERROR] Unable to parse radio state: [%s]\r\n", result.c_str());
sgodinez 110:8f3149c99112 179 }
sgodinez 110:8f3149c99112 180
sgodinez 110:8f3149c99112 181 }
sgodinez 110:8f3149c99112 182 pppConnected = false;
sgodinez 11:134435d8a2d5 183 }
jengbrecht 82:5aa75004e553 184
sgodinez 11:134435d8a2d5 185 return pppConnected;
sgodinez 11:134435d8a2d5 186 }
sgodinez 11:134435d8a2d5 187
jengbrecht 82:5aa75004e553 188 bool Cellular::bind(unsigned int port)
jengbrecht 82:5aa75004e553 189 {
sgodinez 53:27c9622de0f9 190 if(socketOpened) {
jengbrecht 82:5aa75004e553 191 printf("[ERROR] socket is open. Can not set local port\r\n");
sgodinez 53:27c9622de0f9 192 return false;
sgodinez 53:27c9622de0f9 193 }
sgodinez 53:27c9622de0f9 194 if(port > 65535) {
jengbrecht 82:5aa75004e553 195 printf("[ERROR] port out of range (0-65535)\r\n");
sgodinez 53:27c9622de0f9 196 return false;
sgodinez 53:27c9622de0f9 197 }
sgodinez 53:27c9622de0f9 198 local_port = port;
sgodinez 53:27c9622de0f9 199 return true;
sgodinez 11:134435d8a2d5 200 }
sgodinez 11:134435d8a2d5 201
jengbrecht 82:5aa75004e553 202 bool Cellular::open(const std::string& address, unsigned int port, Mode mode)
jengbrecht 82:5aa75004e553 203 {
sgodinez 17:2d7c4ea7491b 204 char buffer[256] = {0};
sgodinez 11:134435d8a2d5 205 Code portCode, addressCode;
jengbrecht 82:5aa75004e553 206
sgodinez 11:134435d8a2d5 207 //1) Check that we do not have a live connection up
sgodinez 11:134435d8a2d5 208 if(socketOpened) {
sgodinez 41:81d035fb0b6a 209 //Check that the address, port, and mode match
sgodinez 41:81d035fb0b6a 210 if(host_address != address || host_port != port || this->mode != mode) {
sgodinez 41:81d035fb0b6a 211 if(this->mode == TCP) {
sgodinez 96:27bdf4aa3a31 212 printf("[ERROR] TCP socket already opened [%s:%d]\r\n", host_address.c_str(), host_port);
sgodinez 41:81d035fb0b6a 213 } else {
sgodinez 96:27bdf4aa3a31 214 printf("[ERROR] UDP socket already opened [%s:%d]\r\n", host_address.c_str(), host_port);
sgodinez 41:81d035fb0b6a 215 }
sgodinez 41:81d035fb0b6a 216 return false;
sgodinez 41:81d035fb0b6a 217 }
jengbrecht 82:5aa75004e553 218
sgodinez 17:2d7c4ea7491b 219 printf("[DEBUG] Socket already opened\r\n");
sgodinez 11:134435d8a2d5 220 return true;
sgodinez 11:134435d8a2d5 221 }
jengbrecht 82:5aa75004e553 222
sgodinez 53:27c9622de0f9 223 //2) Check Parameters
sgodinez 53:27c9622de0f9 224 if(port > 65535) {
jengbrecht 82:5aa75004e553 225 printf("[ERROR] port out of range (0-65535)\r\n");
sgodinez 53:27c9622de0f9 226 return false;
sgodinez 53:27c9622de0f9 227 }
jengbrecht 82:5aa75004e553 228
sgodinez 53:27c9622de0f9 229 //3) Check PPP connection
sgodinez 11:134435d8a2d5 230 if(!isConnected()) {
sgodinez 17:2d7c4ea7491b 231 printf("[ERROR] PPP not established. Attempting to connect\r\n");
sgodinez 11:134435d8a2d5 232 if(!connect()) {
sgodinez 17:2d7c4ea7491b 233 printf("[ERROR] PPP connection failed\r\n");
sgodinez 11:134435d8a2d5 234 return false;
sgodinez 11:134435d8a2d5 235 } else {
sgodinez 17:2d7c4ea7491b 236 printf("[DEBUG] PPP connection established\r\n");
sgodinez 11:134435d8a2d5 237 }
sgodinez 11:134435d8a2d5 238 }
sgodinez 96:27bdf4aa3a31 239
sgodinez 55:56d9a9d98079 240 //Set Local Port
sgodinez 55:56d9a9d98079 241 if(local_port != 0) {
sgodinez 55:56d9a9d98079 242 //Attempt to set local port
sgodinez 55:56d9a9d98079 243 sprintf(buffer, "AT#OUTPORT=%d", local_port);
sgodinez 55:56d9a9d98079 244 Code code = sendBasicCommand(buffer, 1000);
sgodinez 71:82205735732b 245 if(code != SUCCESS) {
jengbrecht 82:5aa75004e553 246 printf("[WARNING] Unable to set local port (%d) [%d]\r\n", local_port, (int) code);
sgodinez 55:56d9a9d98079 247 }
sgodinez 55:56d9a9d98079 248 }
jengbrecht 82:5aa75004e553 249
sgodinez 55:56d9a9d98079 250 //Set TCP/UDP parameters
sgodinez 11:134435d8a2d5 251 if(mode == TCP) {
sgodinez 17:2d7c4ea7491b 252 if(socketCloseable) {
sgodinez 48:dad1e780cb1c 253 Code code = sendBasicCommand("AT#DLEMODE=1,1", 1000);
sgodinez 71:82205735732b 254 if(code != SUCCESS) {
jengbrecht 82:5aa75004e553 255 printf("[WARNING] Unable to set socket closeable [%d]\r\n", (int) code);
sgodinez 17:2d7c4ea7491b 256 }
sgodinez 17:2d7c4ea7491b 257 }
sgodinez 17:2d7c4ea7491b 258 sprintf(buffer, "AT#TCPPORT=1,%d", port);
sgodinez 17:2d7c4ea7491b 259 portCode = sendBasicCommand(buffer, 1000);
sgodinez 17:2d7c4ea7491b 260 addressCode = sendBasicCommand("AT#TCPSERV=1,\"" + address + "\"", 1000);
sgodinez 11:134435d8a2d5 261 } else {
sgodinez 17:2d7c4ea7491b 262 if(socketCloseable) {
sgodinez 17:2d7c4ea7491b 263 Code code = sendBasicCommand("AT#UDPDLEMODE=1", 1000);
sgodinez 71:82205735732b 264 if(code != SUCCESS) {
jengbrecht 82:5aa75004e553 265 printf("[WARNING] Unable to set socket closeable [%d]\r\n", (int) code);
sgodinez 17:2d7c4ea7491b 266 }
sgodinez 17:2d7c4ea7491b 267 }
sgodinez 55:56d9a9d98079 268 sprintf(buffer, "AT#UDPPORT=%d", port);
sgodinez 17:2d7c4ea7491b 269 portCode = sendBasicCommand(buffer, 1000);
sgodinez 55:56d9a9d98079 270 addressCode = sendBasicCommand("AT#UDPSERV=\"" + address + "\"", 1000);
sgodinez 11:134435d8a2d5 271 }
jengbrecht 82:5aa75004e553 272
sgodinez 71:82205735732b 273 if(portCode == SUCCESS) {
sgodinez 11:134435d8a2d5 274 host_port = port;
sgodinez 11:134435d8a2d5 275 } else {
sgodinez 17:2d7c4ea7491b 276 printf("[ERROR] Host port could not be set\r\n");
sgodinez 11:134435d8a2d5 277 }
jengbrecht 82:5aa75004e553 278
sgodinez 71:82205735732b 279 if(addressCode == SUCCESS) {
sgodinez 11:134435d8a2d5 280 host_address = address;
sgodinez 11:134435d8a2d5 281 } else {
sgodinez 17:2d7c4ea7491b 282 printf("[ERROR] Host address could not be set\r\n");
sgodinez 11:134435d8a2d5 283 }
jengbrecht 82:5aa75004e553 284
sgodinez 13:0af863114629 285 // Try and Connect
sgodinez 55:56d9a9d98079 286 std::string sMode;
sgodinez 55:56d9a9d98079 287 std::string sOpenSocketCmd;
sgodinez 55:56d9a9d98079 288 if(mode == TCP) {
sgodinez 55:56d9a9d98079 289 sOpenSocketCmd = "AT#OTCP=1";
sgodinez 55:56d9a9d98079 290 sMode = "TCP";
sgodinez 55:56d9a9d98079 291 } else {
sgodinez 55:56d9a9d98079 292 sOpenSocketCmd = "AT#OUDP";
sgodinez 55:56d9a9d98079 293 sMode = "UDP";
sgodinez 55:56d9a9d98079 294 }
sgodinez 96:27bdf4aa3a31 295
sgodinez 55:56d9a9d98079 296 string response = sendCommand(sOpenSocketCmd, 30000);
sgodinez 13:0af863114629 297 if (response.find("Ok_Info_WaitingForData") != string::npos) {
sgodinez 55:56d9a9d98079 298 printf("[INFO] Opened %s Socket [%s:%d]\r\n", sMode.c_str(), address.c_str(), port);
sgodinez 13:0af863114629 299 socketOpened = true;
sgodinez 13:0af863114629 300 } else {
sgodinez 55:56d9a9d98079 301 printf("[WARNING] Unable to open %s Socket [%s:%d]\r\n", sMode.c_str(), address.c_str(), port);
sgodinez 13:0af863114629 302 socketOpened = false;
sgodinez 13:0af863114629 303 }
jengbrecht 82:5aa75004e553 304
sgodinez 13:0af863114629 305 return socketOpened;
sgodinez 11:134435d8a2d5 306 }
sgodinez 11:134435d8a2d5 307
jengbrecht 82:5aa75004e553 308 bool Cellular::isOpen()
jengbrecht 82:5aa75004e553 309 {
sgodinez 17:2d7c4ea7491b 310 return socketOpened;
sgodinez 11:134435d8a2d5 311 }
sgodinez 11:134435d8a2d5 312
jengbrecht 82:5aa75004e553 313 bool Cellular::close()
jengbrecht 82:5aa75004e553 314 {
sgodinez 35:f28acb1be52d 315 if(io == NULL) {
sgodinez 35:f28acb1be52d 316 printf("[ERROR] MTSBufferedIO not set\r\n");
sgodinez 17:2d7c4ea7491b 317 return false;
sgodinez 13:0af863114629 318 }
sgodinez 35:f28acb1be52d 319
sgodinez 35:f28acb1be52d 320 if(!socketOpened) {
sgodinez 35:f28acb1be52d 321 printf("[WARNING] Socket close() called, but socket was not open\r\n");
sgodinez 35:f28acb1be52d 322 return true;
sgodinez 35:f28acb1be52d 323 }
sgodinez 35:f28acb1be52d 324
sgodinez 17:2d7c4ea7491b 325 if(!socketCloseable) {
sgodinez 17:2d7c4ea7491b 326 printf("[ERROR] Socket is not closeable\r\n");
sgodinez 17:2d7c4ea7491b 327 return false;
sgodinez 17:2d7c4ea7491b 328 }
jengbrecht 82:5aa75004e553 329
sgodinez 110:8f3149c99112 330
sgodinez 110:8f3149c99112 331
sgodinez 110:8f3149c99112 332 if(io->write(ETX, 1000) != 1) {
sgodinez 35:f28acb1be52d 333 printf("[ERROR] Timed out attempting to close socket\r\n");
sgodinez 17:2d7c4ea7491b 334 return false;
sgodinez 13:0af863114629 335 }
sgodinez 110:8f3149c99112 336
sgodinez 110:8f3149c99112 337 Timer tmr;
sgodinez 110:8f3149c99112 338 int counter = 0;
sgodinez 110:8f3149c99112 339 char tmp[256];
sgodinez 110:8f3149c99112 340 tmr.start();
sgodinez 110:8f3149c99112 341 do {
sgodinez 110:8f3149c99112 342 if(socketOpened == false) {
sgodinez 110:8f3149c99112 343 break;
sgodinez 110:8f3149c99112 344 }
sgodinez 110:8f3149c99112 345 read(tmp, 256, 1000);
sgodinez 110:8f3149c99112 346 } while(counter++ < 10);
sgodinez 110:8f3149c99112 347
sgodinez 110:8f3149c99112 348 io->rxClear();
sgodinez 110:8f3149c99112 349 io->txClear();
sgodinez 110:8f3149c99112 350
sgodinez 17:2d7c4ea7491b 351 socketOpened = false;
sgodinez 17:2d7c4ea7491b 352 return true;
sgodinez 11:134435d8a2d5 353 }
sgodinez 11:134435d8a2d5 354
jengbrecht 82:5aa75004e553 355 int Cellular::read(char* data, int max, int timeout)
jengbrecht 82:5aa75004e553 356 {
sgodinez 19:38794784e009 357 if(io == NULL) {
sgodinez 19:38794784e009 358 printf("[ERROR] MTSBufferedIO not set\r\n");
sgodinez 19:38794784e009 359 return -1;
sgodinez 19:38794784e009 360 }
jengbrecht 82:5aa75004e553 361
jengbrecht 82:5aa75004e553 362 //Check that nothing is in the rx buffer
sgodinez 58:408f67fa292f 363 if(!socketOpened && !io->readable()) {
sgodinez 17:2d7c4ea7491b 364 printf("[ERROR] Socket is not open\r\n");
sgodinez 17:2d7c4ea7491b 365 return -1;
sgodinez 17:2d7c4ea7491b 366 }
sgodinez 84:77c5ab16534d 367
sgodinez 17:2d7c4ea7491b 368 int bytesRead = 0;
jengbrecht 82:5aa75004e553 369
sgodinez 17:2d7c4ea7491b 370 if(timeout >= 0) {
sgodinez 68:c490e4a51778 371 bytesRead = io->read(data, max, static_cast<unsigned int>(timeout));
sgodinez 17:2d7c4ea7491b 372 } else {
sgodinez 19:38794784e009 373 bytesRead = io->read(data, max);
sgodinez 17:2d7c4ea7491b 374 }
jengbrecht 82:5aa75004e553 375
sgodinez 32:629e6b1c8e22 376 if(bytesRead > 0 && socketCloseable) {
jengbrecht 82:5aa75004e553 377 //Remove escape characters
sgodinez 32:629e6b1c8e22 378 int index = 0;
sgodinez 32:629e6b1c8e22 379 bool escapeFlag = false;
sgodinez 32:629e6b1c8e22 380 for(int i = 0; i < bytesRead; i++) {
jengbrecht 82:5aa75004e553 381 if(data[i] == DLE || data[i] == ETX) {
jengbrecht 82:5aa75004e553 382 if(escapeFlag == true) {
sgodinez 32:629e6b1c8e22 383 //This character has been escaped
sgodinez 32:629e6b1c8e22 384 escapeFlag = false;
sgodinez 32:629e6b1c8e22 385 } else if(data[bytesRead] == DLE) {
sgodinez 32:629e6b1c8e22 386 //Found escape character
sgodinez 32:629e6b1c8e22 387 escapeFlag = true;
sgodinez 32:629e6b1c8e22 388 continue;
sgodinez 32:629e6b1c8e22 389 } else {
jengbrecht 82:5aa75004e553 390 //ETX sent without escape -> Socket closed
jengbrecht 82:5aa75004e553 391 printf("[INFO] Read ETX character without DLE escape. Socket closed\r\n");
sgodinez 32:629e6b1c8e22 392 socketOpened = false;
sgodinez 32:629e6b1c8e22 393 continue;
sgodinez 32:629e6b1c8e22 394 }
sgodinez 32:629e6b1c8e22 395 }
sgodinez 32:629e6b1c8e22 396
sgodinez 32:629e6b1c8e22 397 if(index != i) {
sgodinez 32:629e6b1c8e22 398 data[index] = data[i];
sgodinez 32:629e6b1c8e22 399 }
sgodinez 32:629e6b1c8e22 400 index++;
sgodinez 32:629e6b1c8e22 401 }
sgodinez 32:629e6b1c8e22 402 bytesRead = index;
sgodinez 32:629e6b1c8e22 403 }
jengbrecht 82:5aa75004e553 404
sgodinez 32:629e6b1c8e22 405 //Scan for socket closed message
sgodinez 32:629e6b1c8e22 406 for(size_t i = 0; i < bytesRead; i++) {
sgodinez 32:629e6b1c8e22 407 if(data[i] == 'O') {
sgodinez 32:629e6b1c8e22 408 if(strstr(&data[i], "Ok_Info_SocketClosed")) {
jengbrecht 82:5aa75004e553 409 printf("[INFO] Found socket closed message. Socket closed\r\n");
sgodinez 32:629e6b1c8e22 410 //Close socket and Cut Off End of Message
sgodinez 32:629e6b1c8e22 411 socketOpened = false;
sgodinez 32:629e6b1c8e22 412 data[i] = '\0';
sgodinez 32:629e6b1c8e22 413 bytesRead = i;
sgodinez 32:629e6b1c8e22 414 break;
sgodinez 32:629e6b1c8e22 415 }
sgodinez 32:629e6b1c8e22 416 }
sgodinez 32:629e6b1c8e22 417 }
sgodinez 17:2d7c4ea7491b 418 return bytesRead;
sgodinez 11:134435d8a2d5 419 }
sgodinez 11:134435d8a2d5 420
jengbrecht 82:5aa75004e553 421 int Cellular::write(const char* data, int length, int timeout)
jengbrecht 82:5aa75004e553 422 {
sgodinez 19:38794784e009 423 if(io == NULL) {
sgodinez 19:38794784e009 424 printf("[ERROR] MTSBufferedIO not set\r\n");
sgodinez 19:38794784e009 425 return -1;
sgodinez 19:38794784e009 426 }
jengbrecht 82:5aa75004e553 427
sgodinez 17:2d7c4ea7491b 428 if(!socketOpened) {
sgodinez 17:2d7c4ea7491b 429 printf("[ERROR] Socket is not open\r\n");
sgodinez 17:2d7c4ea7491b 430 return -1;
sgodinez 17:2d7c4ea7491b 431 }
jengbrecht 82:5aa75004e553 432
sgodinez 35:f28acb1be52d 433 //In order to avoid allocating another buffer, capture indices of
sgodinez 35:f28acb1be52d 434 //characters to escape during write
sgodinez 35:f28acb1be52d 435 int specialWritten = 0;
sgodinez 35:f28acb1be52d 436 std::vector<int> vSpecial;
sgodinez 35:f28acb1be52d 437 if(socketCloseable) {
sgodinez 35:f28acb1be52d 438 for(int i = 0; i < length; i++) {
sgodinez 35:f28acb1be52d 439 if(data[i] == ETX || data[i] == DLE) {
sgodinez 35:f28acb1be52d 440 //Push back index of special characters
sgodinez 35:f28acb1be52d 441 vSpecial.push_back(i);
jengbrecht 82:5aa75004e553 442 }
sgodinez 35:f28acb1be52d 443 }
sgodinez 35:f28acb1be52d 444 }
jengbrecht 82:5aa75004e553 445
sgodinez 17:2d7c4ea7491b 446 int bytesWritten = 0;
sgodinez 17:2d7c4ea7491b 447 if(timeout >= 0) {
sgodinez 17:2d7c4ea7491b 448 Timer tmr;
sgodinez 17:2d7c4ea7491b 449 tmr.start();
sgodinez 35:f28acb1be52d 450 do {
sgodinez 67:1003b410f781 451 int available = io->writeable();
sgodinez 67:1003b410f781 452 if (available > 0) {
sgodinez 35:f28acb1be52d 453 if(specialWritten < vSpecial.size()) {
sgodinez 35:f28acb1be52d 454 //Check if current index is at a special character
sgodinez 35:f28acb1be52d 455 if(bytesWritten == vSpecial[specialWritten]) {
sgodinez 67:1003b410f781 456 if(available < 2) {
sgodinez 35:f28acb1be52d 457 //Requires at least two bytes of space
sgodinez 35:f28acb1be52d 458 wait(0.05);
jengbrecht 82:5aa75004e553 459 continue;
sgodinez 35:f28acb1be52d 460 }
jengbrecht 82:5aa75004e553 461 //Ready to write special character
sgodinez 35:f28acb1be52d 462 if(io->write(DLE)) {
sgodinez 35:f28acb1be52d 463 specialWritten++;
sgodinez 35:f28acb1be52d 464 if(io->write(data[bytesWritten])) {
sgodinez 35:f28acb1be52d 465 bytesWritten++;
sgodinez 35:f28acb1be52d 466 }
sgodinez 35:f28acb1be52d 467 } else {
sgodinez 35:f28acb1be52d 468 //Unable to write escape character, try again next round
sgodinez 35:f28acb1be52d 469 wait(0.05);
sgodinez 35:f28acb1be52d 470 }
sgodinez 35:f28acb1be52d 471 } else {
jengbrecht 82:5aa75004e553 472 //We want to write all the way up to the next special character
sgodinez 35:f28acb1be52d 473 int relativeIndex = vSpecial[specialWritten] - bytesWritten;
sgodinez 67:1003b410f781 474 int size = MIN(available, relativeIndex);
sgodinez 35:f28acb1be52d 475 bytesWritten += io->write(&data[bytesWritten], size);
jengbrecht 82:5aa75004e553 476 }
jengbrecht 82:5aa75004e553 477 } else {
sgodinez 67:1003b410f781 478 int size = MIN(available, length - bytesWritten);
sgodinez 35:f28acb1be52d 479 bytesWritten += io->write(&data[bytesWritten], size);
sgodinez 17:2d7c4ea7491b 480 }
sgodinez 17:2d7c4ea7491b 481 } else {
jengbrecht 82:5aa75004e553 482 wait(0.05);
sgodinez 35:f28acb1be52d 483 }
sgodinez 35:f28acb1be52d 484 } while (tmr.read_ms() <= timeout && bytesWritten < length);
sgodinez 35:f28acb1be52d 485 } else {
sgodinez 35:f28acb1be52d 486 for(int i = 0; i < vSpecial.size(); i++) {
sgodinez 35:f28acb1be52d 487 //Write up to the special character, then write the special character
sgodinez 35:f28acb1be52d 488 int size = vSpecial[i] - bytesWritten;
sgodinez 35:f28acb1be52d 489 int currentWritten = io->write(&data[bytesWritten], size);
sgodinez 35:f28acb1be52d 490 bytesWritten += currentWritten;
sgodinez 35:f28acb1be52d 491 if(currentWritten != size) {
sgodinez 35:f28acb1be52d 492 //Failed to write up to the special character.
sgodinez 35:f28acb1be52d 493 return bytesWritten;
sgodinez 35:f28acb1be52d 494 }
sgodinez 35:f28acb1be52d 495 if(io->write(DLE) && io->write(data[bytesWritten])) {
sgodinez 35:f28acb1be52d 496 bytesWritten++;
sgodinez 35:f28acb1be52d 497 } else {
sgodinez 35:f28acb1be52d 498 //Failed to write the special character.
sgodinez 35:f28acb1be52d 499 return bytesWritten;
sgodinez 17:2d7c4ea7491b 500 }
sgodinez 17:2d7c4ea7491b 501 }
jengbrecht 82:5aa75004e553 502
sgodinez 35:f28acb1be52d 503 bytesWritten = io->write(&data[bytesWritten], length - bytesWritten);
sgodinez 17:2d7c4ea7491b 504 }
jengbrecht 82:5aa75004e553 505
sgodinez 17:2d7c4ea7491b 506 return bytesWritten;
sgodinez 11:134435d8a2d5 507 }
sgodinez 11:134435d8a2d5 508
jengbrecht 82:5aa75004e553 509 unsigned int Cellular::readable()
jengbrecht 82:5aa75004e553 510 {
sgodinez 19:38794784e009 511 if(io == NULL) {
sgodinez 96:27bdf4aa3a31 512 printf("[WARNING] MTSBufferedIO not set\r\n");
sgodinez 19:38794784e009 513 return 0;
sgodinez 19:38794784e009 514 }
sgodinez 96:27bdf4aa3a31 515 if(!socketOpened && !io->readable()) {
sgodinez 96:27bdf4aa3a31 516 printf("[WARNING] Socket is not open\r\n");
sgodinez 17:2d7c4ea7491b 517 return 0;
sgodinez 17:2d7c4ea7491b 518 }
sgodinez 19:38794784e009 519 return io->readable();
sgodinez 11:134435d8a2d5 520 }
sgodinez 11:134435d8a2d5 521
jengbrecht 82:5aa75004e553 522 unsigned int Cellular::writeable()
jengbrecht 82:5aa75004e553 523 {
sgodinez 19:38794784e009 524 if(io == NULL) {
sgodinez 96:27bdf4aa3a31 525 printf("[WARNING] MTSBufferedIO not set\r\n");
sgodinez 19:38794784e009 526 return 0;
sgodinez 19:38794784e009 527 }
sgodinez 17:2d7c4ea7491b 528 if(!socketOpened) {
sgodinez 96:27bdf4aa3a31 529 printf("[WARNING] Socket is not open\r\n");
sgodinez 17:2d7c4ea7491b 530 return 0;
sgodinez 17:2d7c4ea7491b 531 }
jengbrecht 82:5aa75004e553 532
sgodinez 19:38794784e009 533 return io->writeable();
sgodinez 11:134435d8a2d5 534 }
sgodinez 11:134435d8a2d5 535
jengbrecht 82:5aa75004e553 536 void Cellular::reset()
jengbrecht 82:5aa75004e553 537 {
mfiore 29:7408b1bdad37 538 disconnect();
mfiore 29:7408b1bdad37 539 Code code = sendBasicCommand("AT#RESET=0", 10000);
sgodinez 71:82205735732b 540 if(code != SUCCESS) {
mfiore 29:7408b1bdad37 541 printf("[ERROR] Socket Modem did not accept RESET command\n\r");
mfiore 29:7408b1bdad37 542 } else {
mfiore 29:7408b1bdad37 543 printf("[WARNING] Socket Modem is resetting, allow 30 seconds for it to come back\n\r");
mfiore 29:7408b1bdad37 544 }
sgodinez 11:134435d8a2d5 545 }
sgodinez 11:134435d8a2d5 546
sgodinez 71:82205735732b 547 Code Cellular::test()
jengbrecht 0:563b70517320 548 {
sgodinez 96:27bdf4aa3a31 549 bool basicRadioComms = false;
sgodinez 96:27bdf4aa3a31 550 Code code;
sgodinez 96:27bdf4aa3a31 551 Timer tmr;
sgodinez 96:27bdf4aa3a31 552 tmr.start();
sgodinez 96:27bdf4aa3a31 553 do {
sgodinez 96:27bdf4aa3a31 554 printf("[DEBUG] Attempting basic radio communication\r\n");
sgodinez 96:27bdf4aa3a31 555 code = sendBasicCommand("AT", 1000);
sgodinez 96:27bdf4aa3a31 556 if(code == SUCCESS) {
sgodinez 96:27bdf4aa3a31 557 basicRadioComms = true;
sgodinez 96:27bdf4aa3a31 558 break;
sgodinez 96:27bdf4aa3a31 559 } else {
sgodinez 96:27bdf4aa3a31 560 wait(1);
sgodinez 96:27bdf4aa3a31 561 }
sgodinez 96:27bdf4aa3a31 562 } while(tmr.read() < 15);
jengbrecht 82:5aa75004e553 563
sgodinez 96:27bdf4aa3a31 564 if(!basicRadioComms) {
sgodinez 96:27bdf4aa3a31 565 printf("[ERROR] Unable to communicate with the radio\r\n");
sgodinez 96:27bdf4aa3a31 566 return FAILURE;
sgodinez 11:134435d8a2d5 567 }
sgodinez 96:27bdf4aa3a31 568
sgodinez 71:82205735732b 569 return SUCCESS;
jengbrecht 0:563b70517320 570 }
jengbrecht 0:563b70517320 571
sgodinez 71:82205735732b 572 Code Cellular::echo(bool state)
jengbrecht 0:563b70517320 573 {
sgodinez 13:0af863114629 574 Code code;
jengbrecht 0:563b70517320 575 if (state) {
sgodinez 13:0af863114629 576 code = sendBasicCommand("ATE0", 1000);
sgodinez 71:82205735732b 577 echoMode = (code == SUCCESS) ? false : echoMode;
jengbrecht 0:563b70517320 578 } else {
sgodinez 13:0af863114629 579 code = sendBasicCommand("ATE1", 1000);
sgodinez 71:82205735732b 580 echoMode = (code == SUCCESS) ? true : echoMode;
jengbrecht 0:563b70517320 581 }
sgodinez 13:0af863114629 582 return code;
jengbrecht 0:563b70517320 583 }
jengbrecht 0:563b70517320 584
jengbrecht 0:563b70517320 585 int Cellular::getSignalStrength()
jengbrecht 0:563b70517320 586 {
jengbrecht 0:563b70517320 587 string response = sendCommand("AT+CSQ", 1000);
jengbrecht 0:563b70517320 588 if (response.find("OK") == string::npos) {
jengbrecht 0:563b70517320 589 return -1;
jengbrecht 0:563b70517320 590 }
jengbrecht 0:563b70517320 591 int start = response.find(':');
jengbrecht 0:563b70517320 592 int stop = response.find(',', start);
jengbrecht 0:563b70517320 593 string signal = response.substr(start + 2, stop - start - 2);
jengbrecht 0:563b70517320 594 int value;
jengbrecht 0:563b70517320 595 sscanf(signal.c_str(), "%d", &value);
jengbrecht 0:563b70517320 596 return value;
jengbrecht 0:563b70517320 597 }
jengbrecht 0:563b70517320 598
jengbrecht 0:563b70517320 599 Cellular::Registration Cellular::getRegistration()
jengbrecht 0:563b70517320 600 {
sgodinez 96:27bdf4aa3a31 601 string response = sendCommand("AT+CREG?", 5000);
jengbrecht 0:563b70517320 602 if (response.find("OK") == string::npos) {
jengbrecht 0:563b70517320 603 return UNKNOWN;
jengbrecht 0:563b70517320 604 }
jengbrecht 0:563b70517320 605 int start = response.find(',');
jengbrecht 0:563b70517320 606 int stop = response.find(' ', start);
jengbrecht 0:563b70517320 607 string regStat = response.substr(start + 1, stop - start - 1);
jengbrecht 0:563b70517320 608 int value;
jengbrecht 0:563b70517320 609 sscanf(regStat.c_str(), "%d", &value);
jengbrecht 0:563b70517320 610 switch (value) {
jengbrecht 0:563b70517320 611 case 0:
jengbrecht 0:563b70517320 612 return NOT_REGISTERED;
jengbrecht 0:563b70517320 613 case 1:
jengbrecht 0:563b70517320 614 return REGISTERED;
jengbrecht 0:563b70517320 615 case 2:
jengbrecht 0:563b70517320 616 return SEARCHING;
jengbrecht 0:563b70517320 617 case 3:
jengbrecht 0:563b70517320 618 return DENIED;
jengbrecht 0:563b70517320 619 case 4:
jengbrecht 0:563b70517320 620 return UNKNOWN;
jengbrecht 0:563b70517320 621 case 5:
jengbrecht 0:563b70517320 622 return ROAMING;
jengbrecht 0:563b70517320 623 }
sgodinez 4:6561c9128c6f 624 return UNKNOWN;
jengbrecht 0:563b70517320 625 }
jengbrecht 0:563b70517320 626
jengbrecht 82:5aa75004e553 627 Code Cellular::setApn(const std::string& apn)
jengbrecht 82:5aa75004e553 628 {
sgodinez 11:134435d8a2d5 629 Code code = sendBasicCommand("AT#APNSERV=\"" + apn + "\"", 1000);
sgodinez 71:82205735732b 630 if (code != SUCCESS) {
sgodinez 11:134435d8a2d5 631 return code;
sgodinez 11:134435d8a2d5 632 }
sgodinez 11:134435d8a2d5 633 this->apn = apn;
sgodinez 11:134435d8a2d5 634 return code;
sgodinez 11:134435d8a2d5 635 }
sgodinez 11:134435d8a2d5 636
sgodinez 43:3cacf019ed7d 637
jengbrecht 82:5aa75004e553 638 Code Cellular::setDns(const std::string& primary, const std::string& secondary)
jengbrecht 82:5aa75004e553 639 {
sgodinez 41:81d035fb0b6a 640 return sendBasicCommand("AT#DNS=1," + primary + "," + secondary, 1000);
sgodinez 11:134435d8a2d5 641 }
sgodinez 11:134435d8a2d5 642
jengbrecht 82:5aa75004e553 643 bool Cellular::ping(const std::string& address)
jengbrecht 82:5aa75004e553 644 {
jengbrecht 23:bc6f98a1eb22 645 char buffer[256] = {0};
jengbrecht 23:bc6f98a1eb22 646 Code code;
jengbrecht 82:5aa75004e553 647
jengbrecht 23:bc6f98a1eb22 648 code = sendBasicCommand("AT#PINGREMOTE=\"" + address + "\"", 1000);
sgodinez 71:82205735732b 649 if (code != SUCCESS) {
jengbrecht 23:bc6f98a1eb22 650 return false;
jengbrecht 23:bc6f98a1eb22 651 }
jengbrecht 82:5aa75004e553 652
jengbrecht 23:bc6f98a1eb22 653 sprintf(buffer, "AT#PINGNUM=%d", 1);
jengbrecht 23:bc6f98a1eb22 654 code = sendBasicCommand(buffer , 1000);
sgodinez 71:82205735732b 655 if (code != SUCCESS) {
jengbrecht 23:bc6f98a1eb22 656 return false;
jengbrecht 23:bc6f98a1eb22 657 }
jengbrecht 82:5aa75004e553 658
jengbrecht 23:bc6f98a1eb22 659 sprintf(buffer, "AT#PINGDELAY=%d", PINGDELAY);
jengbrecht 23:bc6f98a1eb22 660 code = sendBasicCommand(buffer , 1000);
sgodinez 71:82205735732b 661 if (code != SUCCESS) {
jengbrecht 23:bc6f98a1eb22 662 return false;
jengbrecht 23:bc6f98a1eb22 663 }
jengbrecht 82:5aa75004e553 664
jengbrecht 23:bc6f98a1eb22 665 std::string response;
jengbrecht 23:bc6f98a1eb22 666 for (int i = 0; i < PINGNUM; i++) {
jengbrecht 23:bc6f98a1eb22 667 response = sendCommand("AT#PING", PINGDELAY * 1000);
jengbrecht 23:bc6f98a1eb22 668 if (response.find("alive") != std::string::npos) {
jengbrecht 23:bc6f98a1eb22 669 return true;
jengbrecht 23:bc6f98a1eb22 670 }
jengbrecht 23:bc6f98a1eb22 671 }
jengbrecht 23:bc6f98a1eb22 672 return false;
jengbrecht 23:bc6f98a1eb22 673 }
jengbrecht 23:bc6f98a1eb22 674
jengbrecht 82:5aa75004e553 675 Code Cellular::setSocketCloseable(bool enabled)
jengbrecht 82:5aa75004e553 676 {
sgodinez 17:2d7c4ea7491b 677 if(socketCloseable == enabled) {
jengbrecht 82:5aa75004e553 678 return SUCCESS;
sgodinez 17:2d7c4ea7491b 679 }
jengbrecht 82:5aa75004e553 680
sgodinez 17:2d7c4ea7491b 681 if(socketOpened) {
jengbrecht 82:5aa75004e553 682 printf("[ERROR] socket is already opened. Can not set closeable\r\n");
sgodinez 71:82205735732b 683 return ERROR;
sgodinez 17:2d7c4ea7491b 684 }
jengbrecht 82:5aa75004e553 685
sgodinez 17:2d7c4ea7491b 686 socketCloseable = enabled;
jengbrecht 82:5aa75004e553 687
sgodinez 71:82205735732b 688 return SUCCESS;
sgodinez 17:2d7c4ea7491b 689 }
sgodinez 17:2d7c4ea7491b 690
jengbrecht 82:5aa75004e553 691 Code Cellular::sendSMS(const Sms& sms)
jengbrecht 82:5aa75004e553 692 {
sgodinez 4:6561c9128c6f 693 return sendSMS(sms.phoneNumber, sms.message);
sgodinez 4:6561c9128c6f 694 }
sgodinez 4:6561c9128c6f 695
sgodinez 71:82205735732b 696 Code Cellular::sendSMS(const std::string& phoneNumber, const std::string& message)
jengbrecht 82:5aa75004e553 697 {
jengbrecht 0:563b70517320 698 Code code = sendBasicCommand("AT+CMGF=1", 1000);
sgodinez 71:82205735732b 699 if (code != SUCCESS) {
jengbrecht 0:563b70517320 700 return code;
jengbrecht 0:563b70517320 701 }
jengbrecht 0:563b70517320 702 string cmd = "AT+CMGS=\"+";
jengbrecht 0:563b70517320 703 cmd.append(phoneNumber);
jengbrecht 0:563b70517320 704 cmd.append("\"");
jengbrecht 0:563b70517320 705 string response1 = sendCommand(cmd, 1000);
jengbrecht 0:563b70517320 706 if (response1.find('>') == string::npos) {
sgodinez 71:82205735732b 707 return NO_RESPONSE;
jengbrecht 0:563b70517320 708 }
jengbrecht 0:563b70517320 709 wait(.2);
jengbrecht 0:563b70517320 710 string response2 = sendCommand(message, 4000, CTRL_Z);
sgodinez 17:2d7c4ea7491b 711 printf("SMS Response: %s\r\n", response2.c_str());
jengbrecht 0:563b70517320 712 if (response2.find("+CMGS:") == string::npos) {
sgodinez 71:82205735732b 713 return FAILURE;
jengbrecht 0:563b70517320 714 }
sgodinez 71:82205735732b 715 return SUCCESS;
jengbrecht 0:563b70517320 716 }
jengbrecht 0:563b70517320 717
jengbrecht 82:5aa75004e553 718 std::vector<Cellular::Sms> Cellular::getReceivedSms()
jengbrecht 82:5aa75004e553 719 {
sgodinez 9:5b12c5a8dde4 720 int smsNumber = 0;
sgodinez 4:6561c9128c6f 721 std::vector<Sms> vSms;
sgodinez 4:6561c9128c6f 722 std::string received = sendCommand("AT+CMGL=\"ALL\"", 4000);
sgodinez 5:93e889a5abc6 723 size_t pos = received.find("+CMGL: ");
jengbrecht 82:5aa75004e553 724
sgodinez 5:93e889a5abc6 725 while (pos != std::string::npos) {
sgodinez 4:6561c9128c6f 726 Cellular::Sms sms;
sgodinez 4:6561c9128c6f 727 std::string line(Text::getLine(received, pos, pos));
sgodinez 17:2d7c4ea7491b 728 //printf("[DEBUG] Top of SMS Parse Loop. LINE[%s]\r\n", line.c_str());
jengbrecht 82:5aa75004e553 729 if(line.find("+CMGL: ") == std::string::npos) {
sgodinez 4:6561c9128c6f 730 continue;
sgodinez 4:6561c9128c6f 731 }
jengbrecht 82:5aa75004e553 732
sgodinez 4:6561c9128c6f 733 //Start of SMS message
sgodinez 4:6561c9128c6f 734 std::vector<std::string> vSmsParts = Text::split(line, ',');
sgodinez 4:6561c9128c6f 735 if(vSmsParts.size() != 6) {
sgodinez 17:2d7c4ea7491b 736 printf("[WARNING] Expected 6 commas. SMS[%d] DATA[%s]. Continuing ...\r\n", smsNumber, line.c_str());
sgodinez 4:6561c9128c6f 737 continue;
sgodinez 4:6561c9128c6f 738 }
jengbrecht 82:5aa75004e553 739
sgodinez 4:6561c9128c6f 740 sms.phoneNumber = vSmsParts[2];
sgodinez 4:6561c9128c6f 741 sms.timestamp = vSmsParts[4] + ", " + vSmsParts[5];
jengbrecht 82:5aa75004e553 742
sgodinez 8:3fe68d6130a8 743 if(pos == std::string::npos) {
sgodinez 17:2d7c4ea7491b 744 printf("[WARNING] Expected SMS body. SMS[%d]. Leaving ...\r\n", smsNumber);
sgodinez 8:3fe68d6130a8 745 break;
sgodinez 8:3fe68d6130a8 746 }
sgodinez 9:5b12c5a8dde4 747 //Check for the start of the next SMS message
sgodinez 9:5b12c5a8dde4 748 size_t bodyEnd = received.find("\r\n+CMGL: ", pos);
sgodinez 8:3fe68d6130a8 749 if(bodyEnd == std::string::npos) {
sgodinez 17:2d7c4ea7491b 750 //printf("[DEBUG] Parsing Last SMS. SMS[%d]\r\n", smsNumber);
sgodinez 9:5b12c5a8dde4 751 //This must be the last SMS message
sgodinez 9:5b12c5a8dde4 752 bodyEnd = received.find("\r\n\r\nOK", pos);
sgodinez 8:3fe68d6130a8 753 }
jengbrecht 82:5aa75004e553 754
sgodinez 9:5b12c5a8dde4 755 //Safety check that we found the boundary of this current SMS message
sgodinez 9:5b12c5a8dde4 756 if(bodyEnd != std::string::npos) {
sgodinez 9:5b12c5a8dde4 757 sms.message = received.substr(pos, bodyEnd - pos);
sgodinez 9:5b12c5a8dde4 758 } else {
sgodinez 8:3fe68d6130a8 759 sms.message = received.substr(pos);
sgodinez 17:2d7c4ea7491b 760 printf("[WARNING] Expected to find end of SMS list. SMS[%d] DATA[%s].\r\n", smsNumber, sms.message.c_str());
sgodinez 8:3fe68d6130a8 761 }
sgodinez 5:93e889a5abc6 762 vSms.push_back(sms);
sgodinez 4:6561c9128c6f 763 pos = bodyEnd;
sgodinez 17:2d7c4ea7491b 764 //printf("[DEBUG] Parsed SMS[%d]. Starting Next at position [%d]\r\n", smsNumber, pos);
sgodinez 9:5b12c5a8dde4 765 smsNumber++;
sgodinez 4:6561c9128c6f 766 }
sgodinez 17:2d7c4ea7491b 767 printf("Received %d SMS\r\n", smsNumber);
sgodinez 4:6561c9128c6f 768 return vSms;
sgodinez 4:6561c9128c6f 769 }
sgodinez 4:6561c9128c6f 770
jengbrecht 82:5aa75004e553 771 Code Cellular::deleteOnlyReceivedReadSms()
jengbrecht 82:5aa75004e553 772 {
sgodinez 4:6561c9128c6f 773 return sendBasicCommand("AT+CMGD=1,1", 1000);
sgodinez 4:6561c9128c6f 774 }
sgodinez 4:6561c9128c6f 775
jengbrecht 82:5aa75004e553 776 Code Cellular::deleteAllReceivedSms()
jengbrecht 82:5aa75004e553 777 {
sgodinez 4:6561c9128c6f 778 return sendBasicCommand("AT+CMGD=1,4", 1000);
sgodinez 4:6561c9128c6f 779 }
sgodinez 4:6561c9128c6f 780
sgodinez 96:27bdf4aa3a31 781 Code Cellular::sendBasicCommand(const std::string& command, unsigned int timeoutMillis, char esc)
sgodinez 96:27bdf4aa3a31 782 {
sgodinez 96:27bdf4aa3a31 783 if(socketOpened) {
sgodinez 96:27bdf4aa3a31 784 printf("[ERROR] socket is open. Can not send AT commands\r\n");
sgodinez 96:27bdf4aa3a31 785 return ERROR;
sgodinez 96:27bdf4aa3a31 786 }
sgodinez 96:27bdf4aa3a31 787
sgodinez 96:27bdf4aa3a31 788 string response = sendCommand(command, timeoutMillis, esc);
sgodinez 96:27bdf4aa3a31 789 if (response.size() == 0) {
sgodinez 96:27bdf4aa3a31 790 return NO_RESPONSE;
sgodinez 96:27bdf4aa3a31 791 } else if (response.find("OK") != string::npos) {
sgodinez 96:27bdf4aa3a31 792 return SUCCESS;
sgodinez 96:27bdf4aa3a31 793 } else if (response.find("ERROR") != string::npos) {
sgodinez 96:27bdf4aa3a31 794 return ERROR;
sgodinez 96:27bdf4aa3a31 795 } else {
sgodinez 96:27bdf4aa3a31 796 return FAILURE;
sgodinez 96:27bdf4aa3a31 797 }
sgodinez 96:27bdf4aa3a31 798 }
sgodinez 4:6561c9128c6f 799
sgodinez 71:82205735732b 800 string Cellular::sendCommand(const std::string& command, unsigned int timeoutMillis, char esc)
jengbrecht 0:563b70517320 801 {
sgodinez 19:38794784e009 802 if(io == NULL) {
sgodinez 19:38794784e009 803 printf("[ERROR] MTSBufferedIO not set\r\n");
sgodinez 19:38794784e009 804 return "";
sgodinez 19:38794784e009 805 }
sgodinez 17:2d7c4ea7491b 806 if(socketOpened) {
jengbrecht 82:5aa75004e553 807 printf("[ERROR] socket is open. Can not send AT commands\r\n");
sgodinez 17:2d7c4ea7491b 808 return "";
sgodinez 17:2d7c4ea7491b 809 }
sgodinez 17:2d7c4ea7491b 810
sgodinez 19:38794784e009 811 io->rxClear();
sgodinez 19:38794784e009 812 io->txClear();
sgodinez 8:3fe68d6130a8 813 std::string result;
jengbrecht 82:5aa75004e553 814
sgodinez 68:c490e4a51778 815 //Attempt to write command
sgodinez 68:c490e4a51778 816 if(io->write(command.data(), command.size(), timeoutMillis) != command.size()) {
sgodinez 68:c490e4a51778 817 //Failed to write command
sgodinez 68:c490e4a51778 818 printf("[ERROR] failed to send command to radio within %d milliseconds\r\n", timeoutMillis);
sgodinez 68:c490e4a51778 819 return "";
sgodinez 68:c490e4a51778 820 }
jengbrecht 82:5aa75004e553 821
sgodinez 68:c490e4a51778 822 //Send Escape Character
sgodinez 71:82205735732b 823 if (esc != 0x00) {
sgodinez 71:82205735732b 824 if(io->write(esc, timeoutMillis) != 1) {
sgodinez 101:27bb34e23304 825 printf("[ERROR] failed to send character '%c' (0x%02X) to radio within %d milliseconds\r\n", esc, esc, timeoutMillis);
sgodinez 68:c490e4a51778 826 return "";
sgodinez 68:c490e4a51778 827 }
sgodinez 68:c490e4a51778 828 }
sgodinez 68:c490e4a51778 829
jengbrecht 0:563b70517320 830 int timer = 0;
sgodinez 68:c490e4a51778 831 size_t previous = 0;
sgodinez 8:3fe68d6130a8 832 char tmp[256];
sgodinez 8:3fe68d6130a8 833 tmp[255] = 0;
sgodinez 13:0af863114629 834 bool started = !echoMode;
sgodinez 13:0af863114629 835 bool done = false;
sgodinez 8:3fe68d6130a8 836 do {
sgodinez 91:9439ad14d7f0 837 wait(0.1);
sgodinez 91:9439ad14d7f0 838 timer += 100;
sgodinez 91:9439ad14d7f0 839
sgodinez 68:c490e4a51778 840 previous = result.size();
sgodinez 91:9439ad14d7f0 841 //Make a non-blocking read call by passing timeout of zero
sgodinez 91:9439ad14d7f0 842 int size = io->read(tmp,255,0); //1 less than allocated (timeout is instant)
sgodinez 8:3fe68d6130a8 843 if(size > 0) {
sgodinez 8:3fe68d6130a8 844 result.append(tmp, size);
sgodinez 8:3fe68d6130a8 845 }
sgodinez 13:0af863114629 846 if(!started) {
sgodinez 13:0af863114629 847 //In Echo Mode (Command will have echo'd + 2 characters for \r\n)
sgodinez 13:0af863114629 848 if(result.size() > command.size() + 2) {
sgodinez 13:0af863114629 849 started = true;
sgodinez 13:0af863114629 850 }
sgodinez 13:0af863114629 851 } else {
sgodinez 68:c490e4a51778 852 done = (result.size() == previous);
sgodinez 13:0af863114629 853 }
sgodinez 13:0af863114629 854 if(timer >= timeoutMillis) {
sgodinez 110:8f3149c99112 855 printf("[WARNING] sendCommand [%s] timed out after %d milliseconds\r\n", command.c_str(), timeoutMillis);
sgodinez 13:0af863114629 856 done = true;
sgodinez 13:0af863114629 857 }
sgodinez 13:0af863114629 858 } while (!done);
jengbrecht 82:5aa75004e553 859
sgodinez 8:3fe68d6130a8 860 return result;
jengbrecht 0:563b70517320 861 }
jengbrecht 0:563b70517320 862
jengbrecht 56:e5e5351f14b3 863 std::string Cellular::getRegistrationNames(Registration registration)
jengbrecht 56:e5e5351f14b3 864 {
jengbrecht 56:e5e5351f14b3 865 switch(registration) {
jengbrecht 56:e5e5351f14b3 866 case NOT_REGISTERED:
jengbrecht 56:e5e5351f14b3 867 return "NOT_REGISTERED";
jengbrecht 56:e5e5351f14b3 868 case REGISTERED:
jengbrecht 56:e5e5351f14b3 869 return "REGISTERED";
jengbrecht 56:e5e5351f14b3 870 case SEARCHING:
jengbrecht 56:e5e5351f14b3 871 return "SEARCHING";
jengbrecht 56:e5e5351f14b3 872 case DENIED:
jengbrecht 56:e5e5351f14b3 873 return "DENIED";
jengbrecht 56:e5e5351f14b3 874 case UNKNOWN:
jengbrecht 56:e5e5351f14b3 875 return "UNKNOWN";
jengbrecht 56:e5e5351f14b3 876 case ROAMING:
jengbrecht 56:e5e5351f14b3 877 return "ROAMING";
jengbrecht 56:e5e5351f14b3 878 default:
jengbrecht 56:e5e5351f14b3 879 return "UNKNOWN ENUM";
jengbrecht 56:e5e5351f14b3 880 }
jengbrecht 56:e5e5351f14b3 881 }