747 lines
22 KiB
Markdown
747 lines
22 KiB
Markdown
|
|
# 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. [认证配置](#1-认证配置)
|
|||
|
|
2. [自动注册与轮询](#2-自动注册与轮询)
|
|||
|
|
3. [分配 Distribution Set](#3-分配-distribution-set)
|
|||
|
|
4. [拉取部署详情](#4-拉取部署详情)
|
|||
|
|
5. [上报设备属性](#5-上报设备属性)
|
|||
|
|
6. [下载 artifact](#6-下载-artifact)
|
|||
|
|
7. [SHA256 文件校验](#7-sha256-文件校验)
|
|||
|
|
8. [上报执行状态](#8-上报执行状态)
|
|||
|
|
9. [取消任务](#9-取消任务)
|
|||
|
|
10. [确认任务流程](#10-确认任务流程)
|
|||
|
|
11. [查询验证](#11-查询验证)
|
|||
|
|
12. [完整流程速查](#12-完整流程速查)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. 认证配置
|
|||
|
|
|
|||
|
|
### 1.1 开启 GatewayToken 认证(服务端,一次性)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 设置 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 认证(服务端,一次性)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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 查看当前所有认证配置
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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。
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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):**
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"config": {"polling": {"sleep": "00:05:00"}},
|
|||
|
|
"_links": {
|
|||
|
|
"configData": {
|
|||
|
|
"href": "http://192.168.77.70:8080/DEFAULT/controller/v1/test-curl-001/configData"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**响应(有待处理 action):**
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"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` 认证。
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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"}]'
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**可选参数(完整请求体)**:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"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}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**响应**:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"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。
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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)
|
|||
|
|
|
|||
|
|
### 查询设备属性
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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 完整下载
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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 请求)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 续传:从 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 Content`,`Content-Range: bytes 1048576-195410/195411`。
|
|||
|
|
|
|||
|
|
### 6.3 条件请求(If-Match)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
curl -H "Authorization: GatewayToken my-gateway-key" \
|
|||
|
|
-H "If-Match: 223377ea691bd7fc47865cccfd802771ff1b3fca" \
|
|||
|
|
-o /tmp/test-update.zip \
|
|||
|
|
"http://..."
|
|||
|
|
# SHA1 不匹配 → 412 Precondition Failed
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 6.4 下载 MD5SUM
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
sha256sum /tmp/test-update.zip
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 7.2 对比部署详情中的哈希值
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 部署详情中的 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 格式
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"timestamp": 1750000000000,
|
|||
|
|
"status": {
|
|||
|
|
"execution": "download",
|
|||
|
|
"result": {
|
|||
|
|
"finished": "none",
|
|||
|
|
"progress": {"cnt": 2, "of": 5}
|
|||
|
|
},
|
|||
|
|
"code": 200,
|
|||
|
|
"details": ["Starting download"]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 8.2 四步标准流程
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 定义变量,方便重复使用
|
|||
|
|
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 带进度的上报
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 进度: 第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)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
curl -u admin:admin -X DELETE \
|
|||
|
|
"http://192.168.77.70:8080/rest/v1/targets/test-curl-001/actions/15"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 9.2 设备端处理取消
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# ① 轮询拿到 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 开启确认流程(服务端)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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 分配时要求确认
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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 设备端自动确认
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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 基本信息
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
curl -u admin:admin \
|
|||
|
|
"http://192.168.77.70:8080/rest/v1/targets/test-curl-001"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 11.2 查询 target 所有 action
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
curl -u admin:admin \
|
|||
|
|
"http://192.168.77.70:8080/rest/v1/targets/test-curl-001/actions"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 11.3 查询指定 action 详情
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
curl -u admin:admin \
|
|||
|
|
"http://192.168.77.70:8080/rest/v1/targets/test-curl-001/actions/15"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 11.4 查询 action 状态历史
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
curl -u admin:admin \
|
|||
|
|
"http://192.168.77.70:8080/rest/v1/targets/test-curl-001/actions/15/status"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**响应示例(完成全流程后)**:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"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 属性
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
curl -u admin:admin \
|
|||
|
|
"http://192.168.77.70:8080/rest/v1/targets/test-curl-001/attributes"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 11.6 查询所有 target
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
curl -u admin:admin \
|
|||
|
|
"http://192.168.77.70:8080/rest/v1/targets"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 11.7 查询所有 Distribution Set
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
curl -u admin:admin \
|
|||
|
|
"http://192.168.77.70:8080/rest/v1/distributionsets"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 12. 完整流程速查
|
|||
|
|
|
|||
|
|
### 12.1 一次完整的 OTA 生命周期(复制粘贴即用)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# ═══ 变量设置 ═══
|
|||
|
|
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 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 |
|