Bluetooth Accessories

Last Updated on : 2025-07-01 02:04:49download

Concepts

This topic describes how to enable smart control and management of non-smart tools by integrating them as accessories through smart battery packs. This capability has three key features:

  • Offer a standardized Tuya integration solution for non-smart tools.

  • Enable smart control and OTA updates for non-smart tools based on smart battery packs, while displaying the non-smart tool’s RN page on the app.

  • Deliver a microapp management console for smart battery packs and non-smart tools, so brand owners can maintain relationships between battery packs and tools.

UART
Bluetooth LE
Accessory
Battery Pack
App
Cloud

Bluetooth Accessories

Data structure

The baseline implementation transmits all data via a UINT8_T pointer, with specific data handled at the application layer. For more information, see the demo tuyaos_demo_ble_accessory.

typedef struct {
    UINT8_T channle;
    UINT32_T soft_version;
    UINT32_T hard_version;
} accessory_fw_info_t;

typedef struct {
    UINT8_T                    *p_accessory_fw_info;
    UINT8_T                     device_id[DEVICE_ID_LEN];
    UINT8_T                     common_pid[TUYA_BLE_PRODUCT_ID_MAX_LEN];
    tuya_ble_product_id_type_t  pid_type;
    UINT8_T                     pid_len;
    UINT8_T                     accessory_fw_info_len;
    UINT8_T                     device_id_len;
    UINT8_T                     connect_status; //1-connect 0-disconnect
    UINT8_T                     port_id;
    UINT8_T                     active_status; //1-active 0-not active
    UINT16_T                    short_id;
} tuya_ble_accessory_connection_info_t;

/**@brief    Structure about the accessory active information. */
typedef struct {
    UINT32_T info_crc;
    UINT16_T info_len;
    UINT16_T short_id;
    UINT8_T device_id[DEVICE_ID_LEN];
} tuya_ble_accessory_active_info_t;

/**@brief    Structure about the accessory ID information. */
typedef struct {
    UINT8_T id_type;
    UINT8_T id_len;
    UINT16_T short_id;
} tuya_ble_accessory_id_info_t;

API description

All event handling is invoked within the tuya_ble_protocol_callback function.

Bidirectional transparent transmission between app and sub-devices

Communication is mediated through the Bluetooth sub-device, which enables bidirectional data transmission between accessories and the app by using pass-through commands.

TUYA_BLE_CB_EVT_WITH_SRC_TYPE_DP_DATA_RECEIVED

Receive DP data along with the data source, and transparently transmit the received data to accessories.

case TUYA_BLE_CB_EVT_WITH_SRC_TYPE_DP_DATA_RECEIVED: {
    /* Determine the data source*/
    if (event->dp_data_with_src_type_received_data.src_type != DATA_SOURCE_TYPE_ACCESSORY_EQUIPMENT) {
        break;
    }
    /* Verify whether the device information meets requirements */
    p_id_info = (tuya_ble_accessory_id_info_t*)event->dp_data_with_src_type_received_data.p_add_info;
    if ((p_id_info->id_type != 0) || (p_id_info->id_len != 2)) {
        TAL_PR_ERR("TUYA_BLE_CB_EVT_WITH_SRC_TYPE_DP_DATA_RECEIVED id info error.");
        break;
    }

    /* Check if it is a matched accessory based on short ID */
    if (tuya_ble_accessory_connection_info_find_by_short_id(p_id_info->short_id, &info_index) == TRUE) {
        /* Transmit raw data to accessories*/
        tuya_ble_accessory_uart_cmd_dp_data_send_to_accessory(accessory_info[info_index].port_id, event->dp_data_with_src_type_received_data.sn, event->dp_data_with_src_type_received_data.p_data, event->dp_data_with_src_type_received_data.data_len);
        /* Report to the app */
        tuya_ble_dp_data_with_src_type_send(event->dp_data_with_src_type_received_data.sn, DATA_SOURCE_TYPE_ACCESSORY_EQUIPMENT, DP_SEND_TYPE_ACTIVE, DP_SEND_FOR_CLOUD_PANEL, DP_SEND_WITHOUT_RESPONSE, \
            event->dp_data_with_src_type_received_data.add_info_len, event->dp_data_with_src_type_received_data.p_add_info, \
            event->dp_data_with_src_type_received_data.p_data, event->dp_data_with_src_type_received_data.data_len);
    } else {
        TAL_PR_ERR("unknown device: %d", p_id_info->short_id);
    }
} break;

