Multi-Hackers / SocketModem

Dependents:   M2X_dev axeda_wrapper_dev MTS_M2x_Example1 MTS_Cellular_Connect_Example ... more

Committer:
sgodinez
Date:
Mon Dec 30 23:26:31 2013 +0000
Revision:
101:27bb34e23304
Parent:
96:27bdf4aa3a31
Child:
110:8f3149c99112
Fixed issue where rxClear() did not update RTS.

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