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:
Fri Dec 27 16:47:09 2013 +0000
Revision:
87:5db6c084adc7
Parent:
82:5aa75004e553
Child:
88:a54018a0c576
Updated First example in Cellular and tested, also moved getCodeNames from Cellular to vars

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