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
Diff: cellular/Cellular.cpp
- Revision:
- 12:40ac31a09132
- Parent:
- 11:134435d8a2d5
- Child:
- 13:0af863114629
--- a/cellular/Cellular.cpp Fri Dec 13 14:53:08 2013 +0000 +++ b/cellular/Cellular.cpp Fri Dec 13 20:23:40 2013 +0000 @@ -2,8 +2,17 @@ #define CELLULAR_CPP #include "Cellular.h" +#include "MTSText.h" +#include <sstream> -Cellular::Cellular(MTSBufferedIO* io) : io(io) +Cellular::Cellular(MTSBufferedIO& io) +: io(io) +, code(OK) +, pppConnected(false) +, mode(TCP) +, socketOpened(false) +, local_port(0) +, host_port(0) { } @@ -11,9 +20,142 @@ { } -Cellular::Code Cellular::ATTest() +bool Cellular::connect() { + //Run Test first to validate a good state + //Check RSSI: AT+CSQ + //Check Registration: AT+CREG? == 0,1 + + + //AT#CONNECTIONSTART: Make a PPP connection + std::string pppResult = sendCommand("AT#CONNECTIONSTART", 30000); + + size_t pos = 0; + std::string ip = Text::getLine(pppResult, pos, pos); + std::string status = Text::getLine(pppResult, pos, pos); + + return false; +} + +void Cellular::disconnect() { + +} + +bool Cellular::isConnected() { + //1) Check if APN was set + if(apn.size() == 0) { + printf("[DEBUG] APN is not set\n"); + return false; + } + + //1) Check that we do not have a live connection up + if(socketOpened) { + printf("[DEBUG] Socket is opened\n"); + return true; + } + //2) Query the radio + pppConnected = false; + std::string result = sendCommand("AT#VSTATE", 1000); + if(result.find("CONNECTED") != std::string::npos) { + pppConnected = true; + } + + return pppConnected; +} + +bool Cellular::bind(unsigned int port) { + return false; +} + +bool Cellular::open(const std::string& address, unsigned int port, Mode mode) { + Code portCode, addressCode; + + //1) Check that we do not have a live connection up + if(socketOpened) { + printf("[DEBUG] Socket already opened\n"); + return true; + } + + //2) Check PPP connection + if(!isConnected()) { + printf("[ERROR] PPP not established. Attempting to connect\n"); + if(!connect()) { + printf("[ERROR] PPP connection failed\n"); + return false; + } else { + printf("[DEBUG] PPP connection established\n"); + } + } + + //Setup IP Connection + std::stringstream ss; + if(mode == TCP) { + ss << "AT#TCPPORT=1," << port; + portCode = sendBasicCommand(ss.str(), 1000); + addressCode = sendBasicCommand("AT#TCPSERV=1," + address, 1000); + } else { + ss << "AT#UDPPORT=1," << port; + portCode = sendBasicCommand(ss.str(), 1000); + addressCode = sendBasicCommand("AT#UDPSERV=1," + address, 1000); + } + + if(portCode == OK) { + host_port = port; + } else { + printf("[ERROR] Host port could not be set\n"); + } + + if(addressCode == OK) { + host_address = address; + } else { + printf("[ERROR] Host address could not be set\n"); + } + + + + return false; +} + +bool Cellular::isOpen() { + return false; +} + +void Cellular::close() { + +} + +int Cellular::read(char* data, int max, int timeout) { + return -1; +} + +int Cellular::write(char* data, int length, int timeout) { + return -1; +} + +unsigned int Cellular::readable() { + return 0; +} + +unsigned int Cellular::writeable() { + return 0; +} + +void Cellular::reset() { + +} + +Cellular::Code Cellular::test() { - return sendBasicCommand("AT", 1000); + Code code = sendBasicCommand("AT", 1000); + + if(code != OK) { + printf("[Error] Failed basic AT command"); + return code; + } + + //AT#VSTATE != "CHECKING" + + //AT#GPRSMODE == + return OK; } Cellular::Code Cellular::echoOff(bool state) @@ -39,6 +181,10 @@ return value; } +std::string Cellular::getPhoneNumber() { + return "unknown"; +} + Cellular::Registration Cellular::getRegistration() { string response = sendCommand("AT+CREG?", 1000); @@ -64,38 +210,39 @@ case 5: return ROAMING; } + return UNKNOWN; } -int Cellular::connect(string host, int port) -{ - // Set the Server Address - string hostCmd = "AT#TCPSERV=1,\""; - hostCmd.append(host); - hostCmd.append("\""); - if (sendBasicCommand(hostCmd, 1000) != OK) { - return -1; - } - - // Set the Server Port - string portCmd = "AT#TCPPORT=1,\""; - char tmp[7]; - if (sprintf(tmp, "%d", port) < 0) { - return -1; - } - portCmd.append(string(tmp)); - portCmd.append("\""); - if (sendBasicCommand(portCmd, 1000) != OK) { - return -1; - } - - // Try and Connect - string response = sendCommand("AT#OTCP=1", 2000); - if (response.find("Ok_Info_WaitingForData") != string::npos) { - return 0; - } else { - return -1; - } -} +//int Cellular::connect(string host, int port) +//{ +// // Set the Server Address +// string hostCmd = "AT#TCPSERV=1,\""; +// hostCmd.append(host); +// hostCmd.append("\""); +// if (sendBasicCommand(hostCmd, 1000) != OK) { +// return -1; +// } +// +// // Set the Server Port +// string portCmd = "AT#TCPPORT=1,\""; +// char tmp[7]; +// if (sprintf(tmp, "%d", port) < 0) { +// return -1; +// } +// portCmd.append(string(tmp)); +// portCmd.append("\""); +// if (sendBasicCommand(portCmd, 1000) != OK) { +// return -1; +// } +// +// // Try and Connect +// string response = sendCommand("AT#OTCP=1", 2000); +// if (response.find("Ok_Info_WaitingForData") != string::npos) { +// return 0; +// } else { +// return -1; +// } +//} Cellular::Code Cellular::sendBasicCommand(string command, int timeoutMillis, ESC_CHAR esc) { @@ -111,7 +258,24 @@ } } -Cellular::Code Cellular::sendSMS(string phoneNumber, string message) +Cellular::Code Cellular::setApn(const std::string& apn) { + Code code = sendBasicCommand("AT#APNSERV=\"" + apn + "\"", 1000); + if (code != OK) { + return code; + } + this->apn = apn; + return code; +} + +Cellular::Code Cellular::setDns(const std::string& apn) { + return FAILURE; +} + +Cellular::Code Cellular::sendSMS(const Sms& sms) { + return sendSMS(sms.phoneNumber, sms.message); +} + +Cellular::Code Cellular::sendSMS(const std::string& phoneNumber, const std::string& message) { Code code = sendBasicCommand("AT+CMGF=1", 1000); if (code != OK) { @@ -126,13 +290,74 @@ } wait(.2); string response2 = sendCommand(message, 4000, CTRL_Z); - printf("SMS Response: %s\n", response2); + printf("SMS Response: %s\n", response2.c_str()); if (response2.find("+CMGS:") == string::npos) { return FAILURE; } return OK; } +std::vector<Cellular::Sms> Cellular::getReceivedSms() { + int smsNumber = 0; + std::vector<Sms> vSms; + std::string received = sendCommand("AT+CMGL=\"ALL\"", 4000); + size_t pos = received.find("+CMGL: "); + + while (pos != std::string::npos) { + Cellular::Sms sms; + std::string line(Text::getLine(received, pos, pos)); + //printf("[DEBUG] Top of SMS Parse Loop. LINE[%s]\n", line.c_str()); + if(line.find("+CMGL: ") == std::string::npos) { + continue; + } + + //Start of SMS message + std::vector<std::string> vSmsParts = Text::split(line, ','); + if(vSmsParts.size() != 6) { + printf("[WARNING] Expected 6 commas. SMS[%d] DATA[%s]. Continuing ...\n", smsNumber, line.c_str()); + continue; + } + + sms.phoneNumber = vSmsParts[2]; + sms.timestamp = vSmsParts[4] + ", " + vSmsParts[5]; + + if(pos == std::string::npos) { + printf("[WARNING] Expected SMS body. SMS[%d]. Leaving ...\n", smsNumber); + break; + } + //Check for the start of the next SMS message + size_t bodyEnd = received.find("\r\n+CMGL: ", pos); + if(bodyEnd == std::string::npos) { + //printf("[DEBUG] Parsing Last SMS. SMS[%d]\n", smsNumber); + //This must be the last SMS message + bodyEnd = received.find("\r\n\r\nOK", pos); + } + + //Safety check that we found the boundary of this current SMS message + if(bodyEnd != std::string::npos) { + sms.message = received.substr(pos, bodyEnd - pos); + } else { + sms.message = received.substr(pos); + printf("[WARNING] Expected to find end of SMS list. SMS[%d] DATA[%s].\n", smsNumber, sms.message.c_str()); + } + vSms.push_back(sms); + pos = bodyEnd; + //printf("[DEBUG] Parsed SMS[%d]. Starting Next at position [%d]\n", smsNumber, pos); + smsNumber++; + } + printf("Received %d SMS\n", smsNumber); + return vSms; +} + +Cellular::Code Cellular::deleteOnlyReceivedReadSms() { + return sendBasicCommand("AT+CMGD=1,1", 1000); +} + +Cellular::Code Cellular::deleteAllReceivedSms() { + return sendBasicCommand("AT+CMGD=1,4", 1000); +} + + string Cellular::sendCommand(string command, int timeoutMillis, ESC_CHAR esc) { int size = command.size() + 1; @@ -144,21 +369,29 @@ cmd[size -1] = 0x1A; } - io->rxClear(); - io->txClear(); - int status = io->write(cmd, size); - int available = io->rxAvailable(); + io.rxClear(); + io.txClear(); + std::string result; + int status = io.write(cmd, size); + int available = io.rxAvailable(); int previous = -1; int timer = 0; - while (available != previous && timer < timeoutMillis) { + char tmp[256]; + tmp[255] = 0; + + do { wait(.1); timer = timer + 100; previous = available; - available = io->rxAvailable(); - } - char tmp[available]; - io->read(tmp, available); - return string(tmp); + available = io.rxAvailable(); + + int size = io.read(tmp,255); //1 less than allocated + if(size > 0) { + result.append(tmp, size); + } + } while (available != previous && timer < timeoutMillis); + + return result; } #endif /* CELLULAR_CPP */ \ No newline at end of file