Introduction
I would like to introduce simple source code that supporting NUS profile and pairing. Most of you will choose the proprietary profile to make your own application which is not provided by Bluetooth SIG. Since this reason Nordic is providing one example in SDK which it called to Nordic Uart Service. This profile simulates serial communication as SPP in classic Bluetooth. So you can implement your own packets on this profile simply. But unfortunately it does not support pairing method for secured and smooth BLE connection. So In this blog I want to give you simple example for referencing how to implement pairing and Nordic proprietary service for the both Central and Peripheral.
Implementation
Thankfully it already has been described in our tutorial page for how to implement peer manager in peripheral example. So I will explain only for careful point of implementation and differences.
##Peripheral
-
Enable features in SDK config
#define PEER_MANAGER_ENABLED 1
#define FDS_ENABLED 1
#define FSTORAGE_ENABLED 1
-
Remove part of responding pairing information :
If you don't remove this part, your device will not proceed pairing procedure.static void on_ble_evt(ble_evt_t * p_ble_evt) { … case BLE_GAP_EVT_SEC_PARAMS_REQUEST: // Pairing not supported
err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);APP_ERROR_CHECK(err_code);break; // BLE_GAP_EVT_SEC_PARAMS_REQUEST -
Erase bonding information with button press :
You need to consider how to erase bonding information because if you erase device information only on peer device such a mobile phone then can’t connect again due to bonding information mismatch.int main(void) { … peer_manager_init(erase_bonds); if (erase_bonds == true) { printf("Bonds erased!\r\n"); }
##Central
Most of things are same as peripheral except service discovery part. You can use service discovery in peripheral as well but no need to use for this posting
-
Enable features in SDK config
#define NRF_BLE_GATT_ENABLED 1
#define PEER_MANAGER_ENABLED 1
#define FDS_ENABLED 1
#define FSTORAGE_ENABLED 1
-
Include peer manager headers and gatt header for gatt event control :
#include "peer_manager.h"
#include "fds.h"
#include "fstorage.h"
#include "ble_conn_state.h"
#include "nrf_ble_gatt.h" -
Add peer manager related files :
./components/ble/peer_manager/ (all source files)
./components/ble/common/ble_conn_state.c
./components/libraries/fds/fds.c
./components/libraries/fstorage/fstorage.c
./components/libraries/util/sdk_mapped_flags.c
This is new file for gatt event handling
./components/ble/nrf_ble_gatt/nrf_ble_gatt.c
-
Add changes for initiating bonding procedure
static void ble_nus_c_evt_handler(ble_nus_c_t * p_ble_nus_c, const ble_nus_c_evt_t * p_ble_nus_evt) { uint32_t err_code; switch (p_ble_nus_evt->evt_type) { case BLE_NUS_C_EVT_DISCOVERY_COMPLETE: err_code = ble_nus_c_handles_assign(p_ble_nus_c, p_ble_nus_evt->conn_handle, &p_ble_nus_evt->handles); APP_ERROR_CHECK(err_code); // Initiate bonding. err_code = pm_conn_secure(p_ble_nus_evt->conn_handle, false); APP_ERROR_CHECK(err_code);
-
Change the code from advertising to scan start
The Central device has to scan and initiate connection request to the peripheral device. For this procedure Central device need to implement scan_start() fucntion unlike NUS peripheral example.
static void pm_evt_handler(pm_evt_t const * p_evt) { ... case PM_EVT_PEERS_DELETE_SUCCEEDED: { scan_start(); } break;
-
**Add gatt module This is will give you improvement stability of discovery process
/* GATT generic Event handler. */ void gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t * p_evt) { printf("GATT MTU on link %d changed to %d\r\n", p_evt->conn_handle, p_evt->att_mtu_effective); if (m_retry_db_disc) { ret_code_t err_code; printf("Retrying DB discovery.\r\n"); m_retry_db_disc = false; // Discover peer's services. err_code = ble_db_discovery_start(&m_ble_db_discovery, m_pending_db_disc_conn); if (err_code == NRF_ERROR_BUSY) { printf("ble_db_discovery_start() returned busy, will retry later.\r\n"); m_retry_db_disc = true; } else { APP_ERROR_CHECK(err_code); } } } /* GATT Module init. */ void gatt_init(void) { ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler); APP_ERROR_CHECK(err_code); }
-
Initialize modules
int main(void) { ... uart_init(); buttons_leds_init(&erase_bonds); ble_stack_init(); peer_manager_init(erase_bonds); if (erase_bonds == true) { printf("Bonds erased!\r\n"); } gatt_init(); db_discovery_init(); ... }
##Sample code Here is sample source code which I tested for this blog. This sample codes tested in SDK v12.3.0 and nRF51-DK. It can be used for nRF52-DK as well.
- Peripheral :Sample_for_Peripheral.7z
- Central : Sample_for_Central.7z