Port SDK

Last Updated on : 2022-11-24 09:20:02download

This topic describes how to port Tuya Bluetooth SDK after you import this SDK to your application project.

Make sure the .lib file in the SDK applies to your chip platform and compilation environment. Otherwise, the porting might fail. For more information, see Hardware Support.

Config item setting

You must create a new config header file. For example, create a header file named custom_tuya_ble_config.h and reference this config profile in tuya_ble_config.h.

You can edit configuration items in custom_tuya_ble_config.h as needed. For more information, see Config.

The followings are the configuration items to pay attention to.

  • CUSTOMIZED_TUYA_BLE_CONFIG_FILE

    Used to define a custom name for your created profile. Assign the custom file name to CUSTOMIZED_TUYA_BLE_CONFIG_FILE and define this macro in your project.

    Sample code

    CUSTOMIZED_TUYA_BLE_CONFIG_FILE =  <custom_tuya_ble_config.h>
    
  • TUYA_BLE_PORT_PLATFORM_HEADER_FILE

    Used to define the header file of code for platform porting. Create a new source code file for porting and define this macro for your created profile.

    Sample code

    #define TUYA_BLE_PORT_PLATFORM_HEADER_FILE       "tuya_ble_port_nRF52832.h"
    
  • TUYA_BLE_APP_VERSION_STRING

    Used to define the version number of the application firmware that is built on top of Tuya Bluetooth SDK.

    Sample code

    #define TUYA_BLE_APP_VERSION_STRING         "1.0"   // Define the firmware version as 1.0.
    

    This firmware version number must be updated as the firmware updates.

  • TUYA_BLE_APP_BUILD_FIRMNAME_STRING

    Used to define the name of the application firmware that is built on top of Tuya Bluetooth SDK.

    #define TUYA_BLE_APP_BUILD_FIRMNAME_STRING   "tuya_ble_sdk_demo_nRF52832"
    
  • TUYA_BLE_USE_OS

    Used to indicate whether a chip runs an OS.

    Sample code

    #define TUYA_BLE_USE_OS 0       // The chip does not run an OS.
    
  • TUYA_BLE_DEVICE_COMMUNICATION_ABILITY

    Used to define the device’s capability.

    Sample code

    #define TUYA_BLE_DEVICE_COMMUNICATION_ABILITY
    (TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_BLE|TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_REGISTER_FROM_BLE)
    // Registered as a Bluetooth Low Energy device.
    
  • TUYA_BLE_DATA_MTU_MAX

    The maximum transmission unit (MTU) is the size of the largest protocol data unit (PDU) that can be communicated in a single network layer transaction.

    • Bluetooth 4.0 supports the Attribute Protocol (ATT) MTU size of 23 bytes by default. During attribute data transmission, 1 byte is used for ATT opcode, 2 bytes are used for ATT handle, and 20 bytes are left for the Generic Attribute Profile (GATT).

    • MTU exchange is supported since Bluetooth 4.2. It is to set the maximum amount of data that can be exchanged in a PDU between the master and the slave. When entering connection, the master and the slave exchange their MTU through Exchange MTU Request/Response ATT layer command. Each side cannot transfer larger ATT packets than the other side’s specified ATT MTU.

    Port SDK

    The two sides use the smaller value as the MTU after knowing the other side’s limit.

    Once the Bluetooth connection between the device and the mobile phone is established, MTU exchange is automatically started. The application does not involve MTU exchange but requires the ATT MTU value. Then, the application sends the value of ATT MTU − 3 that is the maximum MTU of each write operation to the device.

    Since the ATT MTU defined for the device cannot exceed 247 bytes, you can define this macro as follows.

    #define TUYA_BLE_DATA_MTU_MAX         244      // ATT MTU is set to 247. The size of a single packet is 244 (247 − 3 = 244).
    
  • TUYA_NV_ERASE_MIN_SIZE

    Used to define the smallest erasable unit of the non-volatile (NV) memory assigned to the Tuya Bluetooth SDK.

    Sample code

    #define TUYA_NV_ERASE_MIN_SIZE 4096   // The size of the smallest erasable unit is set to 4096 bytes.
    
  • TUYA_NV_WRITE_GRAN

    Used to define the granularity of data written to the NV memory.

    Sample code

    #define TUYA_NV_WRITE_GRAN 4    // The data is written in a 4-byte unit.
    
  • TUYA_NV_START_ADDR

    Used to define the start address of the NV memory assigned to the Tuya Bluetooth SDK.

    Sample code

    #define TUYA_NV_START_ADDR 0x1000
    
  • TUYA_NV_AREA_SIZE

    Used to define the size of the NV memory assigned to the Tuya Bluetooth SDK.

    Sample code

    #define TUYA_NV_AREA_SIZE      (4*TUYA_NV_ERASE_MIN_SIZE)
    

    The value you specify must be an integer multiple of TUYA_NV_ERASE_MIN_SIZE.

  • TUYA_BLE_LOG_ENABLE

    Used to define whether to enable the log printing of Tuya Bluetooth SDK.

    We recommend that you enable log printing during debugging and disable it in your release version.

  • TUYA_BLE_LOG_COLORS_ENABLE

    Used to define whether to enable colored text for log printing of Tuya Bluetooth SDK.

  • TUYA_BLE_LOG_LEVEL

    Used to define logging levels for Tuya Bluetooth SDK.

  • TUYA_APP_LOG_ENABLE

    Used to define whether to enable application log.

    We recommend that you enable log printing during debugging and disable it in your release version.

  • TUYA_APP_LOG_COLORS_ENABLE

    Used to define whether to enable colored text for application log.

  • TUYA_APP_LOG_LEVEL

    Used to define levels for application log.

