Parser for AT commands and similar protocols
Fork of ATParser by
ATParser.h@16:8f98e042b9b4, 2017-05-22 (annotated)
- Committer:
- Raffaello
- Date:
- Mon May 22 18:05:51 2017 +0000
- Revision:
- 16:8f98e042b9b4
- Parent:
- 12:7d3c3f7ce928
- Child:
- 17:f395d107f15e
Fixed read string from buffer. Now "%s" works.; Added different initialization start delimiter
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Christopher Haster |
12:7d3c3f7ce928 | 1 | /* Copyright (c) 2015 ARM Limited |
Christopher Haster |
12:7d3c3f7ce928 | 2 | * |
Christopher Haster |
12:7d3c3f7ce928 | 3 | * Licensed under the Apache License, Version 2.0 (the "License"); |
Christopher Haster |
12:7d3c3f7ce928 | 4 | * you may not use this file except in compliance with the License. |
Christopher Haster |
12:7d3c3f7ce928 | 5 | * You may obtain a copy of the License at |
Christopher Haster |
12:7d3c3f7ce928 | 6 | * |
Christopher Haster |
12:7d3c3f7ce928 | 7 | * http://www.apache.org/licenses/LICENSE-2.0 |
Christopher Haster |
12:7d3c3f7ce928 | 8 | * |
Christopher Haster |
12:7d3c3f7ce928 | 9 | * Unless required by applicable law or agreed to in writing, software |
Christopher Haster |
12:7d3c3f7ce928 | 10 | * distributed under the License is distributed on an "AS IS" BASIS, |
Christopher Haster |
12:7d3c3f7ce928 | 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
Christopher Haster |
12:7d3c3f7ce928 | 12 | * See the License for the specific language governing permissions and |
Christopher Haster |
12:7d3c3f7ce928 | 13 | * limitations under the License. |
Christopher Haster |
12:7d3c3f7ce928 | 14 | * |
Christopher Haster |
12:7d3c3f7ce928 | 15 | * @section DESCRIPTION |
Christopher Haster |
12:7d3c3f7ce928 | 16 | * |
Christopher Haster |
12:7d3c3f7ce928 | 17 | * Parser for the AT command syntax |
Christopher Haster |
12:7d3c3f7ce928 | 18 | * |
Christopher Haster |
12:7d3c3f7ce928 | 19 | */ |
Christopher Haster |
12:7d3c3f7ce928 | 20 | |
Christopher Haster |
12:7d3c3f7ce928 | 21 | #include "mbed.h" |
Christopher Haster |
12:7d3c3f7ce928 | 22 | #include <cstdarg> |
Christopher Haster |
12:7d3c3f7ce928 | 23 | #include "BufferedSerial.h" |
Christopher Haster |
12:7d3c3f7ce928 | 24 | |
Christopher Haster |
12:7d3c3f7ce928 | 25 | |
Christopher Haster |
12:7d3c3f7ce928 | 26 | /** |
Christopher Haster |
12:7d3c3f7ce928 | 27 | * Parser class for parsing AT commands |
Christopher Haster |
12:7d3c3f7ce928 | 28 | * |
Christopher Haster |
12:7d3c3f7ce928 | 29 | * Here are some examples: |
Christopher Haster |
12:7d3c3f7ce928 | 30 | * @code |
Christopher Haster |
12:7d3c3f7ce928 | 31 | * ATParser at = ATParser(serial, "\r\n"); |
Christopher Haster |
12:7d3c3f7ce928 | 32 | * int value; |
Christopher Haster |
12:7d3c3f7ce928 | 33 | * char buffer[100]; |
Christopher Haster |
12:7d3c3f7ce928 | 34 | * |
Christopher Haster |
12:7d3c3f7ce928 | 35 | * at.send("AT") && at.recv("OK"); |
Christopher Haster |
12:7d3c3f7ce928 | 36 | * at.send("AT+CWMODE=%d", 3) && at.recv("OK"); |
Christopher Haster |
12:7d3c3f7ce928 | 37 | * at.send("AT+CWMODE?") && at.recv("+CWMODE:%d\r\nOK", &value); |
Christopher Haster |
12:7d3c3f7ce928 | 38 | * at.recv("+IPD,%d:", &value); |
Christopher Haster |
12:7d3c3f7ce928 | 39 | * at.read(buffer, value); |
Christopher Haster |
12:7d3c3f7ce928 | 40 | * at.recv("OK"); |
Christopher Haster |
12:7d3c3f7ce928 | 41 | * @endcode |
Christopher Haster |
12:7d3c3f7ce928 | 42 | */ |
Christopher Haster |
12:7d3c3f7ce928 | 43 | class ATParser |
Christopher Haster |
12:7d3c3f7ce928 | 44 | { |
Christopher Haster |
12:7d3c3f7ce928 | 45 | private: |
Christopher Haster |
12:7d3c3f7ce928 | 46 | // Serial information |
Christopher Haster |
12:7d3c3f7ce928 | 47 | BufferedSerial *_serial; |
Christopher Haster |
12:7d3c3f7ce928 | 48 | int _buffer_size; |
Christopher Haster |
12:7d3c3f7ce928 | 49 | char *_buffer; |
Christopher Haster |
12:7d3c3f7ce928 | 50 | int _timeout; |
Christopher Haster |
12:7d3c3f7ce928 | 51 | |
Christopher Haster |
12:7d3c3f7ce928 | 52 | // Parsing information |
Raffaello | 16:8f98e042b9b4 | 53 | const char *_delimiter_send; |
Raffaello | 16:8f98e042b9b4 | 54 | const char *_delimiter_close; |
Raffaello | 16:8f98e042b9b4 | 55 | int _delim_size_send; |
Raffaello | 16:8f98e042b9b4 | 56 | int _delim_size_close; |
Raffaello | 16:8f98e042b9b4 | 57 | int _delim_check; |
Christopher Haster |
12:7d3c3f7ce928 | 58 | bool dbg_on; |
Christopher Haster |
12:7d3c3f7ce928 | 59 | |
Christopher Haster |
12:7d3c3f7ce928 | 60 | public: |
Christopher Haster |
12:7d3c3f7ce928 | 61 | /** |
Christopher Haster |
12:7d3c3f7ce928 | 62 | * Constructor |
Christopher Haster |
12:7d3c3f7ce928 | 63 | * |
Christopher Haster |
12:7d3c3f7ce928 | 64 | * @param serial serial interface to use for AT commands |
Christopher Haster |
12:7d3c3f7ce928 | 65 | * @param buffer_size size of internal buffer for transaction |
Christopher Haster |
12:7d3c3f7ce928 | 66 | * @param timeout timeout of the connection |
Christopher Haster |
12:7d3c3f7ce928 | 67 | * @param delimiter string of characters to use as line delimiters |
Christopher Haster |
12:7d3c3f7ce928 | 68 | */ |
Christopher Haster |
12:7d3c3f7ce928 | 69 | ATParser(BufferedSerial &serial, const char *delimiter = "\r\n", int buffer_size = 256, int timeout = 8000, bool debug = false) : |
Christopher Haster |
12:7d3c3f7ce928 | 70 | _serial(&serial), |
Christopher Haster |
12:7d3c3f7ce928 | 71 | _buffer_size(buffer_size) { |
Christopher Haster |
12:7d3c3f7ce928 | 72 | _buffer = new char[buffer_size]; |
Christopher Haster |
12:7d3c3f7ce928 | 73 | setTimeout(timeout); |
Christopher Haster |
12:7d3c3f7ce928 | 74 | setDelimiter(delimiter); |
Raffaello | 16:8f98e042b9b4 | 75 | setDelimiterSend(delimiter); |
Christopher Haster |
12:7d3c3f7ce928 | 76 | debugOn(debug); |
Christopher Haster |
12:7d3c3f7ce928 | 77 | } |
Christopher Haster |
12:7d3c3f7ce928 | 78 | |
Christopher Haster |
12:7d3c3f7ce928 | 79 | /** |
Christopher Haster |
12:7d3c3f7ce928 | 80 | * Destructor |
Christopher Haster |
12:7d3c3f7ce928 | 81 | */ |
Christopher Haster |
12:7d3c3f7ce928 | 82 | ~ATParser() { |
Christopher Haster |
12:7d3c3f7ce928 | 83 | delete [] _buffer; |
Christopher Haster |
12:7d3c3f7ce928 | 84 | } |
Christopher Haster |
12:7d3c3f7ce928 | 85 | |
Christopher Haster |
12:7d3c3f7ce928 | 86 | /** |
Christopher Haster |
12:7d3c3f7ce928 | 87 | * Allows timeout to be changed between commands |
Christopher Haster |
12:7d3c3f7ce928 | 88 | * |
Christopher Haster |
12:7d3c3f7ce928 | 89 | * @param timeout timeout of the connection |
Christopher Haster |
12:7d3c3f7ce928 | 90 | */ |
Christopher Haster |
12:7d3c3f7ce928 | 91 | void setTimeout(int timeout) { |
Christopher Haster |
12:7d3c3f7ce928 | 92 | _timeout = timeout; |
Christopher Haster |
12:7d3c3f7ce928 | 93 | } |
Christopher Haster |
12:7d3c3f7ce928 | 94 | |
Christopher Haster |
12:7d3c3f7ce928 | 95 | /** |
Christopher Haster |
12:7d3c3f7ce928 | 96 | * Sets string of characters to use as line delimiters |
Christopher Haster |
12:7d3c3f7ce928 | 97 | * |
Christopher Haster |
12:7d3c3f7ce928 | 98 | * @param delimiter string of characters to use as line delimiters |
Christopher Haster |
12:7d3c3f7ce928 | 99 | */ |
Christopher Haster |
12:7d3c3f7ce928 | 100 | void setDelimiter(const char *delimiter) { |
Raffaello | 16:8f98e042b9b4 | 101 | _delimiter_close = delimiter; |
Raffaello | 16:8f98e042b9b4 | 102 | _delim_size_close = strlen(delimiter); |
Christopher Haster |
12:7d3c3f7ce928 | 103 | } |
Christopher Haster |
12:7d3c3f7ce928 | 104 | |
Christopher Haster |
12:7d3c3f7ce928 | 105 | /** |
Raffaello | 16:8f98e042b9b4 | 106 | * Sets string of characters to use as line delimiters |
Raffaello | 16:8f98e042b9b4 | 107 | * |
Raffaello | 16:8f98e042b9b4 | 108 | * @param delimiter string of characters to use as line delimiters |
Raffaello | 16:8f98e042b9b4 | 109 | */ |
Raffaello | 16:8f98e042b9b4 | 110 | void setDelimiterSend(const char *delimiter) { |
Raffaello | 16:8f98e042b9b4 | 111 | _delimiter_send = delimiter; |
Raffaello | 16:8f98e042b9b4 | 112 | _delim_size_send = strlen(delimiter); |
Raffaello | 16:8f98e042b9b4 | 113 | } |
Raffaello | 16:8f98e042b9b4 | 114 | |
Raffaello | 16:8f98e042b9b4 | 115 | /** |
Christopher Haster |
12:7d3c3f7ce928 | 116 | * Allows echo to be on or off |
Christopher Haster |
12:7d3c3f7ce928 | 117 | * |
Christopher Haster |
12:7d3c3f7ce928 | 118 | * @param echo 1 for echo and 0 turns it off |
Christopher Haster |
12:7d3c3f7ce928 | 119 | */ |
Christopher Haster |
12:7d3c3f7ce928 | 120 | void debugOn(uint8_t on) { |
Christopher Haster |
12:7d3c3f7ce928 | 121 | dbg_on = (on) ? 1 : 0; |
Christopher Haster |
12:7d3c3f7ce928 | 122 | } |
Christopher Haster |
12:7d3c3f7ce928 | 123 | |
Christopher Haster |
12:7d3c3f7ce928 | 124 | /** |
Christopher Haster |
12:7d3c3f7ce928 | 125 | * Sends an AT command |
Christopher Haster |
12:7d3c3f7ce928 | 126 | * |
Christopher Haster |
12:7d3c3f7ce928 | 127 | * Sends a formatted command using printf style formatting |
Christopher Haster |
12:7d3c3f7ce928 | 128 | * @see ::printf |
Christopher Haster |
12:7d3c3f7ce928 | 129 | * |
Christopher Haster |
12:7d3c3f7ce928 | 130 | * @param command printf-like format string of command to send which |
Christopher Haster |
12:7d3c3f7ce928 | 131 | * is appended with the specified delimiter |
Christopher Haster |
12:7d3c3f7ce928 | 132 | * @param ... all printf-like arguments to insert into command |
Christopher Haster |
12:7d3c3f7ce928 | 133 | * @return true only if command is successfully sent |
Christopher Haster |
12:7d3c3f7ce928 | 134 | */ |
Christopher Haster |
12:7d3c3f7ce928 | 135 | bool send(const char *command, ...); |
Christopher Haster |
12:7d3c3f7ce928 | 136 | bool vsend(const char *command, va_list args); |
Christopher Haster |
12:7d3c3f7ce928 | 137 | |
Christopher Haster |
12:7d3c3f7ce928 | 138 | /** |
Christopher Haster |
12:7d3c3f7ce928 | 139 | * Recieve an AT response |
Christopher Haster |
12:7d3c3f7ce928 | 140 | * |
Christopher Haster |
12:7d3c3f7ce928 | 141 | * Recieves a formatted response using scanf style formatting |
Christopher Haster |
12:7d3c3f7ce928 | 142 | * @see ::scanf |
Christopher Haster |
12:7d3c3f7ce928 | 143 | * |
Christopher Haster |
12:7d3c3f7ce928 | 144 | * Responses are parsed line at a time using the specified delimiter. |
Christopher Haster |
12:7d3c3f7ce928 | 145 | * Any recieved data that does not match the response is ignored until |
Christopher Haster |
12:7d3c3f7ce928 | 146 | * a timeout occurs. |
Christopher Haster |
12:7d3c3f7ce928 | 147 | * |
Christopher Haster |
12:7d3c3f7ce928 | 148 | * @param response scanf-like format string of response to expect |
Christopher Haster |
12:7d3c3f7ce928 | 149 | * @param ... all scanf-like arguments to extract from response |
Christopher Haster |
12:7d3c3f7ce928 | 150 | * @return true only if response is successfully matched |
Christopher Haster |
12:7d3c3f7ce928 | 151 | */ |
Christopher Haster |
12:7d3c3f7ce928 | 152 | bool recv(const char *response, ...); |
Christopher Haster |
12:7d3c3f7ce928 | 153 | bool vrecv(const char *response, va_list args); |
Christopher Haster |
12:7d3c3f7ce928 | 154 | |
Christopher Haster |
12:7d3c3f7ce928 | 155 | /** |
Christopher Haster |
12:7d3c3f7ce928 | 156 | * Write a single byte to the underlying stream |
Christopher Haster |
12:7d3c3f7ce928 | 157 | * |
Christopher Haster |
12:7d3c3f7ce928 | 158 | * @param c The byte to write |
Christopher Haster |
12:7d3c3f7ce928 | 159 | * @return The byte that was written or -1 during a timeout |
Christopher Haster |
12:7d3c3f7ce928 | 160 | */ |
Christopher Haster |
12:7d3c3f7ce928 | 161 | int putc(char c); |
Christopher Haster |
12:7d3c3f7ce928 | 162 | |
Christopher Haster |
12:7d3c3f7ce928 | 163 | /** |
Christopher Haster |
12:7d3c3f7ce928 | 164 | * Get a single byte from the underlying stream |
Christopher Haster |
12:7d3c3f7ce928 | 165 | * |
Christopher Haster |
12:7d3c3f7ce928 | 166 | * @return The byte that was read or -1 during a timeout |
Christopher Haster |
12:7d3c3f7ce928 | 167 | */ |
Christopher Haster |
12:7d3c3f7ce928 | 168 | int getc(); |
Christopher Haster |
12:7d3c3f7ce928 | 169 | |
Christopher Haster |
12:7d3c3f7ce928 | 170 | /** |
Christopher Haster |
12:7d3c3f7ce928 | 171 | * Write an array of bytes to the underlying stream |
Christopher Haster |
12:7d3c3f7ce928 | 172 | * |
Christopher Haster |
12:7d3c3f7ce928 | 173 | * @param data the array of bytes to write |
Christopher Haster |
12:7d3c3f7ce928 | 174 | * @param size number of bytes to write |
Christopher Haster |
12:7d3c3f7ce928 | 175 | * @return number of bytes written or -1 on failure |
Christopher Haster |
12:7d3c3f7ce928 | 176 | */ |
Christopher Haster |
12:7d3c3f7ce928 | 177 | int write(const char *data, int size); |
Christopher Haster |
12:7d3c3f7ce928 | 178 | |
Christopher Haster |
12:7d3c3f7ce928 | 179 | /** |
Christopher Haster |
12:7d3c3f7ce928 | 180 | * Read an array of bytes from the underlying stream |
Christopher Haster |
12:7d3c3f7ce928 | 181 | * |
Christopher Haster |
12:7d3c3f7ce928 | 182 | * @param data the destination for the read bytes |
Christopher Haster |
12:7d3c3f7ce928 | 183 | * @param size number of bytes to read |
Christopher Haster |
12:7d3c3f7ce928 | 184 | * @return number of bytes read or -1 on failure |
Christopher Haster |
12:7d3c3f7ce928 | 185 | */ |
Christopher Haster |
12:7d3c3f7ce928 | 186 | int read(char *data, int size); |
Christopher Haster |
12:7d3c3f7ce928 | 187 | |
Christopher Haster |
12:7d3c3f7ce928 | 188 | /** |
Christopher Haster |
12:7d3c3f7ce928 | 189 | * Direct printf to underlying stream |
Christopher Haster |
12:7d3c3f7ce928 | 190 | * @see ::printf |
Christopher Haster |
12:7d3c3f7ce928 | 191 | * |
Christopher Haster |
12:7d3c3f7ce928 | 192 | * @param format format string to pass to printf |
Christopher Haster |
12:7d3c3f7ce928 | 193 | * @param ... arguments to printf |
Christopher Haster |
12:7d3c3f7ce928 | 194 | * @return number of bytes written or -1 on failure |
Christopher Haster |
12:7d3c3f7ce928 | 195 | */ |
Christopher Haster |
12:7d3c3f7ce928 | 196 | int printf(const char *format, ...); |
Christopher Haster |
12:7d3c3f7ce928 | 197 | int vprintf(const char *format, va_list args); |
Christopher Haster |
12:7d3c3f7ce928 | 198 | |
Christopher Haster |
12:7d3c3f7ce928 | 199 | /** |
Christopher Haster |
12:7d3c3f7ce928 | 200 | * Direct scanf on underlying stream |
Christopher Haster |
12:7d3c3f7ce928 | 201 | * @see ::scanf |
Christopher Haster |
12:7d3c3f7ce928 | 202 | * |
Christopher Haster |
12:7d3c3f7ce928 | 203 | * @param format format string to pass to scanf |
Christopher Haster |
12:7d3c3f7ce928 | 204 | * @param ... arguments to scanf |
Christopher Haster |
12:7d3c3f7ce928 | 205 | * @return number of bytes read or -1 on failure |
Christopher Haster |
12:7d3c3f7ce928 | 206 | */ |
Christopher Haster |
12:7d3c3f7ce928 | 207 | int scanf(const char *format, ...); |
Christopher Haster |
12:7d3c3f7ce928 | 208 | int vscanf(const char *format, va_list args); |
Christopher Haster |
12:7d3c3f7ce928 | 209 | |
Christopher Haster |
12:7d3c3f7ce928 | 210 | /** |
Christopher Haster |
12:7d3c3f7ce928 | 211 | * Flushes the underlying stream |
Christopher Haster |
12:7d3c3f7ce928 | 212 | */ |
Christopher Haster |
12:7d3c3f7ce928 | 213 | void flush(); |
Christopher Haster |
12:7d3c3f7ce928 | 214 | }; |
Christopher Haster |
12:7d3c3f7ce928 | 215 |