TUYA_BLE_CB_EVT_WITH_SRC_TYPE_DP_QUERY

Query the DP data with the data source.

case TUYA_BLE_CB_EVT_WITH_SRC_TYPE_DP_QUERY: {
            /* Determine the data source*/
    if (event->dp_query_data_with_src_type.src_type != DATA_SOURCE_TYPE_ACCESSORY_EQUIPMENT) {
        break;
    }
            /* Verify whether the device information meets requirements */
    p_id_info = (tuya_ble_accessory_id_info_t*)event->dp_query_data_with_src_type.p_add_info;
    if ((p_id_info->id_type != 0) || (p_id_info->id_len != 2)) {
        TAL_PR_ERR("TUYA_BLE_CB_EVT_WITH_SRC_TYPE_DP_QUERY id info error.");
        break;
    }
            /* Check if it is a matched accessory based on short ID */
    if (tuya_ble_accessory_connection_info_find_by_short_id(p_id_info->short_id, &info_index) == TRUE) {
        TAL_PR_HEXDUMP_DEBUG("DP Query - accessory:", event->dp_query_data_with_src_type.p_data, event->dp_query_data_with_src_type.data_len);

        /*Send work status*/
        tuya_ble_accessory_uart_cmd_send_work_mode(accessory_info[info_index].port_id);

        /*Send dp query*/
        tuya_ble_accessory_uart_cmd_dp_query(accessory_info[info_index].port_id, event->dp_query_data_with_src_type.p_data, event->dp_query_data_with_src_type.data_len);
    } else {
        TAL_PR_DEBUG("unknown device: %d", p_id_info->short_id);
    }
} break;

TUYA_BLE_CB_EVT_DP_DATA_WITH_SRC_TYPE_SEND_RESPONSE

Respond to DP data reporting with the data source.

case TUYA_BLE_CB_EVT_DP_DATA_WITH_SRC_TYPE_SEND_RESPONSE: {
    /* Determine the data source*/
    if (event->dp_with_src_type_send_response_data.src_type != DATA_SOURCE_TYPE_ACCESSORY_EQUIPMENT) {
        break;
    }
    /* Verify whether the device information meets requirements */
    p_id_info = (tuya_ble_accessory_id_info_t*)event->dp_with_src_type_send_response_data.p_add_info;
    if ((p_id_info->id_type != 0) || (p_id_info->id_len != 2)) {
        TAL_PR_ERR("TUYA_BLE_CB_EVT_DP_DATA_WITH_SRC_TYPE_SEND_RESPONSE id info error.");
        break;
    }
    /* Check if it is a matched accessory based on short ID */
    if (tuya_ble_accessory_connection_info_find_by_short_id(p_id_info->short_id, &info_index) == TRUE) {
        TAL_PR_DEBUG("DP Send Respondse - accessory:sn:0x%08X,type:%d,mode:%d,ack:%d,status:%d", event->dp_with_src_type_send_response_data.sn,\
        event->dp_with_src_type_send_response_data.type, event->dp_with_src_type_send_response_data.mode, event->dp_with_src_type_send_response_data.ack, event->dp_with_src_type_send_response_data.status);
    } else {
        TAL_PR_ERR("unknown device: %d", p_id_info->short_id);
    }
} break;

TUYA_BLE_CB_EVT_DP_DATA_WITH_SRC_TYPE_AND_TIME_SEND_RESPONSE

Respond to DP data reporting with the data source and timestamp.