Chip platform porting

The functions in the port file are the abstract hardware interfaces that you need to port to your chip platform.

  1. Create new port files for chip platform porting, such as tuya_ble_port_nrf52832.h and tuya_ble_port_nrf52832.c, and add them to your project.
  2. In your created port file, implement the interfaces provided in the tuya_ble_port.h as per your configuration.
  3. Then, define the name for your port file in your created config profile.

For more information, see Port.

Implement interfaces as needed. If your chip does not run RTOS, all OS-related interfaces are not necessary. If you use the internal memory management of Tuya Bluetooth SDK, memory allocation and release interfaces are not necessary.

The followings are the functions in the port file to pay attention to.

Bluetooth Service initialization

Tuya Bluetooth SDK does not provide the interface for initializing Bluetooth Service. Your application needs to implement the Services and Characteristics defined in the following table before SDK initialization. Besides Services required by Tuya Bluetooth SDK, you can also define other Services if needed. The initial format of broadcast data must be implemented according to the following table. Otherwise, Tuya Bluetooth SDK cannot work.

Services and Characteristics

Service UUID Characteristic UUID Attribute Security permission Max length
FD50 Note 1 00000001-0000-1001-8001-00805F9B07D0 Write without response None ATT_MTU − 3
00000002-0000-1001-8001-00805F9B07D0 Notify None ATT_MTU − 3
00000003-0000-1001-8001-00805F9B07D0 Read Note 2 None 512
  • FD50: Tuya’s 16-bit universally unique identifier (UUID) registered with Bluetooth SIG.

  • Read: This service is used when you define TUYA_BLE_LINK_LAYER_ENCRYPTION_SUPPORT_ENABLE as 1. Otherwise, defining this attribute is not needed.

Advertising data format

Tuya Bluetooth SDK will automatically update advertisement content after SDK initialization. The application must initialize the advertisement content as described below.

Port SDK

Tuya advertisement packet

Data segment Type Description
Flags 0x01 Length: 0x02
Type: 0x01
Data: 0x06
Service UUID 0x02 Length: 0x03
Type: 0x02
Data: UUID=0xFD50
Service data 0x16 Length: 0x17
Type: 0x16
Data:
UUID: 0xFD50
DATA:20-byte 0x00
Note that Bluetooth advertisement must be initialized according to this format before Tuya Bluetooth SDK initialization.

Scan response data

Data segment Type Description
Manufacturer data 0xFF Length: 0x17
Type: 0xFF
Data:
Company ID: 0x07D0
Data: 20-byte 0x00
Note that Bluetooth advertisement must be initialized according to this format before Tuya Bluetooth SDK initialization.
Complete local name 0x09 Length: Length, up to 6 bytes.
Type: 0x09
Data: the custom name of Length − 1 bytes.

Receive data from GATT client

Call tuya_ble_gatt_receive_data to send data received from the GATT client to Tuya Bluetooth SDK. The SDK will parse the received encrypted data and send it to the application.

This function must be called in Tuya’s callback of write characteristic (UUID: 00000001-0000-1001-8001-00805F9B07D0).

The following sample code is based on the Nordic nRF52832.

/**@brief Function for handling the data from the Nordic UART Service.
*
* @details This function will process the data received from the Nordic UART
Bluetooth LE Service and send
*     it to the UART module.
*
* @param[in] p_evt    Nordic UART Service event.
*/
/**@snippet [Handling the data received over BLE] */
static void nus_commdata_handler(ble_nus_evt_t * p_evt)
{
  if (p_evt->type == BLE_NUS_EVT_RX_DATA)
 {
    tuya_ble_gatt_receive_data((uint8_t*)(p_evt->params.rx_data.p_data),p_evt->params.rx_data.length);
   // Call this function to send the data received from the GATT client to Tuya Bluetooth SDK.
   
 }
}

Main task scheduler

main process function is the main engine of Tuya Bluetooth SDK, which is called by the application.

