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

一、说明

我们可以通过一些方法,对广播的数据进行分类,查找到自己想要的设备。在CC2541中,采用的是将服务UUID丢到广播数据中,下面说一下这种方法。
当然,我们可以自己直接通过判断ADTYPE为 GAP_ADTYPE_MANUFACTURER_SPECIFIC 0XFF 的数据来进行过滤
特别对于IOS设备来说,要获取设备的MAC,则必须将MAC放到广播数据中


二、主机修改部分

  1. 增加查找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;
}
  1. 在 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 );
          }
}
  1. 这里可以额外加一个东西,若想知道现在扫描到的,符合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[i].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++;
  }
}
  1. 获取其他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;  
}  

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

三、从机修改

注意看一下广播数据的格式:

长度 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,

};
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于你提供的 URL 模式 `http://localhost/video/{uuid}/{file}.{type}`,你可以通过 ASP.NET MVC5 的路由配置来实现。 首先,在 `RouteConfig.cs` 文件中进行路由配置。你可以使用以下代码来添加一个自定义的路由规则: ```csharp public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "VideoRoute", url: "video/{uuid}/{file}.{type}", defaults: new { controller = "Video", action = "Play" } ); // 其他路由配置... routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } } ``` 在上述代码中,我们添加了一个名为 "VideoRoute" 的路由规则,它匹配了 `video/{uuid}/{file}.{type}` 这样的 URL,并将请求发送到 `VideoController` 的 `Play` 方法。 接下来,在控制器中创建一个名为 `VideoController` 的控制器,并在其中添加一个名为 `Play` 的方法: ```csharp public class VideoController : Controller { public ActionResult Play(string uuid, string file, string type) { // 在这里处理视频播放逻辑,可以使用 uuid、file 和 type 参数 return View(); } } ``` 在上述代码中,我们在 `VideoController` 中创建了一个名为 `Play` 的方法,并将 `uuid`、`file` 和 `type` 作为参数。你可以在此方法中处理视频播放逻辑,并使用这些参数。 现在,当你访问类似于 `http://localhost/video/12345678/video.mp4` 的 URL 时,它将匹配到 `VideoController` 的 `Play` 方法,并将参数 `uuid` 设置为 `12345678`,参数 `file` 设置为 `video`,参数 `type` 设置为 `mp4`。 请确保在路由配置时将自定义的路由规则放在一般规则之前,以确保正确匹配。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值