File Transfer

Last Updated on : 2024-05-21 06:51:30download

This topic describes the file transfer feature, allowing smart devices, such as door locks, watches, and fitness trackers, to download voice files and watch faces from the mobile app. The TuyaOS Bluetooth LE SDK provides a unified API for file transfer. The application layer only needs to implement this API according to the protocol outlined in this topic.

How it works

Yes
No
No
Yes
Yes
No
Yes
No
Start
The app sends a file transfer
request to the device
The device accepts
the request?
The app sends the file
information to the device
File transfer fails
The device already
has the file?
The app sends the file offset
The device returns the file offset
The app sends the file data
File transfer
is complete?
The app finishes file transfer
The device
returns success?
File transfer succeeds
End

Data structure

typedef struct {
    UINT8_T  type;
    UINT16_T file_id;
    UINT8_T  id_len;
    UINT8_T *id_buf;
    UINT32_T file_ver;
    UINT32_T file_len;
    UINT8_T  file_md5[TUYA_BLE_FILE_MD5_LEN];

    UINT32_T data_len;
    UINT16_T pkt_id;
    UINT16_T pkt_len;
    UINT16_T pkt_crc16;
} TAL_BLE_FILE_INFO_T;

typedef struct {
    UINT8_T  type;
    UINT16_T file_id;
    UINT8_T  status;
    UINT16_T pkt_maxlen;
    UINT32_T stored_len;
    UINT8_T  stored_md5[TUYA_BLE_FILE_MD5_LEN];
} TAL_BLE_FILE_INFO_RSP_T;

typedef struct {
    UINT8_T  type;
    UINT16_T file_id;
    UINT32_T offset;
} TAL_BLE_FILE_OFFSET_REQ_T;

typedef struct {
    UINT8_T  type;
    UINT16_T file_id;
    UINT32_T offset;
} TAL_BLE_FILE_OFFSET_REP_T;

typedef struct {
    UINT8_T  type;
    UINT16_T file_id;
    UINT16_T pkt_id;
    UINT16_T pkt_len;
    UINT16_T pkt_crc16;
    UINT8_T *data;
} TAL_BLE_FILE_DATA_REQ_T;

typedef struct {
    UINT8_T  type;
    UINT16_T file_id;
    UINT8_T  status;
} TAL_BLE_FILE_DATA_RSP_T;

typedef struct {
    UINT8_T  type;
    UINT16_T file_id;
} TAL_BLE_FILE_END_REQ_T;

typedef struct {
    UINT8_T  type;
    UINT16_T file_id;
    UINT8_T  status;
} TAL_BLE_FILE_END_RSP_T;

typedef struct {
    UINT32_T file_addr; /*file store next addr, cur_file_addr = (file_addr -(file_len/0x1000+1)*0x1000*/
    UINT8_T  type;      /*cur file info */
    UINT16_T file_id;
    UINT32_T file_ver;
    UINT32_T file_len;
    UINT8_T  file_md5[TUYA_BLE_MD5_LEN];
    UINT8_T  id_len;
    UINT8_T  *id_buf;
} TAL_BLE_FILE_INFO_DATA_T;

typedef struct {
    mbedtls_md5_context ctx_storage; //md5 loop cac.
    UINT16_T cur_file_id; //operation data.
} TAL_BLE_FILE_MD5_INFO_T;

API description

  1. The application layer receives data through the registered callback tuya_ble_handle_ble_data_evt.

  2. Call tuya_ble_handle_ble_cmd_evt to parse data with the event ID TUYA_BLE_EVT_BLE_CMD.

    Steps 1 and 2 are the common processes for receiving and parsing data. The cmd determines how the data is processed.

  3. Call tuya_ble_sdk_callback with the event ID TUYA_BLE_CB_EVT_FILE_DATA to parse the received data and prepare a response packet.

  4. Call the generic event callback with the event ID TUYA_BLE_EVT_CUSTOM to return a response.

    The following sections detail the file transfer functions specified in steps 3 and 4.

tuya_ble_handle_file_req

Function name tuya_ble_handle_file_req
Function prototype void tuya_ble_handle_file_req(uint16_t cmd,uint8_t*p_recv_data,uint32_t recv_data_len)
Description Read the received file data.
Parameter
  • @param[in] cmd: The request command.
  • @param[in] p_recv_data: The pointer to the buffer with the received data.
  • @param[in] recv_data_len: The length of the received data.
Return value None
Notes None

Example:

void tuya_ble_handle_file_req(uint16_t cmd, uint8_t *recv_data, uint32_t recv_len)
{
  ......

    switch (cmd)
    {
    case FRM_FILE_INFOR_REQ:
        cmd_type = TUYA_BLE_FILE_INFO;
        break;
    case FRM_FILE_OFFSET_REQ:
        cmd_type = TUYA_BLE_FILE_OFFSET_REQ;
        break;
    case FRM_FILE_DATA_REQ:
        cmd_type = TUYA_BLE_FILE_DATA;
        break;
    case FRM_FILE_END_REQ:
        cmd_type = TUYA_BLE_FILE_END;
        break;
    default:
        cmd_type = TUYA_BLE_FILE_UNKONWN;
        break;
    }

    event.evt = TUYA_BLE_CB_EVT_FILE_DATA;
    event.file_data.type = cmd_type;
    event.file_data.data_len = data_len;
    event.file_data.p_data = ble_cb_evt_buffer;

    if (tuya_ble_cb_event_send(&event) != 0)
    {
        tuya_ble_free(ble_cb_evt_buffer);
        TUYA_BLE_LOG_ERROR("tuya_ble_handle_file_req-tuya ble send cb event failed.");
    }
  ......
}

