diff --git a/.gitignore b/.gitignore index 11d1860..24dcacd 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,11 @@ env/ *.pcapng sniff_*.txt +# EEPROM/SII 导出产物(eeprom read --out 生成, 属运行结果不是源码) +sii.json +*.sii +eeprom_*.bin + # 一次性日志分析脚本(硬编码临时路径, 无留存价值) _analyze_log.py diff --git a/README.md b/README.md index fe83255..5a91940 100644 --- a/README.md +++ b/README.md @@ -18,45 +18,53 @@ venv\Scripts\python.exe -m pip install -r requirements.txt ## 目录结构 +入口在最外层,双击即用;代码全部收进 `src/`。 + ``` ecat/ -├─ ecat_server.py 网页控制台后端(REST API + 静态文件), 默认端口 8090 -├─ ecat_tool.py 一体化命令行主站 -├─ ecat_flash_eeprom.py 经网线烧写 SII 镜像(被 ecat_tool flash 复用) -├─ test_motor_backend.py 电机后端自测(不接硬件) -├─ web/ 前端资源(URL 路径不变, 仍是 / 与 /motor.html) -├─ diag/ 独立诊断脚本(互不依赖, 直接单跑) -├─ launch/ 双击入口(.bat/.vbs) +├─ ecat_app.vbs ← 桌面窗口(推荐) +├─ ecat_web.vbs ← 浏览器标签 +├─ ecat_web.bat ← 控制台模式(看日志) +├─ ecat.bat ← 命令行工具 +├─ run_scan.bat ← bring-up 扫描 +├─ README.md / requirements.txt +├─ src/ +│ ├─ ecat_server.py 网页控制台后端(REST API + 静态文件), 默认端口 8090 +│ ├─ ecat_tool.py 一体化命令行主站 +│ ├─ ecat_flash_eeprom.py 经网线烧写 SII 镜像(被 ecat_tool flash 复用) +│ ├─ test_motor_backend.py 电机后端自测(不接硬件) +│ ├─ web/ 前端资源(URL 路径不变, 仍是 / 与 /motor.html) +│ └─ diag/ 独立诊断脚本(互不依赖, 直接单跑) └─ venv/ 本地虚拟环境(不入库) ``` -根目录只放主程序:`ecat_tool.py` import `ecat_flash_eeprom`、 -`test_motor_backend.py` import `ecat_server`,这几个互相 import 的必须同层, -挪进子目录就得改 import 或加包,不值得。 +`src/` 根下那四个 .py 平放是有原因的:`ecat_tool.py` import `ecat_flash_eeprom`、 +`test_motor_backend.py` import `ecat_server`,互相 import 的必须同层,再往下分 +就得改 import 或做成包,不值得。 | 文件 | 说明 | |------|------| -| `ecat_tool.py` | 一体化命令行主站:`adapters` / `status` / `flash` / `eeprom` / `sdo` / `send` 等子命令 | -| `ecat_server.py` | 网页控制台后端(REST API + 静态文件),默认端口 **8090**(8080 已被 ESP32 tools 占用) | -| `ecat_flash_eeprom.py` | 通过网线烧写 `gen_eeprom.py` 生成的 SII 镜像,逐字回读校验(烧完需断电重启让 ESC 重新加载) | -| `test_motor_backend.py` | 电机后端自测,**不接硬件**(假从站模拟 GD32 buildInput/processOutput)。跑法:`venv\Scripts\python.exe test_motor_backend.py` | -| `web/ecat.html` + `web/ecat.css` | 网页控制台前端 | -| `web/motor.html` + `web/motor.js` | 电机控制台:N1–N9 九节点,走 EtherCAT 过程数据(不经 WiFi/HTTP)。节点总览、8 种 Control_Mode、STATUS 实时解码、示波器曲线 | -| `diag/ecat_scan.py` | 最小化 bring-up 扫描:从站身份 + SII dump,`--op` 追加 PDO 测试 | -| `diag/ecat_esc_regs.py` | 从**网络侧**直读 LAN9252 ESC 寄存器,绕开 GD32/PDI,用于判断 EEPROM 加载是否真的失败;支持 `--reload` | -| `diag/ecat_sniff.py` | 旁路抓包,hexdump SOEM 自己发出的帧,用于对照裸帧格式 | +| `src/ecat_tool.py` | 一体化命令行主站:`adapters` / `status` / `flash` / `eeprom` / `sdo` / `send` 等子命令 | +| `src/ecat_server.py` | 网页控制台后端(REST API + 静态文件),默认端口 **8090**(8080 已被 ESP32 tools 占用) | +| `src/ecat_flash_eeprom.py` | 通过网线烧写 `gen_eeprom.py` 生成的 SII 镜像,逐字回读校验(烧完需断电重启让 ESC 重新加载) | +| `src/test_motor_backend.py` | 电机后端自测,**不接硬件**(假从站模拟 GD32 buildInput/processOutput)。跑法:在 `src/` 下 `..\venv\Scripts\python.exe test_motor_backend.py` | +| `src/web/ecat.html` + `ecat.css` | 网页控制台前端 | +| `src/web/motor.html` + `motor.js` | 电机控制台:N1–N9 九节点,走 EtherCAT 过程数据(不经 WiFi/HTTP)。节点总览、8 种 Control_Mode、STATUS 实时解码、示波器曲线 | +| `src/diag/ecat_scan.py` | 最小化 bring-up 扫描:从站身份 + SII dump,`--op` 追加 PDO 测试 | +| `src/diag/ecat_esc_regs.py` | 从**网络侧**直读 LAN9252 ESC 寄存器,绕开 GD32/PDI,用于判断 EEPROM 加载是否真的失败;支持 `--reload` | +| `src/diag/ecat_sniff.py` | 旁路抓包,hexdump SOEM 自己发出的帧,用于对照裸帧格式 | ## 启动方式 -双击 `launch/` 里的入口即可(脚本自己会定位到项目根,不必在特定目录下运行): +双击根目录下的入口即可(脚本自己定位路径,不必在特定目录下运行): | 入口 | 效果 | |------|------| -| `launch/ecat_app.vbs` | pywebview 桌面窗口,无控制台无浏览器标签(已针对部分 GPU 驱动白屏加 `--disable-gpu-compositing`) | -| `launch/ecat_web.vbs` | 后台起服务并打开浏览器标签,无控制台窗口 | -| `launch/ecat_web.bat` | 控制台模式,可见日志,调试用 | -| `launch/ecat.bat` | 命令行工具入口,如 `ecat.bat status`、`ecat.bat flash` | -| `launch/run_scan.bat` | 直接跑 bring-up 扫描,无参数则列出 Npcap 适配器 | +| `ecat_app.vbs` | pywebview 桌面窗口,无控制台无浏览器标签(已针对部分 GPU 驱动白屏加 `--disable-gpu-compositing`) | +| `ecat_web.vbs` | 后台起服务并打开浏览器标签,无控制台窗口 | +| `ecat_web.bat` | 控制台模式,可见日志,调试用 | +| `ecat.bat` | 命令行工具入口,如 `ecat.bat status`、`ecat.bat flash` | +| `run_scan.bat` | 直接跑 bring-up 扫描,无参数则列出 Npcap 适配器 | 电机控制台在服务起来后从主页右上「电机控制台」进入,或直接访问 `/motor.html`。 它只读写 EtherCAT 过程数据,需先在主页点「连接」并让从站进入 OP。 @@ -70,5 +78,5 @@ ecat/ 断电才清零。固件 <1.5.52 无自愈需断电重启,1.5.52+ 有守护自动写回。 `config_map` 失败时后端会自动转储 4 个 SM 现场,可直接对照。 - 前端 CSS/JS 改动后记得 bump `?v=` 缓存版本,否则浏览器会加载旧代码。 - `web/ecat.css` 被 `web/ecat.html` 与 `web/motor.html` 共用,两处版本号要一起改。 + `src/web/ecat.css` 被 `ecat.html` 与 `motor.html` 共用,两处版本号要一起改。 - EEPROM 烧写后必须断电冷启动,ESC 才会重新加载配置。 diff --git a/launch/ecat.bat b/ecat.bat similarity index 55% rename from launch/ecat.bat rename to ecat.bat index 0df69d9..0fb4fcc 100644 --- a/launch/ecat.bat +++ b/ecat.bat @@ -1,10 +1,9 @@ @echo off rem EtherCAT master tool for DCU LAN9252 (scan/flash/send/monitor) rem Examples: ecat.bat status | ecat.bat flash | ecat.bat send --u64 0x1,0x2,0x3,0x4 --duration 5 -rem 本文件在 launch\ 下, %~dp0 指向 launch\, 故 ROOT 取其上一层。 +rem 入口在项目根, 代码在 src\; cd 进 src 是为了让 py 之间的 import 正常解析。 chcp 65001 >nul set PYTHONUTF8=1 -set "ROOT=%~dp0.." -cd /d "%ROOT%" -"%ROOT%\venv\Scripts\python.exe" ecat_tool.py %* +cd /d "%~dp0src" +"%~dp0venv\Scripts\python.exe" ecat_tool.py %* pause diff --git a/launch/ecat_app.vbs b/ecat_app.vbs similarity index 72% rename from launch/ecat_app.vbs rename to ecat_app.vbs index 8a02396..98af173 100644 --- a/launch/ecat_app.vbs +++ b/ecat_app.vbs @@ -1,14 +1,13 @@ ' DCU EtherCAT desktop window (pywebview/WebView2). No console, no browser tab. ' Browser-tab launcher: ecat_web.vbs Console-mode debug launcher: ecat_web.bat -' 本文件在 launch\ 下: 先取自身所在目录, 再上一层拿到项目根。 +' 入口在项目根, 代码在 src\; 工作目录设为 src 以便 py 之间 import 正常解析。 Set sh = CreateObject("WScript.Shell") Set fso = CreateObject("Scripting.FileSystemObject") -here = fso.GetParentFolderName(WScript.ScriptFullName) -base = fso.GetParentFolderName(here) -sh.CurrentDirectory = base +base = fso.GetParentFolderName(WScript.ScriptFullName) +sh.CurrentDirectory = base & "\src" sh.Environment("PROCESS")("PYTHONUTF8") = "1" ' WebView2: keep GPU rasterization but disable GPU compositing. ' Full hardware acceleration white-screens this window on some GPU drivers; ' --disable-gpu-compositing fixes it while still using the GPU for raster. sh.Environment("PROCESS")("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS") = "--disable-gpu-compositing" -sh.Run """" & base & "\venv\Scripts\pythonw.exe"" """ & base & "\ecat_server.py"" --window", 0, False +sh.Run """" & base & "\venv\Scripts\pythonw.exe"" """ & base & "\src\ecat_server.py"" --window", 0, False diff --git a/ecat_web.bat b/ecat_web.bat new file mode 100644 index 0000000..4914d9d --- /dev/null +++ b/ecat_web.bat @@ -0,0 +1,8 @@ +@echo off +rem DCU EtherCAT master web console (serves src\web\ecat.html + pysoem API) +rem 入口在项目根, 代码在 src\; cd 进 src 是为了让 py 之间的 import 正常解析。 +chcp 65001 >nul +set PYTHONUTF8=1 +cd /d "%~dp0src" +"%~dp0venv\Scripts\python.exe" ecat_server.py +pause diff --git a/launch/ecat_web.vbs b/ecat_web.vbs similarity index 59% rename from launch/ecat_web.vbs rename to ecat_web.vbs index fa76ad6..94f1b8a 100644 --- a/launch/ecat_web.vbs +++ b/ecat_web.vbs @@ -1,10 +1,9 @@ ' DCU EtherCAT web console - hidden launcher (no console window). ' Double-click me. Console-mode debug launcher (visible logs): ecat_web.bat -' 本文件在 launch\ 下: 先取自身所在目录, 再上一层拿到项目根。 +' 入口在项目根, 代码在 src\; 工作目录设为 src 以便 py 之间 import 正常解析。 Set sh = CreateObject("WScript.Shell") Set fso = CreateObject("Scripting.FileSystemObject") -here = fso.GetParentFolderName(WScript.ScriptFullName) -base = fso.GetParentFolderName(here) -sh.CurrentDirectory = base +base = fso.GetParentFolderName(WScript.ScriptFullName) +sh.CurrentDirectory = base & "\src" sh.Environment("PROCESS")("PYTHONUTF8") = "1" -sh.Run """" & base & "\venv\Scripts\python.exe"" """ & base & "\ecat_server.py""", 0, False +sh.Run """" & base & "\venv\Scripts\python.exe"" """ & base & "\src\ecat_server.py""", 0, False diff --git a/launch/ecat_web.bat b/launch/ecat_web.bat deleted file mode 100644 index efabc7a..0000000 --- a/launch/ecat_web.bat +++ /dev/null @@ -1,9 +0,0 @@ -@echo off -rem DCU EtherCAT master web console (serves web\ecat.html + pysoem API) -rem 本文件在 launch\ 下, %~dp0 指向 launch\, 故 ROOT 取其上一层。 -chcp 65001 >nul -set PYTHONUTF8=1 -set "ROOT=%~dp0.." -cd /d "%ROOT%" -"%ROOT%\venv\Scripts\python.exe" ecat_server.py -pause diff --git a/launch/run_scan.bat b/run_scan.bat similarity index 51% rename from launch/run_scan.bat rename to run_scan.bat index 5352906..42112c0 100644 --- a/launch/run_scan.bat +++ b/run_scan.bat @@ -2,11 +2,9 @@ rem EtherCAT master bring-up scan (LAN9252) rem Usage: run_scan.bat -> list Npcap adapters rem run_scan.bat I226 -> scan EtherCAT slaves (add --op for PDO test) -rem 本文件在 launch\ 下, %~dp0 指向 launch\, 故 ROOT 取其上一层; -rem 扫描脚本已挪进 diag\。 +rem 入口在项目根, 扫描脚本在 src\diag\。 chcp 65001 >nul set PYTHONUTF8=1 -set "ROOT=%~dp0.." -cd /d "%ROOT%" -"%ROOT%\venv\Scripts\python.exe" diag\ecat_scan.py %* +cd /d "%~dp0src" +"%~dp0venv\Scripts\python.exe" diag\ecat_scan.py %* pause diff --git a/diag/ecat_esc_regs.py b/src/diag/ecat_esc_regs.py similarity index 100% rename from diag/ecat_esc_regs.py rename to src/diag/ecat_esc_regs.py diff --git a/diag/ecat_scan.py b/src/diag/ecat_scan.py similarity index 100% rename from diag/ecat_scan.py rename to src/diag/ecat_scan.py diff --git a/diag/ecat_sniff.py b/src/diag/ecat_sniff.py similarity index 100% rename from diag/ecat_sniff.py rename to src/diag/ecat_sniff.py diff --git a/ecat_flash_eeprom.py b/src/ecat_flash_eeprom.py similarity index 100% rename from ecat_flash_eeprom.py rename to src/ecat_flash_eeprom.py diff --git a/ecat_server.py b/src/ecat_server.py similarity index 100% rename from ecat_server.py rename to src/ecat_server.py diff --git a/ecat_tool.py b/src/ecat_tool.py similarity index 100% rename from ecat_tool.py rename to src/ecat_tool.py diff --git a/test_motor_backend.py b/src/test_motor_backend.py similarity index 100% rename from test_motor_backend.py rename to src/test_motor_backend.py diff --git a/web/ecat.css b/src/web/ecat.css similarity index 100% rename from web/ecat.css rename to src/web/ecat.css diff --git a/web/ecat.html b/src/web/ecat.html similarity index 100% rename from web/ecat.html rename to src/web/ecat.html diff --git a/web/motor.html b/src/web/motor.html similarity index 100% rename from web/motor.html rename to src/web/motor.html diff --git a/web/motor.js b/src/web/motor.js similarity index 100% rename from web/motor.js rename to src/web/motor.js