教程原地址: https://devzone.nordicsemi.com/tutorials/15/c++
如何使用nrf51開發工具包的設備管理器庫來綁定和鏈接對端藍牙設備。git
下面來說講如何使用設備管理器(devicce manager)來存儲和刪除綁定信息。github
配對是每一個BLE設備的安全功能的初始交互,建立一個臨時加密。編程
設備配對後,能夠選擇和繼續綁定。綁定就是交換一個長期安全祕鑰,它被存儲起來以便以後重連和加密。安全
設備管理器作到這一點,是利用存儲模塊pstorage,將綁定信息存儲進flash,這樣即便從新啓動信息也依然存在。假如你綁定的設備數量達到了你本身設定的最大綁定數量,那麼設備管理器將彈出事件,而後你編程能夠自行處理。處理此問題的一個例子:the github-example ble-peripheral-bond-handling.服務器
本教程使用的模板:ble_app_templateapp
下面進入正題:ide
一、添加設備管理庫文件(device manage library)函數
在main.c中包含頭文件 #include "device_manage.h"工具
將.c文件添加到項目中(device_manager_central.c 或者 device_manager_peripheral.c) 。文件在"..\sdk_0.9\components\ble\device_manager" 下面咱們用從機(peripheral)來作做示例:
在c/c++選項中包含相應.h文件的路徑。以下圖:
注意有兩個路徑,第二個路徑中有一個文件 device_manage_cnfg.h,該文件包含設備管理器的配置,能夠在這裏設置最大綁定數,鏈接,等等。
接下里咱們還須要將一個設備管理器依賴的模塊加入工程。
#include "pstorage.h"
..\..\..\..\..\..\components\drivers_nrf\pstorage
and
..\..\..\..\..\..\components\drivers_nrf\pstorage\config
在這裏你能夠找到 pstorage_platform.h 文件,該文件包含pstorage模塊的配置信息。
二、代碼初始化
咱們要將 pstorage 加入系統事件調度器(system event dispatch)。調度器其實就是一個事件處理程序,它決定了發送事件到哪一個處理函數和發送的順序。改動 sys_evt_dispatch 的內容以下:
static void sys_evt_dispatch(uint32_t sys_evt) { ble_advertising_on_sys_evt(sys_evt); }
to:
static void sys_evt_dispatch(uint32_t sys_evt) { pstorage_sys_event_handler(sys_evt); //Add this line ble_advertising_on_sys_evt(sys_evt); }
接下來初始化設備管理器,將下列代碼加入main.c中:
能夠看到,設備管理器初始化函數中設置了鏈接參數。在上面的配對例程中,咱們使用了下面的參數static dm_application_instance_t m_app_handle; /**< Application identifier allocated by device manager */ /**@brief Function for handling the Device Manager events. * * @param[in] p_evt Data associated to the device manager event. */ static uint32_t device_manager_evt_handler(dm_handle_t const * p_handle, dm_event_t const * p_event, ret_code_t event_result) { APP_ERROR_CHECK(event_result); return NRF_SUCCESS; } /**@brief Function for the Device Manager initialization. * * @param[in] erase_bonds Indicates whether bonding information should be cleared from * persistent storage during initialization of the Device Manager. */ static void device_manager_init(bool erase_bonds) { uint32_t err_code; dm_init_param_t init_param = {.clear_persistent_data = erase_bonds}; dm_application_param_t register_param; // Initialize persistent storage module. err_code = pstorage_init(); APP_ERROR_CHECK(err_code); err_code = dm_init(&init_param); APP_ERROR_CHECK(err_code); memset(®ister_param.sec_param, 0, sizeof(ble_gap_sec_params_t)); register_param.sec_param.bond = SEC_PARAM_BOND; register_param.sec_param.mitm = SEC_PARAM_MITM; register_param.sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES; register_param.sec_param.oob = SEC_PARAM_OOB; register_param.sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE; register_param.sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE; register_param.evt_handler = device_manager_evt_handler; register_param.service_type = DM_PROTOCOL_CNTXT_GATT_SRVR_ID; err_code = dm_register(&m_app_handle, ®ister_param); APP_ERROR_CHECK(err_code); }
#define SEC_PARAM_BOND 1 /**< Perform bonding. */
#define SEC_PARAM_MITM 0 /**< Man In The Middle protection not required. */
#define SEC_PARAM_IO_CAPABILITIES BLE_GAP_IO_CAPS_NONE /**< No I/O capabilities. */
#define SEC_PARAM_OOB 0 /**< Out Of Band data not available. */
#define SEC_PARAM_MIN_KEY_SIZE 7 /**< Minimum encryption key size. */
#define SEC_PARAM_MAX_KEY_SIZE 16 /**< Maximum encryption key size. */
DM_PROTOCOL_CNTXT_GATT_SRVR_ID : 做爲服務器
接下來在main()函數中完成初始化。咱們還須要初始化局部變量 erase_bonds,這種操做可以支持咱們經過按下一個按鈕或者相似的東西來擦除全部的綁定。以下:
bool erase_bonds; device_manager_init(erase_bonds);//放在協議棧初始化以後
咱們還須要在BLE調度器(BLE dispatcher)中註冊設備管理事件處理程序:ble_evt_dispatch()函數修改部分具體以下:
from:
static void ble_evt_dispatch(ble_evt_t * p_ble_evt) { on_ble_evt(p_ble_evt); ble_conn_params_on_ble_evt(p_ble_evt); ble_advertising_on_ble_evt(p_ble_evt); /* YOUR_JOB: Add service ble_evt handlers calls here, like, for example: ble_bas_on_ble_evt(&m_bas, p_ble_evt); */ }
to:
static void ble_evt_dispatch(ble_evt_t * p_ble_evt) { on_ble_evt(p_ble_evt); ble_conn_params_on_ble_evt(p_ble_evt); ble_advertising_on_ble_evt(p_ble_evt); /* YOUR_JOB: Add service ble_evt handlers calls here, like, for example: ble_bas_on_ble_evt(&m_bas, p_ble_evt); */ dm_ble_evt_handler(p_ble_evt); //Add this line }
打開主控制面板(Master Control Panel)MCP並檢查咱們的新設備管理鏈接的功能。在編譯和下載咱們的工程以後,咱們能夠看到LED1在閃爍,這代表設備正在廣播。咱們也可使用MCP鏈接它,這時觀察到LED1的閃爍變爲常亮。可是,當咱們試圖和它進行配對和綁定,這會讓咱們遇到麻煩,它會拒絕綁定而後從新返回到廣播狀態
因爲原始代碼已經實現了手動配對,所以咱們作了兩次相同的事情,一次手動,一次使用設備管理器,這就是致使錯誤的緣由。咱們但願配對和綁定由設備管理器處理,咱們能夠將 on_ble_evt 處理程序更改成:
static void on_ble_evt(ble_evt_t * p_ble_evt) { uint32_t err_code; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); APP_ERROR_CHECK(err_code); m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; break; default: // No implementation needed. break; } }
雖然教程上是這麼寫的,不過咱們實際使用的時候通常會加多一條斷開鏈接處理,通過驗證這種寫法是不會影響鏈接和綁定的,以下:
static void on_ble_evt(ble_evt_t * p_ble_evt) { uint32_t err_code; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); APP_ERROR_CHECK(err_code); m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; break;
case BLE_GAP_EVT_DISCONNECTED: //讓設備斷開鏈接後繼續廣播
m_conn_handle = BLE_CONN_HANDLE_INVALID;
AdvertisingStart();
break;
default: // No implementation needed. break; } }
如今咱們可使用MCP或者BLE手機與設備自由鏈接和綁定。請注意,在未鏈接時設備處於廣播狀態,LED1閃爍,在鏈接時LED1常亮。請注意,若是您對開發工具包(development kit)進行配對綁定,斷開後從新鏈接時不須要再次進行綁定就可以得到加密的鏈接。這就是設備管理器的好處。