How to create a Custom Profile-Server

Showing results for 
Search instead for 
Did you mean: 

How to create a Custom Profile-Server

No ratings

How to create a Custom Profile-Server

For this example, the BLE stack VERSION was configure to create a Custom Profile with the KW40Z.

The Custom to create is the Humidity Sensor and is based on the Temperature Sensor.

The First thing to know is that the Generic Attribute Profile (GATT) establishes in detail how to exchange all profile and user data over a BLE connection. GATT deals only with actual data transfer procedures and formats. All standard BLE profiles are based on GATT and must comply with it to operate correctly. This makes GATT a key section of the BLE specification, because every single item of data relevant to applications and users must be formatted, packed, and sent according to the rules.

GATT defines two roles: Server and Client.

  • The GATT server stores the data transported over the Attribute Protocol (ATT) and accepts Attribute Protocol requests, commands and confirmations from the GATT client.
  • The GATT client accesses data on the remote GATT server via read, write, notify, or indicate operations.


   Figure 1. GATT Client-Server

      GATT Database establishes a hierarchy to organize attributes. These are the Profile, Service, Characteristic and Descriptor. Profiles are high level definitions that define how services can be used to enable an application and Services are collections of characteristics. Descriptors are defined attributes that describe a characteristic value.

To define a GATT Database several macros are provided by the GATT_DB API.


Figure 2. GATT database

     To know if the Profile or service is already defined on the specification, you have to look for on Bluetooth SIG profiles and check on the ble_sig_define module if is already declared on the code. In our case the Service is not declared(because is a Custom Profile) but the characteristic of the humidity it is on the specification but not on ble_sig_define.

/*! Humidity Charactristic UUID */

#define gBleSig_Humidity_d                      0x2A6F

The Humidity Sensor is going to have the GATT Server, because is going to be the device that has all the information for the GATT Client.

The Application works like the Temperature Sensor, every time that you press the SW1 on USB is going to send the value.

On the Temperature Sensor demo have the Battery Service and Device Information, so you only have to change the Temperature Service to Humidity Service.


Figure 3. GATT database of Humidity Sensor

     First thing to do is define the Humidity Server that has 16 bytes.

To define a new Server or a Characteristic is in gatt_uuid128.h which is located in the application folder.

All macros, function or structure in SDK have a common template which helps the application to act accordingly.

/* Humidity */

UUID128(uuid_service_humidity, 0xfe ,0x34 ,0x9b ,0x5f ,0x80 ,0x00 ,0x00 ,0x80 ,0x00 ,0x10 ,0x00 ,0x02 ,0x00 ,0xfa ,0x10 ,0x10)


All the Service and Characteristics is declared in gattdb.h. Descriptors are declared after the Characteristic Value declaration but before the next Characteristic declaration. In this case the permission is the CharPresFormatDescriptor that have specific description by the standard. The Units of the Humidity Characteristic is on Percentage that is 0x27AD.

Client Characteristic Configuration Descriptor(CCCD) is a descriptor where clients write some of the bits to activate Server notifications and/or indications

PRIMARY_SERVICE_UUID128(service_humidity, uuid_service_humidity)

CHARACTERISTIC(char_humidity, gBleSig_Humidity_d, (gGattCharPropNotify_c))

VALUE(value_humidity, gBleSig_Humidity_d, (gPermissionNone_c), 2, 0x00, 0x25)

DESCRIPTOR(desc_humidity, gBleSig_CharPresFormatDescriptor_d, (gPermissionFlagReadable_c), 7, 0x0E, 0x00, 0xAD, 0x27, 0x00, 0x00, 0x00)


     After that, create a folder humidity in the next path C:\....\KW40Z_BLE_Software_1.1.2\ConnSw\bluetooth\profiles. Found the temperature folder, copy the temperature_service and paste inside of the humidity folder with another name (humidity_service)

Then go back and look for the interface folder, copy temperature_interface and change the name (humidity_interface) in the same path.

     On the humidity_interface file should have the following code.

The Service structure has the service handle, and the initialization value.

/*! Humidity Service - Configuration */

typedef struct humsConfig_tag


    uint16_t serviceHandle;

    int16_t initialHumidity;       

} humsConfig_t;

The next configuration structure is for the Client; in this case we don’t need it.

/*! Humidity Client - Configuration */

typedef struct humcConfig_tag


    uint16_t    hService;

    uint16_t    hHumidity;

    uint16_t    hHumCccd;

    uint16_t    hHumDesc;

    gattDbCharPresFormat_t  humFormat;

} humcConfig_t;

     At minimum on humidity_service file, should have the following code.

The service stores the device identification for the connected client. This value is changed on subscription and non-subscription events.

/*! Humidity Service - Subscribed Client*/

static deviceId_t mHums_SubscribedClientId;

     The initialization of the service is made by calling the start procedure. This function is usually called when the application is initialized. In this case is on the BleApp_Config(). On stop function, the unsubscribe function is called.

