打印
[其他芯片]

CH573/CC2541 主机 扫描广播 通过UUID过滤设备 & 获取AD TYPE 数据

[复制链接]
3591|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
aoyi|  楼主 | 2021-9-2 14:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一、说明
我们可以通过一些方法,对广播的数据进行分类,查找到自己想要的设备。在CC2541中,采用的是将服务UUID丢到广播数据中,下面说一下这种方法。
当然,我们可以自己直接通过判断ADTYPE为 GAP_ADTYPE_MANUFACTURER_SPECIFIC 0XFF 的数据来进行过滤
特别对于IOS设备来说,要获取设备的MAC,则必须将MAC放到广播数据中

二、主机修改部分
增加查找ADTYPE为服务UUID的函数
//看一下具体的ADTYPE
//#define GAP_ADTYPE_16BIT_COMPLETE               0x03 //!< Service: Complete list of 16-bit UUIDs
//#define GAP_ADTYPE_16BIT_MORE                   0x02 //!< Service: More 16-bit UUIDs available

static bool simpleBLEFindSvcUuid( uint16 uuid, uint8 *pData, uint8 dataLen )
{
  uint8 adLen;
  uint8 adType;
  uint8 *pEnd;

  pEnd = pData + dataLen - 1;

  // While end of data not reached
  while ( pData < pEnd )
  {
    // Get length of next AD item
    adLen = *pData++;
    if ( adLen > 0 )
    {
      adType = *pData;

      // If AD type is for 16-bit service UUID
      if ( adType == GAP_ADTYPE_16BIT_MORE || adType == GAP_ADTYPE_16BIT_COMPLETE )
      {
        pData++;
        adLen--;

        // For each UUID in list
        while ( adLen >= 2 && pData < pEnd )
        {
          // Check for match
          if ( pData[0] == LO_UINT16(uuid) && pData[1] == HI_UINT16(uuid) )
          {
            // Match found
            return TRUE;
          }

          // Go to next
          pData += 2;
          adLen -= 2;
        }

        // Handle possible erroneous extra byte in UUID list
        if ( adLen == 1 )
        {
          pData++;
        }
      }
      else
      {
        // Go to next item
        pData += adLen;
      }
    }
  }

  // Match not found
  return FALSE;
}


使用特权

评论回复
沙发
aoyi|  楼主 | 2021-9-2 14:53 | 只看该作者
在 GAP的 EVENT 中,增加判断
case GAP_DEVICE_INFO_EVENT:
{
          if ( simpleBLEFindSvcUuid( SIMPLEPROFILE_SERV_UUID,
                                     pEvent->deviceInfo.pEvtData,
                                     pEvent->deviceInfo.dataLen ) )
          {
            //向设备发现列表中添加一个设备
            simpleBLEAddDeviceInfo( pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType );
          }
}



这里可以额外加一个东西,若想知道现在扫描到的,符合uuid是对应第几个设备,可以在 simpleBLEAddDeviceInfo中加逻辑判断,其中per_index 就是。
/*********************************************************************
1. @fn      simpleBLEAddDeviceInfo
2.  3. @brief   Add a device to the device discovery result list
4.  5. @return  none
*/
static void simpleBLEAddDeviceInfo( uint8 *pAddr, uint8 addrType )
{
  uint8 i;

  // If result count not at max
  if ( simpleBLEScanRes < DEFAULT_MAX_SCAN_RES )
  {
    // Check if device is already in scan results
    for ( i = 0; i < simpleBLEScanRes; i++ )
    {
      if ( osal_memcmp( pAddr, simpleBLEDevList.addr , B_ADDR_LEN ) )
      {
        per_index = i+1;
        return;
      }
    }

    // Add addr to scan result list
    osal_memcpy( simpleBLEDevList[simpleBLEScanRes].addr, pAddr, B_ADDR_LEN );
    simpleBLEDevList[simpleBLEScanRes].addrType = addrType;

    // Increment scan result count
    simpleBLEScanRes++;
  }
}



获取其他AD TYPE的数据 ,注意,我在这里是借用了GAP_ADTYPE_16BIT_MORE,直接增加其长度 后面加数据了,正常我们要用 GAP_ADTYPE_MANUFACTURER_SPECIFIC 也就是 0xFF 来进行处理
//******************************************************************************
//name:                        Get_Adtype_Data

//introduce:            获取广播数据或扫描应答数据中adType对应的数据

//input parameter:      adType:数据类型
//                      pData:广播包或扫描应答包
//                      dataLen:广播包或扫描应答包的数据长度

//output parameter:     adTypeData_index:对应的adType类型数据的偏移值
//                      adTypeData_len:对应的adType类型数据的长度

