164 lines
7.1 KiB
Markdown
164 lines
7.1 KiB
Markdown
# Device Pod 设备目标能力模型
|
||
|
||
本文是 HWLAB `device-pod` 的长期参考口径。`device-pod` 是一个以单副本 k8s Pod 运行的设备目标代理单元,用于把一个可开发、可下载、可复位、可观测 I/O 的设备目标封装成统一 REST/job API。对外稳定身份由 Service/Deployment 承载,不依赖实际 Pod name。
|
||
|
||
`device-pod` 不等同于裸物理设备,也不是泛化远程 shell。它是以下四个要素的运行时组合:
|
||
|
||
```text
|
||
device-pod
|
||
= deviceTarget
|
||
+ debugInterface
|
||
+ projectWorkspace
|
||
+ ioInterface
|
||
```
|
||
|
||
## 实施计划
|
||
|
||
长期模型以本文为准;分阶段实现计划单独维护,避免把一次性开发步骤写进长期参考:
|
||
|
||
- [Device Pod CLI MVP 计划](../plan/device-pod-cli-mvp.md):先做 code agent 可调用的独立 CLI,通过 profile、gateway 和用户 PC 侧 `device-host-cli` 跑通 workspace、debug-probe 和 io-probe 的最小闭环。
|
||
- [Device Pod Server MVP 计划](../plan/device-pod-server-mvp.md):在 CLI 跑通后再实现真正的 `device-pod-server`,提供与 CLI 对应的 RESTful API、后台监控缓存和前端最小可视化。
|
||
|
||
## Profile 注册与同步
|
||
|
||
MVP 不使用刚性的中心 profile 注册表。`device-pod` profile 的灵活源头是 HWLAB code agent workspace 下的 `.device-pod/` 目录,推荐按 `devicePodId` 存放 profile 文件,例如 `.device-pod/device-pod-71-freq.json`。
|
||
|
||
`device-pod-cli` 每次执行都从当前 code agent workspace 的 `.device-pod/` 读取 profile,并在输出中保留 `profilePath` 和 `profileHash`。进入 `device-pod-server` 阶段后,CLI 或 code agent 仍以 `.device-pod/` 为 profile source-of-truth;每次连接 server 前自动上传或刷新 profile,server 只把 active profile 当作运行时缓存,不把它变成长期配置真相。
|
||
|
||
profile 必须只描述 target、debugInterface、projectWorkspace、ioInterface、gateway route、host CLI 能力和受控路径边界;不得放入 Git key、云端 token、kubeconfig、数据库 URL 或其他长期 secret。profile 校验失败时应返回 `profile-invalid` 或 `profile-missing` blocker,而不是回退到默认设备或任意 shell。
|
||
|
||
## 四要素
|
||
|
||
### `deviceTarget`
|
||
|
||
`deviceTarget` 是被测设备目标本身,可以是一个 MCU 最小系统板、完整业务板卡、仪器模块或其他可被 HWLAB 操作的目标对象。它必须有稳定的 `targetId`,用于锁、trace、evidence 和用户界面归因。
|
||
|
||
### `debugInterface`
|
||
|
||
`debugInterface` 是设备的开发和调试接口,代表下载、烧录、复位、debug probe 状态等能力。典型物理实现包括 DAPLink、J-Link、ST-Link 或厂商下载器。
|
||
|
||
第一版路径固定为:
|
||
|
||
```text
|
||
device-pod -> cloud-api -> gateway -> cmd -> skill/downloader -> debug probe -> target
|
||
```
|
||
|
||
`debugInterface` 只暴露设备语义能力,例如 `debug.probe`、`debug.download`、`debug.reset`。不得把它退化成任意 shell 执行入口。
|
||
|
||
`debugInterface` 不承载源码编译、工程发现或工具链定义;这些属于
|
||
`projectWorkspace`。`debugInterface` 可以消费 `projectWorkspace` 产生的
|
||
artifact,例如 `.hex`、`.bin` 或 `.elf`,并负责把该 artifact 下载、校验、
|
||
复位或附着调试到 `deviceTarget`。
|
||
|
||
### `projectWorkspace`
|
||
|
||
`projectWorkspace` 是设备对应的源码、工程文件和编译工具链上下文,例如 Keil 工程、target 名称、构建脚本和 workspace root。它描述如何从源码生成可下载产物,也为 debug/download job 提供工程路径和工具链边界。
|
||
|
||
`projectWorkspace` 可以和 `debugInterface` 位于同一台用户 PC,也可以只通过 gateway 暴露受控 CLI。HWLAB 不直接读取 secret、kubeconfig、DB URL 或完整源码内容;探测必须有界。
|
||
|
||
工程源码的编译和工具链归属 `projectWorkspace`,包括:
|
||
|
||
- 源码根目录、工程文件和 target 名称;
|
||
- build profile、编译参数和工具链入口;
|
||
- build、clean、artifact list 等工程动作;
|
||
- `.hex`、`.bin`、`.elf` 等下载产物的位置和元数据。
|
||
|
||
因此 build 失败应归类为 workspace/toolchain blocker;download、reset 或
|
||
probe attach 失败才归类为 debug/probe/target blocker。
|
||
|
||
典型流程为:
|
||
|
||
```text
|
||
projectWorkspace.build
|
||
-> artifact
|
||
-> debugInterface.download
|
||
-> debugInterface.reset
|
||
-> ioInterface.status/sample/uart
|
||
```
|
||
|
||
### `ioInterface`
|
||
|
||
`ioInterface` 是设备的实时或近实时 I/O 观测与控制接口,代表 UART、AI、AO、DI、DO、状态采样、日志抓取等能力。典型实现包括 DAPLink 自带串口、独立串口工具、USB/WiFi/厂商协议上位机或 `device-host-cli`。
|
||
|
||
MVP 推荐路径为:
|
||
|
||
```text
|
||
device-pod -> cloud-api -> gateway -> cmd -> device-host-cli -> serial/WiFi/USB/vendor protocol -> target
|
||
```
|
||
|
||
这里 `cmd` 只作为启动受控 PC 侧 CLI 的 transport;串口、WiFi、厂商协议和硬件细节必须隔离在 `device-host-cli` 或等价上位机 CLI 后面。
|
||
|
||
## 接口拆分
|
||
|
||
`debugInterface` 和 `ioInterface` 必须在模型和 API 中拆开,即使它们由同一个物理探针提供。例如 DAPLink 可以同时提供 SWD/CMSIS-DAP 下载调试口和 UART 串口:
|
||
|
||
```text
|
||
DAPLink physical probe
|
||
-> debugInterface: SWD/CMSIS-DAP
|
||
-> ioInterface: UART
|
||
```
|
||
|
||
拆分原因:
|
||
|
||
- `debug.download`、`debug.reset` 是低频强副作用动作,通常需要 approval 和 target 互斥锁。
|
||
- `io.status.read`、`io.sample` 是短读或短窗口采样,关注 freshness、采样窗口和输出有界性。
|
||
- `io.write` 类能力属于硬件 I/O 控制,未来也需要 approval,但不能和下载/烧录混成同一类风险。
|
||
- trace、audit、evidence 必须能区分 `debug` 路径和 `io` 路径。
|
||
|
||
MVP 不拆成两个 k8s Pod;同一个 `device-pod` 内保留两个一等接口,共享 `deviceTarget`、`projectWorkspace`、锁、job 和 evidence 归因。
|
||
|
||
## 最小 REST 口径
|
||
|
||
同步 API 只用于短状态和短探测:
|
||
|
||
```text
|
||
GET /health
|
||
GET /v1/profile
|
||
GET /v1/status
|
||
GET /v1/capabilities
|
||
GET /v1/workspace/status
|
||
GET /v1/debug/status
|
||
GET /v1/io/status
|
||
```
|
||
|
||
异步 API 用于下载、复位、采样等动作;每个 HTTP 调用必须短,长耗时由 job 轮询表达:
|
||
|
||
```text
|
||
POST /v1/workspace/jobs
|
||
POST /v1/debug/jobs
|
||
POST /v1/io/jobs
|
||
GET /v1/jobs/{jobId}
|
||
GET /v1/jobs/{jobId}/output
|
||
POST /v1/jobs/{jobId}/cancel
|
||
```
|
||
|
||
第一版可接受的 intent 示例:
|
||
|
||
```text
|
||
workspace.detect
|
||
workspace.build
|
||
workspace.clean
|
||
workspace.artifact.list
|
||
debug.probe
|
||
debug.download
|
||
debug.reset
|
||
io.status.read
|
||
io.sample
|
||
io.uart.fetch
|
||
```
|
||
|
||
所有响应必须保留 `devicePodId`、`targetId`、`traceId`、`operationId`、`gatewaySessionId`、`interface`、`intent`、`route`、`status` 和 blocker/evidence 字段。真实控制动作不得用 `SOURCE`、`LOCAL`、`DRY-RUN` 或前端状态冒充 `DEV-LIVE`。
|
||
|
||
## 最小系统示例
|
||
|
||
一个 STM32F103 最小系统加 DAPLink 可以完整构成一个 `device-pod`:
|
||
|
||
```text
|
||
deviceTarget: STM32F103 最小系统
|
||
debugInterface: DAPLink SWD/CMSIS-DAP
|
||
projectWorkspace: STM32F103 源码、Keil 工程和编译工具链
|
||
ioInterface: DAPLink UART 串口
|
||
```
|
||
|
||
该模型后续可以扩展到更多 target 或更复杂 I/O probe,但每个 `device-pod` 仍只代表一个明确的设备目标能力单元。
|