Skip to main content

盒子内SDK API 开发文档

MYT-SDK API 接口文档

更新日期 2026-5-6

📌 接口说明

访问地址: http://{主机IP}:8000/swagger

  • 主机IP:设备的网络IP地址(例如:192.168.99.108)
  • 端口:固定为 8000
  • 协议:HTTP

响应格式:所有接口统一返回JSON格式

{
"code": 0,
"message": "ok",
"data": { ... }
}
字段类型说明
codeint状态码,0表示成功,非0表示失败
messagestring状态信息
dataobject返回数据

📚 接口目录

  1. 基本信息
  2. 云机操作
  3. 云机备份
  4. 终端连接
  5. myt_bridge网卡管理
  6. macVlan网卡管理
  7. 魔云腾VPC
  8. 本地机型数据管理
  9. 接口认证
  10. 服务管理
  11. 大模型管理
  12. 云机操作V2镜像
  13. 用户

一、基本信息

1. 获取API版本信息

功能说明:获取当前API版本信息

请求方式:GET

请求URL

http://{主机IP}:8000/info

请求参数:无

请求示例

curl "http://192.168.99.108:8000/info"

成功返回

{
"code": 0,
"message": "ok",
"data": {
"latestVersion": 110,
"currentVersion": 108
}
}

返回字段说明

字段类型说明
latestVersionint线上最新版本号
currentVersionint当前本地版本号

失败返回

{
"code": 500,
"message": "获取版本信息失败",
"data": null
}

注意事项

  • 当 currentVersion < latestVersion 时,建议更新SDK

2. 获取设备基本信息

功能说明:获取当前设备的硬件和系统信息

请求方式:GET

请求URL

http://{主机IP}:8000/info/device

请求参数:无

请求示例

curl "http://192.168.99.108:8000/info/device"

成功返回

{
"code": 0,
"message": "ok",
"data": {
"ip": "192.168.99.108",
"ip_1": "192.168.100.108",
"hwaddr": "AA:BB:CC:DD:EE:FF",
"hwaddr_1": "AA:BB:CC:DD:EE:F1",
"cputemp": 45,
"cpuload": "1.5",
"memtotal": "8GB",
"memuse": "4.2GB",
"mmctotal": "256GB",
"mmcuse": "120GB",
"version": "v1.1.0",
"deviceId": "MYT-P1-001",
"model": "P1",
"speed": "1000Mbps",
"mmcread": "150MB/s",
"mmcwrite": "120MB/s",
"sysuptime": "10天5小时",
"mmcmodel": "Samsung EVO",
"mmctemp": "38",
"network4g": "未连接",
"netWork_eth0": "已连接"
}
}

返回字段说明

字段类型说明
ipstring网口IP
ip_1string网口1的IP
hwaddrstringMAC地址
hwaddr_1stringMAC1地址
cputempintCPU温度
cpuloadstringCPU负载
memtotalstring内存总大小
memusestring内存已使用大小
mmctotalstring磁盘总大小
mmcusestring磁盘已使用大小
versionstring固件版本
deviceIdstring设备ID
modelstring型号版本
speedstring网口速率
mmcreadstring磁盘读取量
mmcwritestring磁盘写入量
sysuptimestring设备运行时间
mmcmodelstring磁盘型号
mmctempstring磁盘温度
network4gstring4G网卡状态
netWork_eth0stringETH0网卡状态

失败返回

{
"code": 500,
"message": "获取设备信息失败",
"data": null
}

二、云机操作

1. 获取安卓云机列表

功能说明:获取设备上所有安卓云机容器列表

请求方式:GET

请求URL

http://{主机IP}:8000/android

请求参数

参数名必选类型说明
namestring根据云机名过滤
runningbool根据云机是否运行过滤,false查询所有
indexNumint根据云机实例位序号过滤(0-24)

请求示例

# 获取所有云机
curl "http://192.168.99.108:8000/android"

# 根据名称过滤
curl "http://192.168.99.108:8000/android?name=test"

# 只获取运行中的云机
curl "http://192.168.99.108:8000/android?running=true"

成功返回

{
"code": 0,
"message": "ok",
"data": {
"count": 2,
"list": [
{
"id": "abc123def456",
"name": "android-01",
"status": "running",
"indexNum": 1,
"dataPath": "/myt/data/android-01",
"modelPath": "/myt/model/android-01",
"image": "registry.example.com/android:v12",
"ip": "192.168.100.101",
"networkName": "myt_bridge",
"portBindings": {},
"dns": "223.5.5.5",
"doboxFps": "60",
"doboxWidth": "1080",
"doboxHeight": "1920",
"doboxDpi": "480",
"mgenable": "0",
"gmsenable": "0",
"s5User": "",
"s5Password": "",
"s5IP": "",
"s5Port": "",
"s5Type": "0",
"created": "2024-01-15 10:30:00",
"started": "2024-01-15 10:31:00",
"finished": "",
"customBinds": [],
"PINCode": ""
}
]
}
}

返回字段说明

字段类型说明
idstring云机容器ID
namestring云机名称
statusstring状态(running/stopped)
indexNumint云机实例位序号
dataPathstring云机Data文件在设备里的路径
modelPathstring云机机型文件在设备里的路径
imagestring云机所用的镜像
ipstring云机局域网IP
networkNamestring容器网卡名称
dnsstring云机DNS
doboxFpsstring云机FPS
doboxWidthstring云机分辨率的宽
doboxHeightstring云机分辨率的高
doboxDpistring云机DPI
mgenablestringmagisk开关,0-关,1-开
gmsenablestringgms开关,0-关,1-开
s5Userstrings5代理用户名
s5Passwordstrings5代理密码
s5IPstrings5代理IP
s5Portstrings5代理端口
s5Typestring代理类型,0-不开启,1-本地域名解析,2-服务器域名解析
createdstring云机容器创建时间
startedstring云机容器上次开启时间
finishedstring云机容器上次关闭时间
customBindsarray自定义文件映射
PINCodestring自定义屏幕锁屏密码

失败返回

{
"code": 500,
"message": "获取云机列表失败",
"data": null
}

2. 创建安卓云机

功能说明:创建一个新的安卓云机容器

请求方式:POST

请求URL

http://{主机IP}:8000/android

请求参数

参数名必选类型说明
namestring云机名称
imageUrlstring镜像完整地址
dnsstring云机DNS,例如223.5.5.5
modelIdstring线上机型ID
modelNamestring线上机型名称
LocalModelstring本地机型名称
modelStaticstring本地静态机型名称(优先级最高)
indexNumint实例序号,P1范围1-24,Q1范围1-12,传0自动分配
sandboxSizestring沙盒大小,例如16GB,32GB
offsetstring云机的开机时间
doboxFpsstring云机FPS
doboxWidthstring云机分辨率的宽
doboxHeightstring云机分辨率的高
doboxDpistring云机DPI
networkobject独立IP设置
startbool创建完成是否开机,默认true
mgenablestringmagisk开关,0-关,1-开,默认0
gmsenablestringgms开关,0-关,1-开,默认0
latitudefloat纬度
longitudefloat经度
countryCodestring国家代码,例如CN,US
portMappingsarray自定义端口映射
s5Userstrings5代理用户名
s5Passwordstrings5代理密码
s5IPstrings5代理IP
s5Portstrings5代理端口
s5Typestring代理类型,0-不开启,1-tun2socks,2-tun2proxy
mytBridgeNamestringmyt_bridge网卡名
customBindsarray自定义文件映射
PINCodestring屏幕锁屏密码,4-8位数字

network对象结构

字段类型说明
gwstring网关,例如192.168.100.1
ipstring云机要设置的IP
subnetstring掩码,例如192.168.100.0/24

portMappings数组元素结构

字段类型说明
containerPortint容器内端口
hostPortint主机端口
hostIPstring主机IP
protocolstring协议(tcp/udp),默认tcp

请求示例

curl -X POST "http://192.168.99.108:8000/android" \
-H "Content-Type: application/json" \
-d '{
"name": "android-01",
"imageUrl": "registry.example.com/android:v12",
"dns": "223.5.5.5",
"modelId": "1",
"indexNum": 1,
"doboxFps": "60",
"doboxWidth": "1080",
"doboxHeight": "1920",
"doboxDpi": "480",
"start": true
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {
"id": "abc123def456789"
}
}

失败返回

{
"code": 500,
"message": "创建云机失败: 镜像不存在",
"data": null
}

注意事项

  • name必须唯一,不能与已有云机重名
  • imageUrl必须是已拉取到本地的镜像地址
  • indexNum范围:P1设备1-24,Q1设备1-12
  • modelStatic优先级高于LocalModel和线上机型

3. 重置安卓云机

功能说明:重置指定的安卓云机

请求方式:PUT

请求URL

http://{主机IP}:8000/android

请求参数

参数名必选类型说明
namestring云机名称
latitudefloat纬度
longitudefloat经度
countryCodestring国家代码,例如CN,US

请求示例

curl -X PUT "http://192.168.99.108:8000/android" \
-H "Content-Type: application/json" \
-d '{
"name": "android-01",
"latitude": 39.9042,
"longitude": 116.4074,
"countryCode": "CN"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "重置云机失败: 云机不存在",
"data": null
}

注意事项

  • 重置会清除云机内的所有数据
  • 重置前请确保已备份重要数据

4. 删除安卓云机

功能说明:删除指定的安卓云机容器

请求方式:DELETE

请求URL

http://{主机IP}:8000/android

请求参数

参数名必选类型说明
namestring云机名称

请求示例

curl -X DELETE "http://192.168.99.108:8000/android" \
-H "Content-Type: application/json" \
-d '{
"name": "android-01"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "删除云机失败: 云机正在运行",
"data": null
}

注意事项

  • 删除操作不可恢复
  • 建议删除前先停止云机

5. 切换安卓镜像

功能说明:切换云机使用的安卓镜像

请求方式:POST

请求URL

http://{主机IP}:8000/android/switchImage

请求参数

参数名必选类型说明
namestring云机名称
imageUrlstring镜像完整地址
adbPortint自定义adb端口,默认5555,设置端口0的时候不开启adb,请不要使用9082、9083、10000、10001、10006、10007、10008等端口
dnsstring云机DNS
enforceboolean安全模式,默认开启
gmsenablestringgms开关,0-关,1-开
macVlanIpstring独立IP设置
mgenablestringmagisk开关,0-关,1-开
mytBridgeNamestringmyt_bridge网卡名,可以接口查询或在设备终端使用ifconfig查询
portMappingsarray增加自定义端口映射
containerPortint容器内端口,如80
hostIPstring主机IP,如 0.0.0.0 或 不填
hostPortint主机端口,如8080
protocolstring协议,如 tcp、udp, 默认tcp
randomFileboolean随机系统文件名
startboolean创建完成开机,默认不开机
vpcIDinteger添加的魔云腾VPC节点ID
whiteListDnsarraydns白名单
customBindsarray自定义文件映射

请求示例

curl -X POST "http://192.168.99.108:8000/android/switchImage" \
-H "Content-Type: application/json" \
-d '{
"name": "android-01",
"imageUrl": "registry.example.com/android:v13",
"start": true
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {
"message": "镜像切换成功"
}
}

失败返回

{
"code": 500,
"message": "切换镜像失败: 镜像不存在",
"data": null
}

注意事项:

  • 切换镜像有风险,有概率无法开机,需要先备份

6. 切换机型

功能说明:切换云机的机型配置

请求方式:POST

请求URL

http://{主机IP}:8000/android/switchModel

请求参数

参数名必选类型说明
namestring云机名称
modelIdstring机型ID
localModelstring本地机型名称
modelStaticstring本地静态机型名称
latitudefloat纬度
longitudefloat经度
countryCodestring国家代码

请求示例

curl -X POST "http://192.168.99.108:8000/android/switchModel" \
-H "Content-Type: application/json" \
-d '{
"name": "android-01",
"modelId": "2",
"countryCode": "US"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "切换机型失败: 机型不存在",
"data": null
}

7. 拉取安卓镜像

功能说明:从镜像仓库拉取安卓镜像到本地

请求方式:POST

请求URL

http://{主机IP}:8000/android/pullImage

请求参数

参数名必选类型说明
imageUrlstring镜像完整地址

请求示例

curl -X POST "http://192.168.99.108:8000/android/pullImage" \
-H "Content-Type: application/json" \
-d '{
"imageUrl": "registry.example.com/android:v12"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "拉取镜像失败: 网络连接超时",
"data": null
}

注意事项

  • 拉取镜像可能需要较长时间,取决于网络速度和镜像大小
  • 确保设备有足够的磁盘空间

8. 启动安卓云机

功能说明:启动指定的安卓云机

请求方式:POST

请求URL

http://{主机IP}:8000/android/start

请求参数

参数名必选类型说明
namestring云机名称

请求示例

curl -X POST "http://192.168.99.108:8000/android/start" \
-H "Content-Type: application/json" \
-d '{
"name": "android-01"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "启动云机失败: 云机已在运行",
"data": null
}

9. 关闭安卓云机

功能说明:关闭指定的安卓云机

请求方式:POST

请求URL

http://{主机IP}:8000/android/stop

请求参数

参数名必选类型说明
namestring云机名称

请求示例

curl -X POST "http://192.168.99.108:8000/android/stop" \
-H "Content-Type: application/json" \
-d '{
"name": "android-01"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "关闭云机失败: 云机未运行",
"data": null
}

10. 重启安卓云机

功能说明:重启指定的安卓云机

请求方式:POST

请求URL

http://{主机IP}:8000/android/restart

请求参数

参数名必选类型说明
namestring云机名称

请求示例

curl -X POST "http://192.168.99.108:8000/android/restart" \
-H "Content-Type: application/json" \
-d '{
"name": "android-01"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "重启云机失败",
"data": null
}

11. 获取本地镜像列表

功能说明:获取设备上已拉取的Docker镜像列表

请求方式:GET

请求URL

http://{主机IP}:8000/android/image

请求参数

参数名必选类型说明
imageNamestring根据镜像名过滤

请求示例

curl "http://192.168.99.108:8000/android/image"

# 根据名称过滤
curl "http://192.168.99.108:8000/android/image?imageName=android"

成功返回

{
"code": 0,
"message": "ok",
"data": {
"count": 2,
"list": [
{
"id": "sha256:abc123",
"imageUrl": "registry.example.com/android:v12",
"size": "2.5GB",
"created": "2024-01-10 08:00:00",
"labels": {
"version": "12",
"type": "android"
}
},
{
"id": "sha256:def456",
"imageUrl": "registry.example.com/android:v13",
"size": "2.8GB",
"created": "2024-01-15 10:00:00",
"labels": {
"version": "13",
"type": "android"
}
}
]
}
}

