教程原地址: 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)进行配对绑定,断开后从新链接时不须要再次进行绑定就可以得到加密的链接。这就是设备管理器的好处。