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:
Mon Dec 16 20:00:20 2013 +0000
Revision:
17:2d7c4ea7491b
Parent:
13:0af863114629
Child:
19:38794784e009
TCP send / receive working.  close() still requires some finesse when other end disconnects.

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