菜单

AI控制云机API

DuoPlus云机自动化控制API

该API为云机内部提供出来的服务,可通过该API接口直接控制云机,执行一些自动化操作,比如:获取屏幕和UI元素、点击和长按、文本输入和键盘、滑动和滚动、应用与页面导航、等待与元素读取等

接入前提:在 DuoPlus 控制台“自动化”→“API”获取 API Key。目标云机须已开机(status == 1),且 HTTP 服务已启用(http_status 为 1 或 "1")。若云机尚未开机,先通过控制台或平台开机接口启动;本文件不包含开机接口。Gateway 使用该 API Key 作为 Bearer Token;部署时须确保设备侧鉴权与该 Key 匹配,否则可能返回 401。

1. 获取云机 IP、地区和自动化支持状态

调用 HTTP Gateway 前,必须先通过平台 list 接口取得目标云机的 ip 和 region,并确认 status == 1、http_status 为 1。

1.1 请求入口

text 复制代码
POST https://openapi.duoplus.cn/api/v1/cloudPhone/list

请求头:

http 复制代码
Content-Type: application/json
Lang: zh
DuoPlus-API-Key: <API_KEY>

1.2 请求参数

按云机 ID 精确查询:

json 复制代码
{
  "image_id": ["IMAGE_ID"],
  "page": 1,
  "pagesize": 100
}

也可按名称查询:

json 复制代码
{
  "name": "phone-name",
  "page": 1,
  "pagesize": 100
}
参数 必填 说明
page 否 页码,从 1 开始;不传默认第 1 页
pagesize 否 每页数量,最大 100;不传默认 10
image_id 否 云机 ID 数组,推荐使用精确 ID
name 否 云机名称;名称可能重复
link_status 否 连接状态数组
group_id 否 分组 ID
proxy_id 否 代理 ID

1.3 自动化必需的返回字段

响应包络示意:

json 复制代码
{
  "code": 200,
  "message": "success",
  "data": {
    "list": [
      {
        "id": "IMAGE_ID",
        "name": "phone-name",
        "status": 1,
        "ip": "10.0.0.10",
        "region": "sg",
        "http_status": 1
      }
    ],
    "total_page": 1
  }
}

上例只展示自动化需要的关键字段,服务端可能返回更多设备信息。

字段 用途
data.list[].id 云机 ID,用于确认选中了正确设备
data.list[].status 1 表示云机已开机;其他状态需先处理
data.list[].ip 作为 Gateway 请求头 CloudIP
data.list[].region 作为 Gateway 请求头 Region;以选中云机的实际返回值为准
data.list[].http_status 1/"1" 表示 HTTP 服务已启用;0/"0" 表示未启用
data.total_page 总页数;未按 ID 精确查询时需要遍历全部分页

成功必须同时满足 HTTP 请求成功和响应顶层 code == 200。

1.4 cURL 示例

bash 复制代码
curl -sS 'https://openapi.duoplus.cn/api/v1/cloudPhone/list' \
  -H 'Content-Type: application/json' \
  -H 'Lang: zh' \
  -H "DuoPlus-API-Key: $DUOPLUS_API_KEY" \
  --data '{"image_id":["IMAGE_ID"],"page":1,"pagesize":100}'

核对匹配项的 id 后,从该项提取:

text 复制代码
CloudIP = matched_phone.ip
Region  = matched_phone.region

只有 status == 1 且 String(http_status) == "1" 时才能继续调用自动化 Gateway。ip 不为空并不代表自动化已启用。若按名称查找,应遍历 total_page 的所有分页,并在名称重复时用 ID 确认目标。平台 OpenAPI 每个接口限 1 QPS;分页请求也应控制频率。

2. 自动化调用入口

所有自动化操作均请求:

text 复制代码
POST https://agent-gateway.duoplus.cn/agent-command
http 复制代码
Content-Type: application/json
Authorization: Bearer <API_KEY>
Region: <REGION>
CloudIP: <CLOUD_IP>
请求头 说明
Authorization Gateway 鉴权,格式为 Bearer <API_KEY>
Region 目标云机 list 返回的 region
CloudIP 云机私网 IP

云机必须已运行并启用 HTTP 服务。Gateway 返回 401 时,应检查 API Key 与设备鉴权配置,不要盲目重试。第 13 节 cURL 中的区域和 IP 示例值必须替换为目标云机的实际返回值。

3. 通用模型

operation 用途
health 检查 Gateway/后端健康状态
ready 检查自动化执行器是否就绪
submit 获取屏幕/UI 或执行 UI 动作
query 查询已保留的命令结果
stop 停止正在运行或卡住的任务

