跳到主要内容

www-server 后端网关

定位

www-server 是 WebUI 面向浏览器的后端边界,负责 HTTP API、WebSocket 实时通道和静态资源托管。它不直接承载时间线存储、MQTT 路由、插件运行等核心业务逻辑,而是复用已有子模块的稳定接口。

第一阶段目标:

  1. 为 WebUI 提供统一 HTTP API;
  2. 将时间线事件查询接到 Genapsed 分配的 Timeline MySQL 只读连接;
  3. 接入 MQTT 桥接,把组件状态、事件、日志和命令与浏览器 API 隔离;
  4. 为浏览器提供 WebSocket 实时事件广播;
  5. 托管 web-ui/dist 静态产物;
  6. 保持实现轻量,暂不引入额外 Web 框架依赖。

架构边界

Browser / WebUI
-> www-server HTTP API / WebSocket
-> Timeline MySQL read connection
-> Runtime State in-memory browser bridge cache
-> Genapsed JSONL logs
-> MQTT Bridge -> MQTT Broker / Genapsed 路由

约束:

  • WebUI 不直接连接 MQTT Broker;
  • WebUI 不直接读取数据库或文件系统;
  • MySQL 承载正式记录、配置、时间线和可查询数据,初始化和权限由 Genapsed 负责;
  • MQTT 承载事件、命令、ACK、结果和组件状态心跳;
  • WebSocket 只面向浏览器推送后端桥接后的实时变化;
  • www-server 不重新定义时间线事件模型;
  • 大文件仍通过 HTTP 数据面提供引用和授权访问,不能放进 MQTT 或 WebSocket 消息体;
  • 错误应直接暴露为明确 JSON 错误,不使用 fallback 掩盖问题。

初版接口

方法路径说明
GET/api/health服务健康检查
GET/api/status健康检查别名
GET/api/build-info返回 WebUI 构建信息、Git 提交和开发模式状态
GET/api/components读取管理控制台组件清单、状态、字段元数据和当前配置
GET/api/components/{component_id}/config读取单个组件配置和运行状态
POST/api/components/{component_id}/config提交配置变更请求,由 Genapsed 校验、保存并触发重载
GET/api/timeline/events查询时间线事件列表
GET/api/timeline/events/{event_id}获取单个时间线事件
POST/api/timeline/events向 Genapsed 发送 MiniVLM 风格时间线事件入库请求
GET/api/logs查询 JSONL 运行日志
GET/api/mqtt/bridge查询 MQTT 桥接状态
GET/api/mqtt/messages查询最近 MQTT 入站消息
POST/api/components/{component_id}/command发布组件 MQTT 命令
POST/api/dev/mqtt/publish原始 MQTT 发布入口已关闭,避免绕过 Genapsed 权限
GET/api/wsWebSocket 实时通道

时间线查询参数

GET /api/timeline/events 支持:

  • startend:Unix 时间戳;
  • camera_idevent_type
  • subject / subjects
  • object / objects
  • action / actions
  • attention_required
  • keyword
  • limitoffset
  • order=desc|asc

时间线写入

POST /api/timeline/events 可以直接接收 MiniVLM timeline_event_generated payload,也可以接收 Genapsed 风格信封:

{
"msg_id": "message-id",
"priority": "normal",
"metadata": {
"trace_id": "trace-id"
},
"payload": {
"event_id": "evt-001",
"camera_id": "living_room",
"time_range": {
"start": 1741000000,
"end": 1741000030
},
"summary": "有人把快递盒放在门口。",
"event_type": "object_moved"
}
}

请求成功只表示 MQTT 入库请求已发送。Genapsed 完成入库后发布 timeline_event_stored result, 服务再向 /api/ws 广播 timeline.event_created

MQTT 桥接

后端桥接默认订阅:

  • everpast/+/status/+:组件状态心跳,写入进程内桥接缓存,并广播 component.status_updated
  • everpast/+/event/+:事件消息只记录和广播,时间线入库由 Genapsed 处理;
  • everpast/+/log/+:组件日志实时通知,校验并广播到 WebSocket,不替组件重复落盘;
  • everpast/+/ack/+everpast/+/result/+:记录到进程内桥接缓存,并转发给浏览器调试面板;
  • timeline_event_stored result:广播 timeline.event_created

UI 发出的管理配置变更会发布到:

everpast/www_server/config/normal/genapsed

UI 发出的组件命令会发布到:

