Simple example to demonstrate custom made BLE service and characteristics.

Fork of BLE_GATT_Example by Bluetooth Low Energy

Files at this revision

API Documentation at this revision

Comitter:
jurica238814
Date:
Thu Nov 09 16:08:04 2017 +0000
Parent:
22:406127954d1f
Commit message:
0xBABE and 0xDEAD works.

Changed in this revision

AckService.h Show annotated file Show diff for this revision Revisions of this file
BLE_API.lib Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-events.lib Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show diff for this revision Revisions of this file
nRF51822.lib Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AckService.h	Thu Nov 09 16:08:04 2017 +0000
@@ -0,0 +1,26 @@
+
+#define MAC_ADDR_SIZE_B (6)
+
+// Template allows you to use 'constant' values on non-constant places (XD)
+template<uint8_t dataSize>
+
+class ACKService{
+    public:
+        const static uint16_t ACK_SERVICE_UUID        = 0xA000;
+        const static uint16_t ACK_CHARA_UUID = 0xA001;
+        const static uint16_t ACK_MAC_CHAR_UUID = 0xA002;
+
+        ACKService(BLEDevice &_ble, uint8_t *_initValues) : ble(_ble), ACK(ACK_CHARA_UUID, _initValues), MAC(ACK_MAC_CHAR_UUID, _initValues, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY){
+                GattCharacteristic *charTable[] = {&ACK, &MAC};     // Add characteristick in table
+                GattService AckService(ACK_SERVICE_UUID, charTable, sizeof(charTable)/sizeof(GattCharacteristic *));   
+                ble.addService(AckService); // Add service in the BLE
+        }
+        void updateMacAddress(uint8_t  *MacAddress){
+            ble.gattServer().write(MAC.getValueHandle(), MacAddress, MAC_ADDR_SIZE_B);
+        }
+    private:
+        BLEDevice &ble;
+        // Create new characteristic
+        WriteOnlyArrayGattCharacteristic<uint8_t, dataSize> ACK;
+        ReadOnlyArrayGattCharacteristic<uint8_t, MAC_ADDR_SIZE_B> MAC;
+};
\ No newline at end of file
--- a/BLE_API.lib	Mon Nov 09 17:08:47 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#a097e1be76f4
--- a/main.cpp	Mon Nov 09 17:08:47 2015 +0000
+++ b/main.cpp	Thu Nov 09 16:08:04 2017 +0000
@@ -1,104 +1,166 @@
-#include "mbed.h"
-#include "ble/BLE.h"
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
-DigitalOut led(LED1, 1);
-uint16_t customServiceUUID  = 0xA000;
-uint16_t readCharUUID       = 0xA001;
-uint16_t writeCharUUID      = 0xA002;
+#include <mbed-events/events.h>
+#include <mbed.h>
+#include "ble/BLE.h"
+#include "AckService.h"
 
-const static char     DEVICE_NAME[]        = "ChangeMe!!"; // change this
-static const uint16_t uuid16_list[]        = {0xFFFF}; //Custom UUID, FFFF is reserved for development
+#define DEBUG       (0)
+#define MSD_SIZE    (18)
 
-/* Set Up custom Characteristics */
-static uint8_t readValue[10] = {0};
-ReadOnlyArrayGattCharacteristic<uint8_t, sizeof(readValue)> readChar(readCharUUID, readValue);
+#if DEBUG
+    #define RX (p26)            // SERIAL STILL DOES NOT WORK!!!
+    #define TX (p25)
+#endif
 
-static uint8_t writeValue[10] = {0};
-WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(writeValue)> writeChar(writeCharUUID, writeValue);
+ACKService<4> *ackServicePtr;
+#if DEBUG
+    Serial pc(TX, RX);
+#endif
 
-/* Set up custom service */
-GattCharacteristic *characteristics[] = {&readChar, &writeChar};
-GattService        customService(customServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *));
+BLE &ble = BLE::Instance();
+
+DigitalOut redLed(p22);
+DigitalOut greenLed(p24);
+DigitalOut blueLed(p23);
+DigitalOut alivenessLED(p26);
 
+const static char     DEVICE_NAME[] = "CRP_ACK";
+const static uint16_t ACK_CHARACTERISTIC_UUID = 0xA001;
+const static uint16_t ACK_SERVICE_UUID        = 0xA000;
+uint8_t MSD[MSD_SIZE] = {0x59, 0x00, 0xE1, 0x61, 0x35, 0xBA, 0xC0, 0xEC, 0x47, 0x2A, 0x98, 0x00, 0xAF, 0x18, 0x43, 0xFF, 0x05, 0x00};
+uint8_t macAddress[6] = {0x23, 0x24, 0x35, 0x22, 0x24, 0x45};
 
