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

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:

  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 () 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=nullptr)
 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 () const
 Indicate if the BLE instance has been initialized. More...
ble_error_t shutdown ()
 Shut down the underlying stack, and reset state of this BLE instance. More...
const char * getVersion ()
 This call allows the application to get the BLE stack version information. More...
ble::Gapgap ()
 Accessor to Gap. More...
const ble::Gapgap () const
 A const alternative to gap(). More...
ble::GattServergattServer ()
 Accessor to GattServer. More...
const ble::GattServergattServer () const
 A const alternative to gattServer(). More...
ble::GattClientgattClient ()
 Accessors to GattClient. More...
const ble::GattClientgattClient () const
 A const alternative to gattClient(). More...
ble::SecurityManagersecurityManager ()
 Accessors to SecurityManager. More...
const ble::SecurityManagersecurityManager () const
 A const alternative to securityManager(). More...
void signalEventsToProcess ()
 This function allows the BLE stack to signal that there is work to do and event processing should be done (BLE::processEvent()). More...
Static Public Member Functions
static BLEInstance ()
 Get a reference to the BLE singleton. More...
static BLEInstance (InstanceID_t id)
 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 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.