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 20 21:11:56 2013 +0000
Revision:
59:7777b3ed5a4c
Parent:
57:88b07490d7e8
Parent:
58:408f67fa292f
Child:
67:1003b410f781
Merged!

Who changed what in which revision?

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