【广播数据包结构讲解】
广播数据包的讲解网上可参考的也挺多,讲解了整个数据包的每个字节每个位的功能描述,非常详细。
今天我们换个方式,按照代码编写的方式,只要是被SDK封装的部分都不做考虑,例如报头、crc校验等,讲讲应用层需要关心的部分,对比下五颗蓝牙芯片的广播包数据。
上图所示为广播包的结构图,需要注意的是数据段最大为37字节,其中广播设备的mac地址占用6字节,所以广播最大的有效的数据是31字节。
广播数据结构
广播数据包最长31字节,而这31字节又被拆成很多小数据包,每个小数据包代表一类广播数据。例如有设备名称数据包,外观数据包,发射功率数据包,服务UUID数据包,服务数据数据包,厂商自定义数据包。
每个小数据包结构如下:
{
unsigned char length; //整数据长度-1
unsigned char type; //数据类型
unsigned char data[length-1];//数据
}
举个例子:如果我全部使用自定义数据包,length=30,type=0xff,data[29],真实能够填充的就是29个字节
广播数据包类型type
type值是蓝牙联盟定义的,全球统一,宏的命名是每个厂家自己定义的,如下是nordic sdk的定义。
/**@defgroup BLE_GAP_AD_TYPE_DEFINITIONS GAP Advertising and Scan Response Data format
* @note Found at https://www.bluetooth.org/Technical/AssignedNumbers/generic_access_profile.htm
* @{ */
#define BLE_GAP_AD_TYPE_FLAGS 0x01 /**< Flags for discoverability. */
#define BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE 0x02 /**< Partial list of 16 bit service UUIDs. */
#define BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE 0x03 /**< Complete list of 16 bit service UUIDs. */
#define BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_MORE_AVAILABLE 0x04 /**< Partial list of 32 bit service UUIDs. */
#define BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_COMPLETE 0x05 /**< Complete list of 32 bit service UUIDs. */
#define BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE 0x06 /**< Partial list of 128 bit service UUIDs. */
#define BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE 0x07 /**< Complete list of 128 bit service UUIDs. */
#define BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME 0x08 /**< Short local device name. */
#define BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME 0x09 /**< Complete local device name. */
#define BLE_GAP_AD_TYPE_TX_POWER_LEVEL 0x0A /**< Transmit power level. */
#define BLE_GAP_AD_TYPE_CLASS_OF_DEVICE 0x0D /**< Class of device. */
#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_HASH_C 0x0E /**< Simple Pairing Hash C. */
#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R 0x0F /**< Simple Pairing Randomizer R. */
#define BLE_GAP_AD_TYPE_SECURITY_MANAGER_TK_VALUE 0x10 /**< Security Manager TK Value. */
#define BLE_GAP_AD_TYPE_SECURITY_MANAGER_OOB_FLAGS 0x11 /**< Security Manager Out Of Band Flags. */
#define BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE 0x12 /**< Slave Connection Interval Range. */
#define BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT 0x14 /**< List of 16-bit Service Solicitation UUIDs. */
#define BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT 0x15 /**< List of 128-bit Service Solicitation UUIDs. */
#define BLE_GAP_AD_TYPE_SERVICE_DATA 0x16 /**< Service Data - 16-bit UUID. */
#define BLE_GAP_AD_TYPE_PUBLIC_TARGET_ADDRESS 0x17 /**< Public Target Address. */
#define BLE_GAP_AD_TYPE_RANDOM_TARGET_ADDRESS 0x18 /**< Random Target Address. */
#define BLE_GAP_AD_TYPE_APPEARANCE 0x19 /**< Appearance. */
#define BLE_GAP_AD_TYPE_ADVERTISING_INTERVAL 0x1A /**< Advertising Interval. */
#define BLE_GAP_AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS 0x1B /**< LE Bluetooth Device Address. */
#define BLE_GAP_AD_TYPE_LE_ROLE 0x1C /**< LE Role. */
#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_HASH_C256 0x1D /**< Simple Pairing Hash C-256. */
#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R256 0x1E /**< Simple Pairing Randomizer R-256. */
#define BLE_GAP_AD_TYPE_SERVICE_DATA_32BIT_UUID 0x20 /**< Service Data - 32-bit UUID. */
#define BLE_GAP_AD_TYPE_SERVICE_DATA_128BIT_UUID 0x21 /**< Service Data - 128-bit UUID. */
#define BLE_GAP_AD_TYPE_LESC_CONFIRMATION_VALUE 0x22 /**< LE Secure Connections Confirmation Value */
#define BLE_GAP_AD_TYPE_LESC_RANDOM_VALUE 0x23 /**< LE Secure Connections Random Value */
#define BLE_GAP_AD_TYPE_URI 0x24 /**< URI */
#define BLE_GAP_AD_TYPE_3D_INFORMATION_DATA 0x3D /**< 3D Information Data. */
根据上面的定义,我们解析下上篇文章中,广播数据包的信息。
ESP32的广播数据代码:(广播包数据最多31的字节)
static void hci_cmd_send_ble_set_adv_data(void)
{
char *adv_name = "ESP-BLE-HELLO";
uint8_t name_len = (uint8_t)strlen(adv_name);
uint8_t adv_data[31] = {0x02, 0x01, 0x06, 0x0, 0x09};
uint8_t adv_data_len;
adv_data[3] = name_len + 1;
for (int i = 0; i < name_len; i++) {
adv_data[5 + i] = (uint8_t)adv_name[i];
}
adv_data_len = 5 + name_len;
uint16_t sz = make_cmd_ble_set_adv_data(hci_cmd_buf, adv_data_len, (uint8_t *)adv_data);
esp_vhci_host_send_packet(hci_cmd_buf, sz);
}
看下其他几家广播数据
-
TI的CC254X,可以自己分析分析,内部有UUID了,让扫描者(手机)提前知道我有那些功能。
static uint8 advertData[] =
{
//自定义的广播数据段
0x03,
GAP_ADTYPE_MANUFACTURER_SPECIFIC,
0,//自定义数据1
0,//自定义数据2
// Flags; this sets the device to use limited discoverable
// mode (advertises for 30 seconds at a time) instead of general
// discoverable mode (advertises indefinitely)
0x02, // length of this data
GAP_ADTYPE_FLAGS,
DEFAULT_DISCOVERABLE_MODE | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
// service UUID, to notify central devices what services are included
// in this peripheral
0x03, // length of this data
GAP_ADTYPE_16BIT_MORE, // some of the UUID's, but not all
LO_UINT16( SIMPLEPROFILE_SERV_UUID ),
HI_UINT16( SIMPLEPROFILE_SERV_UUID ),
};
-
瑞昱的RTL87XX,里面有个0xFF类型的小数据包,下面有他的结构解释图。
static uint8_t advertData[] =
{
0x02,
GAP_ADTYPE_FLAGS,
GAP_ADTYPE_FLAGS_LIMITED | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
0x08, // length
0x09, // type="Complete local name"
'R', 'T', 'L', '8', '7', '6','2',
0x0F, /* length */
0xFF, /* type="GAP_ADTYPE_MANUFACTURER_SPECIFIC" */
0x00, 0x00, /* company Id*/
0x00,0x00,0x00,0x00,0x00,0x00, /*MAC Address*/
0x01, /*TYPE=0x01,0x02,0x03,0x04*/
0x01,0x00, /**/
0x00,0x00,0x00,
};
0xFF主要用于厂商信息和自定义数据,数据区前两个字节是芯片的生产厂家(也可自定义),后面数据自定义。上面图片的长度有问题,不说了。
-
沁恒的CH579,中规中矩,一个flag,一个uuid
static uint8 advertData[] =
{
// flags
0x02,
GAP_ADTYPE_FLAGS,
GAP_ADTYPE_FLAGS_GENERAL | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
// service UUIDs
0x05,
GAP_ADTYPE_16BIT_MORE,
LO_UINT16(HEARTRATE_SERV_UUID),
HI_UINT16(HEARTRATE_SERV_UUID),
LO_UINT16(BATT_SERV_UUID),
HI_UINT16(BATT_SERV_UUID)
};
-
nordic,它就是封装了一层,ble_advertising_init()内部又进行拆解,然后放入协议栈,可能协议栈(不开源)组合成类似的。已注释。
static void advertising_init(void)//广播初始化
{
ret_code_t err_code;
ble_advertising_init_t init;
memset(&init, 0, sizeof(init));
init.advdata.name_type = BLE_ADVDATA_FULL_NAME;//设备名称
init.advdata.include_appearance = true;//外观
init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;//flag:一般可发现模式,不支持BR/EDR
init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
init.advdata.uuids_complete.p_uuids = m_adv_uuids;//首要服务的UUID
init.config.ble_adv_fast_enabled = true;//快速广播模式
init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;//广播间隔
init.config.ble_adv_fast_timeout = APP_ADV_DURATION;//广播持续时间
init.config.ble_adv_fast_timeout = 0;//广播持续时间
init.evt_handler = on_adv_evt;//广播回调
err_code = ble_advertising_init(&m_advertising, &init);//广播模块初始化
APP_ERROR_CHECK(err_code);
ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);//连接设置标记:没啥用,为了以后使用
}
资料下载
市面上nordic的资料最多,我搜集了些,大家需要的话,自行下载。
公众号后台回复关键词【52832】,发送后收到链接即可下载。