P2P 通道下发移动命令

更新时间:2026-04-28 05:50:50LLM 副本以 Markdown 格式查看下载 PDF

P2P Biz Command 模块用于通过 P2P 通道下发业务指令,主要应用于 云台控制移动摄像机旋转巡航计划 等运动控制场景。App 端通过 P2P 连接向设备下发运动指令,设备端解析并执行相应的电机动作,并将执行结果反馈给 App。

整体流程

App 端                          设备端
  |                               |
  |--- Skill 查询 --------------->|  (查询设备运动能力)
  |<-- Skill 回复 ----------------|  (返回支持的电机及能力)
  |                               |
  |--- Action 指令 -------------->|  (下发运动指令)
  |<-- 执行结果回复 --------------|  (反馈执行状态)
  |                               |
  |--- Cancel / Clean ----------->|  (取消/清理指令)
  |<-- 取消结果回复 --------------|

头文件引用

#include "tuya_ipc_p2p_biz_cmd.h"

关键数据结构

命令类型 BIZ_CMD_E

枚举值 说明
BIZ_CMD_SKILL_QUERY 查询设备运动能力集
BIZ_CMD_ACTION 执行运动指令
BIZ_CMD_ACTION_CANCEL 取消指定运动指令
BIZ_CMD_ACTION_CLEAN 清理某个 Session 所有待执行的指令

方向枚举 BIZ_DIR_E

枚举值 说明
BIZ_DIR_FRONT
BIZ_DIR_RIGHT_FRONT 右前
BIZ_DIR_RIGHT
BIZ_DIR_RIGHT_BACK 右后
BIZ_DIR_BACK
BIZ_DIR_LEFT_BACK 左后
BIZ_DIR_LEFT
BIZ_DIR_LEFT_FRONT 左前

可通过位运算组合使用,例如 BIZ_DIR_FRONT | BIZ_DIR_BACK 表示支持前后方向。

电机类型 BIZ_MOTOR_TYPE_E

枚举值 说明
BIZ_MOTOR_TYPE_PTZ 云台转动
BIZ_MOTOR_TYPE_MOVE_IPC 移动摄像机 360 度旋转
BIZ_MOTOR_TYPE_CRUISE_PLAN 巡航计划控制

命令状态 BIZ_CMD_STATUS_E

枚举值 说明
BIZ_CMD_STATUS_RECVED 已接收
BIZ_CMD_STATUS_FINISH 执行完成
BIZ_CMD_STATUS_FAIL 执行失败

转向指令 DIRECTION_T

typedef struct {
    BOOL_T valid;     // 是否有效
    INT_T  angle;     // 转动角度,单位:度
    INT_T  direction; // 转动方向,参考 BIZ_DIR_E
    INT_T  speed;     // 转动速度
    INT_T  time;      // 转动时间
} DIRECTION_T;

angledirection 互斥使用:要么指定一个具体方向,要么指定一个具体角度。

移动指令 MOVE_T

typedef struct {
    BOOL_T valid;     // 是否有效
    INT_T  angle;     // 角度范围,单位:度
    INT_T  direction; // 移动方向,参考 BIZ_DIR_E
    INT_T  speed;     // 移动速度
    INT_T  time;      // 移动时间(-1:持续移动,0:停止移动)
    INT_T  distance;  // 移动距离
} MOVE_T;

动作描述 ACTION_T

typedef struct {
    BOOL_T           is_valid;    // 是否有效
    INT_T            motor_id;    // 电机 ID
    BIZ_MOTOR_TYPE_E motor_type;  // 电机类型
    DIRECTION_T      direction;   // 转向指令
    MOVE_T           move;        // 移动指令
} ACTION_T;

运动命令 MOTION_CMD_T

typedef struct {
    UINT_T   cmd_id;        // 命令序号,每次新命令递增
    INT_T    motor_id;      // 电机 ID
    INT_T    actions_cnt;   // 动作数量
    ACTION_T actions[0];    // 柔性数组,具体动作列表
} MOTION_CMD_T;

取消命令 MOTION_CANCEL_CMD_T

typedef struct {
    UINT_T cmd_id;          // 本次命令序号
    UINT_T target_cmd_id;   // 要取消的目标命令 ID
} MOTION_CANCEL_CMD_T;

API 说明

初始化

tuya_ipc_media_stream_init 入参 on_biz_cmd_recv_cb 赋值,注册业务命令回调函数。

SDK 收到 P2P 业务指令后,会通过此回调将解析后的结构体传递给开发者。

回调函数原型:

