95 lines
6.2 KiB
Markdown
95 lines
6.2 KiB
Markdown
---
|
||
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)
|