跳到主要内容

RTC TCP Client SDK 参考文档

1. 概述

RTC TCP Client(API 前缀 tai_*)是 tRTC(tuya自研RTC协议) 的 TCP 实现。以源码形式提供,通过 PAL(Platform Abstraction Layer)实现跨平台移植,适用于 POSIX、FreeRTOS(ESP-IDF)等环境。

头文件:tuya_ai.h(单一 include)

特点

  • 简洁 API:类型化发送函数(tai_send_texttai_send_audio_*tai_send_image),无需手动组装数据结构体
  • 后台接收线程tai_connect 后自动启动后台线程处理接收和 keepalive
  • 回调驱动:通过 on_audioon_texton_eventon_disconnect 接收数据
  • 无外部依赖:用户 PAL 只需提供原始 TCP 和平台原语;TLS 和加密由 SDK 内部通过 bundled mbedTLS 处理

2. 常量定义

2.1 数据包类型

说明
TAI_PKT_CLIENT_HELLO1客户端握手
TAI_PKT_PING4心跳请求
TAI_PKT_PONG5心跳响应
TAI_PKT_CONNECTION_CLOSE6连接关闭
TAI_PKT_SESSION_NEW7新建会话
TAI_PKT_SESSION_CLOSE8关闭会话
TAI_PKT_CONNECTION_REFRESH_REQ9连接刷新请求
TAI_PKT_CONNECTION_REFRESH_RESP10连接刷新响应
TAI_PKT_VIDEO30视频数据
TAI_PKT_AUDIO31音频数据
TAI_PKT_IMAGE32图像数据
TAI_PKT_FILE33文件数据
TAI_PKT_TEXT34文本数据
TAI_PKT_EVENT35事件数据

2.2 流标志(Stream Flags)

说明
TAI_STREAM_ONE_SHOT0x00单包(完整数据)
TAI_STREAM_START0x01流开始
TAI_STREAM_MIDDLE0x02流中间
TAI_STREAM_END0x03流结束

2.3 事件类型

说明
TAI_EVT_START0会话开始
TAI_EVT_PAYLOADS_END1负载结束
TAI_EVT_END2会话结束
TAI_EVT_ONE_SHOT3单次事件
TAI_EVT_CHAT_BREAK4聊天打断(用户中途说话)
TAI_EVT_SERVER_VAD5云端 VAD 检测到用户停止说话
TAI_EVT_MCP_CMD1000MCP 命令(设备侧执行)
TAI_EVT_SERVER_TIMEOVER1001服务端超时
TAI_EVT_UPDATE_CONTEXT1002上下文更新

2.4 客户端类型

说明
TAI_CLIENT_DEVICE1设备端
TAI_CLIENT_APP2应用端

2.5 音频编码

说明
TAI_AUDIO_PCM101原始 PCM
TAI_AUDIO_OPUS111Opus 编码

2.6 图像格式

说明
TAI_IMG_JPEG1JPEG
TAI_IMG_PNG2PNG

2.7 图像负载类型

说明
TAI_IMG_PAYLOAD_RAW0原始二进制
TAI_IMG_PAYLOAD_BASE641Base64 编码
TAI_IMG_PAYLOAD_URL2URL 字符串

2.8 签名级别

说明
TAI_SIGN_NONE0不签名
TAI_SIGN_HMAC_SHA11HMAC-SHA1
TAI_SIGN_HMAC_SHA2562HMAC-SHA256(推荐)

2.9 数据 ID

说明
TAI_DATA_ID_AUDIO_UP1上行音频
TAI_DATA_ID_AUDIO_DOWN2下行音频
TAI_DATA_ID_TEXT_UP3上行文本
TAI_DATA_ID_TEXT_DOWN4下行文本
TAI_DATA_ID_IMAGE_UP5上行图像
TAI_DATA_ID_AUDIO_AUX7辅助音频

2.10 返回码

说明
TAI_OK0成功
TAI_ERR_ARGS-1参数错误
TAI_ERR_MEM-2内存不足
TAI_ERR_NET-3网络错误
TAI_ERR_TLS-4TLS 错误
TAI_ERR_PROTO-5协议错误
TAI_ERR_HMAC-6HMAC 校验失败
TAI_ERR_AGAIN-7需要重试
TAI_ERR_CRYPTO-8加解密错误

