Mistake on this page?
Report an issue in GitHub or email us

BLE

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:

  1. Interfaces under ble/ to express BLE constructs, such as GAP, GATT, services and characteristics.

  2. 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:

  1. Basic BLE operations, such as initializing the controller.

  2. Accessor to Bluetooth Modules that manage GAP, GATT or the security.

Usage

  1. Set up advertising and connection modes.
  2. Assign UUIDs to the service and its characteristic.
  3. Create an input characteristic.
  4. Construct a service class and add it to the BLE stack.
  5. 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...
Gapgap ()
 Accessor to Gap. More...
const Gapgap () const
 A const alternative to gap(). More...
GattServergattServer ()
 Accessor to GattServer. More...
const GattServergattServer () const
 A const alternative to gattServer(). More...
GattClientgattClient ()
 Accessors to GattClient. More...
const GattClientgattClient () const
 A const alternative to gattClient(). More...
SecurityManagersecurityManager ()
 Accessors to SecurityManager. More...
const SecurityManagersecurityManager () 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 GapAdvertisingParamsgetAdvertisingParams (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 GapAdvertisingDatagetAdvertisingData (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 BLEInstance (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;
}


Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.