PSOC BLE中如何解析广播数据或者扫描响应数据

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

点赞