typedef OPERATE_RET (*BIZ_CMD_CB)(
    UINT_T session_id,    // P2P 会话 ID
    BIZ_CMD_E cmd_type,   // 命令类型
    VOID *cmds,           // 命令数据(根据 cmd_type 转换为对应结构体)
    VOID *rets,           // 返回数据(仅 SKILL_QUERY 时使用)
    INT_T *rets_len       // 返回数据长度
);

反初始化

无需关注。

发送执行结果

OPERATE_RET tuya_ipc_p2p_biz_cmd_send_resp(
    UINT_T session_id,       // P2P 会话 ID
    UINT_T cmd_id,           // 命令 ID(来自 MOTION_CMD_T.cmd_id)
    BIZ_CMD_E cmd,           // 命令类型
    BIZ_CMD_STATUS_E status, // 执行状态:FINISH 或 FAIL
    CHAR_T *reason           // 失败原因,成功时传 NULL
);

运动指令执行完成后,必须 调用此接口向 App 反馈执行结果。

接入步骤

初始化模块并注册回调

// 注册 Biz cmd 回调
tuya_ipc_media_stream_init 入参 on_biz_cmd_recv_cb 赋值;

实现 Skill 查询回调

App 连接设备后会首先查询设备的运动能力。开发者需要根据产品实际硬件能力填写 MOTORS_SKILL_T 结构。

STATIC OPERATE_RET on_skill_query(VOID *rets, INT_T *rets_len)
{
    ...
}

MOTORS_SKILL_T 需要通过 tal_malloc 分配内存,SDK 内部会负责释放。

实现运动指令回调(核心)

回调函数中需要根据 cmd_type 分别处理不同类型的命令:

OPERATE_RET ty_app_p2p_biz_cmd_process(UINT_T session_id, BIZ_CMD_E cmd_type,
                                        VOID *cmds, VOID *rets, INT_T *rets_len)
{
    ...
}

回调函数中 不要阻塞,应采用异步方式将指令放入队列,由独立线程执行运动动作。阻塞回调会影响后续指令的下发时效。

处理 Action 指令

收到 BIZ_CMD_ACTION 时,将命令加入待执行队列,并覆盖同一 Session 的旧指令。

STATIC OPERATE_RET on_motion_action(UINT_T session_id, VOID *cmds)
{
    ...
}

处理 Cancel 与 Clean

// 取消指定命令
STATIC OPERATE_RET on_motion_cancel(UINT_T session_id, VOID *cmds)
{
    ...
}

// 清理某 Session 的所有待执行命令
STATIC OPERATE_RET on_motion_clean(UINT_T session_id)
{
    ...
}

执行运动并反馈结果

在独立线程中从队列取出指令并执行实际的电机控制操作,完成后必须调用 tuya_ipc_p2p_biz_cmd_send_resp 反馈结果:

// 执行运动


// 反馈执行结果
tuya_ipc_p2p_biz_cmd_send_resp(
    entry->session_id,
    entry->motion_cmd.cmd_id,
    BIZ_CMD_ACTION,
    BIZ_CMD_STATUS_FINISH,  // 或 BIZ_CMD_STATUS_FAIL
    NULL                     // 失败时填写原因字符串
);

设计要点

异步处理架构

回调函数(SDK 线程)             运动处理线程
    |                               |
    |-- 加入命令队列 -------------->|
    |   (立即返回,不阻塞)          |-- 取出命令
    |                               |-- 执行电机动作
    |                               |-- 发送执行结果
    |                               |-- 释放节点内存

命令覆盖机制

当同一 Session 连续下发多条运动指令时,新指令会覆盖旧指令:

  • 旧指令状态标记为 COVERED
  • 运动线程发现 COVERED 状态的节点时,发送 Finish 响应并释放。
  • 新指令加入队列头部,优先执行。

线程安全

所有对命令队列 cmd_list 的操作都需要通过 tal_mutex_lock / tal_mutex_unlock 加锁保护,包括:

  • 回调中添加/修改节点
  • 运动线程中读取/删除节点

开发者自定义清单

接入时需要根据产品实际情况修改以下内容:

项目 说明
MOTOR_CNT 电机数量,与硬件一致
motor_type 电机类型,参考 BIZ_MOTOR_TYPE_E
direction 能力 转向支持情况:是否支持角度、方向、速度、时间
move 能力 移动支持情况:方向组合、时间、距离
电机驱动调用 在运动线程中替换为实际的电机控制 API 调用
运动线程栈大小 根据实际需求调整 stackDepth(默认 512 KB)

错误码参考

错误码 说明
OPRT_OK 成功
OPRT_INVALID_PARM 参数无效
OPRT_MALLOC_FAILED 内存分配失败

更多错误码请参考 tuya_error_code.h