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:
Fri Dec 20 16:26:10 2013 +0000
Revision:
55:56d9a9d98079
Parent:
53:27c9622de0f9
Child:
57:88b07490d7e8
Child:
58:408f67fa292f
Got UDP working

Who changed what in which revision?

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