bleResult_t Hums_Start (humsConfig_t *pServiceConfig)


    mHums_SubscribedClientId = gInvalidDeviceId_c;


    return Hums_RecordHumidityMeasurement (pServiceConfig->serviceHandle,



bleResult_t Hums_Stop (humsConfig_t *pServiceConfig)


    return Hums_Unsubscribe();


     Depending on the complexity of the service, the API will implement additional functions. For the Humidity Sensor only have a one characteristic.

The measurement will be saving on the GATT database and send the notification to the client. This function will need the service handle and the new value as input parameters.

bleResult_t Hums_RecordHumidityMeasurement (uint16_t serviceHandle, int16_t humidity)


    uint16_t handle;

    bleResult_t result;

    bleUuid_t uuid = Uuid16(gBleSig_Humidity_d);


    /* Get handle of Humidity characteristic */

    result = GattDb_FindCharValueHandleInService(serviceHandle,

        gBleUuidType16_c, &uuid, &handle);

    if (result != gBleSuccess_c)

        return result;

    /* Update characteristic value */

    result = GattDb_WriteAttribute(handle, sizeof(uint16_t), (uint8_t*)&humidity);

    if (result != gBleSuccess_c)

        return result;


    return gBleSuccess_c;


     After save the measurement on the GATT database with GattDb_WriteAttribute function we send the notification.

To send the notification, first have to get the CCCD and after check if the notification is active, if is active send the notification.

static void Hts_SendHumidityMeasurementNotification


  uint16_t handle



    uint16_t hCccd;

    bool_t isNotificationActive;

    /* Get handle of CCCD */

    if (GattDb_FindCccdHandleForCharValueHandle(handle, &hCccd) != gBleSuccess_c)


    if (gBleSuccess_c == Gap_CheckNotificationStatus

        (mHums_SubscribedClientId, hCccd, &isNotificationActive) &&

        TRUE == isNotificationActive)


          GattServer_SendNotification(mHums_SubscribedClientId, handle);



     Steps to include the files into the demo.

1. Create a clone of the Temperature_Sensor with the name of Humidity_Sensor

2. Unzip the Humidity_Sensor folder.

3. In the fallowing path <kw40zConnSoft_intall_dir>\ConnSw\bluetooth\profiles\interface save the humidity_interface file.

4. In the <kw40zConnSoft_intall_dir>\ConnSw\bluetooth\profiles save the humidity folder

5. In the next directory <kw40zConnSoft_intall_dir>\ConnSw\examples\bluetooth\humidity_sensor\common replaces with the common folder.


      Steps to include the paths into the demo using IAR Embedded Workbench

Once you already save the folders in the corresponding path you must to indicate in the demo where are they.

1. Drag the files into the corresponding folder. The principal menu is going to see like this.


Figure 4. Principal Menu

2. Then click Option


Figure 5. Option

3. Click on the C/C++ Compiler and then on the Preprocessor


    Figure 6. Preposcessor Window

4. After that click on  "..." button to edit the include directories and then click to add a new path.

     Add the <kw40zConnSoft_intall_dir>\ConnSw\bluetooth\profile\humidity path.


Figure 7. Add a path

Finally compile and enjoy the demo!

NOTE: If you want to probe the demo using another board you must to run the humidity_collector demo too.

pastedImage_60.pngFigure 8. Example of the Humidity Sensor using the Humidity Collector demo.

Labels (1)

josem.reyes.chaidez​ who  else   from your area can provide a  quick  review to this  document to  see if  any comment/change is required?

After that  this  will be  published.

Hello Karina, ilianatejeda​ will be reviewing this document this week to be published this week.

I followed this document for creating custom profile for my application in KW40Z development board

I am trying to change UUIDs in gatt_uuid128.h, but after changing no matter how many times i compile, i always see the old UUIDs when i discover services and characteristics using my mobile app, please explain am i missing something



I am using the given bluetooth_wireless_uart_demo example code

I did not change anything other than the UUIDs

I am using IAR compiler (only supported tool now)

Hardware FRDM-KW40Z


Before :

UUID128(uuid_service_wireless_uart, 0xE0, 0x1C, 0x4B, 0x5E, 0x1E, 0xEB, 0xA1, 0x5C, 0xEE, 0xF4, 0x5E, 0xBA, 0x00, 0x01, 0xFF, 0x01)
UUID128(uuid_uart_stream, 0xE0, 0x1C, 0x4B, 0x5E, 0x1E, 0xEB, 0xA1, 0x5C, 0xEE, 0xF4, 0x5E, 0xBA, 0x01, 0x01, 0xFF, 0x01)



UUID128(uuid_service_wireless_uart, 0xba, 0x1C, 0x4B, 0x5E, 0x1E, 0xEB, 0xA1, 0x5C, 0xEE, 0xF4, 0x5E, 0xBA, 0x00, 0x01, 0xFF, 0x01)
UUID128(uuid_uart_stream, 0xab, 0x1C, 0x4B, 0x5E, 0x1E, 0xEB, 0xA1, 0x5C, 0xEE, 0xF4, 0x5E, 0xBA, 0x01, 0x01, 0xFF, 0x01)

Hi chandramohanc‌,

Did you forget the previous paired device in your mobile app? I mean, could you please forget the device in your mobile application before make a reconnection to the device? We have seen that mobile devices used to keep the old information when connecting to devices that were paired before, it is because smartphones uses the address to identify such device. 

On the other hand, I recommend to follow the next guide about custom profiles on NXP BLE stack: 

Hi Jose,

Thanks for the response, i fixed the issue recently

1. If I clone the uart_wireless_demo using ConnectivitySoftwareProjectCloner choosing fullCodebase, modification in uuids doesn't take effect

2. If i clone the uart_wireless_demo using ConnectivitySoftwareProjectCloner choosing applicationFilesOnly fixes the issue

It is very strange that 1st option doesn't work

Hi Jose,

You are right, if i turn OFF and ON bluetooth in my mobile it catches the new changes related to GATT DB / UUIDs

thanks a lot !!

Version history
Last update:
‎09-10-2020 01:59 AM
Updated by: