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:
mbed_official
Date:
Fri Jan 25 15:15:20 2019 +0000
Revision:
77:85a0d3cdd896
Parent:
75:1a8d19363522
Child:
81:816977af0b75
Fix SafeEnum comparison.

.
Commit copied from https://github.com/ARMmbed/mbed-os-example-ble

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"
mbed_official 75:1a8d19363522 24 #include "pretty_printer.h"
Vincent Coubard 0:86bf1d2040b3 25
mbed_official 75:1a8d19363522 26 const static char PEER_NAME[] = "LED";
Vincent Coubard 0:86bf1d2040b3 27
mbed_official 75:1a8d19363522 28 static EventQueue event_queue(/* event count */ 10 * EVENTS_EVENT_SIZE);
Vincent Coubard 0:86bf1d2040b3 29
mbed_official 75:1a8d19363522 30 static DiscoveredCharacteristic led_characteristic;
mbed_official 75:1a8d19363522 31 static bool trigger_led_characteristic = false;
Vincent Coubard 0:86bf1d2040b3 32
mbed_official 75:1a8d19363522 33 void service_discovery(const DiscoveredService *service) {
Vincent Coubard 0:86bf1d2040b3 34 if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
Vincent Coubard 0:86bf1d2040b3 35 printf("S UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle());
Vincent Coubard 0:86bf1d2040b3 36 } else {
Vincent Coubard 0:86bf1d2040b3 37 printf("S UUID-");
Vincent Coubard 0:86bf1d2040b3 38 const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
Vincent Coubard 0:86bf1d2040b3 39 for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
Vincent Coubard 0:86bf1d2040b3 40 printf("%02x", longUUIDBytes[i]);
Vincent Coubard 0:86bf1d2040b3 41 }
Vincent Coubard 0:86bf1d2040b3 42 printf(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
Vincent Coubard 0:86bf1d2040b3 43 }
Vincent Coubard 0:86bf1d2040b3 44 }
Vincent Coubard 0:86bf1d2040b3 45
mbed_official 75:1a8d19363522 46 void update_led_characteristic(void) {
Vincent Coubard 0:86bf1d2040b3 47 if (!BLE::Instance().gattClient().isServiceDiscoveryActive()) {
mbed_official 75:1a8d19363522 48 led_characteristic.read();
Vincent Coubard 0:86bf1d2040b3 49 }
Vincent Coubard 0:86bf1d2040b3 50 }
Vincent Coubard 0:86bf1d2040b3 51
mbed_official 75:1a8d19363522 52 void characteristic_discovery(const DiscoveredCharacteristic *characteristicP) {
mbed_official 75:1a8d19363522 53 printf(" C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getUUID().getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
mbed_official 75:1a8d19363522 54 if (characteristicP->getUUID().getShortUUID() == 0xa001) { /* !ALERT! Alter this filter to suit your device. */
mbed_official 75:1a8d19363522 55 led_characteristic = *characteristicP;
mbed_official 75:1a8d19363522 56 trigger_led_characteristic = true;
Vincent Coubard 0:86bf1d2040b3 57 }
Vincent Coubard 0:86bf1d2040b3 58 }
Vincent Coubard 0:86bf1d2040b3 59
mbed_official 75:1a8d19363522 60 void discovery_termination(Gap::Handle_t connectionHandle) {
mbed_official 75:1a8d19363522 61 printf("terminated SD for handle %u\r\n", connectionHandle);
mbed_official 75:1a8d19363522 62 if (trigger_led_characteristic) {
mbed_official 75:1a8d19363522 63 trigger_led_characteristic = false;
mbed_official 75:1a8d19363522 64 event_queue.call(update_led_characteristic);
Vincent Coubard 0:86bf1d2040b3 65 }
Vincent Coubard 0:86bf1d2040b3 66 }
Vincent Coubard 0:86bf1d2040b3 67
mbed_official 75:1a8d19363522 68 void trigger_toggled_write(const GattReadCallbackParams *response) {
mbed_official 75:1a8d19363522 69 if (response->handle == led_characteristic.getValueHandle()) {
mbed_official 75:1a8d19363522 70 printf("trigger_toggled_write: handle %u, offset %u, len %u\r\n", response->handle, response->offset, response->len);
Vincent Coubard 0:86bf1d2040b3 71 for (unsigned index = 0; index < response->len; index++) {
Vincent Coubard 0:86bf1d2040b3 72 printf("%c[%02x]", response->data[index], response->data[index]);
Vincent Coubard 0:86bf1d2040b3 73 }
Vincent Coubard 0:86bf1d2040b3 74 printf("\r\n");
Vincent Coubard 0:86bf1d2040b3 75
Vincent Coubard 0:86bf1d2040b3 76 uint8_t toggledValue = response->data[0] ^ 0x1;
mbed_official 75:1a8d19363522 77 led_characteristic.write(1, &toggledValue);
Vincent Coubard 0:86bf1d2040b3 78 }
Vincent Coubard 0:86bf1d2040b3 79 }
Vincent Coubard 0:86bf1d2040b3 80
mbed_official 75:1a8d19363522 81 void trigger_read(const GattWriteCallbackParams *response) {
mbed_official 75:1a8d19363522 82 if (response->handle == led_characteristic.getValueHandle()) {
mbed_official 75:1a8d19363522 83 led_characteristic.read();
Vincent Coubard 0:86bf1d2040b3 84 }
Vincent Coubard 0:86bf1d2040b3 85 }
Vincent Coubard 0:86bf1d2040b3 86
mbed_official 75:1a8d19363522 87 class LEDBlinkerDemo : ble::Gap::EventHandler {
mbed_official 75:1a8d19363522 88 public:
mbed_official 75:1a8d19363522 89 LEDBlinkerDemo(BLE &ble, events::EventQueue &event_queue) :
mbed_official 75:1a8d19363522 90 _ble(ble),
mbed_official 75:1a8d19363522 91 _event_queue(event_queue),
mbed_official 75:1a8d19363522 92 _alive_led(LED1, 1),
mbed_official 75:1a8d19363522 93 _actuated_led(LED2, 0),
mbed_official 75:1a8d19363522 94 _is_connecting(false) { }
Vincent Coubard 0:86bf1d2040b3 95
mbed_official 75:1a8d19363522 96 ~LEDBlinkerDemo() { }
mbed_official 75:1a8d19363522 97
mbed_official 75:1a8d19363522 98 void start() {
mbed_official 75:1a8d19363522 99 _ble.gap().setEventHandler(this);
mbed_official 75:1a8d19363522 100
mbed_official 75:1a8d19363522 101 _ble.init(this, &LEDBlinkerDemo::on_init_complete);
mbed_official 75:1a8d19363522 102
mbed_official 75:1a8d19363522 103 _event_queue.call_every(500, this, &LEDBlinkerDemo::blink);
mbed_official 75:1a8d19363522 104
mbed_official 75:1a8d19363522 105 _event_queue.dispatch_forever();
mbed_official 75:1a8d19363522 106 }
Vincent Coubard 0:86bf1d2040b3 107
mbed_official 75:1a8d19363522 108 private:
mbed_official 75:1a8d19363522 109 /** Callback triggered when the ble initialization process has finished */
mbed_official 75:1a8d19363522 110 void on_init_complete(BLE::InitializationCompleteCallbackContext *params) {
mbed_official 75:1a8d19363522 111 if (params->error != BLE_ERROR_NONE) {
mbed_official 75:1a8d19363522 112 printf("Ble initialization failed.");
mbed_official 75:1a8d19363522 113 return;
mbed_official 75:1a8d19363522 114 }
mbed_official 75:1a8d19363522 115
mbed_official 75:1a8d19363522 116 print_mac_address();
mbed_official 75:1a8d19363522 117
mbed_official 75:1a8d19363522 118 _ble.gattClient().onDataRead(trigger_toggled_write);
mbed_official 75:1a8d19363522 119 _ble.gattClient().onDataWritten(trigger_read);
mbed_official 75:1a8d19363522 120
mbed_official 75:1a8d19363522 121 ble::ScanParameters scan_params;
mbed_official 75:1a8d19363522 122 _ble.gap().setScanParameters(scan_params);
mbed_official 75:1a8d19363522 123 _ble.gap().startScan();
mbed_official 45:9fe6d1e21b8a 124 }
mbed_official 75:1a8d19363522 125
mbed_official 75:1a8d19363522 126 void blink() {
mbed_official 75:1a8d19363522 127 _alive_led = !_alive_led;
mbed_official 75:1a8d19363522 128 }
mbed_official 45:9fe6d1e21b8a 129
mbed_official 75:1a8d19363522 130 private:
mbed_official 75:1a8d19363522 131 /* Event handler */
Vincent Coubard 0:86bf1d2040b3 132
mbed_official 75:1a8d19363522 133 void onDisconnectionComplete(const ble::DisconnectionCompleteEvent&) {
mbed_official 75:1a8d19363522 134 _ble.gap().startScan();
mbed_official 75:1a8d19363522 135 _is_connecting = false;
Vincent Coubard 0:86bf1d2040b3 136 }
Vincent Coubard 0:86bf1d2040b3 137
mbed_official 75:1a8d19363522 138 void onConnectionComplete(const ble::ConnectionCompleteEvent& event) {
mbed_official 77:85a0d3cdd896 139 if (event.getOwnRole() == ble::connection_role_t::CENTRAL) {
mbed_official 75:1a8d19363522 140 _ble.gattClient().onServiceDiscoveryTermination(discovery_termination);
mbed_official 75:1a8d19363522 141 _ble.gattClient().launchServiceDiscovery(
mbed_official 75:1a8d19363522 142 event.getConnectionHandle(),
mbed_official 75:1a8d19363522 143 service_discovery,
mbed_official 75:1a8d19363522 144 characteristic_discovery,
mbed_official 75:1a8d19363522 145 0xa000,
mbed_official 75:1a8d19363522 146 0xa001
mbed_official 75:1a8d19363522 147 );
mbed_official 75:1a8d19363522 148 } else {
mbed_official 75:1a8d19363522 149 _ble.gap().startScan();
mbed_official 75:1a8d19363522 150 }
mbed_official 75:1a8d19363522 151 _is_connecting = false;
Vincent Coubard 0:86bf1d2040b3 152 }
Vincent Coubard 0:86bf1d2040b3 153
mbed_official 75:1a8d19363522 154 void onAdvertisingReport(const ble::AdvertisingReportEvent &event) {
mbed_official 75:1a8d19363522 155 /* don't bother with analysing scan result if we're already connecting */
mbed_official 75:1a8d19363522 156 if (_is_connecting) {
mbed_official 75:1a8d19363522 157 return;
mbed_official 75:1a8d19363522 158 }
mbed_official 75:1a8d19363522 159
mbed_official 75:1a8d19363522 160 ble::AdvertisingDataParser adv_data(event.getPayload());
mbed_official 75:1a8d19363522 161
mbed_official 75:1a8d19363522 162 /* parse the advertising payload, looking for a discoverable device */
mbed_official 75:1a8d19363522 163 while (adv_data.hasNext()) {
mbed_official 75:1a8d19363522 164 ble::AdvertisingDataParser::element_t field = adv_data.next();
Vincent Coubard 0:86bf1d2040b3 165
mbed_official 75:1a8d19363522 166 /* connect to a discoverable device */
mbed_official 75:1a8d19363522 167 if (field.type == ble::adv_data_type_t::COMPLETE_LOCAL_NAME &&
mbed_official 75:1a8d19363522 168 field.value.size() == strlen(PEER_NAME) &&
mbed_official 75:1a8d19363522 169 (memcmp(field.value.data(), PEER_NAME, field.value.size()) == 0)) {
mbed_official 75:1a8d19363522 170
mbed_official 75:1a8d19363522 171 printf("Adv from: ");
mbed_official 75:1a8d19363522 172 print_address(event.getPeerAddress().data());
mbed_official 75:1a8d19363522 173 printf(" rssi: %d, scan response: %u, connectable: %u\r\n",
mbed_official 75:1a8d19363522 174 event.getRssi(), event.getType().scan_response(), event.getType().connectable());
mbed_official 75:1a8d19363522 175
mbed_official 75:1a8d19363522 176 ble_error_t error = _ble.gap().stopScan();
mbed_official 75:1a8d19363522 177
mbed_official 75:1a8d19363522 178 if (error) {
mbed_official 75:1a8d19363522 179 print_error(error, "Error caused by Gap::stopScan");
mbed_official 75:1a8d19363522 180 return;
mbed_official 75:1a8d19363522 181 }
mbed_official 75:1a8d19363522 182
mbed_official 75:1a8d19363522 183 const ble::ConnectionParameters connection_params;
Vincent Coubard 0:86bf1d2040b3 184
mbed_official 75:1a8d19363522 185 error = _ble.gap().connect(
mbed_official 75:1a8d19363522 186 event.getPeerAddressType(),
mbed_official 75:1a8d19363522 187 event.getPeerAddress(),
mbed_official 75:1a8d19363522 188 connection_params
mbed_official 75:1a8d19363522 189 );
mbed_official 75:1a8d19363522 190
mbed_official 75:1a8d19363522 191 if (error) {
mbed_official 75:1a8d19363522 192 _ble.gap().startScan();
mbed_official 75:1a8d19363522 193 return;
mbed_official 75:1a8d19363522 194 }
mbed_official 75:1a8d19363522 195
mbed_official 75:1a8d19363522 196 /* we may have already scan events waiting
mbed_official 75:1a8d19363522 197 * to be processed so we need to remember
mbed_official 75:1a8d19363522 198 * that we are already connecting and ignore them */
mbed_official 75:1a8d19363522 199 _is_connecting = true;
mbed_official 45:9fe6d1e21b8a 200
mbed_official 75:1a8d19363522 201 return;
mbed_official 75:1a8d19363522 202 }
mbed_official 75:1a8d19363522 203 }
mbed_official 75:1a8d19363522 204 }
Vincent Coubard 0:86bf1d2040b3 205
mbed_official 75:1a8d19363522 206 private:
mbed_official 75:1a8d19363522 207 BLE &_ble;
mbed_official 75:1a8d19363522 208 events::EventQueue &_event_queue;
mbed_official 75:1a8d19363522 209 DigitalOut _alive_led;
mbed_official 75:1a8d19363522 210 DigitalOut _actuated_led;
mbed_official 75:1a8d19363522 211 bool _is_connecting;
mbed_official 75:1a8d19363522 212 };
mbed_official 75:1a8d19363522 213
mbed_official 75:1a8d19363522 214 /** Schedule processing of events from the BLE middleware in the event queue. */
mbed_official 75:1a8d19363522 215 void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context) {
mbed_official 75:1a8d19363522 216 event_queue.call(Callback<void()>(&context->ble, &BLE::processEvents));
Vincent Coubard 0:86bf1d2040b3 217 }
Vincent Coubard 0:86bf1d2040b3 218
Vincent Coubard 0:86bf1d2040b3 219 int main()
Vincent Coubard 0:86bf1d2040b3 220 {
mbed_official 75:1a8d19363522 221 BLE &ble = BLE::Instance();
mbed_official 75:1a8d19363522 222 ble.onEventsToProcess(schedule_ble_events);
Vincent Coubard 0:86bf1d2040b3 223
mbed_official 75:1a8d19363522 224 LEDBlinkerDemo demo(ble, event_queue);
mbed_official 75:1a8d19363522 225 demo.start();
Vincent Coubard 0:86bf1d2040b3 226
Vincent Coubard 0:86bf1d2040b3 227 return 0;
Vincent Coubard 0:86bf1d2040b3 228 }