返回字段说明

字段类型说明
idstring镜像ID
imageUrlstring镜像完整地址
sizestring镜像大小
createdstring创建时间
labelsobject镜像labels

失败返回

{
"code": 500,
"message": "获取镜像列表失败",
"data": null
}

12. 删除本地镜像

功能说明:删除设备上的本地Docker镜像

请求方式:DELETE

请求URL

http://{主机IP}:8000/android/image

请求参数

参数名必选类型说明
imageUrlstring要删除的镜像完整地址

请求示例

curl -X DELETE "http://192.168.99.108:8000/android/image" \
-H "Content-Type: application/json" \
-d '{
"imageUrl": "registry.example.com/android:v12"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "删除镜像失败: 镜像正在被使用",
"data": null
}

注意事项

  • 正在被云机使用的镜像无法删除
  • 删除前请确保没有云机依赖该镜像

13. 获取本地镜像压缩包列表

功能说明:获取设备上的镜像压缩包文件列表

请求方式:GET

请求URL

http://{主机IP}:8000/android/imageTar

请求参数

参数名必选类型说明
filenamestring根据文件名过滤

请求示例

curl "http://192.168.99.108:8000/android/imageTar"

成功返回

{
"code": 0,
"message": "ok",
"data": {
"count": 2,
"list": [
{
"name": "android_v12.tar",
"size": "2.5GB"
},
{
"name": "android_v13.tar",
"size": "2.8GB"
}
]
}
}

失败返回

{
"code": 500,
"message": "获取镜像压缩包列表失败",
"data": null
}

14. 删除本地镜像压缩包

功能说明:删除设备上的镜像压缩包文件

请求方式:DELETE

请求URL

http://{主机IP}:8000/android/imageTar

请求参数

参数名必选类型说明
filenamestring要删除的镜像压缩包名称

请求示例

curl -X DELETE "http://192.168.99.108:8000/android/imageTar" \
-H "Content-Type: application/json" \
-d '{
"filename": "android_v12.tar"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "删除镜像压缩包失败: 文件不存在",
"data": null
}

15. 导出安卓镜像

功能说明:将本地镜像导出为压缩包文件

请求方式:POST

请求URL

http://{主机IP}:8000/android/image/export

请求参数

参数名必选类型说明
imageUrlstring要导出的镜像完整地址

请求示例

curl -X POST "http://192.168.99.108:8000/android/image/export" \
-H "Content-Type: application/json" \
-d '{
"imageUrl": "registry.example.com/android:v12"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {
"filename": "android_v12_20240115.tar"
}
}

失败返回

{
"code": 500,
"message": "导出镜像失败: 磁盘空间不足",
"data": null
}

注意事项

  • 导出过程可能需要较长时间
  • 确保设备有足够的磁盘空间

16. 下载导出后的安卓镜像包

功能说明:下载已导出的镜像压缩包文件

请求方式:GET

请求URL

http://{主机IP}:8000/android/image/download

请求参数

参数名必选类型说明
filenamestring要下载的镜像包名

请求示例

curl "http://192.168.99.108:8000/android/image/download?filename=android_v12.tar" -o android_v12.tar

成功返回

  • 返回文件的二进制数据,浏览器会自动下载

失败返回

{
"code": 500,
"message": "下载失败: 文件不存在",
"data": null
}

17. 导入安卓镜像

功能说明:通过上传tar文件导入安卓镜像

请求方式:POST

请求URL

http://{主机IP}:8000/android/image/import

Content-Typemultipart/form-data

请求参数

参数名必选类型说明
filefile导入镜像包文件,tar格式

请求示例

curl -X POST "http://192.168.99.108:8000/android/image/import" \
-F "file=@android_v12.tar"

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "导入镜像失败: 文件格式错误",
"data": null
}

注意事项

  • 仅支持tar格式的镜像包
  • 导入过程可能需要较长时间

18. 导出安卓云机

功能说明:将安卓云机导出为压缩包

请求方式:POST

请求URL

http://{主机IP}:8000/android/export

请求参数

参数名必选类型说明
namestring云机名称

请求示例

curl -X POST "http://192.168.99.108:8000/android/export" \
-H "Content-Type: application/json" \
-d '{
"name": "android-01"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {
"exportName": "android-01_20240115.zip"
}
}

失败返回

{
"code": 500,
"message": "导出云机失败: 云机正在运行",
"data": null
}

注意事项

  • 建议导出前先停止云机
  • 导出文件包含云机的完整数据

19. 导入安卓云机

功能说明:通过上传文件导入安卓云机

请求方式:POST

请求URL

http://{主机IP}:8000/android/import

Content-Typemultipart/form-data

请求参数

参数名必选类型说明
filefile导入使用本SDK导出的安卓云机
indexNumint实例序号,P1范围1-24,Q1范围1-12
namestring导入后云机名称

请求示例

curl -X POST "http://192.168.99.108:8000/android/import" \
-F "file=@android-01_20240115.zip" \
-F "indexNum=2" \
-F "name=android-02"

成功返回

{
"code": 0,
"message": "ok",
"data": {
"name": "android-02"
}
}

失败返回

{
"code": 500,
"message": "导入云机失败: 实例位已被占用",
"data": null
}

注意事项

  • 仅支持本SDK导出的云机文件
  • indexNum不能与已有云机冲突

20. 获取机型列表

功能说明:获取线上可用的机型列表

请求方式:GET

请求URL

http://{主机IP}:8000/android/phoneModel

请求参数:无

请求示例

curl "http://192.168.99.108:8000/android/phoneModel"

成功返回

{
"code": 0,
"message": "ok",
"data": {
"total": 50,
"list": [
{
"id": "1",
"name": "Samsung Galaxy S23",
"md5": "abc123def456",
"status": "active",
"currentVersion": 1,
"sdk_ver": "v1.1.0",
"createdAt": 1705286400
},
{
"id": "2",
"name": "Xiaomi 14",
"md5": "def456ghi789",
"status": "active",
"currentVersion": 1,
"sdk_ver": "v1.1.0",
"createdAt": 1705286400
}
]
}
}

返回字段说明

字段类型说明
idstring机型ID
namestring机型名称
md5string机型文件MD5
statusstring状态
currentVersionint当前版本
sdk_verstring对应SDK版本
createdAtint64创建时间戳

失败返回

{
"code": 500,
"message": "获取机型列表失败",
"data": null
}

21. 获取国家代码列表

功能说明:获取可用的国家代码列表

请求方式:GET

请求URL

http://{主机IP}:8000/android/countryCode

请求参数:无

请求示例

curl "http://192.168.99.108:8000/android/countryCode"

成功返回

{
"code": 0,
"message": "ok",
"data": {
"count": 200,
"list": [
{
"countryName": "中国",
"countryCode": "CN"
},
{
"countryName": "美国",
"countryCode": "US"
},
{
"countryName": "日本",
"countryCode": "JP"
}
]
}
}

失败返回

{
"code": 500,
"message": "获取国家代码列表失败",
"data": null
}

22. 设置Macvlan

功能说明:设置Macvlan网络配置

请求方式:POST

请求URL

http://{主机IP}:8000/android/macvlan

请求参数

参数名必选类型说明
gwstring网关,例如192.168.100.1
subnetstring掩码,例如192.168.100.0/24

请求示例

curl -X POST "http://192.168.99.108:8000/android/macvlan" \
-H "Content-Type: application/json" \
-d '{
"gw": "192.168.100.1",
"subnet": "192.168.100.0/24"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "设置Macvlan失败: 网关格式错误",
"data": null
}

注意事项

  • 设置后需要重启相关云机才能生效
  • 确保网关和子网配置正确

23. 设置云机容器IP (Macvlan模式)

功能说明:在Macvlan模式下设置云机容器的IP地址

请求方式:POST

请求URL

http://{主机IP}:8000/android/macvlan

请求参数

参数名必选类型说明
namestring云机名称
ipstring云机要设置的IP

请求示例

curl -X POST "http://192.168.99.108:8000/android/macvlan" \
-H "Content-Type: application/json" \
-d '{
"name": "android-01",
"ip": "192.168.100.101"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "设置IP失败: IP已被占用",
"data": null
}

24. 修改云机容器名称

功能说明:修改云机容器的名称

请求方式:POST

请求URL

http://{主机IP}:8000/android/rename

请求参数

参数名必选类型说明
namestring云机当前名称
newNamestring云机新名称

请求示例

curl -X POST "http://192.168.99.108:8000/android/rename" \
-H "Content-Type: application/json" \
-d '{
"name": "android-01",
"newName": "my-android"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "修改名称失败: 新名称已存在",
"data": null
}

注意事项

  • 新名称不能与已有云机重名
  • 建议在云机停止状态下修改

25. 获取机型备份列表

功能说明:获取已备份的机型数据列表

请求方式:GET

请求URL

http://{主机IP}:8000/android/backup/model

请求参数:无

请求示例

curl "http://192.168.99.108:8000/android/backup/model"

成功返回

{
"code": 0,
"message": "ok",
"data": {
"count": 3,
"list": [
{
"name": "samsung_s23_backup"
},
{
"name": "xiaomi_14_backup"
}
]
}
}

失败返回

{
"code": 500,
"message": "获取机型备份列表失败",
"data": null
}

26. 删除机型备份

功能说明:删除指定的机型备份数据

请求方式:DELETE

请求URL

http://{主机IP}:8000/android/backup/model

请求参数

参数名必选类型说明
namestring机型备份文件名称

请求示例

curl -X DELETE "http://192.168.99.108:8000/android/backup/model" \
-H "Content-Type: application/json" \
-d '{
"name": "samsung_s23_backup"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "删除机型备份失败: 文件不存在",
"data": null
}

27. 备份机型数据

功能说明:将V3镜像创建的云机里的机型数据完整备份

请求方式:POST

请求URL

http://{主机IP}:8000/android/backup/model

请求参数

参数名必选类型说明
namestring要备份机型数据的云机名称
suffixstring备份后机型数据的后缀名

请求示例

curl -X POST "http://192.168.99.108:8000/android/backup/model" \
-H "Content-Type: application/json" \
-d '{
"name": "android-01",
"suffix": "backup_20240115"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "备份机型数据失败: 云机不存在",
"data": null
}

注意事项

  • 仅支持V3镜像创建的云机
  • 备份前建议停止云机

28. 导出机型备份数据

功能说明:导出已备份的机型数据

请求方式:POST

请求URL

http://{主机IP}:8000/android/backup/modelExport

请求参数

参数名必选类型说明
namestring备份机型数据文件名称

请求示例

curl -X POST "http://192.168.99.108:8000/android/backup/modelExport" \
-H "Content-Type: application/json" \
-d '{
"name": "samsung_s23_backup"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "导出机型备份失败: 文件不存在",
"data": null
}

29. 导入备份机型数据

功能说明:通过上传ZIP包导入备份的机型数据

请求方式:POST

请求URL

http://{主机IP}:8000/android/backup/modelImport

Content-Typemultipart/form-data

请求参数

参数名必选类型说明
filefile导入备份机型数据ZIP包

请求示例

curl -X POST "http://192.168.99.108:8000/android/backup/modelImport" \
-F "file=@samsung_s23_backup.zip"

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "导入机型备份失败: 文件格式错误",
"data": null
}

注意事项

  • 仅支持ZIP格式的备份文件

30. 安卓云机执行命令

功能说明:在安卓云机内执行命令

请求方式:POST

请求URL

http://{主机IP}:8000/android/exec

请求参数

参数名必选类型说明
namestring云机名称
commandarray执行的命令,数组形式

请求示例

下载并安装小红书 APK
curl --location --request POST 'http://192.168.99.91:8000/android/exec' \
--header 'User-Agent: Apifox/1.0.0 (https://apifox.com)' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'Host: 192.168.99.91:8000' \
--header 'Connection: keep-alive' \
--data-raw '{
"name": "3333333",
"command": ["sd", "-c", "curl -fsSL -o /sdcard/Download/xhs.apk https://redgray.xhscdn.com/ui/androidPublish/prod/xhs/channel/apk/9.17.0/9170809/v9170809-xhs-share_package_common_X64.apk && cp /sdcard/Download/xhs.apk /data/local/tmp/xhs.apk && pm install /data/local/tmp/xhs.apk && rm /data/local/tmp/xhs.apk"]
}'

成功返回

  Success

失败返回

{
"code": 500,
"message": "执行命令失败: 云机未运行",
"data": null
}

注意事项

  • 云机必须处于运行状态
  • command参数为数组格式,例如 ["sd", "-c", "ls -la"]

31. 清理所有未被使用镜像

功能说明:清理设备上所有未被云机使用的镜像

请求方式:POST

请求URL

http://{主机IP}:8000/android/pruneImages

请求参数:无

请求示例

curl -X POST "http://192.168.99.108:8000/android/pruneImages"

成功返回

{
"code": 0,
"message": "ok",
"data": {
"pruneCount": 5,
"releaseSpace": "12.5GB"
}
}

返回字段说明

字段类型说明
pruneCountint清理数量
releaseSpacestring释放空间

失败返回

{
"code": 500,
"message": "清理镜像失败",
"data": null
}

注意事项

  • 此操作不可恢复
  • 仅清理未被任何云机使用的镜像

32. 批量切换容器镜像

功能说明:清理设备上所有未被云机使用的镜像

请求方式:POST

请求URL

http://{主机IP}:8000/android/change-image

请求参数

参数名必选类型说明
containerNamesarray云机容器名称列表
imagestring目标镜像完整地址

请求示例

curl http://192.168.99.108:8000/android/change-image \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"containerNames": [
"test-1", "test-2", "test-3"
],
"image": "registry.cn-guangzhou.aliyuncs.com/mytos/dobox:myt_supser_sdk_v1.0.14.30.36.1",
}'

成功返回

{
"code": 0,
"message": "OK",
"data": {
"taskId": "mdezt502491dgy413sp0hpf200goqkoa",
"message": "任务已提交,请使用 taskId 查询进度"
}
}

返回字段说明

字段类型说明
messagestring任务提交成功
taskIdstring任务ID

失败返回

{
"code": 51,
"message": "The image field is required",
"data": null
}

33. 复制云机

功能说明:复制指定云机的配置和数据,创建多个相同的云机实例

请求方式:GET

请求URL

http://{主机IP}:8000/android/copy

请求参数

参数名必选类型说明
namestring云机名称
indexNumint实例序号,P1范围1-24,Q1范围1-12,要复制到的目标实例号
countint复制的数量,一次最大20个

请求示例

GET "http://192.168.99.108:8000/android/copy?name=1772502684783_2_T0002&indexNum=6"
或者
curl 'curl 'http://192.168.99.108:8000/android/copy?name=1772502684783_2_T0002&indexNum=6'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 0,
"message": "ok",
"data": {}
}

