一、背景
1.1 低功耗蓝牙(BLE)协议栈
链路层(LL) 控制设备的射频状态,有五个设备状态:待机、广播、扫描、初始化和连接。
广播 为广播数据包,而 扫描 则是监听广播。
GAP通信中角色,中心设备(Central - 主机) 用来扫描和连接 外围设备(Peripheral - 从机)。
大部分情况下外围设备通过广播自己来让中心设备发现自己,并建立 GATT 连接,从而进行更多的数据交换。
也有些情况是不需要连接的,只要外设广播自己的数据即可,用这种方式主要目的是让外围设备,把自己的信息发送给多个中心设备。
1.2 从机广播
从机(外围设备)要被主机连接,那么它就必须先被主机发现。这个时候,从机设备把自身信息以广播形式发射出去。
比如设备A需要先进行广播,即 设备A(Advertiser) 不断发送如下广播信号,t 为广播间隔。每发送一次广播包,我们称其为一次 广播事件(advertising event),因此 t 也称为广播事件间隔,如下图所示。广播事件是一阵一阵的,每次会是有一个持续时间的,蓝牙芯片只有在广播事件期间才打开射频模块发射广播,这个时候功耗比较高,其余时间蓝牙芯片都处于idle待机状态,因此平均功耗就非常低。
当广播发出的时候,每一个广播事件包含三个广播包,即分别在 37/38/39 三个通道上同时广播相同的信息。下图 observer 为主机观察者,advertiser 就是从机广播。
1.3 ESP32蓝牙应用结构
蓝牙是⼀种短距通信系统,其关键特性包括鲁棒性、低功耗、低成本等。蓝牙系统分为两种不同的技术:经典蓝牙 (Classic Bluetooth) 和蓝牙低功耗 (Bluetooth Low Energy)。
ESP32 支持双模蓝牙,即同时支持经典蓝牙和蓝牙低功耗。
从整体结构上,蓝牙可分为控制器 (Controller) 和主机 (Host) 两⼤部分:控制器包括了 PHY、Baseband、Link Controller、Link Manager、Device Manager、HCI 等模块,用于硬件接⼝管理、链路管理等等;主机则包括了 L2CAP、SMP、SDP、ATT、GATT、GAP 以及各种规范,构建了向应用层提供接口的基础,方便应用层对蓝牙系统的访问。主机可以与控制器运行在同⼀个宿主上,也可以分布在不同的宿主上。ESP32 可以支持上述两种方式。
1.4 Bluedroid主机架构
在 ESP-IDF 中,使用经过大量修改后的 BLUEDROID 作为蓝牙主机 (Classic BT + BLE)。BLUEDROID 拥有较为完善的功能,⽀持常用的规范和架构设计,同时也较为复杂。经过大量修改后,BLUEDROID 保留了大多数 BTA 层以下的代码,几乎完全删去了 BTIF 层的代码,使用了较为精简的 BTC 层作为内置规范及 Misc 控制层。修改后的 BLUEDROID 及其与控制器之间的关系如下图:
本篇是关于广播自定义数据包,配置以及启动或关闭广播的流程查看 ESP32学习笔记(26)——BLE GAP从机端广播
二、广播内容参数
在 esp_gap_ble_api_.h 文件中,提供了广播的初始化参数结构体。
/// Advertising data content, according to "Supplement to the Bluetooth Core Specification"
typedef struct {
bool set_scan_rsp; /*!< Set this advertising data as scan response or not*/
bool include_name; /*!< Advertising data include device name or not */
bool include_txpower; /*!< Advertising data include TX power */
int min_interval; /*!< Advertising data show slave preferred connection min interval.
The connection interval in the following manner:
connIntervalmin = Conn_Interval_Min * 1.25 ms
Conn_Interval_Min range: 0x0006 to 0x0C80
Value of 0xFFFF indicates no specific minimum.
Values not defined above are reserved for future use.*/
int max_interval; /*!< Advertising data show slave preferred connection max interval.
The connection interval in the following manner:
connIntervalmax = Conn_Interval_Max * 1.25 ms
Conn_Interval_Max range: 0x0006 to 0x0C80
Conn_Interval_Max shall be equal to or greater than the Conn_Interval_Min.
Value of 0xFFFF indicates no specific maximum.
Values not defined above are reserved for future use.*/
int appearance; /*!< External appearance of device */
uint16_t manufacturer_len; /*!< Manufacturer data length */
uint8_t *p_manufacturer_data; /*!< Manufacturer data point */
uint16_t service_data_len; /*!< Service data length */
uint8_t *p_service_data; /*!< Service data point */
uint16_t service_uuid_len; /*!< Service uuid length */
uint8_t *p_service_uuid; /*!< Service uuid array point */
uint8_t flag; /*!< Advertising flag of discovery mode, see BLE_ADV_DATA_FLAG detail */
} esp_ble_adv_data_t;
-
set_scan_rsp
:设置此结构体数据是否为扫描响应包 -
include_name
:包含设备名称 -
include_txpower
:包含TX电平发送功率 -
min_interval
:最小广播间隔 -
max_interval
:最大广播间隔 -
appearance
:展示图标 -
manufacturer_len
:制造商特定的数据长度(自定义广播数据长度) -
p_manufacturer_data
:制造商特定的数据(自定义广播数据) -
service_data_len
:服务数据长度 -
p_service_data
:服务数据 -
service_uuid_len
:服务UUID长度 -
p_service_uuid
:服务UUID -
flags
:广播数据标识字段
三、广播设备名称
先调用 esp_ble_gap_set_device_name()
设置名称,然后调用 esp_ble_gap_config_adv_data()
,再调用 esp_ble_gap_start_advertising()
static esp_ble_adv_params_t ble_adv_params = {
.adv_int_min = 0x20,
.adv_int_max = 0x40,
.adv_type = ADV_TYPE_IND,
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
.channel_map = ADV_CHNL_ALL,
.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};
static esp_ble_adv_data_t adv_data = {
.include_name = true,
.flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};
esp_ble_gap_set_device_name("hello"); // 设置设备名称
esp_ble_gap_config_adv_data(&adv_data); // 配置广播内容
esp_ble_gap_start_advertising(&ble_adv_params); // 开启广播
四、广播展示图标
设置结构体 esp_ble_adv_data_t 中 appearance
的值,图标值如下:
#define ESP_BLE_APPEARANCE_UNKNOWN 0x0000 /* relate to BTM_BLE_APPEARANCE_UNKNOWN in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_PHONE 0x0040 /* relate to BTM_BLE_APPEARANCE_GENERIC_PHONE in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_COMPUTER 0x0080 /* relate to BTM_BLE_APPEARANCE_GENERIC_COMPUTER in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_WATCH 0x00C0 /* relate to BTM_BLE_APPEARANCE_GENERIC_WATCH in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_SPORTS_WATCH 0x00C1 /* relate to BTM_BLE_APPEARANCE_SPORTS_WATCH in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_CLOCK 0x0100 /* relate to BTM_BLE_APPEARANCE_GENERIC_CLOCK in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_DISPLAY 0x0140 /* relate to BTM_BLE_APPEARANCE_GENERIC_DISPLAY in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_REMOTE 0x0180 /* relate to BTM_BLE_APPEARANCE_GENERIC_REMOTE in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_EYEGLASSES 0x01C0 /* relate to BTM_BLE_APPEARANCE_GENERIC_EYEGLASSES in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_TAG 0x0200 /* relate to BTM_BLE_APPEARANCE_GENERIC_TAG in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_KEYRING 0x0240 /* relate to BTM_BLE_APPEARANCE_GENERIC_KEYRING in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_MEDIA_PLAYER 0x0280 /* relate to BTM_BLE_APPEARANCE_GENERIC_MEDIA_PLAYER in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_BARCODE_SCANNER 0x02C0 /* relate to BTM_BLE_APPEARANCE_GENERIC_BARCODE_SCANNER in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_THERMOMETER 0x0300 /* relate to BTM_BLE_APPEARANCE_GENERIC_THERMOMETER in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_THERMOMETER_EAR 0x0301 /* relate to BTM_BLE_APPEARANCE_THERMOMETER_EAR in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_HEART_RATE 0x0340 /* relate to BTM_BLE_APPEARANCE_GENERIC_HEART_RATE in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_HEART_RATE_BELT 0x0341 /* relate to BTM_BLE_APPEARANCE_HEART_RATE_BELT in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_BLOOD_PRESSURE 0x0380 /* relate to BTM_BLE_APPEARANCE_GENERIC_BLOOD_PRESSURE in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_BLOOD_PRESSURE_ARM 0x0381 /* relate to BTM_BLE_APPEARANCE_BLOOD_PRESSURE_ARM in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_BLOOD_PRESSURE_WRIST 0x0382 /* relate to BTM_BLE_APPEARANCE_BLOOD_PRESSURE_WRIST in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_HID 0x03C0 /* relate to BTM_BLE_APPEARANCE_GENERIC_HID in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_HID_KEYBOARD 0x03C1 /* relate to BTM_BLE_APPEARANCE_HID_KEYBOARD in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_HID_MOUSE 0x03C2 /* relate to BTM_BLE_APPEARANCE_HID_MOUSE in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_HID_JOYSTICK 0x03C3 /* relate to BTM_BLE_APPEARANCE_HID_JOYSTICK in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_HID_GAMEPAD 0x03C4 /* relate to BTM_BLE_APPEARANCE_HID_GAMEPAD in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_HID_DIGITIZER_TABLET 0x03C5 /* relate to BTM_BLE_APPEARANCE_HID_DIGITIZER_TABLET in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_HID_CARD_READER 0x03C6 /* relate to BTM_BLE_APPEARANCE_HID_CARD_READER in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_HID_DIGITAL_PEN 0x03C7 /* relate to BTM_BLE_APPEARANCE_HID_DIGITAL_PEN in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_HID_BARCODE_SCANNER 0x03C8 /* relate to BTM_BLE_APPEARANCE_HID_BARCODE_SCANNER in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_GLUCOSE 0x0400 /* relate to BTM_BLE_APPEARANCE_GENERIC_GLUCOSE in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_WALKING 0x0440 /* relate to BTM_BLE_APPEARANCE_GENERIC_WALKING in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_WALKING_IN_SHOE 0x0441 /* relate to BTM_BLE_APPEARANCE_WALKING_IN_SHOE in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_WALKING_ON_SHOE 0x0442 /* relate to BTM_BLE_APPEARANCE_WALKING_ON_SHOE in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_WALKING_ON_HIP 0x0443 /* relate to BTM_BLE_APPEARANCE_WALKING_ON_HIP in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_CYCLING 0x0480 /* relate to BTM_BLE_APPEARANCE_GENERIC_CYCLING in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_CYCLING_COMPUTER 0x0481 /* relate to BTM_BLE_APPEARANCE_CYCLING_COMPUTER in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_CYCLING_SPEED 0x0482 /* relate to BTM_BLE_APPEARANCE_CYCLING_SPEED in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_CYCLING_CADENCE 0x0483 /* relate to BTM_BLE_APPEARANCE_CYCLING_CADENCE in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_CYCLING_POWER 0x0484 /* relate to BTM_BLE_APPEARANCE_CYCLING_POWER in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_CYCLING_SPEED_CADENCE 0x0485 /* relate to BTM_BLE_APPEARANCE_CYCLING_SPEED_CADENCE in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_PULSE_OXIMETER 0x0C40 /* relate to BTM_BLE_APPEARANCE_GENERIC_PULSE_OXIMETER in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP 0x0C41 /* relate to BTM_BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_PULSE_OXIMETER_WRIST 0x0C42 /* relate to BTM_BLE_APPEARANCE_PULSE_OXIMETER_WRIST in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_WEIGHT 0x0C80 /* relate to BTM_BLE_APPEARANCE_GENERIC_WEIGHT in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_PERSONAL_MOBILITY_DEVICE 0x0CC0 /* relate to BTM_BLE_APPEARANCE_GENERIC_PERSONAL_MOBILITY_DEVICE in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_POWERED_WHEELCHAIR 0x0CC1 /* relate to BTM_BLE_APPEARANCE_POWERED_WHEELCHAIR in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_MOBILITY_SCOOTER 0x0CC2 /* relate to BTM_BLE_APPEARANCE_MOBILITY_SCOOTER in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_CONTINUOUS_GLUCOSE_MONITOR 0x0D00 /* relate to BTM_BLE_APPEARANCE_GENERIC_CONTINUOUS_GLUCOSE_MONITOR in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_INSULIN_PUMP 0x0D40 /* relate to BTM_BLE_APPEARANCE_GENERIC_INSULIN_PUMP in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_INSULIN_PUMP_DURABLE_PUMP 0x0D41 /* relate to BTM_BLE_APPEARANCE_INSULIN_PUMP_DURABLE_PUMP in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_INSULIN_PUMP_PATCH_PUMP 0x0D44 /* relate to BTM_BLE_APPEARANCE_INSULIN_PUMP_PATCH_PUMP in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_INSULIN_PEN 0x0D48 /* relate to BTM_BLE_APPEARANCE_INSULIN_PEN in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_MEDICATION_DELIVERY 0x0D80 /* relate to BTM_BLE_APPEARANCE_GENERIC_MEDICATION_DELIVERY in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS 0x1440 /* relate to BTM_BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION 0x1441 /* relate to BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_AND_NAV 0x1442 /* relate to BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_AND_NAV in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD 0x1443 /* relate to BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD in stack/btm_ble_api.h */
#define ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD_AND_NAV 0x1444 /* relate to BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD_AND_NAV in stack/btm_ble_api.h */
先设置 appearance
的值,然后调用 esp_ble_gap_config_adv_data()
,再调用 esp_ble_gap_start_advertising()
static esp_ble_adv_params_t ble_adv_params = {
.adv_int_min = 0x20,
.adv_int_max = 0x40,
.adv_type = ADV_TYPE_IND,
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
.channel_map = ADV_CHNL_ALL,
.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};
static esp_ble_adv_data_t adv_data = {
.appearance = ESP_BLE_APPEARANCE_GENERIC_PHONE,
.flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};
esp_ble_gap_config_adv_data(&adv_data); // 配置广播内容
esp_ble_gap_start_advertising(&ble_adv_params); // 开启广播
五、广播UUID的值
UUID的种类分为两种:
- 一种是 SIG 定义的公共服务 UUID,所有的公共服务共用一个 128bit 的基础 UUID,不同的服务采用一个 16bit UUID 进行定义。基础UUID:0x0000xxxx-0000-1000-8000-00805F9B34FB
- 另一种就是私有服务的 UUID,这是一个自定义的 128bit UUID。
注意:广播包里的 UUID 不影响服务特征值中 UUID 的值,仅仅是让广播把 UUID 的值广播给扫描设备,方便观察。
这里广播了两个 16bite UUID:0x00EE、0x00FF
调用 esp_ble_gap_config_adv_data()
,再调用 esp_ble_gap_start_advertising()
static uint8_t adv_service_uuid128[32] = {
/* LSB <--------------------------------------------------------------------------------> MSB */
//first uuid, 16bit, [12],[13] is the value
0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00,
//second uuid, 32bit, [12], [13], [14], [15] is the value
0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
};
static esp_ble_adv_params_t ble_adv_params = {
.adv_int_min = 0x20,
.adv_int_max = 0x40,
.adv_type = ADV_TYPE_IND,
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
.channel_map = ADV_CHNL_ALL,
.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};
static esp_ble_adv_data_t adv_data = {
.service_uuid_len = sizeof(adv_service_uuid128),
.p_service_uuid = adv_service_uuid128,
.flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};
esp_ble_gap_config_adv_data(&adv_data); // 配置广播内容
esp_ble_gap_start_advertising(&ble_adv_params); // 开启广播
六、广播从机的连接间隔参数
从机与主机之间的连接间隔,是由从机提出与主机进行协商,然后再由主机决定的参数。
先设置 min_interval 和 max_interval
的值,然后调用 esp_ble_gap_config_adv_data()
,再调用 esp_ble_gap_start_advertising()
static esp_ble_adv_params_t ble_adv_params = {
.adv_int_min = 0x20,
.adv_int_max = 0x40,
.adv_type = ADV_TYPE_IND,
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
.channel_map = ADV_CHNL_ALL,
.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};
static esp_ble_adv_data_t adv_data = {
.min_interval = 0x000A, //slave connection min interval, Time = min_interval * 1.25 msec=7.5ms
.max_interval = 0x0014, //slave connection max interval, Time = max_interval * 1.25 msec=20ms
.flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};
esp_ble_gap_config_adv_data(&adv_data); // 配置广播内容
esp_ble_gap_start_advertising(&ble_adv_params); // 开启广播
通过手机APP nrf connect 扫描后显示:
七、广播自定义数据
p_manufacturer_data
:制造商自定义的数据,这个参数可以自由的设置,只要广播包的空间足够。假设自定义数据为 0x11,0x22,0x33,0x44,0x55。
static uint8_t user_data[5] = {0x11, 0x22, 0x33, 0x44, 0x55};
static esp_ble_adv_params_t ble_adv_params = {
.adv_int_min = 0x20,
.adv_int_max = 0x40,
.adv_type = ADV_TYPE_IND,
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
.channel_map = ADV_CHNL_ALL,
.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};
static esp_ble_adv_data_t adv_data = {
.manufacturer_len = sizeof(user_data),
.p_manufacturer_data = user_data,
.flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};
esp_ble_gap_config_adv_data(&adv_data); // 配置广播内容
esp_ble_gap_start_advertising(&ble_adv_params); // 开启广播
八、广播扫描响应包
先设置 set_scan_rsp = true
将此包设为扫描响应包,然后调用 esp_ble_gap_config_adv_data()
,再调用 esp_ble_gap_start_advertising()
static uint8_t user_data[3] = {0x11, 0x22, 0x33};
static uint8_t user_data2[3] = {0x66, 0x77, 0x88};
static esp_ble_adv_params_t ble_adv_params = {
.adv_int_min = 0x20,
.adv_int_max = 0x40,
.adv_type = ADV_TYPE_IND,
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
.channel_map = ADV_CHNL_ALL,
.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};
static esp_ble_adv_data_t srsp_data = {
.set_scan_rsp = true,
.manufacturer_len = sizeof(user_data2),
.p_manufacturer_data = user_data2,
};
static esp_ble_adv_data_t adv_data = {
.manufacturer_len = sizeof(user_data),
.p_manufacturer_data = user_data,
.flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};
esp_ble_gap_config_adv_data(&srsp_data); // 配置扫描响应包
esp_ble_gap_config_adv_data(&adv_data); // 配置广播数据包
esp_ble_gap_start_advertising(&ble_adv_params); // 开启广播
九、实例
根据 esp-idf\examples\bluetooth\bluedroid\ble\ble_ibeacon 中的例程修改
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#include "nvs_flash.h"
#include "esp_bt.h"
#include "esp_gap_ble_api.h"
#include "esp_gattc_api.h"
#include "esp_gatt_defs.h"
#include "esp_bt_main.h"
#include "esp_bt_defs.h"
#include "esp_ibeacon_api.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
static const char* DEMO_TAG = "IBEACON_DEMO";
///Declare static functions
static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
static esp_ble_adv_params_t ble_adv_params = {
.adv_int_min = 0x20,
.adv_int_max = 0x40,
.adv_type = ADV_TYPE_IND,
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
.channel_map = ADV_CHNL_ALL,
.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};
static uint8_t adv_service_uuid128[32] = {
/* LSB <--------------------------------------------------------------------------------> MSB */
//first uuid, 16bit, [12],[13] is the value
0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00,
//second uuid, 32bit, [12], [13], [14], [15] is the value
0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
};
static uint8_t user_data[3] = {0x11, 0x22, 0x33};
static uint8_t user_data2[3] = {0x66, 0x77, 0x88};
static esp_ble_adv_data_t srsp_data = {
.set_scan_rsp = true,
.manufacturer_len = sizeof(user_data2),
.p_manufacturer_data = user_data2,
};
static esp_ble_adv_data_t adv_data = {
.set_scan_rsp = false,
.include_name = true,
.min_interval = 0x000A, //slave connection min interval, Time = min_interval * 1.25 msec=7.5ms
.max_interval = 0x0014, //slave connection max interval, Time = max_interval * 1.25 msec=20ms
.appearance = ESP_BLE_APPEARANCE_GENERIC_PHONE,
.manufacturer_len = sizeof(user_data),
.p_manufacturer_data = user_data,
.service_uuid_len = sizeof(adv_service_uuid128),
.p_service_uuid = adv_service_uuid128,
.flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};
static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
esp_err_t err;
switch (event) {
case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:{
esp_ble_gap_start_advertising(&ble_adv_params);
break;
}
case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
//adv start complete event to indicate adv start successfully or failed
if ((err = param->adv_start_cmpl.status) != ESP_BT_STATUS_SUCCESS) {
ESP_LOGE(DEMO_TAG, "Adv start failed: %s", esp_err_to_name(err));
}
break;
case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
if ((err = param->adv_stop_cmpl.status) != ESP_BT_STATUS_SUCCESS){
ESP_LOGE(DEMO_TAG, "Adv stop failed: %s", esp_err_to_name(err));
}
else {
ESP_LOGI(DEMO_TAG, "Stop adv successfully");
}
break;
default:
break;
}
}
void ble_ibeacon_appRegister(void)
{
esp_err_t status;
ESP_LOGI(DEMO_TAG, "register callback");
//register the scan callback function to the gap module
if ((status = esp_ble_gap_register_callback(esp_gap_cb)) != ESP_OK) {
ESP_LOGE(DEMO_TAG, "gap register error: %s", esp_err_to_name(status));
return;
}
}
void ble_ibeacon_init(void)
{
esp_bluedroid_init();
esp_bluedroid_enable();
ble_ibeacon_appRegister();
}
void app_main(void)
{
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
esp_bt_controller_init(&bt_cfg);
esp_bt_controller_enable(ESP_BT_MODE_BLE);
ble_ibeacon_init();
esp_ble_gap_set_device_name("hello");
esp_ble_gap_config_adv_data(&srsp_data);
esp_ble_gap_config_adv_data(&adv_data);
}
• 由 Leung 写于 2021 年 7 月 5 日