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

  • Just to add one comment on #sajin comment... I re-burnt the SD132 on nRF52 DK and it started working good. I am not sure why it was not working before.

  • Hello, I am using SDK 11.0 and trying to migrate from DM to PM. While following the tutorial; I managed to compile successfully but when I try to connect my mobile phone with nRF52 DK, I get the following error EVT "PM_EVT_PEER_DATA_UPDATE_FAILED".

    Here is the sequence of my main function.

    ret_code_t err_code;
    bool erase_bonds;
    
     err_code = NRF_LOG_INIT();
    APP_ERROR_CHECK(err_code);
    
    NRF_LOG_PRINTF("D App\r\n");
    
    // Initialize.
    //timers_init();
     APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, NULL);
      buttons_leds_init(&erase_bonds);
    	 if (erase_bonds)
    {
        NRF_LOG_PRINTF("Bonds erased!\r\n");
    }
    
    ble_stack_init();
    //device_manager_init(erase_bonds);
    peer_manager_init(erase_bonds);
    //db_discovery_init();
    	
    gap_params_init();
    conn_params_init();
    services_init();
    advertising_init();
    
    // Start execution.
    application_timers_start();
    err_code = ble_advertising_start(BLE_ADV_MODE_FAST);
    APP_ERROR_CHECK(err_code);
    

    Please help

  • I'm using sdk12.2 which works perfectly ,but the bonding only takes place at first time when the softdevice is burned. When i forgot the device and bond it again it will not bond and get rejection error from nrf52

  • Does anyone could perform DFU using peer manager?

  • This guide doesn't mention using the FS_REGISTER_CFG as part of the fstorage initialisation. Is this an oversight, or because this initialisation is not required?

    The fstorage docs don't go into enough detail to work out what to do with FS_REGISTER_CFG -- particularly what to set the num_pages attribute of the fst_config_t struct. They also don't state whether the FS_REGISTER_CFG call is required at all.