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

Dependents:   M2X_dev axeda_wrapper_dev MTS_M2x_Example1 MTS_Cellular_Connect_Example ... more

Committer:
sgodinez
Date:
Fri Dec 27 15:51:19 2013 +0000
Revision:
84:77c5ab16534d
Parent:
71:82205735732b
Child:
85:b17ad6781c5b
Employed RTS threshold algorithm.  Removed header guards from cpp files.

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