一、说明
我们可以通过一些方法,对广播的数据进行分类,查找到自己想要的设备。在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;
}
- 在 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[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++;
}
}
- 获取其他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,
};