A library for talking to Multi-Tech's Cellular SocketModem Devices.

Dependents:   M2X_dev axeda_wrapper_dev MTS_M2x_Example1 MTS_Cellular_Connect_Example ... more

Committer:
sgodinez
Date:
Fri Dec 27 20:54:26 2013 +0000
Revision:
91:9439ad14d7f0
Parent:
88:a54018a0c576
Child:
92:57d4838f9861
fixed blocking and non-blocking read/write calls.  Fixed sendCmd to allow read() to timeout.

Who changed what in which revision?

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