Committer:
ganlikun
Date:
Mon Oct 24 15:19:39 2022 +0000
Revision:
0:06036f8bee2d
11

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ganlikun 0:06036f8bee2d 1 /* Copyright (c) 2017 ARM Limited
ganlikun 0:06036f8bee2d 2 *
ganlikun 0:06036f8bee2d 3 * Licensed under the Apache License, Version 2.0 (the "License");
ganlikun 0:06036f8bee2d 4 * you may not use this file except in compliance with the License.
ganlikun 0:06036f8bee2d 5 * You may obtain a copy of the License at
ganlikun 0:06036f8bee2d 6 *
ganlikun 0:06036f8bee2d 7 * http://www.apache.org/licenses/LICENSE-2.0
ganlikun 0:06036f8bee2d 8 *
ganlikun 0:06036f8bee2d 9 * Unless required by applicable law or agreed to in writing, software
ganlikun 0:06036f8bee2d 10 * distributed under the License is distributed on an "AS IS" BASIS,
ganlikun 0:06036f8bee2d 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ganlikun 0:06036f8bee2d 12 * See the License for the specific language governing permissions and
ganlikun 0:06036f8bee2d 13 * limitations under the License.
ganlikun 0:06036f8bee2d 14 *
ganlikun 0:06036f8bee2d 15 * @section DESCRIPTION
ganlikun 0:06036f8bee2d 16 *
ganlikun 0:06036f8bee2d 17 * Parser for the AT command syntax
ganlikun 0:06036f8bee2d 18 *
ganlikun 0:06036f8bee2d 19 */
ganlikun 0:06036f8bee2d 20 #ifndef MBED_ATCMDPARSER_H
ganlikun 0:06036f8bee2d 21 #define MBED_ATCMDPARSER_H
ganlikun 0:06036f8bee2d 22
ganlikun 0:06036f8bee2d 23 #include "mbed.h"
ganlikun 0:06036f8bee2d 24 #include <cstdarg>
ganlikun 0:06036f8bee2d 25 #include "Callback.h"
ganlikun 0:06036f8bee2d 26
ganlikun 0:06036f8bee2d 27 /**
ganlikun 0:06036f8bee2d 28 * Parser class for parsing AT commands
ganlikun 0:06036f8bee2d 29 *
ganlikun 0:06036f8bee2d 30 * Here are some examples:
ganlikun 0:06036f8bee2d 31 * @code
ganlikun 0:06036f8bee2d 32 * UARTSerial serial = UARTSerial(D1, D0);
ganlikun 0:06036f8bee2d 33 * ATCmdParser at = ATCmdParser(&serial, "\r\n");
ganlikun 0:06036f8bee2d 34 * int value;
ganlikun 0:06036f8bee2d 35 * char buffer[100];
ganlikun 0:06036f8bee2d 36 *
ganlikun 0:06036f8bee2d 37 * at.send("AT") && at.recv("OK");
ganlikun 0:06036f8bee2d 38 * at.send("AT+CWMODE=%d", 3) && at.recv("OK");
ganlikun 0:06036f8bee2d 39 * at.send("AT+CWMODE?") && at.recv("+CWMODE:%d\r\nOK", &value);
ganlikun 0:06036f8bee2d 40 * at.recv("+IPD,%d:", &value);
ganlikun 0:06036f8bee2d 41 * at.read(buffer, value);
ganlikun 0:06036f8bee2d 42 * at.recv("OK");
ganlikun 0:06036f8bee2d 43 * @endcode
ganlikun 0:06036f8bee2d 44 */
ganlikun 0:06036f8bee2d 45
ganlikun 0:06036f8bee2d 46 namespace mbed {
ganlikun 0:06036f8bee2d 47
ganlikun 0:06036f8bee2d 48 class ATCmdParser : private NonCopyable<ATCmdParser>
ganlikun 0:06036f8bee2d 49 {
ganlikun 0:06036f8bee2d 50 private:
ganlikun 0:06036f8bee2d 51 // File handle
ganlikun 0:06036f8bee2d 52 // Not owned by ATCmdParser
ganlikun 0:06036f8bee2d 53 FileHandle *_fh;
ganlikun 0:06036f8bee2d 54
ganlikun 0:06036f8bee2d 55 int _buffer_size;
ganlikun 0:06036f8bee2d 56 char *_buffer;
ganlikun 0:06036f8bee2d 57 int _timeout;
ganlikun 0:06036f8bee2d 58
ganlikun 0:06036f8bee2d 59 // Parsing information
ganlikun 0:06036f8bee2d 60 const char *_output_delimiter;
ganlikun 0:06036f8bee2d 61 int _output_delim_size;
ganlikun 0:06036f8bee2d 62 char _in_prev;
ganlikun 0:06036f8bee2d 63 bool _dbg_on;
ganlikun 0:06036f8bee2d 64 bool _aborted;
ganlikun 0:06036f8bee2d 65
ganlikun 0:06036f8bee2d 66 struct oob {
ganlikun 0:06036f8bee2d 67 unsigned len;
ganlikun 0:06036f8bee2d 68 const char *prefix;
ganlikun 0:06036f8bee2d 69 mbed::Callback<void()> cb;
ganlikun 0:06036f8bee2d 70 oob *next;
ganlikun 0:06036f8bee2d 71 };
ganlikun 0:06036f8bee2d 72 oob *_oobs;
ganlikun 0:06036f8bee2d 73
ganlikun 0:06036f8bee2d 74 public:
ganlikun 0:06036f8bee2d 75
ganlikun 0:06036f8bee2d 76 /**
ganlikun 0:06036f8bee2d 77 * Constructor
ganlikun 0:06036f8bee2d 78 *
ganlikun 0:06036f8bee2d 79 * @param fh A FileHandle to a digital interface to use for AT commands
ganlikun 0:06036f8bee2d 80 * @param output_delimiter end of command line termination
ganlikun 0:06036f8bee2d 81 * @param buffer_size size of internal buffer for transaction
ganlikun 0:06036f8bee2d 82 * @param timeout timeout of the connection
ganlikun 0:06036f8bee2d 83 * @param debug turns on/off debug output for AT commands
ganlikun 0:06036f8bee2d 84 */
ganlikun 0:06036f8bee2d 85 ATCmdParser(FileHandle *fh, const char *output_delimiter = "\r",
ganlikun 0:06036f8bee2d 86 int buffer_size = 256, int timeout = 8000, bool debug = false)
ganlikun 0:06036f8bee2d 87 : _fh(fh), _buffer_size(buffer_size), _in_prev(0), _oobs(NULL)
ganlikun 0:06036f8bee2d 88 {
ganlikun 0:06036f8bee2d 89 _buffer = new char[buffer_size];
ganlikun 0:06036f8bee2d 90 set_timeout(timeout);
ganlikun 0:06036f8bee2d 91 set_delimiter(output_delimiter);
ganlikun 0:06036f8bee2d 92 debug_on(debug);
ganlikun 0:06036f8bee2d 93 }
ganlikun 0:06036f8bee2d 94
ganlikun 0:06036f8bee2d 95 /**
ganlikun 0:06036f8bee2d 96 * Destructor
ganlikun 0:06036f8bee2d 97 */
ganlikun 0:06036f8bee2d 98 ~ATCmdParser()
ganlikun 0:06036f8bee2d 99 {
ganlikun 0:06036f8bee2d 100 while (_oobs) {
ganlikun 0:06036f8bee2d 101 struct oob *oob = _oobs;
ganlikun 0:06036f8bee2d 102 _oobs = oob->next;
ganlikun 0:06036f8bee2d 103 delete oob;
ganlikun 0:06036f8bee2d 104 }
ganlikun 0:06036f8bee2d 105 delete[] _buffer;
ganlikun 0:06036f8bee2d 106 }
ganlikun 0:06036f8bee2d 107
ganlikun 0:06036f8bee2d 108 /**
ganlikun 0:06036f8bee2d 109 * Allows timeout to be changed between commands
ganlikun 0:06036f8bee2d 110 *
ganlikun 0:06036f8bee2d 111 * @param timeout timeout of the connection
ganlikun 0:06036f8bee2d 112 */
ganlikun 0:06036f8bee2d 113 void set_timeout(int timeout)
ganlikun 0:06036f8bee2d 114 {
ganlikun 0:06036f8bee2d 115 _timeout = timeout;
ganlikun 0:06036f8bee2d 116 }
ganlikun 0:06036f8bee2d 117
ganlikun 0:06036f8bee2d 118 /**
ganlikun 0:06036f8bee2d 119 * For backwards compatibility.
ganlikun 0:06036f8bee2d 120 *
ganlikun 0:06036f8bee2d 121 * Please use set_timeout(int) API only from now on.
ganlikun 0:06036f8bee2d 122 * Allows timeout to be changed between commands
ganlikun 0:06036f8bee2d 123 *
ganlikun 0:06036f8bee2d 124 * @param timeout timeout of the connection
ganlikun 0:06036f8bee2d 125 */
ganlikun 0:06036f8bee2d 126 MBED_DEPRECATED_SINCE("mbed-os-5.5.0", "Replaced with set_timeout for consistency")
ganlikun 0:06036f8bee2d 127 void setTimeout(int timeout)
ganlikun 0:06036f8bee2d 128 {
ganlikun 0:06036f8bee2d 129 set_timeout(timeout);
ganlikun 0:06036f8bee2d 130 }
ganlikun 0:06036f8bee2d 131
ganlikun 0:06036f8bee2d 132 /**
ganlikun 0:06036f8bee2d 133 * Sets string of characters to use as line delimiters
ganlikun 0:06036f8bee2d 134 *
ganlikun 0:06036f8bee2d 135 * @param output_delimiter string of characters to use as line delimiters
ganlikun 0:06036f8bee2d 136 */
ganlikun 0:06036f8bee2d 137 void set_delimiter(const char *output_delimiter)
ganlikun 0:06036f8bee2d 138 {
ganlikun 0:06036f8bee2d 139 _output_delimiter = output_delimiter;
ganlikun 0:06036f8bee2d 140 _output_delim_size = strlen(output_delimiter);
ganlikun 0:06036f8bee2d 141 }
ganlikun 0:06036f8bee2d 142
ganlikun 0:06036f8bee2d 143 /**
ganlikun 0:06036f8bee2d 144 * For backwards compatibility.
ganlikun 0:06036f8bee2d 145 *
ganlikun 0:06036f8bee2d 146 * Please use set_delimiter(const char *) API only from now on.
ganlikun 0:06036f8bee2d 147 * Sets string of characters to use as line delimiters
ganlikun 0:06036f8bee2d 148 *
ganlikun 0:06036f8bee2d 149 * @param output_delimiter string of characters to use as line delimiters
ganlikun 0:06036f8bee2d 150 */
ganlikun 0:06036f8bee2d 151 MBED_DEPRECATED_SINCE("mbed-os-5.5.0", "Replaced with set_delimiter for consistency")
ganlikun 0:06036f8bee2d 152 void setDelimiter(const char *output_delimiter)
ganlikun 0:06036f8bee2d 153 {
ganlikun 0:06036f8bee2d 154 set_delimiter(output_delimiter);
ganlikun 0:06036f8bee2d 155 }
ganlikun 0:06036f8bee2d 156
ganlikun 0:06036f8bee2d 157 /**
ganlikun 0:06036f8bee2d 158 * Allows traces from modem to be turned on or off
ganlikun 0:06036f8bee2d 159 *
ganlikun 0:06036f8bee2d 160 * @param on set as 1 to turn on traces and vice versa.
ganlikun 0:06036f8bee2d 161 */
ganlikun 0:06036f8bee2d 162 void debug_on(uint8_t on)
ganlikun 0:06036f8bee2d 163 {
ganlikun 0:06036f8bee2d 164 _dbg_on = (on) ? 1 : 0;
ganlikun 0:06036f8bee2d 165 }
ganlikun 0:06036f8bee2d 166
ganlikun 0:06036f8bee2d 167 /**
ganlikun 0:06036f8bee2d 168 * For backwards compatibility.
ganlikun 0:06036f8bee2d 169 *
ganlikun 0:06036f8bee2d 170 * Allows traces from modem to be turned on or off
ganlikun 0:06036f8bee2d 171 *
ganlikun 0:06036f8bee2d 172 * @param on set as 1 to turn on traces and vice versa.
ganlikun 0:06036f8bee2d 173 */
ganlikun 0:06036f8bee2d 174 MBED_DEPRECATED_SINCE("mbed-os-5.5.0", "Replaced with debug_on for consistency")
ganlikun 0:06036f8bee2d 175 void debugOn(uint8_t on)
ganlikun 0:06036f8bee2d 176 {
ganlikun 0:06036f8bee2d 177 debug_on(on);
ganlikun 0:06036f8bee2d 178 }
ganlikun 0:06036f8bee2d 179
ganlikun 0:06036f8bee2d 180 /**
ganlikun 0:06036f8bee2d 181 * Sends an AT command
ganlikun 0:06036f8bee2d 182 *
ganlikun 0:06036f8bee2d 183 * Sends a formatted command using printf style formatting
ganlikun 0:06036f8bee2d 184 * @see printf
ganlikun 0:06036f8bee2d 185 *
ganlikun 0:06036f8bee2d 186 * @param command printf-like format string of command to send which
ganlikun 0:06036f8bee2d 187 * is appended with a newline
ganlikun 0:06036f8bee2d 188 * @param ... all printf-like arguments to insert into command
ganlikun 0:06036f8bee2d 189 * @return true only if command is successfully sent
ganlikun 0:06036f8bee2d 190 */
ganlikun 0:06036f8bee2d 191 bool send(const char *command, ...) MBED_PRINTF_METHOD(1,2);
ganlikun 0:06036f8bee2d 192
ganlikun 0:06036f8bee2d 193 bool vsend(const char *command, va_list args);
ganlikun 0:06036f8bee2d 194
ganlikun 0:06036f8bee2d 195 /**
ganlikun 0:06036f8bee2d 196 * Receive an AT response
ganlikun 0:06036f8bee2d 197 *
ganlikun 0:06036f8bee2d 198 * Receives a formatted response using scanf style formatting
ganlikun 0:06036f8bee2d 199 * @see scanf
ganlikun 0:06036f8bee2d 200 *
ganlikun 0:06036f8bee2d 201 * Responses are parsed line at a time.
ganlikun 0:06036f8bee2d 202 * Any received data that does not match the response is ignored until
ganlikun 0:06036f8bee2d 203 * a timeout occurs.
ganlikun 0:06036f8bee2d 204 *
ganlikun 0:06036f8bee2d 205 * @param response scanf-like format string of response to expect
ganlikun 0:06036f8bee2d 206 * @param ... all scanf-like arguments to extract from response
ganlikun 0:06036f8bee2d 207 * @return true only if response is successfully matched
ganlikun 0:06036f8bee2d 208 */
ganlikun 0:06036f8bee2d 209 bool recv(const char *response, ...) MBED_SCANF_METHOD(1,2);
ganlikun 0:06036f8bee2d 210
ganlikun 0:06036f8bee2d 211 bool vrecv(const char *response, va_list args);
ganlikun 0:06036f8bee2d 212
ganlikun 0:06036f8bee2d 213 /**
ganlikun 0:06036f8bee2d 214 * Write a single byte to the underlying stream
ganlikun 0:06036f8bee2d 215 *
ganlikun 0:06036f8bee2d 216 * @param c The byte to write
ganlikun 0:06036f8bee2d 217 * @return The byte that was written or -1 during a timeout
ganlikun 0:06036f8bee2d 218 */
ganlikun 0:06036f8bee2d 219 int putc(char c);
ganlikun 0:06036f8bee2d 220
ganlikun 0:06036f8bee2d 221 /**
ganlikun 0:06036f8bee2d 222 * Get a single byte from the underlying stream
ganlikun 0:06036f8bee2d 223 *
ganlikun 0:06036f8bee2d 224 * @return The byte that was read or -1 during a timeout
ganlikun 0:06036f8bee2d 225 */
ganlikun 0:06036f8bee2d 226 int getc();
ganlikun 0:06036f8bee2d 227
ganlikun 0:06036f8bee2d 228 /**
ganlikun 0:06036f8bee2d 229 * Write an array of bytes to the underlying stream
ganlikun 0:06036f8bee2d 230 *
ganlikun 0:06036f8bee2d 231 * @param data the array of bytes to write
ganlikun 0:06036f8bee2d 232 * @param size number of bytes to write
ganlikun 0:06036f8bee2d 233 * @return number of bytes written or -1 on failure
ganlikun 0:06036f8bee2d 234 */
ganlikun 0:06036f8bee2d 235 int write(const char *data, int size);
ganlikun 0:06036f8bee2d 236
ganlikun 0:06036f8bee2d 237 /**
ganlikun 0:06036f8bee2d 238 * Read an array of bytes from the underlying stream
ganlikun 0:06036f8bee2d 239 *
ganlikun 0:06036f8bee2d 240 * @param data the destination for the read bytes
ganlikun 0:06036f8bee2d 241 * @param size number of bytes to read
ganlikun 0:06036f8bee2d 242 * @return number of bytes read or -1 on failure
ganlikun 0:06036f8bee2d 243 */
ganlikun 0:06036f8bee2d 244 int read(char *data, int size);
ganlikun 0:06036f8bee2d 245
ganlikun 0:06036f8bee2d 246 /**
ganlikun 0:06036f8bee2d 247 * Direct printf to underlying stream
ganlikun 0:06036f8bee2d 248 * @see printf
ganlikun 0:06036f8bee2d 249 *
ganlikun 0:06036f8bee2d 250 * @param format format string to pass to printf
ganlikun 0:06036f8bee2d 251 * @param ... arguments to printf
ganlikun 0:06036f8bee2d 252 * @return number of bytes written or -1 on failure
ganlikun 0:06036f8bee2d 253 */
ganlikun 0:06036f8bee2d 254 int printf(const char *format, ...) MBED_PRINTF_METHOD(1,2);
ganlikun 0:06036f8bee2d 255
ganlikun 0:06036f8bee2d 256 int vprintf(const char *format, va_list args);
ganlikun 0:06036f8bee2d 257
ganlikun 0:06036f8bee2d 258 /**
ganlikun 0:06036f8bee2d 259 * Direct scanf on underlying stream
ganlikun 0:06036f8bee2d 260 * @see scanf
ganlikun 0:06036f8bee2d 261 *
ganlikun 0:06036f8bee2d 262 * @param format format string to pass to scanf
ganlikun 0:06036f8bee2d 263 * @param ... arguments to scanf
ganlikun 0:06036f8bee2d 264 * @return number of bytes read or -1 on failure
ganlikun 0:06036f8bee2d 265 */
ganlikun 0:06036f8bee2d 266 int scanf(const char *format, ...) MBED_SCANF_METHOD(1,2);
ganlikun 0:06036f8bee2d 267
ganlikun 0:06036f8bee2d 268 int vscanf(const char *format, va_list args);
ganlikun 0:06036f8bee2d 269
ganlikun 0:06036f8bee2d 270 /**
ganlikun 0:06036f8bee2d 271 * Attach a callback for out-of-band data
ganlikun 0:06036f8bee2d 272 *
ganlikun 0:06036f8bee2d 273 * @param prefix string on when to initiate callback
ganlikun 0:06036f8bee2d 274 * @param func callback to call when string is read
ganlikun 0:06036f8bee2d 275 * @note out-of-band data is only processed during a scanf call
ganlikun 0:06036f8bee2d 276 */
ganlikun 0:06036f8bee2d 277 void oob(const char *prefix, mbed::Callback<void()> func);
ganlikun 0:06036f8bee2d 278
ganlikun 0:06036f8bee2d 279 /**
ganlikun 0:06036f8bee2d 280 * Flushes the underlying stream
ganlikun 0:06036f8bee2d 281 */
ganlikun 0:06036f8bee2d 282 void flush();
ganlikun 0:06036f8bee2d 283
ganlikun 0:06036f8bee2d 284 /**
ganlikun 0:06036f8bee2d 285 * Abort current recv
ganlikun 0:06036f8bee2d 286 *
ganlikun 0:06036f8bee2d 287 * Can be called from oob handler to interrupt the current
ganlikun 0:06036f8bee2d 288 * recv operation.
ganlikun 0:06036f8bee2d 289 */
ganlikun 0:06036f8bee2d 290 void abort();
ganlikun 0:06036f8bee2d 291 };
ganlikun 0:06036f8bee2d 292 } //namespace mbed
ganlikun 0:06036f8bee2d 293
ganlikun 0:06036f8bee2d 294 #endif //MBED_ATCMDPARSER_H
ganlikun 0:06036f8bee2d 295