HTTP API 指南
本文档介绍如何通过 HTTP API 与 Uni-Lab-OS 进行交互,包括查询设备、提交任务和获取结果。
概述
Uni-Lab-OS 提供 RESTful HTTP API,允许外部系统通过标准 HTTP 请求控制实验室设备。API 基于 FastAPI 构建,默认运行在 http://localhost:8002。
基础信息
Base URL:
http://localhost:8002/api/v1Content-Type:
application/json响应格式: JSON
通用响应结构
{
"code": 0,
"data": { ... },
"message": "success"
}
字段 |
类型 |
说明 |
|---|---|---|
|
int |
状态码,0 表示成功 |
|
object |
响应数据 |
|
string |
响应消息 |
快速开始
以下是一个完整的工作流示例:查询设备 → 获取动作 → 提交任务 → 获取结果。
步骤 1: 获取在线设备
curl -X GET "http://localhost:8002/api/v1/online-devices"
响应示例:
{
"code": 0,
"data": {
"online_devices": {
"host_node": {
"device_key": "/host_node",
"namespace": "",
"machine_name": "本地",
"uuid": "xxx-xxx-xxx",
"node_name": "host_node"
}
},
"total_count": 1,
"timestamp": 1732612345.123
},
"message": "success"
}
步骤 2: 获取设备可用动作
curl -X GET "http://localhost:8002/api/v1/devices/host_node/actions"
响应示例:
{
"code": 0,
"data": {
"device_id": "host_node",
"actions": {
"test_latency": {
"type_name": "unilabos_msgs.action._empty_in.EmptyIn",
"type_name_convert": "unilabos_msgs/action/_empty_in/EmptyIn",
"action_path": "/devices/host_node/test_latency",
"goal_info": "{}",
"is_busy": false,
"current_job_id": null
},
"create_resource": {
"type_name": "unilabos_msgs.action._resource_create_from_outer_easy.ResourceCreateFromOuterEasy",
"action_path": "/devices/host_node/create_resource",
"goal_info": "{res_id: '', device_id: '', class_name: '', ...}",
"is_busy": false,
"current_job_id": null
}
},
"action_count": 5
},
"message": "success"
}
动作状态字段说明:
字段 |
说明 |
|---|---|
|
动作类型的完整名称 |
|
ROS2 动作路径 |
|
动作参数模板 |
|
动作是否正在执行 |
|
当前执行的任务 ID(如果繁忙) |
步骤 3: 提交任务
curl -X POST "http://localhost:8002/api/v1/job/add" \
-H "Content-Type: application/json" \
-d '{"device_id":"host_node","action":"test_latency","action_args":{}}'
请求体:
{
"device_id": "host_node",
"action": "test_latency",
"action_args": {}
}
请求参数说明:
字段 |
类型 |
必填 |
说明 |
|---|---|---|---|
|
string |
✓ |
目标设备 ID |
|
string |
✓ |
动作名称 |
|
object |
✓ |
动作参数(根据动作类型不同而变化) |
响应示例:
{
"code": 0,
"data": {
"jobId": "b6acb586-733a-42ab-9f73-55c9a52aa8bd",
"status": 1,
"result": {}
},
"message": "success"
}
任务状态码:
状态码 |
含义 |
说明 |
|---|---|---|
0 |
UNKNOWN |
未知状态 |
1 |
ACCEPTED |
任务已接受,等待执行 |
2 |
EXECUTING |
任务执行中 |
3 |
CANCELING |
任务取消中 |
4 |
SUCCEEDED |
任务成功完成 |
5 |
CANCELED |
任务已取消 |
6 |
ABORTED |
任务中止(设备繁忙或执行失败) |
步骤 4: 查询任务状态和结果
curl -X GET "http://localhost:8002/api/v1/job/b6acb586-733a-42ab-9f73-55c9a52aa8bd/status"
响应示例(执行中):
{
"code": 0,
"data": {
"jobId": "b6acb586-733a-42ab-9f73-55c9a52aa8bd",
"status": 2,
"result": {}
},
"message": "success"
}
响应示例(执行完成):
{
"code": 0,
"data": {
"jobId": "b6acb586-733a-42ab-9f73-55c9a52aa8bd",
"status": 4,
"result": {
"error": "",
"suc": true,
"return_value": {
"avg_rtt_ms": 103.99,
"avg_time_diff_ms": 7181.55,
"max_time_error_ms": 7210.57,
"task_delay_ms": -1,
"raw_delay_ms": 33.19,
"test_count": 5,
"status": "success"
}
}
},
"message": "success"
}
注意: 任务结果在首次查询后会被自动删除,请确保保存返回的结果数据。
API 端点列表
设备相关
端点 |
方法 |
说明 |
|---|---|---|
|
GET |
获取在线设备列表 |
|
GET |
获取设备配置 |
|
GET |
获取指定设备的可用动作 |
|
GET |
获取动作参数 Schema |
|
GET |
获取所有设备的可用动作 |
任务相关
端点 |
方法 |
说明 |
|---|---|---|
|
POST |
提交新任务 |
|
GET |
查询任务状态和结果 |
资源相关
端点 |
方法 |
说明 |
|---|---|---|
|
GET |
获取资源列表 |
常见动作示例
test_latency - 延迟测试
测试系统延迟,无需参数。
curl -X POST "http://localhost:8002/api/v1/job/add" \
-H "Content-Type: application/json" \
-d '{"device_id":"host_node","action":"test_latency","action_args":{}}'
create_resource - 创建资源
在设备上创建新资源。
curl -X POST "http://localhost:8002/api/v1/job/add" \
-H "Content-Type: application/json" \
-d '{
"device_id": "host_node",
"action": "create_resource",
"action_args": {
"res_id": "my_plate",
"device_id": "host_node",
"class_name": "Plate",
"parent": "deck",
"bind_locations": {"x": 0, "y": 0, "z": 0}
}
}'
错误处理
设备繁忙
当设备正在执行其他任务时,提交新任务会返回 status: 6(ABORTED):
{
"code": 0,
"data": {
"jobId": "xxx",
"status": 6,
"result": {}
},
"message": "success"
}
此时应等待当前任务完成后重试,或使用 /devices/{device_id}/actions 检查动作的 is_busy 状态。
参数错误
{
"code": 2002,
"data": { ... },
"message": "device_id is required"
}
轮询策略
推荐的任务状态轮询策略:
import requests
import time
def wait_for_job(job_id, timeout=60, interval=0.5):
"""等待任务完成并返回结果"""
start_time = time.time()
while time.time() - start_time < timeout:
response = requests.get(f"http://localhost:8002/api/v1/job/{job_id}/status")
data = response.json()["data"]
status = data["status"]
if status in (4, 5, 6): # SUCCEEDED, CANCELED, ABORTED
return data
time.sleep(interval)
raise TimeoutError(f"Job {job_id} did not complete within {timeout} seconds")
# 使用示例
response = requests.post(
"http://localhost:8002/api/v1/job/add",
json={"device_id": "host_node", "action": "test_latency", "action_args": {}}
)
job_id = response.json()["data"]["jobId"]
result = wait_for_job(job_id)
print(result)