蓝牙BLE主机Central讲解三(服务枚举)
前言:
CH582EVT中Central例程修改待连接MAC地址即可与对应的从机建立连接。实现数据传输则是通过枚举特定UUID进而获取透传的handle值。UUID是获取handle值的一种方式,只要能够获取到handle值即可。以下提供两种方式获取handle并进行数据传输。
- 直接抓包已有主机或手机与从机的连接,并进行数据收发,可以获取到收发的handle值;
- 主机枚举从机所有服务并列表对应handle值;
一、抓包获取handle值
二、枚举UUID或者handle值
以下两个函数替换central.c的原有函数
static void centralStartDiscovery(void)
{
centralSvcStartHdl = centralSvcEndHdl = centralCharHdl = 0;
centralDiscState = BLE_DISC_STATE_SVC;
uint8_t ret = 0;
ret = GATT_DiscAllPrimaryServices(centralConnHandle, centralTaskId);
printf("GATT_DiscAllPrimaryServices ret = %x\n", ret);
}
static void centralGATTDiscoveryEvent(gattMsgEvent_t *pMsg)
{
attReadByTypeReq_t req;
if(centralDiscState == BLE_DISC_STATE_SVC)
{
// Service found, store handles
if(pMsg->method == ATT_READ_BY_GRP_TYPE_RSP &&//ATT_FIND_BY_TYPE_VALUE_RSP &&
pMsg->msg.findByTypeValueRsp.numInfo > 0)
{
#if 0
for(uint16_t i = 0; i < pMsg->msg.readByGrpTypeRsp.numGrps; i++)
{
// uuid
printf("uuid = %x", BUILD_UINT16(
pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i +4], \
pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i +5]));
//Primary Service UUID Length
printf("%02d bit x",pMsg->msg.readByGrpTypeRsp.len - 4);
// printf("att len = %d\n", pMsg->msg.readByGrpTypeRsp.len);
printf("start handle:%04x",BUILD_UINT16(
pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i],\
pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i +1]));
// Attribute End Group Handle
printf("end handle:%04x\r\n",BUILD_UINT16(
pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i +2], \
pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i +3]));
}
#endif
}
if((pMsg->method == ATT_READ_BY_GRP_TYPE_RSP &&
pMsg->hdr.status == bleProcedureComplete) ||
(pMsg->method == ATT_ERROR_RSP))
{
// Discover characteristic
centralDiscState = BLE_DISC_STATE_CHAR;
uint8_t ret = GATT_DiscAllChars(centralConnHandle,0x01,0xFFFF,centralTaskId);
PRINT("GATT_DiscAllChars:%02x\r\n",ret);
}
}
else if(centralDiscState == BLE_DISC_STATE_CHAR)
{
// Characteristic found, store handle
if(pMsg->method == ATT_READ_BY_TYPE_RSP &&
pMsg->msg.readByTypeRsp.numPairs > 0)
{
for(unsigned char i = 0; i < pMsg->msg.readByTypeRsp.numPairs ; i++) {
//characteristic properties
uint8_t char_properties = pMsg->msg.readByTypeRsp.pDataList[pMsg->msg.readByTypeRsp.len * i + 2];
uint16_t char_value_handle = BUILD_UINT16(pMsg->msg.readByTypeRsp.pDataList[pMsg->msg.readByTypeRsp.len * i+3], \
pMsg->msg.readByTypeRsp.pDataList[pMsg->msg.readByTypeRsp.len * i + 4]);
//characteristic uuid length
uint8_t char_uuid_length = pMsg->msg.readByGrpTypeRsp.len - 5;
//uuid
uint8_t *char_uuid = &(pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 5]);
PRINT("______________________________\n");
PRINT("char_uuid :");
for(uint8_t i = 0; i < char_uuid_length; i++ ){
printf("%02x ", char_uuid[i]);
}printf("\n");
// PRINT("char_properties :%02x,%s\r\n",char_properties,(char_properties&(GATT_PROP_WRITE|GATT_PROP_WRITE_NO_RSP))?"wite handle":"");
PRINT("char_value_handle:%04x\r\n",char_value_handle);
PRINT("char_uuid :%02d bit\r\n",char_uuid_length);
if(char_properties&(GATT_PROP_WRITE|GATT_PROP_WRITE_NO_RSP)) {
centralCharHdl = char_value_handle;
PRINT("Write handle:%04x\r\n",char_value_handle);
tmos_start_task(centralTaskId, START_READ_OR_WRITE_EVT, 1600);
}
if(char_properties&GATT_PROP_NOTIFY) {
centralCCCDHdl = char_value_handle+1; //通过GATT_DiscAllChars或者handle,noti/indi的handle值需要+1
PRINT("Notify handle:%04x\r\n",char_value_handle);
tmos_start_task(centralTaskId, START_WRITE_CCCD_EVT, 1600);
}
if(char_properties&GATT_PROP_INDICATE) {
centralCCCDHdl = char_value_handle+1; //通过GATT_DiscAllChars或者handle,noti/indi的handle值需要+1
PRINT("Indicate handle:%04x\r\n",char_value_handle);
tmos_start_task(centralTaskId, START_WRITE_CCCD_EVT, 800);
}
}
}
}
}
注意:
使用GATT_DiscAllChars函数或者蓝牙分析仪抓包获取到的noti/indi的handle值需要+1才可以使能成功,write/read没有这方面的限制。使用GATT_ReadUsingCharUUID获取到的handle值直接使能填写使能就可以。
因此在使用枚举的时候,建议失败的时候可以手动+1尝试使能测试。