12451 fe8436f114 test(e2e)+docs: 补上「平台侧积分电量」的**真实**端到端断言(此前只断言 suc=1)
## 起因

用户要求「`energy` 先实现自己积分,硬件能提供时再去掉」。**核实后:该积分早已实现**,
本轮真正缺的是**验证** —— 而且发现一个假覆盖。

## 核实结果:积分早已落地(不是新功能)

- **实现**:`software/api-server/src/workers/energy.rs`(12.9 KB / 8 个单测)——
  每次 `status_post` 按 `mWh = mV × mA × Δt / 3_600_000`(Δt 固定 60 秒)累加到
  **通道级** Redis 累加器(Lua 原子累加 + 最高温跟踪 + 连续无电池计数),
  建单 `reset`、结算 `take_and_reset` → 写 `charge_orders.energy` 与 `charge_records.energy`;
- **协议文档也已标注落地**:`docs/protocol/柜控板固件对接文档.md`「待确认事项」第 13 项
  写的是 **✅ 已落地(兜底方案已生效)**,并给出"硬件若能提供则平台改取硬件值"的口径;
- **`tasks/002` 把它记为「⏸ 阻塞中(等硬件答复)」是过时的** —— 已更正,并写明
  "硬件给值后怎么撤":**单一入口 `energy::accumulate`**,落库字段/记录生成/前端展示都不用动。

## 本轮补的真东西:把假覆盖变成真验证

`test/tcp_e2e_smoke.py` 第 ⑥ 步标题一直写着"验证平台侧积分电量",
**但只断言了 `suc=1`,从未检查电量值** —— 典型的"看起来验证了、其实没验证"。

新增第 ⑨ 步:`off` 结算后**读测试库**,断言:
1. `charge_orders.energy` == **由负载常量推导的期望值**
   (`CHARGING`=54.00V/8.00A × 60s × 3 次 ⇒ 21600 mWh ⇒ **22 Wh**);
2. 已生成 `charge_records`,且其 `energy` 与订单**一致**(同一积分值写两处,分叉即为缺陷);
3. `max_temperature` 被积分路径一并跟踪(29800 K×100)。

**实测结果(测试环境,18/18 通过、exit 0)**:
```
订单 id=58 status=1 energy=22Wh | 记录 energy=22Wh 最高温=29800K×100 | 期望=22Wh
```

**已自证能失败**:把 `CHARGING` 的电流由 8.00A 改为 4.00A(改**真实负载**而非期望值)
→ 实测 `11Wh ≠ 22Wh` → **FAILED / exit 1**;还原 → 18/18 通过。

## 顺带修掉一个"误导性红"

连续跑第 6 次本脚本会撞上 `auth_str` 的**「同一 IMEI 5 次 / 5 分钟」频率限制**(协议 §5.1),
于是第 ① 步被限流、后续 12 条断言**级联失败**,输出看起来像"登录/建单/结算全坏了"。
现第 ① 步即识别 `err == "rate limit exceeded"`,**明确说明是重复运行所致、不是功能缺陷**,
并提示 `systemctl restart pms-api-test` 清零进程内计数器,以 **exit 2(环境问题)**结束。

> 这个坑我实际踩到了:一度以为改动引入了回归,按「踩过的坑」第 7 条的思路先怀疑夹具/测量方式,
> 才定位到是限流。

## 退出码

新增"未验证"档:**读不到测试库 ⇒ exit 2**(需要 SSH 隧道),
**绝不当成通过**;有断言失败仍优先 exit 1。

## 验收

- `cargo check --all-targets`:0 error / 0 warning(本轮未改 Rust 代码);
- `cargo test --bin pms-api`:**189 passed**;
- `python tools/db_schema_diff.py`:**无漂移**;
- `test/schema_alignment_e2e.py --env dev`:全部通过 exit 0;
- `test/tcp_e2e_smoke.py`:**18/18 exit 0**(含新增 5 条积分断言);
- **发布**:本轮只改测试脚本与文档,**无需重新发布**;且实测生产与测试运行的是
  **逐字节相同的二进制**(api `f7e075a4a7a5983ebfe9b641e3d211cfdf7154361627858cbe68737211ff0f95`),
  即测试环境验证的积分链路**就是生产在跑的那份**。

## 文档

- `AGENTS.md` 验收流程第 5 项:注明该脚本现已含电量断言(**需要 SSH 隧道**)、
  以及 `auth_str` 限流的注意事项;
- `tasks/002`(不入库):把 `energy` 从"阻塞中"更正为"已实现 + 已端到端验证",
  并保留"硬件给值后如何撤"的口径。
2026-09-20 05:37:21 +08:00
..