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:
Tue Dec 17 18:49:06 2013 +0000
Revision:
23:bc6f98a1eb22
Parent:
19:38794784e009
Child:
27:8e6188cbcfd4
Child:
29:7408b1bdad37
Added Ping Command and some documentation to Cellular.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
sgodinez 19:38794784e009 8 Cellular* Cellular::instance = NULL;
sgodinez 19:38794784e009 9
sgodinez 19:38794784e009 10 Cellular* Cellular::getInstance() {
sgodinez 19:38794784e009 11 if(instance == NULL) {
sgodinez 19:38794784e009 12 instance = new Cellular(NULL);
sgodinez 19:38794784e009 13 }
sgodinez 19:38794784e009 14 return instance;
sgodinez 19:38794784e009 15 }
sgodinez 19:38794784e009 16
sgodinez 19:38794784e009 17
sgodinez 19:38794784e009 18 Cellular* Cellular::getInstance(MTSBufferedIO* io) {
sgodinez 19:38794784e009 19 if(instance == NULL) {
sgodinez 19:38794784e009 20 instance = new Cellular(io);
sgodinez 19:38794784e009 21 }
sgodinez 19:38794784e009 22 instance->io = io;
sgodinez 19:38794784e009 23 return instance;
sgodinez 19:38794784e009 24 }
sgodinez 19:38794784e009 25
sgodinez 19:38794784e009 26 Cellular::Cellular(MTSBufferedIO* io)
sgodinez 11:134435d8a2d5 27 : io(io)
sgodinez 13:0af863114629 28 , echoMode(true)
sgodinez 11:134435d8a2d5 29 , pppConnected(false)
sgodinez 11:134435d8a2d5 30 , mode(TCP)
sgodinez 11:134435d8a2d5 31 , socketOpened(false)
sgodinez 17:2d7c4ea7491b 32 , socketCloseable(false)
sgodinez 11:134435d8a2d5 33 , local_port(0)
sgodinez 11:134435d8a2d5 34 , host_port(0)
jengbrecht 0:563b70517320 35 {
jengbrecht 0:563b70517320 36 }
jengbrecht 0:563b70517320 37
jengbrecht 0:563b70517320 38 Cellular::~Cellular()
jengbrecht 0:563b70517320 39 {
jengbrecht 0:563b70517320 40 }
jengbrecht 0:563b70517320 41
sgodinez 11:134435d8a2d5 42 bool Cellular::connect() {
sgodinez 13:0af863114629 43 //Check if socket is open
sgodinez 13:0af863114629 44 if(socketOpened) {
sgodinez 13:0af863114629 45 return true;
sgodinez 13:0af863114629 46 }
sgodinez 13:0af863114629 47
sgodinez 11:134435d8a2d5 48 //Run Test first to validate a good state
sgodinez 13:0af863114629 49 if(isConnected()) {
sgodinez 13:0af863114629 50 return true;
sgodinez 13:0af863114629 51 }
sgodinez 13:0af863114629 52
sgodinez 11:134435d8a2d5 53 //Check RSSI: AT+CSQ
sgodinez 13:0af863114629 54 int rssi = getSignalStrength();
sgodinez 17:2d7c4ea7491b 55 printf("[DEBUG] Signal strength: %d\r\n", rssi);
sgodinez 13:0af863114629 56
sgodinez 11:134435d8a2d5 57 //Check Registration: AT+CREG? == 0,1
sgodinez 13:0af863114629 58 Registration registration = getRegistration();
sgodinez 13:0af863114629 59 if(registration != REGISTERED) {
sgodinez 17:2d7c4ea7491b 60 printf("[WARNING] Not Registered [%d]\r\n", (int)registration);
sgodinez 13:0af863114629 61 }
sgodinez 11:134435d8a2d5 62
sgodinez 11:134435d8a2d5 63 //AT#CONNECTIONSTART: Make a PPP connection
sgodinez 17:2d7c4ea7491b 64 printf("[DEBUG] Making PPP Connection Attempt. APN[%s]\r\n", apn.c_str());
sgodinez 13:0af863114629 65 std::string pppResult = sendCommand("AT#CONNECTIONSTART", 120000);
sgodinez 17:2d7c4ea7491b 66 std::vector<std::string> parts = Text::split(pppResult, "\r\n");
sgodinez 13:0af863114629 67
sgodinez 17:2d7c4ea7491b 68 //printf("[DEBUG] PPP CONNECT RESULT [%s]\r\n", pppResult.c_str());
sgodinez 17:2d7c4ea7491b 69 // for(uint32_t i = 0; i < parts.size(); i++) {
sgodinez 17:2d7c4ea7491b 70 // printf("[%d] [%s]\r\n", i, parts[i].c_str());
sgodinez 17:2d7c4ea7491b 71 // }
sgodinez 13:0af863114629 72
sgodinez 13:0af863114629 73 if(pppResult.find("Ok_Info_GprsActivation") != std::string::npos) {
sgodinez 13:0af863114629 74 if(parts.size() >= 2) {
sgodinez 13:0af863114629 75 local_address = parts[1];
sgodinez 13:0af863114629 76 }
sgodinez 17:2d7c4ea7491b 77 printf("[INFO] PPP Connection Established: IP[%s]\r\n", local_address.c_str());
sgodinez 13:0af863114629 78 pppConnected = true;
sgodinez 13:0af863114629 79
sgodinez 13:0af863114629 80 } else {
sgodinez 13:0af863114629 81 pppConnected = false;
sgodinez 13:0af863114629 82 }
sgodinez 11:134435d8a2d5 83
sgodinez 13:0af863114629 84 return pppConnected;
sgodinez 11:134435d8a2d5 85 }
sgodinez 11:134435d8a2d5 86
sgodinez 11:134435d8a2d5 87 void Cellular::disconnect() {
sgodinez 17:2d7c4ea7491b 88 //AT#CONNECTIONSTOP: Close a PPP connection
sgodinez 17:2d7c4ea7491b 89 printf("[DEBUG] Closing PPP Connection\r\n");
sgodinez 11:134435d8a2d5 90
sgodinez 17:2d7c4ea7491b 91 if(socketOpened) {
sgodinez 17:2d7c4ea7491b 92 close();
sgodinez 17:2d7c4ea7491b 93 }
sgodinez 17:2d7c4ea7491b 94
sgodinez 17:2d7c4ea7491b 95 Code code = sendBasicCommand("AT#CONNECTIONSTOP", 10000);
sgodinez 17:2d7c4ea7491b 96 if(code == OK) {
sgodinez 17:2d7c4ea7491b 97 printf("[DEBUG] Successfully closed PPP Connection\r\n");
sgodinez 17:2d7c4ea7491b 98 } else {
sgodinez 17:2d7c4ea7491b 99 printf("[ERROR] Closing PPP Connection [%d]. Continuing ...\r\n", (int)code);
sgodinez 17:2d7c4ea7491b 100 }
sgodinez 17:2d7c4ea7491b 101
sgodinez 17:2d7c4ea7491b 102 pppConnected = false;
sgodinez 11:134435d8a2d5 103 }
sgodinez 11:134435d8a2d5 104
sgodinez 11:134435d8a2d5 105 bool Cellular::isConnected() {
sgodinez 11:134435d8a2d5 106 //1) Check if APN was set
sgodinez 11:134435d8a2d5 107 if(apn.size() == 0) {
sgodinez 17:2d7c4ea7491b 108 printf("[DEBUG] APN is not set\r\n");
sgodinez 11:134435d8a2d5 109 return false;
sgodinez 11:134435d8a2d5 110 }
sgodinez 11:134435d8a2d5 111
sgodinez 11:134435d8a2d5 112 //1) Check that we do not have a live connection up
sgodinez 11:134435d8a2d5 113 if(socketOpened) {
sgodinez 17:2d7c4ea7491b 114 printf("[DEBUG] Socket is opened\r\n");
sgodinez 11:134435d8a2d5 115 return true;
sgodinez 11:134435d8a2d5 116 }
sgodinez 11:134435d8a2d5 117 //2) Query the radio
sgodinez 11:134435d8a2d5 118 pppConnected = false;
sgodinez 11:134435d8a2d5 119 std::string result = sendCommand("AT#VSTATE", 1000);
sgodinez 11:134435d8a2d5 120 if(result.find("CONNECTED") != std::string::npos) {
sgodinez 11:134435d8a2d5 121 pppConnected = true;
sgodinez 11:134435d8a2d5 122 }
sgodinez 11:134435d8a2d5 123
sgodinez 11:134435d8a2d5 124 return pppConnected;
sgodinez 11:134435d8a2d5 125 }
sgodinez 11:134435d8a2d5 126
sgodinez 11:134435d8a2d5 127 bool Cellular::bind(unsigned int port) {
sgodinez 11:134435d8a2d5 128 return false;
sgodinez 11:134435d8a2d5 129 }
sgodinez 11:134435d8a2d5 130
sgodinez 11:134435d8a2d5 131 bool Cellular::open(const std::string& address, unsigned int port, Mode mode) {
sgodinez 17:2d7c4ea7491b 132 char buffer[256] = {0};
sgodinez 11:134435d8a2d5 133 Code portCode, addressCode;
sgodinez 17:2d7c4ea7491b 134 printf("[DEBUG] Attempting to Open Socket\r\n");
sgodinez 11:134435d8a2d5 135
sgodinez 11:134435d8a2d5 136 //1) Check that we do not have a live connection up
sgodinez 11:134435d8a2d5 137 if(socketOpened) {
sgodinez 17:2d7c4ea7491b 138 printf("[DEBUG] Socket already opened\r\n");
sgodinez 11:134435d8a2d5 139 return true;
sgodinez 11:134435d8a2d5 140 }
sgodinez 11:134435d8a2d5 141
sgodinez 11:134435d8a2d5 142 //2) Check PPP connection
sgodinez 11:134435d8a2d5 143 if(!isConnected()) {
sgodinez 17:2d7c4ea7491b 144 printf("[ERROR] PPP not established. Attempting to connect\r\n");
sgodinez 11:134435d8a2d5 145 if(!connect()) {
sgodinez 17:2d7c4ea7491b 146 printf("[ERROR] PPP connection failed\r\n");
sgodinez 11:134435d8a2d5 147 return false;
sgodinez 11:134435d8a2d5 148 } else {
sgodinez 17:2d7c4ea7491b 149 printf("[DEBUG] PPP connection established\r\n");
sgodinez 11:134435d8a2d5 150 }
sgodinez 11:134435d8a2d5 151 }
sgodinez 11:134435d8a2d5 152
sgodinez 17:2d7c4ea7491b 153 ////Setup IP Connection
sgodinez 11:134435d8a2d5 154 if(mode == TCP) {
sgodinez 17:2d7c4ea7491b 155 if(socketCloseable) {
sgodinez 17:2d7c4ea7491b 156 Code code = sendBasicCommand("AT#DLEMODE=1,0", 1000);
sgodinez 17:2d7c4ea7491b 157 if(code != OK) {
sgodinez 17:2d7c4ea7491b 158 printf("[WARNING] Unable to set socket closeable [%d]\r\n", (int) code);
sgodinez 17:2d7c4ea7491b 159 }
sgodinez 17:2d7c4ea7491b 160 }
sgodinez 17:2d7c4ea7491b 161 sprintf(buffer, "AT#TCPPORT=1,%d", port);
sgodinez 17:2d7c4ea7491b 162 portCode = sendBasicCommand(buffer, 1000);
sgodinez 17:2d7c4ea7491b 163 addressCode = sendBasicCommand("AT#TCPSERV=1,\"" + address + "\"", 1000);
sgodinez 11:134435d8a2d5 164 } else {
sgodinez 17:2d7c4ea7491b 165 if(socketCloseable) {
sgodinez 17:2d7c4ea7491b 166 Code code = sendBasicCommand("AT#UDPDLEMODE=1", 1000);
sgodinez 17:2d7c4ea7491b 167 if(code != OK) {
sgodinez 17:2d7c4ea7491b 168 printf("[WARNING] Unable to set socket closeable [%d]\r\n", (int) code);
sgodinez 17:2d7c4ea7491b 169 }
sgodinez 17:2d7c4ea7491b 170 }
sgodinez 17:2d7c4ea7491b 171 sprintf(buffer, "AT#UDPPORT=1,%d", port);
sgodinez 17:2d7c4ea7491b 172 portCode = sendBasicCommand(buffer, 1000);
sgodinez 17:2d7c4ea7491b 173 addressCode = sendBasicCommand("AT#UDPSERV=1,\"" + address + "\"", 1000);
sgodinez 11:134435d8a2d5 174 }
sgodinez 11:134435d8a2d5 175
sgodinez 11:134435d8a2d5 176 if(portCode == OK) {
sgodinez 11:134435d8a2d5 177 host_port = port;
sgodinez 11:134435d8a2d5 178 } else {
sgodinez 17:2d7c4ea7491b 179 printf("[ERROR] Host port could not be set\r\n");
sgodinez 11:134435d8a2d5 180 }
sgodinez 11:134435d8a2d5 181
sgodinez 11:134435d8a2d5 182 if(addressCode == OK) {
sgodinez 11:134435d8a2d5 183 host_address = address;
sgodinez 11:134435d8a2d5 184 } else {
sgodinez 17:2d7c4ea7491b 185 printf("[ERROR] Host address could not be set\r\n");
sgodinez 11:134435d8a2d5 186 }
sgodinez 11:134435d8a2d5 187
sgodinez 13:0af863114629 188 // Try and Connect
sgodinez 13:0af863114629 189 string response = sendCommand("AT#OTCP=1", 30000);
sgodinez 13:0af863114629 190 if (response.find("Ok_Info_WaitingForData") != string::npos) {
sgodinez 17:2d7c4ea7491b 191 printf("[INFO] Opened TCP Socket [%s:%d]\r\n", address.c_str(), port);
sgodinez 13:0af863114629 192 socketOpened = true;
sgodinez 13:0af863114629 193 } else {
sgodinez 17:2d7c4ea7491b 194 printf("[WARNING] Unable to open TCP Socket [%s:%d]\r\n", address.c_str(), port);
sgodinez 13:0af863114629 195 socketOpened = false;
sgodinez 13:0af863114629 196 }
sgodinez 11:134435d8a2d5 197
sgodinez 13:0af863114629 198 return socketOpened;
sgodinez 11:134435d8a2d5 199 }
sgodinez 11:134435d8a2d5 200
sgodinez 11:134435d8a2d5 201 bool Cellular::isOpen() {
sgodinez 17:2d7c4ea7491b 202 return socketOpened;
sgodinez 11:134435d8a2d5 203 }
sgodinez 11:134435d8a2d5 204
sgodinez 17:2d7c4ea7491b 205 bool Cellular::close() {
sgodinez 13:0af863114629 206 if(!socketOpened) {
sgodinez 17:2d7c4ea7491b 207 printf("[ERROR] Socket is not open\r\n");
sgodinez 17:2d7c4ea7491b 208 return false;
sgodinez 13:0af863114629 209 }
sgodinez 11:134435d8a2d5 210
sgodinez 17:2d7c4ea7491b 211 if(!socketCloseable) {
sgodinez 17:2d7c4ea7491b 212 printf("[ERROR] Socket is not closeable\r\n");
sgodinez 17:2d7c4ea7491b 213 return false;
sgodinez 17:2d7c4ea7491b 214 }
sgodinez 17:2d7c4ea7491b 215
sgodinez 17:2d7c4ea7491b 216 //Build Escape Message => ETX
sgodinez 17:2d7c4ea7491b 217 char buffer[2] = { 0x03, 0x00 };
sgodinez 13:0af863114629 218 Code code = sendBasicCommand(buffer, 1000, NONE);
sgodinez 13:0af863114629 219 if(code != OK) {
sgodinez 17:2d7c4ea7491b 220 printf("[ERROR] Radio did not accept close socket command");
sgodinez 17:2d7c4ea7491b 221 return false;
sgodinez 13:0af863114629 222 }
sgodinez 17:2d7c4ea7491b 223 socketOpened = false;
sgodinez 17:2d7c4ea7491b 224 return true;
sgodinez 11:134435d8a2d5 225 }
sgodinez 11:134435d8a2d5 226
sgodinez 11:134435d8a2d5 227 int Cellular::read(char* data, int max, int timeout) {
sgodinez 19:38794784e009 228 if(io == NULL) {
sgodinez 19:38794784e009 229 printf("[ERROR] MTSBufferedIO not set\r\n");
sgodinez 19:38794784e009 230 return -1;
sgodinez 19:38794784e009 231 }
sgodinez 19:38794784e009 232
sgodinez 17:2d7c4ea7491b 233 if(!socketOpened) {
sgodinez 17:2d7c4ea7491b 234 printf("[ERROR] Socket is not open\r\n");
sgodinez 17:2d7c4ea7491b 235 return -1;
sgodinez 17:2d7c4ea7491b 236 }
sgodinez 17:2d7c4ea7491b 237 int bytesRead = 0;
sgodinez 17:2d7c4ea7491b 238
sgodinez 17:2d7c4ea7491b 239 if(timeout >= 0) {
sgodinez 17:2d7c4ea7491b 240 Timer tmr;
sgodinez 17:2d7c4ea7491b 241 tmr.start();
sgodinez 17:2d7c4ea7491b 242 while (tmr.read_ms() <= timeout && bytesRead < max) {
sgodinez 19:38794784e009 243 if (io->readable()) {
sgodinez 19:38794784e009 244 if(io->read(data[bytesRead]) == 1) {
sgodinez 17:2d7c4ea7491b 245 bytesRead++;
sgodinez 17:2d7c4ea7491b 246 }
sgodinez 17:2d7c4ea7491b 247 } else {
sgodinez 17:2d7c4ea7491b 248 wait(0.05);
sgodinez 17:2d7c4ea7491b 249 }
sgodinez 17:2d7c4ea7491b 250 }
sgodinez 17:2d7c4ea7491b 251 } else {
sgodinez 19:38794784e009 252 bytesRead = io->read(data, max);
sgodinez 17:2d7c4ea7491b 253 }
sgodinez 17:2d7c4ea7491b 254
sgodinez 17:2d7c4ea7491b 255 return bytesRead;
sgodinez 11:134435d8a2d5 256 }
sgodinez 11:134435d8a2d5 257
sgodinez 11:134435d8a2d5 258 int Cellular::write(char* data, int length, int timeout) {
sgodinez 19:38794784e009 259 if(io == NULL) {
sgodinez 19:38794784e009 260 printf("[ERROR] MTSBufferedIO not set\r\n");
sgodinez 19:38794784e009 261 return -1;
sgodinez 19:38794784e009 262 }
sgodinez 19:38794784e009 263
sgodinez 17:2d7c4ea7491b 264 if(!socketOpened) {
sgodinez 17:2d7c4ea7491b 265 printf("[ERROR] Socket is not open\r\n");
sgodinez 17:2d7c4ea7491b 266 return -1;
sgodinez 17:2d7c4ea7491b 267 }
sgodinez 17:2d7c4ea7491b 268
sgodinez 17:2d7c4ea7491b 269 int bytesWritten = 0;
sgodinez 17:2d7c4ea7491b 270
sgodinez 17:2d7c4ea7491b 271 if(timeout >= 0) {
sgodinez 17:2d7c4ea7491b 272 Timer tmr;
sgodinez 17:2d7c4ea7491b 273 tmr.start();
sgodinez 17:2d7c4ea7491b 274 while (tmr.read_ms() <= timeout && bytesWritten < length) {
sgodinez 19:38794784e009 275 if (io->writeable()) {
sgodinez 19:38794784e009 276 if(io->write(*data) == 1) {
sgodinez 17:2d7c4ea7491b 277 data++;
sgodinez 17:2d7c4ea7491b 278 bytesWritten++;
sgodinez 17:2d7c4ea7491b 279 }
sgodinez 17:2d7c4ea7491b 280 } else {
sgodinez 17:2d7c4ea7491b 281 wait(0.05);
sgodinez 17:2d7c4ea7491b 282 }
sgodinez 17:2d7c4ea7491b 283 }
sgodinez 17:2d7c4ea7491b 284 } else {
sgodinez 19:38794784e009 285 bytesWritten = io->write(data, length);
sgodinez 17:2d7c4ea7491b 286 }
sgodinez 17:2d7c4ea7491b 287
sgodinez 17:2d7c4ea7491b 288 return bytesWritten;
sgodinez 11:134435d8a2d5 289 }
sgodinez 11:134435d8a2d5 290
sgodinez 11:134435d8a2d5 291 unsigned int Cellular::readable() {
sgodinez 19:38794784e009 292 if(io == NULL) {
sgodinez 19:38794784e009 293 printf("[ERROR] MTSBufferedIO not set\r\n");
sgodinez 19:38794784e009 294 return 0;
sgodinez 19:38794784e009 295 }
sgodinez 17:2d7c4ea7491b 296 if(!socketOpened) {
sgodinez 17:2d7c4ea7491b 297 printf("[ERROR] Socket is not open\r\n");
sgodinez 17:2d7c4ea7491b 298 return 0;
sgodinez 17:2d7c4ea7491b 299 }
sgodinez 19:38794784e009 300 return io->readable();
sgodinez 11:134435d8a2d5 301 }
sgodinez 11:134435d8a2d5 302
sgodinez 11:134435d8a2d5 303 unsigned int Cellular::writeable() {
sgodinez 19:38794784e009 304 if(io == NULL) {
sgodinez 19:38794784e009 305 printf("[ERROR] MTSBufferedIO not set\r\n");
sgodinez 19:38794784e009 306 return 0;
sgodinez 19:38794784e009 307 }
sgodinez 17:2d7c4ea7491b 308 if(!socketOpened) {
sgodinez 17:2d7c4ea7491b 309 printf("[ERROR] Socket is not open\r\n");
sgodinez 17:2d7c4ea7491b 310 return 0;
sgodinez 17:2d7c4ea7491b 311 }
sgodinez 17:2d7c4ea7491b 312
sgodinez 19:38794784e009 313 return io->writeable();
sgodinez 11:134435d8a2d5 314 }
sgodinez 11:134435d8a2d5 315
sgodinez 11:134435d8a2d5 316 void Cellular::reset() {
sgodinez 11:134435d8a2d5 317
sgodinez 11:134435d8a2d5 318 }
sgodinez 11:134435d8a2d5 319
sgodinez 11:134435d8a2d5 320 Cellular::Code Cellular::test()
jengbrecht 0:563b70517320 321 {
sgodinez 11:134435d8a2d5 322 Code code = sendBasicCommand("AT", 1000);
sgodinez 11:134435d8a2d5 323
sgodinez 11:134435d8a2d5 324 if(code != OK) {
sgodinez 11:134435d8a2d5 325 printf("[Error] Failed basic AT command");
sgodinez 11:134435d8a2d5 326 return code;
sgodinez 11:134435d8a2d5 327 }
sgodinez 11:134435d8a2d5 328
sgodinez 11:134435d8a2d5 329 //AT#VSTATE != "CHECKING"
sgodinez 11:134435d8a2d5 330
sgodinez 11:134435d8a2d5 331 //AT#GPRSMODE ==
sgodinez 12:40ac31a09132 332 return OK;
jengbrecht 0:563b70517320 333 }
jengbrecht 0:563b70517320 334
jengbrecht 0:563b70517320 335 Cellular::Code Cellular::echoOff(bool state)
jengbrecht 0:563b70517320 336 {
sgodinez 13:0af863114629 337 Code code;
jengbrecht 0:563b70517320 338 if (state) {
sgodinez 13:0af863114629 339 code = sendBasicCommand("ATE0", 1000);
sgodinez 13:0af863114629 340 echoMode = (code == OK) ? false : echoMode;
jengbrecht 0:563b70517320 341 } else {
sgodinez 13:0af863114629 342 code = sendBasicCommand("ATE1", 1000);
sgodinez 13:0af863114629 343 echoMode = (code == OK) ? true : echoMode;
jengbrecht 0:563b70517320 344 }
sgodinez 13:0af863114629 345 return code;
jengbrecht 0:563b70517320 346 }
jengbrecht 0:563b70517320 347
jengbrecht 0:563b70517320 348 int Cellular::getSignalStrength()
jengbrecht 0:563b70517320 349 {
jengbrecht 0:563b70517320 350 string response = sendCommand("AT+CSQ", 1000);
jengbrecht 0:563b70517320 351 if (response.find("OK") == string::npos) {
jengbrecht 0:563b70517320 352 return -1;
jengbrecht 0:563b70517320 353 }
jengbrecht 0:563b70517320 354 int start = response.find(':');
jengbrecht 0:563b70517320 355 int stop = response.find(',', start);
jengbrecht 0:563b70517320 356 string signal = response.substr(start + 2, stop - start - 2);
jengbrecht 0:563b70517320 357 int value;
jengbrecht 0:563b70517320 358 sscanf(signal.c_str(), "%d", &value);
jengbrecht 0:563b70517320 359 return value;
jengbrecht 0:563b70517320 360 }
jengbrecht 0:563b70517320 361
sgodinez 5:93e889a5abc6 362 std::string Cellular::getPhoneNumber() {
sgodinez 5:93e889a5abc6 363 return "unknown";
sgodinez 5:93e889a5abc6 364 }
sgodinez 5:93e889a5abc6 365
jengbrecht 0:563b70517320 366 Cellular::Registration Cellular::getRegistration()
jengbrecht 0:563b70517320 367 {
jengbrecht 0:563b70517320 368 string response = sendCommand("AT+CREG?", 1000);
jengbrecht 0:563b70517320 369 if (response.find("OK") == string::npos) {
jengbrecht 0:563b70517320 370 return UNKNOWN;
jengbrecht 0:563b70517320 371 }
jengbrecht 0:563b70517320 372 int start = response.find(',');
jengbrecht 0:563b70517320 373 int stop = response.find(' ', start);
jengbrecht 0:563b70517320 374 string regStat = response.substr(start + 1, stop - start - 1);
jengbrecht 0:563b70517320 375 int value;
jengbrecht 0:563b70517320 376 sscanf(regStat.c_str(), "%d", &value);
jengbrecht 0:563b70517320 377 switch (value) {
jengbrecht 0:563b70517320 378 case 0:
jengbrecht 0:563b70517320 379 return NOT_REGISTERED;
jengbrecht 0:563b70517320 380 case 1:
jengbrecht 0:563b70517320 381 return REGISTERED;
jengbrecht 0:563b70517320 382 case 2:
jengbrecht 0:563b70517320 383 return SEARCHING;
jengbrecht 0:563b70517320 384 case 3:
jengbrecht 0:563b70517320 385 return DENIED;
jengbrecht 0:563b70517320 386 case 4:
jengbrecht 0:563b70517320 387 return UNKNOWN;
jengbrecht 0:563b70517320 388 case 5:
jengbrecht 0:563b70517320 389 return ROAMING;
jengbrecht 0:563b70517320 390 }
sgodinez 4:6561c9128c6f 391 return UNKNOWN;
jengbrecht 0:563b70517320 392 }
jengbrecht 0:563b70517320 393
jengbrecht 0:563b70517320 394 Cellular::Code Cellular::sendBasicCommand(string command, int timeoutMillis, ESC_CHAR esc)
jengbrecht 0:563b70517320 395 {
sgodinez 17:2d7c4ea7491b 396 if(socketOpened) {
sgodinez 17:2d7c4ea7491b 397 printf("[ERROR] socket is open. Can not send AT commands\r\n");
sgodinez 17:2d7c4ea7491b 398 return ERROR;
sgodinez 17:2d7c4ea7491b 399 }
sgodinez 17:2d7c4ea7491b 400
jengbrecht 0:563b70517320 401 string response = sendCommand(command, timeoutMillis, esc);
jengbrecht 0:563b70517320 402 if (response.size() == 0) {
jengbrecht 0:563b70517320 403 return NO_RESPONSE;
jengbrecht 0:563b70517320 404 } else if (response.find("OK") != string::npos) {
jengbrecht 0:563b70517320 405 return OK;
jengbrecht 0:563b70517320 406 } else if (response.find("ERROR") != string::npos) {
jengbrecht 0:563b70517320 407 return ERROR;
jengbrecht 0:563b70517320 408 } else {
jengbrecht 0:563b70517320 409 return FAILURE;
jengbrecht 0:563b70517320 410 }
jengbrecht 0:563b70517320 411 }
jengbrecht 0:563b70517320 412
sgodinez 11:134435d8a2d5 413 Cellular::Code Cellular::setApn(const std::string& apn) {
sgodinez 11:134435d8a2d5 414 Code code = sendBasicCommand("AT#APNSERV=\"" + apn + "\"", 1000);
sgodinez 11:134435d8a2d5 415 if (code != OK) {
sgodinez 11:134435d8a2d5 416 return code;
sgodinez 11:134435d8a2d5 417 }
sgodinez 11:134435d8a2d5 418 this->apn = apn;
sgodinez 11:134435d8a2d5 419 return code;
sgodinez 11:134435d8a2d5 420 }
sgodinez 11:134435d8a2d5 421
sgodinez 11:134435d8a2d5 422 Cellular::Code Cellular::setDns(const std::string& apn) {
sgodinez 12:40ac31a09132 423 return FAILURE;
sgodinez 11:134435d8a2d5 424 }
sgodinez 11:134435d8a2d5 425
jengbrecht 23:bc6f98a1eb22 426 bool Cellular::ping(const std::string& address) {
jengbrecht 23:bc6f98a1eb22 427 char buffer[256] = {0};
jengbrecht 23:bc6f98a1eb22 428 Code code;
jengbrecht 23:bc6f98a1eb22 429
jengbrecht 23:bc6f98a1eb22 430 code = sendBasicCommand("AT#PINGREMOTE=\"" + address + "\"", 1000);
jengbrecht 23:bc6f98a1eb22 431 if (code != OK) {
jengbrecht 23:bc6f98a1eb22 432 return false;
jengbrecht 23:bc6f98a1eb22 433 }
jengbrecht 23:bc6f98a1eb22 434
jengbrecht 23:bc6f98a1eb22 435 sprintf(buffer, "AT#PINGNUM=%d", 1);
jengbrecht 23:bc6f98a1eb22 436 code = sendBasicCommand(buffer , 1000);
jengbrecht 23:bc6f98a1eb22 437 if (code != OK) {
jengbrecht 23:bc6f98a1eb22 438 return false;
jengbrecht 23:bc6f98a1eb22 439 }
jengbrecht 23:bc6f98a1eb22 440
jengbrecht 23:bc6f98a1eb22 441 sprintf(buffer, "AT#PINGDELAY=%d", PINGDELAY);
jengbrecht 23:bc6f98a1eb22 442 code = sendBasicCommand(buffer , 1000);
jengbrecht 23:bc6f98a1eb22 443 if (code != OK) {
jengbrecht 23:bc6f98a1eb22 444 return false;
jengbrecht 23:bc6f98a1eb22 445 }
jengbrecht 23:bc6f98a1eb22 446
jengbrecht 23:bc6f98a1eb22 447 std::string response;
jengbrecht 23:bc6f98a1eb22 448 for (int i = 0; i < PINGNUM; i++) {
jengbrecht 23:bc6f98a1eb22 449 response = sendCommand("AT#PING", PINGDELAY * 1000);
jengbrecht 23:bc6f98a1eb22 450 if (response.find("alive") != std::string::npos) {
jengbrecht 23:bc6f98a1eb22 451 return true;
jengbrecht 23:bc6f98a1eb22 452 }
jengbrecht 23:bc6f98a1eb22 453 }
jengbrecht 23:bc6f98a1eb22 454 return false;
jengbrecht 23:bc6f98a1eb22 455 }
jengbrecht 23:bc6f98a1eb22 456
sgodinez 17:2d7c4ea7491b 457 Cellular::Code Cellular::setSocketCloseable(bool enabled) {
sgodinez 17:2d7c4ea7491b 458 if(socketCloseable == enabled) {
sgodinez 17:2d7c4ea7491b 459 return OK;
sgodinez 17:2d7c4ea7491b 460 }
sgodinez 17:2d7c4ea7491b 461
sgodinez 17:2d7c4ea7491b 462 if(socketOpened) {
sgodinez 17:2d7c4ea7491b 463 printf("[ERROR] socket is already opened. Can not set closeable\r\n");
sgodinez 17:2d7c4ea7491b 464 return ERROR;
sgodinez 17:2d7c4ea7491b 465 }
sgodinez 17:2d7c4ea7491b 466
sgodinez 17:2d7c4ea7491b 467 socketCloseable = enabled;
sgodinez 17:2d7c4ea7491b 468
sgodinez 17:2d7c4ea7491b 469 return OK;
sgodinez 17:2d7c4ea7491b 470 }
sgodinez 17:2d7c4ea7491b 471
sgodinez 4:6561c9128c6f 472 Cellular::Code Cellular::sendSMS(const Sms& sms) {
sgodinez 4:6561c9128c6f 473 return sendSMS(sms.phoneNumber, sms.message);
sgodinez 4:6561c9128c6f 474 }
sgodinez 4:6561c9128c6f 475
sgodinez 4:6561c9128c6f 476 Cellular::Code Cellular::sendSMS(const std::string& phoneNumber, const std::string& message)
sgodinez 17:2d7c4ea7491b 477 {
jengbrecht 0:563b70517320 478 Code code = sendBasicCommand("AT+CMGF=1", 1000);
jengbrecht 0:563b70517320 479 if (code != OK) {
jengbrecht 0:563b70517320 480 return code;
jengbrecht 0:563b70517320 481 }
jengbrecht 0:563b70517320 482 string cmd = "AT+CMGS=\"+";
jengbrecht 0:563b70517320 483 cmd.append(phoneNumber);
jengbrecht 0:563b70517320 484 cmd.append("\"");
jengbrecht 0:563b70517320 485 string response1 = sendCommand(cmd, 1000);
jengbrecht 0:563b70517320 486 if (response1.find('>') == string::npos) {
jengbrecht 0:563b70517320 487 return NO_RESPONSE;
jengbrecht 0:563b70517320 488 }
jengbrecht 0:563b70517320 489 wait(.2);
jengbrecht 0:563b70517320 490 string response2 = sendCommand(message, 4000, CTRL_Z);
sgodinez 17:2d7c4ea7491b 491 printf("SMS Response: %s\r\n", response2.c_str());
jengbrecht 0:563b70517320 492 if (response2.find("+CMGS:") == string::npos) {
jengbrecht 0:563b70517320 493 return FAILURE;
jengbrecht 0:563b70517320 494 }
jengbrecht 0:563b70517320 495 return OK;
jengbrecht 0:563b70517320 496 }
jengbrecht 0:563b70517320 497
sgodinez 4:6561c9128c6f 498 std::vector<Cellular::Sms> Cellular::getReceivedSms() {
sgodinez 9:5b12c5a8dde4 499 int smsNumber = 0;
sgodinez 4:6561c9128c6f 500 std::vector<Sms> vSms;
sgodinez 4:6561c9128c6f 501 std::string received = sendCommand("AT+CMGL=\"ALL\"", 4000);
sgodinez 5:93e889a5abc6 502 size_t pos = received.find("+CMGL: ");
sgodinez 4:6561c9128c6f 503
sgodinez 5:93e889a5abc6 504 while (pos != std::string::npos) {
sgodinez 4:6561c9128c6f 505 Cellular::Sms sms;
sgodinez 4:6561c9128c6f 506 std::string line(Text::getLine(received, pos, pos));
sgodinez 17:2d7c4ea7491b 507 //printf("[DEBUG] Top of SMS Parse Loop. LINE[%s]\r\n", line.c_str());
sgodinez 9:5b12c5a8dde4 508 if(line.find("+CMGL: ") == std::string::npos) {
sgodinez 4:6561c9128c6f 509 continue;
sgodinez 4:6561c9128c6f 510 }
sgodinez 4:6561c9128c6f 511
sgodinez 4:6561c9128c6f 512 //Start of SMS message
sgodinez 4:6561c9128c6f 513 std::vector<std::string> vSmsParts = Text::split(line, ',');
sgodinez 4:6561c9128c6f 514 if(vSmsParts.size() != 6) {
sgodinez 17:2d7c4ea7491b 515 printf("[WARNING] Expected 6 commas. SMS[%d] DATA[%s]. Continuing ...\r\n", smsNumber, line.c_str());
sgodinez 4:6561c9128c6f 516 continue;
sgodinez 4:6561c9128c6f 517 }
sgodinez 4:6561c9128c6f 518
sgodinez 4:6561c9128c6f 519 sms.phoneNumber = vSmsParts[2];
sgodinez 4:6561c9128c6f 520 sms.timestamp = vSmsParts[4] + ", " + vSmsParts[5];
sgodinez 4:6561c9128c6f 521
sgodinez 8:3fe68d6130a8 522 if(pos == std::string::npos) {
sgodinez 17:2d7c4ea7491b 523 printf("[WARNING] Expected SMS body. SMS[%d]. Leaving ...\r\n", smsNumber);
sgodinez 8:3fe68d6130a8 524 break;
sgodinez 8:3fe68d6130a8 525 }
sgodinez 9:5b12c5a8dde4 526 //Check for the start of the next SMS message
sgodinez 9:5b12c5a8dde4 527 size_t bodyEnd = received.find("\r\n+CMGL: ", pos);
sgodinez 8:3fe68d6130a8 528 if(bodyEnd == std::string::npos) {
sgodinez 17:2d7c4ea7491b 529 //printf("[DEBUG] Parsing Last SMS. SMS[%d]\r\n", smsNumber);
sgodinez 9:5b12c5a8dde4 530 //This must be the last SMS message
sgodinez 9:5b12c5a8dde4 531 bodyEnd = received.find("\r\n\r\nOK", pos);
sgodinez 8:3fe68d6130a8 532 }
sgodinez 9:5b12c5a8dde4 533
sgodinez 9:5b12c5a8dde4 534 //Safety check that we found the boundary of this current SMS message
sgodinez 9:5b12c5a8dde4 535 if(bodyEnd != std::string::npos) {
sgodinez 9:5b12c5a8dde4 536 sms.message = received.substr(pos, bodyEnd - pos);
sgodinez 9:5b12c5a8dde4 537 } else {
sgodinez 8:3fe68d6130a8 538 sms.message = received.substr(pos);
sgodinez 17:2d7c4ea7491b 539 printf("[WARNING] Expected to find end of SMS list. SMS[%d] DATA[%s].\r\n", smsNumber, sms.message.c_str());
sgodinez 8:3fe68d6130a8 540 }
sgodinez 5:93e889a5abc6 541 vSms.push_back(sms);
sgodinez 4:6561c9128c6f 542 pos = bodyEnd;
sgodinez 17:2d7c4ea7491b 543 //printf("[DEBUG] Parsed SMS[%d]. Starting Next at position [%d]\r\n", smsNumber, pos);
sgodinez 9:5b12c5a8dde4 544 smsNumber++;
sgodinez 4:6561c9128c6f 545 }
sgodinez 17:2d7c4ea7491b 546 printf("Received %d SMS\r\n", smsNumber);
sgodinez 4:6561c9128c6f 547 return vSms;
sgodinez 4:6561c9128c6f 548 }
sgodinez 4:6561c9128c6f 549
sgodinez 4:6561c9128c6f 550 Cellular::Code Cellular::deleteOnlyReceivedReadSms() {
sgodinez 4:6561c9128c6f 551 return sendBasicCommand("AT+CMGD=1,1", 1000);
sgodinez 4:6561c9128c6f 552 }
sgodinez 4:6561c9128c6f 553
sgodinez 4:6561c9128c6f 554 Cellular::Code Cellular::deleteAllReceivedSms() {
sgodinez 4:6561c9128c6f 555 return sendBasicCommand("AT+CMGD=1,4", 1000);
sgodinez 4:6561c9128c6f 556 }
sgodinez 4:6561c9128c6f 557
sgodinez 4:6561c9128c6f 558
jengbrecht 0:563b70517320 559 string Cellular::sendCommand(string command, int timeoutMillis, ESC_CHAR esc)
jengbrecht 0:563b70517320 560 {
sgodinez 19:38794784e009 561 if(io == NULL) {
sgodinez 19:38794784e009 562 printf("[ERROR] MTSBufferedIO not set\r\n");
sgodinez 19:38794784e009 563 return "";
sgodinez 19:38794784e009 564 }
sgodinez 17:2d7c4ea7491b 565 if(socketOpened) {
sgodinez 17:2d7c4ea7491b 566 printf("[ERROR] socket is open. Can not send AT commands\r\n");
sgodinez 17:2d7c4ea7491b 567 return "";
sgodinez 17:2d7c4ea7491b 568 }
sgodinez 17:2d7c4ea7491b 569
jengbrecht 0:563b70517320 570 int size = command.size() + 1;
jengbrecht 0:563b70517320 571 char cmd[size];
jengbrecht 0:563b70517320 572 strcpy(cmd, command.c_str());
jengbrecht 0:563b70517320 573 if (esc == CR) {
jengbrecht 0:563b70517320 574 cmd[size -1] = '\r';
jengbrecht 0:563b70517320 575 } else if (esc == CTRL_Z) {
jengbrecht 0:563b70517320 576 cmd[size -1] = 0x1A;
sgodinez 13:0af863114629 577 } else if(esc == NONE) {
sgodinez 13:0af863114629 578 cmd[size -1] = '\0';
jengbrecht 0:563b70517320 579 }
jengbrecht 0:563b70517320 580
sgodinez 19:38794784e009 581 io->rxClear();
sgodinez 19:38794784e009 582 io->txClear();
sgodinez 8:3fe68d6130a8 583 std::string result;
sgodinez 19:38794784e009 584 int status = io->write(cmd, size);
sgodinez 19:38794784e009 585 int available = io->rxAvailable();
jengbrecht 0:563b70517320 586 int previous = -1;
jengbrecht 0:563b70517320 587 int timer = 0;
sgodinez 8:3fe68d6130a8 588 char tmp[256];
sgodinez 8:3fe68d6130a8 589 tmp[255] = 0;
sgodinez 13:0af863114629 590 bool started = !echoMode;
sgodinez 13:0af863114629 591 bool done = false;
sgodinez 8:3fe68d6130a8 592 do {
jengbrecht 0:563b70517320 593 wait(.1);
jengbrecht 0:563b70517320 594 timer = timer + 100;
jengbrecht 0:563b70517320 595 previous = available;
sgodinez 19:38794784e009 596 available = io->rxAvailable();
sgodinez 8:3fe68d6130a8 597
sgodinez 19:38794784e009 598 int size = io->read(tmp,255); //1 less than allocated
sgodinez 8:3fe68d6130a8 599 if(size > 0) {
sgodinez 8:3fe68d6130a8 600 result.append(tmp, size);
sgodinez 8:3fe68d6130a8 601 }
sgodinez 13:0af863114629 602
sgodinez 13:0af863114629 603 if(!started) {
sgodinez 13:0af863114629 604 //In Echo Mode (Command will have echo'd + 2 characters for \r\n)
sgodinez 13:0af863114629 605 if(result.size() > command.size() + 2) {
sgodinez 13:0af863114629 606 started = true;
sgodinez 13:0af863114629 607 }
sgodinez 13:0af863114629 608 } else {
sgodinez 13:0af863114629 609 done = (available == previous);
sgodinez 13:0af863114629 610 }
sgodinez 13:0af863114629 611 if(timer >= timeoutMillis) {
sgodinez 17:2d7c4ea7491b 612 printf("[WARNING] sendCommand timed out after %d milliseconds\r\n", timeoutMillis);
sgodinez 13:0af863114629 613 done = true;
sgodinez 13:0af863114629 614 }
sgodinez 13:0af863114629 615 } while (!done);
sgodinez 8:3fe68d6130a8 616
sgodinez 8:3fe68d6130a8 617 return result;
jengbrecht 0:563b70517320 618 }
jengbrecht 0:563b70517320 619
jengbrecht 0:563b70517320 620 #endif /* CELLULAR_CPP */