PRE-M8-T03: finalize WarmteLink hardware validation
This commit is contained in:
@@ -9,8 +9,8 @@
|
|||||||
- [`m5-iot-energy.md`](./m5-iot-energy.md) — IoT 集成与能耗采集(Modbus/Energy + MQTT/HA Discovery + 前端侧边栏)
|
- [`m5-iot-energy.md`](./m5-iot-energy.md) — IoT 集成与能耗采集(Modbus/Energy + MQTT/HA Discovery + 前端侧边栏)
|
||||||
- [`m6-tibber-dynamic-energy.md`](./m6-tibber-dynamic-energy.md) — 通用电价层 + DSMR 实时电表接入 + 实时买卖电费计算 + HA Energy 反哺
|
- [`m6-tibber-dynamic-energy.md`](./m6-tibber-dynamic-energy.md) — 通用电价层 + DSMR 实时电表接入 + 实时买卖电费计算 + HA Energy 反哺
|
||||||
- [`m7-meter-epochs-archival.md`](./m7-meter-epochs-archival.md) — 电表生命周期 / 换表归档(Meter epochs)
|
- [`m7-meter-epochs-archival.md`](./m7-meter-epochs-archival.md) — 电表生命周期 / 换表归档(Meter epochs)
|
||||||
- [`pre-m8-warmtelink-p1-poc.md`](./pre-m8-warmtelink-p1-poc.md) — WarmteLink P1 真机概念验证(bring-up 已完成,正式 probe 待实现)
|
- [`pre-m8-warmtelink-p1-poc.md`](./pre-m8-warmtelink-p1-poc.md) — WarmteLink P1 真机概念验证(已完成;正式 CLI 长测与供暖变化均经物理表复核)
|
||||||
- [`m8-warmtelink-energy.md`](./m8-warmtelink-energy.md) — WarmteLink P1 与多数据源 Meter(Planning 占位)
|
- [`m8-warmtelink-energy.md`](./m8-warmtelink-energy.md) — WarmteLink P1 与多数据源 Meter(Planning 已解锁;架构仍开放)
|
||||||
|
|
||||||
本文件定义**所有任务共用的格式与协作规则**,各个里程碑文档不再重复这些约定。
|
本文件定义**所有任务共用的格式与协作规则**,各个里程碑文档不再重复这些约定。
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# M8 — WarmteLink P1 与多数据源 Meter(Planning 占位)
|
# M8 — WarmteLink P1 与多数据源 Meter(Planning 占位)
|
||||||
|
|
||||||
> **状态:Planning 占位;尚未拆解任务卡,尚未锁定架构。** Pre-M8 人工 bring-up 已确认
|
> **状态:Planning 已解锁;尚未拆解任务卡,尚未锁定架构。** [Pre-M8 真机概念验证](./pre-m8-warmtelink-p1-poc.md)
|
||||||
> 两个累计量,但 M8 仍须等待 [Pre-M8 真机概念验证](./pre-m8-warmtelink-p1-poc.md)
|
> 已完成正式 probe、测试和 10 分钟复验;这只满足进入
|
||||||
> 的正式 probe、测试和长时间复验完成后再进入正式设计。
|
> Planning 的证据门,不授权 schema、API、worker 或前端实现。
|
||||||
|
|
||||||
## 1. 候选目标
|
## 1. 候选目标
|
||||||
|
|
||||||
@@ -20,11 +20,15 @@
|
|||||||
- 当前 electricity Meter 与 `dsmr_reading` 之间没有显式 source FK/binding;电费计算通过代码约定直接查询 DSMR 电力寄存器。
|
- 当前 electricity Meter 与 `dsmr_reading` 之间没有显式 source FK/binding;电费计算通过代码约定直接查询 DSMR 电力寄存器。
|
||||||
- `Meter.commodity` 后端已为 `heating` 等品类预留,但“增加 commodity”本身不会自动获得相应数据源或解析能力。
|
- `Meter.commodity` 后端已为 `heating` 等品类预留,但“增加 commodity”本身不会自动获得相应数据源或解析能力。
|
||||||
- 当前 Devices UI/模型是 Modbus 专用,不能直接假设 WarmteLink 应复用 `modbus_device`。
|
- 当前 Devices UI/模型是 Modbus 专用,不能直接假设 WarmteLink 应复用 `modbus_device`。
|
||||||
- 真机实测一个 WarmteLink serial source 同时输出两个累计 channel:channel 1 为生活热水
|
- 正式 CLI 复验中,一个 WarmteLink serial source 在 60/60 帧均输出两个累计 channel:channel 1
|
||||||
`m³`,channel 2 为区域供暖 `GJ`;两者均已与物理表对照一致。
|
为生活热水 `m³`(device type `006`、`5.900 m³`),channel 2 为区域供暖 `GJ`(device type
|
||||||
- 当前 P1 telegram 约每 10 秒一帧,没有瞬时流量、热功率、供水温度或回水温度字段。
|
`012`、基线 `0.017 GJ`);同日与物理表复核一致。最终人工走查开启供暖后,channel 2 又从
|
||||||
- 当前线材/设备组合以 `115200 7N1` 才能稳定解析正文;header/CRC 仍不可验证,正式 ingestion
|
`0.017 GJ` 增至 `0.018 GJ`,物理热量表同步显示 `0.018 GJ`。
|
||||||
必须显式处理该数据质量状态。
|
- 设备 timestamp 严格每 10 秒递进;frame 平均 256 bytes、范围 237–275,不能假定固定帧长。
|
||||||
|
当前 P1 telegram 没有瞬时流量、热功率、供水温度或回水温度字段。
|
||||||
|
- 当前线材/设备组合以 `115200 7N1` 才能稳定解析正文。60/60 frame 缺少标准 `/`,故均为
|
||||||
|
`unverifiable`;即使部分 footer 恰为四位十六进制也不能验证 CRC。正式 ingestion 必须显式
|
||||||
|
处理该数据质量状态,不能将数值与表盘相符视为 CRC valid。
|
||||||
|
|
||||||
## 3. 下一轮 Planning 必须讨论的问题
|
## 3. 下一轮 Planning 必须讨论的问题
|
||||||
|
|
||||||
@@ -41,11 +45,18 @@
|
|||||||
|
|
||||||
## 4. Planning 入口条件
|
## 4. Planning 入口条件
|
||||||
|
|
||||||
正式编写 M8 目标架构、数据模型和原子任务卡前,至少需要:
|
进入 M8 Planning 的证据门已满足:
|
||||||
|
|
||||||
|
- [x] Pre-M8 通过并留下脱敏字段清单。
|
||||||
|
- [x] 正式 probe 复验两个累计量、单位、channel、device type 与更新时间;equipment identifier
|
||||||
|
保持脱敏。
|
||||||
|
- [x] 记录 parser 适配结论和异常 framing/CRC 状态;10 分钟样本的稳定累计值不构成消费更新、
|
||||||
|
reset/wrap 或长期稳定性的证明。
|
||||||
|
- [x] 最终人工走查确认供暖消费时累计量按 `0.001 GJ` 更新并与物理表一致;精确更新延迟、
|
||||||
|
reset/wrap 和长期接纳策略仍留给 Planning。
|
||||||
|
|
||||||
|
正式编写 M8 目标架构、数据模型和原子任务卡前,仍需:
|
||||||
|
|
||||||
- Pre-M8 通过并留下脱敏字段清单。
|
|
||||||
- 用正式 probe 复验两个累计量及其单位、equipment id/channel 和更新时间。
|
|
||||||
- 确认原始 telegram 的长期稳定性、parser 适配方式和异常 CRC 的接纳策略。
|
|
||||||
- 重新走查现有 DSMR ingest、Meter epoch、Modbus device、expose/HA 和 Energy 前端边界。
|
- 重新走查现有 DSMR ingest、Meter epoch、Modbus device、expose/HA 和 Energy 前端边界。
|
||||||
- 与用户讨论并锁定 Meter ↔ source 的配置体验后,再决定 migration/API/UI 方案。
|
- 与用户讨论并锁定 Meter ↔ source 的配置体验后,再决定 migration/API/UI 方案。
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
# Pre-M8 — WarmteLink P1 真机概念验证
|
# Pre-M8 — WarmteLink P1 真机概念验证
|
||||||
|
|
||||||
> **状态:进行中。** 2026-08-22 已完成临时脚本真机 bring-up,并确认两个可用累计量;
|
> **状态:已完成。** 2026-08-22 已完成临时脚本真机 bring-up;随后仓库内正式 probe 以
|
||||||
> 仓库内的正式 probe、解析测试和可重复验收流程尚未实现。完成下方 PRE-M8-T01~T03
|
> `115200 7N1` 连续运行 10 分钟,形成脱敏的可重复验收证据;最终人工走查开启供暖后又观察到
|
||||||
> 后,才把 Pre-M8 标记为完成并解除 M8 Planning 的入口限制。
|
> 区域供暖累计量从 `0.017 GJ` 增至 `0.018 GJ`,并与物理表一致。Pre-M8 现已解除
|
||||||
|
> **M8 Planning** 的入口限制;M8 的架构和实现范围仍未锁定。
|
||||||
|
|
||||||
## 1. 目的
|
## 1. 目的
|
||||||
|
|
||||||
@@ -70,7 +71,8 @@ WarmteLink P1 → USB serial → 原始 telegram → 完整性状态 → 字段
|
|||||||
|
|
||||||
### 3.3 Framing 与 CRC 异常
|
### 3.3 Framing 与 CRC 异常
|
||||||
|
|
||||||
- 连续采集的 telegram 周期约为 10 秒;一次 8 帧盘点中每帧均为 256 字节。
|
- 临时 bring-up 的一次 8 帧盘点中每帧均为 256 字节;正式 10 分钟采样显示长度并不固定,
|
||||||
|
详见 §3.6。
|
||||||
- 正文结构稳定,版本、时间戳、两个 M-Bus channel、单位和值均可重复解析。
|
- 正文结构稳定,版本、时间戳、两个 M-Bus channel、单位和值均可重复解析。
|
||||||
- 实测头部为 `)TU)2NWA-MYRSKY`,偶见 `)TU{2NWA-MYRSKY`;没有标准要求的 `/` 起始符。
|
- 实测头部为 `)TU)2NWA-MYRSKY`,偶见 `)TU{2NWA-MYRSKY`;没有标准要求的 `/` 起始符。
|
||||||
- 帧尾存在 `!`,但其后的字符并非每帧都稳定为四位十六进制;即使恰好是四位,也无法从
|
- 帧尾存在 `!`,但其后的字符并非每帧都稳定为四位十六进制;即使恰好是四位,也无法从
|
||||||
@@ -111,6 +113,42 @@ M8 若要持久化这些读数,必须在 Planning 中单独锁定异常帧的
|
|||||||
- 当前没有瞬时流量、温度或热功率;M8 只承诺累计量采集与展示。
|
- 当前没有瞬时流量、温度或热功率;M8 只承诺累计量采集与展示。
|
||||||
- 串口 framing 和 CRC 异常尚未消失,必须作为正式 ingestion 的显式质量状态处理。
|
- 串口 framing 和 CRC 异常尚未消失,必须作为正式 ingestion 的显式质量状态处理。
|
||||||
|
|
||||||
|
### 3.6 正式 CLI 10 分钟复验(脱敏)
|
||||||
|
|
||||||
|
2026-08-22,仓库内 `python -m scripts.p1_probe` 在真实
|
||||||
|
`/dev/serial/by-id/<redacted>` 上以 `115200 7N1` 运行 `--duration 600 --show-changes`,原始
|
||||||
|
bytes 仅写入 `/tmp`。CLI 正常以 exit code 0 结束;期间没有 I/O error、未处理异常或断连。
|
||||||
|
|
||||||
|
- 读取到 60 个完整 frame、15,362 raw bytes;最后 2 bytes 是下一帧的不完整残片,60 个完整帧
|
||||||
|
合计 15,360 bytes。
|
||||||
|
- 设备 timestamp 从 `18:16:10` 至 `18:26:00`,严格每 10 秒递进。CLI 处理的 59 个相邻间隔中,
|
||||||
|
53 个为 10.0 s、1 个为 9.0 s、3 个为 0.0 s、2 个为 20.0 s,均值 9.81 s;0/20 s 配对来自
|
||||||
|
serial chunk 的批量交付,不代表设备 cadence 改变。
|
||||||
|
- 完整 frame 长度分布为 237 bytes × 2、239 × 1、254 × 12、256 × 31、258 × 11、275 × 3,
|
||||||
|
平均 256 bytes、范围 237–275。不能再把临时样本的「固定 256 bytes」视为帧格式契约;变长与
|
||||||
|
非标准 footer/分块边界一致。
|
||||||
|
- 60/60 的完整性均为 `unverifiable`,因为 60/60 缺少标准 `/` 起始符。footer 长度为 4 × 41、
|
||||||
|
6 × 16、23 × 3;仅 16/60 的 footer 恰为四位十六进制,但仍不能在缺失 `/` 时完成标准 CRC16
|
||||||
|
验证。**没有任何 frame 被报告为 CRC valid。**
|
||||||
|
- 60/60 帧均解析到同一组 9 个 OBIS code:`1-3:0.2.8`、`0-0:1.0.0`、`0-0:96.1.1`、
|
||||||
|
`0-1:24.1.0`、`0-1:96.1.0`、`0-1:24.2.1`、`0-2:24.1.0`、`0-2:96.1.0`、`0-2:24.2.1`。
|
||||||
|
equipment identifier 已脱敏,不进入 Git。
|
||||||
|
- channel 1 的 device type 是 `006`,累计值稳定为 `5.900 m³`;channel 2 的 device type 是
|
||||||
|
`012`,累计值稳定为 `0.017 GJ`。同日人工表盘复核也显示 `5.900 m³` / `0.017 GJ`,正式 CLI
|
||||||
|
因而复现了该基线。
|
||||||
|
- 60 帧中未见瞬时流量、热功率、供水温度或回水温度字段。10 分钟内累计值未变化只能证明这段
|
||||||
|
时间的累计值稳定;它不能证明发生消费时的更新频率,也不能证明 reset 或 wrap 行为。
|
||||||
|
|
||||||
|
### 3.7 最终人工走查:供暖累计量变化
|
||||||
|
|
||||||
|
正式长测交付后,用户又在终端直接运行只读 probe 十几分钟并开启供暖。channel 2 的区域供暖
|
||||||
|
累计量在本次运行中从 `0.017 GJ` 增至 `0.018 GJ`,同一时刻物理热量表也显示 `0.018 GJ`;
|
||||||
|
因此可以确认当前 P1 输出会在实际供暖消费下更新累计量,且 `0.001 GJ` 的变化与物理表一致。
|
||||||
|
|
||||||
|
这次人工走查没有改变完整性结论:telegram 仍缺少标准 `/`,数值与物理表一致不能替代 CRC
|
||||||
|
验证。走查也没有覆盖 reset、wrap 或精确更新延迟;这些仍须由 M8 的接纳、重复确认和告警策略
|
||||||
|
处理,而不能从一次累计量递增外推。
|
||||||
|
|
||||||
## 4. 正式 probe 的预期操作方式
|
## 4. 正式 probe 的预期操作方式
|
||||||
|
|
||||||
实现后,在 workspace virtual environment 中运行只读 probe:
|
实现后,在 workspace virtual environment 中运行只读 probe:
|
||||||
@@ -149,7 +187,7 @@ parser 契约。是否引入 [`dsmr_parser`](https://github.com/ndokter/dsmr_par
|
|||||||
|
|
||||||
### PRE-M8-T01 — 纯函数 telegram framing、CRC 与 OBIS parser
|
### PRE-M8-T01 — 纯函数 telegram framing、CRC 与 OBIS parser
|
||||||
|
|
||||||
- **Status**: `todo`
|
- **Status**: `done`
|
||||||
- **Depends**: `none`
|
- **Depends**: `none`
|
||||||
- **Context**: 先把串口 I/O 与解析分开,用脱敏 fixture 固定标准 DSMR 帧和本机异常帧行为。
|
- **Context**: 先把串口 I/O 与解析分开,用脱敏 fixture 固定标准 DSMR 帧和本机异常帧行为。
|
||||||
|
|
||||||
@@ -176,11 +214,11 @@ parser 契约。是否引入 [`dsmr_parser`](https://github.com/ndokter/dsmr_par
|
|||||||
|
|
||||||
**Acceptance criteria**
|
**Acceptance criteria**
|
||||||
|
|
||||||
- [ ] 标准 fixture 的 frame boundary 与 CRC 可验证为 `valid`。
|
- [x] 标准 fixture 的 frame boundary 与 CRC 可验证为 `valid`。
|
||||||
- [ ] 脱敏本机 fixture 被标为 `unverifiable`,但能按字段而非位置解析 `m³` 和 `GJ` channel。
|
- [x] 脱敏本机 fixture 被标为 `unverifiable`,但能按字段而非位置解析 `m³` 和 `GJ` channel。
|
||||||
- [ ] 任意 chunk boundary 和字段顺序不影响结果,未知字段原样保留。
|
- [x] 任意 chunk boundary 和字段顺序不影响结果,未知字段原样保留。
|
||||||
- [ ] 累计量以 `Decimal` + 原单位返回。
|
- [x] 累计量以 `Decimal` + 原单位返回。
|
||||||
- [ ] `pytest tests/test_p1_probe.py`、`pytest`、`ruff check .` 全绿。
|
- [x] `pytest tests/test_p1_probe.py`、`pytest`、`ruff check .` 全绿。
|
||||||
|
|
||||||
**Reviewer checklist**
|
**Reviewer checklist**
|
||||||
|
|
||||||
@@ -190,7 +228,7 @@ parser 契约。是否引入 [`dsmr_parser`](https://github.com/ndokter/dsmr_par
|
|||||||
|
|
||||||
### PRE-M8-T02 — 只读 serial probe CLI
|
### PRE-M8-T02 — 只读 serial probe CLI
|
||||||
|
|
||||||
- **Status**: `todo`
|
- **Status**: `done`
|
||||||
- **Depends**: `PRE-M8-T01`
|
- **Depends**: `PRE-M8-T01`
|
||||||
- **Context**: 在纯 parser 通过后增加最小 serial I/O,使真机验证可以从仓库稳定复现。
|
- **Context**: 在纯 parser 通过后增加最小 serial I/O,使真机验证可以从仓库稳定复现。
|
||||||
|
|
||||||
@@ -217,12 +255,12 @@ parser 契约。是否引入 [`dsmr_parser`](https://github.com/ndokter/dsmr_par
|
|||||||
|
|
||||||
**Acceptance criteria**
|
**Acceptance criteria**
|
||||||
|
|
||||||
- [ ] CLI 可用 `/dev/serial/by-id/...` 读取,且所有 framing 参数都可显式覆盖。
|
- [x] CLI 可用 `/dev/serial/by-id/...` 读取,且所有 framing 参数都可显式覆盖。
|
||||||
- [ ] 默认参数准确反映本机 `115200 7N1`,帮助文本说明它是实测值而非 DSMR 标准默认。
|
- [x] 默认参数准确反映本机 `115200 7N1`,帮助文本说明它是实测值而非 DSMR 标准默认。
|
||||||
- [ ] raw output 保留原始 bytes;终端清楚区分 `valid`、`invalid`、`unverifiable`。
|
- [x] raw output 保留原始 bytes;终端清楚区分 `valid`、`invalid`、`unverifiable`。
|
||||||
- [ ] permission/busy/disconnect 错误非零退出并给出可执行诊断,绝不建议常驻 root。
|
- [x] permission/busy/disconnect 错误非零退出并给出可执行诊断,绝不建议常驻 root。
|
||||||
- [ ] 依赖输入与两个生成 requirements 文件同步。
|
- [x] 依赖输入与两个生成 requirements 文件同步。
|
||||||
- [ ] `pytest tests/test_p1_probe.py`、`pytest`、`ruff check .` 全绿。
|
- [x] `pytest tests/test_p1_probe.py`、`pytest`、`ruff check .` 全绿。
|
||||||
|
|
||||||
**Reviewer checklist**
|
**Reviewer checklist**
|
||||||
|
|
||||||
@@ -232,7 +270,7 @@ parser 契约。是否引入 [`dsmr_parser`](https://github.com/ndokter/dsmr_par
|
|||||||
|
|
||||||
### PRE-M8-T03 — 正式真机验收与 M8 交接
|
### PRE-M8-T03 — 正式真机验收与 M8 交接
|
||||||
|
|
||||||
- **Status**: `todo`
|
- **Status**: `done`
|
||||||
- **Depends**: `PRE-M8-T02`
|
- **Depends**: `PRE-M8-T02`
|
||||||
- **Context**: 用仓库内 probe 替代本轮临时脚本,形成可重复、脱敏且能支撑 M8 Planning 的证据。
|
- **Context**: 用仓库内 probe 替代本轮临时脚本,形成可重复、脱敏且能支撑 M8 Planning 的证据。
|
||||||
|
|
||||||
@@ -257,11 +295,11 @@ parser 契约。是否引入 [`dsmr_parser`](https://github.com/ndokter/dsmr_par
|
|||||||
|
|
||||||
**Acceptance criteria**
|
**Acceptance criteria**
|
||||||
|
|
||||||
- [ ] 仓库内 probe 在真机连续运行至少 10 分钟,无未处理异常退出。
|
- [x] 仓库内 probe 在真机连续运行至少 10 分钟,无未处理异常退出。
|
||||||
- [ ] 脱敏摘要列出两个累计 channel、单位、精度、cadence 和完整性异常。
|
- [x] 脱敏摘要列出两个累计 channel、单位、精度、cadence 和完整性异常。
|
||||||
- [ ] `0.017 GJ`、`5.900 m³` 的基线或运行时新值与物理表再次对照。
|
- [x] `0.017 GJ`、`5.900 m³` 的基线或运行时新值与物理表再次对照。
|
||||||
- [ ] 明确没有从当前 P1 输出读取到瞬时流量、功率或温度。
|
- [x] 明确没有从当前 P1 输出读取到瞬时流量、功率或温度。
|
||||||
- [ ] Pre-M8 状态与 roadmap/M8 入口同步;代码闸门保持全绿。
|
- [x] Pre-M8 状态与 roadmap/M8 入口同步;代码闸门保持全绿。
|
||||||
|
|
||||||
**Reviewer checklist**
|
**Reviewer checklist**
|
||||||
|
|
||||||
@@ -277,10 +315,11 @@ parser 契约。是否引入 [`dsmr_parser`](https://github.com/ndokter/dsmr_par
|
|||||||
- [x] GJ 和生活热水 m³ 均与物理表面板完全一致。
|
- [x] GJ 和生活热水 m³ 均与物理表面板完全一致。
|
||||||
- [x] 已记录精度、约 10 秒 telegram cadence 和当前字段集合。
|
- [x] 已记录精度、约 10 秒 telegram cadence 和当前字段集合。
|
||||||
- [x] framing/CRC 失败已保留为显式异常,没有误报为校验通过。
|
- [x] framing/CRC 失败已保留为显式异常,没有误报为校验通过。
|
||||||
- [ ] 仓库内 parser、fixtures、probe CLI 和自动化测试完成。
|
- [x] 仓库内 parser、fixtures、probe CLI 和自动化测试完成。
|
||||||
- [ ] 正式 probe 完成至少 10 分钟真机复验并产出脱敏摘要。
|
- [x] 正式 probe 完成至少 10 分钟真机复验并产出脱敏摘要。
|
||||||
|
- [x] 最终人工走查在供暖开启后观察到 `0.017 → 0.018 GJ`,并再次与物理表核对一致。
|
||||||
|
|
||||||
当前人工 bring-up 已足以锁定 M8 的两个累计量目标,但 Pre-M8 milestone 仍需完成 T01~T03。
|
Pre-M8 已完成并向 M8 解锁 Planning;它只交付下列真机事实,不锁定正式架构或实现任务。
|
||||||
|
|
||||||
## 7. 向 M8 的交付物
|
## 7. 向 M8 的交付物
|
||||||
|
|
||||||
|
|||||||
+19
-11
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
本文档记录 `home-automation` 在 `v1.0.3` 之后的下一阶段规划。这一阶段不是小修补,而是几次较大的结构性改动:单库化、前端重写、以及远期的移动端试水。
|
本文档记录 `home-automation` 在 `v1.0.3` 之后的下一阶段规划。这一阶段不是小修补,而是几次较大的结构性改动:单库化、前端重写、以及远期的移动端试水。
|
||||||
|
|
||||||
> 每个里程碑的设计与**可执行原子任务**展开在 [`docs/design/`](./design/README.md):M1 [`m1-db-consolidation.md`](./design/m1-db-consolidation.md)、M2 [`m2-frontend-v2.md`](./design/m2-frontend-v2.md)、M3 [`m3-token-mobile.md`](./design/m3-token-mobile.md)、M4 [`m4-login-hardening.md`](./design/m4-login-hardening.md)、M5 [`m5-iot-energy.md`](./design/m5-iot-energy.md)、M6 [`m6-tibber-dynamic-energy.md`](./design/m6-tibber-dynamic-energy.md)、M7 [`m7-meter-epochs-archival.md`](./design/m7-meter-epochs-archival.md)、Pre-M8 [`pre-m8-warmtelink-p1-poc.md`](./design/pre-m8-warmtelink-p1-poc.md)、M8 [`m8-warmtelink-energy.md`](./design/m8-warmtelink-energy.md)。Pre-M8 已有可执行任务卡;M8 仍是 Planning 占位。
|
> 每个里程碑的设计与**可执行原子任务**展开在 [`docs/design/`](./design/README.md):M1 [`m1-db-consolidation.md`](./design/m1-db-consolidation.md)、M2 [`m2-frontend-v2.md`](./design/m2-frontend-v2.md)、M3 [`m3-token-mobile.md`](./design/m3-token-mobile.md)、M4 [`m4-login-hardening.md`](./design/m4-login-hardening.md)、M5 [`m5-iot-energy.md`](./design/m5-iot-energy.md)、M6 [`m6-tibber-dynamic-energy.md`](./design/m6-tibber-dynamic-energy.md)、M7 [`m7-meter-epochs-archival.md`](./design/m7-meter-epochs-archival.md)、Pre-M8 [`pre-m8-warmtelink-p1-poc.md`](./design/pre-m8-warmtelink-p1-poc.md)、M8 [`m8-warmtelink-energy.md`](./design/m8-warmtelink-energy.md)。Pre-M8 已完成;M8 仅解锁 Planning,架构仍开放。
|
||||||
|
|
||||||
## 当前基线(v1.0.3)
|
## 当前基线(v1.0.3)
|
||||||
|
|
||||||
@@ -40,8 +40,8 @@
|
|||||||
| **M5** ✅ | IoT / 能耗采集 | 通用 Modbus 采集(YAML profile + JSON readings)+ MQTT/HA Discovery + 前端侧边栏 + Energy 视图 |
|
| **M5** ✅ | IoT / 能耗采集 | 通用 Modbus 采集(YAML profile + JSON readings)+ MQTT/HA Discovery + 前端侧边栏 + Energy 视图 |
|
||||||
| **M6** ✅ | 通用电价层 + DSMR 接入 + 实时电费计算 | 通用电价层(manual/tibber profile + 合同版本)+ DSMR 实时电表接入 + 每 15min 寄存器差×价计量电费(不可变快照)+ 日/月/年汇总 + 反哺 HA Energy + 前端合同/价格/费用视图 |
|
| **M6** ✅ | 通用电价层 + DSMR 接入 + 实时电费计算 | 通用电价层(manual/tibber profile + 合同版本)+ DSMR 实时电表接入 + 每 15min 寄存器差×价计量电费(不可变快照)+ 日/月/年汇总 + 反哺 HA Energy + 前端合同/价格/费用视图 |
|
||||||
| **M7** ✅ | 电表生命周期 / 换表归档 | 引入 Meter epoch,计费永不跨表算 delta,跨表/无表/异常 delta 一律降级,累计按当前表归零,追溯换表可重算,Meter CRUD API + 前端管理 UI |
|
| **M7** ✅ | 电表生命周期 / 换表归档 | 引入 Meter epoch,计费永不跨表算 delta,跨表/无表/异常 delta 一律降级,累计按当前表归零,追溯换表可重算,Meter CRUD API + 前端管理 UI |
|
||||||
| **Pre-M8** 🛠️ | WarmteLink P1 真机概念验证 | 人工 bring-up 已确认 `0.017 GJ` 与 `5.900 m³` 两个累计量;待实现正式只读 probe、解析测试和 10 分钟复验 |
|
| **Pre-M8** ✅ | WarmteLink P1 真机概念验证 | 正式只读 CLI 长测通过;人工开启供暖后累计量 `0.017 → 0.018 GJ` 且与物理表一致,所有 frame 的 CRC 状态仍为 `unverifiable` |
|
||||||
| **M8** 📝 | WarmteLink P1 与多数据源 Meter | 等 Pre-M8 正式 probe 完成后,规划一个 serial source 的两个累计 channel 与 Meter 的可配置关系 |
|
| **M8** 📝 | WarmteLink P1 与多数据源 Meter | Pre-M8 已解锁 Planning;再讨论一个 serial source 的两个累计 channel 与 Meter 的可配置关系,尚未锁定架构或实施 |
|
||||||
| **M3** | 开放与移动端(远期试水) | token 鉴权 + React Native 移动端 |
|
| **M3** | 开放与移动端(远期试水) | token 鉴权 + React Native 移动端 |
|
||||||
|
|
||||||
排序原则:**先清地基,再在干净结构上盖楼。** M2 的新 API 和 React 必须建立在合并后的单库之上;M4 是公网安全加固,在 M5 IoT 集成之前先堵住裸密码这个洞;M5 在安全基座就绪后再做 IoT 接入。
|
排序原则:**先清地基,再在干净结构上盖楼。** M2 的新 API 和 React 必须建立在合并后的单库之上;M4 是公网安全加固,在 M5 IoT 集成之前先堵住裸密码这个洞;M5 在安全基座就绪后再做 IoT 接入。
|
||||||
@@ -259,16 +259,22 @@ httpx / paho-mqtt / pyyaml / apscheduler 均为 M5 已有依赖,M6 复用,
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Pre-M8 — WarmteLink P1 真机概念验证(🛠️ bring-up 完成,probe 待实现)
|
## Pre-M8 — WarmteLink P1 真机概念验证(✅ 已完成)
|
||||||
|
|
||||||
### 目标
|
### 目标
|
||||||
|
|
||||||
2026-08-22 的临时真机脚本已确认当前链路需要 `115200 7N1` 才能稳定解析正文;一个
|
2026-08-22 的正式仓库 CLI 以 `115200 7N1` 连续运行 10 分钟,正常退出且没有 I/O error、未处理
|
||||||
WarmteLink source 暴露 channel 1 的生活热水累计量 `5.900 m³` 和 channel 2 的区域供暖
|
异常或断连。一个 WarmteLink source 在 60/60 完整 frame 中暴露 channel 1 的生活热水累计量
|
||||||
累计量 `0.017 GJ`,两者均与物理表完全一致。连续 8 帧没有流量、热功率或温度字段。
|
`5.900 m³` 和 channel 2 的区域供暖累计量 `0.017 GJ`;二者再次与同日物理表一致。没有流量、
|
||||||
|
热功率或温度字段。
|
||||||
|
|
||||||
帧头缺少标准 `/`,CRC 因而不可验证;这项异常必须由正式 probe 原样报告,不能伪装成校验
|
所有完整 frame 都缺少标准 `/`,CRC 因而为 `unverifiable`;这项异常由正式 probe 原样报告,
|
||||||
通过。下一步按 PRE-M8-T01~T03 实现纯 parser、只读 serial CLI,并完成至少 10 分钟真机复验。
|
没有伪装成校验通过。frame 平均 256 bytes、范围 237–275,设备 timestamp 严格每 10 秒递进。
|
||||||
|
10 分钟内累计值无变化只能证明稳定基线,不能证明消费时更新频率或 reset/wrap 行为。
|
||||||
|
|
||||||
|
最终人工走查又在终端连续运行 probe 十几分钟并开启供暖;区域供暖累计量从 `0.017 GJ` 增至
|
||||||
|
`0.018 GJ`,物理热量表同步显示 `0.018 GJ`。这确认了实际消费时的累计递增与 `0.001 GJ`
|
||||||
|
精度,但不改变 CRC `unverifiable` 结论,也不证明精确更新延迟或 reset/wrap 行为。
|
||||||
|
|
||||||
本阶段不落库、不接 API/前端/HA,也不决定正式 Device/Source/Meter 关系。它只向 M8 提供脱敏的真机事实,避免在未知 firmware/字段语义上提前设计。
|
本阶段不落库、不接 API/前端/HA,也不决定正式 Device/Source/Meter 关系。它只向 M8 提供脱敏的真机事实,避免在未知 firmware/字段语义上提前设计。
|
||||||
|
|
||||||
@@ -276,14 +282,16 @@ WarmteLink source 暴露 channel 1 的生活热水累计量 `5.900 m³` 和 chan
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## M8 — WarmteLink P1 与多数据源 Meter(📝 Planning 占位)
|
## M8 — WarmteLink P1 与多数据源 Meter(📝 Planning 已解锁)
|
||||||
|
|
||||||
### 候选目标
|
### 候选目标
|
||||||
|
|
||||||
在 Pre-M8 事实基础上,把 WarmteLink P1 已确认存在的区域供暖 GJ 和生活热水 m³ 接入
|
在 Pre-M8 事实基础上,把 WarmteLink P1 已确认存在的区域供暖 GJ 和生活热水 m³ 接入
|
||||||
Energy 模块,并讨论 Meter 如何与实际数据源建立可配置关系。
|
Energy 模块,并讨论 Meter 如何与实际数据源建立可配置关系。
|
||||||
|
|
||||||
当前不锁定数据库、API、后台 worker 或 UI 结构;特别是 DSMR MQTT source、P1 serial source、Device/Data Source 的定义和多 channel 映射,都留到下一轮 Planning 讨论后再拆原子任务。
|
Pre-M8 的证据门已满足,但当前仍不锁定数据库、API、后台 worker 或 UI 结构;特别是 DSMR MQTT
|
||||||
|
source、P1 serial source、Device/Data Source 的定义和多 channel 映射,都留到下一轮 Planning 讨论
|
||||||
|
并与用户锁定体验后再拆原子任务。
|
||||||
|
|
||||||
> Planning 占位与待决问题:[`docs/design/m8-warmtelink-energy.md`](./design/m8-warmtelink-energy.md)
|
> Planning 占位与待决问题:[`docs/design/m8-warmtelink-energy.md`](./design/m8-warmtelink-energy.md)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user