Read Characteristic from Server

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
user_1528391
Level 4
Level 4
First like received First like given

Hi, i'm trying to read a characteristic from server(peripheral). I found the CyBle_GattcReadUsingCharacteristicUuid function in API Document. Is there any example implementation of it? I'm getting CYBLE_ERROR_INVALID_PARAMETER error when i call that function. Can anyone give me an example project or something about this? I do not need notifications, write etc. Just wanna read a characteristic( which i know the uuid of it) from a server. Below is the code fragment which gave me the CYBLE_ERROR_INVALID_PARAMETER error:

   

.

   

.

   

case CYBLE_EVT_GATTC_DISCOVERY_COMPLETE:

   


readByTypeReqParam.uuid = 0x2A29u;                           // Characteristic UUID for Manufacturer Name String at Device Information Service
readByTypeReqParam.uuidFormat = 0x01;                      // 16 Bit UUID Format
            
apiResult = CyBle_GattcReadUsingCharacteristicUuid(connHandle,&readByTypeReqParam);

   

.

   

.

   

.

1 Solution
user_1528391
Level 4
Level 4
First like received First like given

Finally i got this work. It took much time because i could not find an example project about this. I added some part of the code to below, so maybe someone needs this too.

   

 

   

CYBLE_GATTC_READ_BY_TYPE_REQ_T          readByTypeReqParam;
CYBLE_GATTC_READ_BY_TYPE_RSP_PARAM_T    readResponse;
CYBLE_GATT_ATTR_HANDLE_RANGE_T          range;
CYBLE_UUID_T                            uuid;
CYBLE_API_RESULT_T                      apiResult;

   

case CYBLE_EVT_GATTC_DISCOVERY_COMPLETE:
            printf("\r\nDiscovery complete.\r\n");
            
            range.startHandle   = 0x0001;
            range.endHandle     = 0x0030;
            uuid.uuid16         = 0x2A00; 

   

            readByTypeReqParam.range = range;
            readByTypeReqParam.uuid = uuid;
            readByTypeReqParam.uuidFormat = 0x01;

   

            apiResult = CyBle_GattcReadUsingCharacteristicUuid(connHandle,&readByTypeReqParam);
            if ( apiResult == CYBLE_ERROR_OK )
                printf("CYBLE_ERROR_OK\r\n");
            else
                printf("CYBLE_ERROR_OCCURED\r\n");

   

             break;
            
        case CYBLE_EVT_GATTC_READ_BY_TYPE_RSP:
            
            readResponse = *(CYBLE_GATTC_READ_BY_TYPE_RSP_PARAM_T *) eventParam;
            for( i=2 ; i < readResponse.attrData.length; i++)
            {
                printf("%c\r\n",readResponse.attrData.attrValue);
            }
            break;

View solution in original post

6 Replies
user_1528391
Level 4
Level 4
First like received First like given

I also created a case for this situation but it takes a little long to get an answer. I need to get this work, can anyone help me please? 

0 Likes
user_1528391
Level 4
Level 4
First like received First like given

Finally i got this work. It took much time because i could not find an example project about this. I added some part of the code to below, so maybe someone needs this too.

   

 

   

CYBLE_GATTC_READ_BY_TYPE_REQ_T          readByTypeReqParam;
CYBLE_GATTC_READ_BY_TYPE_RSP_PARAM_T    readResponse;
CYBLE_GATT_ATTR_HANDLE_RANGE_T          range;
CYBLE_UUID_T                            uuid;
CYBLE_API_RESULT_T                      apiResult;

   

case CYBLE_EVT_GATTC_DISCOVERY_COMPLETE:
            printf("\r\nDiscovery complete.\r\n");
            
            range.startHandle   = 0x0001;
            range.endHandle     = 0x0030;
            uuid.uuid16         = 0x2A00; 

   

            readByTypeReqParam.range = range;
            readByTypeReqParam.uuid = uuid;
            readByTypeReqParam.uuidFormat = 0x01;

   

            apiResult = CyBle_GattcReadUsingCharacteristicUuid(connHandle,&readByTypeReqParam);
            if ( apiResult == CYBLE_ERROR_OK )
                printf("CYBLE_ERROR_OK\r\n");
            else
                printf("CYBLE_ERROR_OCCURED\r\n");

   

             break;
            
        case CYBLE_EVT_GATTC_READ_BY_TYPE_RSP:
            
            readResponse = *(CYBLE_GATTC_READ_BY_TYPE_RSP_PARAM_T *) eventParam;
            for( i=2 ; i < readResponse.attrData.length; i++)
            {
                printf("%c\r\n",readResponse.attrData.attrValue);
            }
            break;

ViTi_1549261
Level 3
Level 3
First like received

Hi,

   

 

   

This code snippet was helpful for me to, so I would like to say thanks!

   