34. 查询指定任务进度

功能说明:复制指定云机的配置和数据,创建多个相同的云机实例

请求方式:GET

请求URL

http://{主机IP}:8000/android/task-status

请求参数

参数名必选类型说明
taskIdstring任务 ID(异步任务返回的 taskId)

请求示例

GET "http://192.168.99.108:8000/android/copy?task-status?taskId=mdezt502491dgy413sp0hpf200goqkoa"
或者
curl 'http://192.168.99.183:8000/android/task-status?taskId=mdezt502491dgy413sp0hpf200goqkoa'

成功返回

{
"code": 0,
"message": "ok",
"data": {
"taskId": "tmdezt502491dgy413sp0hpf200goqkoa",
"taskType": "change-image",
"progress": 80,
"status": "running",
"successCount": 2,
"failCount": 0,
"totalCount": 3,
"failDetail": [],
"createTime": "2026-03-09 16:30:00",
"updateTime": "2026-03-09 16:35:00"
}
}

失败返回

{
"code": 50,
"message": "任务不存在",
"data": null
}

35. 通过URL导入云机

功能说明:通过备份包直链地址导入安卓云机

请求方式:POST

请求URL

http://{主机IP}:8000/android/importByUrl

请求参数

参数名必选类型说明
urlstring备份包直链地址,仅支持http/https
indexNumint实例序号,P1范围1-24,Q1范围1-12
namestring导入后云机名称

请求示例

curl -X POST "http://192.168.99.108:8000/android/importByUrl" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/backups/android-01.zip",
"indexNum": 3,
"name": "android-imported"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {
"name": "android-imported"
}
}

失败返回

{
"code": 500,
"message": "导入云机失败: 网络连接超时",
"data": null
}

注意事项

  • 仅支持http/https协议的直链地址
  • indexNum不能与已有云机冲突

36. 导出安卓云机到共享存储

功能说明:将安卓云机导出到共享存储服务

请求方式:POST

请求URL

http://{主机IP}:8000/android/exportToOss

请求参数

参数名必选类型说明
namestring要导出的云机名称
ossUrlstring共享存储地址,例如http://192.168.1.100:8080
bucketstring存储桶名称
filePathstring文件存储路径,不填则自动生成
accessKeystring访问密钥(private Bucket时必填)

请求示例

curl -X POST "http://192.168.99.108:8000/android/exportToOss" \
-H "Content-Type: application/json" \
-d '{
"name": "android-01",
"ossUrl": "http://192.168.1.100:8080",
"bucket": "my-bucket",
"filePath": "backups/android-01.tar.gz"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {
"url": "http://192.168.1.100:8080/my-bucket/backups/android-01.tar.gz"
}
}

失败返回

{
"code": 500,
"message": "导出云机失败: OSS连接失败",
"data": null
}

注意事项

  • 建议导出前先停止云机
  • 确保OSS服务可用且bucket存在

三、云机备份

1. 获取备份压缩包文件列表

功能说明:获取设备上的云机备份压缩包文件列表

请求方式:GET

请求URL

http://{主机IP}:8000/backup

请求参数

参数名必选类型说明
namestring根据文件名过滤

请求示例

curl "http://192.168.99.108:8000/backup"

成功返回

{
"code": 0,
"message": "ok",
"data": {
"count": 3,
"list": [
{
"name": "android-01_20240115.zip",
"size": "1.2GB"
},
{
"name": "android-02_20240116.zip",
"size": "1.5GB"
}
]
}
}

返回字段说明

字段类型说明
namestring备份压缩包文件名
sizestring备份压缩包大小

失败返回

{
"code": 500,
"message": "获取备份列表失败",
"data": null
}

2. 下载备份压缩包文件

功能说明:下载指定的云机备份压缩包

请求方式:GET

请求URL

http://{主机IP}:8000/backup/download

请求参数

参数名必选类型说明
namestring备份压缩包文件名

请求示例

GET "http://192.168.99.108:8000/backup/download?name=android-01_20240115.zip"

curl "http://192.168.99.108:8000/backup/download?name=android-01_20240115.zip" -o android-01_20240115.zip

成功返回

  • 返回文件的二进制数据,浏览器会自动下载

失败返回

{
"code": 500,
"message": "下载失败: 文件不存在",
"data": null
}

3. 删除备份压缩包文件

功能说明:删除指定的云机备份压缩包

请求方式:DELETE

请求URL

http://{主机IP}:8000/backup

请求参数

参数名必选类型说明
namestring备份压缩包文件名

请求示例

curl -X DELETE "http://192.168.99.108:8000/backup" \
-H "Content-Type: application/json" \
-d '{
"name": "android-01_20240115.zip"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "删除备份失败: 文件不存在",
"data": null
}

四、终端连接

1. 连接设备SSH

1.1. 接口概述

功能: 通过 WebSocket 在浏览器中连接到设备的 SSH 终端

协议: WebSocket (基于 HTTP Upgrade)

端点: ws://{host}:8000/link/sshwss://{host}:8000/link/ssh

认证: 需要 HTTP Basic Auth (与其他 myt-sdk API 相同)

适用场景:

  • Web 界面直接 SSH 到设备 (ARM 板、服务器等)
  • 无需本地 SSH 客户端
  • 云手机平台的设备运维和调试

与容器终端的区别:

  • 容器终端 (/link/exec): 连接到 Docker 容器内部
  • 设备 SSH (/link/ssh): 连接到宿主机或远程设备的 SSH 服务

1.2. 连接建立

1.2.1 WebSocket 握手
// 前端示例
const wsUrl =
(location.protocol === "https:" ? "wss://" : "ws://") +
location.host +
"/link/ssh";

const socket = new WebSocket(wsUrl);
socket.binaryType = "arraybuffer"; // 重要:设置为二进制模式

socket.onopen = () => {
console.log("WebSocket 连接已建立");
};

socket.onmessage = (event) => {
// SSH 输出始终是二进制数据
if (event.data instanceof ArrayBuffer) {
const bytes = new Uint8Array(event.data);
// 传递给终端模拟器渲染
terminal.write(bytes);
} else {
// 文本消息 (错误提示)
console.log("服务端消息:", event.data);
}
};

socket.onerror = (error) => {
console.error("WebSocket 错误:", error);
};

socket.onclose = () => {
console.log("WebSocket 连接已关闭");
};
1.2.2 认证方式

两层认证:

  1. WebSocket 层认证: HTTP Basic Auth (访问 myt-sdk API)
  2. SSH 层认证: 用户名 + 密码 (登录目标设备)
// WebSocket 层认证 (同域下自动携带 Cookie)
// 如果跨域,需要在 URL 中携带凭证或通过代理

// SSH 层认证 (通过 login 消息发送)
socket.send(
JSON.stringify({
type: "login",
ip: "192.168.1.100",
port: 22,
user: "root",
password: "your_password",
}),
);

1.3. 消息协议

1.3.1 消息格式

所有客户端发送的消息均为 JSON 文本格式:

{
"type": "消息类型",
"...": "其他字段"
}

服务端返回的消息分为两种:

  • 二进制消息: SSH 终端的输出 (stdout/stderr)
  • 文本消息: 错误提示或状态信息
1.3.2 消息类型详解
1.3.2.1 login - SSH 登录

方向: 客户端 → 服务端

时机: WebSocket 连接建立后立即发送

字段:

字段类型必填说明
typestring固定值 "login"
ipstring目标设备 IP 地址
portintSSH 端口 (通常为 22)
userstringSSH 用户名(默认user)
passwordstringSSH 密码(默认myt)

示例:

{
"type": "login",
"ip": "192.168.1.100",
"port": 22,
"user": "root",
"password": "mypassword"
}

说明:

  • ip 可以是 IPv4 地址、IPv6 地址或域名
  • port 默认 SSH 端口为 22,如果设备使用自定义端口需指定
  • 认证方式仅支持密码认证,不支持密钥认证
  • SSH 连接超时时间为 5 秒

错误响应示例:

SSH连接失败: dial tcp 192.168.1.100:22: i/o timeout
SSH连接失败: ssh: handshake failed: ssh: unable to authenticate
创建Session失败
RequestPty 失败
启动 Shell 失败

成功响应示例:

成功连接到 192.168.1.100:22
1.3.2.2 stdin - 用户输入

方向: 客户端 → 服务端

时机: 用户在终端中输入字符时

字段:

字段类型必填说明
typestring固定值 "stdin"
datastring用户输入的数据 (包括控制字符)

示例:

{
"type": "stdin",
"data": "ls -la\r"
}

