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 20 20:29:10 2013 +0000
Revision:
57:88b07490d7e8
Parent:
56:e5e5351f14b3
Parent:
55:56d9a9d98079
Child:
59:7777b3ed5a4c
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 17:2d7c4ea7491b 307 if(!socketOpened) {
sgodinez 17:2d7c4ea7491b 308 printf("[ERROR] Socket is not open\r\n");
sgodinez 17:2d7c4ea7491b 309 return -1;
sgodinez 17:2d7c4ea7491b 310 }
sgodinez 17:2d7c4ea7491b 311 int bytesRead = 0;
sgodinez 32:629e6b1c8e22 312
sgodinez 17:2d7c4ea7491b 313 if(timeout >= 0) {
sgodinez 17:2d7c4ea7491b 314 Timer tmr;
sgodinez 17:2d7c4ea7491b 315 tmr.start();
sgodinez 35:f28acb1be52d 316 do {
sgodinez 32:629e6b1c8e22 317 int available = io->readable();
sgodinez 32:629e6b1c8e22 318 if (available > 0) {
sgodinez 32:629e6b1c8e22 319 int size = MIN(available, max - bytesRead);
sgodinez 32:629e6b1c8e22 320 bytesRead += io->read(&data[bytesRead], size);
sgodinez 17:2d7c4ea7491b 321 } else {
sgodinez 17:2d7c4ea7491b 322 wait(0.05);
sgodinez 17:2d7c4ea7491b 323 }
sgodinez 35:f28acb1be52d 324 } while (tmr.read_ms() <= timeout && bytesRead < max);
sgodinez 17:2d7c4ea7491b 325 } else {
sgodinez 19:38794784e009 326 bytesRead = io->read(data, max);
sgodinez 17:2d7c4ea7491b 327 }
sgodinez 17:2d7c4ea7491b 328
sgodinez 32:629e6b1c8e22 329 if(bytesRead > 0 && socketCloseable) {
sgodinez 32:629e6b1c8e22 330 //Remove escape characters
sgodinez 32:629e6b1c8e22 331 int index = 0;
sgodinez 32:629e6b1c8e22 332 bool escapeFlag = false;
sgodinez 32:629e6b1c8e22 333 for(int i = 0; i < bytesRead; i++) {
sgodinez 32:629e6b1c8e22 334 if(data[i] == DLE || data[i] == ETX) {
sgodinez 32:629e6b1c8e22 335 if(escapeFlag == true) {
sgodinez 32:629e6b1c8e22 336 //This character has been escaped
sgodinez 32:629e6b1c8e22 337 escapeFlag = false;
sgodinez 32:629e6b1c8e22 338 } else if(data[bytesRead] == DLE) {
sgodinez 32:629e6b1c8e22 339 //Found escape character
sgodinez 32:629e6b1c8e22 340 escapeFlag = true;
sgodinez 32:629e6b1c8e22 341 continue;
sgodinez 32:629e6b1c8e22 342 } else {
sgodinez 32:629e6b1c8e22 343 //ETX sent without escape -> Socket closed
sgodinez 32:629e6b1c8e22 344 printf("[INFO] Read ETX character without DLE escape. Socket closed\r\n");
sgodinez 32:629e6b1c8e22 345 socketOpened = false;
sgodinez 32:629e6b1c8e22 346 continue;
sgodinez 32:629e6b1c8e22 347 }
sgodinez 32:629e6b1c8e22 348 }
sgodinez 32:629e6b1c8e22 349
sgodinez 32:629e6b1c8e22 350 if(index != i) {
sgodinez 32:629e6b1c8e22 351 data[index] = data[i];
sgodinez 32:629e6b1c8e22 352 }
sgodinez 32:629e6b1c8e22 353 index++;
sgodinez 32:629e6b1c8e22 354 }
sgodinez 32:629e6b1c8e22 355 bytesRead = index;
sgodinez 32:629e6b1c8e22 356 }
sgodinez 32:629e6b1c8e22 357
sgodinez 32:629e6b1c8e22 358 printf("[DEBUG] Scanning received data for socket closed message\r\n");
sgodinez 32:629e6b1c8e22 359 //Scan for socket closed message
sgodinez 32:629e6b1c8e22 360 for(size_t i = 0; i < bytesRead; i++) {
sgodinez 32:629e6b1c8e22 361 if(data[i] == 'O') {
sgodinez 32:629e6b1c8e22 362 if(strstr(&data[i], "Ok_Info_SocketClosed")) {
sgodinez 32:629e6b1c8e22 363 printf("[INFO] Found socket closed message. Socket closed\r\n");
sgodinez 32:629e6b1c8e22 364 //Close socket and Cut Off End of Message
sgodinez 32:629e6b1c8e22 365 socketOpened = false;
sgodinez 32:629e6b1c8e22 366 data[i] = '\0';
sgodinez 32:629e6b1c8e22 367 bytesRead = i;
sgodinez 32:629e6b1c8e22 368 break;
sgodinez 32:629e6b1c8e22 369 }
sgodinez 32:629e6b1c8e22 370 }
sgodinez 32:629e6b1c8e22 371 }
sgodinez 17:2d7c4ea7491b 372 return bytesRead;
sgodinez 11:134435d8a2d5 373 }
sgodinez 11:134435d8a2d5 374
sgodinez 41:81d035fb0b6a 375 int Cellular::write(const char* data, int length, int timeout) {
sgodinez 19:38794784e009 376 if(io == NULL) {
sgodinez 19:38794784e009 377 printf("[ERROR] MTSBufferedIO not set\r\n");
sgodinez 19:38794784e009 378 return -1;
sgodinez 19:38794784e009 379 }
sgodinez 19:38794784e009 380
sgodinez 17:2d7c4ea7491b 381 if(!socketOpened) {
sgodinez 17:2d7c4ea7491b 382 printf("[ERROR] Socket is not open\r\n");
sgodinez 17:2d7c4ea7491b 383 return -1;
sgodinez 17:2d7c4ea7491b 384 }
sgodinez 17:2d7c4ea7491b 385
sgodinez 35:f28acb1be52d 386 //In order to avoid allocating another buffer, capture indices of
sgodinez 35:f28acb1be52d 387 //characters to escape during write
sgodinez 35:f28acb1be52d 388 int specialWritten = 0;
sgodinez 35:f28acb1be52d 389 std::vector<int> vSpecial;
sgodinez 35:f28acb1be52d 390 if(socketCloseable) {
sgodinez 35:f28acb1be52d 391 for(int i = 0; i < length; i++) {
sgodinez 35:f28acb1be52d 392 if(data[i] == ETX || data[i] == DLE) {
sgodinez 35:f28acb1be52d 393 //Push back index of special characters
sgodinez 35:f28acb1be52d 394 vSpecial.push_back(i);
sgodinez 35:f28acb1be52d 395 }
sgodinez 35:f28acb1be52d 396 }
sgodinez 35:f28acb1be52d 397 }
sgodinez 35:f28acb1be52d 398
sgodinez 17:2d7c4ea7491b 399 int bytesWritten = 0;
sgodinez 17:2d7c4ea7491b 400 if(timeout >= 0) {
sgodinez 17:2d7c4ea7491b 401 Timer tmr;
sgodinez 17:2d7c4ea7491b 402 tmr.start();
sgodinez 35:f28acb1be52d 403 do {
sgodinez 35:f28acb1be52d 404 int capacity = io->writeable();
sgodinez 35:f28acb1be52d 405 if (capacity > 0) {
sgodinez 35:f28acb1be52d 406 if(specialWritten < vSpecial.size()) {
sgodinez 35:f28acb1be52d 407 //Check if current index is at a special character
sgodinez 35:f28acb1be52d 408 if(bytesWritten == vSpecial[specialWritten]) {
sgodinez 35:f28acb1be52d 409 if(capacity < 2) {
sgodinez 35:f28acb1be52d 410 //Requires at least two bytes of space
sgodinez 35:f28acb1be52d 411 wait(0.05);
sgodinez 35:f28acb1be52d 412 continue;
sgodinez 35:f28acb1be52d 413 }
sgodinez 35:f28acb1be52d 414 //Ready to write special character
sgodinez 35:f28acb1be52d 415 if(io->write(DLE)) {
sgodinez 35:f28acb1be52d 416 specialWritten++;
sgodinez 35:f28acb1be52d 417 if(io->write(data[bytesWritten])) {
sgodinez 35:f28acb1be52d 418 bytesWritten++;
sgodinez 35:f28acb1be52d 419 }
sgodinez 35:f28acb1be52d 420 } else {
sgodinez 35:f28acb1be52d 421 //Unable to write escape character, try again next round
sgodinez 35:f28acb1be52d 422 wait(0.05);
sgodinez 35:f28acb1be52d 423 }
sgodinez 35:f28acb1be52d 424 } else {
sgodinez 35:f28acb1be52d 425 //We want to write all the way up to the next special character
sgodinez 35:f28acb1be52d 426 int relativeIndex = vSpecial[specialWritten] - bytesWritten;
sgodinez 35:f28acb1be52d 427 int size = MIN(capacity, relativeIndex);
sgodinez 35:f28acb1be52d 428 bytesWritten += io->write(&data[bytesWritten], size);
sgodinez 35:f28acb1be52d 429 }
sgodinez 35:f28acb1be52d 430 } else {
sgodinez 35:f28acb1be52d 431 int size = MIN(capacity, length - bytesWritten);
sgodinez 35:f28acb1be52d 432 bytesWritten += io->write(&data[bytesWritten], size);
sgodinez 17:2d7c4ea7491b 433 }
sgodinez 17:2d7c4ea7491b 434 } else {
sgodinez 35:f28acb1be52d 435 wait(0.05);
sgodinez 35:f28acb1be52d 436 }
sgodinez 35:f28acb1be52d 437 } while (tmr.read_ms() <= timeout && bytesWritten < length);
sgodinez 35:f28acb1be52d 438 } else {
sgodinez 35:f28acb1be52d 439 for(int i = 0; i < vSpecial.size(); i++) {
sgodinez 35:f28acb1be52d 440 //Write up to the special character, then write the special character
sgodinez 35:f28acb1be52d 441 int size = vSpecial[i] - bytesWritten;
sgodinez 35:f28acb1be52d 442 int currentWritten = io->write(&data[bytesWritten], size);
sgodinez 35:f28acb1be52d 443 bytesWritten += currentWritten;
sgodinez 35:f28acb1be52d 444 if(currentWritten != size) {
sgodinez 35:f28acb1be52d 445 //Failed to write up to the special character.
sgodinez 35:f28acb1be52d 446 return bytesWritten;
sgodinez 35:f28acb1be52d 447 }
sgodinez 35:f28acb1be52d 448 if(io->write(DLE) && io->write(data[bytesWritten])) {
sgodinez 35:f28acb1be52d 449 bytesWritten++;
sgodinez 35:f28acb1be52d 450 } else {
sgodinez 35:f28acb1be52d 451 //Failed to write the special character.
sgodinez 35:f28acb1be52d 452 return bytesWritten;
sgodinez 17:2d7c4ea7491b 453 }
sgodinez 17:2d7c4ea7491b 454 }
sgodinez 35:f28acb1be52d 455
sgodinez 35:f28acb1be52d 456 bytesWritten = io->write(&data[bytesWritten], length - bytesWritten);
sgodinez 17:2d7c4ea7491b 457 }
sgodinez 17:2d7c4ea7491b 458
sgodinez 17:2d7c4ea7491b 459 return bytesWritten;
sgodinez 11:134435d8a2d5 460 }
sgodinez 11:134435d8a2d5 461
sgodinez 11:134435d8a2d5 462 unsigned int Cellular::readable() {
sgodinez 19:38794784e009 463 if(io == NULL) {
sgodinez 19:38794784e009 464 printf("[ERROR] MTSBufferedIO not set\r\n");
sgodinez 19:38794784e009 465 return 0;
sgodinez 19:38794784e009 466 }
sgodinez 17:2d7c4ea7491b 467 if(!socketOpened) {
sgodinez 17:2d7c4ea7491b 468 printf("[ERROR] Socket is not open\r\n");
sgodinez 17:2d7c4ea7491b 469 return 0;
sgodinez 17:2d7c4ea7491b 470 }
sgodinez 19:38794784e009 471 return io->readable();
sgodinez 11:134435d8a2d5 472 }
sgodinez 11:134435d8a2d5 473
sgodinez 11:134435d8a2d5 474 unsigned int Cellular::writeable() {
sgodinez 19:38794784e009 475 if(io == NULL) {
sgodinez 19:38794784e009 476 printf("[ERROR] MTSBufferedIO not set\r\n");
sgodinez 19:38794784e009 477 return 0;
sgodinez 19:38794784e009 478 }
sgodinez 17:2d7c4ea7491b 479 if(!socketOpened) {
sgodinez 17:2d7c4ea7491b 480 printf("[ERROR] Socket is not open\r\n");
sgodinez 17:2d7c4ea7491b 481 return 0;
sgodinez 17:2d7c4ea7491b 482 }
sgodinez 17:2d7c4ea7491b 483
sgodinez 19:38794784e009 484 return io->writeable();
sgodinez 11:134435d8a2d5 485 }
sgodinez 11:134435d8a2d5 486
sgodinez 11:134435d8a2d5 487 void Cellular::reset() {
mfiore 29:7408b1bdad37 488 disconnect();
mfiore 29:7408b1bdad37 489 Code code = sendBasicCommand("AT#RESET=0", 10000);
mfiore 39:6e94520a3217 490 if(code != CELL_OK) {
mfiore 29:7408b1bdad37 491 printf("[ERROR] Socket Modem did not accept RESET command\n\r");
mfiore 29:7408b1bdad37 492 } else {
mfiore 29:7408b1bdad37 493 printf("[WARNING] Socket Modem is resetting, allow 30 seconds for it to come back\n\r");
mfiore 29:7408b1bdad37 494 }
sgodinez 11:134435d8a2d5 495 }
sgodinez 11:134435d8a2d5 496
sgodinez 11:134435d8a2d5 497 Cellular::Code Cellular::test()
jengbrecht 0:563b70517320 498 {
sgodinez 11:134435d8a2d5 499 Code code = sendBasicCommand("AT", 1000);
sgodinez 11:134435d8a2d5 500
mfiore 39:6e94520a3217 501 if(code != CELL_OK) {
sgodinez 11:134435d8a2d5 502 printf("[Error] Failed basic AT command");
sgodinez 11:134435d8a2d5 503 return code;
sgodinez 11:134435d8a2d5 504 }
sgodinez 11:134435d8a2d5 505
sgodinez 11:134435d8a2d5 506 //AT#VSTATE != "CHECKING"
sgodinez 11:134435d8a2d5 507
sgodinez 11:134435d8a2d5 508 //AT#GPRSMODE ==
mfiore 39:6e94520a3217 509 return CELL_OK;
jengbrecht 0:563b70517320 510 }
jengbrecht 0:563b70517320 511
mfiore 29:7408b1bdad37 512 Cellular::Code Cellular::echo(bool state)
jengbrecht 0:563b70517320 513 {
sgodinez 13:0af863114629 514 Code code;
jengbrecht 0:563b70517320 515 if (state) {
sgodinez 13:0af863114629 516 code = sendBasicCommand("ATE0", 1000);
mfiore 39:6e94520a3217 517 echoMode = (code == CELL_OK) ? false : echoMode;
jengbrecht 0:563b70517320 518 } else {
sgodinez 13:0af863114629 519 code = sendBasicCommand("ATE1", 1000);
mfiore 39:6e94520a3217 520 echoMode = (code == CELL_OK) ? true : echoMode;
jengbrecht 0:563b70517320 521 }
sgodinez 13:0af863114629 522 return code;
jengbrecht 0:563b70517320 523 }
jengbrecht 0:563b70517320 524
jengbrecht 0:563b70517320 525 int Cellular::getSignalStrength()
jengbrecht 0:563b70517320 526 {
jengbrecht 0:563b70517320 527 string response = sendCommand("AT+CSQ", 1000);
jengbrecht 0:563b70517320 528 if (response.find("OK") == string::npos) {
jengbrecht 0:563b70517320 529 return -1;
jengbrecht 0:563b70517320 530 }
jengbrecht 0:563b70517320 531 int start = response.find(':');
jengbrecht 0:563b70517320 532 int stop = response.find(',', start);
jengbrecht 0:563b70517320 533 string signal = response.substr(start + 2, stop - start - 2);
jengbrecht 0:563b70517320 534 int value;
jengbrecht 0:563b70517320 535 sscanf(signal.c_str(), "%d", &value);
jengbrecht 0:563b70517320 536 return value;
jengbrecht 0:563b70517320 537 }
jengbrecht 0:563b70517320 538
sgodinez 5:93e889a5abc6 539 std::string Cellular::getPhoneNumber() {
sgodinez 5:93e889a5abc6 540 return "unknown";
sgodinez 5:93e889a5abc6 541 }
sgodinez 5:93e889a5abc6 542
jengbrecht 0:563b70517320 543 Cellular::Registration Cellular::getRegistration()
jengbrecht 0:563b70517320 544 {
jengbrecht 0:563b70517320 545 string response = sendCommand("AT+CREG?", 1000);
jengbrecht 0:563b70517320 546 if (response.find("OK") == string::npos) {
jengbrecht 0:563b70517320 547 return UNKNOWN;
jengbrecht 0:563b70517320 548 }
jengbrecht 0:563b70517320 549 int start = response.find(',');
jengbrecht 0:563b70517320 550 int stop = response.find(' ', start);
jengbrecht 0:563b70517320 551 string regStat = response.substr(start + 1, stop - start - 1);
jengbrecht 0:563b70517320 552 int value;
jengbrecht 0:563b70517320 553 sscanf(regStat.c_str(), "%d", &value);
jengbrecht 0:563b70517320 554 switch (value) {
jengbrecht 0:563b70517320 555 case 0:
jengbrecht 0:563b70517320 556 return NOT_REGISTERED;
jengbrecht 0:563b70517320 557 case 1:
jengbrecht 0:563b70517320 558 return REGISTERED;
jengbrecht 0:563b70517320 559 case 2:
jengbrecht 0:563b70517320 560 return SEARCHING;
jengbrecht 0:563b70517320 561 case 3:
jengbrecht 0:563b70517320 562 return DENIED;
jengbrecht 0:563b70517320 563 case 4:
jengbrecht 0:563b70517320 564 return UNKNOWN;
jengbrecht 0:563b70517320 565 case 5:
jengbrecht 0:563b70517320 566 return ROAMING;
jengbrecht 0:563b70517320 567 }
sgodinez 4:6561c9128c6f 568 return UNKNOWN;
jengbrecht 0:563b70517320 569 }
jengbrecht 0:563b70517320 570
jengbrecht 0:563b70517320 571 Cellular::Code Cellular::sendBasicCommand(string command, int timeoutMillis, ESC_CHAR esc)
jengbrecht 0:563b70517320 572 {
sgodinez 17:2d7c4ea7491b 573 if(socketOpened) {
sgodinez 17:2d7c4ea7491b 574 printf("[ERROR] socket is open. Can not send AT commands\r\n");
mfiore 39:6e94520a3217 575 return CELL_ERROR;
sgodinez 17:2d7c4ea7491b 576 }
sgodinez 17:2d7c4ea7491b 577
jengbrecht 0:563b70517320 578 string response = sendCommand(command, timeoutMillis, esc);
jengbrecht 0:563b70517320 579 if (response.size() == 0) {
mfiore 39:6e94520a3217 580 return CELL_NO_RESPONSE;
jengbrecht 0:563b70517320 581 } else if (response.find("OK") != string::npos) {
mfiore 39:6e94520a3217 582 return CELL_OK;
jengbrecht 0:563b70517320 583 } else if (response.find("ERROR") != string::npos) {
mfiore 39:6e94520a3217 584 return CELL_ERROR;
jengbrecht 0:563b70517320 585 } else {
mfiore 39:6e94520a3217 586 return CELL_FAILURE;
jengbrecht 0:563b70517320 587 }
jengbrecht 0:563b70517320 588 }
jengbrecht 0:563b70517320 589
sgodinez 11:134435d8a2d5 590 Cellular::Code Cellular::setApn(const std::string& apn) {
sgodinez 11:134435d8a2d5 591 Code code = sendBasicCommand("AT#APNSERV=\"" + apn + "\"", 1000);
mfiore 39:6e94520a3217 592 if (code != CELL_OK) {
sgodinez 11:134435d8a2d5 593 return code;
sgodinez 11:134435d8a2d5 594 }
sgodinez 11:134435d8a2d5 595 this->apn = apn;
sgodinez 11:134435d8a2d5 596 return code;
sgodinez 11:134435d8a2d5 597 }
sgodinez 11:134435d8a2d5 598
sgodinez 43:3cacf019ed7d 599
sgodinez 41:81d035fb0b6a 600 Cellular::Code Cellular::setDns(const std::string& primary, const std::string& secondary) {
sgodinez 41:81d035fb0b6a 601 return sendBasicCommand("AT#DNS=1," + primary + "," + secondary, 1000);
sgodinez 11:134435d8a2d5 602 }
sgodinez 11:134435d8a2d5 603
jengbrecht 23:bc6f98a1eb22 604 bool Cellular::ping(const std::string& address) {
jengbrecht 23:bc6f98a1eb22 605 char buffer[256] = {0};
jengbrecht 23:bc6f98a1eb22 606 Code code;
jengbrecht 23:bc6f98a1eb22 607
jengbrecht 23:bc6f98a1eb22 608 code = sendBasicCommand("AT#PINGREMOTE=\"" + address + "\"", 1000);
mfiore 39:6e94520a3217 609 if (code != CELL_OK) {
jengbrecht 23:bc6f98a1eb22 610 return false;
jengbrecht 23:bc6f98a1eb22 611 }
jengbrecht 23:bc6f98a1eb22 612
jengbrecht 23:bc6f98a1eb22 613 sprintf(buffer, "AT#PINGNUM=%d", 1);
jengbrecht 23:bc6f98a1eb22 614 code = sendBasicCommand(buffer , 1000);
mfiore 39:6e94520a3217 615 if (code != CELL_OK) {
jengbrecht 23:bc6f98a1eb22 616 return false;
jengbrecht 23:bc6f98a1eb22 617 }
jengbrecht 23:bc6f98a1eb22 618
jengbrecht 23:bc6f98a1eb22 619 sprintf(buffer, "AT#PINGDELAY=%d", PINGDELAY);
jengbrecht 23:bc6f98a1eb22 620 code = sendBasicCommand(buffer , 1000);
mfiore 39:6e94520a3217 621 if (code != CELL_OK) {
jengbrecht 23:bc6f98a1eb22 622 return false;
jengbrecht 23:bc6f98a1eb22 623 }
jengbrecht 23:bc6f98a1eb22 624
jengbrecht 23:bc6f98a1eb22 625 std::string response;
jengbrecht 23:bc6f98a1eb22 626 for (int i = 0; i < PINGNUM; i++) {
jengbrecht 23:bc6f98a1eb22 627 response = sendCommand("AT#PING", PINGDELAY * 1000);
jengbrecht 23:bc6f98a1eb22 628 if (response.find("alive") != std::string::npos) {
jengbrecht 23:bc6f98a1eb22 629 return true;
jengbrecht 23:bc6f98a1eb22 630 }
jengbrecht 23:bc6f98a1eb22 631 }
jengbrecht 23:bc6f98a1eb22 632 return false;
jengbrecht 23:bc6f98a1eb22 633 }
jengbrecht 23:bc6f98a1eb22 634
sgodinez 17:2d7c4ea7491b 635 Cellular::Code Cellular::setSocketCloseable(bool enabled) {
sgodinez 17:2d7c4ea7491b 636 if(socketCloseable == enabled) {
mfiore 39:6e94520a3217 637 return CELL_OK;
sgodinez 17:2d7c4ea7491b 638 }
sgodinez 17:2d7c4ea7491b 639
sgodinez 17:2d7c4ea7491b 640 if(socketOpened) {
sgodinez 17:2d7c4ea7491b 641 printf("[ERROR] socket is already opened. Can not set closeable\r\n");
mfiore 39:6e94520a3217 642 return CELL_ERROR;
sgodinez 17:2d7c4ea7491b 643 }
sgodinez 17:2d7c4ea7491b 644
sgodinez 17:2d7c4ea7491b 645 socketCloseable = enabled;
sgodinez 17:2d7c4ea7491b 646
mfiore 39:6e94520a3217 647 return CELL_OK;
sgodinez 17:2d7c4ea7491b 648 }
sgodinez 17:2d7c4ea7491b 649
sgodinez 4:6561c9128c6f 650 Cellular::Code Cellular::sendSMS(const Sms& sms) {
sgodinez 4:6561c9128c6f 651 return sendSMS(sms.phoneNumber, sms.message);
sgodinez 4:6561c9128c6f 652 }
sgodinez 4:6561c9128c6f 653
sgodinez 4:6561c9128c6f 654 Cellular::Code Cellular::sendSMS(const std::string& phoneNumber, const std::string& message)
sgodinez 17:2d7c4ea7491b 655 {
jengbrecht 0:563b70517320 656 Code code = sendBasicCommand("AT+CMGF=1", 1000);
mfiore 39:6e94520a3217 657 if (code != CELL_OK) {
jengbrecht 0:563b70517320 658 return code;
jengbrecht 0:563b70517320 659 }
jengbrecht 0:563b70517320 660 string cmd = "AT+CMGS=\"+";
jengbrecht 0:563b70517320 661 cmd.append(phoneNumber);
jengbrecht 0:563b70517320 662 cmd.append("\"");
jengbrecht 0:563b70517320 663 string response1 = sendCommand(cmd, 1000);
jengbrecht 0:563b70517320 664 if (response1.find('>') == string::npos) {
mfiore 39:6e94520a3217 665 return CELL_NO_RESPONSE;
jengbrecht 0:563b70517320 666 }
jengbrecht 0:563b70517320 667 wait(.2);
jengbrecht 0:563b70517320 668 string response2 = sendCommand(message, 4000, CTRL_Z);
sgodinez 17:2d7c4ea7491b 669 printf("SMS Response: %s\r\n", response2.c_str());
jengbrecht 0:563b70517320 670 if (response2.find("+CMGS:") == string::npos) {
mfiore 39:6e94520a3217 671 return CELL_FAILURE;
jengbrecht 0:563b70517320 672 }
mfiore 39:6e94520a3217 673 return CELL_OK;
jengbrecht 0:563b70517320 674 }
jengbrecht 0:563b70517320 675
sgodinez 4:6561c9128c6f 676 std::vector<Cellular::Sms> Cellular::getReceivedSms() {
sgodinez 9:5b12c5a8dde4 677 int smsNumber = 0;
sgodinez 4:6561c9128c6f 678 std::vector<Sms> vSms;
sgodinez 4:6561c9128c6f 679 std::string received = sendCommand("AT+CMGL=\"ALL\"", 4000);
sgodinez 5:93e889a5abc6 680 size_t pos = received.find("+CMGL: ");
sgodinez 4:6561c9128c6f 681
sgodinez 5:93e889a5abc6 682 while (pos != std::string::npos) {
sgodinez 4:6561c9128c6f 683 Cellular::Sms sms;
sgodinez 4:6561c9128c6f 684 std::string line(Text::getLine(received, pos, pos));
sgodinez 17:2d7c4ea7491b 685 //printf("[DEBUG] Top of SMS Parse Loop. LINE[%s]\r\n", line.c_str());
sgodinez 9:5b12c5a8dde4 686 if(line.find("+CMGL: ") == std::string::npos) {
sgodinez 4:6561c9128c6f 687 continue;
sgodinez 4:6561c9128c6f 688 }
sgodinez 4:6561c9128c6f 689
sgodinez 4:6561c9128c6f 690 //Start of SMS message
sgodinez 4:6561c9128c6f 691 std::vector<std::string> vSmsParts = Text::split(line, ',');
sgodinez 4:6561c9128c6f 692 if(vSmsParts.size() != 6) {
sgodinez 17:2d7c4ea7491b 693 printf("[WARNING] Expected 6 commas. SMS[%d] DATA[%s]. Continuing ...\r\n", smsNumber, line.c_str());
sgodinez 4:6561c9128c6f 694 continue;
sgodinez 4:6561c9128c6f 695 }
sgodinez 4:6561c9128c6f 696
sgodinez 4:6561c9128c6f 697 sms.phoneNumber = vSmsParts[2];
sgodinez 4:6561c9128c6f 698 sms.timestamp = vSmsParts[4] + ", " + vSmsParts[5];
sgodinez 4:6561c9128c6f 699
sgodinez 8:3fe68d6130a8 700 if(pos == std::string::npos) {
sgodinez 17:2d7c4ea7491b 701 printf("[WARNING] Expected SMS body. SMS[%d]. Leaving ...\r\n", smsNumber);
sgodinez 8:3fe68d6130a8 702 break;
sgodinez 8:3fe68d6130a8 703 }
sgodinez 9:5b12c5a8dde4 704 //Check for the start of the next SMS message
sgodinez 9:5b12c5a8dde4 705 size_t bodyEnd = received.find("\r\n+CMGL: ", pos);
sgodinez 8:3fe68d6130a8 706 if(bodyEnd == std::string::npos) {
sgodinez 17:2d7c4ea7491b 707 //printf("[DEBUG] Parsing Last SMS. SMS[%d]\r\n", smsNumber);
sgodinez 9:5b12c5a8dde4 708 //This must be the last SMS message
sgodinez 9:5b12c5a8dde4 709 bodyEnd = received.find("\r\n\r\nOK", pos);
sgodinez 8:3fe68d6130a8 710 }
sgodinez 9:5b12c5a8dde4 711
sgodinez 9:5b12c5a8dde4 712 //Safety check that we found the boundary of this current SMS message
sgodinez 9:5b12c5a8dde4 713 if(bodyEnd != std::string::npos) {
sgodinez 9:5b12c5a8dde4 714 sms.message = received.substr(pos, bodyEnd - pos);
sgodinez 9:5b12c5a8dde4 715 } else {
sgodinez 8:3fe68d6130a8 716 sms.message = received.substr(pos);
sgodinez 17:2d7c4ea7491b 717 printf("[WARNING] Expected to find end of SMS list. SMS[%d] DATA[%s].\r\n", smsNumber, sms.message.c_str());
sgodinez 8:3fe68d6130a8 718 }
sgodinez 5:93e889a5abc6 719 vSms.push_back(sms);
sgodinez 4:6561c9128c6f 720 pos = bodyEnd;
sgodinez 17:2d7c4ea7491b 721 //printf("[DEBUG] Parsed SMS[%d]. Starting Next at position [%d]\r\n", smsNumber, pos);
sgodinez 9:5b12c5a8dde4 722 smsNumber++;
sgodinez 4:6561c9128c6f 723 }
sgodinez 17:2d7c4ea7491b 724 printf("Received %d SMS\r\n", smsNumber);
sgodinez 4:6561c9128c6f 725 return vSms;
sgodinez 4:6561c9128c6f 726 }
sgodinez 4:6561c9128c6f 727
sgodinez 4:6561c9128c6f 728 Cellular::Code Cellular::deleteOnlyReceivedReadSms() {
sgodinez 4:6561c9128c6f 729 return sendBasicCommand("AT+CMGD=1,1", 1000);
sgodinez 4:6561c9128c6f 730 }
sgodinez 4:6561c9128c6f 731
sgodinez 4:6561c9128c6f 732 Cellular::Code Cellular::deleteAllReceivedSms() {
sgodinez 4:6561c9128c6f 733 return sendBasicCommand("AT+CMGD=1,4", 1000);
sgodinez 4:6561c9128c6f 734 }
sgodinez 4:6561c9128c6f 735
sgodinez 4:6561c9128c6f 736
jengbrecht 0:563b70517320 737 string Cellular::sendCommand(string command, int timeoutMillis, ESC_CHAR esc)
jengbrecht 0:563b70517320 738 {
sgodinez 19:38794784e009 739 if(io == NULL) {
sgodinez 19:38794784e009 740 printf("[ERROR] MTSBufferedIO not set\r\n");
sgodinez 19:38794784e009 741 return "";
sgodinez 19:38794784e009 742 }
sgodinez 17:2d7c4ea7491b 743 if(socketOpened) {
sgodinez 17:2d7c4ea7491b 744 printf("[ERROR] socket is open. Can not send AT commands\r\n");
sgodinez 17:2d7c4ea7491b 745 return "";
sgodinez 17:2d7c4ea7491b 746 }
sgodinez 17:2d7c4ea7491b 747
jengbrecht 0:563b70517320 748 int size = command.size() + 1;
jengbrecht 0:563b70517320 749 char cmd[size];
jengbrecht 0:563b70517320 750 strcpy(cmd, command.c_str());
jengbrecht 0:563b70517320 751 if (esc == CR) {
jengbrecht 0:563b70517320 752 cmd[size -1] = '\r';
jengbrecht 0:563b70517320 753 } else if (esc == CTRL_Z) {
jengbrecht 0:563b70517320 754 cmd[size -1] = 0x1A;
sgodinez 13:0af863114629 755 } else if(esc == NONE) {
sgodinez 13:0af863114629 756 cmd[size -1] = '\0';
jengbrecht 0:563b70517320 757 }
jengbrecht 0:563b70517320 758
sgodinez 19:38794784e009 759 io->rxClear();
sgodinez 19:38794784e009 760 io->txClear();
sgodinez 8:3fe68d6130a8 761 std::string result;
sgodinez 19:38794784e009 762 int status = io->write(cmd, size);
jengbrecht 36:bb6b293c7495 763 int available = io->readable();
jengbrecht 0:563b70517320 764 int previous = -1;
jengbrecht 0:563b70517320 765 int timer = 0;
sgodinez 8:3fe68d6130a8 766 char tmp[256];
sgodinez 8:3fe68d6130a8 767 tmp[255] = 0;
sgodinez 13:0af863114629 768 bool started = !echoMode;
sgodinez 13:0af863114629 769 bool done = false;
sgodinez 8:3fe68d6130a8 770 do {
jengbrecht 0:563b70517320 771 wait(.1);
jengbrecht 0:563b70517320 772 timer = timer + 100;
jengbrecht 0:563b70517320 773 previous = available;
jengbrecht 38:4739e039421a 774 available = io->readable();
sgodinez 8:3fe68d6130a8 775
sgodinez 19:38794784e009 776 int size = io->read(tmp,255); //1 less than allocated
sgodinez 8:3fe68d6130a8 777 if(size > 0) {
sgodinez 8:3fe68d6130a8 778 result.append(tmp, size);
sgodinez 8:3fe68d6130a8 779 }
sgodinez 13:0af863114629 780
sgodinez 13:0af863114629 781 if(!started) {
sgodinez 13:0af863114629 782 //In Echo Mode (Command will have echo'd + 2 characters for \r\n)
sgodinez 13:0af863114629 783 if(result.size() > command.size() + 2) {
sgodinez 13:0af863114629 784 started = true;
sgodinez 13:0af863114629 785 }
sgodinez 13:0af863114629 786 } else {
sgodinez 13:0af863114629 787 done = (available == previous);
sgodinez 13:0af863114629 788 }
sgodinez 13:0af863114629 789 if(timer >= timeoutMillis) {
sgodinez 17:2d7c4ea7491b 790 printf("[WARNING] sendCommand timed out after %d milliseconds\r\n", timeoutMillis);
sgodinez 13:0af863114629 791 done = true;
sgodinez 13:0af863114629 792 }
sgodinez 13:0af863114629 793 } while (!done);
sgodinez 8:3fe68d6130a8 794
sgodinez 8:3fe68d6130a8 795 return result;
jengbrecht 0:563b70517320 796 }
jengbrecht 0:563b70517320 797
jengbrecht 56:e5e5351f14b3 798 std::string Cellular::getCodeNames(Code code)
jengbrecht 56:e5e5351f14b3 799 {
jengbrecht 56:e5e5351f14b3 800 switch(code) {
jengbrecht 56:e5e5351f14b3 801 case CELL_OK:
jengbrecht 56:e5e5351f14b3 802 return "CELL_OK";
jengbrecht 56:e5e5351f14b3 803 case CELL_ERROR:
jengbrecht 56:e5e5351f14b3 804 return "CELL_ERROR";
jengbrecht 56:e5e5351f14b3 805 case CELL_NO_RESPONSE:
jengbrecht 56:e5e5351f14b3 806 return "CELL_NO_RESPONSE";
jengbrecht 56:e5e5351f14b3 807 case CELL_FAILURE:
jengbrecht 56:e5e5351f14b3 808 return "CELL_FAILURE";
jengbrecht 56:e5e5351f14b3 809 default:
jengbrecht 56:e5e5351f14b3 810 return "UNKNOWN ENUM";
jengbrecht 56:e5e5351f14b3 811 }
jengbrecht 56:e5e5351f14b3 812 }
jengbrecht 56:e5e5351f14b3 813
jengbrecht 56:e5e5351f14b3 814 std::string Cellular::getRegistrationNames(Registration registration)
jengbrecht 56:e5e5351f14b3 815 {
jengbrecht 56:e5e5351f14b3 816 switch(registration) {
jengbrecht 56:e5e5351f14b3 817 case NOT_REGISTERED:
jengbrecht 56:e5e5351f14b3 818 return "NOT_REGISTERED";
jengbrecht 56:e5e5351f14b3 819 case REGISTERED:
jengbrecht 56:e5e5351f14b3 820 return "REGISTERED";
jengbrecht 56:e5e5351f14b3 821 case SEARCHING:
jengbrecht 56:e5e5351f14b3 822 return "SEARCHING";
jengbrecht 56:e5e5351f14b3 823 case DENIED:
jengbrecht 56:e5e5351f14b3 824 return "DENIED";
jengbrecht 56:e5e5351f14b3 825 case UNKNOWN:
jengbrecht 56:e5e5351f14b3 826 return "UNKNOWN";
jengbrecht 56:e5e5351f14b3 827 case ROAMING:
jengbrecht 56:e5e5351f14b3 828 return "ROAMING";
jengbrecht 56:e5e5351f14b3 829 default:
jengbrecht 56:e5e5351f14b3 830 return "UNKNOWN ENUM";
jengbrecht 56:e5e5351f14b3 831 }
jengbrecht 56:e5e5351f14b3 832 }
jengbrecht 56:e5e5351f14b3 833
jengbrecht 0:563b70517320 834 #endif /* CELLULAR_CPP */