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:
Thu Dec 19 22:18:23 2013 +0000
Revision:
48:dad1e780cb1c
Parent:
43:3cacf019ed7d
Child:
53:27c9622de0f9
Fixed DLE mode parameters

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