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 12 14:45:23 2013 +0000
Revision:
9:5b12c5a8dde4
Parent:
8:3fe68d6130a8
Child:
11:134435d8a2d5
Removed \r\n from tail of received SMS messages.

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 4:6561c9128c6f 7 Cellular::Cellular(MTSBufferedIO& io) : io(io)
jengbrecht 0:563b70517320 8 {
jengbrecht 0:563b70517320 9 }
jengbrecht 0:563b70517320 10
jengbrecht 0:563b70517320 11 Cellular::~Cellular()
jengbrecht 0:563b70517320 12 {
jengbrecht 0:563b70517320 13 }
jengbrecht 0:563b70517320 14
jengbrecht 0:563b70517320 15 Cellular::Code Cellular::ATTest()
jengbrecht 0:563b70517320 16 {
jengbrecht 0:563b70517320 17 return sendBasicCommand("AT", 1000);
jengbrecht 0:563b70517320 18 }
jengbrecht 0:563b70517320 19
jengbrecht 0:563b70517320 20 Cellular::Code Cellular::echoOff(bool state)
jengbrecht 0:563b70517320 21 {
jengbrecht 0:563b70517320 22 if (state) {
jengbrecht 0:563b70517320 23 return sendBasicCommand("ATE0", 1000);
jengbrecht 0:563b70517320 24 } else {
jengbrecht 0:563b70517320 25 return sendBasicCommand("ATE1", 1000);
jengbrecht 0:563b70517320 26 }
jengbrecht 0:563b70517320 27 }
jengbrecht 0:563b70517320 28
jengbrecht 0:563b70517320 29 int Cellular::getSignalStrength()
jengbrecht 0:563b70517320 30 {
jengbrecht 0:563b70517320 31 string response = sendCommand("AT+CSQ", 1000);
jengbrecht 0:563b70517320 32 if (response.find("OK") == string::npos) {
jengbrecht 0:563b70517320 33 return -1;
jengbrecht 0:563b70517320 34 }
jengbrecht 0:563b70517320 35 int start = response.find(':');
jengbrecht 0:563b70517320 36 int stop = response.find(',', start);
jengbrecht 0:563b70517320 37 string signal = response.substr(start + 2, stop - start - 2);
jengbrecht 0:563b70517320 38 int value;
jengbrecht 0:563b70517320 39 sscanf(signal.c_str(), "%d", &value);
jengbrecht 0:563b70517320 40 return value;
jengbrecht 0:563b70517320 41 }
jengbrecht 0:563b70517320 42
sgodinez 5:93e889a5abc6 43 std::string Cellular::getPhoneNumber() {
sgodinez 5:93e889a5abc6 44 return "unknown";
sgodinez 5:93e889a5abc6 45 }
sgodinez 5:93e889a5abc6 46
jengbrecht 0:563b70517320 47 Cellular::Registration Cellular::getRegistration()
jengbrecht 0:563b70517320 48 {
jengbrecht 0:563b70517320 49 string response = sendCommand("AT+CREG?", 1000);
jengbrecht 0:563b70517320 50 if (response.find("OK") == string::npos) {
jengbrecht 0:563b70517320 51 return UNKNOWN;
jengbrecht 0:563b70517320 52 }
jengbrecht 0:563b70517320 53 int start = response.find(',');
jengbrecht 0:563b70517320 54 int stop = response.find(' ', start);
jengbrecht 0:563b70517320 55 string regStat = response.substr(start + 1, stop - start - 1);
jengbrecht 0:563b70517320 56 int value;
jengbrecht 0:563b70517320 57 sscanf(regStat.c_str(), "%d", &value);
jengbrecht 0:563b70517320 58 switch (value) {
jengbrecht 0:563b70517320 59 case 0:
jengbrecht 0:563b70517320 60 return NOT_REGISTERED;
jengbrecht 0:563b70517320 61 case 1:
jengbrecht 0:563b70517320 62 return REGISTERED;
jengbrecht 0:563b70517320 63 case 2:
jengbrecht 0:563b70517320 64 return SEARCHING;
jengbrecht 0:563b70517320 65 case 3:
jengbrecht 0:563b70517320 66 return DENIED;
jengbrecht 0:563b70517320 67 case 4:
jengbrecht 0:563b70517320 68 return UNKNOWN;
jengbrecht 0:563b70517320 69 case 5:
jengbrecht 0:563b70517320 70 return ROAMING;
jengbrecht 0:563b70517320 71 }
sgodinez 4:6561c9128c6f 72 return UNKNOWN;
jengbrecht 0:563b70517320 73 }
jengbrecht 0:563b70517320 74
jengbrecht 0:563b70517320 75 int Cellular::connect(string host, int port)
jengbrecht 0:563b70517320 76 {
jengbrecht 0:563b70517320 77 // Set the Server Address
jengbrecht 0:563b70517320 78 string hostCmd = "AT#TCPSERV=1,\"";
jengbrecht 0:563b70517320 79 hostCmd.append(host);
jengbrecht 0:563b70517320 80 hostCmd.append("\"");
jengbrecht 0:563b70517320 81 if (sendBasicCommand(hostCmd, 1000) != OK) {
jengbrecht 0:563b70517320 82 return -1;
jengbrecht 0:563b70517320 83 }
jengbrecht 0:563b70517320 84
jengbrecht 0:563b70517320 85 // Set the Server Port
jengbrecht 0:563b70517320 86 string portCmd = "AT#TCPPORT=1,\"";
jengbrecht 0:563b70517320 87 char tmp[7];
jengbrecht 0:563b70517320 88 if (sprintf(tmp, "%d", port) < 0) {
jengbrecht 0:563b70517320 89 return -1;
jengbrecht 0:563b70517320 90 }
jengbrecht 0:563b70517320 91 portCmd.append(string(tmp));
jengbrecht 0:563b70517320 92 portCmd.append("\"");
jengbrecht 0:563b70517320 93 if (sendBasicCommand(portCmd, 1000) != OK) {
jengbrecht 0:563b70517320 94 return -1;
jengbrecht 0:563b70517320 95 }
jengbrecht 0:563b70517320 96
jengbrecht 0:563b70517320 97 // Try and Connect
jengbrecht 0:563b70517320 98 string response = sendCommand("AT#OTCP=1", 2000);
jengbrecht 0:563b70517320 99 if (response.find("Ok_Info_WaitingForData") != string::npos) {
jengbrecht 0:563b70517320 100 return 0;
jengbrecht 0:563b70517320 101 } else {
jengbrecht 0:563b70517320 102 return -1;
jengbrecht 0:563b70517320 103 }
jengbrecht 0:563b70517320 104 }
jengbrecht 0:563b70517320 105
jengbrecht 0:563b70517320 106 Cellular::Code Cellular::sendBasicCommand(string command, int timeoutMillis, ESC_CHAR esc)
jengbrecht 0:563b70517320 107 {
jengbrecht 0:563b70517320 108 string response = sendCommand(command, timeoutMillis, esc);
jengbrecht 0:563b70517320 109 if (response.size() == 0) {
jengbrecht 0:563b70517320 110 return NO_RESPONSE;
jengbrecht 0:563b70517320 111 } else if (response.find("OK") != string::npos) {
jengbrecht 0:563b70517320 112 return OK;
jengbrecht 0:563b70517320 113 } else if (response.find("ERROR") != string::npos) {
jengbrecht 0:563b70517320 114 return ERROR;
jengbrecht 0:563b70517320 115 } else {
jengbrecht 0:563b70517320 116 return FAILURE;
jengbrecht 0:563b70517320 117 }
jengbrecht 0:563b70517320 118 }
jengbrecht 0:563b70517320 119
sgodinez 4:6561c9128c6f 120 Cellular::Code Cellular::sendSMS(const Sms& sms) {
sgodinez 4:6561c9128c6f 121 return sendSMS(sms.phoneNumber, sms.message);
sgodinez 4:6561c9128c6f 122 }
sgodinez 4:6561c9128c6f 123
sgodinez 4:6561c9128c6f 124 Cellular::Code Cellular::sendSMS(const std::string& phoneNumber, const std::string& message)
jengbrecht 0:563b70517320 125 {
jengbrecht 0:563b70517320 126 Code code = sendBasicCommand("AT+CMGF=1", 1000);
jengbrecht 0:563b70517320 127 if (code != OK) {
jengbrecht 0:563b70517320 128 return code;
jengbrecht 0:563b70517320 129 }
jengbrecht 0:563b70517320 130 string cmd = "AT+CMGS=\"+";
jengbrecht 0:563b70517320 131 cmd.append(phoneNumber);
jengbrecht 0:563b70517320 132 cmd.append("\"");
jengbrecht 0:563b70517320 133 string response1 = sendCommand(cmd, 1000);
jengbrecht 0:563b70517320 134 if (response1.find('>') == string::npos) {
jengbrecht 0:563b70517320 135 return NO_RESPONSE;
jengbrecht 0:563b70517320 136 }
jengbrecht 0:563b70517320 137 wait(.2);
jengbrecht 0:563b70517320 138 string response2 = sendCommand(message, 4000, CTRL_Z);
sgodinez 4:6561c9128c6f 139 printf("SMS Response: %s\n", response2.c_str());
jengbrecht 0:563b70517320 140 if (response2.find("+CMGS:") == string::npos) {
jengbrecht 0:563b70517320 141 return FAILURE;
jengbrecht 0:563b70517320 142 }
jengbrecht 0:563b70517320 143 return OK;
jengbrecht 0:563b70517320 144 }
jengbrecht 0:563b70517320 145
sgodinez 4:6561c9128c6f 146 std::vector<Cellular::Sms> Cellular::getReceivedSms() {
sgodinez 9:5b12c5a8dde4 147 int smsNumber = 0;
sgodinez 4:6561c9128c6f 148 std::vector<Sms> vSms;
sgodinez 4:6561c9128c6f 149 std::string received = sendCommand("AT+CMGL=\"ALL\"", 4000);
sgodinez 5:93e889a5abc6 150 size_t pos = received.find("+CMGL: ");
sgodinez 4:6561c9128c6f 151
sgodinez 5:93e889a5abc6 152 while (pos != std::string::npos) {
sgodinez 4:6561c9128c6f 153 Cellular::Sms sms;
sgodinez 4:6561c9128c6f 154 std::string line(Text::getLine(received, pos, pos));
sgodinez 9:5b12c5a8dde4 155 //printf("[DEBUG] Top of SMS Parse Loop. LINE[%s]\n", line.c_str());
sgodinez 9:5b12c5a8dde4 156 if(line.find("+CMGL: ") == std::string::npos) {
sgodinez 4:6561c9128c6f 157 continue;
sgodinez 4:6561c9128c6f 158 }
sgodinez 4:6561c9128c6f 159
sgodinez 4:6561c9128c6f 160 //Start of SMS message
sgodinez 4:6561c9128c6f 161 std::vector<std::string> vSmsParts = Text::split(line, ',');
sgodinez 4:6561c9128c6f 162 if(vSmsParts.size() != 6) {
sgodinez 9:5b12c5a8dde4 163 printf("[WARNING] Expected 6 commas. SMS[%d] DATA[%s]. Continuing ...\n", smsNumber, line.c_str());
sgodinez 4:6561c9128c6f 164 continue;
sgodinez 4:6561c9128c6f 165 }
sgodinez 4:6561c9128c6f 166
sgodinez 4:6561c9128c6f 167 sms.phoneNumber = vSmsParts[2];
sgodinez 4:6561c9128c6f 168 sms.timestamp = vSmsParts[4] + ", " + vSmsParts[5];
sgodinez 4:6561c9128c6f 169
sgodinez 8:3fe68d6130a8 170 if(pos == std::string::npos) {
sgodinez 9:5b12c5a8dde4 171 printf("[WARNING] Expected SMS body. SMS[%d]. Leaving ...\n", smsNumber);
sgodinez 8:3fe68d6130a8 172 break;
sgodinez 8:3fe68d6130a8 173 }
sgodinez 9:5b12c5a8dde4 174 //Check for the start of the next SMS message
sgodinez 9:5b12c5a8dde4 175 size_t bodyEnd = received.find("\r\n+CMGL: ", pos);
sgodinez 8:3fe68d6130a8 176 if(bodyEnd == std::string::npos) {
sgodinez 9:5b12c5a8dde4 177 //printf("[DEBUG] Parsing Last SMS. SMS[%d]\n", smsNumber);
sgodinez 9:5b12c5a8dde4 178 //This must be the last SMS message
sgodinez 9:5b12c5a8dde4 179 bodyEnd = received.find("\r\n\r\nOK", pos);
sgodinez 8:3fe68d6130a8 180 }
sgodinez 9:5b12c5a8dde4 181
sgodinez 9:5b12c5a8dde4 182 //Safety check that we found the boundary of this current SMS message
sgodinez 9:5b12c5a8dde4 183 if(bodyEnd != std::string::npos) {
sgodinez 9:5b12c5a8dde4 184 sms.message = received.substr(pos, bodyEnd - pos);
sgodinez 9:5b12c5a8dde4 185 } else {
sgodinez 8:3fe68d6130a8 186 sms.message = received.substr(pos);
sgodinez 9:5b12c5a8dde4 187 printf("[WARNING] Expected to find end of SMS list. SMS[%d] DATA[%s].\n", smsNumber, sms.message.c_str());
sgodinez 8:3fe68d6130a8 188 }
sgodinez 5:93e889a5abc6 189 vSms.push_back(sms);
sgodinez 4:6561c9128c6f 190 pos = bodyEnd;
sgodinez 9:5b12c5a8dde4 191 //printf("[DEBUG] Parsed SMS[%d]. Starting Next at position [%d]\n", smsNumber, pos);
sgodinez 9:5b12c5a8dde4 192 smsNumber++;
sgodinez 4:6561c9128c6f 193 }
sgodinez 9:5b12c5a8dde4 194 printf("Received %d SMS\n", smsNumber);
sgodinez 4:6561c9128c6f 195 return vSms;
sgodinez 4:6561c9128c6f 196 }
sgodinez 4:6561c9128c6f 197
sgodinez 4:6561c9128c6f 198 Cellular::Code Cellular::deleteOnlyReceivedReadSms() {
sgodinez 4:6561c9128c6f 199 return sendBasicCommand("AT+CMGD=1,1", 1000);
sgodinez 4:6561c9128c6f 200 }
sgodinez 4:6561c9128c6f 201
sgodinez 4:6561c9128c6f 202 Cellular::Code Cellular::deleteAllReceivedSms() {
sgodinez 4:6561c9128c6f 203 return sendBasicCommand("AT+CMGD=1,4", 1000);
sgodinez 4:6561c9128c6f 204 }
sgodinez 4:6561c9128c6f 205
sgodinez 4:6561c9128c6f 206
jengbrecht 0:563b70517320 207 string Cellular::sendCommand(string command, int timeoutMillis, ESC_CHAR esc)
jengbrecht 0:563b70517320 208 {
jengbrecht 0:563b70517320 209 int size = command.size() + 1;
jengbrecht 0:563b70517320 210 char cmd[size];
jengbrecht 0:563b70517320 211 strcpy(cmd, command.c_str());
jengbrecht 0:563b70517320 212 if (esc == CR) {
jengbrecht 0:563b70517320 213 cmd[size -1] = '\r';
jengbrecht 0:563b70517320 214 } else if (esc == CTRL_Z) {
jengbrecht 0:563b70517320 215 cmd[size -1] = 0x1A;
jengbrecht 0:563b70517320 216 }
jengbrecht 0:563b70517320 217
sgodinez 4:6561c9128c6f 218 io.rxClear();
sgodinez 4:6561c9128c6f 219 io.txClear();
sgodinez 8:3fe68d6130a8 220 std::string result;
sgodinez 4:6561c9128c6f 221 int status = io.write(cmd, size);
sgodinez 4:6561c9128c6f 222 int available = io.rxAvailable();
jengbrecht 0:563b70517320 223 int previous = -1;
jengbrecht 0:563b70517320 224 int timer = 0;
sgodinez 8:3fe68d6130a8 225 char tmp[256];
sgodinez 8:3fe68d6130a8 226 tmp[255] = 0;
sgodinez 8:3fe68d6130a8 227
sgodinez 8:3fe68d6130a8 228 do {
jengbrecht 0:563b70517320 229 wait(.1);
jengbrecht 0:563b70517320 230 timer = timer + 100;
jengbrecht 0:563b70517320 231 previous = available;
sgodinez 4:6561c9128c6f 232 available = io.rxAvailable();
sgodinez 8:3fe68d6130a8 233
sgodinez 8:3fe68d6130a8 234 int size = io.read(tmp,255); //1 less than allocated
sgodinez 8:3fe68d6130a8 235 if(size > 0) {
sgodinez 8:3fe68d6130a8 236 result.append(tmp, size);
sgodinez 8:3fe68d6130a8 237 }
sgodinez 8:3fe68d6130a8 238 } while (available != previous && timer < timeoutMillis);
sgodinez 8:3fe68d6130a8 239
sgodinez 8:3fe68d6130a8 240 return result;
jengbrecht 0:563b70517320 241 }
jengbrecht 0:563b70517320 242
jengbrecht 0:563b70517320 243 #endif /* CELLULAR_CPP */