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 Final_Project_2 Final_Project CHEN_Final_Project
Revision 12:7d3c3f7ce928, committed 2016-02-18
- Comitter:
- Christopher Haster
- Date:
- Thu Feb 18 15:59:15 2016 -0600
- Parent:
- 11:fd406d4c4227
- Child:
- 13:46a18ad08efc
- Commit message:
- Removed carriage returns
Changed in this revision
| ATParser.cpp | Show annotated file Show diff for this revision Revisions of this file |
| ATParser.h | Show annotated file Show diff for this revision Revisions of this file |
--- a/ATParser.cpp Mon Dec 28 05:37:44 2015 +0000
+++ b/ATParser.cpp Thu Feb 18 15:59:15 2016 -0600
@@ -1,310 +1,310 @@
-/* Copyright (c) 2015 ARM Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @section DESCRIPTION
- *
- * Parser for the AT command syntax
- *
- */
-
-#include "ATParser.h"
-#include "mbed_debug.h"
-
-
-// getc/putc handling with timeouts
-int ATParser::putc(char c)
-{
- Timer timer;
- timer.start();
-
- while (true) {
- if (_serial->writeable()) {
- return _serial->putc(c);
- }
- if (timer.read_ms() > _timeout) {
- return -1;
- }
- }
-}
-
-int ATParser::getc()
-{
- Timer timer;
- timer.start();
-
- while (true) {
- if (_serial->readable()) {
- return _serial->getc();
- }
- if (timer.read_ms() > _timeout) {
- return -1;
- }
- }
-}
-
-void ATParser::flush()
-{
- while (_serial->readable()) {
- _serial->getc();
- }
-}
-
-
-// read/write handling with timeouts
-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 = 0;
- for ( ; i < size; i++) {
- int c = getc();
- 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) {
- return false;
- }
- 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)
-{
- // 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] != '*') {
- _buffer[offset++] = '%';
- _buffer[offset++] = '*';
- i++;
- } else {
- _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).
- // 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) {
- return false;
- }
- // Recieve next character
- int c = getc();
- 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
- vsscanf(_buffer+offset, format, args);
- return j;
- }
- }
-}
-
-
-// Command parsing with line handling
-bool ATParser::vsend(const char *command, va_list args)
-{
- // 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;
- }
- }
-
- // Finish with newline
- for (int i = 0; _delimiter[i]; i++) {
- if (putc(_delimiter[i]) < 0) {
- return false;
- }
- }
-
- debug_if(dbg_on, "AT> %s\r\n", _buffer);
- return true;
-}
-
-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
- // 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 (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] != '*') {
- _buffer[offset++] = '%';
- _buffer[offset++] = '*';
- i++;
- } else {
- _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).
- // 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) {
- return false;
- }
- // 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 are matched
- if (count == j) {
- debug_if(dbg_on, "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) {
- debug_if(dbg_on, "AT< %s", _buffer+offset);
- j = 0;
- }
- }
- }
-
- return true;
-}
-
-
-// Mapping to vararg functions
-int ATParser::printf(const char *format, ...)
-{
- va_list args;
- va_start(args, format);
- int res = vprintf(format, args);
- va_end(args);
- return res;
-}
-
-int ATParser::scanf(const char *format, ...)
-{
- va_list args;
- va_start(args, format);
- int res = vscanf(format, args);
- va_end(args);
- return res;
-}
-
-bool ATParser::send(const char *command, ...)
-{
- va_list args;
- va_start(args, command);
- bool res = vsend(command, args);
- va_end(args);
- return res;
-}
-
-bool ATParser::recv(const char *response, ...)
-{
- va_list args;
- va_start(args, response);
- bool res = vrecv(response, args);
- va_end(args);
- return res;
-}
+/* Copyright (c) 2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @section DESCRIPTION
+ *
+ * Parser for the AT command syntax
+ *
+ */
+
+#include "ATParser.h"
+#include "mbed_debug.h"
+
+
+// getc/putc handling with timeouts
+int ATParser::putc(char c)
+{
+ Timer timer;
+ timer.start();
+
+ while (true) {
+ if (_serial->writeable()) {
+ return _serial->putc(c);
+ }
+ if (timer.read_ms() > _timeout) {
+ return -1;
+ }
+ }
+}
+
+int ATParser::getc()
+{
+ Timer timer;
+ timer.start();
+
+ while (true) {
+ if (_serial->readable()) {
+ return _serial->getc();
+ }
+ if (timer.read_ms() > _timeout) {
+ return -1;
+ }
+ }
+}
+
+void ATParser::flush()
+{
+ while (_serial->readable()) {
+ _serial->getc();
+ }
+}
+
+
+// read/write handling with timeouts
+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 = 0;
+ for ( ; i < size; i++) {
+ int c = getc();
+ 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) {
+ return false;
+ }
+ 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)
+{
+ // 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] != '*') {
+ _buffer[offset++] = '%';
+ _buffer[offset++] = '*';
+ i++;
+ } else {
+ _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).
+ // 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) {
+ return false;
+ }
+ // Recieve next character
+ int c = getc();
+ 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
+ vsscanf(_buffer+offset, format, args);
+ return j;
+ }
+ }
+}
+
+
+// Command parsing with line handling
+bool ATParser::vsend(const char *command, va_list args)
+{
+ // 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;
+ }
+ }
+
+ // Finish with newline
+ for (int i = 0; _delimiter[i]; i++) {
+ if (putc(_delimiter[i]) < 0) {
+ return false;
+ }
+ }
+
+ debug_if(dbg_on, "AT> %s\r\n", _buffer);
+ return true;
+}
+
+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
+ // 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 (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] != '*') {
+ _buffer[offset++] = '%';
+ _buffer[offset++] = '*';
+ i++;
+ } else {
+ _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).
+ // 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) {
+ return false;
+ }
+ // 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 are matched
+ if (count == j) {
+ debug_if(dbg_on, "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) {
+ debug_if(dbg_on, "AT< %s", _buffer+offset);
+ j = 0;
+ }
+ }
+ }
+
+ return true;
+}
+
+
+// Mapping to vararg functions
+int ATParser::printf(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ int res = vprintf(format, args);
+ va_end(args);
+ return res;
+}
+
+int ATParser::scanf(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ int res = vscanf(format, args);
+ va_end(args);
+ return res;
+}
+
+bool ATParser::send(const char *command, ...)
+{
+ va_list args;
+ va_start(args, command);
+ bool res = vsend(command, args);
+ va_end(args);
+ return res;
+}
+
+bool ATParser::recv(const char *response, ...)
+{
+ va_list args;
+ va_start(args, response);
+ bool res = vrecv(response, args);
+ va_end(args);
+ return res;
+}
--- a/ATParser.h Mon Dec 28 05:37:44 2015 +0000
+++ b/ATParser.h Thu Feb 18 15:59:15 2016 -0600
@@ -1,201 +1,201 @@
-/* Copyright (c) 2015 ARM Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @section DESCRIPTION
- *
- * Parser for the AT command syntax
- *
- */
-
-#include "mbed.h"
-#include <cstdarg>
-#include "BufferedSerial.h"
-
-
-/**
-* Parser class for parsing AT commands
-*
-* Here are some examples:
-* @code
-* ATParser at = ATParser(serial, "\r\n");
-* int value;
-* char buffer[100];
-*
-* at.send("AT") && at.recv("OK");
-* at.send("AT+CWMODE=%d", 3) && at.recv("OK");
-* at.send("AT+CWMODE?") && at.recv("+CWMODE:%d\r\nOK", &value);
-* at.recv("+IPD,%d:", &value);
-* at.read(buffer, value);
-* at.recv("OK");
-* @endcode
-*/
-class ATParser
-{
-private:
- // Serial information
- BufferedSerial *_serial;
- int _buffer_size;
- char *_buffer;
- int _timeout;
-
- // Parsing information
- const char *_delimiter;
- int _delim_size;
- bool dbg_on;
-
-public:
- /**
- * Constructor
- *
- * @param serial serial interface to use for AT commands
- * @param buffer_size size of internal buffer for transaction
- * @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, bool debug = false) :
- _serial(&serial),
- _buffer_size(buffer_size) {
- _buffer = new char[buffer_size];
- setTimeout(timeout);
- setDelimiter(delimiter);
- debugOn(debug);
- }
-
- /**
- * Destructor
- */
- ~ATParser() {
- delete [] _buffer;
- }
-
- /**
- * Allows timeout to be changed between commands
- *
- * @param timeout timeout of the connection
- */
- void setTimeout(int timeout) {
- _timeout = timeout;
- }
-
- /**
- * Sets string of characters to use as line delimiters
- *
- * @param delimiter string of characters to use as line delimiters
- */
- void setDelimiter(const char *delimiter) {
- _delimiter = delimiter;
- _delim_size = strlen(delimiter);
- }
-
- /**
- * Allows echo to be on or off
- *
- * @param echo 1 for echo and 0 turns it off
- */
- void debugOn(uint8_t on) {
- dbg_on = (on) ? 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
- * 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
- *
- * Recieves a formatted response using scanf style formatting
- * @see ::scanf
- *
- * Responses are parsed line at a time using the specified delimiter.
- * Any recieved data that does not match the response is ignored until
- * a timeout occurs.
- *
- * @param response scanf-like format string of response to expect
- * @param ... all scanf-like arguments to extract from response
- * @return true only if response is successfully matched
- */
- 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
- * @param size number of bytes to write
- * @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
- * @param size number of bytes to read
- * @return number of bytes read or -1 on failure
- */
- int read(char *data, int size);
-
- /**
- * Direct printf to underlying stream
- * @see ::printf
- *
- * @param format format string to pass to printf
- * @param ... arguments to printf
- * @return number of bytes written or -1 on failure
- */
- int printf(const char *format, ...);
- int vprintf(const char *format, va_list args);
-
- /**
- * Direct scanf on underlying stream
- * @see ::scanf
- *
- * @param format format string to pass to scanf
- * @param ... arguments to scanf
- * @return number of bytes read or -1 on failure
- */
- int scanf(const char *format, ...);
- int vscanf(const char *format, va_list args);
-
- /**
- * Flushes the underlying stream
- */
- void flush();
-};
-
+/* Copyright (c) 2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @section DESCRIPTION
+ *
+ * Parser for the AT command syntax
+ *
+ */
+
+#include "mbed.h"
+#include <cstdarg>
+#include "BufferedSerial.h"
+
+
+/**
+* Parser class for parsing AT commands
+*
+* Here are some examples:
+* @code
+* ATParser at = ATParser(serial, "\r\n");
+* int value;
+* char buffer[100];
+*
+* at.send("AT") && at.recv("OK");
+* at.send("AT+CWMODE=%d", 3) && at.recv("OK");
+* at.send("AT+CWMODE?") && at.recv("+CWMODE:%d\r\nOK", &value);
+* at.recv("+IPD,%d:", &value);
+* at.read(buffer, value);
+* at.recv("OK");
+* @endcode
+*/
+class ATParser
+{
+private:
+ // Serial information
+ BufferedSerial *_serial;
+ int _buffer_size;
+ char *_buffer;
+ int _timeout;
+
+ // Parsing information
+ const char *_delimiter;
+ int _delim_size;
+ bool dbg_on;
+
+public:
+ /**
+ * Constructor
+ *
+ * @param serial serial interface to use for AT commands
+ * @param buffer_size size of internal buffer for transaction
+ * @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, bool debug = false) :
+ _serial(&serial),
+ _buffer_size(buffer_size) {
+ _buffer = new char[buffer_size];
+ setTimeout(timeout);
+ setDelimiter(delimiter);
+ debugOn(debug);
+ }
+
+ /**
+ * Destructor
+ */
+ ~ATParser() {
+ delete [] _buffer;
+ }
+
+ /**
+ * Allows timeout to be changed between commands
+ *
+ * @param timeout timeout of the connection
+ */
+ void setTimeout(int timeout) {
+ _timeout = timeout;
+ }
+
+ /**
+ * Sets string of characters to use as line delimiters
+ *
+ * @param delimiter string of characters to use as line delimiters
+ */
+ void setDelimiter(const char *delimiter) {
+ _delimiter = delimiter;
+ _delim_size = strlen(delimiter);
+ }
+
+ /**
+ * Allows echo to be on or off
+ *
+ * @param echo 1 for echo and 0 turns it off
+ */
+ void debugOn(uint8_t on) {
+ dbg_on = (on) ? 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
+ * 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
+ *
+ * Recieves a formatted response using scanf style formatting
+ * @see ::scanf
+ *
+ * Responses are parsed line at a time using the specified delimiter.
+ * Any recieved data that does not match the response is ignored until
+ * a timeout occurs.
+ *
+ * @param response scanf-like format string of response to expect
+ * @param ... all scanf-like arguments to extract from response
+ * @return true only if response is successfully matched
+ */
+ 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
+ * @param size number of bytes to write
+ * @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
+ * @param size number of bytes to read
+ * @return number of bytes read or -1 on failure
+ */
+ int read(char *data, int size);
+
+ /**
+ * Direct printf to underlying stream
+ * @see ::printf
+ *
+ * @param format format string to pass to printf
+ * @param ... arguments to printf
+ * @return number of bytes written or -1 on failure
+ */
+ int printf(const char *format, ...);
+ int vprintf(const char *format, va_list args);
+
+ /**
+ * Direct scanf on underlying stream
+ * @see ::scanf
+ *
+ * @param format format string to pass to scanf
+ * @param ... arguments to scanf
+ * @return number of bytes read or -1 on failure
+ */
+ int scanf(const char *format, ...);
+ int vscanf(const char *format, va_list args);
+
+ /**
+ * Flushes the underlying stream
+ */
+ void flush();
+};
+