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:
Wed Nov 01 15:30:48 2017 +0000
Revision:
47:70f571463f31
Parent:
30:217bfc94a9b7
Child:
78:3f848aa75a8a
Merge pull request #112 from marcbonnici/master

Add MAC address printouts to examples
.
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 14:332bb3fa072b 17 #include <events/mbed_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 30:217bfc94a9b7 34 static EventQueue eventQueue(/* event count */ 16 * EVENTS_EVENT_SIZE);
mbed_official 3:f0ed4199b362 35
mbed_official 3:f0ed4199b362 36 void print_error(ble_error_t error, const char* msg)
mbed_official 3:f0ed4199b362 37 {
mbed_official 3:f0ed4199b362 38 printf("%s: ", msg);
mbed_official 3:f0ed4199b362 39 switch(error) {
mbed_official 3:f0ed4199b362 40 case BLE_ERROR_NONE:
mbed_official 3:f0ed4199b362 41 printf("BLE_ERROR_NONE: No error");
mbed_official 3:f0ed4199b362 42 break;
mbed_official 3:f0ed4199b362 43 case BLE_ERROR_BUFFER_OVERFLOW:
mbed_official 3:f0ed4199b362 44 printf("BLE_ERROR_BUFFER_OVERFLOW: The requested action would cause a buffer overflow and has been aborted");
mbed_official 3:f0ed4199b362 45 break;
mbed_official 3:f0ed4199b362 46 case BLE_ERROR_NOT_IMPLEMENTED:
mbed_official 3:f0ed4199b362 47 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 48 break;
mbed_official 3:f0ed4199b362 49 case BLE_ERROR_PARAM_OUT_OF_RANGE:
mbed_official 3:f0ed4199b362 50 printf("BLE_ERROR_PARAM_OUT_OF_RANGE: One of the supplied parameters is outside the valid range");
mbed_official 3:f0ed4199b362 51 break;
mbed_official 3:f0ed4199b362 52 case BLE_ERROR_INVALID_PARAM:
mbed_official 3:f0ed4199b362 53 printf("BLE_ERROR_INVALID_PARAM: One of the supplied parameters is invalid");
mbed_official 3:f0ed4199b362 54 break;
mbed_official 3:f0ed4199b362 55 case BLE_STACK_BUSY:
mbed_official 3:f0ed4199b362 56 printf("BLE_STACK_BUSY: The stack is busy");
mbed_official 3:f0ed4199b362 57 break;
mbed_official 3:f0ed4199b362 58 case BLE_ERROR_INVALID_STATE:
mbed_official 3:f0ed4199b362 59 printf("BLE_ERROR_INVALID_STATE: Invalid state");
mbed_official 3:f0ed4199b362 60 break;
mbed_official 3:f0ed4199b362 61 case BLE_ERROR_NO_MEM:
mbed_official 3:f0ed4199b362 62 printf("BLE_ERROR_NO_MEM: Out of Memory");
mbed_official 3:f0ed4199b362 63 break;
mbed_official 3:f0ed4199b362 64 case BLE_ERROR_OPERATION_NOT_PERMITTED:
mbed_official 3:f0ed4199b362 65 printf("BLE_ERROR_OPERATION_NOT_PERMITTED");
mbed_official 3:f0ed4199b362 66 break;
mbed_official 3:f0ed4199b362 67 case BLE_ERROR_INITIALIZATION_INCOMPLETE:
mbed_official 3:f0ed4199b362 68 printf("BLE_ERROR_INITIALIZATION_INCOMPLETE");
mbed_official 3:f0ed4199b362 69 break;
mbed_official 3:f0ed4199b362 70 case BLE_ERROR_ALREADY_INITIALIZED:
mbed_official 3:f0ed4199b362 71 printf("BLE_ERROR_ALREADY_INITIALIZED");
mbed_official 3:f0ed4199b362 72 break;
mbed_official 3:f0ed4199b362 73 case BLE_ERROR_UNSPECIFIED:
mbed_official 3:f0ed4199b362 74 printf("BLE_ERROR_UNSPECIFIED: Unknown error");
mbed_official 3:f0ed4199b362 75 break;
mbed_official 3:f0ed4199b362 76 case BLE_ERROR_INTERNAL_STACK_FAILURE:
mbed_official 3:f0ed4199b362 77 printf("BLE_ERROR_INTERNAL_STACK_FAILURE: internal stack faillure");
mbed_official 3:f0ed4199b362 78 break;
mbed_official 3:f0ed4199b362 79 }
mbed_official 3:f0ed4199b362 80 printf("\r\n");
mbed_official 3:f0ed4199b362 81 }
mbed_official 3:f0ed4199b362 82
mbed_official 3:f0ed4199b362 83 void updatePayload(void)
mbed_official 3:f0ed4199b362 84 {
mbed_official 3:f0ed4199b362 85 // Update the count in the SERVICE_DATA field of the advertising payload
mbed_official 3:f0ed4199b362 86 uint8_t service_data[3];
mbed_official 3:f0ed4199b362 87 service_data[0] = GAPButtonUUID & 0xff;
mbed_official 3:f0ed4199b362 88 service_data[1] = GAPButtonUUID >> 8;
mbed_official 3:f0ed4199b362 89 service_data[2] = cnt; // Put the button click count in the third byte
mbed_official 3:f0ed4199b362 90 ble_error_t err = BLE::Instance().gap().updateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, (uint8_t *)service_data, sizeof(service_data));
mbed_official 3:f0ed4199b362 91 if (err != BLE_ERROR_NONE) {
mbed_official 3:f0ed4199b362 92 print_error(err, "Updating payload failed");
mbed_official 3:f0ed4199b362 93 }
mbed_official 3:f0ed4199b362 94 }
mbed_official 3:f0ed4199b362 95
mbed_official 3:f0ed4199b362 96 void buttonPressedCallback(void)
mbed_official 3:f0ed4199b362 97 {
mbed_official 3:f0ed4199b362 98 ++cnt;
mbed_official 3:f0ed4199b362 99
mbed_official 3:f0ed4199b362 100 // Calling BLE api in interrupt context may cause race conditions
mbed_official 3:f0ed4199b362 101 // Using mbed-events to schedule calls to BLE api for safety
mbed_official 14:332bb3fa072b 102 eventQueue.call(updatePayload);
mbed_official 3:f0ed4199b362 103 }
mbed_official 3:f0ed4199b362 104
mbed_official 3:f0ed4199b362 105 void blinkCallback(void)
mbed_official 3:f0ed4199b362 106 {
mbed_official 3:f0ed4199b362 107 led1 = !led1;
mbed_official 3:f0ed4199b362 108 }
mbed_official 3:f0ed4199b362 109
mbed_official 47:70f571463f31 110 void printMacAddress()
mbed_official 47:70f571463f31 111 {
mbed_official 47:70f571463f31 112 /* Print out device MAC address to the console*/
mbed_official 47:70f571463f31 113 Gap::AddressType_t addr_type;
mbed_official 47:70f571463f31 114 Gap::Address_t address;
mbed_official 47:70f571463f31 115 BLE::Instance().gap().getAddress(&addr_type, address);
mbed_official 47:70f571463f31 116 printf("DEVICE MAC ADDRESS: ");
mbed_official 47:70f571463f31 117 for (int i = 5; i >= 1; i--){
mbed_official 47:70f571463f31 118 printf("%02x:", address[i]);
mbed_official 47:70f571463f31 119 }
mbed_official 47:70f571463f31 120 printf("%02x\r\n", address[0]);
mbed_official 47:70f571463f31 121 }
mbed_official 47:70f571463f31 122
mbed_official 3:f0ed4199b362 123 void bleInitComplete(BLE::InitializationCompleteCallbackContext *context)
mbed_official 3:f0ed4199b362 124 {
mbed_official 3:f0ed4199b362 125 BLE& ble = context->ble;
mbed_official 3:f0ed4199b362 126 ble_error_t err = context->error;
mbed_official 3:f0ed4199b362 127
mbed_official 3:f0ed4199b362 128 if (err != BLE_ERROR_NONE) {
mbed_official 3:f0ed4199b362 129 print_error(err, "BLE initialisation failed");
mbed_official 3:f0ed4199b362 130 return;
mbed_official 3:f0ed4199b362 131 }
mbed_official 3:f0ed4199b362 132
mbed_official 3:f0ed4199b362 133 // Set up the advertising flags. Note: not all combination of flags are valid
mbed_official 3:f0ed4199b362 134 // BREDR_NOT_SUPPORTED: Device does not support Basic Rate or Enchanced Data Rate, It is Low Energy only.
mbed_official 3:f0ed4199b362 135 // LE_GENERAL_DISCOVERABLE: Peripheral device is discoverable at any moment
mbed_official 3:f0ed4199b362 136 err = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
mbed_official 3:f0ed4199b362 137 if (err != BLE_ERROR_NONE) {
mbed_official 3:f0ed4199b362 138 print_error(err, "Setting GAP flags failed");
mbed_official 3:f0ed4199b362 139 return;
mbed_official 3:f0ed4199b362 140 }
mbed_official 3:f0ed4199b362 141
mbed_official 3:f0ed4199b362 142 // Put the device name in the advertising payload
mbed_official 3:f0ed4199b362 143 err = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
mbed_official 3:f0ed4199b362 144 if (err != BLE_ERROR_NONE) {
mbed_official 3:f0ed4199b362 145 print_error(err, "Setting device name failed");
mbed_official 3:f0ed4199b362 146 return;
mbed_official 3:f0ed4199b362 147 }
mbed_official 3:f0ed4199b362 148
mbed_official 3:f0ed4199b362 149 err = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
mbed_official 3:f0ed4199b362 150 if (err != BLE_ERROR_NONE) {
mbed_official 3:f0ed4199b362 151 print_error(err, "Setting service UUID failed");
mbed_official 3:f0ed4199b362 152 return;
mbed_official 3:f0ed4199b362 153 }
mbed_official 3:f0ed4199b362 154
mbed_official 3:f0ed4199b362 155 // The Service Data data type consists of a service UUID with the data associated with that service.
mbed_official 3:f0ed4199b362 156 // We will encode the number of button clicks in the Service Data field
mbed_official 3:f0ed4199b362 157 // First two bytes of SERVICE_DATA field should contain the UUID of the service
mbed_official 3:f0ed4199b362 158 uint8_t service_data[3];
mbed_official 3:f0ed4199b362 159 service_data[0] = GAPButtonUUID & 0xff;
mbed_official 3:f0ed4199b362 160 service_data[1] = GAPButtonUUID >> 8;
mbed_official 3:f0ed4199b362 161 service_data[2] = cnt; // Put the button click count in the third byte
mbed_official 3:f0ed4199b362 162 err = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, (uint8_t *)service_data, sizeof(service_data));
mbed_official 3:f0ed4199b362 163 if (err != BLE_ERROR_NONE) {
mbed_official 3:f0ed4199b362 164 print_error(err, "Setting service data failed");
mbed_official 3:f0ed4199b362 165 return;
mbed_official 3:f0ed4199b362 166 }
mbed_official 3:f0ed4199b362 167
mbed_official 3:f0ed4199b362 168 // It is not connectable as we are just boardcasting
mbed_official 3:f0ed4199b362 169 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED);
mbed_official 3:f0ed4199b362 170
mbed_official 3:f0ed4199b362 171 // Send out the advertising payload every 1000ms
mbed_official 3:f0ed4199b362 172 ble.gap().setAdvertisingInterval(1000);
mbed_official 3:f0ed4199b362 173
mbed_official 3:f0ed4199b362 174 err = ble.gap().startAdvertising();
mbed_official 3:f0ed4199b362 175 if (err != BLE_ERROR_NONE) {
mbed_official 47:70f571463f31 176 print_error(err, "Start advertising failed");
mbed_official 3:f0ed4199b362 177 return;
mbed_official 3:f0ed4199b362 178 }
mbed_official 47:70f571463f31 179
mbed_official 47:70f571463f31 180 printMacAddress();
mbed_official 3:f0ed4199b362 181 }
mbed_official 3:f0ed4199b362 182
mbed_official 3:f0ed4199b362 183 void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
mbed_official 3:f0ed4199b362 184 BLE &ble = BLE::Instance();
mbed_official 14:332bb3fa072b 185 eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
mbed_official 3:f0ed4199b362 186 }
mbed_official 3:f0ed4199b362 187
mbed_official 3:f0ed4199b362 188 int main()
mbed_official 3:f0ed4199b362 189 {
mbed_official 3:f0ed4199b362 190 cnt = 0;
mbed_official 3:f0ed4199b362 191
mbed_official 3:f0ed4199b362 192 BLE &ble = BLE::Instance();
mbed_official 3:f0ed4199b362 193 ble.onEventsToProcess(scheduleBleEventsProcessing);
mbed_official 3:f0ed4199b362 194 ble_error_t err = ble.init(bleInitComplete);
mbed_official 3:f0ed4199b362 195 if (err != BLE_ERROR_NONE) {
mbed_official 3:f0ed4199b362 196 print_error(err, "BLE initialisation failed");
mbed_official 3:f0ed4199b362 197 return 0;
mbed_official 3:f0ed4199b362 198 }
mbed_official 3:f0ed4199b362 199
mbed_official 3:f0ed4199b362 200 // Blink LED every 500 ms to indicate system aliveness
mbed_official 14:332bb3fa072b 201 eventQueue.call_every(500, blinkCallback);
mbed_official 3:f0ed4199b362 202
mbed_official 3:f0ed4199b362 203 // Register function to be called when button is released
mbed_official 3:f0ed4199b362 204 button.rise(buttonPressedCallback);
mbed_official 3:f0ed4199b362 205
mbed_official 14:332bb3fa072b 206 eventQueue.dispatch_forever();
mbed_official 3:f0ed4199b362 207
mbed_official 3:f0ed4199b362 208 return 0;
mbed_official 3:f0ed4199b362 209 }