tuya_ble_file_response

Function name tuya_ble_file_response
Function prototype tuya_ble_status_t tuya_ble_file_response(tuya_ble_file_response_t *p_data)
Description Respond to the file transfer.
Parameter p_data[in]: The response to the file transfer.
Return value
  • TUYA_BLE_SUCCESS: Success.
  • TUYA_BLE_ERR_INVALID_STATE: Invalid status. The file transfer cannot start because of issues such as Bluetooth disconnection.
  • TUYA_BLE_ERR_INVALID_LENGTH: Data length error.
  • TUYA_BLE_ERR_NO_MEM: Failed to request memory allocation.
  • TUYA_BLE_ERR_NO_EVENT: The queue is full.
Notes The device calls this function to return a response on receiving a file transfer request.

Example:

tuya_ble_status_t tuya_ble_file_response(tuya_ble_file_response_t *p_data)
{
   ......

    p_buffer = tuya_ble_malloc(sizeof(tuya_ble_file_response_t) + p_data->data_len);

    if(p_buffer)
    {
        p_res_data = (tuya_ble_file_response_t*)p_buffer;
        p_res_data->p_data = p_buffer + sizeof(tuya_ble_file_response_t);
        p_res_data->data_len = p_data->data_len;
        p_res_data->type = p_data->type;
        memcpy(p_res_data->p_data,p_data->p_data,p_data->data_len);
    }
    else
    {
       return TUYA_BLE_ERR_NO_MEM;
    }

    custom_evt.evt_id = 0;//res
    custom_evt.data = p_res_data;
    custom_evt.custom_event_handler = tuya_ble_handle_file_response_evt;

    TUYA_BLE_LOG_HEXDUMP_DEBUG("custom_data",(uint8_t*)p_res_data->p_data,p_res_data->data_len);

    if (tuya_ble_custom_event_send(custom_evt) != 0)
    {
        tuya_ble_free(p_buffer);
        return TUYA_BLE_ERR_NO_EVENT;
    }

    return TUYA_BLE_SUCCESS;
}
    if (rsp_flag)
    {
        tuya_ble_bulk_data_response(&rsp_data);
    }
}

Callback

tuya_ble_sdk sends status messages or data to the application layer through messages if an RTOS is available, or through registered application layer callbacks if an RTOS is not available.

When receiving file data from the mobile app, tuya_ble_sdk will send an event callback to the application layer.

TUYA_BLE_CB_EVT_FILE_DATA

Event TUYA_BLE_CB_EVT_FILE_DATA
Data structure tuya_ble_bulk_data_request_t
Description File transfer request callback.
Notes You can implement data transfer handlers in this callback.

Data structure

typedef enum
{
    TUYA_BLE_FILE_INFO,            /**< File Information*/
    TUYA_BLE_FILE_OFFSET_REQ,    /**< File offset*/
    TUYA_BLE_FILE_DATA,            /**< File data*/
    TUYA_BLE_FILE_END,            /**< File transfer completed*/
    TUYA_BLE_FILE_UNKONWN,        /**< Others*/
} tuya_ble_file_data_type_t;

typedef struct {
    tuya_ble_file_data_type_t type;
    uint16_t data_len;
    uint8_t *p_data;
} tuya_ble_file_response_t;

Example:

static void tuya_ble_sdk_callback(tuya_ble_cb_evt_param_t *event)
{
    switch (event->evt)
    {
        //...

       case TUYA_BLE_CB_EVT_FILE_DATA: {
#if (TUYA_BLE_FILE_ENABLE != 0)
            TUYA_APP_LOG_INFO("TUYA_BLE_CB_EVT_FILE_DATA");
            tuya_ble_file_handler(&event->file_data);
#endif
        } break;

        //...
    }
}

Example

void tuya_ble_file_handler(tuya_ble_file_data_t *file)
{
    tuya_ble_file_response_t rsp;
    rsp.type = file->type;

    if(file->type != TUYA_BLE_FILE_DATA) {
        TUYA_APP_LOG_INFO("file_type: %d", file->type);
        TUYA_APP_LOG_HEXDUMP_INFO("file_data", file->p_data, file->data_len);
    }

    switch (file->type)
    {
        case TUYA_BLE_FILE_INFO: {
            tuya_ble_file_info_handler(file->p_data, file->data_len, &rsp);
        } break;

        case TUYA_BLE_FILE_OFFSET_REQ: {
            tuya_ble_file_offset_handler(file->p_data, file->data_len, &rsp);
        } break;

        case TUYA_BLE_FILE_DATA: {
            tuya_ble_file_data_handler(file->p_data, file->data_len, &rsp);
        } break;

        case TUYA_BLE_FILE_END: {
            tuya_ble_file_end_handler(file->p_data, file->data_len, &rsp);
        } break;

        case TUYA_BLE_FILE_UNKONWN: {
        } break;

        default: {
        } break;
    }
}

How to use

Prerequisites

  • The test PID: ndhihx1m
  • You have installed the Smart Life app on your phone.
  • Your device has been paired.

Procedure

  1. Open the control panel and tap More.

    File Transfer
  2. The Lock Language option shows Language State Not Set. Tap it to open the language selection page.

    File Transfer
  3. Download and use the desired language.

  4. Wait for the file transfer to finish.

  5. When In Use status appears, the file transfer is completed.

Support and help

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