1、广播数据和扫描响应数据的格式
1-1 广播数据格式
这些都是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
评论区