测试环境

BLE 广播类型

typedef enum {
    ADV_TYPE_IND                = 0x00,
    ADV_TYPE_DIRECT_IND_HIGH    = 0x01,
    ADV_TYPE_SCAN_IND           = 0x02,
    ADV_TYPE_NONCONN_IND        = 0x03,
    ADV_TYPE_DIRECT_IND_LOW     = 0x04,
} esp_ble_adv_type_t;

下面是对这几种广播类型的说明:

  • ADV_TYPE_IND(可连接的非定向广播):
    这是一种用途最广,最常见的广播类型,包括广播数据扫描响应数据,它表示当前设备可以接受任何设备的连接请求。
    进行通用广播的设备能够被扫描设备扫描到,或者在接收到连接请求时作为从设备进入一个连接。

    ESP32 BLE 定向广播-LMLPHP

  • ADV_TYPE_DIRECT_IND_HIGH ADV_TYPE_DIRECT_IND_LOW(可连接的定向广播):
    定向广播类型是为了尽可能快地连接,俗称回连包,这种报文包含两个地址:广播者的地址发起者的地址。发起者收到发给自己的定向广播报文之后,可以立即发送连接请求作为回应。

    当使用定向广播时,设备不能被主动扫描。此外,定向广播报文的有效载荷中也不能带有其他附加数据。该有效载荷只能包含两个必须的地址
    ESP32 BLE 定向广播-LMLPHP

ADV_TYPE_DIRECT_IND_HIGH 为可连接高占空比定向广播,在该模式下,发送在相同广播信道索引上的两个连续 ADV_DIRECT_IND PDU 之间的时间间隔应小于或等于 3.75 毫秒。
ESP32 BLE 定向广播-LMLPHP

ADV_TYPE_DIRECT_IND_LOW 为可连接低占空比定向广播,在该模式下,两个连续的ADV_DIRECT_IND PDU 之间的时间间隔在一个广播事件内应小于或等于 10 毫秒。广播事件应在广播间隔内结束。
ESP32 BLE 定向广播-LMLPHP

  • ADV_TYPE_SCAN_IND(可扫描的非定向广播):
    又称可发现广播,这种广播不能用于发起连接,但允许其他设备扫描该广播设备。这意味着该设备可以被发现,既可以发送广播数据,也可以响应扫描发送扫描响应数据,但不能建立连接。这是一种适用于广播数据的广播形式,动态数据可以包含于广播数据之中,而静态数据可以包含于扫描响应数据之中。
    ESP32 BLE 定向广播-LMLPHP
  • ADV_TYPE_NONCONN_IND(不可连接的非定向广播):
    仅仅发送广播数据,而不能被扫描或者连接。这也是唯一可用于只有发射机而没有接收机设备的广播类型。不可连接设备不会进入连接态,因此,它只能根据主机的要求在广播态和就绪态之间切换。常用于 Beacon 项目。
    ESP32 BLE 定向广播-LMLPHP

基于例程修改实现 BLE 的定向广播

在本测试中,用作 ble client 的设备的蓝牙 public MAC 地址为 e0:5a:1b:1:c2:7e,用作 ble server 的设备的蓝牙 public MAC 地址为 e0:5a:1b:13:79:a6

基于 gatt_server 修改

  • adv_type 修改为 ADV_TYPE_DIRECT_IND_HIGH 或者 ADV_TYPE_DIRECT_IND_LOW,本例中,对端设备 MAC 地址类型为 public,因此,设置 peer_addr_typeBLE_ADDR_TYPE_PUBLIC,将对端设备的 public 蓝牙 MAC 地址赋给 peer_addr
static esp_ble_adv_params_t adv_params = {
    .adv_int_min        = 0x20,
    .adv_int_max        = 0x40,
    .adv_type           = ADV_TYPE_DIRECT_IND_LOW,
    .own_addr_type      = BLE_ADDR_TYPE_PUBLIC,
    .peer_addr          = {0xe0, 0x5a, 0x1b, 0x15, 0xc2, 0x7e},
    .peer_addr_type     = BLE_ADDR_TYPE_PUBLIC,
    .channel_map        = ADV_CHNL_ALL,
    .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};

