Generic Pelion Device Management example for various Advantech modules.

This example is known to work great on the following platforms:

Example Functionality

This example showcases the following device functionality:

  • On timer button increment, simulate Pelion LWM2M button resource change

Use this example with Mbed CLI

1. Import the application into your desktop:

mbed import https://os.mbed.com/teams/Advantech/code/pelion-example-common
cd pelion-example-common

2. Download your developer certificate from pelion portal

3. Compile the program

mbed compile -t <toolchain> -m <TARGET_BOARD>

(supported toolchains : GCC_ARM / ARM / IAR)

4. Copy the binary file pelion-example-common.bin to your mbed device.

Committer:
chuanga
Date:
Tue Mar 12 13:48:39 2019 +0800
Revision:
0:43ff9e3bc244
copying sources from github repository

Who changed what in which revision?

UserRevisionLine numberNew contents of line
chuanga 0:43ff9e3bc244 1 /* Copyright (c) 2015 ARM Limited
chuanga 0:43ff9e3bc244 2 *
chuanga 0:43ff9e3bc244 3 * Licensed under the Apache License, Version 2.0 (the "License");
chuanga 0:43ff9e3bc244 4 * you may not use this file except in compliance with the License.
chuanga 0:43ff9e3bc244 5 * You may obtain a copy of the License at
chuanga 0:43ff9e3bc244 6 *
chuanga 0:43ff9e3bc244 7 * http://www.apache.org/licenses/LICENSE-2.0
chuanga 0:43ff9e3bc244 8 *
chuanga 0:43ff9e3bc244 9 * Unless required by applicable law or agreed to in writing, software
chuanga 0:43ff9e3bc244 10 * distributed under the License is distributed on an "AS IS" BASIS,
chuanga 0:43ff9e3bc244 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
chuanga 0:43ff9e3bc244 12 * See the License for the specific language governing permissions and
chuanga 0:43ff9e3bc244 13 * limitations under the License.
chuanga 0:43ff9e3bc244 14 *
chuanga 0:43ff9e3bc244 15 * @section DESCRIPTION
chuanga 0:43ff9e3bc244 16 *
chuanga 0:43ff9e3bc244 17 * Parser for the AT command syntax
chuanga 0:43ff9e3bc244 18 *
chuanga 0:43ff9e3bc244 19 */
chuanga 0:43ff9e3bc244 20
chuanga 0:43ff9e3bc244 21 #include "ATParser.h"
chuanga 0:43ff9e3bc244 22 #include "mbed_debug.h"
chuanga 0:43ff9e3bc244 23
chuanga 0:43ff9e3bc244 24 #ifdef LF
chuanga 0:43ff9e3bc244 25 #undef LF
chuanga 0:43ff9e3bc244 26 #define LF 10
chuanga 0:43ff9e3bc244 27 #else
chuanga 0:43ff9e3bc244 28 #define LF 10
chuanga 0:43ff9e3bc244 29 #endif
chuanga 0:43ff9e3bc244 30
chuanga 0:43ff9e3bc244 31 #ifdef CR
chuanga 0:43ff9e3bc244 32 #undef CR
chuanga 0:43ff9e3bc244 33 #define CR 13
chuanga 0:43ff9e3bc244 34 #else
chuanga 0:43ff9e3bc244 35 #define CR 13
chuanga 0:43ff9e3bc244 36 #endif
chuanga 0:43ff9e3bc244 37 #define MIN(a,b) (((a)<(b))?(a):(b))
chuanga 0:43ff9e3bc244 38
chuanga 0:43ff9e3bc244 39 // activate / de-activate debug
chuanga 0:43ff9e3bc244 40 #define dbg_on 0
chuanga 0:43ff9e3bc244 41 #define AT_DATA_PRINT 0
chuanga 0:43ff9e3bc244 42 #define AT_COMMAND_PRINT 0
chuanga 0:43ff9e3bc244 43 #define AT_HEXA_DATA 0
chuanga 0:43ff9e3bc244 44
chuanga 0:43ff9e3bc244 45 ATParser::ATParser(BufferedSpi &serial_spi, const char *delimiter, int buffer_size, int timeout) :
chuanga 0:43ff9e3bc244 46 _serial_spi(&serial_spi),
chuanga 0:43ff9e3bc244 47 _buffer_size(buffer_size), _in_prev(0), _oobs(NULL)
chuanga 0:43ff9e3bc244 48 {
chuanga 0:43ff9e3bc244 49 _buffer = new char[buffer_size];
chuanga 0:43ff9e3bc244 50 setTimeout(timeout);
chuanga 0:43ff9e3bc244 51 setDelimiter(delimiter);
chuanga 0:43ff9e3bc244 52 }
chuanga 0:43ff9e3bc244 53
chuanga 0:43ff9e3bc244 54
chuanga 0:43ff9e3bc244 55 // getc/putc handling with timeouts
chuanga 0:43ff9e3bc244 56 int ATParser::putc(char c)
chuanga 0:43ff9e3bc244 57 {
chuanga 0:43ff9e3bc244 58 return _serial_spi->putc(c);
chuanga 0:43ff9e3bc244 59 }
chuanga 0:43ff9e3bc244 60
chuanga 0:43ff9e3bc244 61 int ATParser::getc()
chuanga 0:43ff9e3bc244 62 {
chuanga 0:43ff9e3bc244 63 return _serial_spi->getc();
chuanga 0:43ff9e3bc244 64 }
chuanga 0:43ff9e3bc244 65
chuanga 0:43ff9e3bc244 66 void ATParser::flush()
chuanga 0:43ff9e3bc244 67 {
chuanga 0:43ff9e3bc244 68 _bufferMutex.lock();
chuanga 0:43ff9e3bc244 69 while (_serial_spi->readable()) {
chuanga 0:43ff9e3bc244 70 _serial_spi->getc();
chuanga 0:43ff9e3bc244 71 }
chuanga 0:43ff9e3bc244 72 _bufferMutex.unlock();
chuanga 0:43ff9e3bc244 73 }
chuanga 0:43ff9e3bc244 74
chuanga 0:43ff9e3bc244 75 // read/write handling with timeouts
chuanga 0:43ff9e3bc244 76 int ATParser::write(const char *data, int size_of_data, int size_in_buff)
chuanga 0:43ff9e3bc244 77 {
chuanga 0:43ff9e3bc244 78 int i = 0;
chuanga 0:43ff9e3bc244 79 _bufferMutex.lock();
chuanga 0:43ff9e3bc244 80 debug_if(dbg_on, "ATParser write: %d BYTES\r\n", size_of_data);
chuanga 0:43ff9e3bc244 81 debug_if(AT_DATA_PRINT, "ATParser write: (ASCII) ", size_of_data);
chuanga 0:43ff9e3bc244 82 for (; i < size_of_data; i++) {
chuanga 0:43ff9e3bc244 83 debug_if(AT_DATA_PRINT, "%c", data[i]);
chuanga 0:43ff9e3bc244 84 if (putc(data[i]) < 0) {
chuanga 0:43ff9e3bc244 85 debug_if(AT_DATA_PRINT, "\r\n");
chuanga 0:43ff9e3bc244 86 _bufferMutex.unlock();
chuanga 0:43ff9e3bc244 87 return -1;
chuanga 0:43ff9e3bc244 88 }
chuanga 0:43ff9e3bc244 89 }
chuanga 0:43ff9e3bc244 90 debug_if(AT_DATA_PRINT, "\r\n");
chuanga 0:43ff9e3bc244 91
chuanga 0:43ff9e3bc244 92 _serial_spi->buffsend(size_of_data + size_in_buff);
chuanga 0:43ff9e3bc244 93 _bufferMutex.unlock();
chuanga 0:43ff9e3bc244 94
chuanga 0:43ff9e3bc244 95 return (size_of_data + size_in_buff);
chuanga 0:43ff9e3bc244 96 }
chuanga 0:43ff9e3bc244 97
chuanga 0:43ff9e3bc244 98 int ATParser::read(char *data)
chuanga 0:43ff9e3bc244 99 {
chuanga 0:43ff9e3bc244 100 int readsize;
chuanga 0:43ff9e3bc244 101 int i = 0;
chuanga 0:43ff9e3bc244 102
chuanga 0:43ff9e3bc244 103 _bufferMutex.lock();
chuanga 0:43ff9e3bc244 104
chuanga 0:43ff9e3bc244 105 //this->flush();
chuanga 0:43ff9e3bc244 106 if (!_serial_spi->readable()) {
chuanga 0:43ff9e3bc244 107 readsize = _serial_spi->read();
chuanga 0:43ff9e3bc244 108 } else {
chuanga 0:43ff9e3bc244 109 debug_if(dbg_on, "Pending data when reading from WIFI\r\n");
chuanga 0:43ff9e3bc244 110 return -1;
chuanga 0:43ff9e3bc244 111 }
chuanga 0:43ff9e3bc244 112
chuanga 0:43ff9e3bc244 113 debug_if(dbg_on, "ATParser read: %d data avail in SPI\r\n", readsize);
chuanga 0:43ff9e3bc244 114
chuanga 0:43ff9e3bc244 115 if (readsize < 0) {
chuanga 0:43ff9e3bc244 116 _bufferMutex.unlock();
chuanga 0:43ff9e3bc244 117 return -1;
chuanga 0:43ff9e3bc244 118 }
chuanga 0:43ff9e3bc244 119
chuanga 0:43ff9e3bc244 120 for (i = 0 ; i < readsize; i++) {
chuanga 0:43ff9e3bc244 121 int c = getc();
chuanga 0:43ff9e3bc244 122 if (c < 0) {
chuanga 0:43ff9e3bc244 123 _bufferMutex.unlock();
chuanga 0:43ff9e3bc244 124 return -1;
chuanga 0:43ff9e3bc244 125 }
chuanga 0:43ff9e3bc244 126 data[i] = c;
chuanga 0:43ff9e3bc244 127 }
chuanga 0:43ff9e3bc244 128
chuanga 0:43ff9e3bc244 129 #if AT_HEXA_DATA
chuanga 0:43ff9e3bc244 130 debug_if(AT_DATA_PRINT, "ATParser read: (HEXA) ");
chuanga 0:43ff9e3bc244 131 for (i = 0; i < readsize; i++) {
chuanga 0:43ff9e3bc244 132 debug_if(AT_DATA_PRINT, "%2X ", data[i]);
chuanga 0:43ff9e3bc244 133 if ((i + 1) % 20 == 0) {
chuanga 0:43ff9e3bc244 134 debug_if(AT_DATA_PRINT, "\r\n");
chuanga 0:43ff9e3bc244 135 }
chuanga 0:43ff9e3bc244 136 }
chuanga 0:43ff9e3bc244 137 debug_if(AT_DATA_PRINT, "\r\n");
chuanga 0:43ff9e3bc244 138 #endif
chuanga 0:43ff9e3bc244 139 debug_if(AT_DATA_PRINT, "ATParser read: (ASCII) ");
chuanga 0:43ff9e3bc244 140 for (i = 0; i < readsize; i++) {
chuanga 0:43ff9e3bc244 141 debug_if(AT_DATA_PRINT, "%c", data[i]);
chuanga 0:43ff9e3bc244 142 }
chuanga 0:43ff9e3bc244 143 debug_if(AT_DATA_PRINT, "\r\n");
chuanga 0:43ff9e3bc244 144
chuanga 0:43ff9e3bc244 145 _bufferMutex.unlock();
chuanga 0:43ff9e3bc244 146
chuanga 0:43ff9e3bc244 147 return (readsize);
chuanga 0:43ff9e3bc244 148 }
chuanga 0:43ff9e3bc244 149
chuanga 0:43ff9e3bc244 150 // printf/scanf handling
chuanga 0:43ff9e3bc244 151 int ATParser::vprintf(const char *format, va_list args)
chuanga 0:43ff9e3bc244 152 {
chuanga 0:43ff9e3bc244 153 _bufferMutex.lock();
chuanga 0:43ff9e3bc244 154 if (vsprintf(_buffer, format, args) < 0) {
chuanga 0:43ff9e3bc244 155 _bufferMutex.unlock();
chuanga 0:43ff9e3bc244 156 return false;
chuanga 0:43ff9e3bc244 157 }
chuanga 0:43ff9e3bc244 158
chuanga 0:43ff9e3bc244 159 int i = 0;
chuanga 0:43ff9e3bc244 160 for (; _buffer[i]; i++) {
chuanga 0:43ff9e3bc244 161 if (putc(_buffer[i]) < 0) {
chuanga 0:43ff9e3bc244 162 _bufferMutex.unlock();
chuanga 0:43ff9e3bc244 163 return -1;
chuanga 0:43ff9e3bc244 164 }
chuanga 0:43ff9e3bc244 165 }
chuanga 0:43ff9e3bc244 166 _bufferMutex.unlock();
chuanga 0:43ff9e3bc244 167
chuanga 0:43ff9e3bc244 168 return i;
chuanga 0:43ff9e3bc244 169 }
chuanga 0:43ff9e3bc244 170
chuanga 0:43ff9e3bc244 171 int ATParser::vscanf(const char *format, va_list args)
chuanga 0:43ff9e3bc244 172 {
chuanga 0:43ff9e3bc244 173 // Since format is const, we need to copy it into our buffer to
chuanga 0:43ff9e3bc244 174 // add the line's null terminator and clobber value-matches with asterisks.
chuanga 0:43ff9e3bc244 175 //
chuanga 0:43ff9e3bc244 176 // We just use the beginning of the buffer to avoid unnecessary allocations.
chuanga 0:43ff9e3bc244 177 int i = 0;
chuanga 0:43ff9e3bc244 178 int offset = 0;
chuanga 0:43ff9e3bc244 179
chuanga 0:43ff9e3bc244 180 _bufferMutex.lock();
chuanga 0:43ff9e3bc244 181
chuanga 0:43ff9e3bc244 182 while (format[i]) {
chuanga 0:43ff9e3bc244 183 if (format[i] == '%' && format[i + 1] != '%' && format[i + 1] != '*') {
chuanga 0:43ff9e3bc244 184 _buffer[offset++] = '%';
chuanga 0:43ff9e3bc244 185 _buffer[offset++] = '*';
chuanga 0:43ff9e3bc244 186 i++;
chuanga 0:43ff9e3bc244 187 } else {
chuanga 0:43ff9e3bc244 188 _buffer[offset++] = format[i++];
chuanga 0:43ff9e3bc244 189 }
chuanga 0:43ff9e3bc244 190 }
chuanga 0:43ff9e3bc244 191
chuanga 0:43ff9e3bc244 192 // Scanf has very poor support for catching errors
chuanga 0:43ff9e3bc244 193 // fortunately, we can abuse the %n specifier to determine
chuanga 0:43ff9e3bc244 194 // if the entire string was matched.
chuanga 0:43ff9e3bc244 195 _buffer[offset++] = '%';
chuanga 0:43ff9e3bc244 196 _buffer[offset++] = 'n';
chuanga 0:43ff9e3bc244 197 _buffer[offset++] = 0;
chuanga 0:43ff9e3bc244 198
chuanga 0:43ff9e3bc244 199 // To workaround scanf's lack of error reporting, we actually
chuanga 0:43ff9e3bc244 200 // make two passes. One checks the validity with the modified
chuanga 0:43ff9e3bc244 201 // format string that only stores the matched characters (%n).
chuanga 0:43ff9e3bc244 202 // The other reads in the actual matched values.
chuanga 0:43ff9e3bc244 203 //
chuanga 0:43ff9e3bc244 204 // We keep trying the match until we succeed or some other error
chuanga 0:43ff9e3bc244 205 // derails us.
chuanga 0:43ff9e3bc244 206 int j = 0;
chuanga 0:43ff9e3bc244 207
chuanga 0:43ff9e3bc244 208 while (true) {
chuanga 0:43ff9e3bc244 209 // Ran out of space
chuanga 0:43ff9e3bc244 210 if (j + 1 >= _buffer_size - offset) {
chuanga 0:43ff9e3bc244 211 _bufferMutex.unlock();
chuanga 0:43ff9e3bc244 212 return false;
chuanga 0:43ff9e3bc244 213 }
chuanga 0:43ff9e3bc244 214 // Recieve next character
chuanga 0:43ff9e3bc244 215 int c = getc();
chuanga 0:43ff9e3bc244 216 if (c < 0) {
chuanga 0:43ff9e3bc244 217 _bufferMutex.unlock();
chuanga 0:43ff9e3bc244 218 return -1;
chuanga 0:43ff9e3bc244 219 }
chuanga 0:43ff9e3bc244 220 _buffer[offset + j++] = c;
chuanga 0:43ff9e3bc244 221 _buffer[offset + j] = 0;
chuanga 0:43ff9e3bc244 222
chuanga 0:43ff9e3bc244 223 // Check for match
chuanga 0:43ff9e3bc244 224 int count = -1;
chuanga 0:43ff9e3bc244 225 sscanf(_buffer + offset, _buffer, &count);
chuanga 0:43ff9e3bc244 226
chuanga 0:43ff9e3bc244 227 // We only succeed if all characters in the response are matched
chuanga 0:43ff9e3bc244 228 if (count == j) {
chuanga 0:43ff9e3bc244 229 // Store the found results
chuanga 0:43ff9e3bc244 230 vsscanf(_buffer + offset, format, args);
chuanga 0:43ff9e3bc244 231 _bufferMutex.unlock();
chuanga 0:43ff9e3bc244 232 return j;
chuanga 0:43ff9e3bc244 233 }
chuanga 0:43ff9e3bc244 234 }
chuanga 0:43ff9e3bc244 235 }
chuanga 0:43ff9e3bc244 236
chuanga 0:43ff9e3bc244 237
chuanga 0:43ff9e3bc244 238 // Command parsing with line handling
chuanga 0:43ff9e3bc244 239 bool ATParser::vsend(const char *command, va_list args)
chuanga 0:43ff9e3bc244 240 {
chuanga 0:43ff9e3bc244 241 int i = 0, j = 0;
chuanga 0:43ff9e3bc244 242 _bufferMutex.lock();
chuanga 0:43ff9e3bc244 243 // Create and send command
chuanga 0:43ff9e3bc244 244 if (vsprintf(_buffer, command, args) < 0) {
chuanga 0:43ff9e3bc244 245 _bufferMutex.unlock();
chuanga 0:43ff9e3bc244 246 return false;
chuanga 0:43ff9e3bc244 247 }
chuanga 0:43ff9e3bc244 248 /* get buffer length */
chuanga 0:43ff9e3bc244 249 for (i = 0; _buffer[i]; i++) {
chuanga 0:43ff9e3bc244 250 }
chuanga 0:43ff9e3bc244 251
chuanga 0:43ff9e3bc244 252 for (j = 0; _delimiter[j]; j++) {
chuanga 0:43ff9e3bc244 253 _buffer[i + j] = _delimiter[j];
chuanga 0:43ff9e3bc244 254 }
chuanga 0:43ff9e3bc244 255 _buffer[i + j] = 0; // only to get a clean debug log
chuanga 0:43ff9e3bc244 256
chuanga 0:43ff9e3bc244 257 bool ret = !(_serial_spi->buffwrite(_buffer, i + j) < 0);
chuanga 0:43ff9e3bc244 258
chuanga 0:43ff9e3bc244 259 debug_if(AT_COMMAND_PRINT, "AT> %s\n", _buffer);
chuanga 0:43ff9e3bc244 260 _bufferMutex.unlock();
chuanga 0:43ff9e3bc244 261 return ret;
chuanga 0:43ff9e3bc244 262 }
chuanga 0:43ff9e3bc244 263
chuanga 0:43ff9e3bc244 264 bool ATParser::vrecv(const char *response, va_list args)
chuanga 0:43ff9e3bc244 265 {
chuanga 0:43ff9e3bc244 266 _bufferMutex.lock();
chuanga 0:43ff9e3bc244 267
chuanga 0:43ff9e3bc244 268 if (!_serial_spi->readable()) {
chuanga 0:43ff9e3bc244 269 // debug_if(dbg_on, "NO DATA, read again\r\n");
chuanga 0:43ff9e3bc244 270 if (_serial_spi->read() < 0) {
chuanga 0:43ff9e3bc244 271 return false;
chuanga 0:43ff9e3bc244 272 }
chuanga 0:43ff9e3bc244 273 }
chuanga 0:43ff9e3bc244 274 // else {
chuanga 0:43ff9e3bc244 275 // debug_if(dbg_on, "Pending data\r\n");
chuanga 0:43ff9e3bc244 276 // }
chuanga 0:43ff9e3bc244 277
chuanga 0:43ff9e3bc244 278 restart:
chuanga 0:43ff9e3bc244 279 _aborted = false;
chuanga 0:43ff9e3bc244 280 // Iterate through each line in the expected response
chuanga 0:43ff9e3bc244 281 while (response[0]) {
chuanga 0:43ff9e3bc244 282 // Since response is const, we need to copy it into our buffer to
chuanga 0:43ff9e3bc244 283 // add the line's null terminator and clobber value-matches with asterisks.
chuanga 0:43ff9e3bc244 284 //
chuanga 0:43ff9e3bc244 285 // We just use the beginning of the buffer to avoid unnecessary allocations.
chuanga 0:43ff9e3bc244 286 int i = 0;
chuanga 0:43ff9e3bc244 287 int offset = 0;
chuanga 0:43ff9e3bc244 288 bool whole_line_wanted = false;
chuanga 0:43ff9e3bc244 289
chuanga 0:43ff9e3bc244 290 while (response[i]) {
chuanga 0:43ff9e3bc244 291 if (response[i] == '%' && response[i + 1] != '%' && response[i + 1] != '*') {
chuanga 0:43ff9e3bc244 292 _buffer[offset++] = '%';
chuanga 0:43ff9e3bc244 293 _buffer[offset++] = '*';
chuanga 0:43ff9e3bc244 294 i++;
chuanga 0:43ff9e3bc244 295 } else {
chuanga 0:43ff9e3bc244 296 _buffer[offset++] = response[i++];
chuanga 0:43ff9e3bc244 297 // Find linebreaks, taking care not to be fooled if they're in a %[^\n] conversion specification
chuanga 0:43ff9e3bc244 298 if (response[i - 1] == '\n' && !(i >= 3 && response[i - 3] == '[' && response[i - 2] == '^')) {
chuanga 0:43ff9e3bc244 299 whole_line_wanted = true;
chuanga 0:43ff9e3bc244 300 break;
chuanga 0:43ff9e3bc244 301 }
chuanga 0:43ff9e3bc244 302 }
chuanga 0:43ff9e3bc244 303 }
chuanga 0:43ff9e3bc244 304
chuanga 0:43ff9e3bc244 305 // Scanf has very poor support for catching errors
chuanga 0:43ff9e3bc244 306 // fortunately, we can abuse the %n specifier to determine
chuanga 0:43ff9e3bc244 307 // if the entire string was matched.
chuanga 0:43ff9e3bc244 308 _buffer[offset++] = '%';
chuanga 0:43ff9e3bc244 309 _buffer[offset++] = 'n';
chuanga 0:43ff9e3bc244 310 _buffer[offset++] = 0;
chuanga 0:43ff9e3bc244 311
chuanga 0:43ff9e3bc244 312 // debug_if(dbg_on, "ATParser vrecv: AT? ====%s====\n", _buffer);
chuanga 0:43ff9e3bc244 313 // To workaround scanf's lack of error reporting, we actually
chuanga 0:43ff9e3bc244 314 // make two passes. One checks the validity with the modified
chuanga 0:43ff9e3bc244 315 // format string that only stores the matched characters (%n).
chuanga 0:43ff9e3bc244 316 // The other reads in the actual matched values.
chuanga 0:43ff9e3bc244 317 //
chuanga 0:43ff9e3bc244 318 // We keep trying the match until we succeed or some other error
chuanga 0:43ff9e3bc244 319 // derails us.
chuanga 0:43ff9e3bc244 320 int j = 0;
chuanga 0:43ff9e3bc244 321
chuanga 0:43ff9e3bc244 322 while (true) {
chuanga 0:43ff9e3bc244 323 // Recieve next character
chuanga 0:43ff9e3bc244 324 int c = getc();
chuanga 0:43ff9e3bc244 325 if (c < 0) {
chuanga 0:43ff9e3bc244 326 debug_if(dbg_on, "AT(Timeout)\n");
chuanga 0:43ff9e3bc244 327 _bufferMutex.unlock();
chuanga 0:43ff9e3bc244 328 return false;
chuanga 0:43ff9e3bc244 329 }
chuanga 0:43ff9e3bc244 330
chuanga 0:43ff9e3bc244 331 // debug_if(AT_DATA_PRINT, "%2X ", c);
chuanga 0:43ff9e3bc244 332
chuanga 0:43ff9e3bc244 333 _buffer[offset + j++] = c;
chuanga 0:43ff9e3bc244 334 _buffer[offset + j] = 0;
chuanga 0:43ff9e3bc244 335
chuanga 0:43ff9e3bc244 336 // Check for oob data
chuanga 0:43ff9e3bc244 337 for (struct oob *oob = _oobs; oob; oob = oob->next) {
chuanga 0:43ff9e3bc244 338 if ((unsigned)j == oob->len && memcmp(
chuanga 0:43ff9e3bc244 339 oob->prefix, _buffer + offset, oob->len) == 0) {
chuanga 0:43ff9e3bc244 340 debug_if(dbg_on, "AT! %s\n", oob->prefix);
chuanga 0:43ff9e3bc244 341 oob->cb();
chuanga 0:43ff9e3bc244 342
chuanga 0:43ff9e3bc244 343 if (_aborted) {
chuanga 0:43ff9e3bc244 344 debug_if(dbg_on, "AT(Aborted)\n");
chuanga 0:43ff9e3bc244 345 _bufferMutex.unlock();
chuanga 0:43ff9e3bc244 346 return false;
chuanga 0:43ff9e3bc244 347 }
chuanga 0:43ff9e3bc244 348 // oob may have corrupted non-reentrant buffer,
chuanga 0:43ff9e3bc244 349 // so we need to set it up again
chuanga 0:43ff9e3bc244 350 goto restart;
chuanga 0:43ff9e3bc244 351 }
chuanga 0:43ff9e3bc244 352 }
chuanga 0:43ff9e3bc244 353
chuanga 0:43ff9e3bc244 354 // Check for match
chuanga 0:43ff9e3bc244 355 int count = -1;
chuanga 0:43ff9e3bc244 356 if (whole_line_wanted && c != '\n') {
chuanga 0:43ff9e3bc244 357 // Don't attempt scanning until we get delimiter if they included it in format
chuanga 0:43ff9e3bc244 358 // This allows recv("Foo: %s\n") to work, and not match with just the first character of a string
chuanga 0:43ff9e3bc244 359 // (scanf does not itself match whitespace in its format string, so \n is not significant to it)
chuanga 0:43ff9e3bc244 360 } else {
chuanga 0:43ff9e3bc244 361 sscanf(_buffer + offset, _buffer, &count);
chuanga 0:43ff9e3bc244 362 }
chuanga 0:43ff9e3bc244 363
chuanga 0:43ff9e3bc244 364 // We only succeed if all characters in the response are matched
chuanga 0:43ff9e3bc244 365 if (count == j) {
chuanga 0:43ff9e3bc244 366 debug_if(AT_COMMAND_PRINT, "AT= ====%s====\n", _buffer + offset);
chuanga 0:43ff9e3bc244 367 // Reuse the front end of the buffer
chuanga 0:43ff9e3bc244 368 memcpy(_buffer, response, i);
chuanga 0:43ff9e3bc244 369 _buffer[i] = 0;
chuanga 0:43ff9e3bc244 370
chuanga 0:43ff9e3bc244 371 // Store the found results
chuanga 0:43ff9e3bc244 372 vsscanf(_buffer + offset, _buffer, args);
chuanga 0:43ff9e3bc244 373
chuanga 0:43ff9e3bc244 374 // Jump to next line and continue parsing
chuanga 0:43ff9e3bc244 375 response += i;
chuanga 0:43ff9e3bc244 376 break;
chuanga 0:43ff9e3bc244 377 }
chuanga 0:43ff9e3bc244 378
chuanga 0:43ff9e3bc244 379 // Clear the buffer when we hit a newline or ran out of space
chuanga 0:43ff9e3bc244 380 // running out of space usually means we ran into binary data
chuanga 0:43ff9e3bc244 381 if ((c == '\n')) {
chuanga 0:43ff9e3bc244 382 // debug_if(dbg_on, "New line AT<<< %s", _buffer+offset);
chuanga 0:43ff9e3bc244 383 j = 0;
chuanga 0:43ff9e3bc244 384 }
chuanga 0:43ff9e3bc244 385 if ((j + 1 >= (_buffer_size - offset))) {
chuanga 0:43ff9e3bc244 386
chuanga 0:43ff9e3bc244 387 debug_if(dbg_on, "Out of space AT<<< %s, j=%d", _buffer + offset, j);
chuanga 0:43ff9e3bc244 388 j = 0;
chuanga 0:43ff9e3bc244 389 }
chuanga 0:43ff9e3bc244 390 }
chuanga 0:43ff9e3bc244 391 }
chuanga 0:43ff9e3bc244 392
chuanga 0:43ff9e3bc244 393 _bufferMutex.unlock();
chuanga 0:43ff9e3bc244 394
chuanga 0:43ff9e3bc244 395 return true;
chuanga 0:43ff9e3bc244 396 }
chuanga 0:43ff9e3bc244 397
chuanga 0:43ff9e3bc244 398
chuanga 0:43ff9e3bc244 399 // Mapping to vararg functions
chuanga 0:43ff9e3bc244 400 int ATParser::printf(const char *format, ...)
chuanga 0:43ff9e3bc244 401 {
chuanga 0:43ff9e3bc244 402 va_list args;
chuanga 0:43ff9e3bc244 403 va_start(args, format);
chuanga 0:43ff9e3bc244 404 int res = vprintf(format, args);
chuanga 0:43ff9e3bc244 405 va_end(args);
chuanga 0:43ff9e3bc244 406 return res;
chuanga 0:43ff9e3bc244 407 }
chuanga 0:43ff9e3bc244 408
chuanga 0:43ff9e3bc244 409 int ATParser::scanf(const char *format, ...)
chuanga 0:43ff9e3bc244 410 {
chuanga 0:43ff9e3bc244 411 va_list args;
chuanga 0:43ff9e3bc244 412 va_start(args, format);
chuanga 0:43ff9e3bc244 413 int res = vscanf(format, args);
chuanga 0:43ff9e3bc244 414 va_end(args);
chuanga 0:43ff9e3bc244 415 return res;
chuanga 0:43ff9e3bc244 416 }
chuanga 0:43ff9e3bc244 417
chuanga 0:43ff9e3bc244 418 bool ATParser::send(const char *command, ...)
chuanga 0:43ff9e3bc244 419 {
chuanga 0:43ff9e3bc244 420 va_list args;
chuanga 0:43ff9e3bc244 421 va_start(args, command);
chuanga 0:43ff9e3bc244 422 bool res = vsend(command, args);
chuanga 0:43ff9e3bc244 423 va_end(args);
chuanga 0:43ff9e3bc244 424 return res;
chuanga 0:43ff9e3bc244 425 }
chuanga 0:43ff9e3bc244 426
chuanga 0:43ff9e3bc244 427 bool ATParser::recv(const char *response, ...)
chuanga 0:43ff9e3bc244 428 {
chuanga 0:43ff9e3bc244 429 va_list args;
chuanga 0:43ff9e3bc244 430 va_start(args, response);
chuanga 0:43ff9e3bc244 431 bool res = vrecv(response, args);
chuanga 0:43ff9e3bc244 432 va_end(args);
chuanga 0:43ff9e3bc244 433 return res;
chuanga 0:43ff9e3bc244 434 }
chuanga 0:43ff9e3bc244 435
chuanga 0:43ff9e3bc244 436
chuanga 0:43ff9e3bc244 437 // oob registration
chuanga 0:43ff9e3bc244 438 void ATParser::oob(const char *prefix, Callback<void()> cb)
chuanga 0:43ff9e3bc244 439 {
chuanga 0:43ff9e3bc244 440 struct oob *oob = new struct oob;
chuanga 0:43ff9e3bc244 441 oob->len = strlen(prefix);
chuanga 0:43ff9e3bc244 442 oob->prefix = prefix;
chuanga 0:43ff9e3bc244 443 oob->cb = cb;
chuanga 0:43ff9e3bc244 444 oob->next = _oobs;
chuanga 0:43ff9e3bc244 445 _oobs = oob;
chuanga 0:43ff9e3bc244 446 }
chuanga 0:43ff9e3bc244 447
chuanga 0:43ff9e3bc244 448 void ATParser::abort()
chuanga 0:43ff9e3bc244 449 {
chuanga 0:43ff9e3bc244 450 _aborted = true;
chuanga 0:43ff9e3bc244 451 }
chuanga 0:43ff9e3bc244 452
chuanga 0:43ff9e3bc244 453
chuanga 0:43ff9e3bc244 454