This example demonstrates using the GattClient API to control BLE client devices. The canonical source for this example lives at https://github.com/ARMmbed/mbed-os-example-ble/tree/master/BLE_LEDBlinker

Committer:
sayhuthut
Date:
Thu Mar 07 09:38:15 2019 +0000
Revision:
81:816977af0b75
Parent:
77:85a0d3cdd896
This an example show Central and Peripheral working concurrently.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Vincent Coubard 0:86bf1d2040b3 1 /* mbed Microcontroller Library
Vincent Coubard 0:86bf1d2040b3 2 * Copyright (c) 2006-2015 ARM Limited
Vincent Coubard 0:86bf1d2040b3 3 *
Vincent Coubard 0:86bf1d2040b3 4 * Licensed under the Apache License, Version 2.0 (the "License");
Vincent Coubard 0:86bf1d2040b3 5 * you may not use this file except in compliance with the License.
Vincent Coubard 0:86bf1d2040b3 6 * You may obtain a copy of the License at
Vincent Coubard 0:86bf1d2040b3 7 *
Vincent Coubard 0:86bf1d2040b3 8 * http://www.apache.org/licenses/LICENSE-2.0
Vincent Coubard 0:86bf1d2040b3 9 *
Vincent Coubard 0:86bf1d2040b3 10 * Unless required by applicable law or agreed to in writing, software
Vincent Coubard 0:86bf1d2040b3 11 * distributed under the License is distributed on an "AS IS" BASIS,
Vincent Coubard 0:86bf1d2040b3 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Vincent Coubard 0:86bf1d2040b3 13 * See the License for the specific language governing permissions and
Vincent Coubard 0:86bf1d2040b3 14 * limitations under the License.
Vincent Coubard 0:86bf1d2040b3 15 */
Vincent Coubard 0:86bf1d2040b3 16
mbed_official 12:059c7b7fb18a 17 #include <events/mbed_events.h>
Vincent Coubard 0:86bf1d2040b3 18 #include <mbed.h>
Vincent Coubard 0:86bf1d2040b3 19 #include "ble/BLE.h"
Vincent Coubard 0:86bf1d2040b3 20 #include "ble/DiscoveredCharacteristic.h"
Vincent Coubard 0:86bf1d2040b3 21 #include "ble/DiscoveredService.h"
mbed_official 75:1a8d19363522 22 #include "ble/gap/Gap.h"
mbed_official 75:1a8d19363522 23 #include "ble/gap/AdvertisingDataParser.h"
sayhuthut 81:816977af0b75 24 #include "LEDService.h"
mbed_official 75:1a8d19363522 25 #include "pretty_printer.h"
Vincent Coubard 0:86bf1d2040b3 26
mbed_official 75:1a8d19363522 27 const static char PEER_NAME[] = "LED";
sayhuthut 81:816977af0b75 28 const static char DEVICE_NAME[] = "LED";
Vincent Coubard 0:86bf1d2040b3 29
mbed_official 75:1a8d19363522 30 static EventQueue event_queue(/* event count */ 10 * EVENTS_EVENT_SIZE);
Vincent Coubard 0:86bf1d2040b3 31
mbed_official 75:1a8d19363522 32 static DiscoveredCharacteristic led_characteristic;
mbed_official 75:1a8d19363522 33 static bool trigger_led_characteristic = false;
Vincent Coubard 0:86bf1d2040b3 34
mbed_official 75:1a8d19363522 35 void service_discovery(const DiscoveredService *service) {
Vincent Coubard 0:86bf1d2040b3 36 if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
Vincent Coubard 0:86bf1d2040b3 37 printf("S UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle());
Vincent Coubard 0:86bf1d2040b3 38 } else {
Vincent Coubard 0:86bf1d2040b3 39 printf("S UUID-");
Vincent Coubard 0:86bf1d2040b3 40 const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
Vincent Coubard 0:86bf1d2040b3 41 for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
Vincent Coubard 0:86bf1d2040b3 42 printf("%02x", longUUIDBytes[i]);
Vincent Coubard 0:86bf1d2040b3 43 }
Vincent Coubard 0:86bf1d2040b3 44 printf(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
Vincent Coubard 0:86bf1d2040b3 45 }
Vincent Coubard 0:86bf1d2040b3 46 }
Vincent Coubard 0:86bf1d2040b3 47
mbed_official 75:1a8d19363522 48 void update_led_characteristic(void) {
Vincent Coubard 0:86bf1d2040b3 49 if (!BLE::Instance().gattClient().isServiceDiscoveryActive()) {
mbed_official 75:1a8d19363522 50 led_characteristic.read();
Vincent Coubard 0:86bf1d2040b3 51 }
Vincent Coubard 0:86bf1d2040b3 52 }
Vincent Coubard 0:86bf1d2040b3 53
mbed_official 75:1a8d19363522 54 void characteristic_discovery(const DiscoveredCharacteristic *characteristicP) {
mbed_official 75:1a8d19363522 55 printf(" C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getUUID().getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
mbed_official 75:1a8d19363522 56 if (characteristicP->getUUID().getShortUUID() == 0xa001) { /* !ALERT! Alter this filter to suit your device. */
mbed_official 75:1a8d19363522 57 led_characteristic = *characteristicP;
mbed_official 75:1a8d19363522 58 trigger_led_characteristic = true;
Vincent Coubard 0:86bf1d2040b3 59 }
Vincent Coubard 0:86bf1d2040b3 60 }
Vincent Coubard 0:86bf1d2040b3 61
mbed_official 75:1a8d19363522 62 void discovery_termination(Gap::Handle_t connectionHandle) {
mbed_official 75:1a8d19363522 63 printf("terminated SD for handle %u\r\n", connectionHandle);
mbed_official 75:1a8d19363522 64 if (trigger_led_characteristic) {
mbed_official 75:1a8d19363522 65 trigger_led_characteristic = false;
mbed_official 75:1a8d19363522 66 event_queue.call(update_led_characteristic);
Vincent Coubard 0:86bf1d2040b3 67 }
Vincent Coubard 0:86bf1d2040b3 68 }
Vincent Coubard 0:86bf1d2040b3 69
mbed_official 75:1a8d19363522 70 void trigger_toggled_write(const GattReadCallbackParams *response) {
mbed_official 75:1a8d19363522 71 if (response->handle == led_characteristic.getValueHandle()) {
mbed_official 75:1a8d19363522 72 printf("trigger_toggled_write: handle %u, offset %u, len %u\r\n", response->handle, response->offset, response->len);
Vincent Coubard 0:86bf1d2040b3 73 for (unsigned index = 0; index < response->len; index++) {
Vincent Coubard 0:86bf1d2040b3 74 printf("%c[%02x]", response->data[index], response->data[index]);
Vincent Coubard 0:86bf1d2040b3 75 }
Vincent Coubard 0:86bf1d2040b3 76 printf("\r\n");
Vincent Coubard 0:86bf1d2040b3 77
Vincent Coubard 0:86bf1d2040b3 78 uint8_t toggledValue = response->data[0] ^ 0x1;
mbed_official 75:1a8d19363522 79 led_characteristic.write(1, &toggledValue);
Vincent Coubard 0:86bf1d2040b3 80 }
Vincent Coubard 0:86bf1d2040b3 81 }
Vincent Coubard 0:86bf1d2040b3 82
mbed_official 75:1a8d19363522 83 void trigger_read(const GattWriteCallbackParams *response) {
mbed_official 75:1a8d19363522 84 if (response->handle == led_characteristic.getValueHandle()) {
mbed_official 75:1a8d19363522 85 led_characteristic.read();
Vincent Coubard 0:86bf1d2040b3 86 }
Vincent Coubard 0:86bf1d2040b3 87 }
Vincent Coubard 0:86bf1d2040b3 88
mbed_official 75:1a8d19363522 89 class LEDBlinkerDemo : ble::Gap::EventHandler {
mbed_official 75:1a8d19363522 90 public:
mbed_official 75:1a8d19363522 91 LEDBlinkerDemo(BLE &ble, events::EventQueue &event_queue) :
mbed_official 75:1a8d19363522 92 _ble(ble),
mbed_official 75:1a8d19363522 93 _event_queue(event_queue),
mbed_official 75:1a8d19363522 94 _alive_led(LED1, 1),
mbed_official 75:1a8d19363522 95 _actuated_led(LED2, 0),
sayhuthut 81:816977af0b75 96 _is_connecting(false),
sayhuthut 81:816977af0b75 97 _led_uuid(LEDService::LED_SERVICE_UUID),
sayhuthut 81:816977af0b75 98 _led_service(NULL),
sayhuthut 81:816977af0b75 99 _adv_data_builder(_adv_buffer) { }
Vincent Coubard 0:86bf1d2040b3 100
mbed_official 75:1a8d19363522 101 ~LEDBlinkerDemo() { }
mbed_official 75:1a8d19363522 102
mbed_official 75:1a8d19363522 103 void start() {
mbed_official 75:1a8d19363522 104 _ble.gap().setEventHandler(this);
mbed_official 75:1a8d19363522 105
mbed_official 75:1a8d19363522 106 _ble.init(this, &LEDBlinkerDemo::on_init_complete);
mbed_official 75:1a8d19363522 107
mbed_official 75:1a8d19363522 108 _event_queue.call_every(500, this, &LEDBlinkerDemo::blink);
mbed_official 75:1a8d19363522 109
mbed_official 75:1a8d19363522 110 _event_queue.dispatch_forever();
mbed_official 75:1a8d19363522 111 }
Vincent Coubard 0:86bf1d2040b3 112
sayhuthut 81:816977af0b75 113 void start_advertising() {
sayhuthut 81:816977af0b75 114 /* Create advertising parameters and payload */
sayhuthut 81:816977af0b75 115
sayhuthut 81:816977af0b75 116 ble::AdvertisingParameters adv_parameters(
sayhuthut 81:816977af0b75 117 ble::advertising_type_t::CONNECTABLE_UNDIRECTED,
sayhuthut 81:816977af0b75 118 ble::adv_interval_t(ble::millisecond_t(1000))
sayhuthut 81:816977af0b75 119 );
sayhuthut 81:816977af0b75 120
sayhuthut 81:816977af0b75 121 _adv_data_builder.setFlags();
sayhuthut 81:816977af0b75 122 _adv_data_builder.setLocalServiceList(mbed::make_Span(&_led_uuid, 1));
sayhuthut 81:816977af0b75 123 _adv_data_builder.setName(DEVICE_NAME);
sayhuthut 81:816977af0b75 124
sayhuthut 81:816977af0b75 125 /* Setup advertising */
sayhuthut 81:816977af0b75 126
sayhuthut 81:816977af0b75 127 ble_error_t error = _ble.gap().setAdvertisingParameters(
sayhuthut 81:816977af0b75 128 ble::LEGACY_ADVERTISING_HANDLE,
sayhuthut 81:816977af0b75 129 adv_parameters
sayhuthut 81:816977af0b75 130 );
sayhuthut 81:816977af0b75 131
sayhuthut 81:816977af0b75 132 if (error) {
sayhuthut 81:816977af0b75 133 printf("_ble.gap().setAdvertisingParameters() failed\r\n");
sayhuthut 81:816977af0b75 134 return;
sayhuthut 81:816977af0b75 135 }
sayhuthut 81:816977af0b75 136
sayhuthut 81:816977af0b75 137 error = _ble.gap().setAdvertisingPayload(
sayhuthut 81:816977af0b75 138 ble::LEGACY_ADVERTISING_HANDLE,
sayhuthut 81:816977af0b75 139 _adv_data_builder.getAdvertisingData()
sayhuthut 81:816977af0b75 140 );
sayhuthut 81:816977af0b75 141
sayhuthut 81:816977af0b75 142 if (error) {
sayhuthut 81:816977af0b75 143 printf("_ble.gap().setAdvertisingPayload() failed\r\n");
sayhuthut 81:816977af0b75 144 return;
sayhuthut 81:816977af0b75 145 }
sayhuthut 81:816977af0b75 146
sayhuthut 81:816977af0b75 147 /* Start advertising */
sayhuthut 81:816977af0b75 148
sayhuthut 81:816977af0b75 149 error = _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
sayhuthut 81:816977af0b75 150
sayhuthut 81:816977af0b75 151 if (error) {
sayhuthut 81:816977af0b75 152 printf("_ble.gap().startAdvertising() failed\r\n");
sayhuthut 81:816977af0b75 153 return;
sayhuthut 81:816977af0b75 154 }
sayhuthut 81:816977af0b75 155 }
sayhuthut 81:816977af0b75 156
mbed_official 75:1a8d19363522 157 private:
mbed_official 75:1a8d19363522 158 /** Callback triggered when the ble initialization process has finished */
mbed_official 75:1a8d19363522 159 void on_init_complete(BLE::InitializationCompleteCallbackContext *params) {
mbed_official 75:1a8d19363522 160 if (params->error != BLE_ERROR_NONE) {
mbed_official 75:1a8d19363522 161 printf("Ble initialization failed.");
mbed_official 75:1a8d19363522 162 return;
mbed_official 75:1a8d19363522 163 }
mbed_official 75:1a8d19363522 164
mbed_official 75:1a8d19363522 165 print_mac_address();
mbed_official 75:1a8d19363522 166
mbed_official 75:1a8d19363522 167 _ble.gattClient().onDataRead(trigger_toggled_write);
mbed_official 75:1a8d19363522 168 _ble.gattClient().onDataWritten(trigger_read);
mbed_official 75:1a8d19363522 169
sayhuthut 81:816977af0b75 170 _led_service = new LEDService(_ble, false);
sayhuthut 81:816977af0b75 171 _ble.gattServer().onDataWritten(this, &LEDBlinkerDemo::on_data_written);
sayhuthut 81:816977af0b75 172
mbed_official 75:1a8d19363522 173 ble::ScanParameters scan_params;
mbed_official 75:1a8d19363522 174 _ble.gap().setScanParameters(scan_params);
mbed_official 75:1a8d19363522 175 _ble.gap().startScan();
mbed_official 45:9fe6d1e21b8a 176 }
mbed_official 75:1a8d19363522 177
mbed_official 75:1a8d19363522 178 void blink() {
mbed_official 75:1a8d19363522 179 _alive_led = !_alive_led;
mbed_official 75:1a8d19363522 180 }
mbed_official 45:9fe6d1e21b8a 181
mbed_official 75:1a8d19363522 182 private:
mbed_official 75:1a8d19363522 183 /* Event handler */
Vincent Coubard 0:86bf1d2040b3 184
mbed_official 75:1a8d19363522 185 void onDisconnectionComplete(const ble::DisconnectionCompleteEvent&) {
mbed_official 75:1a8d19363522 186 _ble.gap().startScan();
mbed_official 75:1a8d19363522 187 _is_connecting = false;
Vincent Coubard 0:86bf1d2040b3 188 }
Vincent Coubard 0:86bf1d2040b3 189
mbed_official 75:1a8d19363522 190 void onConnectionComplete(const ble::ConnectionCompleteEvent& event) {
sayhuthut 81:816977af0b75 191 printf("onConnectionComplete\r\n");
mbed_official 77:85a0d3cdd896 192 if (event.getOwnRole() == ble::connection_role_t::CENTRAL) {
mbed_official 75:1a8d19363522 193 _ble.gattClient().onServiceDiscoveryTermination(discovery_termination);
mbed_official 75:1a8d19363522 194 _ble.gattClient().launchServiceDiscovery(
mbed_official 75:1a8d19363522 195 event.getConnectionHandle(),
mbed_official 75:1a8d19363522 196 service_discovery,
mbed_official 75:1a8d19363522 197 characteristic_discovery,
mbed_official 75:1a8d19363522 198 0xa000,
mbed_official 75:1a8d19363522 199 0xa001
mbed_official 75:1a8d19363522 200 );
sayhuthut 81:816977af0b75 201 printf("Connected as Central, start advertising\r\n");
sayhuthut 81:816977af0b75 202 start_advertising();
sayhuthut 81:816977af0b75 203 } else if (event.getOwnRole() == ble::connection_role_t::PERIPHERAL) {
sayhuthut 81:816977af0b75 204 printf("Connected as Peripheral\r\n");
mbed_official 75:1a8d19363522 205 } else {
mbed_official 75:1a8d19363522 206 _ble.gap().startScan();
mbed_official 75:1a8d19363522 207 }
mbed_official 75:1a8d19363522 208 _is_connecting = false;
Vincent Coubard 0:86bf1d2040b3 209 }
Vincent Coubard 0:86bf1d2040b3 210
mbed_official 75:1a8d19363522 211 void onAdvertisingReport(const ble::AdvertisingReportEvent &event) {
mbed_official 75:1a8d19363522 212 /* don't bother with analysing scan result if we're already connecting */
mbed_official 75:1a8d19363522 213 if (_is_connecting) {
mbed_official 75:1a8d19363522 214 return;
mbed_official 75:1a8d19363522 215 }
mbed_official 75:1a8d19363522 216
mbed_official 75:1a8d19363522 217 ble::AdvertisingDataParser adv_data(event.getPayload());
mbed_official 75:1a8d19363522 218
mbed_official 75:1a8d19363522 219 /* parse the advertising payload, looking for a discoverable device */
mbed_official 75:1a8d19363522 220 while (adv_data.hasNext()) {
mbed_official 75:1a8d19363522 221 ble::AdvertisingDataParser::element_t field = adv_data.next();
Vincent Coubard 0:86bf1d2040b3 222
mbed_official 75:1a8d19363522 223 /* connect to a discoverable device */
mbed_official 75:1a8d19363522 224 if (field.type == ble::adv_data_type_t::COMPLETE_LOCAL_NAME &&
mbed_official 75:1a8d19363522 225 field.value.size() == strlen(PEER_NAME) &&
mbed_official 75:1a8d19363522 226 (memcmp(field.value.data(), PEER_NAME, field.value.size()) == 0)) {
mbed_official 75:1a8d19363522 227
mbed_official 75:1a8d19363522 228 printf("Adv from: ");
mbed_official 75:1a8d19363522 229 print_address(event.getPeerAddress().data());
mbed_official 75:1a8d19363522 230 printf(" rssi: %d, scan response: %u, connectable: %u\r\n",
mbed_official 75:1a8d19363522 231 event.getRssi(), event.getType().scan_response(), event.getType().connectable());
mbed_official 75:1a8d19363522 232
mbed_official 75:1a8d19363522 233 ble_error_t error = _ble.gap().stopScan();
mbed_official 75:1a8d19363522 234
mbed_official 75:1a8d19363522 235 if (error) {
mbed_official 75:1a8d19363522 236 print_error(error, "Error caused by Gap::stopScan");
mbed_official 75:1a8d19363522 237 return;
mbed_official 75:1a8d19363522 238 }
mbed_official 75:1a8d19363522 239
mbed_official 75:1a8d19363522 240 const ble::ConnectionParameters connection_params;
Vincent Coubard 0:86bf1d2040b3 241
mbed_official 75:1a8d19363522 242 error = _ble.gap().connect(
mbed_official 75:1a8d19363522 243 event.getPeerAddressType(),
mbed_official 75:1a8d19363522 244 event.getPeerAddress(),
mbed_official 75:1a8d19363522 245 connection_params
mbed_official 75:1a8d19363522 246 );
mbed_official 75:1a8d19363522 247
mbed_official 75:1a8d19363522 248 if (error) {
mbed_official 75:1a8d19363522 249 _ble.gap().startScan();
mbed_official 75:1a8d19363522 250 return;
mbed_official 75:1a8d19363522 251 }
mbed_official 75:1a8d19363522 252
mbed_official 75:1a8d19363522 253 /* we may have already scan events waiting
mbed_official 75:1a8d19363522 254 * to be processed so we need to remember
mbed_official 75:1a8d19363522 255 * that we are already connecting and ignore them */
mbed_official 75:1a8d19363522 256 _is_connecting = true;
mbed_official 45:9fe6d1e21b8a 257
mbed_official 75:1a8d19363522 258 return;
mbed_official 75:1a8d19363522 259 }
mbed_official 75:1a8d19363522 260 }
mbed_official 75:1a8d19363522 261 }
Vincent Coubard 0:86bf1d2040b3 262
sayhuthut 81:816977af0b75 263 /**
sayhuthut 81:816977af0b75 264 * This callback allows the LEDService to receive updates to the ledState Characteristic.
sayhuthut 81:816977af0b75 265 *
sayhuthut 81:816977af0b75 266 * @param[in] params Information about the characterisitc being updated.
sayhuthut 81:816977af0b75 267 */
sayhuthut 81:816977af0b75 268 void on_data_written(const GattWriteCallbackParams *params) {
sayhuthut 81:816977af0b75 269 printf("led_service getValueHandle() %x\r\n", _led_service->getValueHandle());
sayhuthut 81:816977af0b75 270 printf("on_data_written, handle:%x len:%d\r\n", params->handle, params->len);
sayhuthut 81:816977af0b75 271 if ((params->handle == _led_service->getValueHandle()) && (params->len == 1)) {
sayhuthut 81:816977af0b75 272 _actuated_led = *(params->data);
sayhuthut 81:816977af0b75 273 }
sayhuthut 81:816977af0b75 274 }
sayhuthut 81:816977af0b75 275
mbed_official 75:1a8d19363522 276 private:
mbed_official 75:1a8d19363522 277 BLE &_ble;
mbed_official 75:1a8d19363522 278 events::EventQueue &_event_queue;
mbed_official 75:1a8d19363522 279 DigitalOut _alive_led;
mbed_official 75:1a8d19363522 280 DigitalOut _actuated_led;
mbed_official 75:1a8d19363522 281 bool _is_connecting;
sayhuthut 81:816977af0b75 282
sayhuthut 81:816977af0b75 283 UUID _led_uuid;
sayhuthut 81:816977af0b75 284 LEDService *_led_service;
sayhuthut 81:816977af0b75 285
sayhuthut 81:816977af0b75 286 uint8_t _adv_buffer[ble::LEGACY_ADVERTISING_MAX_SIZE];
sayhuthut 81:816977af0b75 287 ble::AdvertisingDataBuilder _adv_data_builder;
mbed_official 75:1a8d19363522 288 };
mbed_official 75:1a8d19363522 289
sayhuthut 81:816977af0b75 290
mbed_official 75:1a8d19363522 291 /** Schedule processing of events from the BLE middleware in the event queue. */
mbed_official 75:1a8d19363522 292 void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context) {
mbed_official 75:1a8d19363522 293 event_queue.call(Callback<void()>(&context->ble, &BLE::processEvents));
Vincent Coubard 0:86bf1d2040b3 294 }
Vincent Coubard 0:86bf1d2040b3 295
Vincent Coubard 0:86bf1d2040b3 296 int main()
Vincent Coubard 0:86bf1d2040b3 297 {
mbed_official 75:1a8d19363522 298 BLE &ble = BLE::Instance();
mbed_official 75:1a8d19363522 299 ble.onEventsToProcess(schedule_ble_events);
Vincent Coubard 0:86bf1d2040b3 300
mbed_official 75:1a8d19363522 301 LEDBlinkerDemo demo(ble, event_queue);
mbed_official 75:1a8d19363522 302 demo.start();
Vincent Coubard 0:86bf1d2040b3 303
Vincent Coubard 0:86bf1d2040b3 304 return 0;
Vincent Coubard 0:86bf1d2040b3 305 }