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:
Thu Dec 26 16:12:49 2013 +0000
Revision:
71:82205735732b
Parent:
68:c490e4a51778
Child:
82:5aa75004e553
Child:
84:77c5ab16534d
Dropped Cellular::Code::CELL_ scope.  Changed OK to SUCCESS. Moved common constants to Var.h

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