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

Files at this revision

API Documentation at this revision

Comitter:
sgodinez
Date:
Mon Dec 30 18:55:48 2013 +0000
Parent:
93:aa7a48e65974
Child:
97:5e65d8f334d5
Commit message:
Fixed mem leak. Improved robustness. Automated Tcp Socket Test.

Changed in this revision

cellular/Cellular.cpp Show annotated file Show diff for this revision Revisions of this file
io/MTSSerialFlowControl.cpp Show annotated file Show diff for this revision Revisions of this file
tests/test_TCP_Socket.h Show annotated file Show diff for this revision Revisions of this file
--- a/cellular/Cellular.cpp	Fri Dec 27 23:55:18 2013 +0000
+++ b/cellular/Cellular.cpp	Mon Dec 30 18:55:48 2013 +0000
@@ -14,12 +14,45 @@
     return instance;
 }
 
+Cellular::Cellular(MTSBufferedIO* io)
+    : io(io)
+    , echoMode(true)
+    , pppConnected(false)
+    , mode(TCP)
+    , socketOpened(false)
+    , socketCloseable(true)
+    , local_port(0)
+    , host_port(0)
+    , dcd(NULL)
+    , dtr(NULL)
+{
+}
+
+Cellular::~Cellular()
+{
+    if (dtr != NULL) {
+        dtr->write(1);
+    }
+    
+    delete dcd;
+    delete dtr;
+}
 
 bool Cellular::init(MTSBufferedIO* io, PinName DCD, PinName DTR)
 {
     if (io == NULL) {
         return false;
     }
+    
+    if(dcd) {
+        delete dcd;
+        dcd = NULL;    
+    }
+    if(dtr) {
+        delete dtr;
+        dtr = NULL;
+    }
+    
     if (DCD != NC) {
         // the radio will raise and lower this line
         dcd = new DigitalIn(DCD); //PTA4 - KL46
@@ -32,27 +65,10 @@
         dtr->write(0);
     }
     instance->io = io;
-    return true;
+    
+    return (test() == SUCCESS);
 }
 
-Cellular::Cellular(MTSBufferedIO* io)
-    : io(io)
-    , echoMode(true)
-    , pppConnected(false)
-    , mode(TCP)
-    , socketOpened(false)
-    , socketCloseable(true)
-    , local_port(0)
-    , host_port(0)
-{
-}
-
-Cellular::~Cellular()
-{
-    if (dtr != NULL) {
-        dtr->write(1);
-    }
-}
 
 bool Cellular::connect()
 {
@@ -61,31 +77,43 @@
         return true;
     }
 
-    //Run Test first to validate a good state
+    //Check if already connected
     if(isConnected()) {
         return true;
     }
+    
+    Timer tmr;
+    
+    //Check Registration: AT+CREG? == 0,1
+    tmr.start();
+    do {
+        Registration registration = getRegistration();
+        if(registration != REGISTERED) {
+            printf("[WARNING] Not Registered [%d] ... waiting\r\n", (int)registration);
+            wait(1);
+        } else {
+            break;
+        }
+    } while(tmr.read() < 30);
 
     //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);
-    }
+    tmr.reset();
+    do {
+        int rssi = getSignalStrength();
+        printf("[DEBUG] Signal strength: %d\r\n", rssi);
+        if(rssi == 99) {
+           printf("[WARNING] No Signal ... waiting\r\n");
+           wait(1);
+        } else {
+            break;   
+        }
+    } while(tmr.read() < 30);    
 
     //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());
-//    }
-
     if(pppResult.find("Ok_Info_GprsActivation") != std::string::npos) {
         if(parts.size() >= 2) {
             local_address = parts[1];
@@ -160,16 +188,15 @@
 {
     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
         if(host_address != address || host_port != port || this->mode != mode) {
             if(this->mode == TCP) {
-                printf("[ERROR] TCP socket already opened (%s:%d)\r\n", host_address.c_str(), host_port);
+                printf("[ERROR] TCP socket already opened [%s:%d]\r\n", host_address.c_str(), host_port);
             } else {
-                printf("[ERROR] UDP socket already opened (%s:%d)\r\n", host_address.c_str(), host_port);
+                printf("[ERROR] UDP socket already opened [%s:%d]\r\n", host_address.c_str(), host_port);
             }
             return false;
         }
@@ -184,7 +211,6 @@
         return false;
     }
 
-
     //3) Check PPP connection
     if(!isConnected()) {
         printf("[ERROR] PPP not established.  Attempting to connect\r\n");
@@ -195,7 +221,7 @@
             printf("[DEBUG] PPP connection established\r\n");
         }
     }
-
+    
     //Set Local Port
     if(local_port != 0) {
         //Attempt to set local port
@@ -241,8 +267,6 @@
         printf("[ERROR] Host address could not be set\r\n");
     }
 
-
-
     // Try and Connect
     std::string sMode;
     std::string sOpenSocketCmd;
@@ -253,6 +277,7 @@
         sOpenSocketCmd = "AT#OUDP";
         sMode = "UDP";
     }
