This application shows how to use GAP to transmit a simple value to disconnected peer listening for advertisement every time that a value is updated. The canonical source for this example lives at: https://github.com/ARMmbed/mbed-os-example-ble/tree/master/BLE_GAPButton

Button count over GAP

This application shows how to use GAP to transmit a simple value to disconnected peer listening for advertisement every time that a value is updated:

  • The value is a count of how many times a button on the device was pressed (the code actually monitors the button's releases, not press downs).
  • We transmit the value in the SERVICE_DATA field of the advertising payload.

Running the application

Requirements

The sample application can be seen on any BLE scanner on a smartphone. If you don't have a scanner on your phone, please install :

- nRF Master Control Panel for Android.

- LightBlue for iPhone.

Hardware requirements are in the main readme.

Building instructions

Building with mbed CLI

If you'd like to use mbed CLI to build this, then you should refer to the main readme. The instructions here relate to using the developer.mbed.org Online Compiler

In order to build this example in the mbed Online Compiler, first import the example using the ‘Import’ button on the right hand side.

Next, select a platform to build for. This must either be a platform that supports BLE, for example the NRF51-DK, or one of the following:

List of platforms supporting Bluetooth Low Energy

Or you must also add a piece of hardware and the supporting library that includes a Bluetooth Low Energy driver for that hardware, for example the K64F or NUCLEO_F401RE with the X-NUCLEO-IDB05A1

List of components supporting Bluetooth Low Energy.

Once you have selected your platform, compile the example and drag and drop the resulting binary onto your board.

For general instructions on using the mbed Online Compiler, please see the mbed Handbook

Checking for success

Note: Screens captures depicted below show what is expected from this example if the scanner used is nRF Master Control Panel version 4.0.5. If you encounter any difficulties consider trying another scanner or another version of nRF Master Control Panel. Alternative scanners may require reference to their manuals.

  • Build the application and install it on your board as explained in the building instructions.
  • Open the BLE scanner on your phone.
  • Start a scan.

https://developer.mbed.org/teams/mbed-os-examples/code/mbed-os-example-ble-GAPButton/raw-file/8f898b781de2/img/start_scan.png

figure 1 How to start scan using nRF Master Control Panel 4.0.5.

  • Find your device; it should be named `GAPButton`; and look at the advertisement broadcasted by your device (there is no need to connect to your device).

https://developer.mbed.org/teams/mbed-os-examples/code/mbed-os-example-ble-GAPButton/raw-file/8f898b781de2/img/discovery.png

figure 2 Scan results using nRF Master Control Panel 4.0.5.

  • The Service Data field of the advertisement packet broadcasted by your device reflects the button press count. The starting value is 0.

https://developer.mbed.org/teams/mbed-os-examples/code/mbed-os-example-ble-GAPButton/raw-file/8f898b781de2/img/initial_state.png

figure 3 Initial state of the button using nRF Master Control Panel 4.0.5.

  • Press the button on the device.

https://developer.mbed.org/teams/mbed-os-examples/code/mbed-os-example-ble-GAPButton/raw-file/8f898b781de2/img/first_press.png

figure 3 State after 1 button press using nRF Master Control Panel 4.0.5.

  • The Service Data field value of the advertisement packet should change every time you press the button.

https://developer.mbed.org/teams/mbed-os-examples/code/mbed-os-example-ble-GAPButton/raw-file/8f898b781de2/img/result.png

figure 3 State after 6 button press using nRF Master Control Panel 4.0.5.

Note

Since broadcasting is not reliable and your phone may scan intermittently, it is possible that your phone will miss button updates.

Committer:
mbed_official
Date:
Thu Aug 04 12:15:26 2016 +0100
Revision:
6:bfe23efb0d97
Parent:
3:f0ed4199b362
Child:
14:332bb3fa072b
Makes button definition in BLE_GapButton example configurable.


Commit copied from https://github.com/ARMmbed/mbed-os-example-ble

Who changed what in which revision?

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