说明:

  • data 包含原始按键数据,包括:
    • 普通字符: a, b, 1, 2
    • 回车: \r\n
    • 退格: \x7f (DEL) 或 \x08 (BS)
    • 方向键: \x1b[A (上), \x1b[B (下), \x1b[C (右), \x1b[D (左)
    • Ctrl+C: \x03
    • Ctrl+D: \x04
  • 数据会直接写入 SSH 会话的 stdin
1.3.2.3 resize - 调整终端大小

方向: 客户端 → 服务端

时机: 浏览器窗口大小变化时

字段:

字段类型必填说明
typestring固定值 "resize"
colsint终端列数 (宽度)
rowsint终端行数 (高度)

示例:

{
"type": "resize",
"cols": 120,
"rows": 30
}

说明:

  • 必须在 login 成功后发送
  • 如果不发送 resize,SSH 终端会使用默认大小 (80x40)
  • 终端大小不匹配会导致显示错乱 (如 vim 编辑器)
1.3.2.4 heartbeat - 保活心跳

方向: 客户端 → 服务端

时机: 定期发送 (建议 30 秒间隔)

字段:

字段类型必填说明
typestring固定值 "heartbeat"

示例:

{
"type": "heartbeat"
}

说明:

  • 防止 WebSocket 连接因空闲超时被中间代理关闭
  • 服务端收到后不做任何响应,仅保持连接活跃
1.3.3 服务端响应
1.3.3.1 SSH 输出 (二进制消息)

方向: 服务端 → 客户端

格式: WebSocket Binary Frame

内容: SSH stdout/stderr 的原始字节流

示例 (伪代码):

socket.onmessage = (event) => {
if (event.data instanceof ArrayBuffer) {
// 二进制数据 - SSH 输出
const bytes = new Uint8Array(event.data);
// 传递给 xterm.js 渲染
terminal.write(bytes);
}
};

说明:

  • 包含 ANSI 转义序列 (颜色、光标控制等)
  • 需要使用终端模拟器 (如 xterm.js) 正确渲染
  • 服务端启用了括号粘贴模式 (Bracketed Paste Mode),输出中会包含 \x1b[?2004h (启用) 和 \x1b[?2004l (关闭) 转义序列。xterm.js 默认支持此模式,无需额外处理。如果使用自定义终端渲染器,需正确解析这些序列以避免显示异常
1.3.3.2 错误消息 (文本消息)

方向: 服务端 → 客户端

格式: WebSocket Text Frame

内容: 错误描述字符串 (带 ANSI 颜色代码)

示例:

\r\n\x1b[31mSSH连接失败: dial tcp 192.168.1.100:22: connection refused\x1b[0m\r\n
\r\n\x1b[32m成功连接到 192.168.1.100:22\x1b[0m\r\n

说明:

  • 错误消息使用红色 (\x1b[31m)
  • 成功消息不含 ANSI 颜色码,为纯文本 (实测验证: 返回 "成功连接到 127.0.0.1:22\n" 无任何转义序列)
  • 消息末尾有 \\x1b[0m 重置颜色 (仅错误消息)

1.4. 完整交互流程

客户端                                服务端
| |
|--- WebSocket Upgrade -------------->|
|<-- 101 Switching Protocols ---------|
| |
|--- {"type":"login",...} ----------->| 建立 SSH 连接
| | 创建 SSH Session
| | 请求 PTY (xterm)
| | 启动 Shell
|<-- Text: "成功连接到 192..." -------|
|<-- Binary: "user@host:~$ " ---------|
| |
|--- {"type":"resize",...} ---------->| 调整 PTY 大小
| |
|--- {"type":"stdin","data":"ls\r"} ->| 写入 SSH stdin
|<-- Binary: "file1\nfile2\n..." ----|
| |
|--- {"type":"heartbeat"} ----------->| (无响应)
| |
|--- {"type":"stdin","data":"exit\r"}>| SSH 会话退出
|<-- Binary: "logout\n" --------------|
|<-- WebSocket Close -----------------|
| |

1.5. 前端集成示例

1.5.1 使用 xterm.js (完整示例)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Web SSH Terminal</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css"
/>
<script src="https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.js"></script>
<style>
body {
margin: 0;
padding: 20px;
background: #0c0c0c;
}
#terminal {
width: 100%;
height: 600px;
}
#login-form {
background: #1e1e1e;
padding: 20px;
border-radius: 8px;
max-width: 400px;
margin: 50px auto;
color: #fff;
}
input {
width: 100%;
padding: 8px;
margin: 5px 0 15px;
border: 1px solid #444;
background: #2d2d2d;
color: #fff;
border-radius: 4px;
}
button {
width: 100%;
padding: 10px;
background: #0078d4;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background: #005a9e;
}
</style>
</head>
<body>
<!-- 登录表单 -->
<div id="login-form">
<h2>SSH 连接</h2>
<label>IP 地址:</label>
<input type="text" id="ip" value="127.0.0.1" />

<label>端口:</label>
<input type="number" id="port" value="22" />

<label>用户名:</label>
<input type="text" id="user" value="root" />

<label>密码:</label>
<input type="password" id="password" />

<button onclick="connect()">连接</button>
</div>

<!-- 终端容器 -->
<div id="terminal" style="display:none;"></div>

<script>
let term, fitAddon, socket, heartbeatTimer;

function connect() {
const ip = document.getElementById("ip").value;
const port = parseInt(document.getElementById("port").value);
const user = document.getElementById("user").value;
const password = document.getElementById("password").value;

if (!ip || !user || !password) {
alert("请填写完整信息");
return;
}

// 隐藏登录表单,显示终端
document.getElementById("login-form").style.display = "none";
document.getElementById("terminal").style.display = "block";

// 初始化终端
term = new Terminal({
cursorBlink: true,
fontSize: 14,
fontFamily: 'Consolas, "Courier New", monospace',
theme: { background: "#0c0c0c" },
});
fitAddon = new FitAddon.FitAddon();
term.loadAddon(fitAddon);
term.open(document.getElementById("terminal"));
fitAddon.fit();
term.focus();

// 连接 WebSocket
const wsUrl = `ws://${location.host}/link/ssh`;
//将${location.host}替换成直接要连接的设备IP和端口,例如:const wsUrl = `ws://10.10.11.4:8000/link/ssh`;
socket = new WebSocket(wsUrl);
socket.binaryType = "arraybuffer";

socket.onopen = () => {
term.write("\r\n\x1b[32m正在建立连接...\x1b[0m\r\n");

// 发送登录认证
socket.send(
JSON.stringify({
type: "login",
ip: ip,
port: port,
user: user,
password: password,
}),
);

// 发送终端大小
const dims = fitAddon.proposeDimensions();
socket.send(
JSON.stringify({
type: "resize",
cols: dims.cols,
rows: dims.rows,
}),
);

// 启动心跳
heartbeatTimer = setInterval(() => {
if (socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify({ type: "heartbeat" }));
}
}, 30000);
};

socket.onmessage = (event) => {
if (event.data instanceof ArrayBuffer) {
// 二进制数据 - SSH 输出
term.write(new Uint8Array(event.data));
} else {
// 文本消息 - 错误或状态
term.write(event.data);
}
};

socket.onerror = () => {
term.write("\r\n\x1b[31mSocket 连接错误\x1b[0m\r\n");
};

socket.onclose = () => {
term.write("\r\n\x1b[31m连接已断开, 请刷新页面重试\x1b[0m\r\n");
clearInterval(heartbeatTimer);
};

// 用户输入 → WebSocket
term.onData((data) => {
if (socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify({ type: "stdin", data: data }));
}
});

// 窗口大小变化 → WebSocket
window.addEventListener("resize", () => {
fitAddon.fit();
const dims = fitAddon.proposeDimensions();
if (socket.readyState === WebSocket.OPEN) {
socket.send(
JSON.stringify({
type: "resize",
cols: dims.cols,
rows: dims.rows,
}),
);
}
});
}
</script>
</body>
</html>
1.5.2 使用原生 WebSocket (无终端模拟器)
const socket = new WebSocket("ws://192.168.1.100:8000/link/ssh");
socket.binaryType = "arraybuffer";

socket.onopen = () => {
// 登录
socket.send(
JSON.stringify({
type: "login",
ip: "127.0.0.1",
port: 22,
user: "root",
password: "mypassword",
}),
);

// 设置终端大小
socket.send(
JSON.stringify({
type: "resize",
cols: 80,
rows: 24,
}),
);

// 执行命令
setTimeout(() => {
socket.send(
JSON.stringify({
type: "stdin",
data: "uname -a\r",
}),
);
}, 1000);

setTimeout(() => {
socket.send(
JSON.stringify({
type: "stdin",
data: "exit\r",
}),
);
}, 3000);
};

socket.onmessage = (event) => {
if (event.data instanceof ArrayBuffer) {
// 二进制数据 - SSH 输出
const text = new TextDecoder().decode(event.data);
console.log("输出:", text);
} else {
// 文本消息 - 错误或状态
console.log("消息:", event.data);
}
};

示例图:连接ssh01

连接ssh02

1.6. 后端实现细节

1.6.1 技术栈
  • Web 框架: GoFrame v2
  • WebSocket: gorilla/websocket
  • SSH 客户端: golang.org/x/crypto/ssh
1.6.2 关键实现
// 1. 升级 HTTP 为 WebSocket
ws, err := wsUpGrader.Upgrade(r.Response.Writer, r.Request, nil)

// 2. 建立 SSH 连接
config := &ssh.ClientConfig{
User: msg.User,
Auth: []ssh.AuthMethod{
ssh.Password(msg.Password),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(), // 生产环境应验证 host key
Timeout: 5 * time.Second,
}
addr := fmt.Sprintf("%s:%d", msg.Ip, msg.Port)
sshClient, err := ssh.Dial("tcp", addr, config)

// 3. 创建 SSH Session
session, err := sshClient.NewSession()

// 4. 请求伪终端 (PTY)
modes := ssh.TerminalModes{
ssh.ECHO: 1,
}
session.RequestPty("xterm", 40, 80, modes)

// 5. 重定向 SSH 输出到 WebSocket
type WebSocketWriter struct {
ws *websocket.Conn
}
func (w *WebSocketWriter) Write(p []byte) (n int, err error) {
err = w.ws.WriteMessage(websocket.BinaryMessage, p)
if err != nil { return 0, err }
return len(p), nil
}

session.Stdout = &WebSocketWriter{ws: ws}
session.Stderr = &WebSocketWriter{ws: ws}

// 6. 启动 Shell
session.Shell()

// 7. 双向转发
// WebSocket 输入 → SSH stdin
sshStdin, _ := session.StdinPipe()
for {
_, msgBytes, err := ws.ReadMessage()
if err != nil { break }

var msg WsMsg
json.Unmarshal(msgBytes, &msg)

switch msg.Type {
case "stdin":
sshStdin.Write([]byte(msg.Data))
case "resize":
session.WindowChange(msg.Rows, msg.Cols)
}
}

// 8. 等待 Shell 退出
go func() {
session.Wait()
ws.Close()
}()

1.7. 常见问题

1.7.1 SSH 连接失败

问题: 收到 "SSH连接失败" 错误

可能原因:

  • 目标设备 SSH 服务未启动
  • IP 地址或端口错误
  • 网络不可达 (防火墙、路由问题)
  • 用户名或密码错误

解决:

  • 确认目标设备 SSH 服务运行: systemctl status sshd
  • 测试网络连通性: ping <ip>telnet <ip> 22
  • 验证用户名密码: ssh user@ip
1.7.2 终端显示乱码

问题: 终端显示乱码或控制字符

原因:

  • 未使用终端模拟器渲染 ANSI 转义序列
  • 终端大小未正确设置
  • 字符编码不匹配

解决:

  • 使用 xterm.js 等终端模拟器
  • login 后立即发送 resize 消息
  • 确保 WebSocket 设置为 binaryType = 'arraybuffer'
1.7.3 连接意外断开

问题: WebSocket 连接在空闲时自动关闭

原因:

  • 中间代理 (Nginx/负载均衡器) 超时
  • SSH 服务器超时断开
  • 网络不稳定

解决:

  • 定期发送 heartbeat 消息 (建议 30 秒)
  • 配置代理服务器的 WebSocket 超时时间
  • 配置 SSH 服务器的 ClientAliveIntervalClientAliveCountMax
1.7.4 无法执行交互式命令

问题: vim, top, htop 等命令显示异常

原因:

  • 终端大小未设置或不匹配
  • 未分配伪终端 (PTY)

解决:

  • 确保发送了正确的 resize 消息
  • 后端必须调用 session.RequestPty() (已默认启用)
1.7.5 密码认证失败

问题: 收到 "ssh: unable to authenticate" 错误

可能原因:

  • 密码错误
  • SSH 服务器禁用了密码认证 (仅允许密钥认证)
  • 用户账户被锁定

解决:

  • 验证密码正确性
  • 检查 SSH 服务器配置: /etc/ssh/sshd_configPasswordAuthentication 应为 yes
  • 检查用户账户状态: passwd -S <user>

1.8. 安全建议

1.8.1 传输安全
  1. 启用 HTTPS/WSS: 生产环境必须使用加密连接,防止密码明文传输
  2. 证书验证: 后端应验证 SSH 服务器的 host key,避免中间人攻击
    // 生产环境应替换 InsecureIgnoreHostKey
    HostKeyCallback: ssh.FixedHostKey(hostKey)
1.8.2 认证鉴权
  1. 双层认证: WebSocket 层 + SSH 层
  2. 密码存储: 前端不应缓存 SSH 密码,每次连接重新输入
  3. 会话超时: 设置最大空闲时间 (如 30 分钟)
1.8.3 访问控制
  1. IP 白名单: 限制可连接的目标 IP 范围
  2. 用户隔离: 限制用户只能 SSH 到自己的设备
  3. 审计日志: 记录所有 SSH 连接和命令执行
1.8.4 防护措施
  1. 连接限制: 限制单个用户的并发 SSH 连接数
  2. 速率限制: 防止暴力破解密码
  3. 命令过滤: 可选地拦截危险命令 (如 rm -rf /)

1.9. 性能优化

  1. 连接池: 复用 SSH 连接 (需要修改后端实现)
  2. 心跳间隔: 30 秒是推荐值,过短会增加网络开销
  3. 缓冲区大小: 后端使用 4KB 缓冲区,适合大多数场景
  4. 资源清理: 连接断开时自动清理 SSH 会话

1.10. 与容器终端的对比

特性设备 SSH (/link/ssh)容器终端 (/link/exec)
连接目标远程设备 SSH 服务Docker 容器内部
认证方式SSH 用户名+密码容器 ID/名称
网络要求需要网络可达目标设备本地 Docker API
权限取决于 SSH 用户权限容器内 root 权限
适用场景设备运维、远程管理容器调试、应用排查
login 参数ip, port, user, passwordcontainer_id, shell

11. 参考资源

附录: 完整消息类型定义

// TypeScript 类型定义
interface WsMsg {
type: "login" | "stdin" | "resize" | "heartbeat";

// login 字段
ip?: string;
port?: number;
user?: string;
password?: string;

// stdin 字段
data?: string;

// resize 字段
cols?: number;
rows?: number;
}

// 使用示例
const loginMsg: WsMsg = {
type: "login",
ip: "192.168.1.100",
port: 22,
user: "root",
password: "mypassword",
};

const stdinMsg: WsMsg = {
type: "stdin",
data: "ls -la\r",
};

const resizeMsg: WsMsg = {
type: "resize",
cols: 120,
rows: 30,
};

const heartbeatMsg: WsMsg = {
type: "heartbeat",
};

附录: 错误码参考

错误消息原因解决方案
dial tcp ... i/o timeout网络不可达或防火墙阻止检查网络连通性和防火墙规则
connection refusedSSH 服务未启动启动 SSH 服务: systemctl start sshd
ssh: unable to authenticate密码错误或认证方式不支持验证密码,检查 SSH 配置
创建Session失败SSH 连接建立后无法创建会话检查 SSH 服务器资源和配置
RequestPty 失败无法分配伪终端检查 SSH 服务器 PTY 配置
启动 Shell 失败无法启动 Shell 进程检查用户 Shell 配置 (/etc/passwd)

2. 修改SSH登录用户密码

功能说明:修改SSH登录用户的密码

请求方式:POST

请求URL

http://{主机IP}:8000/link/ssh/changePwd

请求参数

参数名必选类型说明
usernamestring用户名,默认user
passwordstring新密码

请求示例

curl -X POST "http://192.168.99.108:8000/link/ssh/changePwd" \
-H "Content-Type: application/json" \
-d '{
"username": "user",
"password": "newpassword123"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "修改密码失败",
"data": null
}

注意事项

  • 密码修改后立即生效
  • 请牢记新密码

3. 开关SSH root登录

功能说明:启用或禁止SSH root用户登录

请求方式:POST

请求URL

http://{主机IP}:8000/link/ssh/switchRoot

请求参数

参数名必选类型说明
enablebooltrue-启用root登录,false-禁止root登录

请求示例

curl -X POST "http://192.168.99.108:8000/link/ssh/switchRoot" \
-H "Content-Type: application/json" \
-d '{
"enable": true
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "设置失败",
"data": null
}

注意事项

  • 出于安全考虑,建议禁用root登录

4. 开关SSH服务

功能说明:启用或关闭SSH服务

请求方式:POST

请求URL

http://{主机IP}:8000/link/ssh/enable

请求参数

参数名必选类型说明
enablebooltrue-启用ssh服务,false-关闭ssh服务

请求示例

curl -X POST "http://192.168.99.108:8000/link/ssh/enable" \
-H "Content-Type: application/json" \
-d '{
"enable": true
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "设置SSH服务失败",
"data": null
}

5. 连接容器终端

5.1. 接口概述

功能: 通过 WebSocket 在浏览器中连接到 Docker 容器的交互式终端

协议: WebSocket (基于 HTTP Upgrade)

端点: ws://{host}:8000/link/execwss://{host}:8000/link/exec

认证: 需要 HTTP Basic Auth (与其他 myt-sdk API 相同)

适用场景:

  • Web 界面直接操作容器内部
  • 无需 SSH 或 docker exec 命令
  • 云手机平台的容器调试和运维

5.2. 连接建立

5.2.1 WebSocket 握手
// 前端示例
const wsUrl =
(location.protocol === "https:" ? "wss://" : "ws://") +
location.host +
"/link/exec";

const socket = new WebSocket(wsUrl);

socket.onopen = () => {
console.log("WebSocket 连接已建立");
};

socket.onmessage = (event) => {
// event.data 可能是文本或二进制数据
if (typeof event.data === "string") {
console.log("收到文本:", event.data);
} else {
// 二进制数据 (容器输出)
const arrayBuffer = event.data;
}
};

socket.onerror = (error) => {
console.error("WebSocket 错误:", error);
};

socket.onclose = () => {
console.log("WebSocket 连接已关闭");
};
5.2.2 认证方式

如果 myt-sdk 启用了 Basic Auth,需要在 WebSocket URL 中携带凭证:

// 方式1: URL 中携带 (不推荐,凭证会暴露在 URL)
const wsUrl = `ws://username:password@${host}:8000/link/exec`;

// 方式2: 通过 HTTP 请求头 (推荐)
// 注意:浏览器 WebSocket API 不支持自定义请求头
// 需要先通过 HTTP 请求获取 session/token,或使用代理服务器

推荐方案: 在同域下先通过普通 HTTP 请求完成认证,浏览器会自动携带 Cookie

5.3. 消息协议

5.3.1 消息格式

所有客户端发送的消息均为 JSON 文本格式:

{
"type": "消息类型",
"...": "其他字段"
}

服务端返回的消息分为两种:

  • 文本消息: 错误提示或状态信息
  • 二进制消息: 容器终端的输出 (stdout/stderr)
5.3.2 消息类型详解
5.3.2.1 login - 初始化连接

方向: 客户端 → 服务端

时机: WebSocket 连接建立后立即发送

字段:

字段类型必填说明
typestring固定值 "login"
container_idstring容器 ID 或容器名称
shellstringShell 路径,默认 /bin/sh

示例:

{
"type": "login",
"container_id": "android_slot_0",
"shell": "/bin/bash"
}

说明:

  • container_id 可以是完整的容器 ID (64位十六进制) 或容器名称
  • shell 可选值: /bin/bash, /bin/sh, /bin/zsh 等 (取决于容器内安装的 shell)
  • 如果容器不存在或无法连接,服务端会返回错误文本消息

错误响应示例:

Docker Client Init Error: Cannot connect to the Docker daemon
Exec Create Error: No such container: android_slot_0
Exec Attach Error: container is not running
5.3.2.2 stdin - 用户输入

方向: 客户端 → 服务端

时机: 用户在终端中输入字符时

字段:

字段类型必填说明
typestring固定值 "stdin"
datastring用户输入的数据 (包括控制字符)

示例:

{
"type": "stdin",
"data": "ls -la\r"
}

说明:

  • data 包含原始按键数据,包括:
    • 普通字符: a, b, 1, 2
    • 回车: \r\n
    • 退格: \x7f (DEL) 或 \x08 (BS)
    • 方向键: \x1b[A (上), \x1b[B (下), \x1b[C (右), \x1b[D (左)
    • Ctrl+C: \x03
    • Ctrl+D: \x04
  • 数据会直接写入容器的 stdin
5.3.2.3 resize - 调整终端大小

方向: 客户端 → 服务端

时机: 浏览器窗口大小变化时

字段:

字段类型必填说明
typestring固定值 "resize"
colsint终端列数 (宽度)
rowsint终端行数 (高度)

示例:

{
"type": "resize",
"cols": 120,
"rows": 30
}

说明:

  • 必须在 login 成功后发送
  • 如果不发送 resize,容器终端会使用默认大小 (通常是 80x24)
  • 终端大小不匹配会导致显示错乱 (如 vim 编辑器)
5.3.2.4 heartbeat - 保活心跳

方向: 客户端 → 服务端

时机: 定期发送 (建议 30 秒间隔)

字段:

字段类型必填说明
typestring固定值 "heartbeat"

示例:

{
"type": "heartbeat"
}

说明:

  • 防止 WebSocket 连接因空闲超时被中间代理关闭
  • 服务端收到后不做任何响应,仅保持连接活跃
5.3.3 服务端响应
5.3.3.1 容器输出 (二进制消息)

方向: 服务端 → 客户端

格式: WebSocket Binary Frame

内容: 容器 stdout/stderr 的原始字节流

示例 (伪代码):

socket.onmessage = (event) => {
if (event.data instanceof ArrayBuffer) {
// 二进制数据 - 容器输出
const bytes = new Uint8Array(event.data);
// 传递给 xterm.js 渲染
terminal.write(bytes);
}
};

说明:

  • 包含 ANSI 转义序列 (颜色、光标控制等)
  • 需要使用终端模拟器 (如 xterm.js) 正确渲染
5.3.3.2 错误消息 (文本消息)

方向: 服务端 → 客户端

格式: WebSocket Text Frame

内容: 错误描述字符串

示例:

Docker Client Init Error: Cannot connect to the Docker daemon at unix:///var/run/docker.sock
Exec Create Error: No such container: invalid_container_id
Exec Attach Error: container is not running

说明:

  • 仅在连接初始化失败时发送
  • 收到错误消息后,WebSocket 连接会被服务端关闭

5.4. 完整交互流程

客户端                                服务端
| |
|--- WebSocket Upgrade -------------->|
|<-- 101 Switching Protocols ---------|
| |
|--- {"type":"login",...} ----------->| 创建 Docker Exec
| | 劫持容器 stdin/stdout
|<-- Binary: "root@container:~# " ---|
| |
|--- {"type":"resize",...} ---------->| 调整终端大小
| |
|--- {"type":"stdin","data":"ls\r"} ->| 写入容器 stdin
|<-- Binary: "file1\nfile2\n..." ----|
| |
|--- {"type":"heartbeat"} ----------->| (无响应)
| |
|--- {"type":"stdin","data":"exit\r"}>| 容器进程退出
|<-- Binary: "logout\n" --------------|
|<-- WebSocket Close -----------------|
| |

5.5. 前端集成示例

5.5.1 使用 xterm.js
<!DOCTYPE html>
<html>
<head>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css"
/>
<script src="https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.js"></script>
</head>
<body>
<div id="terminal"></div>

<script>
const term = new Terminal({
cursorBlink: true,
fontSize: 14,
fontFamily: 'Consolas, "Courier New", monospace',
});
const fitAddon = new FitAddon.FitAddon();
term.loadAddon(fitAddon);
term.open(document.getElementById("terminal"));
fitAddon.fit();

// 连接 WebSocket
const wsUrl = `ws://${location.host}/link/exec`;
//location.host替换成自己的设备IP,端口固定为8000,例如:10.10.11.4:8000
const socket = new WebSocket(wsUrl);

socket.onopen = () => {
// 发送 login 消息
socket.send(
JSON.stringify({
type: "login",
//"android_slot_0"替换成容器id或名称,例如:1777544648515_1_T0001
container_id: "android_slot_0",
shell: "/bin/sh",
}),
);

// 发送初始终端大小
const dims = fitAddon.proposeDimensions();
socket.send(
JSON.stringify({
type: "resize",
cols: dims.cols,
rows: dims.rows,
}),
);

// 启动心跳
setInterval(() => {
if (socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify({ type: "heartbeat" }));
}
}, 30000);
};

socket.onmessage = (event) => {
if (typeof event.data === "string") {
// 错误消息
term.write("\r\n\x1b[31m" + event.data + "\x1b[0m\r\n");
} else {
// 容器输出
const reader = new FileReader();
reader.onload = () => {
term.write(new Uint8Array(reader.result));
};
reader.readAsArrayBuffer(event.data);
}
};

socket.onerror = (error) => {
term.write("\r\n\x1b[31mWebSocket Error\x1b[0m\r\n");
};

socket.onclose = () => {
term.write("\r\n\x1b[33mConnection Closed\x1b[0m\r\n");
};

// 用户输入 → WebSocket
term.onData((data) => {
if (socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify({ type: "stdin", data: data }));
}
});

// 窗口大小变化 → WebSocket
window.addEventListener("resize", () => {
fitAddon.fit();
const dims = fitAddon.proposeDimensions();
if (socket.readyState === WebSocket.OPEN) {
socket.send(
JSON.stringify({
type: "resize",
cols: dims.cols,
rows: dims.rows,
}),
);
}
});
</script>
</body>
</html>
5.5.2 使用原生 WebSocket (无终端模拟器)
const socket = new WebSocket("ws://192.168.1.100:8000/link/exec");

socket.onopen = () => {
// 登录
socket.send(
JSON.stringify({
type: "login",
container_id: "my_container",
shell: "/bin/sh",
}),
);

// 设置终端大小
socket.send(
JSON.stringify({
type: "resize",
cols: 80,
rows: 24,
}),
);

// 执行命令
setTimeout(() => {
socket.send(
JSON.stringify({
type: "stdin",
data: "uname -a\r",
}),
);
}, 1000);

setTimeout(() => {
socket.send(
JSON.stringify({
type: "stdin",
data: "exit\r",
}),
);
}, 3000);
};

socket.onmessage = (event) => {
if (typeof event.data === "string") {
console.log("错误:", event.data);
} else {
// 二进制数据
const reader = new FileReader();
reader.onload = () => {
const text = new TextDecoder().decode(reader.result);
console.log("输出:", text);
};
reader.readAsArrayBuffer(event.data);
}
};

示例图:连接终端

5.6. 后端实现细节

5.6.1 技术栈
  • Web 框架: GoFrame v2
  • WebSocket: gorilla/websocket
  • Docker API: docker/docker/client
5.6.2 关键实现
// 1. 升级 HTTP 为 WebSocket
ws, err := wsUpGrader.Upgrade(r.Response.Writer, r.Request, nil)

// 2. 创建 Docker Exec
execConfig := types.ExecConfig{
AttachStdin: true,
AttachStdout: true,
AttachStderr: true,
Tty: true, // 关键:分配伪终端
Cmd: []string{"/bin/bash"},
}
execResp, err := cli.ContainerExecCreate(ctx, containerID, execConfig)

// 3. 劫持连接
resp, err := cli.ContainerExecAttach(ctx, execResp.ID, types.ExecStartCheck{Tty: true})

// 4. 双向转发
// 容器输出 → WebSocket
go func() {
buf := make([]byte, 4096)
for {
n, err := resp.Reader.Read(buf)
if err != nil { return }
ws.WriteMessage(websocket.BinaryMessage, buf[:n])
}
}()

// WebSocket 输入 → 容器
for {
_, msgBytes, err := ws.ReadMessage()
if err != nil { break }

var msg ExecWsMsg
json.Unmarshal(msgBytes, &msg)

switch msg.Type {
case "stdin":
resp.Conn.Write([]byte(msg.Data))
case "resize":
cli.ContainerExecResize(ctx, execID, types.ResizeOptions{
Height: uint(msg.Rows),
Width: uint(msg.Cols),
})
}
}

5.7. 常见问题

5.7.1 连接失败

问题: WebSocket 握手失败 (HTTP 400/401/403)

原因:

  • 未通过 Basic Auth 认证
  • 请求头缺少 Upgrade: websocket

解决:

  • 确保 WebSocket URL 包含认证信息或已通过 Cookie 认证
  • 使用标准 WebSocket 客户端库
5.7.2 容器输出乱码

问题: 终端显示乱码或控制字符

原因:

  • 未使用终端模拟器渲染 ANSI 转义序列
  • 终端大小未正确设置

解决:

  • 使用 xterm.js 等终端模拟器
  • login 后立即发送 resize 消息
5.7.3 连接意外断开

问题: WebSocket 连接在空闲时自动关闭

原因:

  • 中间代理 (Nginx/负载均衡器) 超时
  • 网络不稳定

解决:

  • 定期发送 heartbeat 消息 (建议 30 秒)
  • 配置代理服务器的 WebSocket 超时时间
5.7.4 无法执行交互式命令

问题: vim, top, htop 等命令显示异常

原因:

  • 终端大小未设置或不匹配
  • 未分配伪终端 (Tty)

解决:

  • 确保发送了正确的 resize 消息
  • 后端必须设置 Tty: true (已默认启用)

5.8. 安全建议

  1. 启用 HTTPS/WSS: 生产环境必须使用加密连接
  2. 认证鉴权: 通过 Basic Auth 或 Token 验证用户身份
  3. 容器隔离: 限制用户只能访问自己的容器
  4. 命令审计: 记录所有 stdin 输入到日志
  5. 超时控制: 设置连接最大空闲时间 (如 30 分钟)

5.9. 性能优化

  1. 缓冲区大小: 后端使用 4KB 缓冲区,适合大多数场景
  2. 心跳间隔: 30 秒是推荐值,过短会增加网络开销
  3. 连接复用: 同一容器可以被多个 WebSocket 连接同时访问
  4. 资源清理: 连接断开时自动清理 Docker Exec 会话

5.10. 参考资源

附录: 完整消息类型定义

// TypeScript 类型定义
interface ExecWsMsg {
type: "login" | "stdin" | "resize" | "heartbeat";

// login 字段
container_id?: string;
shell?: string;

// stdin 字段
data?: string;

// resize 字段
cols?: number;
rows?: number;
}

// 使用示例
const loginMsg: ExecWsMsg = {
type: "login",
container_id: "android_slot_0",
shell: "/bin/bash",
};

const stdinMsg: ExecWsMsg = {
type: "stdin",
data: "ls -la\r",
};

const resizeMsg: ExecWsMsg = {
type: "resize",
cols: 120,
rows: 30,
};

const heartbeatMsg: ExecWsMsg = {
type: "heartbeat",
};

五、myt_bridge网卡管理

1. 获取myt_bridge网卡列表

功能说明:获取设备上的myt_bridge网卡列表

请求方式:GET

请求URL

http://{主机IP}:8000/mytBridge

请求参数:无

请求示例

curl "http://192.168.99.108:8000/mytBridge"

成功返回

{
"code": 0,
"message": "ok",
"data": {
"count": 2,
"list": [
{
"name": "myt_bridge",
"cidr": "172.17.0.1/16"
},
{
"name": "myt_bridge_lan",
"cidr": "10.0.0.1/16"
}
]
}
}

失败返回

{
"code": 500,
"message": "获取网卡列表失败",
"data": null
}

2. 创建myt_bridge网卡

功能说明:创建新的myt_bridge网卡

请求方式:POST

请求URL

http://{主机IP}:8000/mytBridge

请求参数

参数名必选类型说明
customNamestring自定义名(最多4字符),会拼接在myt_bridge后面
cidrstringCIDR,例如10.0.0.1/16

请求示例

curl -X POST "http://192.168.99.108:8000/mytBridge" \
-H "Content-Type: application/json" \
-d '{
"customName": "lan",
"cidr": "10.0.0.1/16"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "创建网卡失败: 名称已存在",
"data": null
}

注意事项

  • customName最多4个字符
  • 创建后网卡名为 myt_bridge_customName

3. 更新myt_bridge网卡

功能说明:更新myt_bridge网卡的CIDR配置

请求方式:PUT

请求URL

http://{主机IP}:8000/mytBridge

请求参数

参数名必选类型说明
namestring网卡名(全称或自定义名)
newCidrstring新CIDR,例如10.0.0.1/16

请求示例

curl -X PUT "http://192.168.99.108:8000/mytBridge" \
-H "Content-Type: application/json" \
-d '{
"name": "myt_bridge_lan",
"newCidr": "10.0.0.1/24"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "更新网卡失败: 网卡不存在",
"data": null
}

4. 删除myt_bridge网卡

功能说明:删除指定的myt_bridge网卡

请求方式:DELETE

请求URL

http://{主机IP}:8000/mytBridge

请求参数

参数名必选类型说明
namestring网卡名(全称或自定义名)

请求示例

curl -X DELETE "http://192.168.99.108:8000/mytBridge" \
-H "Content-Type: application/json" \
-d '{
"name": "myt_bridge_lan"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "删除网卡失败: 网卡正在被使用",
"data": null
}

注意事项

  • 正在被云机使用的网卡无法删除
  • 删除前请确保没有云机依赖该网卡

六、macVlan网卡管理

1. 获取网卡详情

功能说明:查询指定 ID 的 macVlan 网卡详细信息

请求方式:GET

请求URL

http://{主机IP}:8000/macvlan

请求参数:无

请求示例

GET "http://192.168.99.108:8000/macvlan"

成功返回

{
"code": 0,
"message": "OK",
"data": {
"macVlan": {
"Name": "myt",
"Id": "24732efd39a53baa9822d49302f701c878e701f2553574fc217e255f1c5289a9",
"Created": "2026-02-04T13:42:39.460109818+08:00",
"Scope": "local",
"Driver": "macvlan",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "192.168.99.0/24",
"Gateway": "192.168.99.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {
"macvlan_mode": "private",
"parent": "eth0"
},
"Labels": {}
}
}
}

返回参数

参数名类型说明
Attachableboolean是否允许手动附加容器
ConfigFromobject配置来源对象
ConfigFrom.Networkstring来源网络名称
ConfigOnlyboolean是否仅配置(不创建网络)
Containersobject连接到该网络的容器映射,键为容器ID/名称,值为端点信息
Createdstring (time.Time)网络创建时间
Driverstring网络驱动名称(如 bridge, overlay, macvlan 等)
EnableIPv6boolean是否启用IPv6
Idstring网络ID
Ingressboolean是否为Swarm Ingress网络
Internalboolean是否为内部网络(限制外部访问)
IPAMobjectIP地址管理(IPAM)配置
IPAM.DriverstringIPAM驱动名称(如 default)
IPAM.OptionsobjectIPAM驱动选项
IPAM.ConfigarrayIPAM配置列表,每个元素为子网配置
IPAM.Config[].AuxiliaryAddressesobject辅助地址映射,键为地址名,值为IP
IPAM.Config[].Gatewaystring子网网关IP
IPAM.Config[].IPRangestring分配的IP范围(如 172.17.0.0/24)
IPAM.Config[].Subnetstring子网CIDR(如 172.17.0.0/16)
Labelsobject网络标签键值对
Namestring网络名称
Optionsobject网络驱动选项
Peersarray对等节点列表(仅Swarm模式)
Peers[].IPstring对等节点IP地址
Peers[].Namestring对等节点名称
Scopestring网络作用域(local, swarm, global)
Servicesobject服务列表(仅Swarm模式),键为服务名,值为服务信息

失败返回

{
"code": 500,
"message": "获取网卡详情失败",
"data": null
}

2. 创建网卡

功能说明:创建新的macVlan网卡

请求方式:POST

请求URL

http://{主机IP}:8000/macvlan

请求参数

参数名必选类型说明
gwstring网关,例如 192.168.100.1
subnetstring掩码,例如 192.168.100.0/24
privateboolean是否禁止macvlan容器互相访问,默认为 true

请求示例

POST http://192.168.99.108:8000/macvlan
Content-Type: application/json
请求体
{
"gw": "192.168.100.1",
"subnet": "192.168.100.0/24",
"private": true
}

或者

curl http://192.168.99.108:8000/macvlan \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"gw": "",
"subnet": "192.168.100.0/24",
"private": true
}'

成功返回

{
"code": 0,
"message": "OK",
"data": {
"id": "string"
}
}

返回参数

参数名类型说明
idstring创建成功的网卡ID

失败返回

{
"code": 500,
"message": "创建网卡失败",
"data": null
}

3. 更新网卡

功能说明:更新一个已存在的 macVlan 网卡的配置。

请求方式:PUT

请求URL

http://{主机IP}:8000/macvlan

请求参数

参数名必选类型说明
gwstring新的网关,例如 192.168.100.1
subnetstring新的掩码,例如 192.168.100.0/24
privateboolean是否禁止macvlan容器互相访问,默认为 true

请求示例

POST http://192.168.99.108:8000/macvlan
Content-Type: application/json
请求体
{
"gw": "192.168.100.1",
"subnet": "192.168.100.0/24",
"private": true
}

或者

curl http://192.168.99.108:8000/macvlan \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"gw": "192.168.100.1",
"subnet": "192.168.100.0/24",
"private": true
}'

成功返回

{
"code": 0,
"message": "OK",
"data": {
"id": "string"
}
}

返回参数

参数名类型说明
idstring创建成功的网卡ID

失败返回

{
"code": 500,
"message": "创建网卡失败",
"data": null
}

4. 删除网卡

功能说明:更新一个已存在的 macVlan 网卡的配置。

请求方式:DELETE

请求URL

http://{主机IP}:8000/macvlan

请求参数:无

请求示例

curl http://192.168.99.108:8000/macvlan \
--request DELETE

成功返回

{
"code": 0,
"message": "OK",
"data": null
}

七、魔云腾VPC

1. 获取网络分组列表

功能说明:查询所有网络分组列表,支持按别名过滤

请求方式:GET

请求URL

http://{主机IP}:8000/mytVpc/group

请求参数

参数名必选类型说明
aliasstring分组别名,传空查询所有

请求示例

# 查询所有分组
GET "http://{主机IP}:8000/mytVpc/group"
# 按别名过滤
curl "http://192.168.99.108:8000/mytVpc/group?alias=test-group"

成功返回

{
"code": 0,
"message": "OK",
"data": {
"count": 1,
"list": [
{
"id": 11,
"alias": "111saa",
"url": "",
"vpcs": {
"vpcCount": 1,
"list": [
{
"id": 289,
"groupId": 11,
"remarks": "socks_220csx",
"protocol": "socks",
"profile": "{\"configType\":3,\"remarks\":\"socks_220csx\",\"server\":\"nub2ccs1.user.wuyouip.com\",\"serverPort\":\"xxxx\",\"password\":\"xxxx\",\"username\":\"xxxx\"}",
"outConfig": "{\"protocol\":\"socks\",\"sendThrough\":null,\"tag\":\"socks_220csx_11_1769492725191\",\"settings\":{\"servers\":[{\"address\":\"nub2ccs1.user.wuyouip.com\",\"port\":xxxx,\"level\":8,\"users\":[{\"user\":\"xxxxx\",\"pass\":\"xxxxxx\",\"level\":8}]}]},\"streamSettings\":null,\"proxySettings\":null,\"mux\":{\"enabled\":false,\"concurrency\":-1,\"xudpConcurrency\":0,\"xudpProxyUDP443\":\"\"},\"targetStrategy\":\"\"}",
"source": 2,
"tag": "socks_220csx_11_1769492725191"
}
]
}
}
]
}
}

2. 增加网络分组列表

功能说明:创建新的网络分组,支持订阅地址或节点地址模式

请求方式:POST

请求URL

http://{主机IP}:8000/mytVpc/group

请求参数

参数名必选类型说明
aliasstring网络分组别名
addressesarray批量添加节点列表(source=2 时必填)
sourceint1-订阅地址,2-节点地址,默认
urlstring批量添加节点列表(source=1 时必填)

请求示例

# 订阅地址模式
curl -X POST "http://192.168.99.108:8000/mytVpc/group" \
-H "Content-Type: application/json" \
-d '{
"alias": "test-group",
"source": 1,
"url": "http://example.com/subscribe"
}'
# 节点地址模式
curl -X POST "http://192.168.99.108:8000/mytVpc/group" \
-H "Content-Type: application/json" \
-d '{
"alias": "node-group",
"source": 2,
"addresses": ["192.168.1.100:8080", "192.168.1.101:8080"]
}'