What was a principle of defining following values:

   

 range.startHandle   = 0x0001;
 range.endHandle     = 0x0030;

0 Likes
user_1528391
Level 4
Level 4
First like received First like given

Your welcome, I'm glad that it helped you out!

   

Handles are the way the server knows it's services&characteristics. It does not call them with their UUID, it calls them with the handles instead. When you add a service&characteristic to your BLE Component. PSOC Creator generates the necessary files for it which also contains the attribute handle definitions.

   

After the end of discovery, startHandle and endHandle specifies which interval will be searched inside of the discovered database. If you use it like this:

   

 

   

range.startHandle   = 0x0001;
range.endHandle     = 0xFFFF;

   

Now the client will search the entire database of the server, after the discovery. You can narrow down the search interval if you know the handle number of the characteristic which you want to scan. You can find the handles of characteristics for the server database in "CYBLE.h" or "BLE.h" files from generated sources. For example, I have a custom characteristic in my project. The characteristic handle for the custom characteristic is in the "CYBLE_Custom.h" file, like below:

   

 

   

#define CYBLE_CONTAINER_ID_READSTATE_CHAR_HANDLE   (0x0019u) /* Handle of readState characteristic */

   

 

   

I had wanted to be sure about I'm scanning for the right interval. So I searched for the entire database, but I guess I could scan that characteristic like below code snippet too:

   

 

   

 range.startHandle   = 0x0019;
 range.endHandle     = 0x0019;

   

Note that this code snippet runs in the central side which scans the server of the peripheral device. You must find the attribute handle from the server(peripheral project) and scan it in the central project.

0 Likes
Anonymous
Not applicable

Hi,

   

I'm facing the exact same problem. I have created a custom profile all I want is to read. My UUID is 128 bit. Data I'm trying to read is utf8s.

   

I'll be glad if you could help.

   

Regards,

   

Akshit

0 Likes

After you connect to the peer device, the ble subsystem updates the ble state as CYBLE_EVT_GAP_DEVICE_CONNECTED. You need to start discovering the peripheral device server. After the discovery ends, the ble subsystem updates the ble state as CYBLE_EVT_GATTC_DISCOVERY_COMPLETE. Now you have the information of the server of the peripheral device. Note that the client or peripheral identifies the database(services, characteristics etc.) with their handles. So if you want to read a characteristic after the discovery ends, you can specify a handle range to let the client(your central device) search that range in the server. You can find the corresponding handle numbers in the CYBLE_Custom.h file of the peripheral project for each characteristic of the peripheral device. Something like this:

   

 

   

#define CYBLE_CUSTOMCHAR1_CHAR_HANDLE   (0x0019u) /* Handle of CUSTOMCHAR1 characteristic

   

Now you know the handle of the characteristic which you want to read. So you can go to the CYBLE_EVT_GATTC_DISCOVERY_COMPLETE case in the ble event handler of your central device project and specify the handle range. Finally, you get the CYBLE_EVT_GATTC_READ_BY_TYPE_RSP event whenever the peripheral device responses to the reading operation. Below is the example of my read operation. It searches for the entire database instead of one handle. And I am reading a characteristic using the UUID of the characteristic.

   

 

   

case CYBLE_EVT_GAP_DEVICE_CONNECTED:

   

printf("\r\nDEVICE CONNECTED.\r\n");

   

 

   

/*Start to dicovery the servioes of the serve after connection*/

   

CyBle_GattcStartDiscovery(connHandle); 

   

break;

   

 

   

case CYBLE_EVT_GATTC_DISCOVERY_COMPLETE:

   

printf("\r\nDiscovery complete.\r\n");

   

 

   

range.startHandle   = 0x0001;

   

range.endHandle     = 0xFFFF;

   

uuid.uuid16         = 0x2223;       //uuid of the characteristic to be read.

   

 

   

readByTypeReqParam.range = range;

   

readByTypeReqParam.uuid = uuid;

   

readByTypeReqParam.uuidFormat = 0x01;

   

 

   

apiResult = CyBle_GattcReadUsingCharacteristicUuid(cyBle_connHandle,&readByTypeReqParam);

   

if ( apiResult != CYBLE_ERROR_OK )

   

printf("\r\nReading Operation is Failed\r\n");

   

 

   

break;

   

            

   

case CYBLE_EVT_GATTC_READ_BY_TYPE_RSP:

   

printf("\r\nReading Operation is Successful.\r\n");

   

 

   

readResponse = *(CYBLE_GATTC_READ_BY_TYPE_RSP_PARAM_T *) eventParam;

   

printf("\r\nLength of Characteristic is: %d\r\n",readResponse.attrData.length );

   

 

   

printf("Characteristic is: %s\r\n",readResponse.attrData.attrValue);

   

 

   

break;