Cellular library for MTS Socket Modem Arduino Shield devices from Multi-Tech Systems

Dependents:   mtsas mtsas mtsas mtsas

Committer:
Mike Fiore
Date:
Wed May 21 15:39:35 2014 -0500
Revision:
9:1a03e3f3e7fe
Parent:
8:2d7259d244d1
Child:
10:c188cc05aed5
more restructuring
move configureSignals and pins to Cellular class
add Radio field to Cellular class to hold radio type

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Mike Fiore 4:1f63354b8d1b 1 #include "mbed.h"
Mike Fiore 1:f155d94d6f3a 2 #include "Cellular.h"
Mike Fiore 1:f155d94d6f3a 3 #include "MTSText.h"
Mike Fiore 4:1f63354b8d1b 4 #include "MTSLog.h"
Mike Fiore 1:f155d94d6f3a 5
Mike Fiore 1:f155d94d6f3a 6 using namespace mts;
Mike Fiore 1:f155d94d6f3a 7
Mike Fiore 8:2d7259d244d1 8 bool Cellular::init(MTSBufferedIO* io)
Mike Fiore 8:2d7259d244d1 9 {
Mike Fiore 8:2d7259d244d1 10 if (io == NULL) {
Mike Fiore 8:2d7259d244d1 11 return false;
Mike Fiore 8:2d7259d244d1 12 }
Mike Fiore 8:2d7259d244d1 13 this->io = io;
Mike Fiore 8:2d7259d244d1 14
Mike Fiore 8:2d7259d244d1 15 return true;
Mike Fiore 8:2d7259d244d1 16 }
Mike Fiore 8:2d7259d244d1 17
Mike Fiore 9:1a03e3f3e7fe 18 bool Cellular::configureSignals(unsigned int DCD, unsigned int DTR, unsigned int RESET)
Mike Fiore 9:1a03e3f3e7fe 19 {
Mike Fiore 9:1a03e3f3e7fe 20 //Set DCD - The radio will raise and lower this line
Mike Fiore 9:1a03e3f3e7fe 21 if (DCD != NC) {
Mike Fiore 9:1a03e3f3e7fe 22 dcd = new DigitalIn(PinName(DCD));
Mike Fiore 9:1a03e3f3e7fe 23 }
Mike Fiore 9:1a03e3f3e7fe 24 /* Set DTR - This line should be lowered when we want to talk to the radio and raised when we're done
Mike Fiore 9:1a03e3f3e7fe 25 * for now we will lower it in the constructor and raise it in the destructor.
Mike Fiore 9:1a03e3f3e7fe 26 */
Mike Fiore 9:1a03e3f3e7fe 27 if (DTR != NC) {
Mike Fiore 9:1a03e3f3e7fe 28 dtr = new DigitalOut(PinName(DTR));
Mike Fiore 9:1a03e3f3e7fe 29 dtr->write(0);
Mike Fiore 9:1a03e3f3e7fe 30 }
Mike Fiore 9:1a03e3f3e7fe 31 //Set RESET - Set the hardware reset line to the radio
Mike Fiore 9:1a03e3f3e7fe 32 if (RESET != NC) {
Mike Fiore 9:1a03e3f3e7fe 33 resetLine = new DigitalOut(PinName(RESET));
Mike Fiore 9:1a03e3f3e7fe 34 }
Mike Fiore 9:1a03e3f3e7fe 35 return true;
Mike Fiore 9:1a03e3f3e7fe 36 }
Mike Fiore 9:1a03e3f3e7fe 37
Mike Fiore 1:f155d94d6f3a 38 std::string Cellular::getRegistrationNames(Registration registration)
Mike Fiore 1:f155d94d6f3a 39 {
Mike Fiore 1:f155d94d6f3a 40 switch(registration) {
Mike Fiore 1:f155d94d6f3a 41 case NOT_REGISTERED:
Mike Fiore 1:f155d94d6f3a 42 return "NOT_REGISTERED";
Mike Fiore 1:f155d94d6f3a 43 case REGISTERED:
Mike Fiore 1:f155d94d6f3a 44 return "REGISTERED";
Mike Fiore 1:f155d94d6f3a 45 case SEARCHING:
Mike Fiore 1:f155d94d6f3a 46 return "SEARCHING";
Mike Fiore 1:f155d94d6f3a 47 case DENIED:
Mike Fiore 1:f155d94d6f3a 48 return "DENIED";
Mike Fiore 1:f155d94d6f3a 49 case UNKNOWN:
Mike Fiore 1:f155d94d6f3a 50 return "UNKNOWN";
Mike Fiore 1:f155d94d6f3a 51 case ROAMING:
Mike Fiore 1:f155d94d6f3a 52 return "ROAMING";
Mike Fiore 1:f155d94d6f3a 53 default:
Mike Fiore 1:f155d94d6f3a 54 return "UNKNOWN ENUM";
Mike Fiore 1:f155d94d6f3a 55 }
Mike Fiore 1:f155d94d6f3a 56 }
Mike Fiore 1:f155d94d6f3a 57
Mike Fiore 1:f155d94d6f3a 58 Code Cellular::test()
Mike Fiore 1:f155d94d6f3a 59 {
Mike Fiore 1:f155d94d6f3a 60 int i = 0;
Mike Fiore 1:f155d94d6f3a 61 while (sendBasicCommand("AT", 1000) != SUCCESS) {
Mike Fiore 1:f155d94d6f3a 62 i++;
Mike Fiore 1:f155d94d6f3a 63 if (i >= 30) {
Mike Fiore 4:1f63354b8d1b 64 logError("Could not talk to radio after 30 tries");
Mike Fiore 1:f155d94d6f3a 65 i = 0;
Mike Fiore 1:f155d94d6f3a 66 }
Mike Fiore 1:f155d94d6f3a 67 wait(1);
Mike Fiore 1:f155d94d6f3a 68 }
Mike Fiore 1:f155d94d6f3a 69 return SUCCESS;
Mike Fiore 1:f155d94d6f3a 70 }
Mike Fiore 1:f155d94d6f3a 71
Mike Fiore 1:f155d94d6f3a 72 int Cellular::getSignalStrength()
Mike Fiore 1:f155d94d6f3a 73 {
Mike Fiore 1:f155d94d6f3a 74 string response = sendCommand("AT+CSQ", 1000);
Mike Fiore 1:f155d94d6f3a 75 if (response.find("OK") == string::npos) {
Mike Fiore 1:f155d94d6f3a 76 return -1;
Mike Fiore 1:f155d94d6f3a 77 }
Mike Fiore 1:f155d94d6f3a 78 int start = response.find(':');
Mike Fiore 1:f155d94d6f3a 79 int stop = response.find(',', start);
Mike Fiore 1:f155d94d6f3a 80 string signal = response.substr(start + 2, stop - start - 2);
Mike Fiore 1:f155d94d6f3a 81 int value;
Mike Fiore 1:f155d94d6f3a 82 sscanf(signal.c_str(), "%d", &value);
Mike Fiore 1:f155d94d6f3a 83 return value;
Mike Fiore 1:f155d94d6f3a 84 }
Mike Fiore 1:f155d94d6f3a 85
Mike Fiore 1:f155d94d6f3a 86 Cellular::Registration Cellular::getRegistration()
Mike Fiore 1:f155d94d6f3a 87 {
Mike Fiore 1:f155d94d6f3a 88 string response = sendCommand("AT+CREG?", 5000);
Mike Fiore 1:f155d94d6f3a 89 if (response.find("OK") == string::npos) {
Mike Fiore 1:f155d94d6f3a 90 return UNKNOWN;
Mike Fiore 1:f155d94d6f3a 91 }
Mike Fiore 1:f155d94d6f3a 92 int start = response.find(',');
Mike Fiore 1:f155d94d6f3a 93 int stop = response.find(' ', start);
Mike Fiore 1:f155d94d6f3a 94 string regStat = response.substr(start + 1, stop - start - 1);
Mike Fiore 1:f155d94d6f3a 95 int value;
Mike Fiore 1:f155d94d6f3a 96 sscanf(regStat.c_str(), "%d", &value);
Mike Fiore 1:f155d94d6f3a 97 switch (value) {
Mike Fiore 1:f155d94d6f3a 98 case 0:
Mike Fiore 1:f155d94d6f3a 99 return NOT_REGISTERED;
Mike Fiore 1:f155d94d6f3a 100 case 1:
Mike Fiore 1:f155d94d6f3a 101 return REGISTERED;
Mike Fiore 1:f155d94d6f3a 102 case 2:
Mike Fiore 1:f155d94d6f3a 103 return SEARCHING;
Mike Fiore 1:f155d94d6f3a 104 case 3:
Mike Fiore 1:f155d94d6f3a 105 return DENIED;
Mike Fiore 1:f155d94d6f3a 106 case 4:
Mike Fiore 1:f155d94d6f3a 107 return UNKNOWN;
Mike Fiore 1:f155d94d6f3a 108 case 5:
Mike Fiore 1:f155d94d6f3a 109 return ROAMING;
Mike Fiore 1:f155d94d6f3a 110 }
Mike Fiore 1:f155d94d6f3a 111 return UNKNOWN;
Mike Fiore 1:f155d94d6f3a 112 }
Mike Fiore 7:0ee8e69a3e9c 113
Mike Fiore 8:2d7259d244d1 114 Code Cellular::setApn(const std::string& apn)
Mike Fiore 8:2d7259d244d1 115 {
Mike Fiore 8:2d7259d244d1 116 Code code = sendBasicCommand("AT#APNSERV=\"" + apn + "\"", 1000);
Mike Fiore 8:2d7259d244d1 117 if (code != SUCCESS) {
Mike Fiore 8:2d7259d244d1 118 return code;
Mike Fiore 8:2d7259d244d1 119 }
Mike Fiore 8:2d7259d244d1 120 this->apn = apn;
Mike Fiore 8:2d7259d244d1 121 return code;
Mike Fiore 8:2d7259d244d1 122 }
Mike Fiore 8:2d7259d244d1 123
Mike Fiore 8:2d7259d244d1 124
Mike Fiore 8:2d7259d244d1 125 Code Cellular::setDns(const std::string& primary, const std::string& secondary)
Mike Fiore 8:2d7259d244d1 126 {
Mike Fiore 8:2d7259d244d1 127 return sendBasicCommand("AT#DNS=1," + primary + "," + secondary, 1000);
Mike Fiore 8:2d7259d244d1 128 }
Mike Fiore 8:2d7259d244d1 129
Mike Fiore 7:0ee8e69a3e9c 130 Code Cellular::sendSMS(const Sms& sms)
Mike Fiore 7:0ee8e69a3e9c 131 {
Mike Fiore 7:0ee8e69a3e9c 132 return sendSMS(sms.phoneNumber, sms.message);
Mike Fiore 7:0ee8e69a3e9c 133 }
Mike Fiore 7:0ee8e69a3e9c 134
Mike Fiore 7:0ee8e69a3e9c 135 Code Cellular::sendSMS(const std::string& phoneNumber, const std::string& message)
Mike Fiore 7:0ee8e69a3e9c 136 {
Mike Fiore 7:0ee8e69a3e9c 137 Code code = sendBasicCommand("AT+CMGF=1", 1000);
Mike Fiore 7:0ee8e69a3e9c 138 if (code != SUCCESS) {
Mike Fiore 7:0ee8e69a3e9c 139 return code;
Mike Fiore 7:0ee8e69a3e9c 140 }
Mike Fiore 7:0ee8e69a3e9c 141 string cmd = "AT+CMGS=\"+";
Mike Fiore 7:0ee8e69a3e9c 142 cmd.append(phoneNumber);
Mike Fiore 7:0ee8e69a3e9c 143 cmd.append("\"");
Mike Fiore 7:0ee8e69a3e9c 144 string response1 = sendCommand(cmd, 1000);
Mike Fiore 7:0ee8e69a3e9c 145 if (response1.find('>') == string::npos) {
Mike Fiore 7:0ee8e69a3e9c 146 return NO_RESPONSE;
Mike Fiore 7:0ee8e69a3e9c 147 }
Mike Fiore 7:0ee8e69a3e9c 148 wait(.2);
Mike Fiore 7:0ee8e69a3e9c 149 string response2 = sendCommand(message, 4000, CTRL_Z);
Mike Fiore 7:0ee8e69a3e9c 150 logInfo("SMS Response: %s", response2.c_str());
Mike Fiore 7:0ee8e69a3e9c 151 if (response2.find("+CMGS:") == string::npos) {
Mike Fiore 7:0ee8e69a3e9c 152 return FAILURE;
Mike Fiore 7:0ee8e69a3e9c 153 }
Mike Fiore 7:0ee8e69a3e9c 154 return SUCCESS;
Mike Fiore 7:0ee8e69a3e9c 155 }
Mike Fiore 7:0ee8e69a3e9c 156
Mike Fiore 7:0ee8e69a3e9c 157 std::vector<Cellular::Sms> Cellular::getReceivedSms()
Mike Fiore 7:0ee8e69a3e9c 158 {
Mike Fiore 7:0ee8e69a3e9c 159 int smsNumber = 0;
Mike Fiore 7:0ee8e69a3e9c 160 std::vector<Sms> vSms;
Mike Fiore 7:0ee8e69a3e9c 161 std::string received = sendCommand("AT+CMGL=\"ALL\"", 4000);
Mike Fiore 7:0ee8e69a3e9c 162 size_t pos = received.find("+CMGL: ");
Mike Fiore 7:0ee8e69a3e9c 163
Mike Fiore 7:0ee8e69a3e9c 164 while (pos != std::string::npos) {
Mike Fiore 7:0ee8e69a3e9c 165 Cellular::Sms sms;
Mike Fiore 7:0ee8e69a3e9c 166 std::string line(Text::getLine(received, pos, pos));
Mike Fiore 7:0ee8e69a3e9c 167 if(line.find("+CMGL: ") == std::string::npos) {
Mike Fiore 7:0ee8e69a3e9c 168 continue;
Mike Fiore 7:0ee8e69a3e9c 169 }
Mike Fiore 7:0ee8e69a3e9c 170
Mike Fiore 7:0ee8e69a3e9c 171 //Start of SMS message
Mike Fiore 7:0ee8e69a3e9c 172 std::vector<std::string> vSmsParts = Text::split(line, ',');
Mike Fiore 7:0ee8e69a3e9c 173 if(vSmsParts.size() != 6) {
Mike Fiore 7:0ee8e69a3e9c 174 logWarning("Expected 6 commas. SMS[%d] DATA[%s]. Continuing ...", smsNumber, line.c_str());
Mike Fiore 7:0ee8e69a3e9c 175 continue;
Mike Fiore 7:0ee8e69a3e9c 176 }
Mike Fiore 7:0ee8e69a3e9c 177
Mike Fiore 7:0ee8e69a3e9c 178 sms.phoneNumber = vSmsParts[2];
Mike Fiore 7:0ee8e69a3e9c 179 sms.timestamp = vSmsParts[4] + ", " + vSmsParts[5];
Mike Fiore 7:0ee8e69a3e9c 180
Mike Fiore 7:0ee8e69a3e9c 181 if(pos == std::string::npos) {
Mike Fiore 7:0ee8e69a3e9c 182 logWarning("Expected SMS body. SMS[%d]. Leaving ...", smsNumber);
Mike Fiore 7:0ee8e69a3e9c 183 break;
Mike Fiore 7:0ee8e69a3e9c 184 }
Mike Fiore 7:0ee8e69a3e9c 185 //Check for the start of the next SMS message
Mike Fiore 7:0ee8e69a3e9c 186 size_t bodyEnd = received.find("\r\n+CMGL: ", pos);
Mike Fiore 7:0ee8e69a3e9c 187 if(bodyEnd == std::string::npos) {
Mike Fiore 7:0ee8e69a3e9c 188 //This must be the last SMS message
Mike Fiore 7:0ee8e69a3e9c 189 bodyEnd = received.find("\r\n\r\nOK", pos);
Mike Fiore 7:0ee8e69a3e9c 190 }
Mike Fiore 7:0ee8e69a3e9c 191
Mike Fiore 7:0ee8e69a3e9c 192 //Safety check that we found the boundary of this current SMS message
Mike Fiore 7:0ee8e69a3e9c 193 if(bodyEnd != std::string::npos) {
Mike Fiore 7:0ee8e69a3e9c 194 sms.message = received.substr(pos, bodyEnd - pos);
Mike Fiore 7:0ee8e69a3e9c 195 } else {
Mike Fiore 7:0ee8e69a3e9c 196 sms.message = received.substr(pos);
Mike Fiore 7:0ee8e69a3e9c 197 logWarning("Expected to find end of SMS list. SMS[%d] DATA[%s].", smsNumber, sms.message.c_str());
Mike Fiore 7:0ee8e69a3e9c 198 }
Mike Fiore 7:0ee8e69a3e9c 199 vSms.push_back(sms);
Mike Fiore 7:0ee8e69a3e9c 200 pos = bodyEnd;
Mike Fiore 7:0ee8e69a3e9c 201 smsNumber++;
Mike Fiore 7:0ee8e69a3e9c 202 }
Mike Fiore 7:0ee8e69a3e9c 203 logInfo("Received %d SMS", smsNumber);
Mike Fiore 7:0ee8e69a3e9c 204 return vSms;
Mike Fiore 7:0ee8e69a3e9c 205 }
Mike Fiore 7:0ee8e69a3e9c 206
Mike Fiore 7:0ee8e69a3e9c 207 Code Cellular::deleteOnlyReceivedReadSms()
Mike Fiore 7:0ee8e69a3e9c 208 {
Mike Fiore 7:0ee8e69a3e9c 209 return sendBasicCommand("AT+CMGD=1,1", 1000);
Mike Fiore 7:0ee8e69a3e9c 210 }
Mike Fiore 7:0ee8e69a3e9c 211
Mike Fiore 7:0ee8e69a3e9c 212 Code Cellular::deleteAllReceivedSms()
Mike Fiore 7:0ee8e69a3e9c 213 {
Mike Fiore 7:0ee8e69a3e9c 214 return sendBasicCommand("AT+CMGD=1,4", 1000);
Mike Fiore 7:0ee8e69a3e9c 215 }