ble example

Dependencies:   BLE_API mbed nRF51822

Fork of BLE_LEDBlinker by Bluetooth Low Energy

Committer:
hmiot
Date:
Thu Jan 19 12:40:00 2017 +0000
Revision:
12:96caa9a52bb3
Parent:
11:023d96b0e427
Central Led blinker

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"
hmiot 12:96caa9a52bb3 21 #include "ble/Gap.h"
hmiot 12:96caa9a52bb3 22 static const uint16_t UNIT_1_25_MS = 1250;
hmiot 12:96caa9a52bb3 23 static const uint16_t UNIT_10_MS = 10000;
hmiot 12:96caa9a52bb3 24 #define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION))
hmiot 12:96caa9a52bb3 25 #define MIN_CONNECTION_INTERVAL MSEC_TO_UNITS(7.5, UNIT_1_25_MS)
hmiot 12:96caa9a52bb3 26 #define MAX_CONNECTION_INTERVAL MSEC_TO_UNITS(30, UNIT_1_25_MS)
hmiot 12:96caa9a52bb3 27 #define SLAVE_LATENCY 0
hmiot 12:96caa9a52bb3 28 #define SUPERVISION_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS)
andresag 11:023d96b0e427 29 DigitalOut alivenessLED(LED1, 1);
rgrover1 6:1730f66fb14d 30
andresag 11:023d96b0e427 31 bool triggerLedCharacteristic = false;
rgrover1 0:415d7f24cb91 32 DiscoveredCharacteristic ledCharacteristic;
hmiot 12:96caa9a52bb3 33 static const Gap::ConnectionParams_t m_conn_params ={
hmiot 12:96caa9a52bb3 34 (uint16_t)MIN_CONNECTION_INTERVAL,
hmiot 12:96caa9a52bb3 35 (uint16_t)MAX_CONNECTION_INTERVAL,
hmiot 12:96caa9a52bb3 36 (uint16_t)SLAVE_LATENCY,
hmiot 12:96caa9a52bb3 37 (uint16_t)SUPERVISION_TIMEOUT
hmiot 12:96caa9a52bb3 38 };
rgrover1 0:415d7f24cb91 39
andresag 11:023d96b0e427 40 Ticker ticker;
hmiot 12:96caa9a52bb3 41 Serial pc(USBTX, USBRX);
rgrover1 0:415d7f24cb91 42 void periodicCallback(void) {
rgrover1 3:146eba831693 43 alivenessLED = !alivenessLED; /* Do blinky on LED1 while we're waiting for BLE events */
rgrover1 0:415d7f24cb91 44 }
rgrover1 0:415d7f24cb91 45
rgrover1 0:415d7f24cb91 46 void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) {
hmiot 12:96caa9a52bb3 47 uint8_t con_status =0;
hmiot 12:96caa9a52bb3 48 Gap::GapState_t con_state;
hmiot 12:96caa9a52bb3 49 if (params->peerAddr[0] != 0x2F) { /* !ALERT! Alter this filter to suit your device. */
rgrover1 0:415d7f24cb91 50 return;
rgrover1 0:415d7f24cb91 51 }
hmiot 12:96caa9a52bb3 52 pc.printf("adv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, isScanResponse %u, AdvertisementType %u\r\n",
rgrover1 0:415d7f24cb91 53 params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2], params->peerAddr[1], params->peerAddr[0],
rgrover1 0:415d7f24cb91 54 params->rssi, params->isScanResponse, params->type);
hmiot 12:96caa9a52bb3 55 // con_state = BLE::Instance().gap().getState();
hmiot 12:96caa9a52bb3 56 //pc.printf("Connection state : %d\r\n",con_state);
hmiot 12:96caa9a52bb3 57 uint8_t count=0;
hmiot 12:96caa9a52bb3 58 // while(!con_status)
hmiot 12:96caa9a52bb3 59 // {
hmiot 12:96caa9a52bb3 60 pc.printf("Count : %d",count++);
hmiot 12:96caa9a52bb3 61 con_status = BLE::Instance().gap().connect(params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, &m_conn_params, NULL);
hmiot 12:96caa9a52bb3 62 pc.printf("Connection Status : %d\r\n",con_status);
hmiot 12:96caa9a52bb3 63 con_state = BLE::Instance().gap().getState();
hmiot 12:96caa9a52bb3 64 pc.printf("Connection state : %d\r\n",con_state);
hmiot 12:96caa9a52bb3 65 // }
hmiot 12:96caa9a52bb3 66 BLE::Instance().gap().stopScan();
rgrover1 0:415d7f24cb91 67 }
rgrover1 0:415d7f24cb91 68
rgrover1 0:415d7f24cb91 69 void serviceDiscoveryCallback(const DiscoveredService *service) {
rgrover1 0:415d7f24cb91 70 if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
hmiot 12:96caa9a52bb3 71 pc.printf("S UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle());
rgrover1 0:415d7f24cb91 72 } else {
hmiot 12:96caa9a52bb3 73 pc.printf("S UUID-");
rgrover1 0:415d7f24cb91 74 const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
rgrover1 0:415d7f24cb91 75 for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
rgrover1 0:415d7f24cb91 76 printf("%02x", longUUIDBytes[i]);
rgrover1 0:415d7f24cb91 77 }
hmiot 12:96caa9a52bb3 78 pc.printf(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
rgrover1 0:415d7f24cb91 79 }
rgrover1 0:415d7f24cb91 80 }
rgrover1 0:415d7f24cb91 81
rgrover1 0:415d7f24cb91 82 void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP) {
hmiot 12:96caa9a52bb3 83 pc.printf(" C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getUUID().getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
rgrover1 10:507318f2afda 84 if (characteristicP->getUUID().getShortUUID() == 0xa001) { /* !ALERT! Alter this filter to suit your device. */
rgrover1 1:1db45b17552e 85 ledCharacteristic = *characteristicP;
rgrover1 1:1db45b17552e 86 triggerLedCharacteristic = true;
rgrover1 0:415d7f24cb91 87 }
rgrover1 0:415d7f24cb91 88 }
rgrover1 0:415d7f24cb91 89
rgrover1 0:415d7f24cb91 90 void discoveryTerminationCallback(Gap::Handle_t connectionHandle) {
hmiot 12:96caa9a52bb3 91 pc.printf("terminated SD for handle %u\r\n", connectionHandle);
rgrover1 0:415d7f24cb91 92 }
rgrover1 0:415d7f24cb91 93
rgrover1 0:415d7f24cb91 94 void connectionCallback(const Gap::ConnectionCallbackParams_t *params) {
hmiot 12:96caa9a52bb3 95 pc.printf("Connection Callback\n\r");
rgrover1 0:415d7f24cb91 96 if (params->role == Gap::CENTRAL) {
andresag 11:023d96b0e427 97 BLE::Instance().gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
andresag 11:023d96b0e427 98 BLE::Instance().gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback, 0xa000, 0xa001);
rgrover1 0:415d7f24cb91 99 }
rgrover1 0:415d7f24cb91 100 }
rgrover1 0:415d7f24cb91 101
rgrover1 0:415d7f24cb91 102 void triggerToggledWrite(const GattReadCallbackParams *response) {
rgrover1 0:415d7f24cb91 103 if (response->handle == ledCharacteristic.getValueHandle()) {
rgrover1 0:415d7f24cb91 104 #if DUMP_READ_DATA
rgrover1 0:415d7f24cb91 105 printf("triggerToggledWrite: handle %u, offset %u, len %u\r\n", response->handle, response->offset, response->len);
rgrover1 0:415d7f24cb91 106 for (unsigned index = 0; index < response->len; index++) {
rgrover1 0:415d7f24cb91 107 printf("%c[%02x]", response->data[index], response->data[index]);
rgrover1 0:415d7f24cb91 108 }
hmiot 12:96caa9a52bb3 109 pc.printf("\r\n");
rgrover1 0:415d7f24cb91 110 #endif
rgrover1 0:415d7f24cb91 111
rgrover1 0:415d7f24cb91 112 uint8_t toggledValue = response->data[0] ^ 0x1;
rgrover1 0:415d7f24cb91 113 ledCharacteristic.write(1, &toggledValue);
rgrover1 0:415d7f24cb91 114 }
rgrover1 0:415d7f24cb91 115 }
rgrover1 0:415d7f24cb91 116
rgrover1 0:415d7f24cb91 117 void triggerRead(const GattWriteCallbackParams *response) {
rgrover1 0:415d7f24cb91 118 if (response->handle == ledCharacteristic.getValueHandle()) {
rgrover1 0:415d7f24cb91 119 ledCharacteristic.read();
rgrover1 0:415d7f24cb91 120 }
rgrover1 0:415d7f24cb91 121 }
rgrover1 0:415d7f24cb91 122
rgrover1 10:507318f2afda 123 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) {
hmiot 12:96caa9a52bb3 124 pc.printf("disconnected\r\n");
rgrover1 0:415d7f24cb91 125 }
rgrover1 0:415d7f24cb91 126
andresag 11:023d96b0e427 127 /**
andresag 11:023d96b0e427 128 * This function is called when the ble initialization process has failed
andresag 11:023d96b0e427 129 */
andresag 11:023d96b0e427 130 void onBleInitError(BLE &ble, ble_error_t error)
andresag 11:023d96b0e427 131 {
andresag 11:023d96b0e427 132 /* Initialization error handling should go here */
andresag 11:023d96b0e427 133 }
rgrover1 0:415d7f24cb91 134
andresag 11:023d96b0e427 135 /**
andresag 11:023d96b0e427 136 * Callback triggered when the ble initialization process has finished
andresag 11:023d96b0e427 137 */
andresag 11:023d96b0e427 138 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
andresag 11:023d96b0e427 139 {
andresag 11:023d96b0e427 140 BLE& ble = params->ble;
andresag 11:023d96b0e427 141 ble_error_t error = params->error;
andresag 11:023d96b0e427 142
andresag 11:023d96b0e427 143 if (error != BLE_ERROR_NONE) {
andresag 11:023d96b0e427 144 /* In case of error, forward the error handling to onBleInitError */
andresag 11:023d96b0e427 145 onBleInitError(ble, error);
andresag 11:023d96b0e427 146 return;
andresag 11:023d96b0e427 147 }
andresag 11:023d96b0e427 148
hmiot 12:96caa9a52bb3 149 pc.printf("Ble Init\n\r");
andresag 11:023d96b0e427 150 /* Ensure that it is the default instance of BLE */
andresag 11:023d96b0e427 151 if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
andresag 11:023d96b0e427 152 return;
andresag 11:023d96b0e427 153 }
andresag 11:023d96b0e427 154
rgrover1 5:3bbad34d1a85 155 ble.gap().onConnection(connectionCallback);
rgrover1 5:3bbad34d1a85 156 ble.gap().onDisconnection(disconnectionCallback);
rgrover1 0:415d7f24cb91 157
rgrover1 7:61e2224ec9a0 158 ble.gattClient().onDataRead(triggerToggledWrite);
rgrover1 7:61e2224ec9a0 159 ble.gattClient().onDataWrite(triggerRead);
rgrover1 0:415d7f24cb91 160
rgrover1 5:3bbad34d1a85 161 ble.gap().setScanParams(500, 400);
rgrover1 5:3bbad34d1a85 162 ble.gap().startScan(advertisementCallback);
andresag 11:023d96b0e427 163 }
andresag 11:023d96b0e427 164
andresag 11:023d96b0e427 165 int main(void) {
andresag 11:023d96b0e427 166 ticker.attach(periodicCallback, 1);
hmiot 12:96caa9a52bb3 167 pc.baud(9600);
hmiot 12:96caa9a52bb3 168 wait(8.0);
hmiot 12:96caa9a52bb3 169 pc.printf("Start\n\r");
andresag 11:023d96b0e427 170 BLE &ble = BLE::Instance();
hmiot 12:96caa9a52bb3 171
hmiot 12:96caa9a52bb3 172
andresag 11:023d96b0e427 173 ble.init(bleInitComplete);
hmiot 12:96caa9a52bb3 174 ble.gap().setDeviceName("Samy");
andresag 11:023d96b0e427 175
andresag 11:023d96b0e427 176 /* SpinWait for initialization to complete. This is necessary because the
andresag 11:023d96b0e427 177 * BLE object is used in the main loop below. */
andresag 11:023d96b0e427 178 while (ble.hasInitialized() == false) { /* spin loop */ }
rgrover1 0:415d7f24cb91 179
rgrover1 0:415d7f24cb91 180 while (true) {
rgrover1 4:460ce53dc854 181 if (triggerLedCharacteristic && !ble.gattClient().isServiceDiscoveryActive()) {
rgrover1 1:1db45b17552e 182 triggerLedCharacteristic = false;
rgrover1 0:415d7f24cb91 183 ledCharacteristic.read(); /* We could have issued this read just as easily from
rgrover1 0:415d7f24cb91 184 * characteristicDiscoveryCallback(); but
rgrover1 2:3e1e967035cb 185 * invoking it here demonstrates the use
rgrover1 2:3e1e967035cb 186 * of isServiceDiscoveryActive() and also
rgrover1 2:3e1e967035cb 187 * the fact that it is permitted to
rgrover1 2:3e1e967035cb 188 * operate on application-local copies of
rgrover1 2:3e1e967035cb 189 * DiscoveredCharacteristic. */
rgrover1 0:415d7f24cb91 190 }
rgrover1 0:415d7f24cb91 191 ble.waitForEvent();
rgrover1 0:415d7f24cb91 192 }
rgrover1 0:415d7f24cb91 193 }