1.主机端
最重要的,相较于上一篇只是多加了一个过滤初始化:
// 设置扫描的UUID限制
err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_UUID_FILTER, &m_nus_uuid);
APP_ERROR_CHECK(err_code);
// 使能扫描的UUID限制
err_code = nrf_ble_scan_filters_enable(&m_scan, NRF_BLE_SCAN_UUID_FILTER, false);
APP_ERROR_CHECK(err_code);
所以我们所需要知道的就是这两个函数参数如何设置。
1.1扫描过滤初始化
ret_code_t nrf_ble_scan_filter_set(nrf_ble_scan_t * const p_scan_ctx,
nrf_ble_scan_filter_type_t type,
void const * p_data)
{
VERIFY_PARAM_NOT_NULL(p_scan_ctx);
VERIFY_PARAM_NOT_NULL(p_data);
switch (type)
{
#if (NRF_BLE_SCAN_NAME_CNT > 0)
case SCAN_NAME_FILTER:
{
char * p_name = (char *)p_data;
return nrf_ble_scan_name_filter_add(p_scan_ctx, p_name);
}
#endif
#if (NRF_BLE_SCAN_SHORT_NAME_CNT > 0)
case SCAN_SHORT_NAME_FILTER:
{
nrf_ble_scan_short_name_t * p_short_name = (nrf_ble_scan_short_name_t *)p_data;
return nrf_ble_scan_short_name_filter_add(p_scan_ctx, p_short_name);
}
#endif
#if (NRF_BLE_SCAN_ADDRESS_CNT > 0)
case SCAN_ADDR_FILTER:
{
uint8_t * p_addr = (uint8_t *)p_data;
return nrf_ble_scan_addr_filter_add(p_scan_ctx, p_addr);
}
#endif
#if (NRF_BLE_SCAN_UUID_CNT > 0)
case SCAN_UUID_FILTER:
{
ble_uuid_t * p_uuid = (ble_uuid_t *)p_data;
return nrf_ble_scan_uuid_filter_add(p_scan_ctx, p_uuid);
}
#endif
#if (NRF_BLE_SCAN_APPEARANCE_CNT > 0)
case SCAN_APPEARANCE_FILTER:
{
uint16_t appearance = *((uint16_t *)p_data);
return nrf_ble_scan_appearance_filter_add(p_scan_ctx, appearance);
}
#endif
default:
return NRF_ERROR_INVALID_PARAM;
}
}
可以看到首先,必须定义相关宏定义才会开启功能,这里我们开启可以过滤UUID的宏定义:
注意,在初始化函数中判断的是 NRF_BLE_SCAN_UUID_CNT 大于0,也就是说这个数代表了你要过滤的UUID有几个。
此时,type的case类型为 SCAN_UUID_FILTER ,所以第二个参数要是它。 第三个参数很明显要是uuid:
而UUID的定义是:
/** @brief Bluetooth Low Energy UUID type, encapsulates both 16-bit and 128-bit UUIDs. */
typedef struct
{
uint16_t uuid; /**< 16-bit UUID value or octets 12-13 of 128-bit UUID. */
uint8_t type; /**< UUID type, see @ref BLE_UUID_TYPES. If type is @ref BLE_UUID_TYPE_UNKNOWN, the value of uuid is undefined. */
} ble_uuid_t;
其中两个参数,一个是128bit完整的UUID中的第12到13两个字节,其次就是type,注释中也已经给出类型有哪几个:
再有就是:
这里如果我们需要过滤多个UUID,则p_uuid应该是一个结构体数组,也就是在定义时我们先要把 NRF_BLE_SCAN_UUID_CNT 定义为UUID个数,再定义,比如我想过滤两个UUID:
所以用于过滤的UUID初始化为:
注意这个 BLE_UUID_NUS_SERVICE 就是从机我们设置的UUID,因为这个例子就是为了过滤出来从机而设置的,实际中你要根据你的从机UUID来设置这个值。所以我们最终过滤初始化设置为:
1.2过滤使能
ret_code_t nrf_ble_scan_filters_enable(nrf_ble_scan_t * const p_scan_ctx,
uint8_t mode,
bool match_all)
{
VERIFY_PARAM_NOT_NULL(p_scan_ctx);
// Check if the mode is correct.
if ((!(mode & NRF_BLE_SCAN_ADDR_FILTER)) &&
(!(mode & NRF_BLE_SCAN_NAME_FILTER)) &&
(!(mode & NRF_BLE_SCAN_UUID_FILTER)) &&
(!(mode & NRF_BLE_SCAN_SHORT_NAME_FILTER)) &&
(!(mode & NRF_BLE_SCAN_APPEARANCE_FILTER)))
{
return NRF_ERROR_INVALID_PARAM;
}
ret_code_t err_code;
// Disable filters.
err_code = nrf_ble_scan_filters_disable(p_scan_ctx);
ASSERT(err_code == NRF_SUCCESS);
nrf_ble_scan_filters_t * p_filters = &p_scan_ctx->scan_filters;
// Turn on the filters of your choice.
#if (NRF_BLE_SCAN_ADDRESS_CNT > 0)
if (mode & NRF_BLE_SCAN_ADDR_FILTER)
{
p_filters->addr_filter.addr_filter_enabled = true;
}
#endif
#if (NRF_BLE_SCAN_NAME_CNT > 0)
if (mode & NRF_BLE_SCAN_NAME_FILTER)
{
p_filters->name_filter.name_filter_enabled = true;
}
#endif
#if (NRF_BLE_SCAN_SHORT_NAME_CNT > 0)
if (mode & NRF_BLE_SCAN_SHORT_NAME_FILTER)
{
p_filters->short_name_filter.short_name_filter_enabled = true;
}
#endif
#if (NRF_BLE_SCAN_UUID_CNT > 0)
if (mode & NRF_BLE_SCAN_UUID_FILTER)
{
p_filters->uuid_filter.uuid_filter_enabled = true;
}
#endif
#if (NRF_BLE_SCAN_APPEARANCE_CNT > 0)
if (mode & NRF_BLE_SCAN_APPEARANCE_FILTER)
{
p_filters->appearance_filter.appearance_filter_enabled = true;
}
#endif
// Select the filter mode.
p_filters->all_filters_mode = match_all;
return NRF_SUCCESS;
}
同样的,我们也需要知道使能过滤扫描的参数该如何设置,首先扫描实例不再赘述,其次这个mode是:
这个可以和上文初始化对应,注意第三个参数:
首先过滤是可以多个条件同时开启的,比如我可以同时过滤名字和UUID,如果 match_all 这个参数是false,则成功通过名字过滤的,和成功通过UUID过滤的,我们都认为是符合。但是当 match_all 这个参数是true时,必须既通过名字过滤又要通过UUID过滤!这里我们只开启了一个,所以是true还是false都无所谓。
1.3回调函数处理
和上一章没有过滤对比,我们的回调事件类型变了:
我们处理事件的结构体变了:
注意,这个params是union类型,也就是每次触发回调函数只能有一种数据结构存在。
上一章:
本章带过滤:
2.从机端
相对于上一章,从机端仅仅配置了在广播数据中增加UUID:
而UUID的定义为:
为了能让主机扫描到,所以和扫描过滤设置的一样。
3.实际现象
08 1B F5 DF CE 07 D3 D0
03 03 01 00