# PRD ① 设备端(rk3588-agent + media-server)远程管理能力(V1) ## 1. 背景 当前 `media-server` 已提供 HTTP 控制台与配置热更新能力(`/api/*`、`/api/config/reload`、`/api/config/rollback` 等)。由于 **大文件模型上传** 在现有 C++ 自研 HTTP Server 上实现成本较高(需要流式接收/写盘/校验/限流),本期采用更工程化的拆分: - `media-server`:继续专注业务图(推理/推流/报警)与热更新。 - `rk3588-agent`(Go 新增常驻进程):对外提供局域网管理面能力:UDP 发现、模型/配置上传落盘、触发 `media-server` reload/rollback、代理读取 graphs/logs。 > 本 PRD 覆盖“轻量热更新/重载/回滚(业务图级)”。systemd/重启系统等运维级操作可作为后续扩展,但不作为 V1 验收项。 ## 2. 目标 1. 管理端可通过 UDP 广播在 1 秒内发现同网段 10 台设备(由 `rk3588-agent` 响应)。 2. 管理端可通过 `rk3588-agent` 上传配置 JSON,设备端原子写入后触发 `media-server` reload 生效。 3. 管理端可通过 `rk3588-agent` 上传模型文件到设备固定目录,并返回可直接在配置中引用的 `model_path`。 4. 所有对外写操作必须鉴权(Token),读操作默认可不鉴权(可配置)。 ## 3. 非目标(V1 不做) - systemd start/stop/restart `media-server`(可在 agent 后续扩展) - 设备重启/固件升级/插件升级 - 跨网段发现(保留后端可做网段扫描 fallback) - 完整 RBAC/用户体系 ## 4. 现状可复用能力(不修改语义) - HTTP Server:`src/http_server.cpp` - Graph/热更新:`GraphManager::ReloadFromFile`、`GraphManager::RollbackFromLastGood` - 配置 Expand + Validate:`utils/config_expand.*`、`utils/config_schema.h` - 运行状态:`GET /api/graphs`、`GET /api/graphs/{name}`、`GET /api/logs/recent` ## 5. 新增功能范围(V1) ### 5.1 新增进程:rk3588-agent(Go) `rk3588-agent` 作为常驻服务,提供: - UDP 广播发现(Option A):对管理端 Search 做响应。 - HTTP 管理 API(对外):模型上传、配置下发、触发 reload/rollback、代理 graphs/logs。 - 本地调用 `media-server`:通过 `http://127.0.0.1:/api/...` 触发 reload/rollback/读取 graphs/logs。 #### 5.1.1 agent 代码目录结构(建议,开发可直接照此建工程) 建议以 Go module 形式独立工程(可放在同仓库 `agent/` 目录,也可独立仓库)。 ```text agent/ go.mod cmd/ rk3588-agent/ main.go internal/ config/ # 读取/校验 /etc/rk3588-agent/config.json discovery/ # UDP 35688 discover responder httpapi/ # 对外 HTTP 路由:/v1/* + auth mediaserver/ # 对内 HTTP client:调用 127.0.0.1:9000/api/* modelstore/ # 模型落盘/sha256/manifest files/ # 原子写盘(tmp+rename)、权限校验 sysinfo/ # hostname/ip/uptime/device_id log/ # 统一日志封装(stdout/journald) ``` ### 5.2 media-server 变更范围(V1) V1 目标是将大文件上传从 `media-server` 移出,因此 **media-server 可不新增大文件上传接口**。仅要求: - 保持现有 `/api/config/reload`、`/api/config/rollback`、`/api/graphs`、`/api/logs/recent` 等接口可用。 - (可选安全加固,非 V1 必须)限制 `media-server` HTTP 仅监听 `127.0.0.1` 或对写接口增加 Token 鉴权。 ## 6. 配置与落盘约定 ### 6.1 新增 agent 配置项(建议) agent 需要独立配置(例如 `/etc/rk3588-agent/config.json`)。建议: ```json { "agent": { "listen": "0.0.0.0:9100", "token": "CHANGE_ME", "require_token_for_read": false, "discovery_enable": true, "discovery_port": 35688, "device_name": "rk3588-cam-01", "device_id_path": "/var/lib/rk3588-agent/device_id", "models_dir": "/opt/rk3588sys/models", "max_upload_mb": 200, "config_path": "/etc/rk3588sys/config.json", "media_server_base_url": "http://127.0.0.1:9000", "media_server_timeout_ms": 3000, "media_server_retry": { "max_attempts": 3, "backoff_ms": [200, 500] } } } ``` 字段说明(V1 关键字段): - `config_path`:agent 写入配置文件的目标路径(与 media-server `--config` 一致)。 - `device_id_path`:device_id 持久化文件路径(不存在则自动生成并写入)。 - `media_server_base_url`:agent 调用 media-server 的本机地址,建议固定 `127.0.0.1`。 - `media_server_timeout_ms`:agent 调用 media-server 的 HTTP 总超时。 - `media_server_retry`:仅对“控制类请求”(reload/rollback)启用的重试策略。 ### 6.2 设备侧文件系统布局(部署约定) 为保证权限与可维护性,约定如下路径: - 可执行文件: - `/opt/rk3588sys/bin/media-server` - `/opt/rk3588sys/agent/rk3588-agent` - 配置文件: - `/etc/rk3588sys/config.json`(media-server `--config` 指向) - `/etc/rk3588-agent/config.json` - 状态/持久化: - `/var/lib/rk3588-agent/device_id` - 模型仓库: - `/opt/rk3588sys/models/manifest.json` - `/opt/rk3588sys/models/files/*.rknn` > 说明:如不希望以 root 运行,可将 `config_path` 改到 `/opt/rk3588sys/config/config.json` 并给 agent 用户写权限;V1 为减少权限复杂度,建议 agent 以 root 运行。 ### 6.3 systemd service(部署字段,开发/运维可直接照抄) #### 6.3.1 rk3588-agent.service 路径建议:`/etc/systemd/system/rk3588-agent.service` ```ini [Unit] Description=RK3588Sys Agent After=network-online.target Wants=network-online.target [Service] Type=simple User=root ExecStart=/opt/rk3588sys/agent/rk3588-agent --config /etc/rk3588-agent/config.json Restart=always RestartSec=2 WorkingDirectory=/ LimitNOFILE=65535 # 可选:基础加固(需要确认路径) NoNewPrivileges=true PrivateTmp=true ProtectHome=true ProtectSystem=full ReadWritePaths=/etc/rk3588sys /etc/rk3588-agent /opt/rk3588sys/models /var/lib/rk3588-agent [Install] WantedBy=multi-user.target ``` #### 6.3.2 media-server.service(建议统一纳入部署约定) 路径建议:`/etc/systemd/system/media-server.service` ```ini [Unit] Description=RK3588Sys Media Server After=network-online.target Wants=network-online.target [Service] Type=simple User=root ExecStart=/opt/rk3588sys/bin/media-server --config /etc/rk3588sys/config.json Restart=always RestartSec=2 LimitNOFILE=65535 # (可选)性能调参:多路推理并发 / RGA 并发 Environment=RK3588_RKNN_CTX_POOL_SIZE=3 Environment=RK3588_RGA_MAX_INFLIGHT=2 [Install] WantedBy=multi-user.target ``` > V1 不要求 agent 控制 systemd,但要求两服务可开机自启。 ### 6.5 性能调参说明(新增) - `RK3588_RKNN_CTX_POOL_SIZE`:同一模型的 RKNN context 池大小(默认 3)。 - `RK3588_RGA_MAX_INFLIGHT`:RGA 全局并发上限(默认 2)。 ### 6.4 模型目录结构 - `${models_dir}/manifest.json` - `${models_dir}/files/__.`(`ext` 默认 `rknn`,白名单控制) ## 7. 约束与安全 - agent 对外写接口必须 `X-RK-Token`。 - 上传限制:必须 `Content-Length`;大小不得超过 `max_upload_mb`。 - agent 写盘采用原子写(临时文件 + rename)。 - agent 与 `media-server` 的本地通信固定走 `127.0.0.1`(避免暴露内部控制面)。 ### 7.1 agent 内部调用 media-server 的 URL/超时/重试策略 agent 只调用 media-server 的既有接口(对内 base URL = `media_server_base_url`): - Reload:`POST {base}/api/config/reload` - Rollback:`POST {base}/api/config/rollback` - Graphs:`GET {base}/api/graphs` - Graph detail:`GET {base}/api/graphs/{name}` - Logs:`GET {base}/api/logs/recent?limit=...` 超时策略(建议默认值): - 读接口(graphs/logs):总超时 `1000ms`(不重试) - 控制接口(reload/rollback):总超时 `media_server_timeout_ms`(默认 `3000ms`),允许重试 重试策略(仅控制接口): - `max_attempts = 3`(首次 + 2 次重试) - 触发条件:连接失败/超时/5xx(不对 4xx 重试) - backoff:`[200ms, 500ms]` 配置下发联动策略(`PUT /v1/config`): 1) agent 原子写入 `config_path` 2) 调用 reload(按控制接口重试策略) 3) 若 reload 最终失败:调用 rollback(按控制接口重试策略) 4) 返回 500,错误消息包含 reload 与 rollback 的结果(便于定位) ### 7.2 启动顺序与可用性 - 建议 systemd 启动顺序:两者都 After network-online。 - agent 对外可先起来;当 media-server 尚未启动时: - `/v1/graphs`、`/v1/logs/recent` 返回 500(error=connect refused/timeout) - `/v1/config` 返回 500(写盘可成功,但 reload 失败会触发 rollback;错误信息提示 media-server 不可用) ## 8. 验收标准(Acceptance Criteria) 1. 同网段 10 台设备,管理端 Search(UDP broadcast)在 1 秒内都能发现;列表包含 `device_id/ip/agent_port/media_port/version/git_sha`。 2. agent `PUT /v1/config`: - 发送合法 config,设备写盘并触发 `media-server` reload 成功,graphs 状态正常。 - 发送非法 config,agent 返回 400;或 reload 失败则 agent 自动 rollback 并返回 500(错误信息可定位)。 3. agent `PUT /v1/models/{name}`:上传成功返回 sha256/path;在配置中引用该 path 并 reload 后,相关节点能正常 Init(以日志/metrics 验证)。 4. 无 token 调用写接口返回 401;错误返回 JSON:`{"error":"..."}`。 ## 9. 开发任务拆分(建议) - [ ] 新增 `rk3588-agent`:HTTP 服务 + Token 鉴权 + 日志 - [ ] UDP discovery:协议解析/回复、device_id 获取与持久化、停止逻辑 - [ ] `GET /v1/info`:聚合 device/version/git_sha/ports/uptime - [ ] `PUT /v1/config`:原子写盘 + 触发 `media-server` reload;失败自动 rollback - [ ] `PUT /v1/models/{name}`:流式落盘 + sha256 + manifest 写入 - [ ] `GET /v1/models`:读取 manifest - [ ] 代理接口:graphs、graph detail、logs recent、reload、rollback - [ ] 统一错误码与日志(见接口清单表)