成功返回

{
"code": 0,
"message": "OK",
"data": null
}

失败返回

# 分组名称未填
{
"code": 51,
"message": "The alias field is required",
"data": null
}
# 填错地址
{
"code": 50,
"message": "Get \"\": unsupported protocol scheme \"\"",
"data": null
}
# 分组已存在
{
"code": 10021,
"message": "Error: 此订阅分组已存在无法新建",
"data": null
}

3. 更新网络分组名

功能说明:修改指定网络分组的别名

请求方式:POST

请求URL

http://{主机IP}:8000/mytVpc/group/alias

请求参数

参数名必选类型说明
idint网络分组ID
newAliasstring分组新别名

请求示例

curl http://192.168.99.108:8000/mytVpc/group/alias \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"id": 1,
"newAlias": "111"
}'

成功返回

{
"code": 0,
"message": "OK",
"data": null
}

失败返回

{
"code": 500,
"message": "更新分组别名失败: 新别名已存在",
"data": null
}

4. 删除网络分组列表

功能说明:删除指定的网络分组,删除前需确保分组内无 VPC 节点

请求方式:DELETE

请求URL

http://{主机IP}:8000/mytVpc/group

请求参数

参数名必选类型说明
idint网络分组ID

请求示例

curl -X DELETE "http://192.168.99.108:8000/mytVpc/group" \
-H "Content-Type: application/json" \
-d '{
"id": 2
}'

