3.9 KiB
3.9 KiB
一、使用的依赖管理体系
本仓库没有传统的包管理器:根目录与所有子目录下不存在 package.json、go.mod、requirements.txt、Pipfile*、*.lock、.npmrc 等任何依赖声明文件;前端侧使用浏览器原生 ES module(type="module")通过相对路径直接引用 ../css/*、../js/common/*,不经过 npm/yarn/pnpm 解析。
Python 后端 (esp32_server.py) 仅依赖 Python 标准库(http.server.SimpleHTTPRequestHandler / ThreadingHTTPServer、socket、subprocess、ctypes、urllib.request、threading、hashlib 等),以及一个可选的桌面外壳依赖 pywebview。该可选依赖在运行时探测缺失时回退到普通浏览器模式:print("pywebview 未安装: pip install pywebview —— 回退浏览器模式"),并通过 serve.bat / esp32_web.vbs 走无 GUI 路径。
非 Python 二进制依赖以独立可执行形式存在:EtherCAT 后端为编译后的单文件 build_native/ecat_native.exe(由外部脚本 build_native.bat 构建),由主服务按需在 8090–8095 端口范围内发现并启动(带 --parent-pid 实现父进程退出时自我结束),不属于当前仓库的包依赖图。
二、关键文件
esp32_server.py:唯一 Python 入口;通过import http.server、ctypes、subprocess等标准库提供服务、反向代理、窗口管理与 ecat 子进程编排。README.md:文档化的启动方式(esp32_app.vbs/esp32_web.vbs/serve.bat),明确了 pywebview 可选性以及 ecat_native 的外部依赖关系。scripts/build_mem.bat:调用 ESP-IDF 构建 DCU/ESP32_COMM 固件的辅助脚本,不引入 Python/JS 依赖。js/、pages/、css/:纯前端资源,无任何<script src="node_modules/...">,全部以相对 URL 引用。
三、架构与约定
- 零打包策略:
esp32_server.py直接 serve 静态 HTML/CSS/JS,页面内用<script type="module" src="../js/app.js">等加载,依赖解决完全由浏览器原生 ES module 完成。 - 可选桌面外壳:pywebview 作为可选依赖——有则用
pythonw+ pywebview 开 WebView2 桌面窗口(无控制台窗体);缺则回退到系统默认浏览器标签页模式,由serve.bat/esp32_web.vbs启动。 - 外置二进制子进程模式:EtherCAT 能力不在 Python 进程中提供,而是通过子进程协议拉取
tools/ecat/build_native/ecat_native.exe,服务端做/ecat/api/*同源转发来绕过其无 CORS + 127.0.0.1 绑定问题。该二进制由另一个 Git 仓库产出,当前仓库只负责发现与生命周期管理。 - 单实例互斥:通过本地 API
/api/focus把新双击重定向到已有实例前台窗口,避免并发拉起多个服务端实例。
四、约定与约束
- 前端资源版本化:修改 CSS/JS 后必须 bump 引用的
?v=缓存参数(否则浏览器加载旧代码),这是 README 中明确记录的强制约定。 - JS 模块内部引用须用
import.meta.url:不能写文档相对路径(如 Worker 文件),页面层级变化会 404(见js/motor/main.js的TICK_WORKER_URL)。 - 新增功能页必须在
tabs.html的TABS数组登记,实验性/一次性页面放lab/并保持自包含。 - 设备地址配置保存在
localStorage.dcu_esp_ip(默认192.168.31.127,见js/common/base-url.js),本服务不持有设备 IP,业务 API 全部直连 ESP32 固件 80 端口。 - Python 侧不得随意引入三方库:当前仅依赖标准库与可选
pywebview;若需增加第三方包,应评估是否仍走“纯标准库 + 可选 GUI”的路径,因为仓库中没有requirements.txt或pip freeze产物,依赖变更无法通过 CI 锁定复现。 - ECAT 子进程必须带
--parent-pid:否则它会清理同端口段其他实例,且主服务退出后会留下孤儿进程占用 Npcap 适配器与端口(见注释阶段 4 迁移说明)。