Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BufferedSerial
Dependents: ESP8266 xdot-passthru Lab_10 Lab9 ... more
Fork of ATParser by
Revision 10:553f9ffaf657, committed 2015-07-26
- Comitter:
- sam_grove
- Date:
- Sun Jul 26 21:53:28 2015 +0000
- Parent:
- 9:9bcb87c27208
- Child:
- 11:fd406d4c4227
- Commit message:
- Small changes
Changed in this revision
--- a/ATParser.cpp Mon Jul 20 21:28:39 2015 +0000
+++ b/ATParser.cpp Sun Jul 26 21:53:28 2015 +0000
@@ -17,97 +17,102 @@
* Parser for the AT command syntax
*
*/
-
+
#include "ATParser.h"
-
-// This can be defined to assist in debugging
-#define AT_ECHO 1
+#include "mbed_debug.h"
// getc/putc handling with timeouts
-int ATParser::putc(char c) {
+int ATParser::putc(char c)
+{
Timer timer;
timer.start();
-
+
while (true) {
- if (_serial->writeable())
+ if (_serial->writeable()) {
return _serial->putc(c);
-
- if (timer.read_ms() > _timeout)
+ }
+ if (timer.read_ms() > _timeout) {
return -1;
+ }
}
}
-int ATParser::getc() {
+int ATParser::getc()
+{
Timer timer;
timer.start();
-
+
while (true) {
- if (_serial->readable())
+ if (_serial->readable()) {
return _serial->getc();
-
- if (timer.read_ms() > _timeout)
+ }
+ if (timer.read_ms() > _timeout) {
return -1;
+ }
}
}
-void ATParser::flush() {
- while (_serial->readable())
+void ATParser::flush()
+{
+ while (_serial->readable()) {
_serial->getc();
+ }
}
// read/write handling with timeouts
-int ATParser::write(const char *data, int size) {
- int i;
- for (i = 0; i < size; i++) {
- if (putc(data[i]) < 0)
+int ATParser::write(const char *data, int size)
+{
+ int i = 0;
+ for ( ; i < size; i++) {
+ if (putc(data[i]) < 0) {
return -1;
+ }
}
-
return i;
}
-int ATParser::read(char *data, int size) {
- int i;
- for (i = 0; i < size; i++) {
+int ATParser::read(char *data, int size)
+{
+ int i = 0;
+ for ( ; i < size; i++) {
int c = getc();
- if (c < 0)
+ if (c < 0) {
return -1;
-
+ }
data[i] = c;
}
-
return i;
}
// printf/scanf handling
-int ATParser::vprintf(const char *format, va_list args) {
- if (vsprintf(_buffer, format, args) < 0)
+int ATParser::vprintf(const char *format, va_list args)
+{
+ if (vsprintf(_buffer, format, args) < 0) {
return false;
-
- int i;
- for (i = 0; _buffer[i]; i++) {
- if (putc(_buffer[i]) < 0)
+ }
+ int i = 0;
+ for ( ; _buffer[i]; i++) {
+ if (putc(_buffer[i]) < 0) {
return -1;
+ }
}
-
return i;
}
-int ATParser::vscanf(const char *format, va_list args) {
+int ATParser::vscanf(const char *format, va_list args)
+{
// Since format is const, we need to copy it into our buffer to
// add the line's null terminator and clobber value-matches with asterisks.
//
// We just use the beginning of the buffer to avoid unnecessary allocations.
int i = 0;
int offset = 0;
-
+
while (format[i]) {
- if (format[i] == '%' &&
- format[i+1] != '%' &&
- format[i+1] != '*') {
+ if (format[i] == '%' && format[i+1] != '%' && format[i+1] != '*') {
_buffer[offset++] = '%';
_buffer[offset++] = '*';
i++;
@@ -115,40 +120,40 @@
_buffer[offset++] = format[i++];
}
}
-
+
// Scanf has very poor support for catching errors
// fortunately, we can abuse the %n specifier to determine
// if the entire string was matched.
_buffer[offset++] = '%';
_buffer[offset++] = 'n';
_buffer[offset++] = 0;
-
+
// To workaround scanf's lack of error reporting, we actually
// make two passes. One checks the validity with the modified
- // format string that only stores the matched characters (%n).
+ // format string that only stores the matched characters (%n).
// The other reads in the actual matched values.
//
// We keep trying the match until we succeed or some other error
// derails us.
int j = 0;
-
+
while (true) {
// Ran out of space
- if (j+1 >= _buffer_size - offset)
+ if (j+1 >= _buffer_size - offset) {
return false;
-
+ }
// Recieve next character
int c = getc();
- if (c < 0)
+ if (c < 0) {
return -1;
-
+ }
_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 are matched
if (count == j) {
// Store the found results
@@ -160,30 +165,31 @@
// Command parsing with line handling
-bool ATParser::vsend(const char *command, va_list args) {
+bool ATParser::vsend(const char *command, va_list args)
+{
// Create and send command
- if (vsprintf(_buffer, command, args) < 0)
+ if (vsprintf(_buffer, command, args) < 0) {
return false;
-
+ }
for (int i = 0; _buffer[i]; i++) {
- if (putc(_buffer[i]) < 0)
+ if (putc(_buffer[i]) < 0) {
return false;
+ }
}
-
+
// Finish with newline
for (int i = 0; _delimiter[i]; i++) {
- if (putc(_delimiter[i]) < 0)
+ if (putc(_delimiter[i]) < 0) {
return false;
+ }
}
-
-#ifdef AT_ECHO
- ::printf("AT> %s\r\n", _buffer);
-#endif
-
+
+ debug_if(at_echo, "AT> %s\r\n", _buffer);
return true;
}
-bool ATParser::vrecv(const char *response, va_list args) {
+bool ATParser::vrecv(const char *response, va_list args)
+{
// Iterate through each line in the expected response
while (response[0]) {
// Since response is const, we need to copy it into our buffer to
@@ -192,14 +198,12 @@
// We just use the beginning of the buffer to avoid unnecessary allocations.
int i = 0;
int offset = 0;
-
+
while (response[i]) {
if (memcmp(&response[i+1-_delim_size], _delimiter, _delim_size) == 0) {
i++;
break;
- } else if (response[i] == '%' &&
- response[i+1] != '%' &&
- response[i+1] != '*') {
+ } else if (response[i] == '%' && response[i+1] != '%' && response[i+1] != '*') {
_buffer[offset++] = '%';
_buffer[offset++] = '*';
i++;
@@ -207,73 +211,70 @@
_buffer[offset++] = response[i++];
}
}
-
+
// Scanf has very poor support for catching errors
// fortunately, we can abuse the %n specifier to determine
// if the entire string was matched.
_buffer[offset++] = '%';
_buffer[offset++] = 'n';
_buffer[offset++] = 0;
-
+
// To workaround scanf's lack of error reporting, we actually
// make two passes. One checks the validity with the modified
- // format string that only stores the matched characters (%n).
+ // format string that only stores the matched characters (%n).
// The other reads in the actual matched values.
//
// We keep trying the match until we succeed or some other error
// derails us.
int j = 0;
-
+
while (true) {
// Ran out of space
- if (j+1 >= _buffer_size - offset)
+ if (j+1 >= _buffer_size - offset) {
return false;
-
+ }
// Recieve next character
int c = getc();
- if (c < 0)
+ 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 are matched
if (count == j) {
-#ifdef AT_ECHO
- ::printf("AT= %s\r\n", _buffer+offset);
-#endif
+ debug_if(at_echo, "AT= %s\r\n", _buffer+offset);
// Reuse the front end of the buffer
memcpy(_buffer, response, i);
_buffer[i] = 0;
-
+
// Store the found results
vsscanf(_buffer+offset, _buffer, args);
-
+
// Jump to next line and continue parsing
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
+ debug_if(at_echo, "AT< %s", _buffer+offset);
j = 0;
}
}
}
-
+
return true;
}
// Mapping to vararg functions
-int ATParser::printf(const char *format, ...) {
+int ATParser::printf(const char *format, ...)
+{
va_list args;
va_start(args, format);
int res = vprintf(format, args);
@@ -281,7 +282,8 @@
return res;
}
-int ATParser::scanf(const char *format, ...) {
+int ATParser::scanf(const char *format, ...)
+{
va_list args;
va_start(args, format);
int res = vscanf(format, args);
@@ -289,7 +291,8 @@
return res;
}
-bool ATParser::send(const char *command, ...) {
+bool ATParser::send(const char *command, ...)
+{
va_list args;
va_start(args, command);
bool res = vsend(command, args);
@@ -297,7 +300,8 @@
return res;
}
-bool ATParser::recv(const char *response, ...) {
+bool ATParser::recv(const char *response, ...)
+{
va_list args;
va_start(args, response);
bool res = vrecv(response, args);
--- a/ATParser.h Mon Jul 20 21:28:39 2015 +0000
+++ b/ATParser.h Sun Jul 26 21:53:28 2015 +0000
@@ -17,13 +17,12 @@
* Parser for the AT command syntax
*
*/
-
+
#include "mbed.h"
#include <cstdarg>
-
#include "BufferedSerial.h"
-
+
/**
* Parser class for parsing AT commands
*
@@ -41,17 +40,19 @@
* at.recv("OK");
* @endcode
*/
-class ATParser {
+class ATParser
+{
private:
// Serial information
BufferedSerial *_serial;
int _buffer_size;
char *_buffer;
int _timeout;
-
+
// Parsing information
const char *_delimiter;
int _delim_size;
+ uint8_t at_echo;
public:
/**
@@ -62,22 +63,22 @@
* @param timeout timeout of the connection
* @param delimiter string of characters to use as line delimiters
*/
- ATParser(BufferedSerial *serial, const char *delimiter = "\r\n",
- int buffer_size = 256, int timeout = 8000) :
- _serial(serial),
- _buffer_size(buffer_size) {
+ ATParser(BufferedSerial &serial, const char *delimiter = "\r\n", int buffer_size = 256, int timeout = 8000, uint8_t echo = 0) :
+ _serial(&serial),
+ _buffer_size(buffer_size) {
_buffer = new char[buffer_size];
setTimeout(timeout);
setDelimiter(delimiter);
+ setEcho(echo);
}
-
+
/**
* Destructor
*/
~ATParser() {
delete [] _buffer;
}
-
+
/**
* Allows timeout to be changed between commands
*
@@ -86,7 +87,7 @@
void setTimeout(int timeout) {
_timeout = timeout;
}
-
+
/**
* Sets string of characters to use as line delimiters
*
@@ -98,19 +99,28 @@
}
/**
+ * Allows echo to be on or off
+ *
+ * @param echo 1 for echo and 0 turns it off
+ */
+ void setEcho(uint8_t echo) {
+ at_echo = (echo) ? 1 : 0;
+ }
+
+ /**
* Sends an AT command
*
* Sends a formatted command using printf style formatting
* @see ::printf
*
- * @param command printf-like format string of command to send which
+ * @param command printf-like format string of command to send which
* is appended with the specified delimiter
* @param ... all printf-like arguments to insert into command
* @return true only if command is successfully sent
*/
bool send(const char *command, ...);
bool vsend(const char *command, va_list args);
-
+
/**
* Recieve an AT response
*
@@ -127,23 +137,23 @@
*/
bool recv(const char *response, ...);
bool vrecv(const char *response, va_list args);
-
- /**
+
+ /**
* Write a single byte to the underlying stream
*
* @param c The byte to write
* @return The byte that was written or -1 during a timeout
*/
int putc(char c);
-
- /**
+
+ /**
* Get a single byte from the underlying stream
*
* @return The byte that was read or -1 during a timeout
*/
int getc();
-
- /**
+
+ /**
* Write an array of bytes to the underlying stream
*
* @param data the array of bytes to write
@@ -151,8 +161,8 @@
* @return number of bytes written or -1 on failure
*/
int write(const char *data, int size);
-
- /**
+
+ /**
* Read an array of bytes from the underlying stream
*
* @param data the destination for the read bytes
@@ -160,7 +170,7 @@
* @return number of bytes read or -1 on failure
*/
int read(char *data, int size);
-
+
/**
* Direct printf to underlying stream
* @see ::printf
@@ -171,7 +181,7 @@
*/
int printf(const char *format, ...);
int vprintf(const char *format, va_list args);
-
+
/**
* Direct scanf on underlying stream
* @see ::scanf
@@ -182,7 +192,7 @@
*/
int scanf(const char *format, ...);
int vscanf(const char *format, va_list args);
-
+
/**
* Flushes the underlying stream
*/
--- a/BufferedSerial.lib Mon Jul 20 21:28:39 2015 +0000 +++ b/BufferedSerial.lib Sun Jul 26 21:53:28 2015 +0000 @@ -1,1 +1,1 @@ -http://developer.mbed.org/users/sam_grove/code/BufferedSerial/#9ee15ae3d1a3 +http://developer.mbed.org/users/sam_grove/code/BufferedSerial/#779304f9c5d2
