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.

Note: It is recommended that new users of MCC to go through the MPLAB® Code Configurator (MCC) User's Guide.
  1. Create a new MCC Harmony Project. For more details, refer to Creating a New MCC Harmony Project
  2. 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
  3. 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
  4. 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
  5. 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
  6. 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
  7. 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
  8. 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
  9. 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.

Figure 4-15. Packet Handling Flow Diagram

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.

Table 4-4. Service Initialization
FunctionFileDescription
void BLE_CPS_Init(void)ble_cps_handler.cThis 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.cThis 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.

Table 4-5. BLE Event Process
FunctionFileDescription
void BLE_CPS_GapEventProcess(BLE_GAP_Event_T *p_event)ble_cps_handler.cThis 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.cThis 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.

Table 4-6. Packet Decoding
FunctionFileDescription
void BLE_CPS_<SvcName><CharNo:>_DECODE_CmdDecode(uint16_t packetLen,uint8_t* p_packet)ble_cps_<SvcName><CharNo:>_decode.cThis 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.cThis 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.cThis 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.
Table 4-7. Packet Error Detection
FunctionFileDescription
static uint8/16/32_t ble_cps_<SvcName><CharNo:>_decode_<crctype>(uint8_t* p_data, size_t length)ble_cps_<SvcName><CharNo:>_decode.cThis 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.cThis 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.cThis 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*/
}
The callback register initialization function, as specified in the service initialization, will register all the callback functions by internally invoking the callback register function defined in the decode file.
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

To facilitate packet sending, response, and notification, the BLE Custom Protocol App Service Component generates code that provides helper APIs. Users can utilize these APIs to send framed response/notification packets.
Table 4-8. Helper APIs
FunctionFileDescription
uint16_t BLE_CPS_SendResponse(uint16_t payloadLength, uint8_t *p_payload)ble_cps_handler.cThe 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.cThe 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.