//return:                TRUE:找到adType类型的数据
//                      FALSE:没找到adType类型的数据
//******************************************************************************
static bool Get_Adtype_Data( uint8 adType, uint8 *pData, uint8 dataLen, uint8 *adTypeData_index, uint8 *adTypeData_len)
{  
  (void)adTypeData_index;       //防止编译报错
  (void)adTypeData_len;         //防止编译报错

  uint8 adLen;                  //对应数据段的长度
  uint8 *pCurrent;              //当前位置的指针
  uint8 *pEnd;                  //尾指针

  pEnd = pData + dataLen - 1;   //指向包尾

  pCurrent = pData;             //当前指针指向包头

  while ( pCurrent < pEnd )     //判断当前指针是否还未到包尾
  {
    adLen = *pCurrent++;        //获取本段数据段的长度

    if ( adLen > 0 )
    {      
      if ( adType == *pCurrent )                        //如果找到了adType
      {        
        *adTypeData_index = (pCurrent + 1) - pData;     //数据段在数据包中的偏移值
        *adTypeData_len = adLen - 1;                    //数据段长度

        return TRUE;                                    //返回TRUE
      }
      else                                              //没找到adType则指向下一个数据段
      {
        pCurrent += adLen;
      }
    }
  }

  return FALSE;         //本数据串中没有找到adType
}

//**************************************************  
//name:         Hex_To_Str  
//input:        十六进制进制转字符串  
//return:       修改后的字符串  
//**************************************************  
char* Hex_To_Str( uint8 *pHex )  
{   
  char        hex[] = "0123456789ABCDEF";  
  static char str[100];  
  char        *pStr = str;  

  for ( uint8 i = 0; i < sizeof(pHex); i++ )  
  {  
    *pStr++ = hex[*pHex >> 4];  
    *pStr++ = hex[*pHex++ & 0x0F];  
  }  

  return str;  
}  


使用特权

评论回复
板凳
aoyi|  楼主 | 2021-9-2 14:55 | 只看该作者
在 GAP_DEVICE_INFO_EVENT

                #if 0
           {
              //读广播包或扫描应答包的某个数据段
              uint8 adType = GAP_ADTYPE_FLAGS;  //需要扫描的类型数据
              uint8 adTypeData_index = 0;       //数据段在数据包中的偏移值
              uint8 adTypeData_len = 0;         //数据段的长度
              bool status = FALSE;

              status = Get_Adtype_Data( adType,
                                        pEvent->deviceInfo.pEvtData,
                                        pEvent->deviceInfo.dataLen,
                                        &adTypeData_index,
                                        &adTypeData_len);
              if(status == TRUE)
              {
                NPI_PrintString("GAP_ADTYPE_FLAGS:");   
                NPI_WriteTransport((uint8 *)(Hex_To_Str(pEvent->deviceInfo.pEvtData + adTypeData_index)),
                                             adTypeData_len*2);         
                NPI_PrintString("\r\n");            
                NPI_PrintValue("size:", adTypeData_len, 10);            
                NPI_PrintString("\r\n");
              }
            }
                #else
                //读广播包或扫描应答包的某个数据段
                uint8 adType = GAP_ADTYPE_16BIT_MORE;  //需要扫描的类型数据
                uint8 adTypeData_index = 0;       //数据段在数据包中的偏移值
                uint8 adTypeData_len = 0;         //数据段的长度
                bool status = FALSE;

                status = Get_Adtype_Data( adType,
                                          pEvent->deviceInfo.pEvtData,
                                          pEvent->deviceInfo.dataLen,
                                          &adTypeData_index,
                                          &adTypeData_len);
                if(status == TRUE)
                {
                  char str[20];
                  g_SensorValue[per_index-1][0] = *(pEvent->deviceInfo.pEvtData + adTypeData_index+2);
                  g_SensorValue[per_index-1][1] = *(pEvent->deviceInfo.pEvtData + adTypeData_index+3);
                  g_SensorValue[per_index-1][2] = *(pEvent->deviceInfo.pEvtData + adTypeData_index+4);
                  g_SensorValue[per_index-1][3] = *(pEvent->deviceInfo.pEvtData + adTypeData_index+5);
                  g_adc[per_index-1] = 256* (*(pEvent->deviceInfo.pEvtData + adTypeData_index+6)) + *(pEvent->deviceInfo.pEvtData + adTypeData_index+7);

                  sprintf(str, "[%d]:%d.%d,%d.%d,%d",per_index,g_SensorValue[per_index-1][0], g_SensorValue[per_index-1][1],g_SensorValue[per_index-1][2], g_SensorValue[per_index-1][3],g_adc[per_index-1]);
                  NPI_PrintString(str);
                  NPI_PrintString("\r\n");

                  LCD_WRITE_STRING( str, HAL_LCD_LINE_1+per_index );

                }
                 #endif


使用特权

评论回复
地板
aoyi|  楼主 | 2021-9-2 14:55 | 只看该作者
三、从机修改
注意看一下广播数据的格式:

长度 ADTYPE 数据

// GAP - Advertisement data (max size = 31 bytes, though this is
// best kept short to conserve power while advertisting)
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,

  // service UUID, to notify central devices what services are included
  // in this peripheral
  0x09,   // 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 ),
0,
0,
0,
0,
0,
0,

};


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

99

主题

3301

帖子

3

粉丝