Demo BLE Central function

Fork of BLE_HeartRate_DELTA by Delta

This example demonstrates BLE central that to interact with the HRM peripheral.

The example uses two applications running on two different devices:

The first device - the central - runs the application BLE_Central_HeartRate_DELTA from this repository.

The second device - the peripheral - runs the application BLE_HeartRate_DELTA.

Revision:
2:504d4bd0e684
Parent:
1:82331af3e4c9
--- a/main.cpp	Tue Mar 14 08:33:26 2017 +0000
+++ b/main.cpp	Fri Mar 24 08:30:59 2017 +0000
@@ -14,6 +14,11 @@
  * limitations under the License.
  */
 
+#include "Gap.h"
+#include "ble/GattCharacteristic.h"
+#include "ble/UUID.h"
+#include "ble/DiscoveredCharacteristic.h"
+#include "ble/DiscoveredService.h"
 #include "mbed.h"
 #include "ble/BLE.h"
 #include "ble/services/HeartRateService.h"
@@ -21,17 +26,103 @@
 #include "ble/services/DeviceInformationService.h"
 
 DigitalOut led1(LED1);
+Serial uart(USBTX, USBRX, 115200);
 
-const static char     DEVICE_NAME[]        = "DELTA_HRM1";
+const static char     DEVICE_NAME[]        = "DELTA_HRM_CEN";
 static const uint16_t uuid16_list[]        = {GattService::UUID_HEART_RATE_SERVICE,
                                               GattService::UUID_DEVICE_INFORMATION_SERVICE};
 static volatile bool  triggerSensorPolling = false;
 
 uint8_t hrmCounter = 100; // init HRM to 100bps
+const static char     PEER_NAME[]        = "DELTA_HRM1";
 
 HeartRateService         *hrService;
 DeviceInformationService *deviceInfo;
 
+void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) {
+    for (uint8_t i = 0; i < params->advertisingDataLen; ++i) {
+        const uint8_t record_length = params->advertisingData[i];
+        if (record_length == 0) continue;
+        const uint8_t type = params->advertisingData[i + 1];
+        const uint8_t* value = params->advertisingData + i + 2;
+        const uint8_t value_length = record_length - 1;
+
+        if(type == GapAdvertisingData::COMPLETE_LOCAL_NAME) {
+            if ((value_length == sizeof(PEER_NAME)) && (memcmp(value, PEER_NAME, value_length) == 0)) {
+                uart.printf("%s ", value);
+                uart.printf(", adv peerAddr [%02x %02x %02x %02x %02x %02x], rssi %d, isScanResponse %u, AdvertisementType %u\r\n",
+                    params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2],
+                    params->peerAddr[1], params->peerAddr[0], params->rssi, params->isScanResponse, params->type
+                );
+                BLE::Instance(BLE::DEFAULT_INSTANCE).gap().stopScan();
+                BLE::Instance(BLE::DEFAULT_INSTANCE).gap().connect(params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL);
+                break;
+            }
+        }
+        i += record_length;
+    }
+}
+
+void serviceDiscoveryCallback(const DiscoveredService *service) {
+    uart.printf("serviceDiscoveryCallback\r\n");
+    if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
+        uart.printf("S UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle());
+    } else {
+        uart.printf("S UUID-");
+        const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
+        for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
+            uart.printf("%02x", longUUIDBytes[i]);
+        }
+        uart.printf(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
+    }
+}
+
+void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP) {
+    if (characteristicP->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
+        uart.printf("  C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getUUID().getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
+        if (characteristicP->getUUID().getShortUUID() == 0x2a37) { /* !ALERT! Alter this filter to suit your device. */   
+            uint16_t value = BLE_HVX_NOTIFICATION;
+            BLE::Instance(BLE::DEFAULT_INSTANCE).gattClient().write(GattClient::GATT_OP_WRITE_REQ, characteristicP->getConnectionHandle(), characteristicP->getValueHandle() + 1, 2, (uint8_t *)&value);
+        }
+    }
+    else {
+        uart.printf("  C UUID-");
+        const uint8_t *longUUIDBytes = characteristicP->getUUID().getBaseUUID();
+        for (unsigned i = (UUID::LENGTH_OF_LONG_UUID) - 1; i < UUID::LENGTH_OF_LONG_UUID; i--) {
+            uart.printf("%02x ", longUUIDBytes[i]);
+        }
+        uart.printf(" valueAttr[%u] props[%x]\r\n", characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
+    }
+}
+
+void discoveryTerminationCallback(Gap::Handle_t connectionHandle) {
+    uart.printf("terminated SD for handle %u\r\n", connectionHandle);
+}
+
+void connectionCallback(const Gap::ConnectionCallbackParams_t *params) {
+    uart.printf("connectionCallback\r\n");
+    if (params->role == Gap::CENTRAL) {
+        BLE::Instance(BLE::DEFAULT_INSTANCE).gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
+        BLE::Instance(BLE::DEFAULT_INSTANCE).gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback);
+    }
+}
+
+void dataReadCallback(const GattReadCallbackParams *response) {
+    
+}
+
+void dataWriteCallback(const GattWriteCallbackParams *response) {
+    
+}
+
+void hvxCallback(const GattHVXCallbackParams *response) {
+    uart.printf("hvxCallback\r\n");
+    for (unsigned index = 0; index < response->len; index++) {
+        uart.printf("[%02x]", response->data[index]);
+    }
+    uart.printf("\r\n");
+}
+
 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
 {
     BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising(); // restart advertising
@@ -55,7 +146,12 @@
         return;
     }
 
+    //Register callback function
+    ble.gap().onConnection(connectionCallback);
     ble.gap().onDisconnection(disconnectionCallback);
+    ble.gattClient().onDataRead(dataReadCallback);
+    ble.gattClient().onDataWrite(dataWriteCallback);
+    ble.gattClient().onHVX(hvxCallback);
 
     /* Setup primary service. */
     hrService = new HeartRateService(ble, hrmCounter, HeartRateService::LOCATION_FINGER);
@@ -69,8 +165,12 @@
     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);
     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
     ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
-    ble.gap().setAdvertisingInterval(1000); /* 1000ms */
+    ble.gap().setAdvertisingInterval(160); /* 160ms */
     ble.gap().startAdvertising();
+    
+    //Central - start scan
+    ble.gap().setScanParams(500, 400);
+    ble.gap().startScan(advertisementCallback);
 }
 
 int main(void)