ST / Mbed OS mbed-os-example-ble-GAPButton

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.

Committer:
Vincent Coubard
Date:
Tue Jul 26 14:42:20 2016 +0100
Revision:
0:8f898b781de2
Child:
1:7f4e41bacb3c
Update example at tag mbed-os-5.0.1-rc1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Vincent Coubard 0:8f898b781de2 1 /* mbed Microcontroller Library
Vincent Coubard 0:8f898b781de2 2 * Copyright (c) 2006-2013 ARM Limited
Vincent Coubard 0:8f898b781de2 3 *
Vincent Coubard 0:8f898b781de2 4 * Licensed under the Apache License, Version 2.0 (the "License");
Vincent Coubard 0:8f898b781de2 5 * you may not use this file except in compliance with the License.
Vincent Coubard 0:8f898b781de2 6 * You may obtain a copy of the License at
Vincent Coubard 0:8f898b781de2 7 *
Vincent Coubard 0:8f898b781de2 8 * http://www.apache.org/licenses/LICENSE-2.0
Vincent Coubard 0:8f898b781de2 9 *
Vincent Coubard 0:8f898b781de2 10 * Unless required by applicable law or agreed to in writing, software
Vincent Coubard 0:8f898b781de2 11 * distributed under the License is distributed on an "AS IS" BASIS,
Vincent Coubard 0:8f898b781de2 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Vincent Coubard 0:8f898b781de2 13 * See the License for the specific language governing permissions and
Vincent Coubard 0:8f898b781de2 14 * limitations under the License.
Vincent Coubard 0:8f898b781de2 15 */
Vincent Coubard 0:8f898b781de2 16
Vincent Coubard 0:8f898b781de2 17 #include <mbed-events/events.h>
Vincent Coubard 0:8f898b781de2 18 #include <mbed.h>
Vincent Coubard 0:8f898b781de2 19 #include "ble/BLE.h"
Vincent Coubard 0:8f898b781de2 20
Vincent Coubard 0:8f898b781de2 21 DigitalOut led1(LED1, 1);
Vincent Coubard 0:8f898b781de2 22 InterruptIn button(BUTTON1);
Vincent Coubard 0:8f898b781de2 23 uint8_t cnt;
Vincent Coubard 0:8f898b781de2 24
Vincent Coubard 0:8f898b781de2 25 // Change your device name below
Vincent Coubard 0:8f898b781de2 26 const char DEVICE_NAME[] = "GAPButton";
Vincent Coubard 0:8f898b781de2 27
Vincent Coubard 0:8f898b781de2 28 /* We can arbiturarily choose the GAPButton service UUID to be 0xAA00
Vincent Coubard 0:8f898b781de2 29 * as long as it does not overlap with the UUIDs defined here:
Vincent Coubard 0:8f898b781de2 30 * https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx */
Vincent Coubard 0:8f898b781de2 31 #define GAPButtonUUID 0xAA00
Vincent Coubard 0:8f898b781de2 32 const uint16_t uuid16_list[] = {GAPButtonUUID};
Vincent Coubard 0:8f898b781de2 33
Vincent Coubard 0:8f898b781de2 34 static EventQueue eventQueue(
Vincent Coubard 0:8f898b781de2 35 /* event count */ 16 * /* event size */ 32
Vincent Coubard 0:8f898b781de2 36 );
Vincent Coubard 0:8f898b781de2 37
Vincent Coubard 0:8f898b781de2 38 void print_error(ble_error_t error, const char* msg)
Vincent Coubard 0:8f898b781de2 39 {
Vincent Coubard 0:8f898b781de2 40 printf("%s: ", msg);
Vincent Coubard 0:8f898b781de2 41 switch(error) {
Vincent Coubard 0:8f898b781de2 42 case BLE_ERROR_NONE:
Vincent Coubard 0:8f898b781de2 43 printf("BLE_ERROR_NONE: No error");
Vincent Coubard 0:8f898b781de2 44 break;
Vincent Coubard 0:8f898b781de2 45 case BLE_ERROR_BUFFER_OVERFLOW:
Vincent Coubard 0:8f898b781de2 46 printf("BLE_ERROR_BUFFER_OVERFLOW: The requested action would cause a buffer overflow and has been aborted");
Vincent Coubard 0:8f898b781de2 47 break;
Vincent Coubard 0:8f898b781de2 48 case BLE_ERROR_NOT_IMPLEMENTED:
Vincent Coubard 0:8f898b781de2 49 printf("BLE_ERROR_NOT_IMPLEMENTED: Requested a feature that isn't yet implement or isn't supported by the target HW");
Vincent Coubard 0:8f898b781de2 50 break;
Vincent Coubard 0:8f898b781de2 51 case BLE_ERROR_PARAM_OUT_OF_RANGE:
Vincent Coubard 0:8f898b781de2 52 printf("BLE_ERROR_PARAM_OUT_OF_RANGE: One of the supplied parameters is outside the valid range");
Vincent Coubard 0:8f898b781de2 53 break;
Vincent Coubard 0:8f898b781de2 54 case BLE_ERROR_INVALID_PARAM:
Vincent Coubard 0:8f898b781de2 55 printf("BLE_ERROR_INVALID_PARAM: One of the supplied parameters is invalid");
Vincent Coubard 0:8f898b781de2 56 break;
Vincent Coubard 0:8f898b781de2 57 case BLE_STACK_BUSY:
Vincent Coubard 0:8f898b781de2 58 printf("BLE_STACK_BUSY: The stack is busy");
Vincent Coubard 0:8f898b781de2 59 break;
Vincent Coubard 0:8f898b781de2 60 case BLE_ERROR_INVALID_STATE:
Vincent Coubard 0:8f898b781de2 61 printf("BLE_ERROR_INVALID_STATE: Invalid state");
Vincent Coubard 0:8f898b781de2 62 break;
Vincent Coubard 0:8f898b781de2 63 case BLE_ERROR_NO_MEM:
Vincent Coubard 0:8f898b781de2 64 printf("BLE_ERROR_NO_MEM: Out of Memory");
Vincent Coubard 0:8f898b781de2 65 break;
Vincent Coubard 0:8f898b781de2 66 case BLE_ERROR_OPERATION_NOT_PERMITTED:
Vincent Coubard 0:8f898b781de2 67 printf("BLE_ERROR_OPERATION_NOT_PERMITTED");
Vincent Coubard 0:8f898b781de2 68 break;
Vincent Coubard 0:8f898b781de2 69 case BLE_ERROR_INITIALIZATION_INCOMPLETE:
Vincent Coubard 0:8f898b781de2 70 printf("BLE_ERROR_INITIALIZATION_INCOMPLETE");
Vincent Coubard 0:8f898b781de2 71 break;
Vincent Coubard 0:8f898b781de2 72 case BLE_ERROR_ALREADY_INITIALIZED:
Vincent Coubard 0:8f898b781de2 73 printf("BLE_ERROR_ALREADY_INITIALIZED");
Vincent Coubard 0:8f898b781de2 74 break;
Vincent Coubard 0:8f898b781de2 75 case BLE_ERROR_UNSPECIFIED:
Vincent Coubard 0:8f898b781de2 76 printf("BLE_ERROR_UNSPECIFIED: Unknown error");
Vincent Coubard 0:8f898b781de2 77 break;
Vincent Coubard 0:8f898b781de2 78 case BLE_ERROR_INTERNAL_STACK_FAILURE:
Vincent Coubard 0:8f898b781de2 79 printf("BLE_ERROR_INTERNAL_STACK_FAILURE: internal stack faillure");
Vincent Coubard 0:8f898b781de2 80 break;
Vincent Coubard 0:8f898b781de2 81 }
Vincent Coubard 0:8f898b781de2 82 printf("\r\n");
Vincent Coubard 0:8f898b781de2 83 }
Vincent Coubard 0:8f898b781de2 84
Vincent Coubard 0:8f898b781de2 85 void updatePayload(void)
Vincent Coubard 0:8f898b781de2 86 {
Vincent Coubard 0:8f898b781de2 87 // Update the count in the SERVICE_DATA field of the advertising payload
Vincent Coubard 0:8f898b781de2 88 uint8_t service_data[3];
Vincent Coubard 0:8f898b781de2 89 service_data[0] = GAPButtonUUID & 0xff;
Vincent Coubard 0:8f898b781de2 90 service_data[1] = GAPButtonUUID >> 8;
Vincent Coubard 0:8f898b781de2 91 service_data[2] = cnt; // Put the button click count in the third byte
Vincent Coubard 0:8f898b781de2 92 ble_error_t err = BLE::Instance().gap().updateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, (uint8_t *)service_data, sizeof(service_data));
Vincent Coubard 0:8f898b781de2 93 if (err != BLE_ERROR_NONE) {
Vincent Coubard 0:8f898b781de2 94 print_error(err, "Updating payload failed");
Vincent Coubard 0:8f898b781de2 95 }
Vincent Coubard 0:8f898b781de2 96 }
Vincent Coubard 0:8f898b781de2 97
Vincent Coubard 0:8f898b781de2 98 void buttonPressedCallback(void)
Vincent Coubard 0:8f898b781de2 99 {
Vincent Coubard 0:8f898b781de2 100 ++cnt;
Vincent Coubard 0:8f898b781de2 101
Vincent Coubard 0:8f898b781de2 102 // Calling BLE api in interrupt context may cause race conditions
Vincent Coubard 0:8f898b781de2 103 // Using mbed-events to schedule calls to BLE api for safety
Vincent Coubard 0:8f898b781de2 104 eventQueue.post(updatePayload);
Vincent Coubard 0:8f898b781de2 105 }
Vincent Coubard 0:8f898b781de2 106
Vincent Coubard 0:8f898b781de2 107 void blinkCallback(void)
Vincent Coubard 0:8f898b781de2 108 {
Vincent Coubard 0:8f898b781de2 109 led1 = !led1;
Vincent Coubard 0:8f898b781de2 110 }
Vincent Coubard 0:8f898b781de2 111
Vincent Coubard 0:8f898b781de2 112 void bleInitComplete(BLE::InitializationCompleteCallbackContext *context)
Vincent Coubard 0:8f898b781de2 113 {
Vincent Coubard 0:8f898b781de2 114 BLE& ble = context->ble;
Vincent Coubard 0:8f898b781de2 115 ble_error_t err = context->error;
Vincent Coubard 0:8f898b781de2 116
Vincent Coubard 0:8f898b781de2 117 if (err != BLE_ERROR_NONE) {
Vincent Coubard 0:8f898b781de2 118 print_error(err, "BLE initialisation failed");
Vincent Coubard 0:8f898b781de2 119 return;
Vincent Coubard 0:8f898b781de2 120 }
Vincent Coubard 0:8f898b781de2 121
Vincent Coubard 0:8f898b781de2 122 // Set up the advertising flags. Note: not all combination of flags are valid
Vincent Coubard 0:8f898b781de2 123 // BREDR_NOT_SUPPORTED: Device does not support Basic Rate or Enchanced Data Rate, It is Low Energy only.
Vincent Coubard 0:8f898b781de2 124 // LE_GENERAL_DISCOVERABLE: Peripheral device is discoverable at any moment
Vincent Coubard 0:8f898b781de2 125 err = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
Vincent Coubard 0:8f898b781de2 126 if (err != BLE_ERROR_NONE) {
Vincent Coubard 0:8f898b781de2 127 print_error(err, "Setting GAP flags failed");
Vincent Coubard 0:8f898b781de2 128 return;
Vincent Coubard 0:8f898b781de2 129 }
Vincent Coubard 0:8f898b781de2 130
Vincent Coubard 0:8f898b781de2 131 // Put the device name in the advertising payload
Vincent Coubard 0:8f898b781de2 132 err = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
Vincent Coubard 0:8f898b781de2 133 if (err != BLE_ERROR_NONE) {
Vincent Coubard 0:8f898b781de2 134 print_error(err, "Setting device name failed");
Vincent Coubard 0:8f898b781de2 135 return;
Vincent Coubard 0:8f898b781de2 136 }
Vincent Coubard 0:8f898b781de2 137
Vincent Coubard 0:8f898b781de2 138 err = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
Vincent Coubard 0:8f898b781de2 139 if (err != BLE_ERROR_NONE) {
Vincent Coubard 0:8f898b781de2 140 print_error(err, "Setting service UUID failed");
Vincent Coubard 0:8f898b781de2 141 return;
Vincent Coubard 0:8f898b781de2 142 }
Vincent Coubard 0:8f898b781de2 143
Vincent Coubard 0:8f898b781de2 144 // The Service Data data type consists of a service UUID with the data associated with that service.
Vincent Coubard 0:8f898b781de2 145 // We will encode the number of button clicks in the Service Data field
Vincent Coubard 0:8f898b781de2 146 // First two bytes of SERVICE_DATA field should contain the UUID of the service
Vincent Coubard 0:8f898b781de2 147 uint8_t service_data[3];
Vincent Coubard 0:8f898b781de2 148 service_data[0] = GAPButtonUUID & 0xff;
Vincent Coubard 0:8f898b781de2 149 service_data[1] = GAPButtonUUID >> 8;
Vincent Coubard 0:8f898b781de2 150 service_data[2] = cnt; // Put the button click count in the third byte
Vincent Coubard 0:8f898b781de2 151 err = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, (uint8_t *)service_data, sizeof(service_data));
Vincent Coubard 0:8f898b781de2 152 if (err != BLE_ERROR_NONE) {
Vincent Coubard 0:8f898b781de2 153 print_error(err, "Setting service data failed");
Vincent Coubard 0:8f898b781de2 154 return;
Vincent Coubard 0:8f898b781de2 155 }
Vincent Coubard 0:8f898b781de2 156
Vincent Coubard 0:8f898b781de2 157 // It is not connectable as we are just boardcasting
Vincent Coubard 0:8f898b781de2 158 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED);
Vincent Coubard 0:8f898b781de2 159
Vincent Coubard 0:8f898b781de2 160 // Send out the advertising payload every 1000ms
Vincent Coubard 0:8f898b781de2 161 ble.gap().setAdvertisingInterval(1000);
Vincent Coubard 0:8f898b781de2 162
Vincent Coubard 0:8f898b781de2 163 err = ble.gap().startAdvertising();
Vincent Coubard 0:8f898b781de2 164 if (err != BLE_ERROR_NONE) {
Vincent Coubard 0:8f898b781de2 165 print_error(err, "Sart advertising failed");
Vincent Coubard 0:8f898b781de2 166 return;
Vincent Coubard 0:8f898b781de2 167 }
Vincent Coubard 0:8f898b781de2 168 }
Vincent Coubard 0:8f898b781de2 169
Vincent Coubard 0:8f898b781de2 170 void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
Vincent Coubard 0:8f898b781de2 171 BLE &ble = BLE::Instance();
Vincent Coubard 0:8f898b781de2 172 eventQueue.post(Callback<void()>(&ble, &BLE::processEvents));
Vincent Coubard 0:8f898b781de2 173 }
Vincent Coubard 0:8f898b781de2 174
Vincent Coubard 0:8f898b781de2 175 int main()
Vincent Coubard 0:8f898b781de2 176 {
Vincent Coubard 0:8f898b781de2 177 cnt = 0;
Vincent Coubard 0:8f898b781de2 178
Vincent Coubard 0:8f898b781de2 179 BLE &ble = BLE::Instance();
Vincent Coubard 0:8f898b781de2 180 ble.onEventsToProcess(scheduleBleEventsProcessing);
Vincent Coubard 0:8f898b781de2 181 ble_error_t err = ble.init(bleInitComplete);
Vincent Coubard 0:8f898b781de2 182 if (err != BLE_ERROR_NONE) {
Vincent Coubard 0:8f898b781de2 183 print_error(err, "BLE initialisation failed");
Vincent Coubard 0:8f898b781de2 184 return 0;
Vincent Coubard 0:8f898b781de2 185 }
Vincent Coubard 0:8f898b781de2 186
Vincent Coubard 0:8f898b781de2 187 // Blink LED every 500 ms to indicate system aliveness
Vincent Coubard 0:8f898b781de2 188 eventQueue.post_every(blinkCallback, 500);
Vincent Coubard 0:8f898b781de2 189
Vincent Coubard 0:8f898b781de2 190 // Register function to be called when button is released
Vincent Coubard 0:8f898b781de2 191 button.rise(buttonPressedCallback);
Vincent Coubard 0:8f898b781de2 192
Vincent Coubard 0:8f898b781de2 193 while (true) {
Vincent Coubard 0:8f898b781de2 194 eventQueue.dispatch();
Vincent Coubard 0:8f898b781de2 195 }
Vincent Coubard 0:8f898b781de2 196
Vincent Coubard 0:8f898b781de2 197 return 0;
Vincent Coubard 0:8f898b781de2 198 }