+    
     string response = sendCommand(sOpenSocketCmd, 30000);
     if (response.find("Ok_Info_WaitingForData") != string::npos) {
         printf("[INFO] Opened %s Socket [%s:%d]\r\n", sMode.c_str(), address.c_str(), port);
@@ -466,11 +491,11 @@
 unsigned int Cellular::readable()
 {
     if(io == NULL) {
-        printf("[ERROR] MTSBufferedIO not set\r\n");
+        printf("[WARNING] MTSBufferedIO not set\r\n");
         return 0;
     }
-    if(!socketOpened) {
-        printf("[ERROR] Socket is not open\r\n");
+    if(!socketOpened && !io->readable()) {
+        printf("[WARNING] Socket is not open\r\n");
         return 0;
     }
     return io->readable();
@@ -479,11 +504,11 @@
 unsigned int Cellular::writeable()
 {
     if(io == NULL) {
-        printf("[ERROR] MTSBufferedIO not set\r\n");
+        printf("[WARNING] MTSBufferedIO not set\r\n");
         return 0;
     }
     if(!socketOpened) {
-        printf("[ERROR] Socket is not open\r\n");
+        printf("[WARNING] Socket is not open\r\n");
         return 0;
     }
 
@@ -503,16 +528,26 @@
 
 Code Cellular::test()
 {
-    Code code = sendBasicCommand("AT", 1000);
+    bool basicRadioComms = false;
+    Code code;
+    Timer tmr;
+    tmr.start();
+    do {
+        printf("[DEBUG] Attempting basic radio communication\r\n");
+        code = sendBasicCommand("AT", 1000);
+        if(code == SUCCESS) {
+            basicRadioComms = true;
+            break;   
+        } else {
+            wait(1);   
+        }
+    } while(tmr.read() < 15);
 
-    if(code != SUCCESS) {
-        printf("[Error] Failed basic AT command");
-        return code;
+    if(!basicRadioComms) {
+        printf("[ERROR] Unable to communicate with the radio\r\n");
+        return FAILURE;
     }
-
-    //AT#VSTATE != "CHECKING"
-
-    //AT#GPRSMODE ==
+    
     return SUCCESS;
 }
 
@@ -545,7 +580,7 @@
 
 Cellular::Registration Cellular::getRegistration()
 {
-    string response = sendCommand("AT+CREG?", 1000);
+    string response = sendCommand("AT+CREG?", 5000);
     if (response.find("OK") == string::npos) {
         return UNKNOWN;
     }
@@ -571,25 +606,6 @@
     return UNKNOWN;
 }
 
-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");
-        return ERROR;
-    }
-
-    string response = sendCommand(command, timeoutMillis, esc);
-    if (response.size() == 0) {
-        return NO_RESPONSE;
-    } else if (response.find("OK") != string::npos) {
-        return SUCCESS;
-    } else if (response.find("ERROR") != string::npos) {
-        return ERROR;
-    } else {
-        return FAILURE;
-    }
-}
-
 Code Cellular::setApn(const std::string& apn)
 {
     Code code = sendBasicCommand("AT#APNSERV=\"" + apn + "\"", 1000);
@@ -744,6 +760,24 @@
     return sendBasicCommand("AT+CMGD=1,4", 1000);
 }
 
+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");
+        return ERROR;
+    }
+
+    string response = sendCommand(command, timeoutMillis, esc);
+    if (response.size() == 0) {
+        return NO_RESPONSE;
+    } else if (response.find("OK") != string::npos) {
+        return SUCCESS;
+    } else if (response.find("ERROR") != string::npos) {
+        return ERROR;
+    } else {
+        return FAILURE;
+    }
+}
 
 string Cellular::sendCommand(const std::string& command, unsigned int timeoutMillis, char esc)
 {
--- a/io/MTSSerialFlowControl.cpp	Fri Dec 27 23:55:18 2013 +0000
+++ b/io/MTSSerialFlowControl.cpp	Mon Dec 30 18:55:48 2013 +0000
@@ -35,7 +35,11 @@
 void MTSSerialFlowControl::handleRead()
 {
     while (serial.readable()) {
-        rxBuffer.write(serial.getc());
+        char byte = serial.getc();
+        if(rxBuffer.write(byte) != 1) {
+            printf("[ERROR] Serial Rx Byte Dropped [%c][%02X]\r\n", byte, byte);
+            notifyStopSending();
+        }
         if (rxBuffer.size() > highThreshold) {
             notifyStopSending();
         }
--- a/tests/test_TCP_Socket.h	Fri Dec 27 23:55:18 2013 +0000
+++ b/tests/test_TCP_Socket.h	Mon Dec 30 18:55:48 2013 +0000
@@ -2,6 +2,30 @@
 #define _TEST_TCP_SOCKET_H_
 
 using namespace mts;
+const char PATTERN_LINE1[] = "abcdefghijklmnopqrstuvwzyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()[]{}|";
+const char PATTERN[] =  "abcdefghijklmnopqrstuvwzyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()[]{}|\r\n"
+                        "abcdefghijklmnopqrstuvwzyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()[]{}/\r\n"
+                        "abcdefghijklmnopqrstuvwzyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()[]{}-\r\n"
+                        "abcdefghijklmnopqrstuvwzyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()[]{}\\\r\n"
+                        "abcdefghijklmnopqrstuvwzyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()[]{}|\r\n"
+                        "abcdefghijklmnopqrstuvwzyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()[]{}/\r\n"
+                        "abcdefghijklmnopqrstuvwzyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()[]{}-\r\n"
+                        "abcdefghijklmnopqrstuvwzyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()[]{}\\\r\n"
+                        "abcdefghijklmnopqrstuvwzyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()[]{}*";
+                        
+                        
+const char MENU[] =     "1       send ascii pattern until keypress\r\n"
+                        "2       send ascii pattern (numbered)\r\n"
+                        "3       send pattern and close socket\r\n"
+                        "4       send [ETX] and wait for keypress\r\n"
+                        "5       send [DLE] and wait for keypress\r\n"
+                        "6       send all hex values (00-FF)\r\n"
+                        "q       quit\r\n"
+                        ">:\r\n";
+                        
+const char WELCOME[] =  "Connected to: TCP test server";
+
+bool testTcpSocketIteration();
 
 void testTcpSocket() {
     Code code;
@@ -39,54 +63,15 @@
         printf("Error during TCP socket open [%s:%d]\r\n", TEST_SERVER.c_str(), TEST_PORT);
     }
     
-    printf("Receiving Data (timeout = 15 seconds)\r\n");
-    Timer tmr;
-    int bytesRead = 0;
-    const int size = 1024;
-    char data[size] = { 0 };
-    tmr.start();
-    do {
-        int status = Cellular::getInstance()->read(&data[bytesRead], size - bytesRead, 1000);
-        if(status != -1) {
-            bytesRead += status;
-        } else {
-            printf("Error reading from socket\r\n");
-            data[bytesRead] = '\0';
-            break;
-        }
-        printf("Total bytes read %d\r\n", bytesRead);
-    } while (tmr.read_ms() <= 15000 && bytesRead < size);
-   
-    printf("READ: [%d] [%s]\r\n", bytesRead, data);
+    //Find Welcome Message and Menu
     
-        
-    printf("Waiting 10 seconds\r\n");
-    wait(10);
-    
-    printf("Writing to socket\r\n");
-    sprintf(data, "3\r\n");
-    int bytesWritten = Cellular::getInstance()->write(data, 4, 10000);
-    if(bytesWritten == 4) {
-        printf("Successfully wrote 'q'\r\n");
-    } else {
-        printf("Failed to write 'q'\r\n");   
+    int count = 0;
+    while(testTcpSocketIteration()) {
+        count++;
+        printf("Successful Iterations: %d\r\n", count);
     }
     
-    bytesRead = 0;
-    tmr.start();
-    do {
-        int status = Cellular::getInstance()->read(&data[bytesRead], size - bytesRead, 1000);
-        if(status != -1) {
-            bytesRead += status;
-        } else {
-            printf("Error reading from socket\r\n");
-            data[bytesRead] = '\0';
-            break;
-        }
-        printf("Total bytes read %d\r\n", bytesRead);
-    } while (tmr.read_ms() <= 15000 && bytesRead < size);
-    printf("READ: [%d] [%s]\r\n", bytesRead, data);
-   
+    
     printf("Closing socket\r\n");
     Cellular::getInstance()->close();
     
@@ -96,4 +81,102 @@
     Cellular::getInstance()->disconnect();   
 }
 
+bool testTcpSocketIteration() {
+    
+    Timer tmr;
+    int bytesRead = 0;
+    const int bufferSize = 1024;
+    char buffer[bufferSize] = { 0 };
+    std::string result;
+    
+    printf("Receiving Data\r\n");
+    tmr.start();
+    do {
+        int size = Cellular::getInstance()->read(buffer, bufferSize, 1000);
+        if(size != -1) {
+            result.append(buffer, size);
+        } else {
+            printf("Error reading from socket\r\n");
+            return false;
+        }
+        printf("Total bytes read %d\r\n", result.size());
+    } while (tmr.read() <= 15 && bytesRead < bufferSize);
+   
+    printf("READ: [%d] [%s]\r\n", bytesRead, result.c_str());
+    
+    size_t pos = result.find(PATTERN_LINE1);
+    if(pos != std::string::npos) {
+        //compare buffers
+        int patternSize = sizeof(PATTERN) - 1;
+        const char* ptr = &result.data()[pos];
+        bool match = true;
+        for(int i = 0; i < patternSize; i++) {
+            if(PATTERN[i] != ptr[i]) {
+                printf("1ST PATTERN DOESN'T MATCH AT [%d]\r\n", i);
+                printf("PATTERN [%02X]  BUFFER [%02X]\r\n", PATTERN[i], ptr[i]);
+                match = false;
+                break;   
+            }
+        }
+        if(match) {
+            printf("FOUND 1ST PATTERN\r\n");   
+        }
+        
+        pos = result.find(PATTERN_LINE1, pos + patternSize);
+        if(pos != std::string::npos) {
+            //compare buffers
+            ptr = &result.data()[pos];
+            match = true;
+            for(int i = 0; i < patternSize; i++) {
+                if(PATTERN[i] != ptr[i]) {
+                    printf("2ND PATTERN DOESN'T MATCH AT [%d]\r\n", i);
+                    printf("PATTERN [%02X]  BUFFER [%02X]\r\n", PATTERN[i], ptr[i]);
+                    match = false;
+                    break;   
+                }
+            }
+            if(match) {
+                printf("FOUND 2ND PATTERN\r\n");   
+            }
+        }
+    }
+    
+    
+
+    result.clear();
+    
+    printf("Writing to socket: 2\r\n");
+    if(Cellular::getInstance()->write("2\r\n", 3, 10000) == 3) {
+        printf("Successfully wrote '2'\r\n");
+    } else {
+        printf("Failed to write '2'\r\n");   
+        return false;
+    }
+    printf("Expecting 'how many ? >:\r\n");
+    bytesRead = Cellular::getInstance()->read(buffer, bufferSize, 10000);
+    if(bytesRead != -1) {
+        result.append(buffer, bytesRead);
+        printf("READ: [%d] [%s]\r\n", bytesRead, result.c_str());
+        if(result.find("how many") != std::string::npos) {
+            printf("Successfully found 'how many'\r\n");   
+            printf("Writing to socket: 2\r\n");
+            if(Cellular::getInstance()->write("2\r\n", 3, 10000) == 3) {
+                printf("Successfully wrote '2'\r\n");
+            } else {
+                printf("Failed to write '2'\r\n");   
+                return false;
+            }
+        } else {
+            printf("Missing second option to menu item 2\r\n");
+        }
+    } else {
+        printf("Error reading from socket\r\n");
+        return false;
+    }
+    
+    
+    return true;
+}
+
+
 #endif