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的宏定义:

android 8之后蓝牙配对广播受限制解决_nRF52832

注意,在初始化函数中判断的是 NRF_BLE_SCAN_UUID_CNT 大于0,也就是说这个数代表了你要过滤的UUID有几个。

此时,type的case类型为 SCAN_UUID_FILTER ,所以第二个参数要是它。 第三个参数很明显要是uuid:

android 8之后蓝牙配对广播受限制解决_nRF52832_02

而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,注释中也已经给出类型有哪几个:

android 8之后蓝牙配对广播受限制解决_单片机_03

 

再有就是:

android 8之后蓝牙配对广播受限制解决_蓝牙_04

这里如果我们需要过滤多个UUID,则p_uuid应该是一个结构体数组,也就是在定义时我们先要把 NRF_BLE_SCAN_UUID_CNT 定义为UUID个数,再定义,比如我想过滤两个UUID:

android 8之后蓝牙配对广播受限制解决_蓝牙_05

 

所以用于过滤的UUID初始化为:

android 8之后蓝牙配对广播受限制解决_nRF52832_06

 

注意这个 BLE_UUID_NUS_SERVICE  就是从机我们设置的UUID,因为这个例子就是为了过滤出来从机而设置的,实际中你要根据你的从机UUID来设置这个值。所以我们最终过滤初始化设置为:

android 8之后蓝牙配对广播受限制解决_蓝牙_07

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是:

android 8之后蓝牙配对广播受限制解决_nRF52832_08

这个可以和上文初始化对应,注意第三个参数:

android 8之后蓝牙配对广播受限制解决_nRF52832_09

 

首先过滤是可以多个条件同时开启的,比如我可以同时过滤名字和UUID,如果 match_all 这个参数是false,则成功通过名字过滤的,和成功通过UUID过滤的,我们都认为是符合。但是当 match_all 这个参数是true时,必须既通过名字过滤又要通过UUID过滤!这里我们只开启了一个,所以是true还是false都无所谓。

1.3回调函数处理

和上一章没有过滤对比,我们的回调事件类型变了:

android 8之后蓝牙配对广播受限制解决_bluetooth_10

我们处理事件的结构体变了:

android 8之后蓝牙配对广播受限制解决_bluetooth_11

 

注意,这个params是union类型,也就是每次触发回调函数只能有一种数据结构存在。

上一章:

android 8之后蓝牙配对广播受限制解决_nrf_12

 

本章带过滤:

android 8之后蓝牙配对广播受限制解决_单片机_13

 

2.从机端

相对于上一章,从机端仅仅配置了在广播数据中增加UUID:

android 8之后蓝牙配对广播受限制解决_bluetooth_14

 

而UUID的定义为:

android 8之后蓝牙配对广播受限制解决_nRF52832_15

 

为了能让主机扫描到,所以和扫描过滤设置的一样。 

3.实际现象

08 1B F5 DF CE 07 D3 D0

03 03 01 00