成功返回

{
"code": 0,
"message": "OK",
"data": null
}

失败返回

{
"code": 10022,
"message": "Error: 此订阅分组不存在",
"data": null
}

5. 指定云机 VPC 节点

功能说明:为指定云机绑定 VPC 节点及 DNS 白名单

请求方式:POST

请求URL

http://{主机IP}:8000/mytVpc/addRule

请求参数

参数名必选类型说明
namestring云机容器名称
vpcIDintVPC 节点 ID
WhiteListDnsarrayVDNS 白名单列表

请求示例

curl http://192.168.99.108:8000/mytVpc/addRule \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"name": "p738c384c1581ad24c3fcf199684f5f5_13_T00013",
"vpcID": 1,
"WhiteListDns": [
""
]
}

成功返回

{
"code": 0,
"message": "OK",
"data": null
}

失败返回

{
"code": 51,
"message": "The name field is required",
"data": null
}

{
"code": 10023,
"message": "Error: 此VPC节点不存在",
"data": null
}

6. 已设置云机 VPC 节点

功能说明:查询已绑定 VPC 节点的云机规则列表

请求方式:GET

请求URL

http://{主机IP}:8000/mytVpc/containerRule

请求参数:无

请求示例

curl "http://192.168.99.108:8000/mytVpc/containerRule"

成功返回

{
"code": 0,
"message": "OK",
"data": {
"count": 2,
"list": [
{
"id": 1,
"containerID": "5fd727704a60691f7ed5c13575ac261c0f28eebb9aea8141412818f74fa110d5",
"containerIP": "",
"containerName": "Test_1",
"containerState": "running",
"status": 1,
"groupName": "111saa",
"vpcRemarks": "socks_220csx",
"WhiteListDns": []
},
{
"id": 2,
"containerID": "e2e38a2d7ea53d40e58ba5d54327b807a714139dca0ec69faeb176336686a060",
"containerIP": "172.17.0.7",
"containerName": "p738c384c1581ad24c3fcf199684f5f5_13_T00013",
"containerState": "running",
"status": 1,
"groupName": "test-grup",
"vpcRemarks": "澳洲AX01 50500进阶版 0.3x",
"WhiteListDns": []
}
]
}
}

8. 删除网络分组内节点

功能说明:从指定网络分组中移除一个云机节点。

请求方式:DELETE

请求URL

http://{主机IP}:8000/mytVpc

请求参数

参数名必选类型说明
vpcIDint要删除的 VPC 节点 ID

请求示例

curl -X DELETE "http://192.168.99.108:8000/mytVpc" \
-H "Content-Type: application/json" \
-d '{
"vpcID": 1
}'

成功返回

{
"code": 0,
"message": "OK",
"data": null
}

失败返回

{
"code": 10023,
"message": "Error: 此VPC节点不存在",
"data": null
}

9. 更新指定网络分组

功能说明:更新指定网络分组的配置信息。

请求方式:POST

请求URL

http://{主机IP}:8000/mytVpc/group/update

请求参数

参数名必选类型说明
IDint网络分组ID

请求示例

curl -X DELETE "http://192.168.99.108:8000/mytVpc" \
-H "Content-Type: application/json" \
-d '{
"vpcID": 1
}'

成功返回

{
"code": 0,
"message": "OK",
"data": null
}

失败返回

{
"code": 10022,
"message": "Error: 此订阅分组不存在",
"data": null
}

10. 增加socks5节点

功能说明:向指定网络分组添加 socks5 节点。

请求方式:POST

请求URL

http://{主机IP}:8000/mytVpc/socks

请求参数

参数名必选类型说明
aliasstring订阅分组别名,如果别名不存在将创建新分组,若存在则加入到此分组中
listarraysocks5 节点列表

list 数组元素结构

字段类型说明
remarksstring节点别名
socksIpstrings5 IP
socksPortints5 端口
socksUserstrings5 用户名
socksPasswordistrings5 密码

请求示例

curl -X POST "http://192.168.99.108:8000/mytVpc/socks" \
-H "Content-Type: application/json" \
-d '{
"alias": "socks-group",
"list": [
{
"remarks": "node1",
"socksIp": "192.168.1.100",
"socksPort": 1080,
"socksUser": "user1",
"socksPassword": "pass123"
}
]
}'

成功返回

{
"code": 0,
"message": "OK",
"data": null
}

失败返回

{
"code": 51,
"message": "The alias field is required",
"data": null
}

11. 开关DNS白名单

功能说明:启用 / 禁用指定 VPC 规则的 DNS 白名单。

请求方式:POST

请求URL

http://{主机IP}:8000/mytVpc/whiteListDns

请求参数

参数名必选类型说明
ruleIDint规则 ID
enablebool是否启用,默认 true
whiteListDnsarrayDNS 白名单列表

请求示例

curl http://192.168.99.108:8000/mytVpc/whiteListDns \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"ruleID": 1,
"enable": true,
"whiteListDns": [
""
]
}'

成功返回

{
"code": 0,
"message": "OK",
"data": null
}

12. VPC节点延迟测试

功能说明:测试指定 VPC 节点的网络延迟。

请求方式:GET

请求URL

http://{主机IP}:8000/mytVpc/test

请求参数

参数名必选类型说明
addressstring节点地址,address 格式如 "1.1.1.1:80" 或 "www.google.com:443"

请求示例

curl 'http://192.168.99.108:8000/mytVpc/test?address=50500.b-vm915x.8h2jssajkd.g-songs.ting-wo-shuo-xiexieni.com'

成功返回

{
"code": 0,
"message": "OK",
"data": {
"msg": "dial tcp: address 50500.b-vm915x.8h2jssajkd.g-songs.ting-wo-shuo-xiexieni.com: missing port in address",
"latency": "0ms"
}
}

13. 批量指定云机VPC节点

功能说明:批量指定云机VPC节点

请求方式:POST

请求URL

http://{主机IP}:8000/mytVpc/addRule/batch

请求参数

参数名必选类型说明
namesarray云机容器名称列表
vpcIDintegervpc节点ID
WhiteListDnsarrayDNS白名单

请求示例

curl -X POST -H "Content-Type: application/json" -d '{
"names": ["android_1", "android_2"],
"vpcID": 123,
"WhiteListDns": ["8.8.8.8"]
}' "http://192.168.99.108:8000/mytVpc/addRule/batch"

成功返回

{
"code": 0,
"message": "批量指定成功",
"data": {}
}

失败返回

{
"code": 500,
"message": "批量指定失败",
"data": null
}

14. 清除云机VPC节点

功能说明:清除指定云机的VPC节点

请求方式:POST

请求URL

http://{主机IP}:8000/mytVpc/delRule

请求参数

参数名必选类型说明
namestring云机容器名称

请求示例

curl -X POST -H "Content-Type: application/json" -d '{"name": "android_1"}' "http://192.168.99.108:8000/mytVpc/delRule"

成功返回

{
"code": 0,
"message": "清除成功",
"data": {}
}

失败返回

{
"code": 500,
"message": "清除失败,容器不存在",
"data": null
}


15. 批量清除云机VPC节点

功能说明:批量清除云机的VPC节点

请求方式:POST

请求URL

http://{主机IP}:8000/mytVpc/delRule/batch

请求参数