If your chip does not run an OS, the application must call tuya_ble_main_tasks_execin the main loop.

The following sample code is based on the Nordic nRF52832.

static void idle_state_handle(void) // Called in the main loop.
{
  ret_code_t err_code;
  err_code = nrf_ble_lesc_request_handler();
  APP_ERROR_CHECK(err_code);
  tuya_ble_main_tasks_exec();  // Main task scheduler.
  if ((NRF_LOG_PROCESS() == false)&&(tuya_ble_sleep_allowed_check()))
 {
    nrf_pwr_mgmt_run();
 }
}

If your chip runs an OS, the SDK will automatically create a task by using the OS API from the port layer to run the main process function.

Bluetooth disconnection callback

The application calls tuya_ble_connected_handler() and tuya_ble_disconnected_handler() function in the Bluetooth disconnection callback of your chip platform SDK. Tuya Bluetooth SDK manages the internal Bluetooth connection based on this function.

The following sample code is based on the Nordic nRF52832.

static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
  uint32_t err_code;
  switch (p_ble_evt->header.evt_id)
 {
  case BLE_GAP_EVT_CONNECTED:
    NRF_LOG_INFO("Connected");
    tuya_ble_connected_handler();  // Call `tuya_ble_connected_handler()`.
    err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
    APP_ERROR_CHECK(err_code);
    m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
    err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
    APP_ERROR_CHECK(err_code);
    break;
  case BLE_GAP_EVT_DISCONNECTED:   
    NRF_LOG_INFO("Disconnected"); 
    tuya_ble_disconnected_handler(); // Call `tuya_ble_disconnected_handler()`.
    tuya_ota_init_disconnect();
    // LED indication will be changed when advertising starts.
    m_conn_handle = BLE_CONN_HANDLE_INVALID;
    break;
     ....
  default:
    // No implementation needed.
    break;
 }
}

Initialize Tuya Bluetooth SDK

tuya_ble_sdk_init(tuya_ble_device_param_t * param_data)

Sample code

static tuya_ble_device_param_t tuya_ble_device_param = {
    .use_ext_license_key = 1, // Define this function as `1` for debugging purpose and the license information that the application passes in will be used. In the release version, define this function as `0` and the license information will be written by Tuya's production tool.
    .device_id_len       = 16,  // If `use_ext_license_key` is `0`, license is obtained from Tuya's production test tool. Passing in the license is not needed. Assign `0` to `device_id_len`.  
    .p_type              = TUYA_BLE_PRODUCT_ID_TYPE_PID,
    .product_id_len      = 8,
    .adv_local_name_len  = 4,
    .firmware_version    = 0x00000201,  // The firmware version is 2.1.
    .hardware_version    = 0x00000100,  // The hardware version is 1.0.
    .device_id           = "tuyaf3752699xxxx"  // The parameter in the license.
    .auth_key            = "4gBM3DK6SRmRn9LTLbyOUAz3bHMGxxxx" //// The parameter in the license.
    .mac_addr_string     = "DC234D12XXXX"  //// The parameter in the license.
    .product_id          = "suq5jmo5" // Set it to the PID of the product created on the Tuya IoT Platform.
    .adv_local_name      = "demo"  // The custom name of Bluetooth advertisement.
};



void tuya_ble_sdk_demo_init(void)  // The initialization function, which must be called by the application.
{
    if(device_param.use_ext_license_key==1)
    {
        device_param.device_id_len = 16;   // Set `device_id_len` to 16 if you want to pass in the license information for debugging purpose. Otherwise, set it to `0`.
    }  
    tuya_ble_sdk_init(&tuya_ble_device_param); // Tuya Bluetooth SDK initialization function. It must be called. Otherwise, the SDK cannot run.
    TUYA_APP_LOG_HEXDUMP_INFO("auth key", tuya_ble_current_para.auth_settings.auth_key, AUTH_KEY_LEN);   // Print the `auth_key`.
    TUYA_APP_LOG_HEXDUMP_INFO("device id", tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN);  // Print the `device_id`.

    tuya_ble_callback_queue_register(tuya_ble_sdk_callback);// Registration callback.

}
  • Generally, the license list is used to authorize the network module for debugging purposes. For more information about getting the license, see Bluetooth LE Series Authorization.

  • In production, the license is written to the network module by using the Authorization Software. For more information, see Bluetooth LE Series Authorization.

Register message queue

The SDK sends data or events to the mobile app using messages or the registered callbacks.

If your chip runs an OS, API calls are made based on asynchronous message-based communication. When Tuya Bluetooth SDK is initialized, it automatically creates a task based on tuya_ble_config.h file to process the message events of the SDK and creates a message queue to receive the responses of the API. The application is notified of the results of the API call in the form of messages, so the application needs to create a message queue and call tuya_ble_callback_queue_register() after calling tuya_ble_sdk_init() to register the message queue to the SDK. The callback is:

