Files
DCU_DesktopController/docs/compose/spec/host-code-quality.md
T

95 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
feature: host-code-quality
status: delivered
updated: 2026-09-23
branch: main
commits: 2c6235d..8043d8e(含评估、P0/P2/P3、界面回滚与安全重做 scope/seq/ota)
---
# 上位机代码质量评估(冗余 / 复杂度 / 屎山风险)
## Report
**What was built** — 全仓质量评估,并按风险优先级做了可验证整改。评估结论:综合约 **3.5/5**(改出来的屎山,仍可救)。
**当前真实状态(2026-09-23 界面正常后)**:
- **P0 服务端风险**:已落地(非幂等不自动重发、网卡默认 I210、跨进程 native 互斥/复用)。
- **P2 服务端边界**:`ecat_client.py` / `ecat_proc.py` 仍在;`esp32_server.py` 已变薄。
- **P3 卫生**:git 内 `scripts/` 收敛、报告在 `docs/reports/`、lab dump 清理。
- **电机前端**:**有意回滚后再安全重做**。完整 `main.js` 恢复 STATUS 契约(`offlineOverlay` / `statusLive`)后,仅外提 **`scope.js` / `seq.js` / `ota.js`**;`main.js` **3233** 行。连接/轮询/`renderStatusPanel` **仍在 main.js**。
- **未再实施**(上次拆分改坏界面后的决策):conn-poll 外提、R5 transport 版本/参数下沉、R6 电机链路强制 ecat-bus、R7 toast/quiet 去重。`ecat-bus.js` 仍供 device-link 使用;电机 `transport*.js` 保持拆分前行为。
### 整改对照(与仓库现状对齐)
| ID | 状态 | 落点 |
|----|------|------|
| R1 非幂等不重发 | **done** | `ecat_client.py` `_ecat_target_idempotent` |
| R2 网卡默认 I210 | **done** | README / `ecat_proc` / `ecat-bus.js` |
| R3 跨进程互斥/复用 | **done** | `_EcatProcXLock` + 复用健康监听 |
| R4 拆 main.js | **partial** | `scope`/`seq`/`ota` 已外提;**无** conn-poll;STATUS 渲染仍在 main.js |
| R5 版本/参数下沉 | **not in tree** | 电机 transport 回滚后无 `waitVersion`(device-link 侧未依赖) |
| R6 ECAT bootstrap 单点 | **partial** | `ecat-bus.js` 供 device-link;电机 transport-ecat 仍为拆分前实现 |
| R7 toast/quiet 去重 | **not in tree** | main.js 内仍有 `toast` / `setQuietMode`;`toast-stack.js` 已移除 |
| R8–R11 服务端 | **done** | `ecat_client.py` + `ecat_proc.py` |
| R12–R14 卫生 | **done** | scripts 清单 / docs/reports / lab dump |
| R15 README | **partial** | 结构与正式脚本清单已写;长篇实测未整段迁出 |
| R16 CSS | **partial** | 所有权注释;两套 btn/toast 刻意分域 |
### 不可逆教训(再拆必读)
1. STATUS DOM 契约:HTML 为 `#offlineOverlay` / `#statusLive`;错用不存在的 id 会导致**永远显示离线**(CSS 未坏)。
2. 机械外提禁止同作用域重复绑定(`setQuietMode` / `TICK_WORKER_URL`)。
3. **禁止** PowerShell 默认编码改 UTF-8 源文件。
4. **验收以界面为准**(`scripts/ui_diag_motor.mjs`),后端 e2e 绿不能代替 UI 绿。
5. 现场快照:`_backup/motor-good-7ea80f0/`(gitignore)。
**Verification** —
- `py_compile esp32_server.py ecat_client.py ecat_proc.py` PASS(P0/P2 保留期)
- `test_esf_pack.py` PASS;`test_motor_refresh.mjs` 62/62 PASS(前端重做后)
- `node --check` main/scope/seq/ota PASS
- UI 门禁(Edge→:2625/motor.html):控制台无报错;绿灯 AL OP;N1–N3 有数据;离线遮罩 `display:none`
- 真机 `e2e_web_send_latency.py`(重做后两轮):均为 **PASS 26 / FAIL 1**,exit=1。唯一失败项固定为 **`motor/start`(force_reopen)后立刻读 health 显示 `loop=0`**;同轮 `dc=1 dc_us=250 wkc=3`,且 `motor/send`×6 与 GD32 出口 tx/ack 均前进(HTTP p50≈1.9–5.4ms,出口 p50≈2.1–2.3ms,点击→STATUS≈14ms),WiFi 对照可用。判定为 **e2e 对 force_reopen 后 health 的采样竞态/口径问题**,不是发送链路回归;界面侧数据正常。
**Journey log** —
- 大拆 P1 曾导致界面全无数据 → 用户要求回滚 + 保留现场 + 重做
- 重做策略:只外提示波器/序列/OTA,**不动** STATUS/连接状态机
- e2e 冷启动 `loop=0` 与「发送已成功」可并存:属 health 采样竞态,不单说明链路死
- 历史坏提交仍在 git 时间线,工作区以回滚后状态为准;未做 history rewrite
- main 相对 `gitee/main` ahead 数十提交,是否 push 由用户决定
## [S1] Problem
用户要求评估 `G:\Robot_v2\DCU\tools\ESP32` 上位机是否已成「屎山」(冗余/复杂/难维护),并按清单整改。中途因大拆分导致电机页界面无数据,需在**不破坏现场**的前提下恢复并只做安全范围内的重构。
## [S2] Design
### 评估结论(保持)
- 领域复杂度真实(CAN FD、双链路、PDO 实时、pywebview 双进程)。
- 主要结构债:上帝文件、重复状态机、服务端越界替 ecat 补进程治理、杂物堆积。
- 综合约 **3.5/5**:可治理,但边界必须跟上迭代。
### 整改后架构契约(当前)
1. **电机页 STATUS**:仅 `toggleClsIfChanged(statusEl("offlineOverlay"|"statusLive"), ...)`,与 `motor.html` id 一致。
2. **电机前端模块**:`main.js` 装配 + `scope.js` / `seq.js` / `ota.js`(factory 注入 ctx);连接与 STATUS 渲染留在 main.js。
3. **服务端**:`esp32_server.py` + `ecat_client.py`(代理/ESF1/幂等策略)+ `ecat_proc.py`(autostart/锁/RT)。
4. **ECAT 默认网卡**:`I210` 为代码/文档一致来源。
5. **现场备份**:`_backup/` 不入库。
### [S3] Out of Scope
- 不再自动进行连接层大拆 / transport 版本下沉(除非另开任务并加 UI 门禁)
- 不 rewrite git 历史
- 不评估固件仓内部实现
- 本回合不 push 远端(除非用户明确要求)
## Tasks
- [x] T1: 全仓评估与 R1–R16 清单 — acceptance: 规格含证据与优先级 (covers: S2)
- [x] T2: P0 服务端风险修复 — acceptance: 幂等策略 + I210 + 跨进程锁 (covers: S2)
- [x] T3: P2/P3 服务端拆分与卫生 — acceptance: ecat_client/proc + scripts/reports (covers: S2)
- [x] T4: 界面故障根因与回滚 — acceptance: overlay 契约恢复,UI 门禁通过 (covers: S2)
- [x] T5: 安全重做 scope/seq/ota — acceptance: 每步 UI 门禁 + node --check (covers: S2)
- [x] T6: 收尾 e2e + 规格与现状对齐 — acceptance: e2e 结果记入 Report;对照表反映 partial/not-in-tree (covers: S2)