-/*
- *  Restart advertising when phone app disconnects
-*/
-void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *)
-{
-    BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising();
+static EventQueue eventQueue(
+    /* event count */ 10 * /* event size */ 32
+);
+
+void onConnectionCallback(const Gap::ConnectionCallbackParams_t *params){
+    #if DEBUG
+        pc.printf("BLE device is connected.\n");
+    #endif
+    redLed = 1;
+    greenLed = 1;
+    blueLed = 0;
 }
 
-/*
- *  Handle writes to writeCharacteristic
-*/
-void writeCharCallback(const GattWriteCallbackParams *params)
-{
-    /* Check to see what characteristic was written, by handle */
-    if(params->handle == writeChar.getValueHandle()) {
-        /* toggle LED if only 1 byte is written */
-        if(params->len == 1) {
-            led = params->data[0];
-            (params->data[0] == 0x00) ? printf("led on\n\r") : printf("led off\n\r"); // print led toggle
-        }
-        /* Print the data if more than 1 byte is written */
-        else {
-            printf("Data received: length = %d, data = 0x",params->len);
-            for(int x=0; x < params->len; x++) {
-                printf("%x", params->data[x]);
-            }
-            printf("\n\r");
-        }
-        /* Update the readChar with the value of writeChar */
-        BLE::Instance(BLE::DEFAULT_INSTANCE).gattServer().write(readChar.getValueHandle(), params->data, params->len);
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params){
+    (void) params;
+    redLed = 0;
+    greenLed = 1;
+    blueLed = 1;
+    ble.disconnect(Gap::LOCAL_HOST_TERMINATED_CONNECTION);
+    BLE::Instance().gap().startAdvertising();
+}
+
+void blinkCallback(void){
+    alivenessLED = !alivenessLED; /* Do blinky on LED1 to indicate system aliveness. */
+}
+
+void updateMac(const GattReadCallbackParams *response){
+    ackServicePtr->updateMacAddress(macAddress);    // Update MAC address
+}
+
+
+/**
+ * This callback allows the LEDService to receive updates to the ledState Characteristic.
+ *
+ * @param[in] params
+ *     Information about the characterisitc being updated.
+ */
+void onDataWrittenCallback(const GattWriteCallbackParams *params) {
+    #if DEBUG
+        pc.printf("Data written into characteristic.\n");
+    #endif
+    
+    
+    if(params->data[0] == 0xBA)
+        if(params->data[1] == 0xBE)
+            greenLed = 0;
+        
+    if(params->data[0] == 0xDE)
+        if(params->data[1] == 0xAD)
+            greenLed = 1;
+}
+
+/**
+ * This function is called when the ble initialization process has failled
+ */
+void onBleInitError(BLE &ble, ble_error_t error){
+    /* Initialization error handling should go here */
+}
+
+/**
+ * Callback triggered when the ble initialization process has finished
+ */
+void bleInitComplete(BLE::InitializationCompleteCallbackContext *params){
+    BLE&        ble   = params->ble;
+    ble_error_t error = params->error;
+
+    if (error != BLE_ERROR_NONE) {
+        /* In case of error, forward the error handling to onBleInitError */
+        onBleInitError(ble, error);
+        return;
     }
-}
-/*
- * Initialization callback
- */
-void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
-{
-    BLE &ble          = params->ble;
-    ble_error_t error = params->error;
-    
-    if (error != BLE_ERROR_NONE) {
+
+    /* Ensure that it is the default instance of BLE */
+    if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
         return;
     }
 
     ble.gap().onDisconnection(disconnectionCallback);
-    ble.gattServer().onDataWritten(writeCharCallback);
+    ble.gap().onConnection(onConnectionCallback);
+    ble.gattServer().onDataWritten(onDataWrittenCallback);
+    ble.gattClient().onDataRead(updateMac); 
 
-    /* Setup advertising */
-    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); // BLE only, no classic BT
-    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); // advertising type
-    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); // add name
-    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); // UUID's broadcast in advertising packet
-    ble.gap().setAdvertisingInterval(100); // 100ms.
-
-    /* Add our custom service */
-    ble.addService(customService);
-
-    /* Start advertising */
+    uint8_t init_values[4] = {0,0,0,0};
+    /* Get my MAC address */
+    BLEProtocol::AddressType_t macAddressType;
+    ble.gap().getAddress(&macAddressType, macAddress);
+    ackServicePtr = new ACKService<4>(ble, init_values);
+    ackServicePtr->updateMacAddress(macAddress);    // Update MAC address
+    
+    /* setup advertising */
+    //ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
+    //ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
+    //ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, (uint8_t *)MSD, MSD_SIZE);
+    ble.gap().setAdvertisingInterval(500); /* 1000ms. */
     ble.gap().startAdvertising();
 }
 
-/*
- *  Main loop
-*/
-int main(void)
-{
-    /* initialize stuff */
-    printf("\n\r********* Starting Main Loop *********\n\r");
+void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
+    BLE &ble = BLE::Instance();
+    eventQueue.post(Callback<void()>(&ble, &BLE::processEvents));
+}
+
+
+
+int main(){
+    redLed = 1;
+    greenLed = 1;
+    blueLed = 1;
     
-    BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
+    eventQueue.post_every(500, blinkCallback);
+
+    ble.onEventsToProcess(scheduleBleEventsProcessing);
     ble.init(bleInitComplete);
     
-    /* SpinWait for initialization to complete. This is necessary because the
-     * BLE object is used in the main loop below. */
-    while (ble.hasInitialized()  == false) { /* spin loop */ }
-
-    /* Infinite loop waiting for BLE interrupt events */
     while (true) {
-        ble.waitForEvent(); /* Save power */
+        eventQueue.dispatch();
     }
-}
\ No newline at end of file
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-events.lib	Thu Nov 09 16:08:04 2017 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-events.git/#6be60bf880c11a0beafcc2064bf467f8d897529a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Thu Nov 09 16:08:04 2017 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#21dd7008a1540c02150f1b87c12294301db979bb
--- a/mbed.bld	Mon Nov 09 17:08:47 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/9296ab0bfc11
\ No newline at end of file
--- a/nRF51822.lib	Mon Nov 09 17:08:47 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/teams/Nordic-Semiconductor/code/nRF51822/#bf85bf7e73d5