Other Parts Discussed in Thread: SYSCONFIG, , CC2541
Tool/software:
I need to read a CTS value(s) from a device.
So far I used the following:
1. After a link was established calling the following
uint8_t uuid[2] = {0x05, 0x18}; // CTS Service GATT_DiscPrimaryServiceByUUID(gapEstMsg->connectionHandle,uuid,2,BLEAppUtil_getSelfEntity());
2. Then Getting a ATT_FIND_BY_TYPE_VALUE_RSP event in GATT_EventHandler() function in app_data.c
At this event, I parsed the start and end handles of the service and called the
bStatus_t bstatus = GATT_DiscAllChars(gattMsg->connHandle, lastStart, lastEnd, BLEAppUtil_getSelfEntity());
To get the CTS characteristics.
3. This resulted a new ATT_READ_BY_TYPE_RSP event in GATT_EventHandler() function.
Since the CTS service has more then one char. I looped throughout the data returned to this function until I identify the
characteristics UUID I am interested in which is 0x2a2b
4. At that point I could not find(figure) out how to extract the CTS data, which should be an array of 10 bytes (as far as I understand)
In the code below I just print out the bytes found in in the pDataList , which I index like an array. The values I get makes no sense to me as CTS Data
so I probably should look another place.
Optimally the example I am looking for wile use the GATT_DiscCharsByUUID instaed of GATT_DiscAllChars()
Thanks
/*********************************************************************
* @fn GATT_EventHandler
*
* @brief The purpose of this function is to handle GATT events
* that rise from the GATT and were registered in
* @ref BLEAppUtil_RegisterGAPEvent
*
* @param event - message event.
* @param pMsgData - pointer to message data.
*
* @return none
*/
static void GATT_EventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData)
{
gattMsgEvent_t *gattMsg = ( gattMsgEvent_t * )pMsgData;
switch ( gattMsg->method )
{
case ATT_FLOW_CTRL_VIOLATED_EVENT:
{
MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE, 0, "GATT status: ATT flow control is violated");
}
break;
case ATT_MTU_UPDATED_EVENT:
{
MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE, 0, "GATT status: ATT MTU update to %d",
gattMsg->msg.mtuEvt.MTU);
}
break;
///////////////////////////
case ATT_FIND_BY_TYPE_VALUE_RSP:
{
uint16_t lastStart;
uint16_t lastEnd;
attFindByTypeValueRsp_t att = (attFindByTypeValueRsp_t)gattMsg->msg.findByTypeValueRsp;
/* We need to build the 16-bit handles that we received when we discovered the service. */
for (uint8_t i = 0; i < att.numInfo; i++)
{
/* NOTE: We are in little endian, but the BUILD_UINT16 macro accounts for this */
/* The first two bytes will be start handle */
uint16_t attHandle = BUILD_UINT16(att.pHandlesInfo[i * 4], att.pHandlesInfo[i * 4 + 1]);
/* The second two bytes will be the end handle */
uint16_t endHandle = BUILD_UINT16(att.pHandlesInfo[i * 4 + 2], att.pHandlesInfo[i * 4 + 3]);
lastStart = attHandle;
lastEnd = endHandle;
MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0, "start: %x", attHandle);
display_index++;
MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0, "end: %x", endHandle);
display_index++;
}
/* This delay can be replaced with a timer, or applicaton event that then calls GATT_DiscAllChars.
* Without a delay, timer, or separate application event, this call will fail since the stack is busy
* processing messages during this time. For the sake of the example, a delay was used, but
* it does not have to be an explicit delay.
*/
ClockP_sleep(2);
////////////////////////////////////////
bStatus_t bstatus = GATT_DiscAllChars(gattMsg->connHandle,
lastStart,
lastEnd,
BLEAppUtil_getSelfEntity());
if (bstatus != SUCCESS)
{
MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0,"CharsDiscAll FAILED!!!");
display_index++;
}else{
MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0,"CharsDiscAll SUCCEDDED");
display_index++;
}
}
break;
////////////////////
case ATT_READ_BY_TYPE_RSP:
{
attReadByTypeRsp_t att = (attReadByTypeRsp_t)gattMsg->msg.readByTypeRsp;
MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0, "ATT_READ_BY_TYPE_RSP len: %d numPairs: %d", att.len, att.numPairs);
display_index++;
for (uint8_t i = 0; i < att.numPairs; i++)
{
/* This is the Attribute Handle */
uint16_t attHandle = BUILD_UINT16(att.pDataList[i * att.len + 0], att.pDataList[i * att.len + 1]);
MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0,"ATT Handle: %x", attHandle);
display_index++;
/* This is the index to the beginning of the value data AFTER the attribute handle */
uint8_t index = i * att.len + 2;
/* The characteristic value data */
uint8_t data1 = att.pDataList[index]; // Bit field of characteristic properties
uint8_t data2 = att.pDataList[index + 1]; // Second Byte of Characteristic Value Handle
uint8_t data3 = att.pDataList[index + 2]; // First Byte of Characteristic Value Handle
/* If we were using 128-bit Bluetooth UUIDs, then we would have 16 of these instead of 2. */
uint8_t data4 = att.pDataList[index + 3]; // Second byte of UUID
uint8_t data5 = att.pDataList[index + 4]; // First byte of UUID
uint16_t UUID=(uint16_t)(data5<<8)+data4;
/* Since we are in little endian, we have to reverse the order to make the values make sense. */
MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0,"UUID: [%x] %x%x Val Handle: %x%x Properties: %x",UUID, data5, data4, data3, data2, data1);
display_index++;
MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0,"Data items: %d ",att.len*att.numPairs );
if(UUID==0x2a2b){
for(uint16_t i=0;i< att.len*att.numPairs;i++){
MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0,"[%d] ",att.pDataList[i] );
}
}
}
}
break;
////////////////////
case ATT_WRITE_REQ: //ATT_READ_BY_TYPE_RSP:
{
attReadByTypeRsp_t att = (attReadByTypeRsp_t)gattMsg->msg.readByTypeRsp;
if (att.numPairs == 0)
break;
MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0, "ATT_READ_BY_TYPE_RSP");
display_index++;
MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0, "Length: %d : Number of Pairs: %d", att.len, att.numPairs);
display_index++;
for (uint8_t i = 0; i < att.numPairs; i++)
{
/* This is the Attribute Handle */
uint16_t attHandle = BUILD_UINT16(att.pDataList[i * att.len + 0], att.pDataList[i * att.len + 1]);
/* This is the index to the beginning of the value data AFTER the attribute handle */
uint8_t index = i * att.len + 2;
/* The characteristic value data */
uint8_t char_properties = att.pDataList[index]; // Bit field of characteristic properties
uint16_t value_handle = BUILD_UINT16(att.pDataList[index + 1], att.pDataList[index + 2]);
MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0,
" ATT Handle: %x : Value Handle %x : Properties : %x",
attHandle, value_handle, char_properties);
display_index++;
if (att.len - 5 == 2)
{
uint16_t char_16bit_uuid = BUILD_UINT16(att.pDataList[index + 3], att.pDataList[index + 4]);
MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0," UUID: %x", char_16bit_uuid);
display_index++;
}
else
{
MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0," UUID: ");
for (uint8_t j = 0; j < 16; j++)
{
MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, j + 10, "%x", att.pDataList[index + 3 + j]);
}
display_index++;
}
}
}
break;
///////////////////////////////////////////
default:
break;
}
}