Parser for AT commands and similar protocols

Dependencies:   BufferedSerial

ATParser.h

Committer:
geky
Date:
2015-07-17
Revision:
6:51f1171b5ebc
Parent:
5:26bc9255b751
Child:
7:d1b193880af1

File content as of revision 6:51f1171b5ebc:

/* 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"

 
/**
* The ATParser class wraps information about the serial in use
*/
class ATParser {
private:
    // Serial information
    BufferedSerial *_serial;
    int _buffer_size;
    char *_buffer;
    int _timeout;
    
    // Parsing information
    const char *_delimiter;
    int _delim_size;    
    
    // Helper methods for reading/writing lines with 
    // timeout and buffer limitations
    bool _putline(const char *line);
    bool _getline(char *line, int size);

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, int buffer_size = 256, int timeout = 8000,
             const char *delimiter = "\r\n") :
            _serial(serial),
            _buffer_size(buffer_size) {
        _buffer = new char[buffer_size];
        setTimeout(timeout);
        setDelimiter(delimiter);
    }
    
    /**
    * 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);
    }
    
    /**
    * 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);
            
    /**
    * Issue AT commands
    *
    * Issues formatted commands and parses formatted responses.
    * A command call is identical to a send call followed by a recv call.
    * @see send, recv
    *
    * Here are some examples:
    * @code
    * at.command("AT", "OK");
    * at.command("AT+CWMODE=%d", "OK", 3);
    * at.command("AT+CWMODE?", "+CWMODE:%d\r\nOK", &result);
    * @endcode
    *
    * @param command printf-like format string of command to send
    * @param response scanf-like format string of response to expect
    * @param ... all printf-like arguments to insert into command followed by 
    *            all scanf-like arguments to extract from response
    * @return true only if response is successfully matched
    */
    bool command(const char *command, const char *response, ...);
    bool vcommand(const char *command, 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
    */
    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
    */
    int read(char *data, int size);
    
    /**
    * Flushes the underlying stream
    */
    void flush();
};