Migrating to Peer Manager

The tutorial has been updated for SDK v11, which contains the production-ready release of Peer Manager. The original tutorial can be found on this page, below the updated tutorial.

#Migrating to Peer Manager (SDK v11)# This version of the Peer Manager requires the S13x SoftDevice v2.0.0. A migration document for this SoftDevice can be found in the SDK at

[sdk]/components/softdevice/s132/doc/s13x_nrf5x_2.0.0_migration_document.pdf

##Introduction##

As of SDK v10, a new module has been introduced which is able to handle bonds to both central and peripheral devices simultaneously. The following tutorial is intended to serve as a guide for migrating projects from Device Manager to Peer Manager. For more complete information, including an architectural overview and more comprehensive examples of use, please see the Peer Manager section at the Nordic Infocenter.

The guide assumes that Keil µVision is used for development. The guide will use the HRS application as an example, which can be found in the SDK at [sdk]/examples/ble_peripheral/ble_app_hrs.

##Add required files and includes##

Peer Manager is divided into a number of modules, which must be included for the application to use it. Right click on the nRF_BLE group in the project window. Click Add existing files to group 'nRF_BLE' and add:

  • [sdk]/components/ble/peer_manager/ (all source files)
  • [sdk]/components/ble/common/ble_conn_state.c

Then right click on the nRF_Libraries group in the project window. Click Add existing files to group 'nRF_Libraries' and add:

  • [sdk]/components/libraries/fds/fds.c
  • [sdk]/components/libraries/fstorage/fstorage.c
  • [sdk]/components/libraries/util/sdk_mapped_flags.c

Now go to Project -> Options for target ... -> C/C++. From there, add the following directories to the Include Paths:

  • [sdk]/components/ble/peer_manager/
  • [sdk]/components/libraries/fds
  • [sdk]/components/libraries/fstorage
  • [sdk]/components/libraries/experimental_section_vars

To set up the correct headers, we will first remove those required by Device Manager:

#include "pstorage.h"
#include "device_manager.h"

Then, include the headers required by Peer Manager:

#include "fstorage.h"
#include "fds.h"
#include "peer_manager.h"
#include "ble_conn_state.h"

Initialization

Fstorage

First, we will set up the underlying flash storage module. Device Manager relied on pstorage, while Peer Manager uses the newer fstorage. In sys_evt_dispatch(), remove the call to pstorage_sys_event_handler() and add a call to fs_sys_event_handler() at the same location:

// Forward Softdevice events to the fstorage module
fs_sys_event_handler(sys_evt);

Peer Manager

First, ensure that BLE events are passed to the Peer Manager module. In ble_evt_dispatch, remove the call to dm_ble_evt_handler() and add a call to ble_conn_state_on_ble_evt() and pm_on_ble_evt() at the same location:

// Forward BLE events to the Connection State module.
// This must be called before any event handler that uses this module.
ble_conn_state_on_ble_evt(p_ble_evt);

// Forward BLE events to the Peer Manager
pm_on_ble_evt(p_ble_evt);

The Peer Manager modules are initialized the first time an event handler is registered in each module, which is done by pm_init(). There is no need to access the Peer Manager submodules directly.

Locate the function device_manager_evt_handler(), and replace it with

static void pm_evt_handler(pm_evt_t const * p_evt)
{
    switch(p_evt->evt_id)
    {
        case PM_EVT_BONDED_PEER_CONNECTED:
        case PM_EVT_CONN_SEC_START:
        case PM_EVT_CONN_SEC_SUCCEEDED:
        case PM_EVT_CONN_SEC_FAILED:
        case PM_EVT_CONN_SEC_CONFIG_REQ:
        case PM_EVT_STORAGE_FULL:
        case PM_EVT_ERROR_UNEXPECTED:
        case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED:
        case PM_EVT_PEER_DATA_UPDATE_FAILED:
        case PM_EVT_PEER_DELETE_SUCCEEDED:
        case PM_EVT_PEER_DELETE_FAILED:
        case PM_EVT_PEERS_DELETE_SUCCEEDED:
        case PM_EVT_PEERS_DELETE_FAILED:
        case PM_EVT_LOCAL_DB_CACHE_APPLIED:
        case PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED:
        case PM_EVT_SERVICE_CHANGED_IND_SENT:
        case PM_EVT_SERVICE_CHANGED_IND_CONFIRMED:
        default:
            break;
    }
}

