4.2 Project Generation with Bluetooth® Low Energy Custom Protocol App Service Component
This section describes how to create a BLE custom protocol project using the MCC.
Project Generation
This section outlines the steps necessary to develop an application based on the BLE Custom Protocol Service MCC component, using MCC.
- Create a new MCC Harmony Project. For more details, refer to Creating a New MCC Harmony Project
- From the “Device Resources"
field, navigate to Libraries>Harmony>Wireless>Application
Services>BLE>BLE Custom Protocol Service and click on
the Plus Symbol as illustrated in the following figure.
Figure 4-7. BLE Custom Protocol Service - Upon selection, the user will
receive a prompt for auto-connect requests for various component
dependencies. Select Yes for all attachment auto-connect
requests.
Figure 4-8. Auto-Connect Request - Users can select the board
and activate the console by enabling the USART console interface in SHD, for
more details refer to Getting Started with WME Bluetooth Low Energy
Applications from Related Links. Project Graph will be as
illustrated in the following figure:
Figure 4-9. Project Graph for WBZ451 - By default, app code
generation is enabled in both the BLE Custom Protocol Service and the BLE
Config Service. Therefore, users must enable the console for a successful
build, as the app code generation will insert a few console prints for
feature demonstration. If users are generating their own application and do
not need any console, they can disable the app code generation option in
both custom protocol and BLE configuration component .
Figure 4-10. Enable App Code Generation - The user must configure the
following elements in the customized service based on the application use
case: the number of services, service names, service UUIDs, number of
characteristics, and characteristics' UUIDs. Additionally, the user must
configure the characteristic properties if they do not wish to enable a
custom protocol on that characteristic or if they intend to use that
particular characteristic for a different purpose.
Figure 4-11. Configure Customized Service - Enable the custom protocol on
the required characteristic, which will automatically configure the selected
characteristic properties in the customized service.
Figure 4-12. Custom Protocol Enable - Users must select the
appropriate byte role according to the application use case, as demonstrated
below. Data information must be added/updated according to the specific use
case requirements.
Figure 4-13. Byte Role and Data Information - Click on the Generate
tab to initiate code generation. Once the code is generated, the source
files related to and dependent on the Custom Protocol Service will be
generated and added to the project. Users can then compile the project by
clicking the build icon. The folder structure for the harmony-generated
source files:
Figure 4-14. Folder structure
Component Generated Code Flow
The packet will be processed based on the attribute handle. Upon a GATT write event, the received packet is queued in the app message queue according to its attribute handle. The packet is then decoded and managed within the app task.

