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:
jengbrecht
Date:
Thu Dec 19 16:54:09 2013 +0000
Revision:
38:4739e039421a
Parent:
37:61373f492403
Child:
40:14342c4de476
Sorry... Fixed issue in Cellular.cpp where rxAvailable was still being used, replaced with readable method call.

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