This is a very minimal example, intended to show the different events that can be acted on. How to handle these events will vary between applications, but an example is shown at the Nordic Infocenter.

Replace device_manager_init() with the following function, and remove the m_app_handle variable:

static void peer_manager_init(bool erase_bonds)
{
    ble_gap_sec_params_t sec_param;
    ret_code_t err_code;

    err_code = pm_init();
    APP_ERROR_CHECK(err_code);

    if (erase_bonds)
    {
        err_code = pm_peers_delete();
        APP_ERROR_CHECK(err_code);
    }

    memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));

    // Security parameters to be used for all security procedures.
    sec_param.bond              = SEC_PARAM_BOND;
    sec_param.mitm              = SEC_PARAM_MITM;
    sec_param.lesc              = SEC_PARAM_LESC;
    sec_param.keypress          = SEC_PARAM_KEYPRESS;
    sec_param.io_caps           = SEC_PARAM_IO_CAPABILITIES;
    sec_param.oob               = SEC_PARAM_OOB;
    sec_param.min_key_size      = SEC_PARAM_MIN_KEY_SIZE;
    sec_param.max_key_size      = SEC_PARAM_MAX_KEY_SIZE;
    sec_param.kdist_own.enc     = 1;
    sec_param.kdist_own.id      = 1;
    sec_param.kdist_peer.enc    = 1;
    sec_param.kdist_peer.id     = 1;

    err_code = pm_sec_params_set(&sec_param);
    APP_ERROR_CHECK(err_code);

    err_code = pm_register(pm_evt_handler);
    APP_ERROR_CHECK(err_code);
}

The ble_gap_sec_params_t parameter passed to pm_sec_params_set() is the same as previously passed to pm_register(), and the same settings can be used. Add a line calling peer_manager_init() in the main() function, before you start scanning or advertising.

Further Reading


#Migrating to experimental Peer Manager (SDK v10)#

##Introduction##

As of SDK v10, a new module has been introduced which is able to handle bonds to both central and peripheral devices simultaneously. The following tutorial is intended to serve as a guide for migrating projects from Device Manager to Peer Manager. For more complete information, including an architectural overview and more comprehensive examples of use, please see the Peer Manager section at the Nordic Infocenter.

The guide assumes that Keil µVision is used for development. The guide will use the HRS application from SDK 10 as an example, which can be found in the SDK at sdk/Nordic/nrf51/examples/ble_peripheral/ble_app_hrs.

##Add required files and includes##

Peer Manager is divided into a number of modules, which must be included for the application to use it. Right click on the nRF_BLE group in the project window. Click Add existing files to group 'nRF_BLE' and add:

  • sdk/Nordic/nrf51/components/ble/peer_manager/ (all source files)
  • sdk/Nordic/nrf51/components/ble/common/ble_conn_state.c

Then right click on the nRF_Libraries group in the project window. Click Add existing files to group 'nRF_Libraries' and add:

  • sdk/Nordic/nrf51/components/libraries/fds/fds.c
  • sdk/Nordic/nrf51/components/libraries/fstorage/fstorage.c
  • sdk/Nordic/nrf51/components/libraries/util/sdk_mapped_flags.c

Now go to Project -> Options for target ... -> C/C++. From there, add the following directories to the Include Paths:

  • sdk/Nordic/nrf51/components/ble/peer_manager/
  • sdk/Nordic/nrf51/components/libraries/fds
  • sdk/Nordic/nrf51/components/libraries/fstorage
  • sdk/Nordic/nrf51/components/libraries/experimental_section_vars

