how to set BLE Device Information service characteristics programatically?

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

cross mob
Anonymous
Not applicable

Hi,

   

I know how to set the custom characteristics of a custom service using following code -

   

CYBLE_GATT_HANDLE_VALUE_PAIR_T tempHandle;
tempHandle.attrHandle = CYBLE_CUSTOMSERVICE_NAME_CHAR_HANDLE;
tempHandle.value.val = data;
tempHandle.value.len = sizeof(data);

   

CyBle_GattsWriteAttributeValue(&tempHandle, 0, &CYBLE_CUSTOMSERVICE_NAME_CHAR_HANDLE, CYBLE_GATT_DB_LOCALLY_INITIATED);

   

But now I want to set characteristics of Device Information service programatically (i.e Serial Number String). These services are standard services. Is there any example which I can use to set standard characteristics? If I try the above code to set it, it doesn't work. I can see the constant value set using the BLE settings.

   

Please help. Thanks in advance.

   

Kind Regards,

   

Jitender

0 Likes
1 Solution
Anonymous
Not applicable

Hi, 

   

The command you are looking for is CyBle_DissSetCharacteristicValue(CYBLE_DIS_SERIAL_NUMBER   , sizeof(serNum), serNum);

   

If you right click the BLE component and select "Open API Documentation" and then go to "Service Specific API's" and then select "Device Information Service" you will find everything you are looking for,

   

Hope this helps,

   

Stephen

View solution in original post

10 Replies
Anonymous
Not applicable

Hi, 

   

The command you are looking for is CyBle_DissSetCharacteristicValue(CYBLE_DIS_SERIAL_NUMBER   , sizeof(serNum), serNum);

   

If you right click the BLE component and select "Open API Documentation" and then go to "Service Specific API's" and then select "Device Information Service" you will find everything you are looking for,

   

Hope this helps,

   

Stephen

Anonymous
Not applicable

And here is an example how i've done it:

   

#define CFG_SERIAL_NUMBER "my-serial-number"

   

CyBle_DissSetCharacteristicValue( CYBLE_DIS_SERIAL_NUMBER, sizeof( CFG_SERIAL_NUMBER ), CFG_SERIAL_NUMBER );

Anonymous
Not applicable

And here is a tip how you can make your GATT Characteristic write's neater:

   

CYBLE_GATT_HANDLE_VALUE_PAIR_T pair = { { data, sizeof( data ) }, CYBLE_XXX_YYY_CHAR_HANDLE };
CyBle_GattsWriteAttributeValue( &pair, 0, &cyBle_connHandle, CYBLE_GATT_DB_LOCALLY_INITIATED );

   

 

   

(It looks better in your source code where the two lines does not wrap like in this forum)

Anonymous
Not applicable

Hi Steven and Speedycat.

   

Thanks for the code reference and examples. I liked the neater version of code! 🙂

   

I tried to use the CyBle_DissSetCharacteristicValue function but I can't see the value in serial number string when exploring the ble device using CySmart app.

   

Serial string under Device Information still shows the constant value assigned in settings of BLE component not the one I set programmatically. Below is the complete code I used. Do you see if I missed anything??

   

 

   

#include <stdio.h>
#include <project.h>

   

void AppCallBack(uint32 event, void* eventParam)
{
    CYBLE_API_RESULT_T apiResult;

   


    switch (event)
    {
        case CYBLE_EVT_STACK_ON: /* This event is received when component is Started */
            /* Enter into discoverable mode so that remote can search it. */
            apiResult = CyBle_GappStartAdvertisement(CYBLE_ADVERTISING_FAST);
            if(apiResult != CYBLE_ERROR_OK)
            {   
                
            }
            
            break;
        case CYBLE_EVT_GAP_DEVICE_DISCONNECTED:
            /* Put the device to discoverable mode so that remote can search it. */
            apiResult = CyBle_GappStartAdvertisement(CYBLE_ADVERTISING_FAST);
            if(apiResult != CYBLE_ERROR_OK)
            {
                
            }
            break;
        default:
            break;
    }
}

   


int main()
{
    CyGlobalIntEnable;         /* Enable global interrupts. */
    
    CyBle_Start(AppCallBack);
    
    const char8 serialNumber[] = "123456";
    
    CyBle_DissSetCharacteristicValue(CYBLE_DIS_SERIAL_NUMBER, sizeof(serialNumber), (uint8 *)serialNumber);
    
    for(;;)
    {
        CyBle_ProcessEvents();    
    }
}

   

 

   

Thanks.

   

Kind Regards

   

Jitender

0 Likes
Anonymous
Not applicable

I got it working. It was having issue with Serial Number Length in BLE component. I increased that and it is now updating the new value.

   

Now I got another small issue. How do I assign DeviceMacAddress to Serial Number? If I use the following code that doesn't work. I think it has something to do with data type conversion, Right? Any Idea?

   

CYBLE_GAP_BD_ADDR_T localAddr;

   

CyBle_GetDeviceAddress(&localAddr);

   

CyBle_DissSetCharacteristicValue(CYBLE_DIS_SERIAL_NUMBER, sizeof(localAddr.bdAddr), localAddr.bdAddr);

Anonymous
Not applicable

I have not tried to change my device address. But take a look at the generated function CyBle_EventHandler() in BLE_eventHandler.c . The event case CYBLE_EVT_STACK_ON shows how the device address is set.

   

 

   

CyBle_EventHandler() is the actual event handler for the BLE stack. At the end of this function you can see how it calls the function you gave CyBle_Start(). It took me long time before I realized this; before I thought my event handler function was the only one. This has been confusing since the API documentation have said you have to reply to events that CyBle_EventHandler() has done for you.

0 Likes
Anonymous
Not applicable

Sorry, I misunderstood your question. But extended knowledge is good anyway 🙂

   

 

   

The device address is byte array of size 6. These values are just numbers in the range [0, 256). The Device Information Service's Characteristics are utf8 arrays, so you need to convert the numbers to a character string. I think the proper way is to use snprintf() (I'm more a C++ guy than a C guy). Take a look here: http://en.cppreference.com/w/c/io/fprintf

   

EDIT: use the snprintf() function instead.

   

UPDATE 2016/06/16: The printf family of functions requires larger heap and stack size, according to the OTA application note (http://www.cypress.com/file/198301/download). The suggestions there are a heap size of 0x0400 and a stack size of 0x0800. Not sure if increasing these will have any impact on your application (but increasing these solved another problem I had regarding frequently notifications).

0 Likes
Anonymous
Not applicable

OK, here you go:

   

 

   

#include <stdint.h>
#include <stdio.h>

   

uint8_t* addr = cyBle_deviceAddress.bdAddr;

   

// get Attribute size of the Serial Number Characteristic
// (Attribute should be configured for a size of at least
// 6*2 + 5 + 1 == 18)
uint32_t size = CYBLE_GATT_DB_ATTR_GET_ATTR_GEN_LEN(
                cyBle_diss.charHandle[ CYBLE_DIS_SERIAL_NUMBER ] );
uint8_t str[ size ];
snprintf( str, size, "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
          addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] );
CyBle_DissSetCharacteristicValue( CYBLE_DIS_SERIAL_NUMBER, size, str );

Thanks and this was exactly i was looking for

0 Likes
Anonymous
Not applicable

Thanks speedycat, I would definitely try your solution and let you know!

   

Thanks once again 🙂

0 Likes