参数名必选类型说明
namestring云机容器名称列表

请求示例

curl -X POST -H "Content-Type: application/json" -d '{"name": ["android_1", "android_2"]}' "http://192.168.99.108:8000/mytVpc/delRule/batch"

成功返回

{
"code": 0,
"message": "批量清除成功",
"data": {}
}

失败返回

{
"code": 500,
"message": "批量清除失败",
"data": null
}

16. 清除容器域名过滤

功能说明:清除指定容器的域名过滤设置

请求方式:POST

请求URL

http://{主机IP}:8000/mytVpc/domainFilter

请求参数

参数名必选类型说明
containerIDstring容器ID或名称

请求示例

curl -X DELETE "http://192.168.99.108:8000/mytVpc/domainFilter?containerID=abc123"

成功返回

{
"code": 0,
"message": "清除成功",
"data": {}
}

失败返回

{
"code": 500,
"message": "清除失败,容器不存在",
"data": null
}

17. 查询容器域名过滤

功能说明:查询指定容器的域名过滤列表

请求方式:GET

请求URL

http://{主机IP}:8000/mytVpc/domainFilter

请求参数

参数名必选类型说明
containerIDstring容器ID或名称

请求示例

curl -X GET "http://192.168.99.108:8000/mytVpc/domainFilter?containerID=abc123"

成功返回

{
"code": 0,
"message": "查询成功",
"data": {
"domains": ["example.com", "google.com"]
}
}

失败返回

{
"code": 500,
"message": "查询失败,容器不存在",
"data": null
}

18. 设置容器域名过滤

功能说明:设置指定容器的域名过滤列表

请求方式:POST

请求URL

http://{主机IP}:8000/mytVpc/domainFilter

请求参数

参数名必选类型说明
containerIDstring容器ID或名称
domainsarray域名列表,传空数组则清空

请求示例

curl -X POST -H "Content-Type: application/json" -d '{
"containerID": "abc123",
"domains": ["example.com", "google.com"]
}' "http://192.168.99.108:8000/mytVpc/domainFilter"

成功返回

{
"code": 0,
"message": "设置成功",
"data": {}
}

失败返回

{
"code": 500,
"message": "设置失败",
"data": null
}

19. 清除全局域名过滤

功能说明:清除全局域名过滤设置

请求方式:POST

请求URL

http://{主机IP}:8000/mytVpc/domainFilter/global

请求参数:无

请求示例

curl -X POST -H "Content-Type: application/json" -d '{
"containerID": "abc123",
"domains": ["example.com", "google.com"]
}' "http://192.168.99.108:8000/mytVpc/domainFilter"

成功返回

{
"code": 0,
"message": "清除成功",
"data": {}
}

失败返回

{
"code": 500,
"message": "清除失败",
"data": null
}

20. 查询全局域名过滤

功能说明:查询全局域名过滤列表

请求方式:POST

请求URL

http://{主机IP}:8000/mytVpc/domainFilter/global

请求参数:无

请求示例

curl -X GET "http://192.168.99.108:8000/mytVpc/domainFilter/global"

成功返回

{
"code": 0,
"message": "查询成功",
"data": {
"domains": ["example.com", "*.blocked.com"]
}
}

失败返回

{
"code": 500,
"message": "查询失败",
"data": null
}

21. 设置全局域名过滤

功能说明:设置全局域名过滤列表

请求方式:POST

请求URL

http://{主机IP}:8000/mytVpc/domainFilter/global

请求参数

参数名必选类型说明
domainsarray域名列表,支持 domain:/full:/keyword:/regexp: 前缀,传空数组则清空

请求示例

curl -X POST -H "Content-Type: application/json" -d '{
"domains": ["domain:example.com", "keyword:blocked"]
}' "http://192.168.99.108:8000/mytVpc/domainFilter/global"

成功返回

{
"code": 0,
"message": "设置成功",
"data": {}
}

失败返回

{
"code": 500,
"message": "设置失败",
"data": null
}

22. 更新网络分组别名

功能说明:更新网络分组别名

请求方式:POST

请求URL

http://{主机IP}:8000/mytVpc/group/alias

请求参数

参数名必选类型说明
idinteger网络分组ID
newAliasstring分组新别名

请求示例

curl -X POST -H "Content-Type: application/json" -d '{"id":123, "newAlias": "newgroup"}' "http://192.168.99.108:8000/mytVpc/group/alias"

成功返回

{
"code": 0,
"message": "更新成功",
"data": {}
}

失败返回

{
"code": 500,
"message": "更新失败,分组不存在",
"data": null
}

八、本地机型数据管理

1. 获取本地机型列表

功能说明:获取设备上的本地机型数据列表

请求方式:GET

请求URL

http://{主机IP}:8000/phoneModel

请求参数:无

请求示例

curl "http://192.168.99.108:8000/phoneModel"

成功返回

{
"code": 0,
"message": "ok",
"data": {
"count": 5,
"list": [
{
"name": "samsung_s23"
},
{
"name": "xiaomi_14"
},
{
"name": "pixel_8"
}
]
}
}

返回字段说明

字段类型说明
namestring机型文件名称

失败返回

{
"code": 500,
"message": "获取本地机型列表失败",
"data": null
}

2. 删除本地机型数据

功能说明:删除指定的本地机型数据

请求方式:DELETE

请求URL

http://{主机IP}:8000/phoneModel

请求参数

参数名必选类型说明
namestring机型文件名称

请求示例

curl -X DELETE "http://192.168.99.108:8000/phoneModel" \
-H "Content-Type: application/json" \
-d '{
"name": "samsung_s23"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "删除本地机型失败: 文件不存在",
"data": null
}

3. 导出本地机型数据

功能说明:导出指定的本地机型数据

请求方式:POST

请求URL

http://{主机IP}:8000/phoneModel/export

请求参数

参数名必选类型说明
namestring机型文件名称

请求示例

curl -X POST "http://192.168.99.108:8000/phoneModel/export" \
-H "Content-Type: application/json" \
-d '{
"name": "samsung_s23"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "导出本地机型失败: 文件不存在",
"data": null
}

4. 导入机型数据

功能说明:通过上传ZIP包导入机型数据

请求方式:POST

请求URL

http://{主机IP}:8000/phoneModel/import

Content-Typemultipart/form-data

请求参数

参数名必选类型说明
filefile导入修改后的机型ZIP包

请求示例

curl -X POST "http://192.168.99.108:8000/phoneModel/import" \
-F "file=@samsung_s23.zip"

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "导入机型数据失败: 文件格式错误",
"data": null
}

注意事项

  • 仅支持ZIP格式的机型数据包

九、接口认证

1. 修改认证密码

功能说明:修改API接口认证密码(默认用户名admin)

请求方式:POST

请求URL

http://{主机IP}:8000/auth/password

请求参数

参数名必选类型说明
newPasswordstring新密码
confirmPasswordstring确认新密码

请求示例

curl -X POST "http://192.168.99.108:8000/auth/password" \
-H "Content-Type: application/json" \
-d '{
"newPassword": "newpassword123",
"confirmPassword": "newpassword123"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "修改密码失败: 两次密码不一致",
"data": null
}

注意事项

  • 两次输入的密码必须一致
  • 默认用户名为admin
  • 密码修改后立即生效

2. 关闭接口认证

功能说明:关闭API接口认证功能

请求方式:POST

请求URL

http://{主机IP}:8000/auth/close

请求参数:无

请求示例

curl -X POST "http://192.168.99.108:8000/auth/close"

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "关闭认证失败",
"data": null
}

注意事项

  • 关闭认证后,所有接口将无需认证即可访问
  • 出于安全考虑,建议在内网环境下使用

十、服务管理

1. 更新服务

功能说明:在线更新SDK服务到最新版本

请求方式:GET

请求URL

http://{主机IP}:8000/server/upgrade

请求参数:无

请求示例

curl "http://192.168.99.108:8000/server/upgrade"

成功返回

{
"code": 0,
"message": "ok",
"data": {
"msg": "更新成功,服务将自动重启"
}
}

失败返回

{
"code": 500,
"message": "更新失败: 网络连接超时",
"data": null
}

注意事项

  • 更新成功后服务会自动重启
  • 更新过程中请勿断电或断网

2. 通过上传SDK更新服务

功能说明:通过上传SDK压缩包更新服务

请求方式:POST

请求URL

http://{主机IP}:8000/server/upgrade/upload

Content-Typemultipart/form-data

请求参数

参数名必选类型说明
filefileSDK压缩包文件,zip格式

请求示例

curl -X POST "http://192.168.99.108:8000/server/upgrade/upload" \
-F "file=@myt-sdk-v1.2.0.zip"

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "更新失败: 文件格式错误",
"data": null
}

注意事项

  • 仅支持zip格式的SDK压缩包
  • 更新成功后服务会自动重启

3. 清空设备磁盘数据

功能说明:清空设备磁盘上的所有数据(高危操作!)

请求方式:POST

请求URL

http://{主机IP}:8000/server/device/reset

请求参数:无

请求示例

curl -X POST "http://192.168.99.108:8000/server/device/reset"

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "清空数据失败",
"data": null
}

注意事项

  • ⚠️ 高危操作!此操作将清空设备上的所有数据,不可恢复!
  • 执行前请确保已备份所有重要数据
  • 操作完成后设备将恢复出厂状态

4. 重启设备

功能说明:重启设备

请求方式:POST

请求URL

http://{主机IP}:8000/server/device/reboot

请求参数:无

请求示例

curl -X POST "http://192.168.99.108:8000/server/device/reboot"

成功返回

{
"code": 0,
"message": "ok",
"data": {
"message": "设备将在5秒后重启"
}
}

失败返回

{
"code": 500,
"message": "重启设备失败",
"data": null
}

注意事项

  • 重启过程中所有云机将停止运行
  • 重启完成后需要手动启动云机

5. 开启和屏蔽dockerApi 2375端口

功能说明:控制主机上 Docker Remote API(端口 2375)的开启或屏蔽状态

请求方式:POST

请求URL

http://{主机IP}:8000/server/dockerApi

请求参数

参数名必选类型说明
enablebooleantrue 表示开启,false 表示屏蔽

请求示例

curl -X POST "http://192.168.99.108:8000/server/dockerApi" \
-H "Content-Type: application/json" \
-d '{"enable": true}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "操作失败",
"data": null
}

6. 获取主机网络信息

功能说明:获取设备当前的网络配置信息,包括网关、子网和网卡接口

请求方式:GET

请求URL

http://{主机IP}:8000/server/network

请求参数:无

请求示例

curl http://192.168.99.108:8000/server/network

成功返回

{
"code": 0,
"message": "ok",
"data": {
"info": {
"gateway": "192.168.99.1",
"networkCIDR": "192.168.99.0/24",
"interface": "eth0"
}
}
}

失败返回

{
"code": 500,
"message": "获取网络信息失败",
"data": null
}

十一、大模型管理

1. 导入大模型 ZIP 包

功能说明:导入大模型 ZIP 包到设备中

请求方式:POST

请求URL

http://{主机IP}:8000/lm/import

请求参数

参数名必选类型说明
filefile大模型 ZIP 包文件(multipart/form-data 格式)

请求示例

curl -X POST -F "file=@./llm_model.zip" "http://192.168.99.108:8000/lm/import"

成功返回

{
"code": 0,
"message": "导入大模型ZIP包成功",
"data": null
}

失败返回

{
"code": 500,
"message": "导入大模型ZIP包失败,文件格式错误或损坏",
"data": null
}

2. 获取系统信息

功能说明:获取设备及大模型相关系统信息

请求方式:GET

请求URL

http://{主机IP}:8000/lm/info

请求参数:无

请求示例

curl "http://192.168.99.108:8000/lm/info"

成功返回

{
"code": 0,
"message": "ok",
"data": {
"api_version": "v1.0.0",
"nsmi_version": "1.2.3",
"pcie_driver_version": "4.5.6",
"firmware_version": "v2.1.0",
"devices": [
{
"device_id": 1,
"mode": "PCIE",
"global_id": 1001,
"internal_id": 101,
"fan_speed_ratio": 50,
"temp": 42,
"power": 35,
"voltage": 12,
"chips": [
{
"chip_id": 10001,
"chip_name": "RK3588",
"chip_ver": "v1.1",
"cpu_id": "CPU001",
"health": 0,
"temp": 40,
"memory_info": {
"total_size": 8589934592,
"free_size": 4294967296,
"util_rate": 50,
"hugepage_size": 2097152,
"hugepage_total_cnt": 1024,
"hugepage_free_cnt": 512
}
}
]
}
]
}
}

返回字段说明

参数名类型说明
api_versionstringAPI 版本
firmware_versionstring固件版本
devicesarray设备列表
device_idinteger设备全局 ID
chipsarray芯片列表
memory_infoobject内存信息
total_sizeinteger总内存大小(Bytes)
util_rateinteger内存使用率(%)

失败返回

{
"code": 500,
"message": "获取系统信息失败",
"data": null
}

3. 删除本地大模型

功能说明:删除设备上指定名称的本地大模型

请求方式:DELETE

请求URL

http://{主机IP}:8000/lm/local

请求参数

参数名必选类型说明
namestring本地大模型名称

请求示例

curl -X DELETE "http://192.168.99.108:8000/lm/local?name=chatglm3"

成功返回

{
"code": 0,
"message": "删除本地大模型成功",
"data": null
}

失败返回

{
"code": 500,
"message": "删除本地大模型失败,模型不存在",
"data": null
}

4. 获取本地大模型列表

功能说明:获取设备上所有本地大模型的列表信息

请求方式:GET

请求URL

http://{主机IP}:8000/lm/local

请求参数:无

请求示例

curl "http://192.168.99.108:8000/lm/local"

成功返回

{
"code": 0,
"message": "ok",
"data": {
"count": 2,
"list": [
{
"name": "chatglm3",
"size": "10GB",
"files": [
{
"filePath": "/models/chatglm3/main.rknn",
"size": "8GB"
},
{
"filePath": "/models/chatglm3/vocab.json",
"size": "200MB"
}
]
},
{
"name": "llama2",
"size": "15GB",
"files": [
{
"filePath": "/models/llama2/model.rknn",
"size": "12GB"
},
{
"filePath": "/models/llama2/tokenizer.gguf",
"size": "300MB"
}
]
}
]
}
}

返回字段说明

参数名类型说明
countinteger本地大模型总数
namestringstring
sizearray大模型总大小
filesarray大模型包含文件列表
filePathstring文件路径

失败返回

{
"code": 500,
"message": "获取本地大模型列表失败",
"data": null
}

5. 获取模型运行状态

功能说明:获取当前设备上大模型的运行状态信息

请求方式:GET

请求URL

http://{主机IP}:8000/lm/models

