1、广播数据和扫描响应数据的格式
1-1 广播数据格式
这些都是SIG蓝牙组织规定的标准广播数据格式,一般BLE广播数据的开头都是0x020106,后面接着就是设备名、服务ID等广播数据,从上图中可以看出0x02是长度,0x01是SIG规定的指定值,0x06是这个0x01所代表的标志的具体值。紧接着后面的数据都是遵循这样的格式,即长度+SIG规定的标志值+SIG规定的标志值数据(其中长度等于SIG规定的标志值的长度和SIG规定的标志值所代表的数据长度相加)
1-2 扫描响应数据格式
这些也是SIG蓝牙组织规定的标准扫描响应数据格式,格式跟广播数据的格式是一样的。
这些都是SIG蓝牙组织规定的标准广播数据格式,一般BLE广播数据的开头都是0x020106,后面接着就是设备名、服务ID等广播数据,从上图中可以看出0x02是长度,0x01是SIG规定的指定值,0x06是这个0x01所代表的标志的具体值。紧接着后面的数据都是遵循这样的格式,即长度+SIG规定的标志值+SIG规定的标志值数据(其中长度等于SIG规定的标志值的长度和SIG规定的标志值所代表的数据长度相加)
1-2 扫描响应数据格式
这些也是SIG蓝牙组织规定的标准扫描响应数据格式,格式跟广播数据的格式是一样的。
2、广播数据和扫描响应数据分析
从上面的1章节中可以看到不管是广播数据还是扫描响应数据,其数据格式都是一样的,都是长度+SIG规定的标志值+SIG规定的标志值所表示的数据(其中长度等于SIG规定的标志值的长度和SIG规定的标志值所代表的数据长度相加)。因此,如果我们要分析广播数据或者扫描响应数据,只要判断SIG规定的标志值是什么就可以知道,广播的数据里面有什么信息。其中SIG规定的标志值,如下表所示:
| SIG规定的标志 | CYPRESS规定的枚举名 | 枚举值 |
| Flags | CYBLE_GAP_ADV_FLAGS | 0x01 |
| Incomplete List of 16-bit Service Class UUIDs | CYBLE_GAP_ADV_INCOMPL_16UUID | 0x02 |
| Complete List of 16-bit Service Class UUIDs | CYBLE_GAP_ADV_COMPL_16UUID | 0x03 |
| Incomplete List of 32-bit Service Class UUIDs | CYBLE_GAP_ADV_INCOMPL_32_UUID | 0x04 |
| Complete List of 32-bit Service Class UUIDs | CYBLE_GAP_ADV_COMPL_32_UUID | 0x05 |
| Incomplete List of 128-bit Service Class UUIDs | CYBLE_GAP_ADV_INCOMPL_128_UUID | 0x06 |
| Complete List of 128-bit Service Class UUIDs | CYBLE_GAP_ADV_COMPL_128_UUID | 0x07 |
| Shortened Local Name | CYBLE_GAP_ADV_SHORT_NAME | 0x08 |
| Complete Local Name | CYBLE_GAP_ADV_COMPL_NAME | 0x09 |
| Tx Power Level | CYBLE_GAP_ADV_TX_PWR_LVL | 0x0A |
| Class of Device | CYBLE_GAP_ADV_CLASS_OF_DEVICE | 0x0D |
| Simple Pairing Hash C | CYBLE_GAP_ADV_SMPL_PAIR_HASH_C | 0x0E |
| Simple Pairing Randomizer R | CYBLE_GAP_ADV_SMPL_PAIR_RANDOM_R | 0x0F |
| Device ID | CYBLE_GAP_ADV_DEVICE_ID | 0x10 |
| Security Manager TK Value | CYBLE_GAP_ADV_SCRT_MNGR_TK_VAL | 0x10 |
| Security Manager Out of Band Flags | CYBLE_GAP_ADV_SCRT_MNGR_OOB_FLAGS | 0x11 |
| Slave Connection Interval Range | CYBLE_GAP_ADV_SLAVE_CONN_INTRV_RANGE | 0x12 |
| List of 16-bit Service Solicitation UUIDs | CYBLE_GAP_ADV_SOLICIT_16UUID | 0x14 |
| List of 128-bit Service Solicitation UUIDs | CYBLE_GAP_ADV_SOLICIT_128UUID | 0x15 |
| Service Data - 16-bit UUID | CYBLE_GAP_ADV_SRVC_DATA_16UUID | 0x16 |
| Public Target Address | CYBLE_GAP_ADV_PUBLIC_TARGET_ADDR | 0x17 |
| Random Target Address | CYBLE_GAP_ADV_RANDOM_TARGET_ADDR | 0x18 |
| Appearance | CYBLE_GAP_ADV_APPEARANCE | 0x19 |
| Advertising Interval | CYBLE_GAP_ADV_ADVERT_INTERVAL | 0x1A |
| LE Bluetooth Device Address | CYBLE_GAP_ADV_LE_BT_DEVICE_ADDR | 0x1B |
| LE Role | CYBLE_GAP_ADV_LE_ROLE | 0x1C |
| Simple Pairing Hash C-256 | CYBLE_GAP_ADV_SMPL_PAIR_HASH_C256 | 0x1D |
| Simple Pairing Randomizer R-256 | CYBLE_GAP_ADV_SMPL_PAIR_RANDOM_R256 | 0x1E |
| List of 32-bit Service Solicitation UUIDs | CYBLE_GAP_ADV_SOLICIT_32UUID | 0x1F |
| Service Data - 32-bit UUID | CYBLE_GAP_ADV_SRVC_DATA_32UUID | 0x20 |
| Service Data - 128-bit UUID | CYBLE_GAP_ADV_SRVC_DATA_128UUID | 0x21 |
| 3D Information Data | CYBLE_GAP_ADV_3D_INFO_DATA | 0x3D |
3、广播数据和扫描响应数据分析---代码实现
/******************************************************************************
* Function Name: Parser_adv_data_scan_data
***************************************************************************//**
*
* 解析空中广播数据或者扫描响应数据
* \param pdata:指向空中广播数据或者扫描响应数据的指针
* \param total_len:空中广播数据或者扫描响应数据的长度
* \return
* None
*
******************************************************************************/
void Parser_adv_data_scan_data(uint8_t *pdata, uint8_t total_len)
{
uint8_t* pend=pdata+total_len;
uint8_t DeviceName[DeviceNameLength];
uint8_t length=0;
uint8_t i,ServiceCount;
pdata++;
while(pend>pdata)
{
// pdata-1表示的是对应内容的长度,pdata+1表示的是对应的内容
switch(*pdata)
{
case CYBLE_GAP_ADV_FLAGS:
// printf("Flags is %d\r\n",*(pdata+1));
// 下一个SIG规定的标志的位置
length=1+*(pdata-1);
break;
//比如有几个服务,那么就有几个服务的UUID,广播中只要没有把全部的服务UUID,就是CYBLE_GAP_ADV_INCOMPL_16UUID
case CYBLE_GAP_ADV_INCOMPL_16UUID:
// 服务ID的数量
ServiceCount=(*(pdata-1)-1)/2;
for(i=0;i<ServiceCount;i++)
{
switch(i)
{
case 0:
printf("Service1 ID is: 0x%02X%02X\r\n",*(pdata+i+2),*(pdata+i+1));
break;
case 1:
printf("Service2 ID is: 0x%02X%02X\r\n",*(pdata+i+3),*(pdata+i+2));
break;
case 2:
printf("Service3 ID is: 0x%02X%02X\r\n",*(pdata+i+4),*(pdata+i+3));
break;
case 3:
printf("Service4 ID is: 0x%02X%02X\r\n",*(pdata+i+5),*(pdata+i+4));
break;
case 4:
printf("Service5 ID is: 0x%02X%02X\r\n",*(pdata+i+6),*(pdata+i+5));
break;
case 5:
printf("Service6 ID is: 0x%02X%02X\r\n",*(pdata+i+7),*(pdata+i+6));
break;
case 6:
printf("Service7 ID is: 0x%02X%02X\r\n",*(pdata+i+8),*(pdata+i+7));
break;
case 7:
printf("Service8 ID is: 0x%02X%02X\r\n",*(pdata+i+9),*(pdata+i+8));
break;
case 8:
printf("Service9 ID is: 0x%02X%02X\r\n",*(pdata+i+10),*(pdata+i+9));
break;
case 9:
printf("Service10 ID is: 0x%02X%02X\r\n",*(pdata+i+11),*(pdata+i+10));
break;
default:
break;
}
}
length=1+*(pdata-1);
break;
case CYBLE_GAP_ADV_COMPL_16UUID:
ServiceCount=(*(pdata-1)-1)/2;
for(i=0;i<ServiceCount;i++)
{
switch(i)
{
case 0:
printf("Service1 ID is: 0x%02X%02X\r\n",*(pdata+i+2),*(pdata+i+1));
break;
case 1:
printf("Service2 ID is: 0x%02X%02X\r\n",*(pdata+i+3),*(pdata+i+2));
break;
case 2:
printf("Service3 ID is: 0x%02X%02X\r\n",*(pdata+i+4),*(pdata+i+3));
break;
case 3:
printf("Service4 ID is: 0x%02X%02X\r\n",*(pdata+i+5),*(pdata+i+4));
break;
case 4:
printf("Service5 ID is: 0x%02X%02X\r\n",*(pdata+i+6),*(pdata+i+5));
break;
case 5:
printf("Service6 ID is: 0x%02X%02X\r\n",*(pdata+i+7),*(pdata+i+6));
break;
case 6:
printf("Service7 ID is: 0x%02X%02X\r\n",*(pdata+i+8),*(pdata+i+7));
break;
case 7:
printf("Service8 ID is: 0x%02X%02X\r\n",*(pdata+i+9),*(pdata+i+8));
break;
case 8:
printf("Service9 ID is: 0x%02X%02X\r\n",*(pdata+i+10),*(pdata+i+9));
break;
case 9:
printf("Service10 ID is: 0x%02X%02X\r\n",*(pdata+i+11),*(pdata+i+10));
break;
default:
break;
}
}
length=1+*(pdata-1);
break;
case CYBLE_GAP_ADV_INCOMPL_32_UUID:
break;
case CYBLE_GAP_ADV_COMPL_32_UUID:
break;
case CYBLE_GAP_ADV_INCOMPL_128_UUID:
break;
case CYBLE_GAP_ADV_COMPL_128_UUID:
break;
case CYBLE_GAP_ADV_SHORT_NAME:
//提前初始化DeviceName指针的前面20个Byte
memset(DeviceName,0,sizeof(DeviceName));
memcpy(DeviceName,(pdata+1),*(pdata-1)-1);
printf("Shortened Local Name is: %s\r\n",DeviceName);
length=1+*(pdata-1);
break;
case CYBLE_GAP_ADV_COMPL_NAME:
//提前初始化DeviceName指针的前面20个Byte
memset(DeviceName,0,sizeof(DeviceName));
memcpy(DeviceName,(pdata+1),*(pdata-1)-1);
printf("Complete Local Name is: %s\r\n",DeviceName);
length=1+*(pdata-1);
break;
case CYBLE_GAP_ADV_TX_PWR_LVL:
printf("Tx Power Level is: %ddbm\r\n",*(pdata+1));
length=1+*(pdata-1);
break;
case CYBLE_GAP_ADV_CLASS_OF_DEVICE:
break;
case CYBLE_GAP_ADV_SMPL_PAIR_HASH_C:
break;
case CYBLE_GAP_ADV_SMPL_PAIR_RANDOM_R:
break;
//CYBLE_GAP_ADV_SCRT_MNGR_TK_VAL的枚举值
//跟CYBLE_GAP_ADV_DEVICE_ID相同
case CYBLE_GAP_ADV_DEVICE_ID:
break;
case CYBLE_GAP_ADV_SCRT_MNGR_OOB_FLAGS:
break;
case CYBLE_GAP_ADV_SLAVE_CONN_INTRV_RANGE:
break;
case CYBLE_GAP_ADV_SOLICIT_16UUID:
break;
case CYBLE_GAP_ADV_SOLICIT_128UUID:
break;
case CYBLE_GAP_ADV_SRVC_DATA_16UUID:
break;
case CYBLE_GAP_ADV_PUBLIC_TARGET_ADDR:
break;
case CYBLE_GAP_ADV_RANDOM_TARGET_ADDR:
break;
case CYBLE_GAP_ADV_APPEARANCE:
break;
case CYBLE_GAP_ADV_ADVERT_INTERVAL:
break;
case CYBLE_GAP_ADV_LE_BT_DEVICE_ADDR:
break;
case CYBLE_GAP_ADV_LE_ROLE:
break;
case CYBLE_GAP_ADV_SMPL_PAIR_HASH_C256:
break;
case CYBLE_GAP_ADV_SMPL_PAIR_RANDOM_R256:
break;
case CYBLE_GAP_ADV_SOLICIT_32UUID:
break;
case CYBLE_GAP_ADV_SRVC_DATA_32UUID:
break;
case CYBLE_GAP_ADV_SRVC_DATA_128UUID:
break;
case CYBLE_GAP_ADV_3D_INFO_DATA:
break;
default:
break;
}
pdata+=length;
}
}
4、空中的广播数据或扫描响应数据的处理---代码实现
当我们需要处理周边BLE设备的广播数据或者扫描响应数据时,可以这样处理如下:
/******************************************************************************
* Function Name: HandleScanDevices
***************************************************************************//**
*
* 处理扫描到的周边BLE设备
*
* \return
* None
*
******************************************************************************/
void HandleScanDevices(CYBLE_GAPC_ADV_REPORT_T* ScanReport)
{
// printf("Advertising or Scan Response Data is 0x%02X%02X%02X%02X%02X%02X\r\n",
// );
uint8_t i=0;
// 第一次扫描时,保存第一次扫描到的设备地址
if(flag^1)
{
flag=1;
// if(CYBLE_GAPC_SCAN_RSP==ScanReport->eventType)
// {
//
// printf("*************************************************************\r\n");
// printf("Scan Response Data:\r\n");
// Parser_adv_data_scan_data(ScanReport->data,ScanReport->dataLen);
// return;
// }
if(CYBLE_GAPC_CONN_UNDIRECTED_ADV==ScanReport->eventType)
{
DeviceCount++;
memcpy(DeviceList+(DeviceCount-1)*6,ScanReport->peerBdAddr,6);
printf("*************************************************************\r\n");
printf("Advertising Data:\r\n");
printf("Mac Address of the device advertising is: 0x%02X%02X%02X%02X%02X%02X\r\n",
ScanReport->peerBdAddr[5],
ScanReport->peerBdAddr[4],
ScanReport->peerBdAddr[3],
ScanReport->peerBdAddr[2],
ScanReport->peerBdAddr[1],
ScanReport->peerBdAddr[0]
);
Parser_adv_data_scan_data(ScanReport->data,ScanReport->dataLen);
return;
}
}
// 循环比较扫描到的地址是不是之前扫描过的,如果有之前扫描过的地址,则马上返回,否则马上把新的地址打印出来
for(i=0;ipeerBdAddr,DeviceList+i*6,6)==0)
{
// NewAddr=0;
return;
}
}
DeviceCount++;
memcpy(DeviceList+(DeviceCount-1)*6,ScanReport->peerBdAddr,6);
// if(CYBLE_GAPC_SCAN_RSP==ScanReport->eventType)
// {
// printf("*************************************************************\r\n");
// printf("Scan Response Data:\r\n");
// }
if(CYBLE_GAPC_CONN_UNDIRECTED_ADV==ScanReport->eventType)
{
printf("*************************************************************\r\n");
printf("Advertising Data:\r\n");
printf("Mac Address of the device advertising is: 0x%02X%02X%02X%02X%02X%02X\r\n",
ScanReport->peerBdAddr[5],
ScanReport->peerBdAddr[4],
ScanReport->peerBdAddr[3],
ScanReport->peerBdAddr[2],
ScanReport->peerBdAddr[1],
ScanReport->peerBdAddr[0]
);
}
Parser_adv_data_scan_data(ScanReport->data,ScanReport->dataLen);
}
转载至:http://ececdaf4.wiz03.com/share/s/3IXdHQ3P5k-v2nS-fl33REKL3CfYbM3VQ4hA2IX99w1e3G4S
评论区