everpast/www_server/cmd/<priority>/genapsed

配置变更由 Genapsed 校验权限、写入配置数据库、渲染目标组件配置文件并发布 reload_config。 组件命令也先提交给 Genapsed,由 Genapsed 校验后以自己的身份向目标组件发布标准命令。 配置读取使用 Genapsed 分配给 www_server 的 MySQL 只读连接,默认从 data/genapsed/database/credentials.jsonsystem.www_server.sqlalchemy_url 读取,也可通过 EVERPAST_WWW_CONFIG_DATABASE_URL 覆盖。如果配置主库不可用,配置 API 会返回 config_database_unconfiguredconfig_database_unavailable,不会回退到本地默认配置。 www-server 这个仓库名含连字符,MQTT topic 中使用 www_server 作为后端网关组件 ID。 www-server 自身运行数据默认写入主仓库 data/www_server/,日志默认按天写入 data/logs/www_server/YYYY-MM-DD.jsonl。日志查询递归读取 data/logs,该根目录可通过 Genapsed 管理的组件配置或 EVERPAST_WWW_LOG_PATH 覆盖。

管理配置接口

当前代码内置以下管理组件定义,用于 WebUI 生成配置表单并展示运行状态:

组件 ID名称当前状态
www_server后端网关已接入管理控制台
web-uiWeb UI已接入管理控制台
timeline时间线存储已接入管理控制台,数据库类型只支持 mysql
genapsedGenapsed 中枢已接入管理控制台
mqttMQTT Broker已接入管理控制台,并驱动后端 MQTT 桥接配置
minivlmMiniVLM已接入管理控制台,开发模式默认启用 worker
nvr_bridgeNVR-Bridge已接入管理控制台,开发模式默认启用 Frigate worker
frigateFrigate NVR已接入管理控制台;开发模式默认由 Genapsed 渲染配置并启动容器
plugins插件系统已接入管理控制台

POST /api/components/{component_id}/config 不直接写本地配置文件,也不直接修改目标组件。 它会先在 www-server 内完成字段归一化和基础校验,再通过 MQTT 发布 request_config_updateeverpast/www_server/config/normal/genapsed。Genapsed 负责最终权限校验、 写入配置主库、渲染目标组件配置文件,并发布 reload_config

WebUI 配置表单由 /api/components 返回的字段元数据动态渲染。当前已支持 textpasswordnumberbooleanselectarrayobject 类型;数组和对象字段在前端以 JSON 文本编辑, 提交前解析为结构化值,后端再按字段类型做基础校验。

后续路线

  1. 接入 Genapsed 管理服务,开放插件、权限和完整生命周期接口;
  2. 增加媒体文件授权访问接口;
  3. 为 MQTT 命令增加 ACK 关联、超时重试和失败审计;
  4. 引入认证和局域网设备首次配置流程;
  5. 接入 Genapsed 分配的 MySQL 连接和数据库权限审计展示。

反向代理(Unified API Gateway)

www-server 内置反向代理能力,作为后端服务(如 Frigate NVR)的统一入口。这样鉴权、日志等横切关注点只需在网关层实现。

配置方式

通过环境变量 EVERPAST_WWW_PROXY_ROUTES 注入 JSON 路由配置:

[
{
"prefix": "/nvr",
"upstream": "http://127.0.0.1:5000",
"strip_prefix": true
}
]
  • prefix — 匹配的 URL 路径前缀,如 /nvr
  • upstream — 上游服务基础 URL
  • strip_prefix — 转发时是否去除 prefix(true/nvr/api/stats 转发为 /api/stats

静态资源路径重写

Frigate NVR 的 Web 前端使用绝对路径引用静态资源(如 <script src="/assets/main-xxx.js">)。当通过反向代理的子路径(如 /nvr/)访问时,浏览器会将这些路径解析为 http://host:8080/assets/xxx,导致 404。

www-server 在代理 HTML 响应时自动将 /assets/ 重写为路径前缀形式(如 /nvr/assets/),使得静态资源请求重新经过反向代理到达上游服务。同时重写 Frigate 的 window.baseUrl 以修正 API 调用路径。

实现模块

文件职责
proxy.pyProxyRouteReverseProxyConfig(路由匹配与解析)、ReverseProxy(aiohttp 异步请求转发)
config.pyEVERPAST_WWW_PROXY_ROUTES 环境变量解析配置
server.pycreate_app() 中优先注册普通路由,再动态注册代理路由