Parser for AT commands and similar protocols
Diff: ATParser.cpp
- 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;