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

Revision:
82:5aa75004e553
Parent:
71:82205735732b
Child:
85:b17ad6781c5b
Child:
87:5db6c084adc7
--- a/cellular/Cellular.cpp	Fri Dec 27 15:19:49 2013 +0000
+++ b/cellular/Cellular.cpp	Fri Dec 27 15:41:24 2013 +0000
@@ -9,7 +9,8 @@
 
 Cellular* Cellular::instance = NULL;
 
-Cellular* Cellular::getInstance() {
+Cellular* Cellular::getInstance()
+{
     if(instance == NULL) {
         instance = new Cellular(NULL);
     }
@@ -17,109 +18,118 @@
 }
 
 
-bool Cellular::init(MTSBufferedIO* io) {
+bool Cellular::init(MTSBufferedIO* io, PinName DCD, PinName DTR)
+{
     if (io == NULL) {
         return false;
     }
+    if (DCD != NC) {
+        // the radio will raise and lower this line
+        dcd = new DigitalIn(DCD); //PTA4 - KL46
+    }
+    if (DTR != NC) {
+        dtr = new DigitalOut(DTR); //PTC9 - KL46
+        /* This line should be lowered when we want to talk to the radio and raised when we're done
+        for now we will lower it in the constructor and raise it in the destructor
+        */
+        dtr->write(0);
+    }
     instance->io = io;
     return true;
 }
 
-Cellular::Cellular(MTSBufferedIO* io) 
-: io(io)
-, echoMode(true)
-, pppConnected(false)
-, mode(TCP)
-, socketOpened(false)
-, socketCloseable(true)
-, local_port(0)
-, host_port(0)
+Cellular::Cellular(MTSBufferedIO* io)
+    : io(io)
+    , echoMode(true)
+    , pppConnected(false)
+    , mode(TCP)
+    , socketOpened(false)
+    , socketCloseable(true)
+    , local_port(0)
+    , host_port(0)
 {
-    // the radio's DCD signal is mapped to PTA4
-    // the radio will raise and lower this line
-    dcd = new DigitalIn(PTA4);
-    // the DTR line to the radio is mapped PTC9
-    // this line should be lowered when we want to talk to the radio and raised when we're done
-    // for now we will lower it in the constructor and raise it in the destructor
-    dtr = new DigitalOut(PTC9);
-    dtr->write(0);
 }
 
 Cellular::~Cellular()
 {
-    dtr->write(1);
+    if (dtr != NULL) {
+        dtr->write(1);
+    }
 }
 
-bool Cellular::connect() {
+bool Cellular::connect()
+{
     //Check if socket is open
     if(socketOpened) {
-        return true;   
+        return true;
     }
-    
+
     //Run Test first to validate a good state
     if(isConnected()) {
         return true;
     }
-    
-    //Check RSSI: AT+CSQ    
+
+    //Check RSSI: AT+CSQ
     int rssi = getSignalStrength();
     printf("[DEBUG] Signal strength: %d\r\n", rssi);
-    
+
     //Check Registration: AT+CREG? == 0,1
     Registration registration = getRegistration();
     if(registration != REGISTERED) {
-        printf("[WARNING] Not Registered [%d]\r\n", (int)registration);    
+        printf("[WARNING] Not Registered [%d]\r\n", (int)registration);
     }
-    
+
     //AT#CONNECTIONSTART: Make a PPP connection
     printf("[DEBUG] Making PPP Connection Attempt. APN[%s]\r\n", apn.c_str());
     std::string pppResult = sendCommand("AT#CONNECTIONSTART", 120000);
     std::vector<std::string> parts = Text::split(pppResult, "\r\n");
-    
+
     //printf("[DEBUG] PPP CONNECT RESULT [%s]\r\n", pppResult.c_str());
 //    for(uint32_t i = 0; i < parts.size(); i++) {
-//        printf("[%d] [%s]\r\n", i, parts[i].c_str());   
+//        printf("[%d] [%s]\r\n", i, parts[i].c_str());
 //    }
-           
+
     if(pppResult.find("Ok_Info_GprsActivation") != std::string::npos) {
         if(parts.size() >= 2) {
-            local_address = parts[1];   
+            local_address = parts[1];
         }
         printf("[INFO] PPP Connection Established: IP[%s]\r\n", local_address.c_str());
         pppConnected = true;
-        
+
     } else {
-        pppConnected = false;   
+        pppConnected = false;
     }
-    
+
     return pppConnected;
 }
 
-void Cellular::disconnect() {
+void Cellular::disconnect()
+{
     //AT#CONNECTIONSTOP: Close a PPP connection
     printf("[DEBUG] Closing PPP Connection\r\n");
-    
-    if(socketOpened) { 
-        close();   
+
+    if(socketOpened) {
+        close();
     }
-    
+
     Code code = sendBasicCommand("AT#CONNECTIONSTOP", 10000);
     if(code == SUCCESS) {
         printf("[DEBUG] Successfully closed PPP Connection\r\n");
     } else {
-        printf("[ERROR] Closing PPP Connection [%d].  Continuing ...\r\n", (int)code);   
+        printf("[ERROR] Closing PPP Connection [%d].  Continuing ...\r\n", (int)code);
     }
-    
+
     pppConnected = false;
 }
 
-bool Cellular::isConnected() {
+bool Cellular::isConnected()
+{
     //1) Check if APN was set
     if(apn.size() == 0) {
         printf("[DEBUG] APN is not set\r\n");
         return false;
     }
-    
+
     //1) Check that we do not have a live connection up
     if(socketOpened) {
         printf("[DEBUG] Socket is opened\r\n");
@@ -131,28 +141,30 @@
     if(result.find("CONNECTED") != std::string::npos) {
         pppConnected = true;
     }
-    
+
     return pppConnected;
 }
 
-bool Cellular::bind(unsigned int port) {
+bool Cellular::bind(unsigned int port)
+{
     if(socketOpened) {
-        printf("[ERROR] socket is open. Can not set local port\r\n");    
+        printf("[ERROR] socket is open. Can not set local port\r\n");
         return false;
     }
     if(port > 65535) {
-        printf("[ERROR] port out of range (0-65535)\r\n");    
+        printf("[ERROR] port out of range (0-65535)\r\n");
         return false;
     }
     local_port = port;
     return true;
 }
 
-bool Cellular::open(const std::string& address, unsigned int port, Mode mode) {
+bool Cellular::open(const std::string& address, unsigned int port, Mode mode)
+{
     char buffer[256] = {0};
     Code portCode, addressCode;
     printf("[DEBUG] Attempting to Open Socket\r\n");
-    
+
     //1) Check that we do not have a live connection up
     if(socketOpened) {
         //Check that the address, port, and mode match
@@ -164,18 +176,18 @@
             }
             return false;
         }
-        
+
         printf("[DEBUG] Socket already opened\r\n");
         return true;
     }
-    
+
     //2) Check Parameters
     if(port > 65535) {
-        printf("[ERROR] port out of range (0-65535)\r\n");    
+        printf("[ERROR] port out of range (0-65535)\r\n");
         return false;
     }
-    
-    
+
+
     //3) Check PPP connection
     if(!isConnected()) {
         printf("[ERROR] PPP not established.  Attempting to connect\r\n");
@@ -186,23 +198,23 @@
             printf("[DEBUG] PPP connection established\r\n");
         }
     }
-    
+
     //Set Local Port
     if(local_port != 0) {
         //Attempt to set local port
         sprintf(buffer, "AT#OUTPORT=%d", local_port);
         Code code = sendBasicCommand(buffer, 1000);
         if(code != SUCCESS) {
-            printf("[WARNING] Unable to set local port (%d) [%d]\r\n", local_port, (int) code);       
+            printf("[WARNING] Unable to set local port (%d) [%d]\r\n", local_port, (int) code);
         }
     }
-    
+
     //Set TCP/UDP parameters
     if(mode == TCP) {
         if(socketCloseable) {
             Code code = sendBasicCommand("AT#DLEMODE=1,1", 1000);
             if(code != SUCCESS) {
-                printf("[WARNING] Unable to set socket closeable [%d]\r\n", (int) code);       
+                printf("[WARNING] Unable to set socket closeable [%d]\r\n", (int) code);
             }
         }
         sprintf(buffer, "AT#TCPPORT=1,%d", port);
@@ -212,28 +224,28 @@
         if(socketCloseable) {
             Code code = sendBasicCommand("AT#UDPDLEMODE=1", 1000);
             if(code != SUCCESS) {
-                printf("[WARNING] Unable to set socket closeable [%d]\r\n", (int) code);       
+                printf("[WARNING] Unable to set socket closeable [%d]\r\n", (int) code);
             }
         }
         sprintf(buffer, "AT#UDPPORT=%d", port);
         portCode = sendBasicCommand(buffer, 1000);
         addressCode = sendBasicCommand("AT#UDPSERV=\"" + address + "\"", 1000);
     }
-    
+
     if(portCode == SUCCESS) {
         host_port = port;
     } else {
         printf("[ERROR] Host port could not be set\r\n");
     }
-    
+
     if(addressCode == SUCCESS) {
         host_address = address;
     } else {
         printf("[ERROR] Host address could not be set\r\n");
     }
-    
-    
-    
+
+
+
     // Try and Connect
     std::string sMode;
     std::string sOpenSocketCmd;
@@ -252,15 +264,17 @@
         printf("[WARNING] Unable to open %s Socket [%s:%d]\r\n", sMode.c_str(),  address.c_str(), port);
         socketOpened = false;
     }
-        
+
     return socketOpened;
 }
 
-bool Cellular::isOpen() {
+bool Cellular::isOpen()
+{
     return socketOpened;
 }
 
-bool Cellular::close() {
+bool Cellular::close()
+{
     if(io == NULL) {
         printf("[ERROR] MTSBufferedIO not set\r\n");
         return false;
@@ -275,7 +289,7 @@
         printf("[ERROR] Socket is not closeable\r\n");
         return false;
     }
-    
+
     Timer tmr;
     int timeout = 1000;
     int written = 0;
@@ -284,7 +298,7 @@
         written = io->write(ETX);
         if(written < 0) {
             printf("[ERROR] Failed to write to MTSBufferedIO\r\n");
-            return false;   
+            return false;
         }
         wait(0.05);
     } while(tmr.read_ms() <= timeout && written != 1);
@@ -293,37 +307,38 @@
         printf("[ERROR] Timed out attempting to close socket\r\n");
         return false;
     }
-    
+
     socketOpened = false;
     return true;
 }
 
-int Cellular::read(char* data, int max, int timeout) {
+int Cellular::read(char* data, int max, int timeout)
+{
     if(io == NULL) {
         printf("[ERROR] MTSBufferedIO not set\r\n");
         return -1;
     }
-    
-    //Check that nothing is in the rx buffer 
+
+    //Check that nothing is in the rx buffer
     if(!socketOpened && !io->readable()) {
         printf("[ERROR] Socket is not open\r\n");
         return -1;
     }
     int bytesRead = 0;
-    
+
     if(timeout >= 0) {
         bytesRead = io->read(data, max, static_cast<unsigned int>(timeout));
     } else {
         bytesRead = io->read(data, max);
     }
-    
+
     if(bytesRead > 0 && socketCloseable) {
-        //Remove escape characters   
+        //Remove escape characters
         int index = 0;
         bool escapeFlag = false;
         for(int i = 0; i < bytesRead; i++) {
-           if(data[i] == DLE || data[i] == ETX) {
-               if(escapeFlag == true) {
+            if(data[i] == DLE || data[i] == ETX) {
+                if(escapeFlag == true) {
                     //This character has been escaped
                     escapeFlag = false;
                 } else if(data[bytesRead] == DLE) {
@@ -331,8 +346,8 @@
                     escapeFlag = true;
                     continue;
                 } else {
-                    //ETX sent without escape -> Socket closed 
-                    printf("[INFO] Read ETX character without DLE escape. Socket closed\r\n"); 
+                    //ETX sent without escape -> Socket closed
+                    printf("[INFO] Read ETX character without DLE escape. Socket closed\r\n");
                     socketOpened = false;
                     continue;
                 }
@@ -345,12 +360,12 @@
         }
         bytesRead = index;
     }
-    
+
     //Scan for socket closed message
     for(size_t i = 0; i < bytesRead; i++) {
         if(data[i] == 'O') {
             if(strstr(&data[i], "Ok_Info_SocketClosed")) {
-                printf("[INFO] Found socket closed message. Socket closed\r\n"); 
+                printf("[INFO] Found socket closed message. Socket closed\r\n");
                 //Close socket and Cut Off End of Message
                 socketOpened = false;
                 data[i] = '\0';
@@ -362,17 +377,18 @@
     return bytesRead;
 }
 
-int Cellular::write(const char* data, int length, int timeout) {
+int Cellular::write(const char* data, int length, int timeout)
+{
     if(io == NULL) {
         printf("[ERROR] MTSBufferedIO not set\r\n");
         return -1;
     }
-    
+
     if(!socketOpened) {
         printf("[ERROR] Socket is not open\r\n");
         return -1;
     }
-    
+
     //In order to avoid allocating another buffer, capture indices of
     //characters to escape during write
     int specialWritten = 0;
@@ -382,10 +398,10 @@
             if(data[i] == ETX || data[i] == DLE) {
                 //Push back index of special characters
                 vSpecial.push_back(i);
-            }                   
+            }
         }
     }
-    
+
     int bytesWritten = 0;
     if(timeout >= 0) {
         Timer tmr;
@@ -399,9 +415,9 @@
                         if(available < 2) {
                             //Requires at least two bytes of space
                             wait(0.05);
-                            continue;   
+                            continue;
                         }
-                        //Ready to write special character    
+                        //Ready to write special character
                         if(io->write(DLE)) {
                             specialWritten++;
                             if(io->write(data[bytesWritten])) {
@@ -412,17 +428,17 @@
                             wait(0.05);
                         }
                     } else {
-                        //We want to write all the way up to the next special character    
+                        //We want to write all the way up to the next special character
                         int relativeIndex = vSpecial[specialWritten] - bytesWritten;
                         int size = MIN(available, relativeIndex);
                         bytesWritten += io->write(&data[bytesWritten], size);
-                    }                    
-                } else {                
+                    }
+                } else {
                     int size = MIN(available, length - bytesWritten);
                     bytesWritten += io->write(&data[bytesWritten], size);
                 }
             } else {
-                wait(0.05);   
+                wait(0.05);
             }
         } while (tmr.read_ms() <= timeout && bytesWritten < length);
     } else {
@@ -442,14 +458,15 @@
                 return bytesWritten;
             }
         }
-    
+
         bytesWritten = io->write(&data[bytesWritten], length - bytesWritten);
     }
-    
+
     return bytesWritten;
 }
 
-unsigned int Cellular::readable() {
+unsigned int Cellular::readable()
+{
     if(io == NULL) {
         printf("[ERROR] MTSBufferedIO not set\r\n");
         return 0;
@@ -461,7 +478,8 @@
     return io->readable();
 }
 
-unsigned int Cellular::writeable() {
+unsigned int Cellular::writeable()
+{
     if(io == NULL) {
         printf("[ERROR] MTSBufferedIO not set\r\n");
         return 0;
@@ -470,11 +488,12 @@
         printf("[ERROR] Socket is not open\r\n");
         return 0;
     }
-    
+
     return io->writeable();
 }
 
-void Cellular::reset() {
+void Cellular::reset()
+{
     disconnect();
     Code code = sendBasicCommand("AT#RESET=0", 10000);
     if(code != SUCCESS) {
@@ -487,15 +506,15 @@
 Code Cellular::test()
 {
     Code code = sendBasicCommand("AT", 1000);
-    
+
     if(code != SUCCESS) {
         printf("[Error] Failed basic AT command");
         return code;
     }
 
     //AT#VSTATE != "CHECKING"
-    
-    //AT#GPRSMODE == 
+
+    //AT#GPRSMODE ==
     return SUCCESS;
 }
 
@@ -557,7 +576,7 @@
 Code Cellular::sendBasicCommand(const std::string& command, unsigned int timeoutMillis, char esc)
 {
     if(socketOpened) {
-        printf("[ERROR] socket is open. Can not send AT commands\r\n");    
+        printf("[ERROR] socket is open. Can not send AT commands\r\n");
         return ERROR;
     }
 
@@ -573,7 +592,8 @@
     }
 }
 
-Code Cellular::setApn(const std::string& apn) {
+Code Cellular::setApn(const std::string& apn)
+{
     Code code = sendBasicCommand("AT#APNSERV=\"" + apn + "\"", 1000);
     if (code != SUCCESS) {
         return code;
@@ -583,31 +603,33 @@
 }
 
 
-Code Cellular::setDns(const std::string& primary, const std::string& secondary) {
+Code Cellular::setDns(const std::string& primary, const std::string& secondary)
+{
     return sendBasicCommand("AT#DNS=1," + primary + "," + secondary, 1000);
 }
 
-bool Cellular::ping(const std::string& address) {
+bool Cellular::ping(const std::string& address)
+{
     char buffer[256] = {0};
     Code code;
-    
+
     code = sendBasicCommand("AT#PINGREMOTE=\"" + address + "\"", 1000);
     if (code != SUCCESS) {
         return false;
     }
-    
+
     sprintf(buffer, "AT#PINGNUM=%d", 1);
     code = sendBasicCommand(buffer , 1000);
     if (code != SUCCESS) {
         return false;
     }
-    
+
     sprintf(buffer, "AT#PINGDELAY=%d", PINGDELAY);
     code = sendBasicCommand(buffer , 1000);
     if (code != SUCCESS) {
         return false;
     }
-    
+
     std::string response;
     for (int i = 0; i < PINGNUM; i++) {
         response = sendCommand("AT#PING", PINGDELAY * 1000);
@@ -618,27 +640,29 @@
     return false;
 }
 
-Code Cellular::setSocketCloseable(bool enabled) {
+Code Cellular::setSocketCloseable(bool enabled)
+{
     if(socketCloseable == enabled) {
-        return SUCCESS;    
+        return SUCCESS;
     }
-    
+
     if(socketOpened) {
-        printf("[ERROR] socket is already opened. Can not set closeable\r\n");    
+        printf("[ERROR] socket is already opened. Can not set closeable\r\n");
         return ERROR;
     }
-    
+
     socketCloseable = enabled;
-    
+
     return SUCCESS;
 }
 
-Code Cellular::sendSMS(const Sms& sms) {
+Code Cellular::sendSMS(const Sms& sms)
+{
     return sendSMS(sms.phoneNumber, sms.message);
 }
 
 Code Cellular::sendSMS(const std::string& phoneNumber, const std::string& message)
-{    
+{
     Code code = sendBasicCommand("AT+CMGF=1", 1000);
     if (code != SUCCESS) {
         return code;
@@ -659,30 +683,31 @@
     return SUCCESS;
 }
 
-std::vector<Cellular::Sms> Cellular::getReceivedSms() {
+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]\r\n", line.c_str());
-        if(line.find("+CMGL: ") == std::string::npos) {           
+        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 ...\r\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 ...\r\n", smsNumber);
             break;
@@ -694,7 +719,7 @@
             //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);
@@ -711,11 +736,13 @@
     return vSms;
 }
 
-Code Cellular::deleteOnlyReceivedReadSms() {
+Code Cellular::deleteOnlyReceivedReadSms()
+{
     return sendBasicCommand("AT+CMGD=1,1", 1000);
 }
 
-Code Cellular::deleteAllReceivedSms() {
+Code Cellular::deleteAllReceivedSms()
+{
     return sendBasicCommand("AT+CMGD=1,4", 1000);
 }
 
@@ -727,21 +754,21 @@
         return "";
     }
     if(socketOpened) {
-        printf("[ERROR] socket is open. Can not send AT commands\r\n");    
+        printf("[ERROR] socket is open. Can not send AT commands\r\n");
         return "";
     }
 
     io->rxClear();
     io->txClear();
     std::string result;
-    
+
     //Attempt to write command
     if(io->write(command.data(), command.size(), timeoutMillis) != command.size()) {
         //Failed to write command
         printf("[ERROR] failed to send command to radio within %d milliseconds\r\n", timeoutMillis);
         return "";
     }
-    
+
     //Send Escape Character
     if (esc != 0x00) {
         if(io->write(esc, timeoutMillis) != 1) {
@@ -764,7 +791,7 @@
         if(size > 0) {
             result.append(tmp, size);
         }
-        
+
         if(!started) {
             //In Echo Mode (Command will have echo'd + 2 characters for \r\n)
             if(result.size() > command.size() + 2) {
@@ -778,7 +805,7 @@
             done = true;
         }
     } while (!done);
-    
+
     return result;
 }