Example of BLE scan/connect/service discovery

Fork of BLE_LEDBlinker by Bluetooth Low Energy

Committer:
tsungta
Date:
Fri Dec 09 10:10:14 2016 +0000
Revision:
13:75f95a5cf9c1
Parent:
12:f0ffc006e62d
Child:
14:92bb9a8ccd0b
First commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 0:415d7f24cb91 1 /* mbed Microcontroller Library
rgrover1 0:415d7f24cb91 2 * Copyright (c) 2006-2015 ARM Limited
rgrover1 0:415d7f24cb91 3 *
rgrover1 0:415d7f24cb91 4 * Licensed under the Apache License, Version 2.0 (the "License");
rgrover1 0:415d7f24cb91 5 * you may not use this file except in compliance with the License.
rgrover1 0:415d7f24cb91 6 * You may obtain a copy of the License at
rgrover1 0:415d7f24cb91 7 *
rgrover1 0:415d7f24cb91 8 * http://www.apache.org/licenses/LICENSE-2.0
rgrover1 0:415d7f24cb91 9 *
rgrover1 0:415d7f24cb91 10 * Unless required by applicable law or agreed to in writing, software
rgrover1 0:415d7f24cb91 11 * distributed under the License is distributed on an "AS IS" BASIS,
rgrover1 0:415d7f24cb91 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rgrover1 0:415d7f24cb91 13 * See the License for the specific language governing permissions and
rgrover1 0:415d7f24cb91 14 * limitations under the License.
rgrover1 0:415d7f24cb91 15 */
rgrover1 0:415d7f24cb91 16
rgrover1 0:415d7f24cb91 17 #include "mbed.h"
rgrover1 6:1730f66fb14d 18 #include "ble/BLE.h"
rgrover1 6:1730f66fb14d 19 #include "ble/DiscoveredCharacteristic.h"
rgrover1 6:1730f66fb14d 20 #include "ble/DiscoveredService.h"
rgrover1 0:415d7f24cb91 21
andresag 11:023d96b0e427 22 DigitalOut alivenessLED(LED1, 1);
rgrover1 6:1730f66fb14d 23
tsungta 13:75f95a5cf9c1 24 #if defined(TARGET_DELTA_DFCM_NNN40)
tsungta 13:75f95a5cf9c1 25 Serial uart(p17, p16);//temp use for NNN50
tsungta 13:75f95a5cf9c1 26 #else
tsungta 13:75f95a5cf9c1 27 Serial uart(USBTX, USBRX);
tsungta 13:75f95a5cf9c1 28 #endif
tsungta 13:75f95a5cf9c1 29
andresag 11:023d96b0e427 30 bool triggerLedCharacteristic = false;
rgrover1 0:415d7f24cb91 31 DiscoveredCharacteristic ledCharacteristic;
rgrover1 0:415d7f24cb91 32
andresag 11:023d96b0e427 33 Ticker ticker;
andresag 11:023d96b0e427 34
rgrover1 0:415d7f24cb91 35 void periodicCallback(void) {
rgrover1 3:146eba831693 36 alivenessLED = !alivenessLED; /* Do blinky on LED1 while we're waiting for BLE events */
rgrover1 0:415d7f24cb91 37 }
rgrover1 0:415d7f24cb91 38
rgrover1 0:415d7f24cb91 39 void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) {
tsungta 12:f0ffc006e62d 40 if (params->peerAddr[0] != 0xF9) { /* !ALERT! Alter this filter to suit your device. */
rgrover1 0:415d7f24cb91 41 return;
rgrover1 0:415d7f24cb91 42 }
tsungta 13:75f95a5cf9c1 43 uart.printf("adv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, isScanResponse %u, AdvertisementType %u\r\n",
rgrover1 0:415d7f24cb91 44 params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2], params->peerAddr[1], params->peerAddr[0],
rgrover1 0:415d7f24cb91 45 params->rssi, params->isScanResponse, params->type);
rgrover1 0:415d7f24cb91 46
andresag 11:023d96b0e427 47 BLE::Instance().gap().connect(params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL);
rgrover1 0:415d7f24cb91 48 }
rgrover1 0:415d7f24cb91 49
rgrover1 0:415d7f24cb91 50 void serviceDiscoveryCallback(const DiscoveredService *service) {
tsungta 13:75f95a5cf9c1 51 uart.printf("serviceDiscoveryCallback\n");
rgrover1 0:415d7f24cb91 52 if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
tsungta 13:75f95a5cf9c1 53 uart.printf("S UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle());
rgrover1 0:415d7f24cb91 54 } else {
tsungta 13:75f95a5cf9c1 55 uart.printf("S UUID-");
rgrover1 0:415d7f24cb91 56 const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
rgrover1 0:415d7f24cb91 57 for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
tsungta 13:75f95a5cf9c1 58 uart.printf("%02x", longUUIDBytes[i]);
rgrover1 0:415d7f24cb91 59 }
tsungta 13:75f95a5cf9c1 60 uart.printf(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
rgrover1 0:415d7f24cb91 61 }
rgrover1 0:415d7f24cb91 62 }
rgrover1 0:415d7f24cb91 63
rgrover1 0:415d7f24cb91 64 void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP) {
tsungta 12:f0ffc006e62d 65 if (characteristicP->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
tsungta 13:75f95a5cf9c1 66 uart.printf(" C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getUUID().getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
tsungta 12:f0ffc006e62d 67 if (characteristicP->getUUID().getShortUUID() == 0x2a19) { /* !ALERT! Alter this filter to suit your device. */
tsungta 12:f0ffc006e62d 68 ledCharacteristic = *characteristicP;
tsungta 12:f0ffc006e62d 69 triggerLedCharacteristic = true;
tsungta 12:f0ffc006e62d 70 }
tsungta 12:f0ffc006e62d 71 }
tsungta 12:f0ffc006e62d 72 else {
tsungta 13:75f95a5cf9c1 73 uart.printf(" C UUID-");
tsungta 12:f0ffc006e62d 74 const uint8_t *longUUIDBytes = characteristicP->getUUID().getBaseUUID();
tsungta 12:f0ffc006e62d 75 for (unsigned i = (UUID::LENGTH_OF_LONG_UUID) - 1; i < UUID::LENGTH_OF_LONG_UUID; i--) {
tsungta 13:75f95a5cf9c1 76 uart.printf("%02x ", longUUIDBytes[i]);
tsungta 12:f0ffc006e62d 77 }
tsungta 13:75f95a5cf9c1 78 uart.printf(" valueAttr[%u] props[%x]\r\n", characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
rgrover1 0:415d7f24cb91 79 }
rgrover1 0:415d7f24cb91 80 }
rgrover1 0:415d7f24cb91 81
rgrover1 0:415d7f24cb91 82 void discoveryTerminationCallback(Gap::Handle_t connectionHandle) {
tsungta 13:75f95a5cf9c1 83 uart.printf("terminated SD for handle %u\r\n", connectionHandle);
rgrover1 0:415d7f24cb91 84 }
rgrover1 0:415d7f24cb91 85
rgrover1 0:415d7f24cb91 86 void connectionCallback(const Gap::ConnectionCallbackParams_t *params) {
tsungta 13:75f95a5cf9c1 87 uart.printf("connectionCallback\n");
rgrover1 0:415d7f24cb91 88 if (params->role == Gap::CENTRAL) {
andresag 11:023d96b0e427 89 BLE::Instance().gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
tsungta 12:f0ffc006e62d 90 BLE::Instance().gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback);
rgrover1 0:415d7f24cb91 91 }
rgrover1 0:415d7f24cb91 92 }
rgrover1 0:415d7f24cb91 93
rgrover1 0:415d7f24cb91 94 void triggerToggledWrite(const GattReadCallbackParams *response) {
rgrover1 0:415d7f24cb91 95 if (response->handle == ledCharacteristic.getValueHandle()) {
rgrover1 0:415d7f24cb91 96 #if DUMP_READ_DATA
tsungta 13:75f95a5cf9c1 97 uart.printf("triggerToggledWrite: handle %u, offset %u, len %u\r\n", response->handle, response->offset, response->len);
rgrover1 0:415d7f24cb91 98 for (unsigned index = 0; index < response->len; index++) {
tsungta 13:75f95a5cf9c1 99 uart.printf("%c[%02x]", response->data[index], response->data[index]);
rgrover1 0:415d7f24cb91 100 }
tsungta 13:75f95a5cf9c1 101 uart.printf("\r\n");
rgrover1 0:415d7f24cb91 102 #endif
rgrover1 0:415d7f24cb91 103
rgrover1 0:415d7f24cb91 104 uint8_t toggledValue = response->data[0] ^ 0x1;
rgrover1 0:415d7f24cb91 105 ledCharacteristic.write(1, &toggledValue);
rgrover1 0:415d7f24cb91 106 }
rgrover1 0:415d7f24cb91 107 }
rgrover1 0:415d7f24cb91 108
rgrover1 0:415d7f24cb91 109 void triggerRead(const GattWriteCallbackParams *response) {
rgrover1 0:415d7f24cb91 110 if (response->handle == ledCharacteristic.getValueHandle()) {
rgrover1 0:415d7f24cb91 111 ledCharacteristic.read();
rgrover1 0:415d7f24cb91 112 }
rgrover1 0:415d7f24cb91 113 }
rgrover1 0:415d7f24cb91 114
rgrover1 10:507318f2afda 115 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) {
tsungta 13:75f95a5cf9c1 116 uart.printf("disconnected\r\n");
rgrover1 0:415d7f24cb91 117 }
rgrover1 0:415d7f24cb91 118
andresag 11:023d96b0e427 119 /**
andresag 11:023d96b0e427 120 * This function is called when the ble initialization process has failed
andresag 11:023d96b0e427 121 */
andresag 11:023d96b0e427 122 void onBleInitError(BLE &ble, ble_error_t error)
andresag 11:023d96b0e427 123 {
andresag 11:023d96b0e427 124 /* Initialization error handling should go here */
andresag 11:023d96b0e427 125 }
rgrover1 0:415d7f24cb91 126
andresag 11:023d96b0e427 127 /**
andresag 11:023d96b0e427 128 * Callback triggered when the ble initialization process has finished
andresag 11:023d96b0e427 129 */
andresag 11:023d96b0e427 130 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
andresag 11:023d96b0e427 131 {
andresag 11:023d96b0e427 132 BLE& ble = params->ble;
andresag 11:023d96b0e427 133 ble_error_t error = params->error;
andresag 11:023d96b0e427 134
andresag 11:023d96b0e427 135 if (error != BLE_ERROR_NONE) {
andresag 11:023d96b0e427 136 /* In case of error, forward the error handling to onBleInitError */
andresag 11:023d96b0e427 137 onBleInitError(ble, error);
andresag 11:023d96b0e427 138 return;
andresag 11:023d96b0e427 139 }
andresag 11:023d96b0e427 140
andresag 11:023d96b0e427 141 /* Ensure that it is the default instance of BLE */
andresag 11:023d96b0e427 142 if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
andresag 11:023d96b0e427 143 return;
andresag 11:023d96b0e427 144 }
andresag 11:023d96b0e427 145
rgrover1 5:3bbad34d1a85 146 ble.gap().onConnection(connectionCallback);
rgrover1 5:3bbad34d1a85 147 ble.gap().onDisconnection(disconnectionCallback);
rgrover1 0:415d7f24cb91 148
rgrover1 7:61e2224ec9a0 149 ble.gattClient().onDataRead(triggerToggledWrite);
rgrover1 7:61e2224ec9a0 150 ble.gattClient().onDataWrite(triggerRead);
rgrover1 0:415d7f24cb91 151
rgrover1 5:3bbad34d1a85 152 ble.gap().setScanParams(500, 400);
rgrover1 5:3bbad34d1a85 153 ble.gap().startScan(advertisementCallback);
andresag 11:023d96b0e427 154 }
andresag 11:023d96b0e427 155
andresag 11:023d96b0e427 156 int main(void) {
tsungta 13:75f95a5cf9c1 157 uart.printf("APPLICATION START\r\n");
andresag 11:023d96b0e427 158 ticker.attach(periodicCallback, 1);
andresag 11:023d96b0e427 159
andresag 11:023d96b0e427 160 BLE &ble = BLE::Instance();
andresag 11:023d96b0e427 161 ble.init(bleInitComplete);
andresag 11:023d96b0e427 162
andresag 11:023d96b0e427 163 /* SpinWait for initialization to complete. This is necessary because the
andresag 11:023d96b0e427 164 * BLE object is used in the main loop below. */
andresag 11:023d96b0e427 165 while (ble.hasInitialized() == false) { /* spin loop */ }
tsungta 13:75f95a5cf9c1 166 uart.printf("init DONE\r\n");
rgrover1 0:415d7f24cb91 167 while (true) {
rgrover1 4:460ce53dc854 168 if (triggerLedCharacteristic && !ble.gattClient().isServiceDiscoveryActive()) {
rgrover1 1:1db45b17552e 169 triggerLedCharacteristic = false;
rgrover1 0:415d7f24cb91 170 ledCharacteristic.read(); /* We could have issued this read just as easily from
rgrover1 0:415d7f24cb91 171 * characteristicDiscoveryCallback(); but
rgrover1 2:3e1e967035cb 172 * invoking it here demonstrates the use
rgrover1 2:3e1e967035cb 173 * of isServiceDiscoveryActive() and also
rgrover1 2:3e1e967035cb 174 * the fact that it is permitted to
rgrover1 2:3e1e967035cb 175 * operate on application-local copies of
rgrover1 2:3e1e967035cb 176 * DiscoveredCharacteristic. */
rgrover1 0:415d7f24cb91 177 }
rgrover1 0:415d7f24cb91 178 ble.waitForEvent();
rgrover1 0:415d7f24cb91 179 }
rgrover1 0:415d7f24cb91 180 }