Files
hawkbit/huaxu/CURL-API.md
lingwei.kong c191bd07ba
Some checks failed
Mark & close stale issues / stale (push) Has been cancelled
Vulnerability Scan / trivy-scan (1.0) (push) Has been cancelled
Vulnerability Scan / trivy-scan (master) (push) Has been cancelled
添加huaxuapi说明
2026-06-26 17:14:13 +08:00

22 KiB
Raw Permalink Blame History

Hawkbit DDI API — curl 完整操作手册

基于实际验证的 Hawkbit DDI API v1 交互流程,所有命令均已跑通。

环境信息

Hawkbit Server:  http://192.168.77.70:8080
Tenant:          DEFAULT
Auth:            GatewayToken my-gateway-key    (DDI 接口)
                 admin:admin                    (Management 接口)
Controller ID:   test-curl-001
DistributionSet: id=1 (r3576test:V1.0.0.0)

目录

  1. 认证配置
  2. 自动注册与轮询
  3. 分配 Distribution Set
  4. 拉取部署详情
  5. 上报设备属性
  6. 下载 artifact
  7. SHA256 文件校验
  8. 上报执行状态
  9. 取消任务
  10. 确认任务流程
  11. 查询验证
  12. 完整流程速查

1. 认证配置

1.1 开启 GatewayToken 认证(服务端,一次性)

# 设置 token key
curl -u admin:admin -X PUT \
  -H "Content-Type: application/json" \
  "http://192.168.77.70:8080/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.77.70:8080/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.77.70:8080/rest/v1/system/configs/authentication.targettoken.enabled" \
  -d '{"value": true}'

1.3 查看当前所有认证配置

curl -s -u admin:admin \
  "http://192.168.77.70:8080/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.77.70:8080/DEFAULT/controller/v1/test-curl-001"

响应(无待处理 action

{
  "config": {"polling": {"sleep": "00:05:00"}},
  "_links": {
    "configData": {
      "href": "http://192.168.77.70:8080/DEFAULT/controller/v1/test-curl-001/configData"
    }
  }
}

响应(有待处理 action

{
  "config": {"polling": {"sleep": "00:05:00"}},
  "_links": {
    "deploymentBase": {
      "href": "http://192.168.77.70:8080/DEFAULT/controller/v1/test-curl-001/deploymentBase/15?c=424529173"
    },
    "configData": {
      "href": "http://192.168.77.70:8080/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.77.70:8080/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.77.70:8080/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.77.70:8080/DEFAULT/controller/v1/test-curl-001/softwaremodules/1/artifacts/update.zip"
              },
              "md5sum-http": {
                "href": "http://192.168.77.70:8080/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.77.70:8080/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.77.70:8080/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.77.70:8080/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.77.70:8080/DEFAULT/controller/v1/test-curl-001/softwaremodules/1/artifacts/update.zip"

响应206 Partial ContentContent-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.77.70:8080/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.77.70:8080/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.77.70:8080/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.77.70:8080/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.77.70:8080/rest/v1/targets/test-curl-001/actions/15"

9.2 设备端处理取消

# ① 轮询拿到 cancelAction
curl -H "Authorization: GatewayToken my-gateway-key" \
  "http://192.168.77.70:8080/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.77.70:8080/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.77.70:8080/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.77.70:8080/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.77.70:8080/DEFAULT/controller/v1/test-curl-001/confirmationBase/15/feedback"

11. 查询验证

11.1 查询 target 基本信息

curl -u admin:admin \
  "http://192.168.77.70:8080/rest/v1/targets/test-curl-001"

11.2 查询 target 所有 action

curl -u admin:admin \
  "http://192.168.77.70:8080/rest/v1/targets/test-curl-001/actions"

11.3 查询指定 action 详情

curl -u admin:admin \
  "http://192.168.77.70:8080/rest/v1/targets/test-curl-001/actions/15"

11.4 查询 action 状态历史

curl -u admin:admin \
  "http://192.168.77.70:8080/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.77.70:8080/rest/v1/targets/test-curl-001/attributes"

11.6 查询所有 target

curl -u admin:admin \
  "http://192.168.77.70:8080/rest/v1/targets"

11.7 查询所有 Distribution Set

curl -u admin:admin \
  "http://192.168.77.70:8080/rest/v1/distributionsets"

12. 完整流程速查

12.1 一次完整的 OTA 生命周期(复制粘贴即用)

# ═══ 变量设置 ═══
HOST="http://192.168.77.70:8080"
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 SetManagement 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