To set up the correct headers, we will first remove those required by Device Manager:

#include "pstorage.h"
#include "device_manager.h"

Then, include the headers required by Peer Manager:

#include "fstorage.h"
#include "fds.h"
#include "peer_manager.h"
#include "ble_conn_state.h"

Initialization

Fstorage

First, we will set up the underlying flash storage module. Device Manager relied on pstorage, while Peer Manager uses the newer fstorage. In sys_evt_dispatch(), remove the call to pstorage_sys_event_handler() and add a call to fs_sys_event_handler() at the same location:

// Forward Softdevice events to the fstorage module
fs_sys_event_handler(sys_evt);

Peer Manager

First, ensure that BLE events are passed to the Peer Manager module. In ble_evt_dispatch, remove the call to dm_ble_evt_handler() and add a call to ble_conn_state_on_ble_evt() and pm_ble_evt_handler() at the same location:

// Forward BLE events to the Connection State module.
// This must be called before any event handler that uses this module.
ble_conn_state_on_ble_evt(p_ble_evt);

// Forward BLE events to the Peer Manager
pm_ble_evt_handler(p_ble_evt);

The Peer Manager modules are initialized the first time an event handler is registered in each module, which is done by pm_init(). Therefore, except to register separate event handlers in addition to those registered by Peer Manager, there is no need to access the Peer Manager submodules directly.

Locate the function device_manager_evt_handler(), and replace it with

static void pm_evt_handler(pm_evt_t const * p_evt)
{
    switch(p_evt->evt_id)
    {
        case PM_EVT_BONDED_PEER_CONNECTED:
        case PM_EVT_LINK_SECURED:
        case PM_EVT_LINK_SECURE_FAILED:
        case PM_EVT_STORAGE_FULL:
        case PM_EVT_ERROR_UNEXPECTED:
        case PM_EVT_PEER_DATA_UPDATED:
        case PM_EVT_PEER_DATA_UPDATE_FAILED:
        case PM_EVT_ERROR_LOCAL_DB_CACHE_APPLY:
        case PM_EVT_LOCAL_DB_CACHE_APPLIED:
        case PM_EVT_SERVICE_CHANGED_INDICATION_SENT:
        default:
            break;
    }
}

This is a very minimal example, intended to show the different events that can be acted on. How to handle these events will vary between applications, but an example is shown at the Nordic Infocenter.

Replace device_manager_init() with the following function, and remove the m_app_handle variable:

static void peer_manager_init(bool erase_bonds)
{
    ble_gap_sec_params_t sec_param;
    ret_code_t err_code;

    err_code = pm_init();
    APP_ERROR_CHECK(err_code);

    if (erase_bonds)
    {
        pm_peer_delete_all();
    }

    memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));

    // Security parameters to be used for all security procedures.
    sec_param.bond              = SEC_PARAM_BOND;
    sec_param.mitm              = SEC_PARAM_MITM;
    sec_param.io_caps           = SEC_PARAM_IO_CAPABILITIES;
    sec_param.oob               = SEC_PARAM_OOB;
    sec_param.min_key_size      = SEC_PARAM_MIN_KEY_SIZE;
    sec_param.max_key_size      = SEC_PARAM_MAX_KEY_SIZE;
    sec_param.kdist_periph.enc  = 1;
    sec_param.kdist_periph.id   = 1;
    sec_param.kdist_central.enc = 1;
    sec_param.kdist_central.id  = 1;

    err_code = pm_sec_params_set(&sec_param);
    APP_ERROR_CHECK(err_code);

    err_code = pm_register(pm_evt_handler);
    APP_ERROR_CHECK(err_code);
}

The ble_gap_sec_params_t parameter passed to pm_sec_params_set() is the same as previously passed to pm_register(), and the same settings can be used. Add a line calling peer_manager_init() in the main() function, before you start scanning or advertising.

Further Reading