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:
mfiore
Date:
Thu Dec 19 19:53:43 2013 +0000
Revision:
40:14342c4de476
Parent:
38:4739e039421a
Parent:
39:6e94520a3217
Child:
43:3cacf019ed7d
merge changes

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