22 KiB
22 KiB
Hawkbit DDI API — curl 完整操作手册
基于实际验证的 Hawkbit DDI API v1 交互流程,所有命令均已跑通。
环境信息
Hawkbit Server: http://192.168.142.128:9090
Tenant: DEFAULT
Auth: GatewayToken my-gateway-key (DDI 接口)
admin:admin (Management 接口)
Controller ID: test-curl-001
DistributionSet: id=1 (r3576test:V1.0.0.0)
目录
- 认证配置
- 自动注册与轮询
- 分配 Distribution Set
- 拉取部署详情
- 上报设备属性
- 下载 artifact
- SHA256 文件校验
- 上报执行状态
- 取消任务
- 确认任务流程
- 查询验证
- 完整流程速查
1. 认证配置
1.1 开启 GatewayToken 认证(服务端,一次性)
# 设置 token key
curl -u admin:admin -X PUT \
-H "Content-Type: application/json" \
"http://192.168.142.128:9090/rest/v1/system/configs/authentication.gatewaytoken.key" \
-d '{"value": "my-gateway-key"}'
# 启用 gateway token 认证
curl -u admin:admin -X PUT \
-H "Content-Type: application/json" \
"http://192.168.142.128:9090/rest/v1/system/configs/authentication.gatewaytoken.enabled" \
-d '{"value": true}'
1.2 开启 TargetToken 认证(服务端,一次性)
curl -u admin:admin -X PUT \
-H "Content-Type: application/json" \
"http://192.168.142.128:9090/rest/v1/system/configs/authentication.targettoken.enabled" \
-d '{"value": true}'
1.3 查看当前所有认证配置
curl -s -u admin:admin \
"http://192.168.142.128:9090/rest/v1/system/configs" \
| python3 -m json.tool | grep -E "authentication\.(gateway|target)"
1.4 认证方式对比
DDI 请求头:
GatewayToken → Authorization: GatewayToken my-gateway-key
TargetToken → Authorization: TargetToken <设备securityToken>
Management API 请求头:
Basic Auth → -u admin:admin
2. 自动注册与轮询
2.1 首次轮询(自动注册)
GET /{tenant}/controller/v1/{controllerId}
设备 SN 在 Hawkbit 中不存在时,服务端自动调用 findOrRegisterTargetIfItDoesNotExist() 创建 target。
curl -v \
-H "Authorization: GatewayToken my-gateway-key" \
-H "Accept: application/json" \
"http://192.168.142.128:9090/DEFAULT/controller/v1/test-curl-001"
响应(无待处理 action):
{
"config": {"polling": {"sleep": "00:05:00"}},
"_links": {
"configData": {
"href": "http://192.168.142.128:9090/DEFAULT/controller/v1/test-curl-001/configData"
}
}
}
响应(有待处理 action):
{
"config": {"polling": {"sleep": "00:05:00"}},
"_links": {
"deploymentBase": {
"href": "http://192.168.142.128:9090/DEFAULT/controller/v1/test-curl-001/deploymentBase/15?c=424529173"
},
"configData": {
"href": "http://192.168.142.128:9090/DEFAULT/controller/v1/test-curl-001/configData"
}
}
}
2.2 响应中的 HAL 链接含义
| 链接 rel | 含义 | 下一步动作 |
|---|---|---|
deploymentBase |
有待执行的部署任务 | 拉取部署详情 → 下载 → 安装 |
cancelAction |
有取消指令 | 确认取消 |
confirmationBase |
有需要确认的任务 | 发送确认 |
configData |
服务端要求上报属性 | PUT 属性数据 |
installedBase |
有历史安装记录 | 可查询 |
3. 分配 Distribution Set
POST /rest/v1/distributionsets/{distributionSetId}/assignedTargets
⚠️ 这是 Management API,用
-u admin:admin认证。
curl -u admin:admin -X POST \
-H "Content-Type: application/json" \
"http://192.168.142.128:9090/rest/v1/distributionsets/1/assignedTargets" \
-d '[{"id": "test-curl-001"}]'
可选参数(完整请求体):
{
"id": "test-curl-001",
"type": "forced",
"forcetime": 1682408575278,
"weight": 1000,
"maintenanceWindow": {
"schedule": "00:00-04:00",
"duration": "02:00:00",
"timezone": "+08:00"
},
"confirmationRequired": false
}
响应:200 OK,返回 MgmtTargetAssignmentResponseBody。
分配成功后,设备下次轮询就会拿到 deploymentBase 链接。
4. 拉取部署详情
GET /{tenant}/controller/v1/{controllerId}/deploymentBase/{actionId}
curl -H "Authorization: GatewayToken my-gateway-key" \
-H "Accept: application/json" \
"http://192.168.142.128:9090/DEFAULT/controller/v1/test-curl-001/deploymentBase/15"
响应:
{
"id": "15",
"deployment": {
"download": "forced",
"update": "forced",
"chunks": [
{
"part": "os",
"version": "V1.0.0.0",
"name": "r3576-OS-android",
"artifacts": [
{
"filename": "update.zip",
"hashes": {
"sha1": "223377ea691bd7fc47865cccfd802771ff1b3fca",
"md5": "28a17f5fb87d637756c0cc5d555d69b7",
"sha256": "438b8f9e2af3a3334dc72272d167e0deda8c6e65bb1585202151b3cb866bb530"
},
"size": 195411,
"_links": {
"download-http": {
"href": "http://192.168.142.128:9090/DEFAULT/controller/v1/test-curl-001/softwaremodules/1/artifacts/update.zip"
},
"md5sum-http": {
"href": "http://192.168.142.128:9090/DEFAULT/controller/v1/test-curl-001/softwaremodules/1/artifacts/update.zip.MD5SUM"
}
}
}
]
}
]
}
}
字段说明
| 字段 | 说明 |
|---|---|
id |
action ID,后续反馈操作的关键参数 |
deployment.download |
forced=强制下载 / attempt=尝<><E5B09D><EFBFBD>下载 / skip=跳过 |
deployment.update |
forced=强制安装 / attempt=尝试安装 / skip=跳过 |
chunks[].part |
软件模块类型(os / app / …) |
chunks[].version |
软件版本号 |
chunks[].artifacts[].filename |
要下载的文件名 |
chunks[].artifacts[].hashes |
SHA1 / MD5 / SHA256 校验值 |
chunks[].artifacts[].size |
文件大小(bytes) |
_links.download-http.href |
下载地址 |
download / update handlingType 组合
| download | update | 含义 |
|---|---|---|
forced |
forced |
立即下载并安装 |
attempt |
attempt |
设备自行决定是否下载/安装 |
forced |
skip |
只下载不安装(download only) |
skip |
skip |
maintenance window 未到,等待下次轮询 |
5. 上报设备属性
PUT /{tenant}/controller/v1/{controllerId}/configData
⚠️ 必须先轮询一次让 target 自动注册,再上报属性,否则 404。
curl -H "Authorization: GatewayToken my-gateway-key" \
-H "Content-Type: application/json" -X PUT \
"http://192.168.142.128:9090/DEFAULT/controller/v1/test-curl-001/configData" \
-d '{
"mode": "merge",
"data": {
"osType": "linux",
"platform": "x86_64",
"kernel": "6.17.0-35-generic",
"hostname": "test-curl-001",
"hwRevision": "VMware Virtual Platform",
"manufacturer": "VMware, Inc.",
"swVersion": "V1.0.0.0"
}
}'
mode 说明
| mode | 行为 |
|---|---|
merge |
合并:只更新传入的 key,保留已有属性(推荐) |
replace |
替换:完全覆盖已有属性 |
remove |
删除:移除传入的 key |
响应:200 OK(空 body)
查询设备属性
curl -u admin:admin \
"http://192.168.142.128:9090/rest/v1/targets/test-curl-001/attributes"
6. 下载 artifact
GET /{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{fileName}
6.1 完整下载
curl -H "Authorization: GatewayToken my-gateway-key" \
-o /tmp/test-update.zip \
"http://192.168.142.128:9090/DEFAULT/controller/v1/test-curl-001/softwaremodules/1/artifacts/update.zip"
响应:200 OK,二进制流。
6.2 断点续传(Range 请求)
# 续传:从 byte 1048576 开始
curl -H "Authorization: GatewayToken my-gateway-key" \
-H "Range: bytes=1048576-" \
-o /tmp/test-update.zip.part --append \
"http://192.168.142.128:9090/DEFAULT/controller/v1/test-curl-001/softwaremodules/1/artifacts/update.zip"
响应:206 Partial Content,Content-Range: bytes 1048576-195410/195411。
6.3 条件请求(If-Match)
curl -H "Authorization: GatewayToken my-gateway-key" \
-H "If-Match: 223377ea691bd7fc47865cccfd802771ff1b3fca" \
-o /tmp/test-update.zip \
"http://..."
# SHA1 不匹配 → 412 Precondition Failed
6.4 下载 MD5SUM
curl -H "Authorization: GatewayToken my-gateway-key" \
"http://192.168.142.128:9090/DEFAULT/controller/v1/test-curl-001/softwaremodules/1/artifacts/update.zip.MD5SUM"
响应:28a17f5fb87d637756c0cc5d555d69b7 update.zip
6.5 从 HAL 链接提取下载地址
artifact 的 _links 中有两个下载链接,优先级:
download → HTTPS(如果有,首选)
download-http → HTTP(回退方案)
md5sum-http → MD5 校验文件(HTTP)
7. SHA256 文件校验
7.1 计算本地文件 SHA256
sha256sum /tmp/test-update.zip
7.2 对比部署详情中的哈希值
# 部署详情中的 SHA256:
# "sha256": "438b8f9e2af3a3334dc72272d167e0deda8c6e65bb1585202151b3cb866bb530"
echo "438b8f9e2af3a3334dc72272d167e0deda8c6e65bb1585202151b3cb866bb530 /tmp/test-update.zip" | sha256sum -c
# → /tmp/test-update.zip: OK
8. 上报执行状态
POST /{tenant}/controller/v1/{controllerId}/deploymentBase/{actionId}/feedback
8.1 状态上报 JSON 格式
{
"timestamp": 1750000000000,
"status": {
"execution": "download",
"result": {
"finished": "none",
"progress": {"cnt": 2, "of": 5}
},
"code": 200,
"details": ["Starting download"]
}
}
8.2 四步标准流程
# 定义变量,方便重复使用
D="http://192.168.142.128:9090/DEFAULT/controller/v1/test-curl-001/deploymentBase/15/feedback"
A="Authorization: GatewayToken my-gateway-key"
J="Content-Type: application/json"
# ① download — 开始下载
curl -H "$A" -H "$J" \
-d '{"status":{"execution":"download","result":{"finished":"none"},"details":["Starting download"]}}' \
"$D"
# ② downloaded — 下载完成
curl -H "$A" -H "$J" \
-d '{"status":{"execution":"downloaded","result":{"finished":"none"},"details":["Downloaded update.zip"]}}' \
"$D"
# ③ proceeding — 安装中
curl -H "$A" -H "$J" \
-d '{"status":{"execution":"proceeding","result":{"finished":"none"},"details":["Installing update"]}}' \
"$D"
# ④ closed — 最终结果
# 成功:
curl -H "$A" -H "$J" \
-d '{"status":{"execution":"closed","result":{"finished":"success"},"details":["Installation complete"],"code":200}}' \
"$D"
# 失败:
curl -H "$A" -H "$J" \
-d '{"status":{"execution":"closed","result":{"finished":"failure"},"details":["Installation failed"],"code":500}}' \
"$D"
8.3 execution 枚举值
| execution | Hawkbit Status | 说明 |
|---|---|---|
download |
DOWNLOAD |
开始下载 |
downloaded |
DOWNLOADED |
下载完成 |
proceeding |
RUNNING |
安装进行中 |
closed |
FINISHED / ERROR |
最终状态(配合 result.finished) |
canceled |
CANCELED |
已取消 |
rejected |
WARNING |
已拒绝 |
scheduled |
RUNNING |
已计划 |
resumed |
RUNNING |
恢复执行 |
8.4 result.finished 枚举值
| finished | 含义 |
|---|---|
none |
尚未完成(中间状态) |
success |
执行成功 |
failure |
执行失败 |
8.5 带进度的上报
# 进度: 第2个/总共5个 artifact
curl -H "$A" -H "$J" \
-d '{"status":{"execution":"proceeding","result":{"finished":"none","progress":{"cnt":2,"of":5}},"details":["Downloading artifact 2/5"]}}' \
"$D"
8.6 取消反馈(cancelAction feedback)
curl -H "$A" -H "$J" \
-d '{"status":{"execution":"canceled","result":{"finished":"none"},"details":["Cancel acknowledged"]}}' \
"http://192.168.142.128:9090/DEFAULT/controller/v1/test-curl-001/cancelAction/15/feedback"
8.7 确认反馈(confirmationBase feedback)
curl -H "$A" -H "$J" \
-d '{"confirmation":"confirmed","code":200,"details":["Auto-confirmed"]}' \
"http://192.168.142.128:9090/DEFAULT/controller/v1/test-curl-001/confirmationBase/15/feedback"
8.8 常见错误
| HTTP 状态码 | 原因 | 解决 |
|---|---|---|
401 |
认证未通过 | 检查 Authorization header 格式 |
404 |
URL 路径错误或 target 不存在 | 确保 /{tenant}/controller/v1/... |
405 |
feedback URL 带了 ?c=xxx 参数 |
POST 前剥离查询参数 |
410 Gone |
action 已不再活跃 | 已经 closed 或 canceled |
400 Body Not Readable |
JSON 格式错误 | "final" 应为 "finished","progress":{} 应为 null 或省略 |
9. 取消任务
9.1 服务端发起取消(Management API)
curl -u admin:admin -X DELETE \
"http://192.168.142.128:9090/rest/v1/targets/test-curl-001/actions/15"
9.2 设备端处理取消
# ① 轮询拿到 cancelAction
curl -H "Authorization: GatewayToken my-gateway-key" \
"http://192.168.142.128:9090/DEFAULT/controller/v1/test-curl-001"
# → _links.cancelAction.href
# ② 确认取消
curl -H "Authorization: GatewayToken my-gateway-key" \
-H "Content-Type: application/json" \
-d '{"status":{"execution":"canceled","result":{"finished":"none"},"details":["Acknowledged"]}}' \
"http://192.168.142.128:9090/DEFAULT/controller/v1/test-curl-001/cancelAction/15/feedback"
10. 确认任务流程
10.1 开启确认流程(服务端)
curl -u admin:admin -X PUT \
-H "Content-Type: application/json" \
"http://192.168.142.128:9090/rest/v1/system/configs/user.confirmation.flow.enabled" \
-d '{"value": true}'
10.2 分配时要求确认
curl -u admin:admin -X POST \
-H "Content-Type: application/json" \
"http://192.168.142.128:9090/rest/v1/distributionsets/1/assignedTargets" \
-d '[{"id":"test-curl-001","confirmationRequired":true}]'
10.3 设备端自动确认
curl -H "Authorization: GatewayToken my-gateway-key" \
-H "Content-Type: application/json" \
-d '{"confirmation":"confirmed","code":200,"details":["Auto-confirmed"]}' \
"http://192.168.142.128:9090/DEFAULT/controller/v1/test-curl-001/confirmationBase/15/feedback"
11. 查询验证
11.1 查询 target 基本信息
curl -u admin:admin \
"http://192.168.142.128:9090/rest/v1/targets/test-curl-001"
11.2 查询 target 所有 action
curl -u admin:admin \
"http://192.168.142.128:9090/rest/v1/targets/test-curl-001/actions"
11.3 查询指定 action 详情
curl -u admin:admin \
"http://192.168.142.128:9090/rest/v1/targets/test-curl-001/actions/15"
11.4 查询 action 状态历史
curl -u admin:admin \
"http://192.168.142.128:9090/rest/v1/targets/test-curl-001/actions/15/status"
响应示例(完成全流程后):
{
"content": [
{"id":58, "type": "finished", "messages": ["Installation complete"], ...},
{"id":57, "type": "running", "messages": ["Installing update"], ...},
{"id":56, "type": "downloaded","messages": ["Downloaded update.zip"], ...},
{"id":55, "type": "download", "messages": ["Starting download"], ...},
{"id":54, "type": "download", "messages": ["Target downloads ..."], ...},
{"id":53, "type": "retrieved", "messages": ["Target retrieved ..."], ...},
{"id":52, "type": "running", "messages": ["Assignment initiated ..."]}
],
"total": 7, "size": 7
}
11.5 查询 target 属性
curl -u admin:admin \
"http://192.168.142.128:9090/rest/v1/targets/test-curl-001/attributes"
11.6 查询所有 target
curl -u admin:admin \
"http://192.168.142.128:9090/rest/v1/targets"
11.7 查询所有 Distribution Set
curl -u admin:admin \
"http://192.168.142.128:9090/rest/v1/distributionsets"
12. 完整流程速查
12.1 一次完整的 OTA 生命周期(复制粘贴即用)
# ═══ 变量设置 ═══
HOST="http://192.168.142.128:9090"
TENANT="DEFAULT"
CID="test-curl-001"
AUTH="Authorization: GatewayToken my-gateway-key"
ADMIN="admin:admin"
# ═══ Step 1: 轮询(自动注册)═══════════════════════════════════════
curl -s -H "$AUTH" -H "Accept: application/json" \
"$HOST/$TENANT/controller/v1/$CID" | python3 -m json.tool
# ═══ Step 2: 分配 Distribution Set(Management API)═════════════════
curl -u $ADMIN -X POST -H "Content-Type: application/json" \
"$HOST/rest/v1/distributionsets/1/assignedTargets" \
-d '[{"id": "'$CID'"}]'
# ═══ Step 3: 轮询(拿到 deploymentBase)═════════════════════════════
RESP=$(curl -s -H "$AUTH" -H "Accept: application/json" \
"$HOST/$TENANT/controller/v1/$CID")
echo "$RESP" | python3 -m json.tool
# 提取 actionId(假设第一次分配,取 deploymentBase URL 中的数字)
DEPLOY_URL=$(echo "$RESP" | python3 -c "import sys,json; print(json.load(sys.stdin)['_links']['deploymentBase']['href'])")
AID=$(echo "$DEPLOY_URL" | grep -oP 'deploymentBase/\K\d+')
echo "Action ID: $AID"
# ═══ Step 4: 拉取部署详情 ══════════════════════════════════════════
DEPLOY=$(curl -s -H "$AUTH" -H "Accept: application/json" \
"$HOST/$TENANT/controller/v1/$CID/deploymentBase/$AID")
echo "$DEPLOY" | python3 -m json.tool
# 提取下载地址和 SHA256
DL_URL=$(echo "$DEPLOY" | python3 -c "
import sys,json
art = json.load(sys.stdin)['deployment']['chunks'][0]['artifacts'][0]
print(art['_links']['download-http']['href'])
")
SHA256=$(echo "$DEPLOY" | python3 -c "
import sys,json
print(json.load(sys.stdin)['deployment']['chunks'][0]['artifacts'][0]['hashes']['sha256'])
")
echo "Download: $DL_URL"
echo "SHA256: $SHA256"
# ═══ Step 5: 上报属性 ══════════════════════════════════════════════
curl -s -H "$AUTH" -H "Content-Type: application/json" -X PUT \
"$HOST/$TENANT/controller/v1/$CID/configData" \
-d '{"mode":"merge","data":{"osType":"linux","hostname":"'$CID'","swVersion":"V1.0.0.0"}}'
# ═══ Step 6: 下载 ══════════════════════════════════════════════════
curl -H "$AUTH" -o /tmp/update.zip "$DL_URL"
# ═══ Step 7: 校验 ══════════════════════════════════════════════════
echo "$SHA256 /tmp/update.zip" | sha256sum -c
# ═══ Step 8: 上报四步状态 ══════════════════════════════════════════
FB="$HOST/$TENANT/controller/v1/$CID/deploymentBase/$AID/feedback"
curl -s -H "$AUTH" -H "Content-Type: application/json" \
-d '{"status":{"execution":"download","result":{"finished":"none"},"details":["Starting"]}}' "$FB"
curl -s -H "$AUTH" -H "Content-Type: application/json" \
-d '{"status":{"execution":"downloaded","result":{"finished":"none"},"details":["Downloaded"]}}' "$FB"
curl -s -H "$AUTH" -H "Content-Type: application/json" \
-d '{"status":{"execution":"proceeding","result":{"finished":"none"},"details":["Installing"]}}' "$FB"
curl -s -H "$AUTH" -H "Content-Type: application/json" \
-d '{"status":{"execution":"closed","result":{"finished":"success"},"details":["Installation complete"],"code":200}}' "$FB"
# ═══ Step 9: 验证 ══════════════════════════════════════════════════
curl -s -u $ADMIN "$HOST/rest/v1/targets/$CID/actions/$AID/status" | python3 -m json.tool
echo "Done! Action $AID is now finished."
12.2 Hawkbit 状态流转图
管理员分配 DS
│
▼
RUNNING WAITING_FOR_CONFIRMATION
│ │
▼ │ confirmed
RETRIEVED ◄─── deploymentBase ▼
│ (轮询返回) RUNNING
▼ │
DOWNLOAD ...
│
▼
DOWNLOADED
│
▼
PROCEEDING ──→ status: RUNNING
│
┌───┴───┐
▼ ▼
FINISHED ERROR ◄─── closed + success/failure
(成功) (失败)
任意阶段 ──cancel──→ CANCELING ──→ CANCELED
12.3 API 端点速查表
| 操作 | 方法 | 路径 | 认证 |
|---|---|---|---|
| 轮询 | GET | /{tenant}/controller/v1/{controllerId} |
DDI |
| 部署详情 | GET | /{tenant}/controller/v1/{controllerId}/deploymentBase/{actionId} |
DDI |
| 上报反馈 | POST | .../deploymentBase/{actionId}/feedback |
DDI |
| 取消反馈 | POST | .../cancelAction/{actionId}/feedback |
DDI |
| 确认反馈 | POST | .../confirmationBase/{actionId}/feedback |
DDI |
| 上报属性 | PUT | /{tenant}/controller/v1/{controllerId}/configData |
DDI |
| 下载文件 | GET | /{tenant}/controller/v1/{controllerId}/softwaremodules/{id}/artifacts/{file} |
DDI |
| 下载MD5 | GET | .../softwaremodules/{id}/artifacts/{file}.MD5SUM |
DDI |
| 分配 DS | POST | /rest/v1/distributionsets/{id}/assignedTargets |
Basic |
| 查询 target | GET | /rest/v1/targets/{controllerId} |
Basic |
| 查询 action | GET | /rest/v1/targets/{controllerId}/actions/{id} |
Basic |
| 查询状态 | GET | /rest/v1/targets/{controllerId}/actions/{id}/status |
Basic |
| 查询属性 | GET | /rest/v1/targets/{controllerId}/attributes |
Basic |
| 取消 action | DELETE | /rest/v1/targets/{controllerId}/actions/{id} |
Basic |
| 配置管理 | GET/PUT/DELETE | /rest/v1/system/configs/{key} |
Basic |