Files
DCU_DesktopController/docs/compose/spec/pdo-fast-send.md
T
cbb 2c6235d920 feat(ecat): PDO 快发 ESF1 桌面强制直通,堵死慢发回落
桌面 APP 下 ECAT motor 发送只走 pywebview ESF1→native TCP;
删除桥内 HTTP/JSON 回落。附延迟测量与 pack 自测脚本与规格文档。
2026-09-21 02:11:49 +08:00

110 lines
4.7 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: pdo-fast-send
status: delivered
updated: 2026-09-23
branch: main
commits: working-tree (uncommitted; dual-repo main authorized)
---
# PDO 快发(网页按钮 → 原生入队二进制直通)
## Report
**What was built** — 桌面 APP(esp32_app)下,电机页 EtherCAT 链路的**全部** motor
发送**强制**走 ESF1 二进制快发:JS `desktopEcatSendRaw` → GUI 进程
`ecat_send_raw` 打包 → native 持久 TCP 口(health.`fast_send_port`)入 `g_cmd_q`。
**已堵死慢发**:Python 桥删除 HTTP `send_raw` / JSON `motor/send` 回落;前端在
`hasDesktopFastSend()` 为真时失败直接 `ok:false`,不再 `api("motor/send")`。
浏览器无壳标签仍走 HTTP `/ecat/api/motor/send`(脚本/诊断同理)。布局:请求
magic `ESF1` + nframes + 72B/帧;响应 `FSOK` 8 字节。
**Verification** —
- `build_native.bat` PASS;health `fast_send_port` 存在,loop=1 wkc=3
- `scripts/test_esf_pack.py` PASS;`py_compile esp32_server.py` PASS
- `node --check` desktop-bridge / transport-ecat / transport / main PASS
- `scripts/check_esf_latency.py`:TCP FSOK p50≈0.046–0.08ms(HTTP 对照仍在 native 路由上)
- 源码检查:`ecat_send_raw_frames` 无 `motor/send`/`http_send_raw` 回落;
`sendViaFastOrJson` 有桥时不调 `api("motor/send")`
- `test_motor_transport.mjs` 68/68 PASS(Node 无 pywebview → 走 HTTP 契约路径)
- `test_motor_refresh.mjs` 62/62 PASS
- 独立评审 CRITICAL/MAJOR(锁/静态缓冲/端口缓存)此前已修复
**Journey log** —
- 用户期望「纳秒进 PDO」不可达;可压的是控制面,入队后仍是 250µs 一拍 PDO
- pywebview JS→Python hop 仍在,TCP 快发已把 native 侧压到 ~50–80µs
- 沙箱拦 `git worktree add` → 用户明确授权双仓 main
- 持久 TCP 必须 send+recv 整段持锁,否则 FSOK 错配
- **2026-09-23:用户要求堵死慢发**——桌面强制 ESF1、桥内删除 HTTP/JSON 回落;
浏览器/脚本仍保留 native HTTP 路由
## [S1] Problem
电机控制台在 EtherCAT 链路上点发送时,信号要走很长控制面才进 `ecat_native`
的 `g_cmd_q`:浏览器 fetch→代理→JSON,桌面 APP 再叠 pywebview 桥。用户要
「一点按钮极短 CPU 周期内进 PDO」。纳秒不可达;native 入队后到总线由 PDO
周期决定(250µs 档),可压缩的是控制面。HTTP 路径还存在 **8–12ms 调度尾部**,
必须防止桌面壳误走慢路径。
## [S2] Design
### 目标行为(2026-09-23 修订:堵死慢发)
1. 桌面 APP + 桥可用:ECAT 全部 motor 发送 **只走** ESF1 TCP;失败 `ok:false`,
**无** HTTP/JSON 回落。
2. Python `ecat_send_raw_frames`:**仅** TCP ESF1(失败可重探端口后再试 TCP 一次)。
3. 浏览器标签(无 pywebview):仍走 `/ecat/api/motor/send`。
4. native `/api/motor/send` 与 `/api/motor/send_raw` **保留**(浏览器/诊断脚本)。
5. UI 不新增专用开关;`sendHint` / `desktopBridgeLabel` 反映通道形态。
6. 不承诺纳秒。
### 工作区(用户授权覆盖)
- ESP32 与 tools/ecat 均在 **main** 上改(2026-09-23 授权;沙箱拦 worktree add)。
- native:`tools/ecat/ecat_native.c` + `build_native.bat`。
### 二进制帧布局(小端)
**请求**:
```
u32 magic = 0x31465345 /* ESF1 */
u8 nframes /* 1..64 */
u8 flags
u16 reserved
repeat nframes: /* 72B each */
u8 ch, u8 dlc, u16 pad, u32 id, u8 data[64]
```
**响应**:`u32 FSOK(0x4B4F5346) | u8 ok | u8 queued | u16 backlog`
### Native
- `127.0.0.1` `bind(0)` 快发口;health 增加 `fast_send_port`。
- 持久连接读 ESF1 → `parse_esf` → 共用 `enqueue_frames` → FSOK。
- HTTP `/api/motor/send_raw` 与 JSON `/api/motor/send` 仍服务浏览器/脚本。
- `send_raw` 解析缓冲为栈上(HTTP 多线程)。
### GUI 桥(esp32_server.py)
- `pack_esf` / `unpack_fsok`;`_GuiApi.ecat_send_raw`。
- **仅**持久 TCP;connect+sendall+recv 整段持锁。
- 失败:关 socket + `g_fast_send_port=0` → 重探后再试 TCP 一次 → 仍败则 ok:false。
- **无** HTTP/JSON 回落代码。
### 前端
- `desktop-bridge.js`:`desktopEcatSendRaw` / `hasDesktopFastSend`。
- `transport-ecat.js`:`sendViaFastOrJson` 有桥时只调快发。
- 缓存版本 `?v=20260923i`。
### Out of Scope
- 纳秒;共享内存;预装载+位触发;浏览器强制禁 HTTP;删除 native JSON 路由;
改 PDO 周期;WiFi 链路。
## Tasks
- [x] T1: native 快发口 + `/api/motor/send_raw` + health 字段 (covers: S2)
- [x] T2: Python 打包 + `ecat_send_raw` TCP-only(无回落) (covers: S2; depends: T1)
- [x] T3: desktop-bridge + transport-ecat 有桥强制快发 (covers: S2; depends: T2)
- [x] T4: 延迟脚本 + 文档 + 堵死慢发修订 (covers: S2; depends: T1)