执行动作的通用请求:

json 复制代码
{
  "operation": "submit",
  "command_id": "click-element-1730000000000-a1b2c3d4",
  "task_id": "click-element-task-1730000000000-a1b2c3d4",
  "action": "execute",
  "payload": {
    "task_type": "ai",
    "task_id": "click-element-task-1730000000000-a1b2c3d4",
    "action": "execute",
    "action_name": "CLICK_ELEMENT",
    "params": {
      "text": "Search",
      "wait_after": 500
    }
  }
}
  • command_id 与 task_id 应唯一。
  • action_name 使用大写动作名。
  • 动作参数放入 payload.params。
  • 可在顶层加入 Unix 毫秒时间戳 deadline_at。
  • 同步动作最长约 300 秒,客户端超时可设为约 310 秒。

任意动作的 params 均可带:

参数 说明
wait_before 动作前等待时间,毫秒
wait_after 动作后等待时间,毫秒;导航/加载建议 500–1500

4. 健康与就绪检查

健康检查:

json 复制代码
{"operation":"health"}

就绪检查:

json 复制代码
{"operation":"ready"}

响应满足 executor == "ready" 或 ready == true 即表示执行器就绪。收到 503 或 NOT_READY 时,可在启动超时内继续轮询。

5. 获取屏幕和 UI 元素

5.1 请求

json 复制代码
{
  "operation": "submit",
  "command_id": "ui-state-1730000000000-a1b2c3d4",
  "task_id": "ui-state-task-1730000000000-a1b2c3d4",
  "action": "get_ui_state",
  "payload": {
    "task_type": "ai",
    "task_id": "ui-state-task-1730000000000-a1b2c3d4",
    "action": "get_ui_state",
    "lang": "zh"
  }
}

5.2 响应解析

result_json 是 JSON 字符串,需要二次解析:

javascript 复制代码
const outer = await response.json();
const result = JSON.parse(outer.result_json);

解析后的对象可能包含:

  • success:动作是否成功;
  • UI 元素树:用于按文本、资源 ID、内容描述等定位控件;
  • screenshot:Base64 编码的当前屏幕截图。

截图解码:

javascript 复制代码
const encoded = result.screenshot.replace(/^data:[^,]+,/, "");
const bytes = Buffer.from(encoded, "base64");

第一次操作前读取 UI;每次点击、输入、滑动或导航后再次读取,以真实屏幕变化验证结果。

6. 点击与长按

6.1 元素点击 CLICK_ELEMENT

json 复制代码
{"text":"Continue","wait_after":800}
参数 说明
resource_id Android 资源 ID,通常最稳定
content_desc 无障碍内容描述
text 元素显示文本
class_name Android 控件类名
element_order 多个元素匹配时的序号,从 0 开始
json 复制代码
{"resource_id":"com.example:id/login"}
json 复制代码
{"content_desc":"Search"}
json 复制代码
{"text":"Item","element_order":1}

优先选择:resource_id → content_desc/text → 坐标。

6.2 元素长按 LONG_ELEMENT

json 复制代码
{"text":"Message","duration":1200}

选择字段同 CLICK_ELEMENT,duration 单位为毫秒。

6.3 坐标动作

点击 CLICK_COORDINATE:

json 复制代码
{"x":500,"y":420,"wait_after":500}

长按 LONG_COORDINATE:

json 复制代码
{"x":500,"y":420,"duration":1200}

双击 DOUBLE_TAP_COORDINATE:

json 复制代码
{"x":500,"y":420}

坐标为 0..1000 的相对值,左上角 (0,0),右下角 (1000,1000):

text 复制代码
relative_x = round(pixel_x / screenshot_width  * 1000)
relative_y = round(pixel_y / screenshot_height * 1000)

坐标动作前应立即截图并取目标中心;页面跳转或旋转后不能复用旧坐标。

7. 文本输入和键盘

7.1 输入 INPUT_CONTENT

json 复制代码
{"content":"hello world","clear_first":true}

输入前必须先聚焦输入框:获取 UI → 点击输入框 → INPUT_CONTENT → 必要时发送 Enter → 再次获取 UI 验证。

7.2 键盘 KEYBOARD_OPERATION

json 复制代码
{"key":"enter"}

支持:enter、delete、tab、escape、space。

8. 滑动与滚动

动作名:SLIDE_PAGE。

默认手势:

json 复制代码
{"direction":"up","wait_after":600}

支持 up、down、left、right。向下浏览内容时,手指向上滑,因此使用 up。

自定义轨迹:

