更新readme

This commit is contained in:
tian 2026-04-14 09:39:28 +08:00
parent f309e2d576
commit 3efa303afd

327
Readme.md
View File

@ -1,64 +1,96 @@
# PRD ③ 管理端后端Go managerdV1
# managerd
## 1. 目标与运行方式
`managerd` 是 RK3588 管理端后端服务,负责设备发现、设备注册表维护、代理访问设备端 `rk3588-agent`,并提供内嵌 Web UI、OpenAPI 页面和 HTTP API。
- 提供本机 HTTP API 给 React UI 使用。
- 负责 UDP 广播发现Option A维护设备缓存与在线状态。
- 通过设备端 `rk3588-agent` 完成配置/模型等运维操作,并可通过 agent 代理读取 graphs/logs。
- 支持批量任务(并发、进度、失败原因)并通过 SSE 推送。
## 当前状态
运行:单可执行 `managerd`,默认监听 `127.0.0.1:18080`(可配置)。
- 提供 HTTP API供前端或其他本地工具调用。
- 内嵌 Web UI启动后可直接在浏览器访问。
- 支持 UDP 广播发现设备,并维护内存中的设备在线状态。
- 支持代理访问设备端 agent 的常用接口,以及 `/v1/*` 通用透传。
- 支持批量任务执行,并通过 SSE 推送逐设备状态。
- 模板从本地 `templates/*.json` 读取。
## 2. 外部依赖与约束
## 运行方式
- Go 版本:>= 1.22(建议)
- 标准库优先Web 框架可选 `chi`/`gin`(建议 chi + net/http
- 不需要数据库V1 用内存 + 可选本地 JSON 持久化)。
默认通过单个可执行文件运行:
## 3. 模块划分
```bash
managerd
```
### 3.1 Discovery
也可以指定配置文件路径:
- 向所有可用网卡的广播地址发送 UDP discover。
- 监听本地 UDP socket 收集 replies时间窗默认 1200ms
- 去重规则:按 `device_id` 去重,以最新 reply 为准。
```bash
managerd path/to/managerd.json
```
### 3.2 Device Registry
程序启动后:
- 内存缓存:
- `device_id -> {ip, agent_port, media_port, device_name, version, git_sha, last_seen_ms, online}`
- 定时刷新(可配置间隔):对 online 设备拉取 `GET /v1/graphs`agent 代理),更新摘要。
- Offline 规则:超过 `offline_after_ms`(如 10000ms未见到则标记离线。
- `GET /` 会重定向到 `/ui`
- `GET /ui` 为内嵌管理页面
- `GET /openapi.json` 返回 OpenAPI 描述
- `GET /health` 返回健康检查结果
### 3.3 Device Client
当前仓库中的示例配置监听地址为 `0.0.0.0:18080`
- 统一超时connect 1s、overall 3s可配置
- 统一错误包装:返回 `error_code + message + device_id`
- Token
- 全局默认 tokenV1
- 可预留 per-device tokenP1
## 依赖
### 3.4 Templates/Config Builder
- Go `1.23.3`
- `github.com/go-chi/chi/v5`
- `github.com/go-chi/cors`
- `github.com/google/uuid`
- 模板库来源:
- V1managerd 内置embed或本地 `templates/` 目录读取
- 返回前端表单 schemaV1 允许手工维护(避免解析占位符带来的不确定性)。
- 生成 root config基于模板与 params产出 `{global,templates,instances}`
## 主要模块
### 3.5 Task Runner
### Discovery
- 任务类型:
- `config_apply`(对 N 台设备下发 config
- 向所有可用广播网卡发送 UDP discover 请求
- 在本地临时 UDP 端口监听回复
- 按 `device_id` 去重,并使用最新回复更新注册表
### Device Registry
- 以内存维护设备列表
- 每 2 秒执行一次离线判定
- 超过 `offline_after_ms` 未更新则标记为离线
- 每 30 秒对在线设备拉取一次 `GET /v1/graphs`,更新 `graphs` 字段
- 除 UDP 发现外,成功代理调用设备接口时也会刷新设备 `last_seen_ms`
### Agent Client
- 默认 HTTP 请求超时为 3 秒
- 对配置下发、模型上传、`/v1/config/ui/*`、人脸库上传等长操作使用 120 秒超时
- 自动附带全局 `X-RK-Token`
### Template Service
- 从本地 `templates/` 目录加载 `.json` 模板
- 返回模板列表和单个模板详情
- 当前没有实现 embed 模板加载
### Task Runner
- 支持并发执行,默认并发数为 `concurrency`
- 支持 SSE 推送逐设备状态
- 当前支持的任务类型:
- `config_apply`
- `reload`
- `rollback`
- `model_upload`V1 可先做单设备;批量后续)
- 并发控制:默认 5可配置
- 状态:`pending/running/success/failed`(逐设备与整体)。
- 推送SSE `GET /api/tasks/:id/events`
- `media_start`
- `media_restart`
- `media_stop`
## 4. managerd 对前端 API 规格V1
## API 概览
### 4.1 Discovery
### 基础接口
- `GET /health`
- `GET /openapi.json`
- `GET /` -> 302 跳转到 `/ui`
- `GET /ui`
### Discovery
#### `POST /api/discovery/search`
@ -71,62 +103,123 @@ Request:
Response:
```json
{ "items": [ {"device_id":"...","ip":"...","agent_port":9100,"media_port":9000,"device_name":"...","version":"...","git_sha":"..."} ] }
{
"items": [
{
"device_id": "...",
"hostname": "...",
"ip": "...",
"agent_port": 9100,
"media_port": 9000,
"device_name": "...",
"version": "...",
"git_sha": "...",
"uptime_sec": 0,
"last_seen_ms": 0,
"online": true
}
]
}
```
### 4.2 Devices
### Devices
#### `GET /api/devices`
Response:
返回当前注册表中的设备列表:
```json
{ "items": [ {"device_id":"...","online":true,"last_seen_ms":0,"ip":"...","agent_port":9100,"media_port":9000,"device_name":"...","version":"...","git_sha":"...","graphs":[...]} ] }
{
"items": [
{
"device_id": "...",
"hostname": "...",
"ip": "...",
"agent_port": 9100,
"media_port": 9000,
"device_name": "...",
"version": "...",
"git_sha": "...",
"uptime_sec": 0,
"last_seen_ms": 0,
"online": true,
"graphs": {}
}
]
}
```
#### `GET /api/devices/:id`
#### `POST /api/devices`
Response包含 `info`、`graphs_summary`、`last_seen`。
### 4.3 Device actions代理调用
以下全部通过 agent
- `POST /api/devices/:id/reload` → agent `POST /v1/media-server/reload`
- `POST /api/devices/:id/rollback` → agent `POST /v1/media-server/rollback`
- `GET /api/devices/:id/graphs` → agent `GET /v1/graphs`
- `GET /api/devices/:id/graphs/:name` → agent `GET /v1/graphs/{name}`
- `GET /api/devices/:id/logs?limit=200` → agent `GET /v1/logs/recent?limit=200`
### 4.4 Config apply
#### `POST /api/devices/:id/config/apply`
Request:
手工添加一个设备到注册表:
```json
{ "config": { } }
{
"device_id": "demo-device",
"device_name": "Demo",
"ip": "192.168.1.10",
"agent_port": 9100,
"media_port": 9000
}
```
Behavior调用 agent `PUT /v1/config`
#### `GET /api/devices/{id}`
### 4.5 Model upload
直接返回该设备对象。
#### `POST /api/devices/:id/models/upload`
### 设备代理接口
Request`multipart/form-data`,字段
以下接口由 managerd 转发到设备端 agent
- `name`: string
- `file`: binary
- `GET /api/devices/{id}/info` -> `GET /v1/info`
- `POST /api/devices/{id}/reload` -> `POST /v1/media-server/reload`
- `POST /api/devices/{id}/rollback` -> `POST /v1/media-server/rollback`
- `GET /api/devices/{id}/graphs` -> `GET /v1/graphs`
- `GET /api/devices/{id}/graphs/{name}` -> `GET /v1/graphs/{name}`
- `GET /api/devices/{id}/logs?limit=200` -> `GET /v1/logs/recent?limit=200`
- `POST /api/devices/{id}/config/apply` -> `PUT /v1/config`
- `GET /api/devices/{id}/models` -> `GET /v1/models`
- `POST /api/devices/{id}/media-server/start` -> `POST /v1/media-server/start`
- `POST /api/devices/{id}/media-server/restart` -> `POST /v1/media-server/restart`
- `POST /api/devices/{id}/media-server/stop` -> `POST /v1/media-server/stop`
- `GET /api/devices/{id}/media-server/status` -> `GET /v1/media-server/status`
Behavior读取文件流转发为 agent `PUT /v1/models/{name}`raw body
#### 通用透传
### 4.6 Templates
- `ANY /api/devices/{id}/v1/*`
该路由会将 `/api/devices/{id}` 之后的路径原样透传到设备端 agent可用于
- `/v1/config`
- `/v1/config/ui/schema`
- `/v1/config/ui/state`
- `/v1/config/ui/plan`
- `/v1/config/ui/apply`
- `/v1/face-gallery`
- `/v1/face-gallery/reload`
- 以及其他已存在的 `/v1/*` 接口
### 模型上传
#### `POST /api/devices/{id}/models/upload`
请求类型:`multipart/form-data`
字段:
- `name`: 模型名
- `file`: 二进制文件
行为managerd 读取上传文件,并转发为设备端 agent 的 `PUT /v1/models/{name}`
### Templates
- `GET /api/templates`
- `GET /api/templates/:name`
- `GET /api/templates/{name}`
### 4.7 Tasks
当前模板数据来自本地 `templates/*.json`
### Tasks
#### `POST /api/tasks`
@ -135,51 +228,48 @@ Request:
```json
{
"type": "config_apply",
"device_ids": ["..."],
"payload": { "config": {} }
"device_ids": ["device-a", "device-b"],
"payload": {
"config": {}
}
}
```
说明:
- `config_apply` 会将 payload 作为配置内容下发到 `/v1/config`
- `media_start``media_restart` 可选接收 `{"config":"xxx"}` 形式的 payload
Response:
```json
{ "task_id": "..." }
```
#### `GET /api/tasks/:id/events` (SSE)
#### `GET /api/tasks`
Event `device_update` data:
返回当前内存中的任务列表。
```json
{ "device_id":"...","status":"running|success|failed","progress":0.0,"error":"" }
```
#### `GET /api/tasks/{id}/events`
## 5. 错误处理规范managerd → 前端)
- 成功2xx + `{"ok":true}` 或正常业务 JSON
- 失败4xx/5xx +
```json
{ "error": { "code": "...", "message": "...", "device_id": "...", "detail": "..." } }
```
建议错误码:
- `DISCOVERY_FAILED`
- `DEVICE_NOT_FOUND`
- `DEVICE_OFFLINE`
- `DEVICE_HTTP_ERROR`
- `DEVICE_TIMEOUT`
- `TASK_NOT_FOUND`
- `VALIDATION_ERROR`
## 6. 配置文件managerd建议
`managerd.json`
SSE 事件名为 `device_update`,数据格式:
```json
{
"listen": "127.0.0.1:18080",
"device_id": "...",
"status": "running",
"progress": 0.0,
"error": ""
}
```
## 配置文件
`managerd.json` 示例:
```json
{
"listen": "0.0.0.0:18080",
"discovery_port": 35688,
"discovery_timeout_ms": 1200,
"offline_after_ms": 10000,
@ -188,9 +278,28 @@ Event `device_update` data:
}
```
## 7. 验收标准
字段说明:
1. Search 可发现设备并更新 registry离线判断正确。
2. 可通过 agent 读取 graphs/logs`GET /v1/graphs`、`GET /v1/logs/recent`)。
3. 单设备 `config/apply`、`reload`、`rollback` 可用,错误可定位。
4. 批量 `config_apply` 任务可并发执行并通过 SSE 输出逐台结果。
- `listen`: managerd 监听地址
- `discovery_port`: 设备发现广播端口
- `discovery_timeout_ms`: 搜索超时
- `offline_after_ms`: 多久未更新则视为离线
- `agent_token`: 转发到设备端 agent 的统一 token
- `concurrency`: 批量任务并发数
## 目录说明
- `cmd/managerd`: 程序入口
- `internal/api`: API 路由与处理器
- `internal/service`: discovery、registry、task、template、agent client
- `internal/web`: 内嵌 Web UI
- `templates`: 本地模板
- `scripts/deploy`: 部署脚本
## 验证现状
当前仓库已通过:
```bash
go test ./...
```