M5-T13: document Modbus/Energy/MQTT, mark M5 done, finalize OpenAPI
This commit is contained in:
@@ -12,8 +12,11 @@
|
||||
- SMTP 配置、测试发信与 public IPv4 changed 邮件通知
|
||||
- location recorder
|
||||
- poo recorder
|
||||
- Home Assistant inbound / outbound integration
|
||||
- Home Assistant inbound / outbound integration(REST 通道)
|
||||
- TickTick OAuth 与 action task 集成
|
||||
- **Modbus 设备采集**:通过 YAML profile(首个:SDM120 电表)按设备周期轮询 Modbus-TCP 网关,解码工程量并落通用读数表(`modbus_device` + `modbus_reading`)
|
||||
- **MQTT + Home Assistant Discovery**:以可勾选方式把 Modbus 设备/工程量注册为 HA device/entity(含 binary_sensor online),state 周期发布;配置变更可重连重发
|
||||
- **前端侧边栏 + Energy 视图**:侧边导航替换顶栏;Energy 页管理 Modbus 设备、展示最新读数与 Recharts 走势图;Config 页 Accordion 分区展开;Expose 设置勾选 HA 可暴露实体
|
||||
- pytest 测试与 OpenAPI 导出脚本
|
||||
- Docker / Compose 部署入口
|
||||
|
||||
@@ -30,6 +33,9 @@
|
||||
- public IPv4 当前状态与变化历史
|
||||
- location 记录(`location` 表)
|
||||
- poo 记录(`poo_records` 表)
|
||||
- Modbus 设备定义(`modbus_device` 表)
|
||||
- Modbus 通用读数(`modbus_reading` 表,JSON payload)
|
||||
- HA 实体暴露开关(`exposed_entity_toggle` 表)
|
||||
|
||||
配置层只保留一个数据库环境变量:
|
||||
|
||||
@@ -41,7 +47,7 @@
|
||||
python -m scripts.run_migrations
|
||||
```
|
||||
|
||||
该命令会通过 Alembic 将 `app.db` 初始化或升级到最新 head(含 `location` / `poo_records` 表)。
|
||||
该命令会通过 Alembic 将 `app.db` 初始化或升级到最新 head(含全部表,包括 M5 新增的 `modbus_device`、`modbus_reading`、`exposed_entity_toggle`)。
|
||||
|
||||
## 当前目录
|
||||
|
||||
@@ -49,7 +55,7 @@ python -m scripts.run_migrations
|
||||
|
||||
- `app/`: FastAPI 应用代码(包含 JSON API、业务服务、数据模型)
|
||||
- `frontend/`: React SPA 前端(Vite + React + TypeScript + Mantine)
|
||||
- `alembic_app/`: App DB 的 Alembic migration 环境(同时管理 `location` / `poo_records` 表)
|
||||
- `alembic_app/`: App DB 的 Alembic migration 环境(管理所有表,含 M5 新增的 `modbus_device`、`modbus_reading`、`exposed_entity_toggle`)
|
||||
- `tests/`: pytest 测试
|
||||
- `docs/`: 当前系统说明文档
|
||||
- `scripts/`: 辅助脚本,例如 OpenAPI 导出
|
||||
@@ -128,6 +134,7 @@ M2 用 React SPA 取代了原有 Jinja 服务端模板,由 FastAPI 同源托
|
||||
- **Vite + React + TypeScript + Mantine**(组件库)
|
||||
- **TanStack Query**(数据请求/缓存)
|
||||
- **Leaflet / react-leaflet**(地图与热力图)
|
||||
- **Recharts**(Energy 视图走势图,M5 引入)
|
||||
- **openapi-typescript + openapi-fetch**(类型化 API client,由 `openapi/openapi.json` 生成)
|
||||
|
||||
### 本地开发(前端)
|
||||
@@ -177,7 +184,7 @@ npm run build # 构建,确认产出 dist
|
||||
- App DB:`sqlite:///./data/app.db`
|
||||
- 数据目录:`./data/`
|
||||
|
||||
所有模型(auth / config / public_ip / location / poo)共用同一个 `Base`,均通过单一 Alembic 链管理:
|
||||
所有模型(auth / config / public_ip / location / poo / modbus / expose)共用同一个 `Base`,均通过单一 Alembic 链管理:
|
||||
|
||||
- Alembic 环境:`alembic_app.ini` + `alembic_app/`
|
||||
- 统一 migration job:`python -m scripts.run_migrations`
|
||||
@@ -281,6 +288,84 @@ admin 可在 React SPA 设置页(`/config`)自选启用 RFC 6238 TOTP:
|
||||
|
||||
TOTP issuer 标签(显示在 Authenticator 里)通过 `AUTH_TOTP_ISSUER` 环境变量配置(`.env` 部署级),默认回退 `app_name`。
|
||||
|
||||
## M5 Modbus 设备采集 / Energy / MQTT + HA Discovery
|
||||
|
||||
M5 给后端接入家庭 IoT 生态,新增通用 Modbus 采集链路(首个领域:能耗)、MQTT + Home Assistant Discovery 发布,以及前端侧边栏与 Energy 视图。
|
||||
|
||||
### 依赖
|
||||
|
||||
后端新增:
|
||||
- `pymodbus`:Modbus-TCP 客户端(轮询电表等 slave 设备)
|
||||
- `paho-mqtt`:MQTT 客户端(HA Discovery 与 state 发布)
|
||||
- `pyyaml`:YAML profile 加载(设备协议声明式描述)
|
||||
|
||||
前端新增:
|
||||
- `recharts`:Energy 视图走势图
|
||||
|
||||
### Modbus 设备采集
|
||||
|
||||
采集链路采用两层分离:**YAML profile**(协议知识,随代码走)+ **`modbus_device` 数据库行**(部署/可配置信息)+ **`modbus_reading` 通用读数表**(JSON payload 遥测)。
|
||||
|
||||
- **profile**(如 `sdm120.yaml`)描述:读哪些寄存器(FC04 块读)、每个量的 key/unit/device_class/ha_component。纯协议知识,不含 unit_id / friendly_name 等部署项。
|
||||
- **`modbus_device` 行**:friendly_name、网关 host/port、Modbus slave `unit_id`(电表 Meter ID,设备面板可改故落 DB)、选用哪个 profile、采样周期、是否启用。
|
||||
- **`modbus_reading` 行**:device_id FK、recorded_at、payload(JSON,如 `{"voltage": 230.2, "current": 1.3, ...}`)。
|
||||
- 多设备可共享同一 profile(如两块 SDM120 共用 `sdm120` profile,各自独立 unit_id 和 friendly_name)。
|
||||
- APScheduler 后台 job 周期轮询所有 `enabled` 设备,更新 `last_poll_at` / `last_poll_ok`。全局开关 `MODBUS_POLLING_ENABLED`(CONFIG_FIELDS)。
|
||||
|
||||
**手工命令行试读**(不依赖 DB,最快验证网关连通性):
|
||||
|
||||
```bash
|
||||
# 按 profile 解码读一次(验证整套解码链路)
|
||||
python -m scripts.modbus_cli read --host <网关IP> --port 502 --unit 1 --profile sdm120
|
||||
|
||||
# 手工指定请求内容(first-contact 验证,不依赖 profile)
|
||||
python -m scripts.modbus_cli probe --host <网关IP> --port 502 --unit 1 --fc 4 --address 0x0000 --count 2 --decode float32
|
||||
```
|
||||
|
||||
CLI 工具为受控手工验证而设(设备需接市电),仅暴露读功能码(FC03/04),无写寄存器子命令。
|
||||
|
||||
### MQTT + Home Assistant Discovery
|
||||
|
||||
后端作为 MQTT 发布方,把 Modbus 设备/工程量以 HA Discovery 协议自动注册为 device/entity:
|
||||
|
||||
- 每个 Modbus 设备 = 一个 HA device(`unique_id` 锚定于设备 `uuid`,不随改名变)
|
||||
- 各工程量 = sensor entity(device_class/unit 取自 YAML profile);另有 binary_sensor `online`(取 `last_poll_ok`)
|
||||
- 每次轮询成功后推 state topic;连接成功或勾选变更时重发 retained discovery config
|
||||
- `POST /api/config/mqtt/test`:试连 broker 并发布一条测试消息(可用 MQTT Explorer 验证链路)
|
||||
|
||||
**Config 页配置流程**:
|
||||
1. 在 `/config` 的「MQTT」section 填写 broker host/port/username/password,启用 `MQTT_ENABLED`
|
||||
2. 点「发送测试消息」确认 broker 链路通
|
||||
3. 启用 `HA_DISCOVERY_ENABLED`
|
||||
4. 在「Home Assistant Expose」面板勾选要暴露的实体,点「重新发布 discovery」
|
||||
5. 在 Home Assistant 确认对应 device/entity 出现
|
||||
|
||||
### API 端点(M5 新增)
|
||||
|
||||
| 端点 | 用途 |
|
||||
| --- | --- |
|
||||
| `GET /api/modbus/devices` | 列出 Modbus 设备 |
|
||||
| `POST /api/modbus/devices` | 新建设备 |
|
||||
| `GET /api/modbus/devices/{uuid}` | 单个设备 |
|
||||
| `PATCH /api/modbus/devices/{uuid}` | 修改设备(含 enable/disable)|
|
||||
| `DELETE /api/modbus/devices/{uuid}` | 删除设备;有读数时 409 |
|
||||
| `GET /api/modbus/devices/{uuid}/metrics` | 该设备 profile 的量目录(key/unit/device_class)|
|
||||
| `GET /api/modbus/devices/{uuid}/latest` | 最新一条读数 payload |
|
||||
| `GET /api/modbus/devices/{uuid}/readings` | 时间范围读数(start/end/limit),供走势图 |
|
||||
| `POST /api/modbus/devices/{uuid}/test` | 即时试读(不落库) |
|
||||
| `GET /api/modbus/profiles` | 列出可用 profile 名 + 描述 |
|
||||
| `GET /api/expose` | 可暴露实体目录 + 勾选状态 + MQTT/Discovery 状态 |
|
||||
| `PUT /api/expose` | 设置逐 key 暴露开关 |
|
||||
| `POST /api/expose/republish` | 手动重发 discovery |
|
||||
| `POST /api/config/mqtt/test` | 试连 broker 并发布测试消息 |
|
||||
|
||||
### 前端视图(M5 新增)
|
||||
|
||||
- **侧边栏**:把顶栏改为侧边导航(Home / Records / Energy / Config + 主题切换 + 注销),当前路由高亮,移动端可折叠。
|
||||
- **`/energy`(Energy 视图)**:设备 CRUD(新建/编辑/删除,删除有二次确认;有读数时引导改用禁用);最新读数卡片(字段标签/单位取自 profile metrics);时间序列走势图(Recharts,支持电压/电流/功率/电能,带时间范围选择)。
|
||||
- **Config 页 Accordion**:各大 config section 可独立折叠/展开;「Home Assistant Expose」面板按设备分组勾选可暴露实体、显示 MQTT/Discovery 连接状态、「重新发布 discovery」按钮。
|
||||
- SPA 路由新增 `/energy`。
|
||||
|
||||
## Config 持久化
|
||||
|
||||
当前 config 页面不会把修改写回 `.env`。
|
||||
@@ -306,6 +391,9 @@ TOTP issuer 标签(显示在 Authenticator 里)通过 `AUTH_TOTP_ISSUER` 环
|
||||
- SMTP 基础配置
|
||||
- TickTick OAuth 配置
|
||||
- Home Assistant 配置
|
||||
- MQTT broker 配置(`MQTT_ENABLED`、`MQTT_BROKER_HOST/PORT/USERNAME/PASSWORD`、`MQTT_TLS_ENABLED`)
|
||||
- Home Assistant Discovery 配置(`HA_DISCOVERY_ENABLED`、`HA_DISCOVERY_PREFIX`)
|
||||
- Modbus 采集配置(`MODBUS_POLLING_ENABLED`)
|
||||
|
||||
其中 SMTP password 与其他 secret 字段一致:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user