00

Committer:
ganlikun
Date:
Sun Jun 12 14:02:44 2022 +0000
Revision:
0:13413ea9a877
00

Who changed what in which revision?

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