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
source/main.cpp@77:85a0d3cdd896, 2019-01-25 (annotated)
- 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?
User | Revision | Line number | New 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 | } |