Central/ Peripheral example: Central Device connects to a Peripheral called "LED" and additionally a led can be toggled with a button -> BLE_LED_PERIPHERAL needed

Dependencies:   BLE_API mbed nRF51822

Fork of BLE_LED_CENTRAL by Alex Gernhaeuser

Committer:
Alexgerni
Date:
Tue Aug 08 20:35:34 2017 +0000
Revision:
0:26b1912de8d8
Central Device connects to a Peripheral called "LED" and additionally a led can be toggled with a button -> BLE_LED_PERIPHERAL needed

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Alexgerni 0:26b1912de8d8 1 /* mbed Microcontroller Library
Alexgerni 0:26b1912de8d8 2 * Copyright (c) 2006-2015 ARM Limited
Alexgerni 0:26b1912de8d8 3 *
Alexgerni 0:26b1912de8d8 4 * Licensed under the Apache License, Version 2.0 (the "License");
Alexgerni 0:26b1912de8d8 5 * you may not use this file except in compliance with the License.
Alexgerni 0:26b1912de8d8 6 * You may obtain a copy of the License at
Alexgerni 0:26b1912de8d8 7 *
Alexgerni 0:26b1912de8d8 8 * http://www.apache.org/licenses/LICENSE-2.0
Alexgerni 0:26b1912de8d8 9 *
Alexgerni 0:26b1912de8d8 10 * Unless required by applicable law or agreed to in writing, software
Alexgerni 0:26b1912de8d8 11 * distributed under the License is distributed on an "AS IS" BASIS,
Alexgerni 0:26b1912de8d8 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Alexgerni 0:26b1912de8d8 13 * See the License for the specific language governing permissions and
Alexgerni 0:26b1912de8d8 14 * limitations under the License.
Alexgerni 0:26b1912de8d8 15 */
Alexgerni 0:26b1912de8d8 16
Alexgerni 0:26b1912de8d8 17 #include "mbed.h"
Alexgerni 0:26b1912de8d8 18 #include "ble/BLE.h"
Alexgerni 0:26b1912de8d8 19 #include "ble/DiscoveredCharacteristic.h"
Alexgerni 0:26b1912de8d8 20 #include "ble/DiscoveredService.h"
Alexgerni 0:26b1912de8d8 21
Alexgerni 0:26b1912de8d8 22 DigitalOut alivenessLED(p16, 0);
Alexgerni 0:26b1912de8d8 23 InterruptIn button(p9);
Alexgerni 0:26b1912de8d8 24 Serial pc(p5, p4);
Alexgerni 0:26b1912de8d8 25 Ticker ticker, ticker2;
Alexgerni 0:26b1912de8d8 26
Alexgerni 0:26b1912de8d8 27 static DiscoveredCharacteristic ledCharacteristic;
Alexgerni 0:26b1912de8d8 28 static const char PEER_NAME[] = "LED";
Alexgerni 0:26b1912de8d8 29
Alexgerni 0:26b1912de8d8 30 void periodicCallback(void)
Alexgerni 0:26b1912de8d8 31 {
Alexgerni 0:26b1912de8d8 32 alivenessLED = !alivenessLED; /* Do blinky on LED1 while we're waiting for BLE events */
Alexgerni 0:26b1912de8d8 33 }
Alexgerni 0:26b1912de8d8 34
Alexgerni 0:26b1912de8d8 35 void buttonPressedCallback(void)
Alexgerni 0:26b1912de8d8 36 {
Alexgerni 0:26b1912de8d8 37 /* Note that the buttonPressedCallback() executes in interrupt context, so it is safer to access
Alexgerni 0:26b1912de8d8 38 * BLE device API from the main thread. */
Alexgerni 0:26b1912de8d8 39 uint8_t toggledValue = 0x1;
Alexgerni 0:26b1912de8d8 40 ledCharacteristic.write(1, &toggledValue);
Alexgerni 0:26b1912de8d8 41 pc.printf("LED on... \n");
Alexgerni 0:26b1912de8d8 42 }
Alexgerni 0:26b1912de8d8 43
Alexgerni 0:26b1912de8d8 44 void buttonReleasedCallback(void)
Alexgerni 0:26b1912de8d8 45 {
Alexgerni 0:26b1912de8d8 46 /* Note that the buttonPressedCallback() executes in interrupt context, so it is safer to access
Alexgerni 0:26b1912de8d8 47 * BLE device API from the main thread. */
Alexgerni 0:26b1912de8d8 48 uint8_t toggledValue = 0x0;
Alexgerni 0:26b1912de8d8 49 ledCharacteristic.write(1, &toggledValue);
Alexgerni 0:26b1912de8d8 50 pc.printf("LED off... \n");
Alexgerni 0:26b1912de8d8 51 }
Alexgerni 0:26b1912de8d8 52
Alexgerni 0:26b1912de8d8 53 void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params)
Alexgerni 0:26b1912de8d8 54 {
Alexgerni 0:26b1912de8d8 55 // parse the advertising payload, looking for data type COMPLETE_LOCAL_NAME
Alexgerni 0:26b1912de8d8 56 // The advertising payload is a collection of key/value records where
Alexgerni 0:26b1912de8d8 57 // byte 0: length of the record excluding this byte
Alexgerni 0:26b1912de8d8 58 // byte 1: The key, it is the type of the data
Alexgerni 0:26b1912de8d8 59 // byte [2..N] The value. N is equal to byte0 - 1
Alexgerni 0:26b1912de8d8 60 for (uint8_t i = 0; i < params->advertisingDataLen; ++i) {
Alexgerni 0:26b1912de8d8 61
Alexgerni 0:26b1912de8d8 62 const uint8_t record_length = params->advertisingData[i];
Alexgerni 0:26b1912de8d8 63 if (record_length == 0) {
Alexgerni 0:26b1912de8d8 64 continue;
Alexgerni 0:26b1912de8d8 65 }
Alexgerni 0:26b1912de8d8 66 const uint8_t type = params->advertisingData[i + 1];
Alexgerni 0:26b1912de8d8 67 const uint8_t* value = params->advertisingData + i + 2;
Alexgerni 0:26b1912de8d8 68 const uint8_t value_length = record_length - 1;
Alexgerni 0:26b1912de8d8 69
Alexgerni 0:26b1912de8d8 70 if(type == GapAdvertisingData::COMPLETE_LOCAL_NAME) {
Alexgerni 0:26b1912de8d8 71 if ((value_length == sizeof(PEER_NAME)) && (memcmp(value, PEER_NAME, value_length) == 0)) {
Alexgerni 0:26b1912de8d8 72 pc.printf(
Alexgerni 0:26b1912de8d8 73 "adv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, isScanResponse %u, AdvertisementType %u\r\n",
Alexgerni 0:26b1912de8d8 74 params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2],
Alexgerni 0:26b1912de8d8 75 params->peerAddr[1], params->peerAddr[0], params->rssi, params->isScanResponse, params->type
Alexgerni 0:26b1912de8d8 76 );
Alexgerni 0:26b1912de8d8 77 BLE::Instance().gap().connect(params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL);
Alexgerni 0:26b1912de8d8 78 break;
Alexgerni 0:26b1912de8d8 79 }
Alexgerni 0:26b1912de8d8 80 }
Alexgerni 0:26b1912de8d8 81 i += record_length;
Alexgerni 0:26b1912de8d8 82 }
Alexgerni 0:26b1912de8d8 83 }
Alexgerni 0:26b1912de8d8 84
Alexgerni 0:26b1912de8d8 85 void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP)
Alexgerni 0:26b1912de8d8 86 {
Alexgerni 0:26b1912de8d8 87 pc.printf(" C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getUUID().getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
Alexgerni 0:26b1912de8d8 88 if (characteristicP->getUUID().getShortUUID() == 0xa001) { /* !ALERT! Alter this filter to suit your device. */
Alexgerni 0:26b1912de8d8 89 ledCharacteristic = *characteristicP;
Alexgerni 0:26b1912de8d8 90 }
Alexgerni 0:26b1912de8d8 91 }
Alexgerni 0:26b1912de8d8 92
Alexgerni 0:26b1912de8d8 93 void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
Alexgerni 0:26b1912de8d8 94 {
Alexgerni 0:26b1912de8d8 95 if (params->role == Gap::CENTRAL) {
Alexgerni 0:26b1912de8d8 96 BLE &ble = BLE::Instance();
Alexgerni 0:26b1912de8d8 97 //ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
Alexgerni 0:26b1912de8d8 98 ble.gattClient().launchServiceDiscovery(params->handle, NULL, characteristicDiscoveryCallback, 0xa000, 0xa001);
Alexgerni 0:26b1912de8d8 99 }
Alexgerni 0:26b1912de8d8 100 }
Alexgerni 0:26b1912de8d8 101
Alexgerni 0:26b1912de8d8 102 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *)
Alexgerni 0:26b1912de8d8 103 {
Alexgerni 0:26b1912de8d8 104 pc.printf("disconnected\r\n");
Alexgerni 0:26b1912de8d8 105 /* Start scanning and try to connect again */
Alexgerni 0:26b1912de8d8 106 BLE::Instance().gap().startScan(advertisementCallback);
Alexgerni 0:26b1912de8d8 107 }
Alexgerni 0:26b1912de8d8 108
Alexgerni 0:26b1912de8d8 109 void onBleInitError(BLE &ble, ble_error_t error)
Alexgerni 0:26b1912de8d8 110 {
Alexgerni 0:26b1912de8d8 111 /* Initialization error handling should go here */
Alexgerni 0:26b1912de8d8 112 }
Alexgerni 0:26b1912de8d8 113
Alexgerni 0:26b1912de8d8 114 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
Alexgerni 0:26b1912de8d8 115 {
Alexgerni 0:26b1912de8d8 116 BLE& ble = params->ble;
Alexgerni 0:26b1912de8d8 117 ble_error_t error = params->error;
Alexgerni 0:26b1912de8d8 118
Alexgerni 0:26b1912de8d8 119 if (error != BLE_ERROR_NONE) {
Alexgerni 0:26b1912de8d8 120 /* In case of error, forward the error handling to onBleInitError */
Alexgerni 0:26b1912de8d8 121 onBleInitError(ble, error);
Alexgerni 0:26b1912de8d8 122 return;
Alexgerni 0:26b1912de8d8 123 }
Alexgerni 0:26b1912de8d8 124
Alexgerni 0:26b1912de8d8 125 /* Ensure that it is the default instance of BLE */
Alexgerni 0:26b1912de8d8 126 if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
Alexgerni 0:26b1912de8d8 127 return;
Alexgerni 0:26b1912de8d8 128 }
Alexgerni 0:26b1912de8d8 129
Alexgerni 0:26b1912de8d8 130 ble.gap().onDisconnection(disconnectionCallback);
Alexgerni 0:26b1912de8d8 131 ble.gap().onConnection(connectionCallback);
Alexgerni 0:26b1912de8d8 132
Alexgerni 0:26b1912de8d8 133 // scan interval: 400ms and scan window: 400ms.
Alexgerni 0:26b1912de8d8 134 // Every 400ms the device will scan for 400ms
Alexgerni 0:26b1912de8d8 135 // This means that the device will scan continuously.
Alexgerni 0:26b1912de8d8 136 ble.gap().setScanParams(400, 400);
Alexgerni 0:26b1912de8d8 137 ble.gap().startScan(advertisementCallback);
Alexgerni 0:26b1912de8d8 138 }
Alexgerni 0:26b1912de8d8 139
Alexgerni 0:26b1912de8d8 140
Alexgerni 0:26b1912de8d8 141 int main(void) {
Alexgerni 0:26b1912de8d8 142 pc.baud(115200);
Alexgerni 0:26b1912de8d8 143 pc.printf("Initialization starts... \n");
Alexgerni 0:26b1912de8d8 144
Alexgerni 0:26b1912de8d8 145 ticker.attach(periodicCallback, 1); /* Blink LED every second */
Alexgerni 0:26b1912de8d8 146 button.fall(buttonPressedCallback);
Alexgerni 0:26b1912de8d8 147 button.rise(buttonReleasedCallback);
Alexgerni 0:26b1912de8d8 148
Alexgerni 0:26b1912de8d8 149 BLE &ble = BLE::Instance();
Alexgerni 0:26b1912de8d8 150 ble.init(bleInitComplete);
Alexgerni 0:26b1912de8d8 151
Alexgerni 0:26b1912de8d8 152 while (true) {
Alexgerni 0:26b1912de8d8 153 ble.waitForEvent();
Alexgerni 0:26b1912de8d8 154 }
Alexgerni 0:26b1912de8d8 155 }