This is an example of BLE GATT Client, which receives broadcast data from BLE_Server_BME280 ( a GATT server) , then transfers values up to mbed Device Connector (cloud).

Please refer details about BLEClient_mbedDevConn below. https://github.com/soramame21/BLEClient_mbedDevConn

The location of required BLE GATT server, BLE_Server_BME280, is at here. https://developer.mbed.org/users/edamame22/code/BLE_Server_BME280/

Committer:
Ren Boting
Date:
Tue Sep 05 11:56:13 2017 +0900
Revision:
2:b894b3508057
Parent:
0:29983394c6b6
Update all libraries and reform main.cpp

Who changed what in which revision?

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