请求参数:无

请求示例

curl "http://192.168.99.108:8000/lm/models"

成功返回

{
"code": 0,
"message": "ok",
"data": {
"object": "model_list",
"data": [
{
"id": "model_001",
"object": "model",
"created": 1735689600,
"owned_by": "local",
"meta": {
"ctx_size": 2048,
"predict": 1024,
"temp": 0.7
}
}
]
}
}

返回字段说明

参数名类型说明
idstring模型 ID
createdinteger创建时间戳
metaobject模型元数据
ctx_sizeinteger上下文窗口大小

失败返回

{
"code": 500,
"message": "获取模型运行状态失败",
"data": null
}

6. 重置设备

功能说明:对指定设备进行硬件或软件重置

请求方式:POST

请求URL

http://{主机IP}:8000/lm/reset

请求参数

参数名必选类型说明
typestring重置类型(hw - 硬件,sw - 软件)
device_idinteger设备 ID

请求示例

curl -X POST -H "Content-Type: application/json" -d '{"type":"sw","device_id":1}' "http://192.168.99.108:8000/lm/reset"

成功返回

{
"code": 0,
"message": "设备重置成功",
"data": null
}

失败返回

{
"code": 500,
"message": "设备重置失败,设备ID不存在",
"data": null
}

7. 启动 LLM 服务

功能说明:启动指定配置的 LLM 服务

请求方式:POST

请求URL

http://{主机IP}:8000/lm/server/start

请求参数

参数名必选类型说明
hoststring监听地址,默认值:0.0.0.0
portinteger监听端口,默认值:8081
timeoutinteger超时时间(秒),默认值:30
modelsobject模型配置列表(key 为模型别名)
aliasstring模型别名(与 key 一致)
modelstring主模型文件路径(RKNN)
weightstring主模型权重路径
ctx-sizeinteger上下文窗口大小,默认值:0
tempnumber温度参数,默认值:0.8

请求示例

curl -X POST -H "Content-Type: application/json" -d '{
"host": "0.0.0.0",
"port": 8081,
"timeout": 30,
"models": {
"chatglm3": {
"alias": "chatglm3",
"model": "/models/chatglm3/main.rknn",
"weight": "/models/chatglm3/weight.bin",
"ctx-size": 2048,
"temp": 0.7
}
}
}' "http://192.168.99.108:8000/lm/server/start"

成功返回

{
"code": 0,
"message": "LLM服务启动成功",
"data": null
}

失败返回

{
"code": 500,
"message": "LLM服务启动失败,模型文件不存在",
"data": null
}

8. 停止 LLM 服务

功能说明:停止当前运行的 LLM 服务

请求方式:POST

请求URL

http://{主机IP}:8000/lm/server/stop

请求参数:无

请求示例

curl -X POST "http://192.168.99.108:8000/lm/server/stop"

成功返回

{
"code": 0,
"message": "LLM服务停止成功",
"data": null
}

失败返回

{
"code": 500,
"message": "LLM服务停止失败,服务未运行",
"data": null
}

9. 设置工作模式

功能说明:设置指定设备和芯片的工作模式

请求方式:POST

请求URL

http://{主机IP}:8000/lm/workMode

请求参数

参数名必选类型说明
device_idinteger设备 ID
chip_idinteger芯片 ID
work_modeinteger工作模式,默认值:2

请求示例

curl -X POST -H "Content-Type: application/json" -d '{"device_id":1,"chip_id":10001,"work_mode":2}' "http://192.168.99.108:8000/lm/workMode"

成功返回

{
"code": 0,
"message": "工作模式设置成功",
"data": null
}

失败返回

{
"code": 500,
"message": "工作模式设置失败,设备或芯片ID不存在",
"data": null
}

10. 模型推理对话补全

功能说明:模型推理对话补全

请求方式:POST

请求URL

http://{主机IP}:8000/v1/chat/completions

请求参数

参数名必选类型说明
modelstring模型别名
messagesarray对话历史,每个元素包含 role 和 content
streamboolean是否流式返回,默认 true
max_tokensinteger最大生成 Token 数,默认 2048
temperaturenumber随机性 (0-1),默认 0.7
top_pnumber核采样概率,默认 0.9

请求示例

curl -X POST -H "Content-Type: application/json" -d '{
"model": "llama3",
"messages": [
{"role": "user", "content": "Hello, who are you?"}
],
"stream": true,
"max_tokens": 2048,
"temperature": 0.7,
"top_p": 0.9
}' "http://192.168.99.108:8000/v1/chat/completions"

成功返回

{
"code": 0,
"message": "操作成功",
"data": {
"id": "chatcmpl-123",
"object": "chat.completion",
"created": 1677652288,
"model": "llama3",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "I am an AI assistant."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 10,
"completion_tokens": 20,
"total_tokens": 30
}
}
}

失败返回

{
"code": 500,
"message": "模型不存在或服务异常",
"data": null
}

11. 模型文本向量化

功能说明:模型文本向量化

请求方式:POST

请求URL

http://{主机IP}:8000/v1/embeddings

请求参数

参数名必选类型说明
modelstring模型别名
inputstring/array输入文本,可以是字符串或字符串数组
dimensionsinteger返回的向量维度(仅V3模型支持)
encoding_formatstring返回向量的格式,float 或 base64,默认 float

请求示例

curl -X POST -H "Content-Type: application/json" -d '{
"model": "text-embedding-3-small",
"input": "The quick brown fox jumps over the lazy dog",
"dimensions": 256,
"encoding_format": "float"
}' "http://192.168.99.108:8000/v1/embeddings"

成功返回

{
"code": 0,
"message": "操作成功",
"data": {
"object": "list",
"data": [
{
"object": "embedding",
"index": 0,
"embedding": [0.1, 0.2, 0.3, 0.4]
}
],
"model": "text-embedding-3-small",
"usage": {
"prompt_tokens": 10,
"total_tokens": 10
}
}
}

失败返回

{
"code": 500,
"message": "向量化失败,模型不支持或输入格式错误",
"data": null
}

十二、云机操作V2镜像

1. 创建云机V2

功能说明:创建一个新的安卓云机实例。

请求方式:POST

请求URL

http://{主机IP}:8000/androidV2

请求参数

参数名必选类型说明
namestring云机名称
indexNuminteger实例序号,P1范围1-24,Q1范围1-12,传0将自动分配一个空闲实例序号
imageUrlstring镜像完整地址
sandboxSizestring沙盒大小,例如 "16GB","32GB"
dnsstring云机DNS,例如 "223.5.5.5"
offsetstring云机的开机时间
doboxFpsstring云机FPS
doboxWidthstring云机分辨率的宽
doboxHeightstring云机分辨率的高
doboxDpistring云机DPI
enforceboolean安全模式,默认开启
macVlanIpstring独立IP设置
startboolean创建完成是否开机,默认为 true
vpcIDinteger添加的魔云腾VPC节点ID
portMappingsarray增加自定义端口映射,格式见下方示例
mytBridgeNamestringmyt_bridge网卡名,可以接口查询或在设备终端使用ifconfig查询

请求示例

POST http://192.168.99.108:8000/androidv2
Content-Type: application/json
请求体
{
"name": "test-cloud-phone-v2",
"indexNum": 0,
"imageUrl": "registry.example.com/android:12.0-base",
"sandboxSize": "32GB",
"dns": "8.8.8.8",
"offset": "08:00",
"doboxFps": "60",
"doboxWidth": "1080",
"doboxHeight": "1920",
"doboxDpi": "480",
"enforce": true,
"macVlanIp": "192.168.100.100",
"start": true,
"vpcID": 0,
"portMappings": [
{
"containerPort": 5555,
"hostPort": 55550,
"hostIP": "0.0.0.0",
"protocol": "tcp"
}
],
"mytBridgeName": "myt_bridge_default"
}

成功返回

{
"code": 0,
"message": "OK",
"data": {
"id": "string"
}
}

失败返回

{
"code": 50,
"message": "失败原因",
"data": {
"id": ""
}
}

2. 重置云机V2

功能说明:重置指定名称的安卓云机实例,恢复到初始状态。

请求方式:PUT

请求URL

http://{主机IP}:8000/androidV2

请求参数

参数名必选类型说明
namestring云机名称

请求示例

curl http://192.168.99.108:8000/androidV2 \
--request PUT \
--header 'Content-Type: application/json' \
--data '{
"name": "test-cloud-phone-v2"
}'

成功返回

{
"code": 0,
"message": "OK",
"data": null
}

失败返回

{
"code": 500,
"message": "重置云机失败",
"data": null
}

3. 批量切换容器镜像

功能说明:将多个指定名称的安卓云机批量切换到一个新的镜像。

请求方式:POST

请求URL

http://{主机IP}:8000/androidV2/change-image

请求参数

参数名必选类型说明
containerNamesarray云机名称列表
imagestring新的镜像地址

请求示例

POST http://192.168.99.108:8000/androidV2/change-image
Content-Type: application/json
请求体
{
"containerNames": [
"test-cloud-phone-v2",
"test-cloud-phone-v2-2"
],
"image": "registry.example.com/android:12.0-base"
}
或者
curl http://192.168.99.108:8000/androidV2/change-image \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"containerNames": [
"test-cloud-phone-v2",
"test-cloud-phone-v2-2"
],
"image": "registry.example.com/android:12.0-base"
}'

成功返回

{
"code": 0,
"message": "OK",
"data": null
}

失败返回

{
"code": 500,
"message": "批量切换容器镜像失败",
"data": null
}

4. 复制云机

功能说明:复制指定名称的安卓云机实例。

请求方式:GET

请求URL

http://{主机IP}:8000/androidV2/copy

请求参数

参数名必选类型说明
namestring云机名称
indexNuminteger坑位数
countinteger复制数量,默认为1

请求示例

GET "http://192.168.99.108:8000/androidV2/copy?name=test&indexNum=1&count=1"

curl 'http://192.168.99.108:8000/androidV2/copy?name=test&indexNum=1&count=1'

成功返回

data: {"current":1,"total":1,"name":"test_copy_1","status":"copying","message":"正在复制 data 目录"}

data: {"current":1,"total":1,"name":"test_copy_1","status":"copying","message":"正在创建容器"}

data: {"current":1,"total":1,"name":"test_copy_1","status":"success","message":"27cccd9e0ef05c089c92f4831d191bee9cc20c00db8695f920968d6e2d927181"}

data: {"current":1,"total":1,"name":"","status":"done","message":"","success":["test_copy_1"]}

失败返回

{
"code": 500,
"message": "失败原因",
"data": null
}

5. 切换安卓镜像

功能说明:切换指定名称的安卓云机实例的镜像。

请求方式:POST

请求URL

http://{主机IP}:8000/androidV2/switchImage

请求参数

参数名必选类型说明
imageUrlstring镜像完整地址称
namestring云机名称像地址
adbPortinteger自定义adb端口,默认5555,设置端口0的时候不开启adb,请不要使用9082、9083、10000、10001、10006、10007、10008等端口
dnsstring云机DNS,例如223.5.5.5
doboxDpistring云机DPI
doboxFpsstring云机的帧率(FPS)
doboxWidthstring云机分辨率的宽度
doboxHeightstring云机分辨率的高度
enforcestring是否启用安全模式,默认开启
macVlanIpstring独立 IP 设置,用于为云机分配一个固定的 MACVLAN IP 地址。
mytBridgeNamestringmyt_bridge 网卡名称,可通过接口查询或在设备终端使用 ifconfig 查询。
offsetstring云机的开机时间度
portMappingsstring增加自定义端口映射
startboolean创建完成开机,默认不开机
vpcIDinteger添加的魔云腾VPC节点ID

自定义端口映射

参数名必选类型说明
containerPortinteger容器内端口,如 80
hostIPstring主机IP,如 0.0.0.0 或 不填
hostPortinteger主机端口,如 8080
protocolstring协议,如 tcp、udp, 默认tcp

请求示例

POST http://192.168.99.183:8000/androidV2/switchImage
Content-Type: application/json
请求体
{
"name": "1773039649840_3_T0003",
"imageUrl": "registry.cn-guangzhou.aliyuncs.com/mytos/dobox:P10_base_202509221352"
}

# 或使用curl
curl http://192.168.99.183:8000/androidV2/switchImage \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"name": "1773039649840_3_T0003",
"imageUrl": "registry.cn-guangzhou.aliyuncs.com/mytos/dobox:P10_base_202509221352",
"dns": "",
"offset": "",
"doboxFps": "",
"doboxWidth": "",
"doboxHeight": "",
"doboxDpi": "",
"enforce": true,
"macVlanIp": "",
"start": true,
"vpcID": 0,
"adbPort": 5555,
"portMappings": [
{
"containerPort": 0,
"hostPort": 0,
"hostIP": "",
"protocol": "tcp"
}
]
}'

成功返回

{
"code": 0,
"message": "OK",
"data": null
}

失败返回

{
"code": 10006,
"message": "Error: 容器不存在无法操作,请确认容器名称是否正确",
"data": null
}

十三、用户

1. 登录获取魔云腾Token

功能说明:登录魔云腾平台获取Token,用于同步授权

请求方式:POST

请求URL

http://{主机IP}:8000/user/loginMyt

请求参数

参数名必选类型说明
namestring用户名
passwordstring密码

请求示例

curl -X POST "http://192.168.99.108:8000/user/loginMyt" \
-H "Content-Type: application/json" \
-d '{
"name": "username",
"password": "password123"
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {
"mytToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
}

返回字段说明

字段类型说明
mytTokenstring魔云腾访问Token

失败返回

{
"code": 500,
"message": "登录失败: 用户名或密码错误",
"data": null
}

2. 同步授权

功能说明:同步魔云腾平台授权信息到本地

请求方式:POST

请求URL

http://{主机IP}:8000/user/syncAuthorization

请求参数

参数名必选类型说明
mytTokenstring魔云腾Token

请求示例

curl -X POST "http://192.168.99.108:8000/user/syncAuthorization" \
-H "Content-Type: application/json" \
-d '{
"mytToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}'

成功返回

{
"code": 0,
"message": "ok",
"data": {}
}

失败返回

{
"code": 500,
"message": "同步授权失败: Token无效",
"data": null
}

附录

错误码说明

错误码说明
0成功
400请求参数错误
401未授权/认证失败
404资源不存在
500服务器内部错误

常见问题

  1. 接口返回401错误

    • 检查是否开启了接口认证
    • 确认认证信息是否正确
  2. 云机创建失败

    • 检查镜像是否已拉取到本地
    • 确认实例序号是否被占用
    • 检查磁盘空间是否充足
  3. 无法连接设备

    • 确认设备IP地址是否正确
    • 检查网络连接是否正常
    • 确认端口8000是否开放