BLE
Note: Some functions, variables or types have been deprecated. Please see the class reference linked below for details.
Bluetooth low energy (BLE) is a low power wireless technology standard for building personal area networks. Typical applications of BLE are health care, fitness trackers, beacons, smart home, security, entertainment, proximity sensors, industrial and automotive.
Arm Mbed BLE, also called BLE_API
, is the Bluetooth Low Energy software solution for Mbed. Many Mbed targets and components support Mbed BLE. Developers can use it to create new BLE enabled applications.
Mbed’s BLE_API
interfaces with the BLE controller on the platform. It hides the BLE stack’s complexity behind C++ abstractions and is compatible with all BLE-enabled Mbed platforms. The Mbed OS BLE_API
automatically configuring the clocks, timers and other hardware peripherals to work at their lowest power consumption.
BLE_API
, bridges and stacks
You can build a BLE application using Mbed OS, BLE_API
and a controller-specific Bluetooth stack together with some bridge software to adapt it to BLE_API
:
BLE_API
as described above.- The bridge software is specific to each vendor’s platform. It provides the instantiations for the interfaces
BLE_API
offers and helps drive the underlying controller and Bluetooth stack. - The Bluetooth stack implements the Bluetooth protocol and is specific to the controller, so a vendor using different controllers may provide different stacks.
Inside BLE_API
BLE_API
offers building blocks to help construct applications. These fall into two broad categories:
-
Interfaces under
ble/
to express BLE constructs, such as GAP, GATT, services and characteristics. -
Classes under
ble/services
to offer reference implementations for many of the commonly used GATT profiles. The code under 'services/' isn't essential, but it’s a useful starting point for prototyping. We continue to implement the standard GATT profiles.
The BLEDevice class and header
The entry point of Mbed's BLE_API
is the BLE class accessible using the header ble/BLE.h
. This class allows you to obtain a BLE object that includes the basic attributes of a spec-compatible BLE device and can work with any BLE radio:
#include "ble/BLE.h"
BLE& mydevicename = BLE::Instance();
The class's member functions can be divided by purpose:
-
Basic BLE operations, such as initializing the controller.
-
Accessor to Bluetooth Modules that manage GAP, GATT or the security.
Usage
- Set up advertising and connection modes.
- Assign UUIDs to the service and its characteristic.
- Create an input characteristic.
- Construct a service class and add it to the BLE stack.
- Push notifications when the characteristic's value changes.
BLE class reference
Data Structures | |
struct | InitializationCompleteCallbackContext |
Initialization complete event. More... | |
struct | OnEventsToProcessCallbackContext |
Events to process event. More... |
Public Types | |
typedef unsigned | InstanceID_t |
Opaque type used to store the ID of a BLE instance. More... | |
typedef FunctionPointerWithContext< OnEventsToProcessCallbackContext * > | OnEventsToProcessCallback_t |
Events to process event handler. More... | |
typedef void(* | InitializationCompleteCallback_t) (InitializationCompleteCallbackContext *context) |
Initialization complete event handler. More... |
Public Member Functions | |
InstanceID_t | getInstanceID (void) const |
Fetch the ID of a BLE instance. More... | |
void | onEventsToProcess (const OnEventsToProcessCallback_t &on_event_cb) |
Register a callback called when the BLE stack has pending work. More... | |
void | processEvents () |
Process ALL pending events living in the BLE stack and return once all events have been consumed. More... | |
ble_error_t | init (InitializationCompleteCallback_t completion_cb=NULL) |
Initialize the BLE controller/stack. More... | |
template<typename T > | |
ble_error_t | init (T *object, void(T::*completion_cb)(InitializationCompleteCallbackContext *context)) |
Initialize the BLE controller/stack. More... | |
bool | hasInitialized (void) const |
Indicate if the BLE instance has been initialized. More... | |
ble_error_t | shutdown (void) |
Shut down the underlying stack, and reset state of this BLE instance. More... | |
const char * | getVersion (void) |
This call allows the application to get the BLE stack version information. More... | |
Gap & | gap () |
Accessor to Gap. More... | |
const Gap & | gap () const |
A const alternative to gap(). More... | |
GattServer & | gattServer () |
Accessor to GattServer. More... | |
const GattServer & | gattServer () const |
A const alternative to gattServer(). More... | |
GattClient & | gattClient () |
Accessors to GattClient. More... | |
const GattClient & | gattClient () const |
A const alternative to gattClient(). More... | |
SecurityManager & | securityManager () |
Accessors to SecurityManager. More... | |
const SecurityManager & | securityManager () const |
A const alternative to securityManager(). More... | |
BLE (InstanceID_t instanceID=DEFAULT_INSTANCE) | |
Constructor for a handle to a BLE instance (the BLE stack). More... | |
void | waitForEvent (void) |
Yield control to the BLE stack or to other tasks waiting for events. More... | |
ble_error_t | setAddress (BLEProtocol::AddressType_t type, const BLEProtocol::AddressBytes_t address) |
Set the BTLE MAC address and type. More... | |
ble_error_t | getAddress (BLEProtocol::AddressType_t *typeP, BLEProtocol::AddressBytes_t address) |
Fetch the Bluetooth Low Energy MAC address and type. More... | |
void | setAdvertisingType (GapAdvertisingParams::AdvertisingType advType) |
Set the GAP advertising mode to use for this device. More... | |
void | setAdvertisingInterval (uint16_t interval) |
Set the advertising interval. More... | |
uint16_t | getMinAdvertisingInterval (void) const |
Get the minimum advertising interval in milliseconds, which can be used for connectable advertising types. More... | |
uint16_t | getMinNonConnectableAdvertisingInterval (void) const |
Get the minimum advertising interval in milliseconds, which can be used for nonconnectable advertising type. More... | |
uint16_t | getMaxAdvertisingInterval (void) const |
Get the maximum advertising interval in milliseconds. More... | |
void | setAdvertisingTimeout (uint16_t timeout) |
Set the advertising duration. More... | |
void | setAdvertisingParams (const GapAdvertisingParams &advParams) |
Set up a particular, user-constructed set of advertisement parameters for the underlying stack. More... | |
const GapAdvertisingParams & | getAdvertisingParams (void) const |
Get the current advertising parameters. More... | |
ble_error_t | accumulateAdvertisingPayload (uint8_t flags) |
Accumulate an AD structure in the advertising payload. More... | |
ble_error_t | accumulateAdvertisingPayload (GapAdvertisingData::Appearance app) |
Accumulate an AD structure in the advertising payload. More... | |
ble_error_t | accumulateAdvertisingPayloadTxPower (int8_t power) |
Accumulate an AD structure in the advertising payload. More... | |
ble_error_t | accumulateAdvertisingPayload (GapAdvertisingData::DataType type, const uint8_t *data, uint8_t len) |
Accumulate a variable length byte-stream as an AD structure in the advertising payload. More... | |
ble_error_t | setAdvertisingData (const GapAdvertisingData &advData) |
Set up a particular, user-constructed advertisement payload for the underlying stack. More... | |
const GapAdvertisingData & | getAdvertisingData (void) const |
Get a reference to the current advertising payload. More... | |
void | clearAdvertisingPayload (void) |
Reset any advertising payload prepared from prior calls to accumulateAdvertisingPayload(). More... | |
ble_error_t | setAdvertisingPayload (void) |
Dynamically reset the accumulated advertising payload and scanResponse. More... | |
ble_error_t | accumulateScanResponse (GapAdvertisingData::DataType type, const uint8_t *data, uint8_t len) |
Accumulate a variable length byte-stream as an AD structure in the scanResponse payload. More... | |
void | clearScanResponse (void) |
Reset any scan response prepared from prior calls to accumulateScanResponse(). More... | |
ble_error_t | startAdvertising (void) |
Start advertising. More... | |
ble_error_t | stopAdvertising (void) |
Stop advertising. More... | |
ble_error_t | setScanParams (uint16_t interval=GapScanningParams::SCAN_INTERVAL_MAX, uint16_t window=GapScanningParams::SCAN_WINDOW_MAX, uint16_t timeout=0, bool activeScanning=false) |
Set up parameters for GAP scanning (observer mode). More... | |
ble_error_t | setScanInterval (uint16_t interval) |
Set up the scanInterval parameter for GAP scanning (observer mode). More... | |
ble_error_t | setScanWindow (uint16_t window) |
Set up the scanWindow parameter for GAP scanning (observer mode). More... | |
ble_error_t | setScanTimeout (uint16_t timeout) |
Set up parameters for GAP scanning (observer mode). More... | |
void | setActiveScan (bool activeScanning) |
Set up parameters for GAP scanning (observer mode). More... | |
ble_error_t | startScan (void(*callback)(const Gap::AdvertisementCallbackParams_t *params)) |
Start scanning (Observer Procedure) based on the parameters currently in effect. More... | |
template<typename T > | |
ble_error_t | startScan (T *object, void(T::*memberCallback)(const Gap::AdvertisementCallbackParams_t *params)) |
Start the scanning procedure. More... | |
ble_error_t | stopScan (void) |
Stop scanning. More... | |
ble_error_t | connect (const BLEProtocol::AddressBytes_t peerAddr, BLEProtocol::AddressType_t peerAddrType=BLEProtocol::AddressType::RANDOM_STATIC, const Gap::ConnectionParams_t *connectionParams=NULL, const GapScanningParams *scanParams=NULL) |
Create a connection (GAP Link Establishment). More... | |
ble_error_t | disconnect (Gap::Handle_t connectionHandle, Gap::DisconnectionReason_t reason) |
This call initiates the disconnection procedure, and its completion is communicated to the application with an invocation of the onDisconnection callback. More... | |
ble_error_t | disconnect (Gap::DisconnectionReason_t reason) |
This call initiates the disconnection procedure, and its completion is communicated to the application with an invocation of the onDisconnection callback. More... | |
Gap::GapState_t | getGapState (void) const |
Returns the current Gap state of the device using a bitmask that describes whether the device is advertising or connected. More... | |
ble_error_t | getPreferredConnectionParams (Gap::ConnectionParams_t *params) |
Get the GAP peripheral's preferred connection parameters. More... | |
ble_error_t | setPreferredConnectionParams (const Gap::ConnectionParams_t *params) |
Set the GAP peripheral's preferred connection parameters. More... | |
ble_error_t | updateConnectionParams (Gap::Handle_t handle, const Gap::ConnectionParams_t *params) |
Update connection parameters while in the peripheral role. More... | |
ble_error_t | setDeviceName (const uint8_t *deviceName) |
Set the device name characteristic in the Gap service. More... | |
ble_error_t | getDeviceName (uint8_t *deviceName, unsigned *lengthP) |
Get the value of the device name characteristic in the Gap service. More... | |
ble_error_t | setAppearance (GapAdvertisingData::Appearance appearance) |
Set the appearance characteristic in the Gap service. More... | |
ble_error_t | getAppearance (GapAdvertisingData::Appearance *appearanceP) |
Get the appearance characteristic in the Gap service. More... | |
ble_error_t | setTxPower (int8_t txPower) |
Set the radio's transmit power. More... | |
void | getPermittedTxPowerValues (const int8_t **valueArrayPP, size_t *countP) |
Query the underlying stack for permitted arguments for setTxPower(). More... | |
ble_error_t | addService (GattService &service) |
Add a service declaration to the local server ATT table. More... | |
ble_error_t | readCharacteristicValue (GattAttribute::Handle_t attributeHandle, uint8_t *buffer, uint16_t *lengthP) |
Read the value of a characteristic from the local GattServer. More... | |
ble_error_t | readCharacteristicValue (Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t *buffer, uint16_t *lengthP) |
Read the value of a characteristic from the local GattServer. More... | |
ble_error_t | updateCharacteristicValue (GattAttribute::Handle_t attributeHandle, const uint8_t *value, uint16_t size, bool localOnly=false) |
Update the value of a characteristic on the local GattServer. More... | |
ble_error_t | updateCharacteristicValue (Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, const uint8_t *value, uint16_t size, bool localOnly=false) |
Update the value of a characteristic on the local GattServer. More... | |
ble_error_t | initializeSecurity (bool enableBonding=true, bool requireMITM=true, SecurityManager::SecurityIOCapabilities_t iocaps=SecurityManager::IO_CAPS_NONE, const SecurityManager::Passkey_t passkey=NULL) |
Enable the BLE stack's Security Manager. More... | |
ble_error_t | getLinkSecurity (Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP) |
Get the security status of a connection. More... | |
ble_error_t | purgeAllBondingState (void) |
Delete all peer device context and all related bonding information from the database within the security manager. More... | |
void | onTimeout (Gap::TimeoutEventCallback_t timeoutCallback) |
Set up a callback for timeout events. More... | |
void | onConnection (Gap::ConnectionEventCallback_t connectionCallback) |
Set up a callback for connection events. More... | |
void | onDisconnection (Gap::DisconnectionEventCallback_t disconnectionCallback) |
Append to a chain of callbacks to be invoked upon GAP disconnection. More... | |
template<typename T > | |
void | onDisconnection (T *tptr, void(T::*mptr)(const Gap::DisconnectionCallbackParams_t *)) |
The same as onDisconnection() but allows an object reference and member function to be added to the chain of callbacks. More... | |
void | onRadioNotification (void(*callback)(bool)) |
Radio Notification is a feature that enables ACTIVE and INACTIVE (nACTIVE) signals from the stack. More... | |
void | onDataSent (void(*callback)(unsigned count)) |
Add a callback for the GATT event DATA_SENT (which is triggered when updates are sent out by GATT in the form of notifications). More... | |
template<typename T > | |
void | onDataSent (T *objPtr, void(T::*memberPtr)(unsigned count)) |
The same as onDataSent() but allows an object reference and member function to be added to the chain of callbacks. More... | |
void | onDataWritten (void(*callback)(const GattWriteCallbackParams *eventDataP)) |
Set up a callback for when an attribute has its value updated by or at the connected peer. More... | |
template<typename T > | |
void | onDataWritten (T *objPtr, void(T::*memberPtr)(const GattWriteCallbackParams *context)) |
The same as onDataWritten() but allows an object reference and member function to be added to the chain of callbacks. More... | |
ble_error_t | onDataRead (void(*callback)(const GattReadCallbackParams *eventDataP)) |
Set up a callback to be invoked on the peripheral when an attribute is being read by a remote client. More... | |
template<typename T > | |
ble_error_t | onDataRead (T *objPtr, void(T::*memberPtr)(const GattReadCallbackParams *context)) |
The same as onDataRead() but allows an object reference and member function to be added to the chain of callbacks. More... | |
void | onUpdatesEnabled (GattServer::EventCallback_t callback) |
Set up a callback for when notifications or indications are enabled for a characteristic on the local GattServer. More... | |
void | onUpdatesDisabled (GattServer::EventCallback_t callback) |
Set up a callback for when notifications or indications are disabled for a characteristic on the local GattServer. More... | |
void | onConfirmationReceived (GattServer::EventCallback_t callback) |
Set up a callback for when the GATT server receives a response for an indication event sent previously. More... | |
void | onSecuritySetupInitiated (SecurityManager::SecuritySetupInitiatedCallback_t callback) |
Set up a callback for when the security setup procedure (key generation and exchange) for a link has started. More... | |
void | onSecuritySetupCompleted (SecurityManager::SecuritySetupCompletedCallback_t callback) |
Set up a callback for when the security setup procedure (key generation and exchange) for a link has completed. More... | |
void | onLinkSecured (SecurityManager::LinkSecuredCallback_t callback) |
Set up a callback for when a link with the peer is secured. More... | |
void | onSecurityContextStored (SecurityManager::HandleSpecificEvent_t callback) |
Set up a callback for successful bonding, meaning that link-specific security context is stored persistently for a peer device. More... | |
void | onPasskeyDisplay (SecurityManager::PasskeyDisplayCallback_t callback) |
Set up a callback for when the passkey needs to be displayed on a peripheral with DISPLAY capability. More... |
Static Public Member Functions | |
static BLE & | Instance (InstanceID_t id=DEFAULT_INSTANCE) |
Get a reference to the BLE singleton corresponding to a given interface. More... | |
static const char * | errorToString (ble_error_t error) |
Translate error code into a printable string. More... |
Static Public Attributes | |
static const InstanceID_t | DEFAULT_INSTANCE = 0 |
The value of the BLE::InstanceID_t for the default BLE instance. More... | |
static const InstanceID_t | NUM_INSTANCES = 1 |
The number of permitted BLE instances for the application. More... |
Example: BLE beacon
Here is an example demonstrating how you can create a BLE beacon.
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 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 <events/mbed_events.h>
#include <mbed.h>
#include "ble/BLE.h"
#include "pretty_printer.h"
static events::EventQueue event_queue(/* event count */ 16 * EVENTS_EVENT_SIZE);
/** @deprecated This demo is deprecated and no replacement is currently available.
*/
MBED_DEPRECATED_SINCE(
"mbed-os-5.11",
"This demo is deprecated and no replacement is currently available."
)
class BeaconDemo : ble::Gap::EventHandler {
public:
BeaconDemo(BLE &ble, events::EventQueue &event_queue) :
_ble(ble),
_event_queue(event_queue),
_adv_data_builder(_adv_buffer) { }
void start() {
_ble.gap().setEventHandler(this);
_ble.init(this, &BeaconDemo::on_init_complete);
_event_queue.dispatch_forever();
}
private:
/**
* iBeacon payload builder.
*
* This data structure contains the payload of an iBeacon. The payload is
* built at construction time and application code can set up an iBeacon by
* injecting the raw field into the GAP advertising payload as a
* GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA.
*/
union Payload {
/**
* Raw data of the payload.
*/
uint8_t raw[25];
struct {
/**
* Beacon manufacturer identifier.
*/
uint16_t companyID;
/**
* Packet ID; Equal to 2 for an iBeacon.
*/
uint8_t ID;
/**
* Length of the remaining data presents in the payload.
*/
uint8_t len;
/**
* Beacon UUID.
*/
uint8_t proximityUUID[16];
/**
* Beacon Major group ID.
*/
uint16_t majorNumber;
/**
* Beacon minor ID.
*/
uint16_t minorNumber;
/**
* Tx power received at 1 meter; in dBm.
*/
uint8_t txPower;
};
/**
* Assemble an iBeacon payload.
*
* @param[in] uuid Beacon network ID. iBeacon operators use this value
* to group their iBeacons into a single network, a single region and
* identify their organization among others.
*
* @param[in] majNum Beacon major group ID. iBeacon exploitants may use
* this field to divide the region into subregions, their network into
* subnetworks.
*
* @param[in] minNum Identifier of the Beacon in its subregion.
*
* @param[in] transmitPower Measured transmit power of the beacon at 1
* meter. Scanners use this parameter to approximate the distance
* to the beacon.
*
* @param[in] companyIDIn ID of the beacon manufacturer.
*/
Payload(
const uint8_t *uuid,
uint16_t majNum,
uint16_t minNum,
uint8_t transmitPower,
uint16_t companyIDIn
) : companyID(companyIDIn),
ID(0x02),
len(0x15),
majorNumber(__REV16(majNum)),
minorNumber(__REV16(minNum)),
txPower(transmitPower)
{
memcpy(proximityUUID, uuid, 16);
}
};
/** Callback triggered when the ble initialization process has finished */
void on_init_complete(BLE::InitializationCompleteCallbackContext *params) {
if (params->error != BLE_ERROR_NONE) {
printf("Ble initialization failed.");
return;
}
print_mac_address();
start_advertising();
}
void start_advertising() {
/* Create advertising parameters and payload */
ble::AdvertisingParameters adv_parameters(
ble::advertising_type_t::CONNECTABLE_UNDIRECTED,
ble::adv_interval_t(ble::millisecond_t(1000))
);
_adv_data_builder.setFlags();
/**
* The Beacon payload has the following composition:
* 128-Bit / 16byte UUID = E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61
* Major/Minor = 0x1122 / 0x3344
* Tx Power = 0xC8 = 200, 2's compliment is 256-200 = (-56dB)
*
* Note: please remember to calibrate your beacons TX Power for more accurate results.
*/
static const uint8_t uuid[] = { 0xE2, 0x0A, 0x39, 0xF4, 0x73, 0xF5, 0x4B, 0xC4,
0xA1, 0x2F, 0x17, 0xD1, 0xAD, 0x07, 0xA9, 0x61 };
uint16_t major_number = 1122;
uint16_t minor_number = 3344;
uint16_t tx_power = 0xC8;
uint16_t comp_id = 0x004C;
Payload ibeacon(uuid, major_number, minor_number, tx_power, comp_id);
_adv_data_builder.setManufacturerSpecificData(ibeacon.raw);
/* Setup advertising */
ble_error_t error = _ble.gap().setAdvertisingParameters(
ble::LEGACY_ADVERTISING_HANDLE,
adv_parameters
);
if (error) {
print_error(error, "_ble.gap().setAdvertisingParameters() failed");
return;
}
error = _ble.gap().setAdvertisingPayload(
ble::LEGACY_ADVERTISING_HANDLE,
_adv_data_builder.getAdvertisingData()
);
if (error) {
print_error(error, "_ble.gap().setAdvertisingPayload() failed");
return;
}
/* Start advertising */
error = _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
if (error) {
print_error(error, "_ble.gap().startAdvertising() failed");
return;
}
}
private:
/* Event handler */
void onDisconnectionComplete(const ble::DisconnectionCompleteEvent&) {
_ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
}
private:
BLE &_ble;
events::EventQueue &_event_queue;
uint8_t _adv_buffer[ble::LEGACY_ADVERTISING_MAX_SIZE];
ble::AdvertisingDataBuilder _adv_data_builder;
};
/** Schedule processing of events from the BLE middleware in the event queue. */
void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context) {
event_queue.call(Callback<void()>(&context->ble, &BLE::processEvents));
}
int main()
{
BLE &ble = BLE::Instance();
ble.onEventsToProcess(schedule_ble_events);
BeaconDemo demo(ble, event_queue);
demo.start();
return 0;
}
Example: BLE heart rate monitor
Here is an example demonstrating how to build a heart rate sensor that can be connected and monitored by a BLE client such as your phone.
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 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 <events/mbed_events.h>
#include <mbed.h>
#include "ble/BLE.h"
#include "ble/gap/Gap.h"
#include "ble/services/HeartRateService.h"
#include "pretty_printer.h"
const static char DEVICE_NAME[] = "Heartrate";
static events::EventQueue event_queue(/* event count */ 16 * EVENTS_EVENT_SIZE);
class HeartrateDemo : ble::Gap::EventHandler {
public:
HeartrateDemo(BLE &ble, events::EventQueue &event_queue) :
_ble(ble),
_event_queue(event_queue),
_led1(LED1, 1),
_connected(false),
_hr_uuid(GattService::UUID_HEART_RATE_SERVICE),
_hr_counter(100),
_hr_service(ble, _hr_counter, HeartRateService::LOCATION_FINGER),
_adv_data_builder(_adv_buffer) { }
void start() {
_ble.gap().setEventHandler(this);
_ble.init(this, &HeartrateDemo::on_init_complete);
_event_queue.call_every(500, this, &HeartrateDemo::blink);
_event_queue.call_every(1000, this, &HeartrateDemo::update_sensor_value);
_event_queue.dispatch_forever();
}
private:
/** Callback triggered when the ble initialization process has finished */
void on_init_complete(BLE::InitializationCompleteCallbackContext *params) {
if (params->error != BLE_ERROR_NONE) {
printf("Ble initialization failed.");
return;
}
print_mac_address();
start_advertising();
}
void start_advertising() {
/* Create advertising parameters and payload */
ble::AdvertisingParameters adv_parameters(
ble::advertising_type_t::CONNECTABLE_UNDIRECTED,
ble::adv_interval_t(ble::millisecond_t(1000))
);
_adv_data_builder.setFlags();
_adv_data_builder.setAppearance(ble::adv_data_appearance_t::GENERIC_HEART_RATE_SENSOR);
_adv_data_builder.setLocalServiceList(mbed::make_Span(&_hr_uuid, 1));
_adv_data_builder.setName(DEVICE_NAME);
/* Setup advertising */
ble_error_t error = _ble.gap().setAdvertisingParameters(
ble::LEGACY_ADVERTISING_HANDLE,
adv_parameters
);
if (error) {
printf("_ble.gap().setAdvertisingParameters() failed\r\n");
return;
}
error = _ble.gap().setAdvertisingPayload(
ble::LEGACY_ADVERTISING_HANDLE,
_adv_data_builder.getAdvertisingData()
);
if (error) {
printf("_ble.gap().setAdvertisingPayload() failed\r\n");
return;
}
/* Start advertising */
error = _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
if (error) {
printf("_ble.gap().startAdvertising() failed\r\n");
return;
}
}
void update_sensor_value() {
if (_connected) {
// Do blocking calls or whatever is necessary for sensor polling.
// In our case, we simply update the HRM measurement.
_hr_counter++;
// 100 <= HRM bps <=175
if (_hr_counter == 175) {
_hr_counter = 100;
}
_hr_service.updateHeartRate(_hr_counter);
}
}
void blink(void) {
_led1 = !_led1;
}
private:
/* Event handler */
void onDisconnectionComplete(const ble::DisconnectionCompleteEvent&) {
_ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
_connected = false;
}
virtual void onConnectionComplete(const ble::ConnectionCompleteEvent &event) {
if (event.getStatus() == BLE_ERROR_NONE) {
_connected = true;
}
}
private:
BLE &_ble;
events::EventQueue &_event_queue;
DigitalOut _led1;
bool _connected;
UUID _hr_uuid;
uint8_t _hr_counter;
HeartRateService _hr_service;
uint8_t _adv_buffer[ble::LEGACY_ADVERTISING_MAX_SIZE];
ble::AdvertisingDataBuilder _adv_data_builder;
};
/** Schedule processing of events from the BLE middleware in the event queue. */
void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context) {
event_queue.call(Callback<void()>(&context->ble, &BLE::processEvents));
}
int main()
{
BLE &ble = BLE::Instance();
ble.onEventsToProcess(schedule_ble_events);
HeartrateDemo demo(ble, event_queue);
demo.start();
return 0;
}
Related content
- Mbed Enabled targets and components that support BLE.
- BLE tutorial.
- Office Hours video about BLE.