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 21:10:13 2013 +0000
Revision:
58:408f67fa292f
Parent:
55:56d9a9d98079
Child:
59:7777b3ed5a4c
Changed Cellular::read() to allow retrieval of remaining rx bytes after socket closed

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 58:408f67fa292f 308 //Check that nothing is in the rx buffer
sgodinez 58:408f67fa292f 309 if(!socketOpened && !io->readable()) {
sgodinez 17:2d7c4ea7491b 310 printf("[ERROR] Socket is not open\r\n");
sgodinez 17:2d7c4ea7491b 311 return -1;
sgodinez 17:2d7c4ea7491b 312 }
sgodinez 17:2d7c4ea7491b 313 int bytesRead = 0;
sgodinez 32:629e6b1c8e22 314
sgodinez 17:2d7c4ea7491b 315 if(timeout >= 0) {
sgodinez 17:2d7c4ea7491b 316 Timer tmr;
sgodinez 17:2d7c4ea7491b 317 tmr.start();
sgodinez 35:f28acb1be52d 318 do {
sgodinez 32:629e6b1c8e22 319 int available = io->readable();
sgodinez 32:629e6b1c8e22 320 if (available > 0) {
sgodinez 32:629e6b1c8e22 321 int size = MIN(available, max - bytesRead);
sgodinez 32:629e6b1c8e22 322 bytesRead += io->read(&data[bytesRead], size);
sgodinez 17:2d7c4ea7491b 323 } else {
sgodinez 17:2d7c4ea7491b 324 wait(0.05);
sgodinez 17:2d7c4ea7491b 325 }
sgodinez 35:f28acb1be52d 326 } while (tmr.read_ms() <= timeout && bytesRead < max);
sgodinez 17:2d7c4ea7491b 327 } else {
sgodinez 19:38794784e009 328 bytesRead = io->read(data, max);
sgodinez 17:2d7c4ea7491b 329 }
sgodinez 17:2d7c4ea7491b 330
sgodinez 32:629e6b1c8e22 331 if(bytesRead > 0 && socketCloseable) {
sgodinez 32:629e6b1c8e22 332 //Remove escape characters
sgodinez 32:629e6b1c8e22 333 int index = 0;
sgodinez 32:629e6b1c8e22 334 bool escapeFlag = false;
sgodinez 32:629e6b1c8e22 335 for(int i = 0; i < bytesRead; i++) {
sgodinez 32:629e6b1c8e22 336 if(data[i] == DLE || data[i] == ETX) {
sgodinez 32:629e6b1c8e22 337 if(escapeFlag == true) {
sgodinez 32:629e6b1c8e22 338 //This character has been escaped
sgodinez 32:629e6b1c8e22 339 escapeFlag = false;
sgodinez 32:629e6b1c8e22 340 } else if(data[bytesRead] == DLE) {
sgodinez 32:629e6b1c8e22 341 //Found escape character
sgodinez 32:629e6b1c8e22 342 escapeFlag = true;
sgodinez 32:629e6b1c8e22 343 continue;
sgodinez 32:629e6b1c8e22 344 } else {
sgodinez 32:629e6b1c8e22 345 //ETX sent without escape -> Socket closed
sgodinez 32:629e6b1c8e22 346 printf("[INFO] Read ETX character without DLE escape. Socket closed\r\n");
sgodinez 32:629e6b1c8e22 347 socketOpened = false;
sgodinez 32:629e6b1c8e22 348 continue;
sgodinez 32:629e6b1c8e22 349 }
sgodinez 32:629e6b1c8e22 350 }
sgodinez 32:629e6b1c8e22 351
sgodinez 32:629e6b1c8e22 352 if(index != i) {
sgodinez 32:629e6b1c8e22 353 data[index] = data[i];
sgodinez 32:629e6b1c8e22 354 }
sgodinez 32:629e6b1c8e22 355 index++;
sgodinez 32:629e6b1c8e22 356 }
sgodinez 32:629e6b1c8e22 357 bytesRead = index;
sgodinez 32:629e6b1c8e22 358 }
sgodinez 32:629e6b1c8e22 359
sgodinez 32:629e6b1c8e22 360 printf("[DEBUG] Scanning received data for socket closed message\r\n");
sgodinez 32:629e6b1c8e22 361 //Scan for socket closed message
sgodinez 32:629e6b1c8e22 362 for(size_t i = 0; i < bytesRead; i++) {
sgodinez 32:629e6b1c8e22 363 if(data[i] == 'O') {
sgodinez 32:629e6b1c8e22 364 if(strstr(&data[i], "Ok_Info_SocketClosed")) {
sgodinez 32:629e6b1c8e22 365 printf("[INFO] Found socket closed message. Socket closed\r\n");
sgodinez 32:629e6b1c8e22 366 //Close socket and Cut Off End of Message
sgodinez 32:629e6b1c8e22 367 socketOpened = false;
sgodinez 32:629e6b1c8e22 368 data[i] = '\0';
sgodinez 32:629e6b1c8e22 369 bytesRead = i;
sgodinez 32:629e6b1c8e22 370 break;
sgodinez 32:629e6b1c8e22 371 }
sgodinez 32:629e6b1c8e22 372 }
sgodinez 32:629e6b1c8e22 373 }
sgodinez 17:2d7c4ea7491b 374 return bytesRead;
sgodinez 11:134435d8a2d5 375 }
sgodinez 11:134435d8a2d5 376
sgodinez 41:81d035fb0b6a 377 int Cellular::write(const char* data, int length, int timeout) {
sgodinez 19:38794784e009 378 if(io == NULL) {
sgodinez 19:38794784e009 379 printf("[ERROR] MTSBufferedIO not set\r\n");
sgodinez 19:38794784e009 380 return -1;
sgodinez 19:38794784e009 381 }
sgodinez 19:38794784e009 382
sgodinez 17:2d7c4ea7491b 383 if(!socketOpened) {
sgodinez 17:2d7c4ea7491b 384 printf("[ERROR] Socket is not open\r\n");
sgodinez 17:2d7c4ea7491b 385 return -1;
sgodinez 17:2d7c4ea7491b 386 }
sgodinez 17:2d7c4ea7491b 387
sgodinez 35:f28acb1be52d 388 //In order to avoid allocating another buffer, capture indices of
sgodinez 35:f28acb1be52d 389 //characters to escape during write
sgodinez 35:f28acb1be52d 390 int specialWritten = 0;
sgodinez 35:f28acb1be52d 391 std::vector<int> vSpecial;
sgodinez 35:f28acb1be52d 392 if(socketCloseable) {
sgodinez 35:f28acb1be52d 393 for(int i = 0; i < length; i++) {
sgodinez 35:f28acb1be52d 394 if(data[i] == ETX || data[i] == DLE) {
sgodinez 35:f28acb1be52d 395 //Push back index of special characters
sgodinez 35:f28acb1be52d 396 vSpecial.push_back(i);
sgodinez 35:f28acb1be52d 397 }
sgodinez 35:f28acb1be52d 398 }
sgodinez 35:f28acb1be52d 399 }
sgodinez 35:f28acb1be52d 400
sgodinez 17:2d7c4ea7491b 401 int bytesWritten = 0;
sgodinez 17:2d7c4ea7491b 402 if(timeout >= 0) {
sgodinez 17:2d7c4ea7491b 403 Timer tmr;
sgodinez 17:2d7c4ea7491b 404 tmr.start();
sgodinez 35:f28acb1be52d 405 do {
sgodinez 35:f28acb1be52d 406 int capacity = io->writeable();
sgodinez 35:f28acb1be52d 407 if (capacity > 0) {
sgodinez 35:f28acb1be52d 408 if(specialWritten < vSpecial.size()) {
sgodinez 35:f28acb1be52d 409 //Check if current index is at a special character
sgodinez 35:f28acb1be52d 410 if(bytesWritten == vSpecial[specialWritten]) {
sgodinez 35:f28acb1be52d 411 if(capacity < 2) {
sgodinez 35:f28acb1be52d 412 //Requires at least two bytes of space
sgodinez 35:f28acb1be52d 413 wait(0.05);
sgodinez 35:f28acb1be52d 414 continue;
sgodinez 35:f28acb1be52d 415 }
sgodinez 35:f28acb1be52d 416 //Ready to write special character
sgodinez 35:f28acb1be52d 417 if(io->write(DLE)) {
sgodinez 35:f28acb1be52d 418 specialWritten++;
sgodinez 35:f28acb1be52d 419 if(io->write(data[bytesWritten])) {
sgodinez 35:f28acb1be52d 420 bytesWritten++;
sgodinez 35:f28acb1be52d 421 }
sgodinez 35:f28acb1be52d 422 } else {
sgodinez 35:f28acb1be52d 423 //Unable to write escape character, try again next round
sgodinez 35:f28acb1be52d 424 wait(0.05);
sgodinez 35:f28acb1be52d 425 }
sgodinez 35:f28acb1be52d 426 } else {
sgodinez 35:f28acb1be52d 427 //We want to write all the way up to the next special character
sgodinez 35:f28acb1be52d 428 int relativeIndex = vSpecial[specialWritten] - bytesWritten;
sgodinez 35:f28acb1be52d 429 int size = MIN(capacity, relativeIndex);
sgodinez 35:f28acb1be52d 430 bytesWritten += io->write(&data[bytesWritten], size);
sgodinez 35:f28acb1be52d 431 }
sgodinez 35:f28acb1be52d 432 } else {
sgodinez 35:f28acb1be52d 433 int size = MIN(capacity, length - bytesWritten);
sgodinez 35:f28acb1be52d 434 bytesWritten += io->write(&data[bytesWritten], size);
sgodinez 17:2d7c4ea7491b 435 }
sgodinez 17:2d7c4ea7491b 436 } else {
sgodinez 35:f28acb1be52d 437 wait(0.05);
sgodinez 35:f28acb1be52d 438 }
sgodinez 35:f28acb1be52d 439 } while (tmr.read_ms() <= timeout && bytesWritten < length);
sgodinez 35:f28acb1be52d 440 } else {
sgodinez 35:f28acb1be52d 441 for(int i = 0; i < vSpecial.size(); i++) {
sgodinez 35:f28acb1be52d 442 //Write up to the special character, then write the special character
sgodinez 35:f28acb1be52d 443 int size = vSpecial[i] - bytesWritten;
sgodinez 35:f28acb1be52d 444 int currentWritten = io->write(&data[bytesWritten], size);
sgodinez 35:f28acb1be52d 445 bytesWritten += currentWritten;
sgodinez 35:f28acb1be52d 446 if(currentWritten != size) {
sgodinez 35:f28acb1be52d 447 //Failed to write up to the special character.
sgodinez 35:f28acb1be52d 448 return bytesWritten;
sgodinez 35:f28acb1be52d 449 }
sgodinez 35:f28acb1be52d 450 if(io->write(DLE) && io->write(data[bytesWritten])) {
sgodinez 35:f28acb1be52d 451 bytesWritten++;
sgodinez 35:f28acb1be52d 452 } else {
sgodinez 35:f28acb1be52d 453 //Failed to write the special character.
sgodinez 35:f28acb1be52d 454 return bytesWritten;
sgodinez 17:2d7c4ea7491b 455 }
sgodinez 17:2d7c4ea7491b 456 }
sgodinez 35:f28acb1be52d 457
sgodinez 35:f28acb1be52d 458 bytesWritten = io->write(&data[bytesWritten], length - bytesWritten);
sgodinez 17:2d7c4ea7491b 459 }
sgodinez 17:2d7c4ea7491b 460
sgodinez 17:2d7c4ea7491b 461 return bytesWritten;
sgodinez 11:134435d8a2d5 462 }
sgodinez 11:134435d8a2d5 463
sgodinez 11:134435d8a2d5 464 unsigned int Cellular::readable() {
sgodinez 19:38794784e009 465 if(io == NULL) {
sgodinez 19:38794784e009 466 printf("[ERROR] MTSBufferedIO not set\r\n");
sgodinez 19:38794784e009 467 return 0;
sgodinez 19:38794784e009 468 }
sgodinez 17:2d7c4ea7491b 469 if(!socketOpened) {
sgodinez 17:2d7c4ea7491b 470 printf("[ERROR] Socket is not open\r\n");
sgodinez 17:2d7c4ea7491b 471 return 0;
sgodinez 17:2d7c4ea7491b 472 }
sgodinez 19:38794784e009 473 return io->readable();
sgodinez 11:134435d8a2d5 474 }
sgodinez 11:134435d8a2d5 475
sgodinez 11:134435d8a2d5 476 unsigned int Cellular::writeable() {
sgodinez 19:38794784e009 477 if(io == NULL) {
sgodinez 19:38794784e009 478 printf("[ERROR] MTSBufferedIO not set\r\n");
sgodinez 19:38794784e009 479 return 0;
sgodinez 19:38794784e009 480 }
sgodinez 17:2d7c4ea7491b 481 if(!socketOpened) {
sgodinez 17:2d7c4ea7491b 482 printf("[ERROR] Socket is not open\r\n");
sgodinez 17:2d7c4ea7491b 483 return 0;
sgodinez 17:2d7c4ea7491b 484 }
sgodinez 17:2d7c4ea7491b 485
sgodinez 19:38794784e009 486 return io->writeable();
sgodinez 11:134435d8a2d5 487 }
sgodinez 11:134435d8a2d5 488
sgodinez 11:134435d8a2d5 489 void Cellular::reset() {
mfiore 29:7408b1bdad37 490 disconnect();
mfiore 29:7408b1bdad37 491 Code code = sendBasicCommand("AT#RESET=0", 10000);
mfiore 39:6e94520a3217 492 if(code != CELL_OK) {
mfiore 29:7408b1bdad37 493 printf("[ERROR] Socket Modem did not accept RESET command\n\r");
mfiore 29:7408b1bdad37 494 } else {
mfiore 29:7408b1bdad37 495 printf("[WARNING] Socket Modem is resetting, allow 30 seconds for it to come back\n\r");
mfiore 29:7408b1bdad37 496 }
sgodinez 11:134435d8a2d5 497 }
sgodinez 11:134435d8a2d5 498
sgodinez 11:134435d8a2d5 499 Cellular::Code Cellular::test()
jengbrecht 0:563b70517320 500 {
sgodinez 11:134435d8a2d5 501 Code code = sendBasicCommand("AT", 1000);
sgodinez 11:134435d8a2d5 502
mfiore 39:6e94520a3217 503 if(code != CELL_OK) {
sgodinez 11:134435d8a2d5 504 printf("[Error] Failed basic AT command");
sgodinez 11:134435d8a2d5 505 return code;
sgodinez 11:134435d8a2d5 506 }
sgodinez 11:134435d8a2d5 507
sgodinez 11:134435d8a2d5 508 //AT#VSTATE != "CHECKING"
sgodinez 11:134435d8a2d5 509
sgodinez 11:134435d8a2d5 510 //AT#GPRSMODE ==
mfiore 39:6e94520a3217 511 return CELL_OK;
jengbrecht 0:563b70517320 512 }
jengbrecht 0:563b70517320 513
mfiore 29:7408b1bdad37 514 Cellular::Code Cellular::echo(bool state)
jengbrecht 0:563b70517320 515 {
sgodinez 13:0af863114629 516 Code code;
jengbrecht 0:563b70517320 517 if (state) {
sgodinez 13:0af863114629 518 code = sendBasicCommand("ATE0", 1000);
mfiore 39:6e94520a3217 519 echoMode = (code == CELL_OK) ? false : echoMode;
jengbrecht 0:563b70517320 520 } else {
sgodinez 13:0af863114629 521 code = sendBasicCommand("ATE1", 1000);
mfiore 39:6e94520a3217 522 echoMode = (code == CELL_OK) ? true : echoMode;
jengbrecht 0:563b70517320 523 }
sgodinez 13:0af863114629 524 return code;
jengbrecht 0:563b70517320 525 }
jengbrecht 0:563b70517320 526
jengbrecht 0:563b70517320 527 int Cellular::getSignalStrength()
jengbrecht 0:563b70517320 528 {
jengbrecht 0:563b70517320 529 string response = sendCommand("AT+CSQ", 1000);
jengbrecht 0:563b70517320 530 if (response.find("OK") == string::npos) {
jengbrecht 0:563b70517320 531 return -1;
jengbrecht 0:563b70517320 532 }
jengbrecht 0:563b70517320 533 int start = response.find(':');
jengbrecht 0:563b70517320 534 int stop = response.find(',', start);
jengbrecht 0:563b70517320 535 string signal = response.substr(start + 2, stop - start - 2);
jengbrecht 0:563b70517320 536 int value;
jengbrecht 0:563b70517320 537 sscanf(signal.c_str(), "%d", &value);
jengbrecht 0:563b70517320 538 return value;
jengbrecht 0:563b70517320 539 }
jengbrecht 0:563b70517320 540
sgodinez 5:93e889a5abc6 541 std::string Cellular::getPhoneNumber() {
sgodinez 5:93e889a5abc6 542 return "unknown";
sgodinez 5:93e889a5abc6 543 }
sgodinez 5:93e889a5abc6 544
jengbrecht 0:563b70517320 545 Cellular::Registration Cellular::getRegistration()
jengbrecht 0:563b70517320 546 {
jengbrecht 0:563b70517320 547 string response = sendCommand("AT+CREG?", 1000);
jengbrecht 0:563b70517320 548 if (response.find("OK") == string::npos) {
jengbrecht 0:563b70517320 549 return UNKNOWN;
jengbrecht 0:563b70517320 550 }
jengbrecht 0:563b70517320 551 int start = response.find(',');
jengbrecht 0:563b70517320 552 int stop = response.find(' ', start);
jengbrecht 0:563b70517320 553 string regStat = response.substr(start + 1, stop - start - 1);
jengbrecht 0:563b70517320 554 int value;
jengbrecht 0:563b70517320 555 sscanf(regStat.c_str(), "%d", &value);
jengbrecht 0:563b70517320 556 switch (value) {
jengbrecht 0:563b70517320 557 case 0:
jengbrecht 0:563b70517320 558 return NOT_REGISTERED;
jengbrecht 0:563b70517320 559 case 1:
jengbrecht 0:563b70517320 560 return REGISTERED;
jengbrecht 0:563b70517320 561 case 2:
jengbrecht 0:563b70517320 562 return SEARCHING;
jengbrecht 0:563b70517320 563 case 3:
jengbrecht 0:563b70517320 564 return DENIED;
jengbrecht 0:563b70517320 565 case 4:
jengbrecht 0:563b70517320 566 return UNKNOWN;
jengbrecht 0:563b70517320 567 case 5:
jengbrecht 0:563b70517320 568 return ROAMING;
jengbrecht 0:563b70517320 569 }
sgodinez 4:6561c9128c6f 570 return UNKNOWN;
jengbrecht 0:563b70517320 571 }
jengbrecht 0:563b70517320 572
jengbrecht 0:563b70517320 573 Cellular::Code Cellular::sendBasicCommand(string command, int timeoutMillis, ESC_CHAR esc)
jengbrecht 0:563b70517320 574 {
sgodinez 17:2d7c4ea7491b 575 if(socketOpened) {
sgodinez 17:2d7c4ea7491b 576 printf("[ERROR] socket is open. Can not send AT commands\r\n");
mfiore 39:6e94520a3217 577 return CELL_ERROR;
sgodinez 17:2d7c4ea7491b 578 }
sgodinez 17:2d7c4ea7491b 579
jengbrecht 0:563b70517320 580 string response = sendCommand(command, timeoutMillis, esc);
jengbrecht 0:563b70517320 581 if (response.size() == 0) {
mfiore 39:6e94520a3217 582 return CELL_NO_RESPONSE;
jengbrecht 0:563b70517320 583 } else if (response.find("OK") != string::npos) {
mfiore 39:6e94520a3217 584 return CELL_OK;
jengbrecht 0:563b70517320 585 } else if (response.find("ERROR") != string::npos) {
mfiore 39:6e94520a3217 586 return CELL_ERROR;
jengbrecht 0:563b70517320 587 } else {
mfiore 39:6e94520a3217 588 return CELL_FAILURE;
jengbrecht 0:563b70517320 589 }
jengbrecht 0:563b70517320 590 }
jengbrecht 0:563b70517320 591
sgodinez 11:134435d8a2d5 592 Cellular::Code Cellular::setApn(const std::string& apn) {
sgodinez 11:134435d8a2d5 593 Code code = sendBasicCommand("AT#APNSERV=\"" + apn + "\"", 1000);
mfiore 39:6e94520a3217 594 if (code != CELL_OK) {
sgodinez 11:134435d8a2d5 595 return code;
sgodinez 11:134435d8a2d5 596 }
sgodinez 11:134435d8a2d5 597 this->apn = apn;
sgodinez 11:134435d8a2d5 598 return code;
sgodinez 11:134435d8a2d5 599 }
sgodinez 11:134435d8a2d5 600
sgodinez 43:3cacf019ed7d 601
sgodinez 41:81d035fb0b6a 602 Cellular::Code Cellular::setDns(const std::string& primary, const std::string& secondary) {
sgodinez 41:81d035fb0b6a 603 return sendBasicCommand("AT#DNS=1," + primary + "," + secondary, 1000);
sgodinez 11:134435d8a2d5 604 }
sgodinez 11:134435d8a2d5 605
jengbrecht 23:bc6f98a1eb22 606 bool Cellular::ping(const std::string& address) {
jengbrecht 23:bc6f98a1eb22 607 char buffer[256] = {0};
jengbrecht 23:bc6f98a1eb22 608 Code code;
jengbrecht 23:bc6f98a1eb22 609
jengbrecht 23:bc6f98a1eb22 610 code = sendBasicCommand("AT#PINGREMOTE=\"" + address + "\"", 1000);
mfiore 39:6e94520a3217 611 if (code != CELL_OK) {
jengbrecht 23:bc6f98a1eb22 612 return false;
jengbrecht 23:bc6f98a1eb22 613 }
jengbrecht 23:bc6f98a1eb22 614
jengbrecht 23:bc6f98a1eb22 615 sprintf(buffer, "AT#PINGNUM=%d", 1);
jengbrecht 23:bc6f98a1eb22 616 code = sendBasicCommand(buffer , 1000);
mfiore 39:6e94520a3217 617 if (code != CELL_OK) {
jengbrecht 23:bc6f98a1eb22 618 return false;
jengbrecht 23:bc6f98a1eb22 619 }
jengbrecht 23:bc6f98a1eb22 620
jengbrecht 23:bc6f98a1eb22 621 sprintf(buffer, "AT#PINGDELAY=%d", PINGDELAY);
jengbrecht 23:bc6f98a1eb22 622 code = sendBasicCommand(buffer , 1000);
mfiore 39:6e94520a3217 623 if (code != CELL_OK) {
jengbrecht 23:bc6f98a1eb22 624 return false;
jengbrecht 23:bc6f98a1eb22 625 }
jengbrecht 23:bc6f98a1eb22 626
jengbrecht 23:bc6f98a1eb22 627 std::string response;
jengbrecht 23:bc6f98a1eb22 628 for (int i = 0; i < PINGNUM; i++) {
jengbrecht 23:bc6f98a1eb22 629 response = sendCommand("AT#PING", PINGDELAY * 1000);
jengbrecht 23:bc6f98a1eb22 630 if (response.find("alive") != std::string::npos) {
jengbrecht 23:bc6f98a1eb22 631 return true;
jengbrecht 23:bc6f98a1eb22 632 }
jengbrecht 23:bc6f98a1eb22 633 }
jengbrecht 23:bc6f98a1eb22 634 return false;
jengbrecht 23:bc6f98a1eb22 635 }
jengbrecht 23:bc6f98a1eb22 636
sgodinez 17:2d7c4ea7491b 637 Cellular::Code Cellular::setSocketCloseable(bool enabled) {
sgodinez 17:2d7c4ea7491b 638 if(socketCloseable == enabled) {
mfiore 39:6e94520a3217 639 return CELL_OK;
sgodinez 17:2d7c4ea7491b 640 }
sgodinez 17:2d7c4ea7491b 641
sgodinez 17:2d7c4ea7491b 642 if(socketOpened) {
sgodinez 17:2d7c4ea7491b 643 printf("[ERROR] socket is already opened. Can not set closeable\r\n");
mfiore 39:6e94520a3217 644 return CELL_ERROR;
sgodinez 17:2d7c4ea7491b 645 }
sgodinez 17:2d7c4ea7491b 646
sgodinez 17:2d7c4ea7491b 647 socketCloseable = enabled;
sgodinez 17:2d7c4ea7491b 648
mfiore 39:6e94520a3217 649 return CELL_OK;
sgodinez 17:2d7c4ea7491b 650 }
sgodinez 17:2d7c4ea7491b 651
sgodinez 4:6561c9128c6f 652 Cellular::Code Cellular::sendSMS(const Sms& sms) {
sgodinez 4:6561c9128c6f 653 return sendSMS(sms.phoneNumber, sms.message);
sgodinez 4:6561c9128c6f 654 }
sgodinez 4:6561c9128c6f 655
sgodinez 4:6561c9128c6f 656 Cellular::Code Cellular::sendSMS(const std::string& phoneNumber, const std::string& message)
sgodinez 17:2d7c4ea7491b 657 {
jengbrecht 0:563b70517320 658 Code code = sendBasicCommand("AT+CMGF=1", 1000);
mfiore 39:6e94520a3217 659 if (code != CELL_OK) {
jengbrecht 0:563b70517320 660 return code;
jengbrecht 0:563b70517320 661 }
jengbrecht 0:563b70517320 662 string cmd = "AT+CMGS=\"+";
jengbrecht 0:563b70517320 663 cmd.append(phoneNumber);
jengbrecht 0:563b70517320 664 cmd.append("\"");
jengbrecht 0:563b70517320 665 string response1 = sendCommand(cmd, 1000);
jengbrecht 0:563b70517320 666 if (response1.find('>') == string::npos) {
mfiore 39:6e94520a3217 667 return CELL_NO_RESPONSE;
jengbrecht 0:563b70517320 668 }
jengbrecht 0:563b70517320 669 wait(.2);
jengbrecht 0:563b70517320 670 string response2 = sendCommand(message, 4000, CTRL_Z);
sgodinez 17:2d7c4ea7491b 671 printf("SMS Response: %s\r\n", response2.c_str());
jengbrecht 0:563b70517320 672 if (response2.find("+CMGS:") == string::npos) {
mfiore 39:6e94520a3217 673 return CELL_FAILURE;
jengbrecht 0:563b70517320 674 }
mfiore 39:6e94520a3217 675 return CELL_OK;
jengbrecht 0:563b70517320 676 }
jengbrecht 0:563b70517320 677
sgodinez 4:6561c9128c6f 678 std::vector<Cellular::Sms> Cellular::getReceivedSms() {
sgodinez 9:5b12c5a8dde4 679 int smsNumber = 0;
sgodinez 4:6561c9128c6f 680 std::vector<Sms> vSms;
sgodinez 4:6561c9128c6f 681 std::string received = sendCommand("AT+CMGL=\"ALL\"", 4000);
sgodinez 5:93e889a5abc6 682 size_t pos = received.find("+CMGL: ");
sgodinez 4:6561c9128c6f 683
sgodinez 5:93e889a5abc6 684 while (pos != std::string::npos) {
sgodinez 4:6561c9128c6f 685 Cellular::Sms sms;
sgodinez 4:6561c9128c6f 686 std::string line(Text::getLine(received, pos, pos));
sgodinez 17:2d7c4ea7491b 687 //printf("[DEBUG] Top of SMS Parse Loop. LINE[%s]\r\n", line.c_str());
sgodinez 9:5b12c5a8dde4 688 if(line.find("+CMGL: ") == std::string::npos) {
sgodinez 4:6561c9128c6f 689 continue;
sgodinez 4:6561c9128c6f 690 }
sgodinez 4:6561c9128c6f 691
sgodinez 4:6561c9128c6f 692 //Start of SMS message
sgodinez 4:6561c9128c6f 693 std::vector<std::string> vSmsParts = Text::split(line, ',');
sgodinez 4:6561c9128c6f 694 if(vSmsParts.size() != 6) {
sgodinez 17:2d7c4ea7491b 695 printf("[WARNING] Expected 6 commas. SMS[%d] DATA[%s]. Continuing ...\r\n", smsNumber, line.c_str());
sgodinez 4:6561c9128c6f 696 continue;
sgodinez 4:6561c9128c6f 697 }
sgodinez 4:6561c9128c6f 698
sgodinez 4:6561c9128c6f 699 sms.phoneNumber = vSmsParts[2];
sgodinez 4:6561c9128c6f 700 sms.timestamp = vSmsParts[4] + ", " + vSmsParts[5];
sgodinez 4:6561c9128c6f 701
sgodinez 8:3fe68d6130a8 702 if(pos == std::string::npos) {
sgodinez 17:2d7c4ea7491b 703 printf("[WARNING] Expected SMS body. SMS[%d]. Leaving ...\r\n", smsNumber);
sgodinez 8:3fe68d6130a8 704 break;
sgodinez 8:3fe68d6130a8 705 }
sgodinez 9:5b12c5a8dde4 706 //Check for the start of the next SMS message
sgodinez 9:5b12c5a8dde4 707 size_t bodyEnd = received.find("\r\n+CMGL: ", pos);
sgodinez 8:3fe68d6130a8 708 if(bodyEnd == std::string::npos) {
sgodinez 17:2d7c4ea7491b 709 //printf("[DEBUG] Parsing Last SMS. SMS[%d]\r\n", smsNumber);
sgodinez 9:5b12c5a8dde4 710 //This must be the last SMS message
sgodinez 9:5b12c5a8dde4 711 bodyEnd = received.find("\r\n\r\nOK", pos);
sgodinez 8:3fe68d6130a8 712 }
sgodinez 9:5b12c5a8dde4 713
sgodinez 9:5b12c5a8dde4 714 //Safety check that we found the boundary of this current SMS message
sgodinez 9:5b12c5a8dde4 715 if(bodyEnd != std::string::npos) {
sgodinez 9:5b12c5a8dde4 716 sms.message = received.substr(pos, bodyEnd - pos);
sgodinez 9:5b12c5a8dde4 717 } else {
sgodinez 8:3fe68d6130a8 718 sms.message = received.substr(pos);
sgodinez 17:2d7c4ea7491b 719 printf("[WARNING] Expected to find end of SMS list. SMS[%d] DATA[%s].\r\n", smsNumber, sms.message.c_str());
sgodinez 8:3fe68d6130a8 720 }
sgodinez 5:93e889a5abc6 721 vSms.push_back(sms);
sgodinez 4:6561c9128c6f 722 pos = bodyEnd;
sgodinez 17:2d7c4ea7491b 723 //printf("[DEBUG] Parsed SMS[%d]. Starting Next at position [%d]\r\n", smsNumber, pos);
sgodinez 9:5b12c5a8dde4 724 smsNumber++;
sgodinez 4:6561c9128c6f 725 }
sgodinez 17:2d7c4ea7491b 726 printf("Received %d SMS\r\n", smsNumber);
sgodinez 4:6561c9128c6f 727 return vSms;
sgodinez 4:6561c9128c6f 728 }
sgodinez 4:6561c9128c6f 729
sgodinez 4:6561c9128c6f 730 Cellular::Code Cellular::deleteOnlyReceivedReadSms() {
sgodinez 4:6561c9128c6f 731 return sendBasicCommand("AT+CMGD=1,1", 1000);
sgodinez 4:6561c9128c6f 732 }
sgodinez 4:6561c9128c6f 733
sgodinez 4:6561c9128c6f 734 Cellular::Code Cellular::deleteAllReceivedSms() {
sgodinez 4:6561c9128c6f 735 return sendBasicCommand("AT+CMGD=1,4", 1000);
sgodinez 4:6561c9128c6f 736 }
sgodinez 4:6561c9128c6f 737
sgodinez 4:6561c9128c6f 738
jengbrecht 0:563b70517320 739 string Cellular::sendCommand(string command, int timeoutMillis, ESC_CHAR esc)
jengbrecht 0:563b70517320 740 {
sgodinez 19:38794784e009 741 if(io == NULL) {
sgodinez 19:38794784e009 742 printf("[ERROR] MTSBufferedIO not set\r\n");
sgodinez 19:38794784e009 743 return "";
sgodinez 19:38794784e009 744 }
sgodinez 17:2d7c4ea7491b 745 if(socketOpened) {
sgodinez 17:2d7c4ea7491b 746 printf("[ERROR] socket is open. Can not send AT commands\r\n");
sgodinez 17:2d7c4ea7491b 747 return "";
sgodinez 17:2d7c4ea7491b 748 }
sgodinez 17:2d7c4ea7491b 749
jengbrecht 0:563b70517320 750 int size = command.size() + 1;
jengbrecht 0:563b70517320 751 char cmd[size];
jengbrecht 0:563b70517320 752 strcpy(cmd, command.c_str());
jengbrecht 0:563b70517320 753 if (esc == CR) {
jengbrecht 0:563b70517320 754 cmd[size -1] = '\r';
jengbrecht 0:563b70517320 755 } else if (esc == CTRL_Z) {
jengbrecht 0:563b70517320 756 cmd[size -1] = 0x1A;
sgodinez 13:0af863114629 757 } else if(esc == NONE) {
sgodinez 13:0af863114629 758 cmd[size -1] = '\0';
jengbrecht 0:563b70517320 759 }
jengbrecht 0:563b70517320 760
sgodinez 19:38794784e009 761 io->rxClear();
sgodinez 19:38794784e009 762 io->txClear();
sgodinez 8:3fe68d6130a8 763 std::string result;
sgodinez 19:38794784e009 764 int status = io->write(cmd, size);
jengbrecht 36:bb6b293c7495 765 int available = io->readable();
jengbrecht 0:563b70517320 766 int previous = -1;
jengbrecht 0:563b70517320 767 int timer = 0;
sgodinez 8:3fe68d6130a8 768 char tmp[256];
sgodinez 8:3fe68d6130a8 769 tmp[255] = 0;
sgodinez 13:0af863114629 770 bool started = !echoMode;
sgodinez 13:0af863114629 771 bool done = false;
sgodinez 8:3fe68d6130a8 772 do {
jengbrecht 0:563b70517320 773 wait(.1);
jengbrecht 0:563b70517320 774 timer = timer + 100;
jengbrecht 0:563b70517320 775 previous = available;
jengbrecht 38:4739e039421a 776 available = io->readable();
sgodinez 8:3fe68d6130a8 777
sgodinez 19:38794784e009 778 int size = io->read(tmp,255); //1 less than allocated
sgodinez 8:3fe68d6130a8 779 if(size > 0) {
sgodinez 8:3fe68d6130a8 780 result.append(tmp, size);
sgodinez 8:3fe68d6130a8 781 }
sgodinez 13:0af863114629 782
sgodinez 13:0af863114629 783 if(!started) {
sgodinez 13:0af863114629 784 //In Echo Mode (Command will have echo'd + 2 characters for \r\n)
sgodinez 13:0af863114629 785 if(result.size() > command.size() + 2) {
sgodinez 13:0af863114629 786 started = true;
sgodinez 13:0af863114629 787 }
sgodinez 13:0af863114629 788 } else {
sgodinez 13:0af863114629 789 done = (available == previous);
sgodinez 13:0af863114629 790 }
sgodinez 13:0af863114629 791 if(timer >= timeoutMillis) {
sgodinez 17:2d7c4ea7491b 792 printf("[WARNING] sendCommand timed out after %d milliseconds\r\n", timeoutMillis);
sgodinez 13:0af863114629 793 done = true;
sgodinez 13:0af863114629 794 }
sgodinez 13:0af863114629 795 } while (!done);
sgodinez 8:3fe68d6130a8 796
sgodinez 8:3fe68d6130a8 797 return result;
jengbrecht 0:563b70517320 798 }
jengbrecht 0:563b70517320 799
jengbrecht 0:563b70517320 800 #endif /* CELLULAR_CPP */