The following key functions are generated to facilitate packet decoding. These
functions will be automatically inserted into the appropriate file during code
generation, eliminating the need for any manual intervention by the user. The
service name (Svc name) is provided by the user through the GUI, and charNo refers
to the characteristic number for which the user is generating code by enabling the
custom protocol option. For instance, if the service name is "led" and the custom
protocol is enabled on characteristic 0, the file name will be
app_wls_cps_led0
, and the global function name in that file
will begin with APP_WLS_CPS_LED0
.
Service Initialization:
The functions listed in the table below are the primary functions used for
initialization. They will be called by the APP_Tasks()
function
within app.c
.
Function | File | Description |
---|---|---|
void BLE_CPS_Init(void) | ble_cps_handler.c | This function will initialize custom service by
registering custom service to GATT server. It will be invoked by the
APP_Tasks() function within
app.c and will be included as part of code
generation. |
void
APP_WLS_CPS_<SvcName><CharNo:>_CallbackRegisterInit(void) | app_wls_cps_<SvcName><CharNo:>_action_handler.c | This function will register the callbacks. It will
be invoked by the APP_Tasks() function within
app.c and will be included as part of code
generation. |
BLE Event Process:
The functions outlined in the table below are the primary functions utilized for processing BLE events in custom protocol decoding, with the assistance of several local functions. For BLE characteristic write events, the packet will be sent to the decoding component for protocol decoding and handling, provided that the custom protocol is enabled for that characteristic.
Function | File | Description |
---|---|---|
void BLE_CPS_GapEventProcess(BLE_GAP_Event_T
*p_event) | ble_cps_handler.c | This function is responsible for processing GAP
events received from the BLE stack for custom protocol app. It will
be invoked by the APP_BleGapEvtHandler() function
within app_ble_handler.c and will be included as
part of code generation. |
void BLE_CPS_GattEventProcess(GATT_Event_T
*p_event) | ble_cps_handler.c | This function is responsible for processing GATT
events received from the BLE stack for custom protocol app. It will
be invoked by the APP_GattEvtHandler() function
within app_ble_handler.c and will be included as
part of code generation. |
Packet Decoding:
The function listed in the table below is the primary function used for decoding. This function decodes the packet using local functions and invokes the corresponding command action callback function, allowing the user to implement the necessary code for each command action. Additionally, it will call the error handler if any errors are detected in the respective packet.
Function | File | Description |
---|---|---|
void
BLE_CPS_<SvcName><CharNo:>_DECODE_CmdDecode(uint16_t
packetLen,uint8_t* p_packet) | ble_cps_<SvcName><CharNo:>_decode.c | This function decodes the packet and calls the
action handler to execute the corresponding action. It will be
invoked by the local function
ble_cps_<SvcName><CharNo:>_AttributeHandle()
within ble_cps_handler.c during the processing of
GATT events and will be included as part of the code
generation. |
void
BLE_CPS_<SvcName><CharNo:>_DECODE_CallbackRegister(BLE_CPS_LEDCTRL0_DECODE_Cb_T
callback) | ble_cps_<SvcName><CharNo:>_decode.c | This function will register the necessary callbacks for user actions. It will be invoked by the application's callback registration initialization, which is implemented as part of the application action handler file. |
void
BLE_CPS_<SvcName><CharNo:>_DECODE_DeviceDisconnected(void) | ble_cps_<SvcName><CharNo:>_decode.c | This function will be called from
BLE_CPS_GapEventProcess() when a BLE device
disconnection occurs. It will trigger the device disconnect
callback, allowing the user to implement any necessary actions in
response to the BLE disconnection. |
Function | File | Description |
---|---|---|
static uint8/16/32_t
ble_cps_<SvcName><CharNo:>_decode_<crctype>(uint8_t*
p_data, size_t length) | ble_cps_<SvcName><CharNo:>_decode.c | This local function, generated based on the CRC selection in byte role, will be used to calculate the CRC. It will be invoked by the command decode function. |
static uint8/16/32_t
ble_cps_<SvcName><CharNo:>_decode_<checksumtype>(uint8_t*
p_data, size_t length) | ble_cps_<SvcName><CharNo:>_decode.c | This local function, generated based on the Checksum selection in byte role, will be used to calculate the Checksum. It will be invoked by the command decode function. |
static uint32_t
app_ble_cps_<SvcName><CharNo:>_SequenceCheck(uint8/16_t
seqNumber) | ble_cps_<SvcName><CharNo:>_decode.c | This local function, generated based on the sequence number selection in byte role, will be used to check the sequence number matching or not and will return with error code. It will be invoked by the command decode function. |
Action Handler:
The action handler includes the relevant callback functions for users to implement their business logic. Depending on the Command ID/Opcode, the decode function will invoke the appropriate callback function. The callback function table and names will be generated based on the service name, characteristic number, and command name. For instance, if the service name is "led," the characteristic is zero, and the command names are “command1” and “command2”, the callback table and callback functions will be as follows.
static APP_WLS_CPS_LED0_ActionTableEntry_T s_cmdTable[APP_WLS_CPS_LED0_COMMAND_COUNT] = { {APP_WLS_CPS_LED0_COMMAND1, app_wls_cps_led0_ActionCommand1}, {APP_WLS_CPS_LED0_COMMAND2, app_wls_cps_led0_ActionCommand2}, }; static void app_wls_cps_led0_ActionCommand1(uint8_t* p_payload, uint16_t payloadLength) { /*Add User Code here for action handling*/ } static void app_wls_cps_led0_ActionCommand2(uint8_t* p_payload, uint16_t payloadLength) { /*Add User Code here for action handling*/ } static void app_wls_cps_led0_ErrorHandler(BLE_CPS_SVC00_DECODE_ErrorType_T errortype) { /*Add User Code here for error handling*/ } static void app_wls_cps_led0_DeviceDisconnected(void) { /*Add User Code here for BLE connection close*/ }
void APP_WLS_CPS_LED0_CallbackRegisterInit(void)
{
BLE_CPS_LED0_DECODE_Cb_T appCallback =
{
s_cmdTable,
NULL, /*If required, replace NULL with a user-defined callback function to validate sequence numbers*/
NULL, /*If required, replace NULL with a user-defined callback function for CRC/Checksum calculation*/
app_wls_cps_led0_ErrorHandler,
app_wls_cps_led0_DeviceDisconnected
};
BLE_CPS_LED0_DECODE_CallbackRegister(appCallback);
}
Users can replace the default implementation of sequence number and
CRC/Checksum with their own implementation by replacing the “NULL” with their own
function pointer, which must follow the defined prototype of the default
implementation as mentioned in the table Packet Error
Detection.User Helper APIs
Function | File | Description |
---|---|---|
uint16_t BLE_CPS_SendResponse(uint16_t
payloadLength, uint8_t *p_payload) | ble_cps_handler.c | The user can utilize this API to send the response. The response will be sent as a BLE notification using the respective attribute handle from which the packet is received. The user must provide the payload length and the payload buffer pointer as parameters. A successful operation will return a zero, in accordance with the stack API result. |
uint16_t BLE_CPS_NotifyData(uint16_t
attrHandle, uint16_t payloadLength, uint8_t
*p_payload) | ble_cps_handler.c | The user can utilize this API to send the Notification. The user must provide attribute handle, the payload length and the payload buffer pointer as parameters. A successful operation will return a zero, in accordance with the stack API result. |