3. 配置(tai_config_t

调用 tai_ctx_init 前填充此结构体。所有指针字段在 context 生命周期内必须保持有效。

3.1 服务器配置

字段类型说明
hostconst char *服务器地址(通常从 iot_client_get_session_token() 返回的 token 中解析得到)
portuint16_t服务器端口
tls_sniconst char *TLS SNI 主机名(通常与 host 相同;若 token 中提供域名,优先使用域名)

3.2 身份配置

字段类型说明
device_idconst char *设备 ID(配网后获得的 devid)
local_keyconst char *本地密钥(配网后获得的 local_key)
client_typeuint8_t客户端类型:TAI_CLIENT_DEVICETAI_CLIENT_APP
protocol_versionuint8_t协议版本:使用 TAI_VER_21

3.3 会话选项

字段类型说明
session_attrs_jsonconst char *会话属性 JSON(NULL 使用默认值)。可配置云端 VAD、音频格式等
event_user_data_jsonconst char *事件用户数据 JSON(NULL 使用默认值)
agent_tokenconst char *Agent Token(指定特定 Agent,NULL 使用产品默认 Agent)

3.4 业务标识

字段类型说明
biz_codeuint32_t业务码
biz_taguint64_t业务标签

3.5 安全配置

字段类型说明
sign_leveluint8_t签名级别:TAI_SIGN_NONE / TAI_SIGN_HMAC_SHA256(推荐)

3.6 保活配置

字段类型说明
ping_interval_msuint32_tPing 间隔(0 = 默认 60000ms)
ping_timeout_msuint32_tPing 超时(0 = 默认 90000ms)

3.7 测试配置

字段类型说明
disable_tlsuint8_t非零时跳过 TLS,仅用于集成测试

3.8 平台适配

字段类型说明
palconst pal_t *平台适配层实现指针

3.9 回调函数

所有回调均在后台接收线程中调用。

字段类型说明
on_audiofunction pointer音频数据回调
on_textfunction pointer文本数据回调
on_eventfunction pointer事件回调(MCP、打断、VAD 等)
on_disconnectfunction pointer断连回调
user_datavoid *透传到所有回调

回调签名:

void (*on_audio)(tai_ctx_t *ctx,
const uint8_t *data, size_t len,
uint32_t sample_rate, uint16_t frame_duration,
void *user_data);

void (*on_text)(tai_ctx_t *ctx,
const char *text, size_t len,
uint8_t stream_flag, // TAI_STREAM_*
void *user_data);

void (*on_event)(tai_ctx_t *ctx,
uint16_t event_type, // TAI_EVT_*
const uint8_t *data, size_t len,
void *user_data);

void (*on_disconnect)(tai_ctx_t *ctx,
uint16_t error_code,
void *user_data);

4. 生命周期 API

tai_ctx_size

size_t tai_ctx_size(void);

返回 context 所需的内存大小。调用方需分配至少此大小的内存,传给 tai_ctx_init


tai_ctx_init

tai_ctx_t *tai_ctx_init(void *mem, const tai_config_t *cfg);

初始化 context。mem 必须至少为 tai_ctx_size() 字节,且在 context 生命周期内保持有效。

参数:

  • mem — 预分配的内存块
  • cfg — 配置结构体

返回值: 成功返回 tai_ctx_t*(即 mem 强转),失败返回 NULL。


tai_ctx_deinit

void tai_ctx_deinit(tai_ctx_t *ctx);

反初始化 context,释放内部资源。调用后 mem 可以 free。必须在 tai_disconnect 之后调用。


tai_connect

int tai_connect(tai_ctx_t *ctx);

执行 TLS 握手、发送 ClientHello、建立会话、启动后台接收线程。

返回值: TAI_OK 成功,TAI_ERR_* 失败。

行为:

  • 阻塞直到连接建立或失败
  • 成功后,后台线程开始处理 Ping/Pong 和接收数据
  • 连接成功后即可调用 tai_send_* 系列函数

tai_disconnect

void tai_disconnect(tai_ctx_t *ctx);

停止后台接收线程,发送 SessionClose + ConnectionClose,关闭 TLS 连接。

行为:

  • 阻塞直到后台线程退出
  • 调用后不可再发送数据
  • 之后应调用 tai_ctx_deinit

5. 发送 API

tai_send_text

int tai_send_text(tai_ctx_t *ctx, const char *text, size_t len);

发送文本消息。单包完成(内部设置 ONE_SHOT 标志)。

参数:

  • text — UTF-8 文本
  • len — 文本字节数

返回值: TAI_OKTAI_ERR_*


tai_send_audio_start

int tai_send_audio_start(tai_ctx_t *ctx,
uint8_t codec, uint8_t channels,
uint8_t bit_depth, uint32_t sample_rate);

开始一段音频流。必须在 tai_send_audio_chunk 之前调用。

参数:

  • codec — 编码格式:TAI_AUDIO_PCM(101)或 TAI_AUDIO_OPUS(111)
  • channels — 声道数(通常为 1)
  • bit_depth — 位深(通常为 16)
  • sample_rate — 采样率(通常为 16000)

tai_send_audio_chunk

int tai_send_audio_chunk(tai_ctx_t *ctx, const uint8_t *pcm, size_t len);

发送一帧音频数据。可多次调用(流中间包)。

参数:

  • pcm — 音频数据(PCM 或 Opus 帧,取决于 audio_start 时的 codec)
  • len — 数据字节数

tai_send_audio_end

int tai_send_audio_end(tai_ctx_t *ctx);

结束音频流。通知服务端本次音频输入完毕,开始处理。


tai_send_image

int tai_send_image(tai_ctx_t *ctx,
const uint8_t *data, size_t len,
uint8_t format, uint16_t width, uint16_t height);

发送单张图片。

参数:

  • data — 图片二进制数据
  • len — 数据长度
  • format — 图片格式:TAI_IMG_JPEG(1)或 TAI_IMG_PNG(2)
  • width / height — 图片尺寸

tai_send_image_with_text

int tai_send_image_with_text(tai_ctx_t *ctx,
const char *text, size_t text_len,
const uint8_t *img_data, size_t img_len,
uint8_t format,
uint16_t width, uint16_t height);

同时发送文本和图片(如图片理解场景)。内部会先发文本包再发图片包,组成一次完整请求。


tai_chat_break

int tai_chat_break(tai_ctx_t *ctx);

发送聊天打断事件。用于用户主动打断 AI 回复(如按键中断)。服务端收到后会停止当前响应生成。


tai_send_mcp_response

int tai_send_mcp_response(tai_ctx_t *ctx, const char *json_rpc_response);

发送 MCP 命令的响应。当 on_event 收到 TAI_EVT_MCP_CMD 时,设备执行完命令后通过此函数返回结果。

参数:

  • json_rpc_response — JSON-RPC 格式的响应字符串

6. 日志

static inline void tai_set_log_level(int level);
static inline int tai_get_log_level(void);

设置/获取运行时日志级别。有效值:

含义
0禁用所有日志
1TAI_LOG_ERROR
2TAI_LOG_WARN
3TAI_LOG_INFO
4TAI_LOG_DEBUG(默认)

编译时可通过定义 TAI_LOG_LEVEL 宏设置最大编译级别(超过的日志在编译期消除)。


7. 典型使用流程

#include "tuya_ai.h"

// 1. 分配内存
void *mem = malloc(tai_ctx_size());

// 2. 配置
tai_config_t cfg = {
.host = "ai-gw.example.com",
.port = 8883,
.device_id = devid,
.local_key = local_key,
.client_type = TAI_CLIENT_DEVICE,
.protocol_version = TAI_VER_21,
.sign_level = TAI_SIGN_HMAC_SHA256,
.pal = &my_pal,
.on_audio = my_on_audio,
.on_text = my_on_text,
.on_event = my_on_event,
.on_disconnect = my_on_disconnect,
};

// 3. 初始化 + 连接
tai_ctx_t *ctx = tai_ctx_init(mem, &cfg);
if (tai_connect(ctx) != TAI_OK) { /* handle error */ }

// 4. 发送文本
tai_send_text(ctx, "hello", 5);

// 5. 或发送音频流
tai_send_audio_start(ctx, TAI_AUDIO_PCM, 1, 16, 16000);
while (has_audio) {
tai_send_audio_chunk(ctx, pcm_frame, frame_len);
}
tai_send_audio_end(ctx);

// 6. 响应通过回调异步接收...

// 7. 清理
tai_disconnect(ctx);
tai_ctx_deinit(ctx);
free(mem);

8. 线程安全

  • tai_send_* 函数是线程安全的,可以从任意线程调用
  • 所有回调在同一个后台接收线程中按序调用
  • 不要在回调中调用 tai_disconnecttai_ctx_deinit(会死锁)
  • 如需在回调中触发断连,应通过设置标志位由其他线程执行