case TUYA_BLE_CB_EVT_DP_DATA_WITH_SRC_TYPE_AND_TIME_SEND_RESPONSE: {
    /* Determine the data source*/
    if (event->dp_with_src_type_and_time_send_response_data.src_type != DATA_SOURCE_TYPE_ACCESSORY_EQUIPMENT) {
        break;
    }
            /* Verify whether the device information meets requirements */
    p_id_info = (tuya_ble_accessory_id_info_t*)event->dp_with_src_type_and_time_send_response_data.p_add_info;
    if ((p_id_info->id_type != 0) || (p_id_info->id_len != 2)) {
        TAL_PR_ERR("TUYA_BLE_CB_EVT_DP_DATA_WITH_SRC_TYPE_AND_TIME_SEND_RESPONSE id info error.");
        break;
    }
            /* Check if it is a matched accessory based on short ID */
    if (tuya_ble_accessory_connection_info_find_by_short_id(p_id_info->short_id, &info_index) == TRUE) {
        TAL_PR_DEBUG("DP Send Respondse - accessory:sn:0x%08X,type:%d,mode:%d,ack:%d,status:%d", event->dp_with_src_type_and_time_send_response_data.sn,\
        event->dp_with_src_type_and_time_send_response_data.type, event->dp_with_src_type_and_time_send_response_data.mode, event->dp_with_src_type_and_time_send_response_data.ack, event->dp_with_src_type_and_time_send_response_data.status);
    } else {
        TAL_PR_ERR("unknown device,%d", p_id_info->short_id);
    }
} break;

Bidirectional transmission between sub-devices and accessories

Accessories and sub-devices communicate via UART using custom commands in the protocol, which only requires implementation at the application layer.

VOID_T tuya_ble_custom_app_uart_common_process(UINT8_T *p_in_data, UINT16_T in_len);

This function is defined as weak in the underlying layer and implemented at the application layer. The compiler will prioritize linking the application-layer version when implemented. The underlying layer has already completed data parsing and forwarding. All input data consists of accessory-reported packets, so you only need to process the received data by calling this interface.

VOID_T tuya_ble_accessory_uart_protocol_process(UINT8_T port_id, UINT8_T *p_in_data, UINT16_T in_len);

The interface handles all commands for interacting with accessories.

  • TUYA_BLE_ACCESSORY_UART_CMD_OTA_REQUEST

  • TUYA_BLE_ACCESSORY_UART_CMD_OTA_FILE_INFO

  • TUYA_BLE_ACCESSORY_UART_CMD_OTA_FILE_OFFSET

  • TUYA_BLE_ACCESSORY_UART_CMD_OTA_DATA

  • TUYA_BLE_ACCESSORY_UART_CMD_OTA_END

  • TUYA_BLE_ACCESSORY_UART_CMD_HANDUP

  • TUYA_BLE_ACCESSORY_UART_CMD_DEVICE_INFO_REPORT

  • TUYA_BLE_ACCESSORY_UART_CMD_DP_DATA_REPORT

  • TUYA_BLE_ACCESSORY_UART_CMD_QUERY_MODULE_MAC

  • TUYA_BLE_ACCESSORY_UART_CMD_FATORY_CMD

For more information, see the demo tuyaos_demo_ble_accessory.

FAQs

Which macros do I need to focus on to enable this capability?

// This capability is not supported by default and needs to be enabled through macro definition.
#define TUYA_BLE_ACCESSORY_MOUNT_SUPPORTED 1
// The baseline shall support multi-source data transmission.
#define TUYA_BLE_MUTI_DATA_SOURCE_SUPPORTED 1
// And general serial port capabilities.
#define TUYA_BLE_FEATURE_UART_COMMON_ENABLE 1

What are the configuration parameters of the serial port?

Non-smart accessories communicate with the battery pack via UART. The specifications are as follows:

  • Baud: 9600

  • Data length: 8 bits

  • Stop bit: 1

  • Flow control: none

How to check whether accessories are online or offline?

The RX pin of the battery pack is configured with a weak pull-down while the TX pin of the accessory uses a pull-up resistor. The battery pack periodically checks the RX pin’s state. A sustained pull-down indicates accessory disconnection (offline status), a triggered high level initiates a handshake command, and a successful handshake confirms online status.

Why is the device not registered and shown on the panel despite normal communication?

The Bluetooth accessory capability is an advanced feature that requires additional PID activation. For more information, contact Tuya’s account manager.

Support and help

If you have any problems with TuyaOS development, you can post your questions in the Tuya Developer Forum.