tuya_ble_status_t tuya_ble_callback_queue_register(void *cb_queue)

os_msg_queue_create(&tuya_custom_queue_handle,MAX_NUMBER_OF_TUYA_CUSTOM_MESSAGE, sizeof(tuya_ble_cb_evt_param_t));
tuya_ble_callback_queue_register(tuya_custom_queue_handle);  // Register callbacks.

void tuya_custom_queue_handle(void *p_param) // The application receives any events from the SDK. You can complete the service logic as needed.
{
  tuya_ble_cb_evt_param_t event;
  while (true)
 {
    if (os_msg_recv(tuya_custom_queue_handle, &event, 0xFFFFFFFF) == true)
   {
      switch (event.evt)
     {
      case TUYA_BLE_CB_EVT_CONNECTE_STATUS:
        break;
      case TUYA_BLE_CB_EVT_DP_WRITE:      
        break;
      case TUYA_BLE_CB_EVT_DP_DATA_REPORT_RESPONSE:
        break;
      case TUYA_BLE_CB_EVT_DP_DATA_WTTH_TIME_REPORT_RESPONSE:
        break;
      case TUYA_BLE_CB_EVT_UNBOUND:
        break;
      case TUYA_BLE_CB_EVT_ANOMALY_UNBOUND:
        break;
      case TUYA_BLE_CB_EVT_DEVICE_RESET:
        break;
      case TUYA_BLE_CB_EVT_DP_QUERY:
        break;
      case TUYA_BLE_CB_EVT_OTA_DATA:
        break;
      case TUYA_BLE_CB_EVT_NETWORK_INFO:
        break;
      case TUYA_BLE_CB_EVT_WIFI_SSID:
        break;
      case TUYA_BLE_CB_EVT_TIME_STAMP:
        break;
      case TUYA_BLE_CB_EVT_TIME_NORMAL:
        break;
      case TUYA_BLE_CB_EVT_DATA_PASSTHROUGH:
        break;
      default:
        break;
     }     
      tuya_ble_event_response(&event);// With an RTOS, the application must call this function to return the result to the Tuya Bluetooth SDK.
   }
 }
}

If your chip does not run an OS, use the following function to register the callback.

tuya_ble_status_t tuya_ble_callback_queue_register(tuya_ble_callback_t cb)

tuya_ble_callback_queue_register(tuya_ble_sdk_callback);    // Register callbacks.

static void tuya_ble_sdk_callback(tuya_ble_cb_evt_param_t* event) //  The application receives any events from the SDK. You can complete the service logic as needed.
{
      switch (event->evt)
     {
      case TUYA_BLE_CB_EVT_CONNECTE_STATUS:
        break;
      case TUYA_BLE_CB_EVT_DP_WRITE:      
        break;
      case TUYA_BLE_CB_EVT_DP_DATA_REPORT_RESPONSE:
        break;
      case TUYA_BLE_CB_EVT_DP_DATA_WTTH_TIME_REPORT_RESPONSE:
        break;
      case TUYA_BLE_CB_EVT_UNBOUND:
        break;
      case TUYA_BLE_CB_EVT_ANOMALY_UNBOUND:
        break;
      case TUYA_BLE_CB_EVT_DEVICE_RESET:
        break;
      case TUYA_BLE_CB_EVT_DP_QUERY:
        break;
      case TUYA_BLE_CB_EVT_OTA_DATA:
        break;
      case TUYA_BLE_CB_EVT_NETWORK_INFO:
        break;
      case TUYA_BLE_CB_EVT_WIFI_SSID:
        break;
      case TUYA_BLE_CB_EVT_TIME_STAMP:
        break;
      case TUYA_BLE_CB_EVT_TIME_NORMAL:
        break;
      case TUYA_BLE_CB_EVT_DATA_PASSTHROUGH:
        break;
      default:
        break;

}

Bluetooth pairing

So far, the porting is completed. You can compile the code and flash the firmware to your chip for debugging.

If the porting succeeds, the SDK log should look like this: PID, device_uuid, auth_key, and MAC are all configured and bood_flag is 0 indicating unbound status. The following log is printed by J-Link RTT Viewer.

Port SDK

  1. Use a Bluetooth testing tool such as nRF Connect to scan Bluetooth devices. You will find a device named demo if the Bluetooth works.

    Port SDK
  2. Tap the device and check the advertising data. In TYPE=16 the data is 0x50FD41….

    For 0x50FD41…, 0x41 indicates the device is unbound. If the device is bound, the flag should be 0x49 and the adverting data is 0x50FD49….

    Port SDK
  3. Open the Tuya Smart app and scan for devices.

    Port SDK
  4. Tap Next to bind the device.

    Port SDK
  5. The device log is shown below.

    Port SDK

Next steps

After SDK porting, you can proceed with application development.