json 复制代码
{
  "direction": "up",
  "start_x": 520,
  "start_y": 780,
  "end_x": 500,
  "end_y": 260,
  "wait_after": 600
}

先尝试默认手势;每次滑动后重新读取屏幕。连续无效时轻微调整轨迹,同一目标通常最多尝试 3 次。

9. 应用与页面导航

打开应用 OPEN_APP:

json 复制代码
{"package_name":"com.android.settings","wait_after":1200}

返回桌面 GO_TO_HOME:

json 复制代码
{}

返回上一页 PAGE_BACK:

json 复制代码
{}

10. 等待与元素读取

固定等待 WAIT_TIME:

json 复制代码
{"wait_time":1500}

等待元素 WAIT_FOR_SELECTOR:

json 复制代码
{"resource_id":"com.example:id/result","timeout":15}

或:

json 复制代码
{"text":"Completed","timeout":10}

timeout 默认 10 秒。

读取单个元素文本 GET_SINGLE_ELEMENT_TEXT:

json 复制代码
{"resource_id":"com.example:id/title"}

可使用 text、resource_id、class_name 等选择字段。

11. 查询结果与停止任务

查询命令结果:

json 复制代码
{"operation":"query","command_id":"<COMMAND_ID>"}

停止卡住的任务:

json 复制代码
{
  "operation": "stop",
  "command_id": "stop-1730000000000-a1b2c3d4",
  "task_id": "<TASK_ID>",
  "reason": "operation timeout"
}

stop 仅用于长时间运行或卡住的任务,不用于正常完成操作。

12. 成功判定

对 submit 的 UI 动作,不能仅根据 HTTP 200 判断成功。必须同时满足:

  1. HTTP 请求成功;
  2. 外层 state == "SUCCEEDED";
  3. 二次解析后的 result_json.success == true;
  4. 重新获取 UI 后,屏幕状态符合预期。
javascript 复制代码
const outer = await response.json();
if (outer.state !== "SUCCEEDED") throw new Error("Gateway command failed");

const result = JSON.parse(outer.result_json);
if (result.success !== true) throw new Error("UI action failed");

// 再次调用 get_ui_state,验证真实界面结果。

13. 完整 cURL 示例

13.1 获取当前屏幕

bash 复制代码
curl -sS 'https://agent-gateway.duoplus.cn/agent-command' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $DUOPLUS_API_KEY" \
  -H "Region: $DUOPLUS_REGION" \
  -H "CloudIP: $DUOPLUS_CLOUD_IP" \
  --data '{
    "operation":"submit",
    "command_id":"ui-state-UNIQUE_ID",
    "task_id":"ui-state-task-UNIQUE_ID",
    "action":"get_ui_state",
    "payload":{
      "task_type":"ai",
      "task_id":"ui-state-task-UNIQUE_ID",
      "action":"get_ui_state",
      "lang":"zh"
    }
  }'

13.2 点击元素

bash 复制代码
curl -sS 'https://agent-gateway.duoplus.cn/agent-command' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $DUOPLUS_API_KEY" \
  -H "Region: $DUOPLUS_REGION" \
  -H "CloudIP: $DUOPLUS_CLOUD_IP" \
  --data '{
    "operation":"submit",
    "command_id":"click-UNIQUE_ID",
    "task_id":"click-task-UNIQUE_ID",
    "action":"execute",
    "payload":{
      "task_type":"ai",
      "task_id":"click-task-UNIQUE_ID",
      "action":"execute",
      "action_name":"CLICK_ELEMENT",
      "params":{"text":"Continue","wait_after":800}
    }
  }'

执行第 13 节示例前,设置 DUOPLUS_API_KEY、DUOPLUS_REGION、DUOPLUS_CLOUD_IP,并将每次请求中重复出现的 UNIQUE_ID 换成新的唯一值;同一次请求的顶层和 payload 中的 task_id 必须一致。示例为 Bash 语法;PowerShell 中环境变量写法不同。

14. 自动化建议

  • 每次动作前读取 UI,每次动作后重新读取并验证。
  • 优先使用元素选择器;WebView、Canvas 或无法识别的控件再使用坐标。
  • 导航或加载动作加入约 500–1500 ms 的 wait_after。
  • 同一策略最多重试 3 次;无变化时更换选择器、坐标或导航方式。
  • 验证码、支付、账户恢复或破坏性确认应暂停,由用户决定。
  • 截图只是观察结果,不能代替任务完成验证。
上一个
如何永久开启APP的无障碍权限
下一个
云手机RPA文档
最近修改: 2026-09-28Powered by