基于 gatt_client 修改

  • 例程中默认是通过判断扫描到的广播数据中的设备名称和代码中预先定义的 server 设备名称是否一致从而发起连接,而对于定向广播而言,有效载荷是不包含 31 字节的广播数据的,只有广播者的地址和发起者的地址,所以代码中的判断条件需要修改,可将 MAC 地址是否一致作为判断条件,否则连接不到 server 设备。
            uint8_t remote_bt_addr[6] = {0xe0, 0x5a, 0x1b, 0x13, 0x79, 0xa6};
            // if (adv_name != NULL) {
                //if (strlen(remote_device_name) == adv_name_len && strncmp((char *)adv_name, remote_device_name, adv_name_len) == 0) {
                if (compare_arrays(scan_result->scan_rst.bda, remote_bt_addr, 6) == 0) {
                    ESP_LOGI(GATTC_TAG, "searched device\n");
                    if (connect == false) {
                        connect = true;
                        ESP_LOGI(GATTC_TAG, "connect to the remote device.");
                        esp_ble_gap_stop_scanning();
                        esp_ble_gattc_open(gl_profile_tab[PROFILE_A_APP_ID].gattc_if, scan_result->scan_rst.bda, scan_result->scan_rst.ble_addr_type, true);
                    }
                }
            // }
            break;
  • 用于比对 MAC 地址是否一致:
int compare_arrays(const uint8_t* array1, const uint8_t* array2, size_t size) {
    for (size_t i = 0; i < size; i++) {
        if (array1[i] != array2[i]) {
            return -1;
        }
    }
    return 0;
}
  • 打印设备蓝牙 MAC 地址:
    {
        uint8_t derived_mac_addr[6] = {0};
        ESP_ERROR_CHECK(esp_read_mac(derived_mac_addr, ESP_MAC_BT));
        ESP_LOGI("BT MAC", "0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x",
             derived_mac_addr[0], derived_mac_addr[1], derived_mac_addr[2],
             derived_mac_addr[3], derived_mac_addr[4], derived_mac_addr[5]);
    }

日志输出

I (0) cpu_start: Starting scheduler on APP CPU.
I (607) system_api: Base MAC address is not set
I (607) system_api: read default base MAC address from EFUSE
I (607) BT MAC: 0xe0, 0x5a, 0x1b, 0x15, 0xc2, 0x7e
I (607) BTDM_INIT: BT controller compile version [2c56073]
I (617) phy_init: phy_version 4670,719f9f6,Feb 18 2021,17:07:07
I (1037) GATTC_DEMO: REG_EVT
I (1057) GATTC_DEMO: scan start success
I (1067) GATTC_DEMO: 0a 25 10 be 07 a0 
I (1067) GATTC_DEMO: searched Adv Data Len 29, Scan Response Len 0
I (1077) GATTC_DEMO: searched Device Name Len 0
I (1077) GATTC_DEMO: 
I (1087) GATTC_DEMO: 0e fa 98 7c 81 5a 
I (1087) GATTC_DEMO: searched Adv Data Len 10, Scan Response Len 0
I (1097) GATTC_DEMO: searched Device Name Len 0
I (1097) GATTC_DEMO: 
I (1107) GATTC_DEMO: e0 5a 1b 13 79 a6 
I (1107) GATTC_DEMO: searched Adv Data Len 0, Scan Response Len 0
I (1117) GATTC_DEMO: searched Device Name Len 0
I (1127) GATTC_DEMO: 

I (1127) GATTC_DEMO: searched device

I (1127) GATTC_DEMO: connect to the remote device.

I (607) BT MAC: 0xe0, 0x5a, 0x1b, 0x15, 0xc2, 0x7e 和 server 端设置的定向广播对端的 MAC 地址一致。

I (1107) GATTC_DEMO: e0 5a 1b 13 79 a6 
I (1107) GATTC_DEMO: searched Adv Data Len 0, Scan Response Len 0
I (1117) GATTC_DEMO: searched Device Name Len 0
I (1127) GATTC_DEMO: 

可以看到,client 设备有成功扫描到 server 设备,由于定向广播报文的有效载荷中不带有其他附加数据,所以广播和扫描响应数据的长度均为 0。

参考链接

08-22 10:23