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:26:46 2013 +0000
Revision:
56:e5e5351f14b3
Parent:
43:3cacf019ed7d
Child:
57:88b07490d7e8
Added more documentation to the Cellular class, along with static methods for converting some enums to strings. Also, removed one of the getInstance functions and changed it to an init function.

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