ATParser for X-NUCLEO-IDW01M1 module

Dependencies:   BufferedSerial

Dependents:   SPWF01SA-lapi-1 SPWF01SA Nucleo-AWS-IoT-mbed

Fork of ATParser by ST Expansion SW Team

Committer:
mridup
Date:
Thu Jul 07 06:39:34 2016 +0000
Revision:
17:bf5ceea4d6f2
Parent:
16:b9b53df4dc4d
Child:
18:23f4573bcda2
fix for vrecv() to get the last '\n' byte in case of recv'ing strings with number endings.

Who changed what in which revision?

UserRevisionLine numberNew 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 "ATParser.h"
Christopher Haster 12:7d3c3f7ce928 22 #include "mbed_debug.h"
Christopher Haster 12:7d3c3f7ce928 23
Christopher Haster 12:7d3c3f7ce928 24
Christopher Haster 12:7d3c3f7ce928 25 // getc/putc handling with timeouts
Christopher Haster 12:7d3c3f7ce928 26 int ATParser::putc(char c)
Christopher Haster 12:7d3c3f7ce928 27 {
Christopher Haster 12:7d3c3f7ce928 28 Timer timer;
Christopher Haster 12:7d3c3f7ce928 29 timer.start();
Christopher Haster 12:7d3c3f7ce928 30
Christopher Haster 12:7d3c3f7ce928 31 while (true) {
Christopher Haster 12:7d3c3f7ce928 32 if (_serial->writeable()) {
Christopher Haster 12:7d3c3f7ce928 33 return _serial->putc(c);
Christopher Haster 12:7d3c3f7ce928 34 }
Christopher Haster 12:7d3c3f7ce928 35 if (timer.read_ms() > _timeout) {
Christopher Haster 12:7d3c3f7ce928 36 return -1;
Christopher Haster 12:7d3c3f7ce928 37 }
Christopher Haster 12:7d3c3f7ce928 38 }
Christopher Haster 12:7d3c3f7ce928 39 }
Christopher Haster 12:7d3c3f7ce928 40
Christopher Haster 12:7d3c3f7ce928 41 int ATParser::getc()
Christopher Haster 12:7d3c3f7ce928 42 {
Christopher Haster 12:7d3c3f7ce928 43 Timer timer;
Christopher Haster 12:7d3c3f7ce928 44 timer.start();
Christopher Haster 12:7d3c3f7ce928 45
Christopher Haster 12:7d3c3f7ce928 46 while (true) {
Christopher Haster 12:7d3c3f7ce928 47 if (_serial->readable()) {
Christopher Haster 12:7d3c3f7ce928 48 return _serial->getc();
Christopher Haster 12:7d3c3f7ce928 49 }
Christopher Haster 12:7d3c3f7ce928 50 if (timer.read_ms() > _timeout) {
Christopher Haster 12:7d3c3f7ce928 51 return -1;
Christopher Haster 12:7d3c3f7ce928 52 }
Christopher Haster 12:7d3c3f7ce928 53 }
Christopher Haster 12:7d3c3f7ce928 54 }
Christopher Haster 12:7d3c3f7ce928 55
Christopher Haster 12:7d3c3f7ce928 56 void ATParser::flush()
Christopher Haster 12:7d3c3f7ce928 57 {
Christopher Haster 12:7d3c3f7ce928 58 while (_serial->readable()) {
Christopher Haster 12:7d3c3f7ce928 59 _serial->getc();
Christopher Haster 12:7d3c3f7ce928 60 }
Christopher Haster 12:7d3c3f7ce928 61 }
Christopher Haster 12:7d3c3f7ce928 62
Christopher Haster 12:7d3c3f7ce928 63
Christopher Haster 12:7d3c3f7ce928 64 // read/write handling with timeouts
Christopher Haster 12:7d3c3f7ce928 65 int ATParser::write(const char *data, int size)
Christopher Haster 12:7d3c3f7ce928 66 {
Christopher Haster 12:7d3c3f7ce928 67 int i = 0;
Christopher Haster 12:7d3c3f7ce928 68 for ( ; i < size; i++) {
Christopher Haster 12:7d3c3f7ce928 69 if (putc(data[i]) < 0) {
Christopher Haster 12:7d3c3f7ce928 70 return -1;
Christopher Haster 12:7d3c3f7ce928 71 }
Christopher Haster 12:7d3c3f7ce928 72 }
Christopher Haster 12:7d3c3f7ce928 73 return i;
Christopher Haster 12:7d3c3f7ce928 74 }
Christopher Haster 12:7d3c3f7ce928 75
Christopher Haster 12:7d3c3f7ce928 76 int ATParser::read(char *data, int size)
Christopher Haster 12:7d3c3f7ce928 77 {
Christopher Haster 12:7d3c3f7ce928 78 int i = 0;
Christopher Haster 12:7d3c3f7ce928 79 for ( ; i < size; i++) {
Christopher Haster 12:7d3c3f7ce928 80 int c = getc();
Christopher Haster 12:7d3c3f7ce928 81 if (c < 0) {
Christopher Haster 12:7d3c3f7ce928 82 return -1;
Christopher Haster 12:7d3c3f7ce928 83 }
Christopher Haster 12:7d3c3f7ce928 84 data[i] = c;
Christopher Haster 12:7d3c3f7ce928 85 }
Christopher Haster 12:7d3c3f7ce928 86 return i;
Christopher Haster 12:7d3c3f7ce928 87 }
Christopher Haster 12:7d3c3f7ce928 88
Christopher Haster 12:7d3c3f7ce928 89
Christopher Haster 12:7d3c3f7ce928 90 // printf/scanf handling
Christopher Haster 12:7d3c3f7ce928 91 int ATParser::vprintf(const char *format, va_list args)
Christopher Haster 12:7d3c3f7ce928 92 {
Christopher Haster 12:7d3c3f7ce928 93 if (vsprintf(_buffer, format, args) < 0) {
Christopher Haster 12:7d3c3f7ce928 94 return false;
Christopher Haster 12:7d3c3f7ce928 95 }
Christopher Haster 12:7d3c3f7ce928 96 int i = 0;
Christopher Haster 12:7d3c3f7ce928 97 for ( ; _buffer[i]; i++) {
Christopher Haster 12:7d3c3f7ce928 98 if (putc(_buffer[i]) < 0) {
Christopher Haster 12:7d3c3f7ce928 99 return -1;
Christopher Haster 12:7d3c3f7ce928 100 }
Christopher Haster 12:7d3c3f7ce928 101 }
Christopher Haster 12:7d3c3f7ce928 102 return i;
Christopher Haster 12:7d3c3f7ce928 103 }
Christopher Haster 12:7d3c3f7ce928 104
Christopher Haster 12:7d3c3f7ce928 105 int ATParser::vscanf(const char *format, va_list args)
Christopher Haster 12:7d3c3f7ce928 106 {
Christopher Haster 12:7d3c3f7ce928 107 // Since format is const, we need to copy it into our buffer to
Christopher Haster 12:7d3c3f7ce928 108 // add the line's null terminator and clobber value-matches with asterisks.
Christopher Haster 12:7d3c3f7ce928 109 //
Christopher Haster 12:7d3c3f7ce928 110 // We just use the beginning of the buffer to avoid unnecessary allocations.
Christopher Haster 12:7d3c3f7ce928 111 int i = 0;
Christopher Haster 12:7d3c3f7ce928 112 int offset = 0;
Christopher Haster 12:7d3c3f7ce928 113
Christopher Haster 12:7d3c3f7ce928 114 while (format[i]) {
Christopher Haster 12:7d3c3f7ce928 115 if (format[i] == '%' && format[i+1] != '%' && format[i+1] != '*') {
Christopher Haster 12:7d3c3f7ce928 116 _buffer[offset++] = '%';
Christopher Haster 12:7d3c3f7ce928 117 _buffer[offset++] = '*';
Christopher Haster 12:7d3c3f7ce928 118 i++;
Christopher Haster 12:7d3c3f7ce928 119 } else {
Christopher Haster 12:7d3c3f7ce928 120 _buffer[offset++] = format[i++];
Christopher Haster 12:7d3c3f7ce928 121 }
Christopher Haster 12:7d3c3f7ce928 122 }
Christopher Haster 12:7d3c3f7ce928 123
Christopher Haster 12:7d3c3f7ce928 124 // Scanf has very poor support for catching errors
Christopher Haster 12:7d3c3f7ce928 125 // fortunately, we can abuse the %n specifier to determine
Christopher Haster 12:7d3c3f7ce928 126 // if the entire string was matched.
Christopher Haster 12:7d3c3f7ce928 127 _buffer[offset++] = '%';
Christopher Haster 12:7d3c3f7ce928 128 _buffer[offset++] = 'n';
Christopher Haster 12:7d3c3f7ce928 129 _buffer[offset++] = 0;
Christopher Haster 12:7d3c3f7ce928 130
Christopher Haster 12:7d3c3f7ce928 131 // To workaround scanf's lack of error reporting, we actually
Christopher Haster 12:7d3c3f7ce928 132 // make two passes. One checks the validity with the modified
Christopher Haster 12:7d3c3f7ce928 133 // format string that only stores the matched characters (%n).
Christopher Haster 12:7d3c3f7ce928 134 // The other reads in the actual matched values.
Christopher Haster 12:7d3c3f7ce928 135 //
Christopher Haster 12:7d3c3f7ce928 136 // We keep trying the match until we succeed or some other error
Christopher Haster 12:7d3c3f7ce928 137 // derails us.
Christopher Haster 12:7d3c3f7ce928 138 int j = 0;
Christopher Haster 12:7d3c3f7ce928 139
Christopher Haster 12:7d3c3f7ce928 140 while (true) {
Christopher Haster 12:7d3c3f7ce928 141 // Ran out of space
Christopher Haster 12:7d3c3f7ce928 142 if (j+1 >= _buffer_size - offset) {
Christopher Haster 12:7d3c3f7ce928 143 return false;
Christopher Haster 12:7d3c3f7ce928 144 }
Christopher Haster 12:7d3c3f7ce928 145 // Recieve next character
Christopher Haster 12:7d3c3f7ce928 146 int c = getc();
Christopher Haster 12:7d3c3f7ce928 147 if (c < 0) {
Christopher Haster 12:7d3c3f7ce928 148 return -1;
Christopher Haster 12:7d3c3f7ce928 149 }
Christopher Haster 12:7d3c3f7ce928 150 _buffer[offset + j++] = c;
Christopher Haster 12:7d3c3f7ce928 151 _buffer[offset + j] = 0;
Christopher Haster 12:7d3c3f7ce928 152
Christopher Haster 12:7d3c3f7ce928 153 // Check for match
Christopher Haster 12:7d3c3f7ce928 154 int count = -1;
Christopher Haster 12:7d3c3f7ce928 155 sscanf(_buffer+offset, _buffer, &count);
Christopher Haster 12:7d3c3f7ce928 156
Christopher Haster 12:7d3c3f7ce928 157 // We only succeed if all characters in the response are matched
Christopher Haster 12:7d3c3f7ce928 158 if (count == j) {
Christopher Haster 12:7d3c3f7ce928 159 // Store the found results
Christopher Haster 12:7d3c3f7ce928 160 vsscanf(_buffer+offset, format, args);
Christopher Haster 12:7d3c3f7ce928 161 return j;
Christopher Haster 12:7d3c3f7ce928 162 }
Christopher Haster 12:7d3c3f7ce928 163 }
Christopher Haster 12:7d3c3f7ce928 164 }
Christopher Haster 12:7d3c3f7ce928 165
Christopher Haster 12:7d3c3f7ce928 166
Christopher Haster 12:7d3c3f7ce928 167 // Command parsing with line handling
Christopher Haster 12:7d3c3f7ce928 168 bool ATParser::vsend(const char *command, va_list args)
Christopher Haster 12:7d3c3f7ce928 169 {
Christopher Haster 12:7d3c3f7ce928 170 // Create and send command
Christopher Haster 12:7d3c3f7ce928 171 if (vsprintf(_buffer, command, args) < 0) {
Christopher Haster 12:7d3c3f7ce928 172 return false;
Christopher Haster 12:7d3c3f7ce928 173 }
Christopher Haster 12:7d3c3f7ce928 174 for (int i = 0; _buffer[i]; i++) {
Christopher Haster 12:7d3c3f7ce928 175 if (putc(_buffer[i]) < 0) {
Christopher Haster 12:7d3c3f7ce928 176 return false;
Christopher Haster 12:7d3c3f7ce928 177 }
Christopher Haster 12:7d3c3f7ce928 178 }
Christopher Haster 12:7d3c3f7ce928 179
Christopher Haster 12:7d3c3f7ce928 180 // Finish with newline
Christopher Haster 12:7d3c3f7ce928 181 for (int i = 0; _delimiter[i]; i++) {
Christopher Haster 12:7d3c3f7ce928 182 if (putc(_delimiter[i]) < 0) {
Christopher Haster 12:7d3c3f7ce928 183 return false;
Christopher Haster 12:7d3c3f7ce928 184 }
Christopher Haster 12:7d3c3f7ce928 185 }
Christopher Haster 12:7d3c3f7ce928 186
Christopher Haster 12:7d3c3f7ce928 187 debug_if(dbg_on, "AT> %s\r\n", _buffer);
Christopher Haster 12:7d3c3f7ce928 188 return true;
Christopher Haster 12:7d3c3f7ce928 189 }
Christopher Haster 12:7d3c3f7ce928 190
Christopher Haster 12:7d3c3f7ce928 191 bool ATParser::vrecv(const char *response, va_list args)
Christopher Haster 12:7d3c3f7ce928 192 {
Christopher Haster 12:7d3c3f7ce928 193 // Iterate through each line in the expected response
Christopher Haster 12:7d3c3f7ce928 194 while (response[0]) {
Christopher Haster 12:7d3c3f7ce928 195 // Since response is const, we need to copy it into our buffer to
Christopher Haster 12:7d3c3f7ce928 196 // add the line's null terminator and clobber value-matches with asterisks.
Christopher Haster 12:7d3c3f7ce928 197 //
Christopher Haster 12:7d3c3f7ce928 198 // We just use the beginning of the buffer to avoid unnecessary allocations.
Christopher Haster 12:7d3c3f7ce928 199 int i = 0;
Christopher Haster 12:7d3c3f7ce928 200 int offset = 0;
Christopher Haster 12:7d3c3f7ce928 201
Christopher Haster 12:7d3c3f7ce928 202 while (response[i]) {
Christopher Haster 12:7d3c3f7ce928 203 if (memcmp(&response[i+1-_delim_size], _delimiter, _delim_size) == 0) {
Christopher Haster 12:7d3c3f7ce928 204 i++;
Christopher Haster 12:7d3c3f7ce928 205 break;
Christopher Haster 12:7d3c3f7ce928 206 } else if (response[i] == '%' && response[i+1] != '%' && response[i+1] != '*') {
Christopher Haster 12:7d3c3f7ce928 207 _buffer[offset++] = '%';
Christopher Haster 12:7d3c3f7ce928 208 _buffer[offset++] = '*';
Christopher Haster 12:7d3c3f7ce928 209 i++;
Christopher Haster 12:7d3c3f7ce928 210 } else {
Christopher Haster 12:7d3c3f7ce928 211 _buffer[offset++] = response[i++];
Christopher Haster 12:7d3c3f7ce928 212 }
Christopher Haster 12:7d3c3f7ce928 213 }
Christopher Haster 12:7d3c3f7ce928 214
Christopher Haster 12:7d3c3f7ce928 215 // Scanf has very poor support for catching errors
Christopher Haster 12:7d3c3f7ce928 216 // fortunately, we can abuse the %n specifier to determine
Christopher Haster 12:7d3c3f7ce928 217 // if the entire string was matched.
Christopher Haster 12:7d3c3f7ce928 218 _buffer[offset++] = '%';
Christopher Haster 12:7d3c3f7ce928 219 _buffer[offset++] = 'n';
Christopher Haster 12:7d3c3f7ce928 220 _buffer[offset++] = 0;
Christopher Haster 12:7d3c3f7ce928 221
Christopher Haster 12:7d3c3f7ce928 222 // To workaround scanf's lack of error reporting, we actually
Christopher Haster 12:7d3c3f7ce928 223 // make two passes. One checks the validity with the modified
Christopher Haster 12:7d3c3f7ce928 224 // format string that only stores the matched characters (%n).
Christopher Haster 12:7d3c3f7ce928 225 // The other reads in the actual matched values.
Christopher Haster 12:7d3c3f7ce928 226 //
Christopher Haster 12:7d3c3f7ce928 227 // We keep trying the match until we succeed or some other error
Christopher Haster 12:7d3c3f7ce928 228 // derails us.
Christopher Haster 12:7d3c3f7ce928 229 int j = 0;
mridup 15:311f99666a8d 230
Christopher Haster 12:7d3c3f7ce928 231 while (true) {
mridup 16:b9b53df4dc4d 232 // Receive next character
Christopher Haster 12:7d3c3f7ce928 233 int c = getc();
Christopher Haster 12:7d3c3f7ce928 234 if (c < 0) {
Christopher Haster 12:7d3c3f7ce928 235 return false;
Christopher Haster 12:7d3c3f7ce928 236 }
Christopher Haster 12:7d3c3f7ce928 237 _buffer[offset + j++] = c;
Christopher Haster 12:7d3c3f7ce928 238 _buffer[offset + j] = 0;
Christopher Haster 12:7d3c3f7ce928 239
Christopher Haster 12:7d3c3f7ce928 240 // Check for match
Christopher Haster 12:7d3c3f7ce928 241 int count = -1;
Christopher Haster 12:7d3c3f7ce928 242 sscanf(_buffer+offset, _buffer, &count);
mridup 15:311f99666a8d 243
Christopher Haster 12:7d3c3f7ce928 244 // We only succeed if all characters in the response are matched
mridup 15:311f99666a8d 245 if(count==j) {
mridup 16:b9b53df4dc4d 246 //check if last input is a number
mridup 16:b9b53df4dc4d 247 if (_buffer[offset-6]=='%' && _buffer[offset-5]=='*'
mridup 16:b9b53df4dc4d 248 && (_buffer[offset-4]=='x' || _buffer[offset-4]=='d' || _buffer[offset-4]=='u'))
mridup 16:b9b53df4dc4d 249 {
mridup 16:b9b53df4dc4d 250 //if the last char is a number, keep getting the next character till CR
mridup 16:b9b53df4dc4d 251 while(true)
mridup 15:311f99666a8d 252 {
mridup 16:b9b53df4dc4d 253 int c = getc();
mridup 16:b9b53df4dc4d 254 if (c < 0) {
mridup 16:b9b53df4dc4d 255 return false;
mridup 16:b9b53df4dc4d 256 }
mridup 17:bf5ceea4d6f2 257 if(c==0xD) {//there is no next number so exit from condition
mridup 17:bf5ceea4d6f2 258 c = getc();//get rid of the following '\n' delimiter
mridup 16:b9b53df4dc4d 259 break;
mridup 16:b9b53df4dc4d 260 }
mridup 16:b9b53df4dc4d 261 else {
mridup 16:b9b53df4dc4d 262 _buffer[offset + j++] = c;
mridup 16:b9b53df4dc4d 263 _buffer[offset + j] = 0;
mridup 15:311f99666a8d 264 }
mridup 15:311f99666a8d 265 }
mridup 16:b9b53df4dc4d 266 }
mridup 15:311f99666a8d 267
Christopher Haster 12:7d3c3f7ce928 268 debug_if(dbg_on, "AT= %s\r\n", _buffer+offset);
Christopher Haster 12:7d3c3f7ce928 269 // Reuse the front end of the buffer
Christopher Haster 12:7d3c3f7ce928 270 memcpy(_buffer, response, i);
Christopher Haster 12:7d3c3f7ce928 271 _buffer[i] = 0;
Christopher Haster 12:7d3c3f7ce928 272
Christopher Haster 12:7d3c3f7ce928 273 // Store the found results
Christopher Haster 12:7d3c3f7ce928 274 vsscanf(_buffer+offset, _buffer, args);
Christopher Haster 12:7d3c3f7ce928 275
Christopher Haster 12:7d3c3f7ce928 276 // Jump to next line and continue parsing
Christopher Haster 12:7d3c3f7ce928 277 response += i;
Christopher Haster 12:7d3c3f7ce928 278 break;
Christopher Haster 12:7d3c3f7ce928 279 }
Christopher Haster 12:7d3c3f7ce928 280
Christopher Haster 13:46a18ad08efc 281 // Clear the buffer when we hit a newline or ran out of space
Christopher Haster 13:46a18ad08efc 282 // running out of space usually means we ran into binary data
Christopher Haster 13:46a18ad08efc 283 if (j+1 >= _buffer_size - offset ||
Christopher Haster 13:46a18ad08efc 284 strcmp(&_buffer[offset + j-_delim_size], _delimiter) == 0) {
Christopher Haster 13:46a18ad08efc 285
Christopher Haster 12:7d3c3f7ce928 286 debug_if(dbg_on, "AT< %s", _buffer+offset);
Christopher Haster 12:7d3c3f7ce928 287 j = 0;
Christopher Haster 12:7d3c3f7ce928 288 }
Christopher Haster 12:7d3c3f7ce928 289 }
Christopher Haster 12:7d3c3f7ce928 290 }
Christopher Haster 12:7d3c3f7ce928 291
Christopher Haster 12:7d3c3f7ce928 292 return true;
Christopher Haster 12:7d3c3f7ce928 293 }
Christopher Haster 12:7d3c3f7ce928 294
Christopher Haster 12:7d3c3f7ce928 295
Christopher Haster 12:7d3c3f7ce928 296 // Mapping to vararg functions
Christopher Haster 12:7d3c3f7ce928 297 int ATParser::printf(const char *format, ...)
Christopher Haster 12:7d3c3f7ce928 298 {
Christopher Haster 12:7d3c3f7ce928 299 va_list args;
Christopher Haster 12:7d3c3f7ce928 300 va_start(args, format);
Christopher Haster 12:7d3c3f7ce928 301 int res = vprintf(format, args);
Christopher Haster 12:7d3c3f7ce928 302 va_end(args);
Christopher Haster 12:7d3c3f7ce928 303 return res;
Christopher Haster 12:7d3c3f7ce928 304 }
Christopher Haster 12:7d3c3f7ce928 305
Christopher Haster 12:7d3c3f7ce928 306 int ATParser::scanf(const char *format, ...)
Christopher Haster 12:7d3c3f7ce928 307 {
Christopher Haster 12:7d3c3f7ce928 308 va_list args;
Christopher Haster 12:7d3c3f7ce928 309 va_start(args, format);
Christopher Haster 12:7d3c3f7ce928 310 int res = vscanf(format, args);
Christopher Haster 12:7d3c3f7ce928 311 va_end(args);
Christopher Haster 12:7d3c3f7ce928 312 return res;
Christopher Haster 12:7d3c3f7ce928 313 }
Christopher Haster 12:7d3c3f7ce928 314
Christopher Haster 12:7d3c3f7ce928 315 bool ATParser::send(const char *command, ...)
Christopher Haster 12:7d3c3f7ce928 316 {
Christopher Haster 12:7d3c3f7ce928 317 va_list args;
Christopher Haster 12:7d3c3f7ce928 318 va_start(args, command);
Christopher Haster 12:7d3c3f7ce928 319 bool res = vsend(command, args);
Christopher Haster 12:7d3c3f7ce928 320 va_end(args);
Christopher Haster 12:7d3c3f7ce928 321 return res;
Christopher Haster 12:7d3c3f7ce928 322 }
Christopher Haster 12:7d3c3f7ce928 323
Christopher Haster 12:7d3c3f7ce928 324 bool ATParser::recv(const char *response, ...)
Christopher Haster 12:7d3c3f7ce928 325 {
Christopher Haster 12:7d3c3f7ce928 326 va_list args;
Christopher Haster 12:7d3c3f7ce928 327 va_start(args, response);
Christopher Haster 12:7d3c3f7ce928 328 bool res = vrecv(response, args);
Christopher Haster 12:7d3c3f7ce928 329 va_end(args);
Christopher Haster 12:7d3c3f7ce928 330 return res;
Christopher Haster 12:7d3c3f7ce928 331 }