广播数据(advertData)和扫描响应(scanRspData)
在典型的蓝牙BLE(Bluetooth Low Energy )系统中,从机设备广播数据让所有主机设备知道它是一个可连接的设备。接收到广播数据的主机,发送一个扫描请求(scan request)给从机,从机再返回扫描请求。
首先看一下广播数据,下面是广播包的数据定义:
static uint8 advertData[] =
{
// 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,
// in this peripheral
0x1A, // length of this data 26byte
GAP_ADTYPE_MANUFACTURER_SPECIFIC,
/*Apple Pre-Amble*/
0x4C,
0x00,
0x02,
0x15,
/*Device UUID (16 Bytes)*/
0x4A, 0xA8, 0x31, 0x6E, 0x88, 0xE8, 0x96, 0x78, 0xCA, 0x74, 0xDE, 0x07, 0x19, 0x8A, 0xB3, 0x9B,
// 0x2A, 0x97, 0x20, 0x4E, 0x68, 0xB8, 0x86, 0x18, 0xC8, 0x34, 0xDD, 0x67, 0x79, 0x85, 0x43, 0x8B,
//0xe2, 0xc5, 0x6d, 0xb5, 0xdf, 0xfb, 0x48, 0xd2, 0xb0, 0x60, 0xd0, 0xf5, 0xa7, 0x10, 0x96, 0xe0,
/*Major Value (2 Bytes)*/
0x00,0x00,
/*Minor Value (2 Bytes)*/
0x00,0x00,
/*Measured Power*/
0xCD
};
advertData[]
数组中第一个字节
0x1A
代表此段数据的长度,第二个字节为广播的数据模式,从第三个字节到第一个字节指定的长度为止,为有效的数据。以此类推。此广播数据中包含了从设备的广播模式和
UUID
。这个是ibeacon的广播数据定义。
扫描响应的数据定义如下:
// GAP - SCAN RSP data (max size = 31 bytes)
static uint8 scanRspData[] =
{
// complete name
0x05, // length of this data
GAP_ADTYPE_LOCAL_NAME_COMPLETE,
'N', 'A', 'M', 'E',
// connection interval range
0x05, // length of this data
GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,
LO_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ), // 100ms
HI_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ),
LO_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ), // 1s
HI_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ),
// Tx power level
0x02, // length of this data
GAP_ADTYPE_POWER_LEVEL,
0 // 0dBm
};
我们平时打开手机扫描蓝牙设备时扫描到的设备的名字,就是在这里进行定义的,所以如果
想获取设备名称,就要获得扫描回应
scanRspData[]
的数据,并从中分离出类型为
GAP_ADTYPE_LOCAL_NAME_COMPLETE
的数据。
那么,如何解析广播数据和扫描响应包呢?
主机回调函数simpleBLECentralEventCB( gapCentralRoleEvent_t *pEvent )是当发生某一件事时调用的函数,当相应事件发生时,分析出是哪个事件并进行相应的处理。GAP_DEVICE_INFO_EVENT是获取从机设备信息的处理事件,GAP_DEVICE_DISCOVERY_EVENT是设备发现事件。在GAP_DEVICE_INFO_EVENT事件中有两个不同数据,广播数据和扫描回应数据,这就是我们要解析的部分。我们先来看一下主机回调函数simpleBLECentralEventCB( gapCentralRoleEvent_t *pEvent )传递的gapCentralRoleEvent_t的参数指针。其结构为:
/**
* Central Event Structure
*/
typedef union
{
gapEventHdr_t gap; //!< GAP_MSG_EVENT and status.
gapDeviceInitDoneEvent_t initDone; //!< GAP initialization done.
gapDeviceInfoEvent_t deviceInfo; //!< Discovery device information event structure.
gapDevDiscEvent_t discCmpl; //!< Discovery complete event structure.
gapEstLinkReqEvent_t linkCmpl; //!< Link complete event structure.
gapLinkUpdateEvent_t linkUpdate; //!< Link update event structure.
gapTerminateLinkEvent_t linkTerminate; //!< Link terminated event structure.
} gapCentralRoleEvent_t;
其中有一个deviceInfo成员,为设备信息相关的数据,其类型为gapDeviceInitDoneEvent_t,结构定义如下:
/**
* GAP_DEVICE_INFO_EVENT message format. This message is sent to the
* app during a Device Discovery Request, when a new advertisement or scan
* response is received.
*/
typedef struct
{
osal_event_hdr_t hdr; //!< GAP_MSG_EVENT and status
uint8 opcode; //!< GAP_DEVICE_INFO_EVENT
uint8 eventType; //!< Advertisement Type: @ref GAP_ADVERTISEMENT_REPORT_TYPE_DEFINES
uint8 addrType; //!< address type: @ref GAP_ADDR_TYPE_DEFINES
uint8 addr[B_ADDR_LEN]; //!< Address of the advertisement or SCAN_RSP
int8 rssi; //!< Advertisement or SCAN_RSP RSSI
uint8 dataLen; //!< Length (in bytes) of the data field (evtData)
uint8 *pEvtData; //!< Data field of advertisement or SCAN_RSP
} gapDeviceInfoEvent_t;
在这个结构体里,有定义广播的类型,以及具体指向广播数据或者扫描响应数据段的指针和数据长度。我们可以通过eventType来区分*pEvtData的数据具体为广播数据还是扫描响应数据。通过主机回调函数simpleBLECentralEventCB( gapCentralRoleEvent_t *pEvent ),我们再进一步来解析eventType和*pEvtData。
case GAP_DEVICE_INFO_EVENT:
{
if(pEvent->deviceInfo.eventType == GAP_ADRPT_SCAN_RSP ) //scan_rsp
{
pEvent->deviceInfo.dataLen; //扫描回应数据长度
pEvent->deviceInfo.pEvtData; //扫描回应数据
}
if(pEvent->deviceInfo.eventType == GAP_ADRPT_ADV_IND ) //adv
{
pEvent->deviceInfo.dataLen; //广播数据长度
pEvent->deviceInfo.pEvtData; //广播数据
}
}
Break;
欢迎大家扫描下方二维码关注我的个人微信公众号,一起交流学习,谢谢。