BLE GAP Button example

This example is a fork of the following mbed-os example:

https://developer.mbed.org/teams/mbed-os-examples/code/mbed-os-example-ble-GAPButton/

Please read the documentation in this page.

Revision:
1:7f4e41bacb3c
Parent:
0:8f898b781de2
Child:
2:e532bbe3fd8e
--- a/source/main.cpp	Tue Jul 26 14:42:20 2016 +0100
+++ b/source/main.cpp	Thu Jul 28 23:14:40 2016 +0100
@@ -1,198 +1,198 @@
-/* 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.
- */
-
-#include <mbed-events/events.h>
-#include <mbed.h>
-#include "ble/BLE.h"
-
-DigitalOut  led1(LED1, 1);
-InterruptIn button(BUTTON1);
-uint8_t cnt;
-
-// Change your device name below
-const char DEVICE_NAME[] = "GAPButton";
-
-/* We can arbiturarily choose the GAPButton service UUID to be 0xAA00
- * as long as it does not overlap with the UUIDs defined here:
- * https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx */
-#define GAPButtonUUID 0xAA00
-const uint16_t uuid16_list[] = {GAPButtonUUID};
-
-static EventQueue eventQueue(
-    /* event count */ 16 * /* event size */ 32
-);
-
-void print_error(ble_error_t error, const char* msg)
-{
-    printf("%s: ", msg);
-    switch(error) {
-        case BLE_ERROR_NONE:
-            printf("BLE_ERROR_NONE: No error");
-            break;
-        case BLE_ERROR_BUFFER_OVERFLOW:
-            printf("BLE_ERROR_BUFFER_OVERFLOW: The requested action would cause a buffer overflow and has been aborted");
-            break;
-        case BLE_ERROR_NOT_IMPLEMENTED:
-            printf("BLE_ERROR_NOT_IMPLEMENTED: Requested a feature that isn't yet implement or isn't supported by the target HW");
-            break;
-        case BLE_ERROR_PARAM_OUT_OF_RANGE:
-            printf("BLE_ERROR_PARAM_OUT_OF_RANGE: One of the supplied parameters is outside the valid range");
-            break;
-        case BLE_ERROR_INVALID_PARAM:
-            printf("BLE_ERROR_INVALID_PARAM: One of the supplied parameters is invalid");
-            break;
-        case BLE_STACK_BUSY:
-            printf("BLE_STACK_BUSY: The stack is busy");
-            break;
-        case BLE_ERROR_INVALID_STATE:
-            printf("BLE_ERROR_INVALID_STATE: Invalid state");
-            break;
-        case BLE_ERROR_NO_MEM:
-            printf("BLE_ERROR_NO_MEM: Out of Memory");
-            break;
-        case BLE_ERROR_OPERATION_NOT_PERMITTED:
-            printf("BLE_ERROR_OPERATION_NOT_PERMITTED");
-            break;
-        case BLE_ERROR_INITIALIZATION_INCOMPLETE:
-            printf("BLE_ERROR_INITIALIZATION_INCOMPLETE");
-            break;
-        case BLE_ERROR_ALREADY_INITIALIZED:
-            printf("BLE_ERROR_ALREADY_INITIALIZED");
-            break;
-        case BLE_ERROR_UNSPECIFIED:
-            printf("BLE_ERROR_UNSPECIFIED: Unknown error");
-            break;
-        case BLE_ERROR_INTERNAL_STACK_FAILURE:
-            printf("BLE_ERROR_INTERNAL_STACK_FAILURE: internal stack faillure");
-            break;
-    }
-    printf("\r\n");
-}
-
-void updatePayload(void)
-{
-    // Update the count in the SERVICE_DATA field of the advertising payload
-    uint8_t service_data[3];
-    service_data[0] = GAPButtonUUID & 0xff;
-    service_data[1] = GAPButtonUUID >> 8;
-    service_data[2] = cnt; // Put the button click count in the third byte
-    ble_error_t err = BLE::Instance().gap().updateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, (uint8_t *)service_data, sizeof(service_data));
-    if (err != BLE_ERROR_NONE) {
-        print_error(err, "Updating payload failed");
-    }
-}
-
-void buttonPressedCallback(void)
-{
-    ++cnt;
-
-    // Calling BLE api in interrupt context may cause race conditions
-    // Using mbed-events to schedule calls to BLE api for safety
-    eventQueue.post(updatePayload);
-}
-
-void blinkCallback(void)
-{
-    led1 = !led1;
-}
-
-void bleInitComplete(BLE::InitializationCompleteCallbackContext *context)
-{
-    BLE&        ble = context->ble;
-    ble_error_t err = context->error;
-
-    if (err != BLE_ERROR_NONE) {
-        print_error(err, "BLE initialisation failed");
-        return;
-    }
-
-    // Set up the advertising flags. Note: not all combination of flags are valid
-    // BREDR_NOT_SUPPORTED: Device does not support Basic Rate or Enchanced Data Rate, It is Low Energy only.
-    // LE_GENERAL_DISCOVERABLE: Peripheral device is discoverable at any moment
-    err = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
-    if (err != BLE_ERROR_NONE) {
-        print_error(err, "Setting GAP flags failed");
-        return;
-    }
-
-    // Put the device name in the advertising payload
-    err = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
-    if (err != BLE_ERROR_NONE) {
-        print_error(err, "Setting device name failed");
-        return;
-    }
-
-    err = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
-    if (err != BLE_ERROR_NONE) {
-        print_error(err, "Setting service UUID failed");
-        return;
-    }
-
-    // The Service Data data type consists of a service UUID with the data associated with that service.
-    // We will encode the number of button clicks in the Service Data field
-    // First two bytes of SERVICE_DATA field should contain the UUID of the service
-    uint8_t service_data[3];
-    service_data[0] = GAPButtonUUID & 0xff;
-    service_data[1] = GAPButtonUUID >> 8;
-    service_data[2] = cnt; // Put the button click count in the third byte
-    err = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, (uint8_t *)service_data, sizeof(service_data));
-    if (err != BLE_ERROR_NONE) {
-        print_error(err, "Setting service data failed");
-        return;
-    }
-
-    // It is not connectable as we are just boardcasting
-    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED);
-
-    // Send out the advertising payload every 1000ms
-    ble.gap().setAdvertisingInterval(1000);
-
-    err = ble.gap().startAdvertising();
-    if (err != BLE_ERROR_NONE) {
-        print_error(err, "Sart advertising failed");
-        return;
-    }
-}
-
-void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
-    BLE &ble = BLE::Instance();
-    eventQueue.post(Callback<void()>(&ble, &BLE::processEvents));
-}
-
-int main()
-{
-    cnt = 0;
-
-    BLE &ble = BLE::Instance();
-    ble.onEventsToProcess(scheduleBleEventsProcessing);
-    ble_error_t err = ble.init(bleInitComplete);
-    if (err != BLE_ERROR_NONE) {
-        print_error(err, "BLE initialisation failed");
-        return 0;
-    }
-
-    // Blink LED every 500 ms to indicate system aliveness
-    eventQueue.post_every(blinkCallback, 500);
-
-    // Register function to be called when button is released
-    button.rise(buttonPressedCallback);
-
-    while (true) {
-        eventQueue.dispatch();
-    }
-
-    return 0;
-}
+/* 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.
+ */
+
+#include <mbed-events/events.h>
+#include <mbed.h>
+#include "ble/BLE.h"
+
+DigitalOut  led1(LED1, 1);
+InterruptIn button(BUTTON1);
+uint8_t cnt;
+
+// Change your device name below
+const char DEVICE_NAME[] = "GAPButton";
+
+/* We can arbiturarily choose the GAPButton service UUID to be 0xAA00
+ * as long as it does not overlap with the UUIDs defined here:
+ * https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx */
+#define GAPButtonUUID 0xAA00
+const uint16_t uuid16_list[] = {GAPButtonUUID};
+
+static EventQueue eventQueue(
+    /* event count */ 16 * /* event size */ 32
+);
+
+void print_error(ble_error_t error, const char* msg)
+{
+    printf("%s: ", msg);
+    switch(error) {
+        case BLE_ERROR_NONE:
+            printf("BLE_ERROR_NONE: No error");
+            break;
+        case BLE_ERROR_BUFFER_OVERFLOW:
+            printf("BLE_ERROR_BUFFER_OVERFLOW: The requested action would cause a buffer overflow and has been aborted");
+            break;
+        case BLE_ERROR_NOT_IMPLEMENTED:
+            printf("BLE_ERROR_NOT_IMPLEMENTED: Requested a feature that isn't yet implement or isn't supported by the target HW");
+            break;
+        case BLE_ERROR_PARAM_OUT_OF_RANGE:
+            printf("BLE_ERROR_PARAM_OUT_OF_RANGE: One of the supplied parameters is outside the valid range");
+            break;
+        case BLE_ERROR_INVALID_PARAM:
+            printf("BLE_ERROR_INVALID_PARAM: One of the supplied parameters is invalid");
+            break;
+        case BLE_STACK_BUSY:
+            printf("BLE_STACK_BUSY: The stack is busy");
+            break;
+        case BLE_ERROR_INVALID_STATE:
+            printf("BLE_ERROR_INVALID_STATE: Invalid state");
+            break;
+        case BLE_ERROR_NO_MEM:
+            printf("BLE_ERROR_NO_MEM: Out of Memory");
+            break;
+        case BLE_ERROR_OPERATION_NOT_PERMITTED:
+            printf("BLE_ERROR_OPERATION_NOT_PERMITTED");
+            break;
+        case BLE_ERROR_INITIALIZATION_INCOMPLETE:
+            printf("BLE_ERROR_INITIALIZATION_INCOMPLETE");
+            break;
+        case BLE_ERROR_ALREADY_INITIALIZED:
+            printf("BLE_ERROR_ALREADY_INITIALIZED");
+            break;
+        case BLE_ERROR_UNSPECIFIED:
+            printf("BLE_ERROR_UNSPECIFIED: Unknown error");
+            break;
+        case BLE_ERROR_INTERNAL_STACK_FAILURE:
+            printf("BLE_ERROR_INTERNAL_STACK_FAILURE: internal stack faillure");
+            break;
+    }
+    printf("\r\n");
+}
+
+void updatePayload(void)
+{
+    // Update the count in the SERVICE_DATA field of the advertising payload
+    uint8_t service_data[3];
+    service_data[0] = GAPButtonUUID & 0xff;
+    service_data[1] = GAPButtonUUID >> 8;
+    service_data[2] = cnt; // Put the button click count in the third byte
+    ble_error_t err = BLE::Instance().gap().updateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, (uint8_t *)service_data, sizeof(service_data));
+    if (err != BLE_ERROR_NONE) {
+        print_error(err, "Updating payload failed");
+    }
+}
+
+void buttonPressedCallback(void)
+{
+    ++cnt;
+
+    // Calling BLE api in interrupt context may cause race conditions
+    // Using mbed-events to schedule calls to BLE api for safety
+    eventQueue.post(updatePayload);
+}
+
+void blinkCallback(void)
+{
+    led1 = !led1;
+}
+
+void bleInitComplete(BLE::InitializationCompleteCallbackContext *context)
+{
+    BLE&        ble = context->ble;
+    ble_error_t err = context->error;
+
+    if (err != BLE_ERROR_NONE) {
+        print_error(err, "BLE initialisation failed");
+        return;
+    }
+
+    // Set up the advertising flags. Note: not all combination of flags are valid
+    // BREDR_NOT_SUPPORTED: Device does not support Basic Rate or Enchanced Data Rate, It is Low Energy only.
+    // LE_GENERAL_DISCOVERABLE: Peripheral device is discoverable at any moment
+    err = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
+    if (err != BLE_ERROR_NONE) {
+        print_error(err, "Setting GAP flags failed");
+        return;
+    }
+
+    // Put the device name in the advertising payload
+    err = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
+    if (err != BLE_ERROR_NONE) {
+        print_error(err, "Setting device name failed");
+        return;
+    }
+
+    err = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
+    if (err != BLE_ERROR_NONE) {
+        print_error(err, "Setting service UUID failed");
+        return;
+    }
+
+    // The Service Data data type consists of a service UUID with the data associated with that service.
+    // We will encode the number of button clicks in the Service Data field
+    // First two bytes of SERVICE_DATA field should contain the UUID of the service
+    uint8_t service_data[3];
+    service_data[0] = GAPButtonUUID & 0xff;
+    service_data[1] = GAPButtonUUID >> 8;
+    service_data[2] = cnt; // Put the button click count in the third byte
+    err = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, (uint8_t *)service_data, sizeof(service_data));
+    if (err != BLE_ERROR_NONE) {
+        print_error(err, "Setting service data failed");
+        return;
+    }
+
+    // It is not connectable as we are just boardcasting
+    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED);
+
+    // Send out the advertising payload every 1000ms
+    ble.gap().setAdvertisingInterval(1000);
+
+    err = ble.gap().startAdvertising();
+    if (err != BLE_ERROR_NONE) {
+        print_error(err, "Sart advertising failed");
+        return;
+    }
+}
+
+void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
+    BLE &ble = BLE::Instance();
+    eventQueue.post(Callback<void()>(&ble, &BLE::processEvents));
+}
+
+int main()
+{
+    cnt = 0;
+
+    BLE &ble = BLE::Instance();
+    ble.onEventsToProcess(scheduleBleEventsProcessing);
+    ble_error_t err = ble.init(bleInitComplete);
+    if (err != BLE_ERROR_NONE) {
+        print_error(err, "BLE initialisation failed");
+        return 0;
+    }
+
+    // Blink LED every 500 ms to indicate system aliveness
+    eventQueue.post_every(500, blinkCallback);
+
+    // Register function to be called when button is released
+    button.rise(buttonPressedCallback);
+
+    while (true) {
+        eventQueue.dispatch();
+    }
+
+    return 0;
+}