Parser for AT commands and similar protocols

Dependencies:   BufferedSerial

Revision:
7:d1b193880af1
Parent:
6:51f1171b5ebc
Child:
8:91515b168c70
--- a/ATParser.cpp	Fri Jul 17 21:00:23 2015 +0000
+++ b/ATParser.cpp	Mon Jul 20 18:23:54 2015 +0000
@@ -56,6 +56,7 @@
         _serial->getc();
 }
 
+
 // read/write handling with timeouts
 int ATParser::write(const char *data, int size) {
     int i;
@@ -84,10 +85,16 @@
 }
 
 
-// getline/putline handling with timeouts/bounds checking
-bool ATParser::_putline(const char *line) {    
-    for (int i = 0; line[i]; i++) {
-        if (putc(line[i]) < 0)
+// Command parsing with line handling
+bool ATParser::vsend(const char *command, va_list args) {
+    flush();
+    
+    // Create and send command
+    if (vsprintf(_buffer, command, args) < 0)
+        return false;
+        
+    for (int i = 0; _buffer[i]; i++) {
+        if (putc(_buffer[i]) < 0)
             return false;
     }
     
@@ -98,46 +105,8 @@
     }
     
 #ifdef AT_ECHO
-    printf("AT> %s\r\n", line);
+    printf("AT> %s\r\n", _buffer);
 #endif
-    
-    return true;
-}
-
-bool ATParser::_getline(char *line, int size) {
-    int i = 0;
-    
-    while (i < size) {
-        int c = getc();
-        if (c < 0)
-            return false;
-            
-        line[i++] = c;
-        
-        // Finish when we hit a newline
-        if (memcmp(&line[i-_delim_size], _delimiter, _delim_size) == 0) {
-            line[i-_delim_size] = 0;
-#ifdef AT_ECHO            
-            printf("AT< %s\r\n", line);
-#endif
-            return true;
-        }
-    }
-    
-    // Ran out of space
-    return false;
-}
-
-
-// Command parsing with line handling
-bool ATParser::vsend(const char *command, va_list args) {
-    flush();
-    
-    // Create and send command
-    if (vsprintf(_buffer, command, args) < 0)
-        return false;
-    if (!_putline(_buffer))
-        return false;
         
     return true;
 }
@@ -146,9 +115,9 @@
     // Iterate through each line in the expected response
     while (response[0]) {
         // Since response is const, we need to copy it into our buffer to
-        // add the line's null terminator and clobber value matches with asterisks.
+        // add the line's null terminator and clobber value-matches with asterisks.
         //
-        // We just use the beginning of the buffer to avoid unecessary allocations.
+        // We just use the beginning of the buffer to avoid unnecessary allocations.
         int i = 0;
         int offset = 0;
         
@@ -181,16 +150,26 @@
         //
         // We keep trying the match until we succeed or some other error
         // derails us.
-        while (true) {
-            // Recieve response
-            if (!_getline(_buffer+offset, _buffer_size-offset))
+        int j = 0;
+        
+        while (j+1 < _buffer_size - offset) {
+            // Recieve next character
+            int c = getc();
+            if (c < 0)
                 return false;
-            
+                
+            _buffer[offset + j++] = c;
+            _buffer[offset + j] = 0;
+        
+            // Check for match
             int count = -1;
             sscanf(_buffer+offset, _buffer, &count);
             
-            // We only succeed if all characters in the response is matched
-            if (count >= 0 && (_buffer+offset)[count] == 0) {
+            // We only succeed if all characters in the response are matched
+            if (count == j) {
+#ifdef AT_ECHO            
+                printf("AT= %s\r\n", _buffer+offset);
+#endif
                 // Reuse the front end of the buffer
                 memcpy(_buffer, response, i);
                 _buffer[i] = 0;
@@ -202,6 +181,14 @@
                 response += i;
                 break;
             }
+            
+            // Clear the buffer when we hit a newline
+            if (strcmp(&_buffer[offset + j-_delim_size], _delimiter) == 0) {
+#ifdef AT_ECHO            
+                printf("AT< %s", _buffer+offset);
+#endif
+                j = 0;
+            }
         }
     }
     
@@ -222,6 +209,7 @@
     return true;
 }
 
+
 // Mapping to vararg functions
 bool ATParser::send(const char *command, ...) {
     va_list args;