Files

46 lines
4.9 KiB
Markdown
Raw Permalink Normal View History

# ESP32 DCU 调试控制台 — 配置系统
## 1. 系统与分层
本仓库没有集中式的配置文件(无 `*.yaml`、`*.toml`、`*.env`),采用三层组合方式完成运行时配置:
- **用户偏好层**:浏览器端 `localStorage`,用于持久化设备 IP、电机传输链路、刷新率、CAN DBC 设置等。
- **进程/工具层**:Python 服务通过 `argparse` 解析命令行参数(`--port`、`--window`、`--no-browser`);Windows 批处理/VBScript 再提供默认值与启动入口。
- **外部依赖层**:通过调用外部子进程(`tools/ecat/build_native/ecat_native.exe`)并传入 `--parent-pid` 等方式传递进程间通信所需配置。
## 2. 关键文件
- `esp32_server.py`:服务端核心。HTTP 服务器(端口探测/绑定)、EtherCAT 反向代理、pywebview 窗口外壳、子进程生命周期管理,均通过 argparse 与模块级常量硬编码控制。
- `serve.bat`:控制台模式启动器,设 `PORT=2625` 后执行 `python esp32_server.py --port %PORT%`。
- `esp32_web.vbs` / `esp32_app.vbs`:分别以隐藏窗口/桌面窗(pywebview)方式启动 `esp32_server.py`,区别仅在于是否传 `--window`。
- `js/common/base-url.js`:统一封装设备 IP 的 `localStorage` key(`dcu_esp_ip`)与默认值(`DEFAULT_ESP_IP = '192.168.31.127'`)。注释明确“各页面共用”“只负责公共实现”。
- `js/motor/transport.js`:维护 ECAT/WiFi 传输切换状态,key 为 `dcu_motor_transport`。
- `js/motor/transport-ecat.js`:ECAT 传输配置,含网卡适配器、周期时间(4ms→250us 迁移标记 `LS_PERIOD_MIG`、`LS_SPIN`)等,全部落 localStorage。
- `js/can/persist.js`、`js/ota/file-handle.js`:各自功能页的偏好持久化(DBC、刷新目标 `LS_FLASH_TARGET`、最近固件元数据 `LS_FILE_META`)。
- `js/app.js`:主标签外壳页面,读写主页的共享设备 IP。
## 3. 架构与设计约定
### 3.1 设备发现与连接
- 所有页面向设备发起 API 请求的目标由 `getBaseUrl()` 计算:`http://` + 当前设备 IP,IP 从 `localStorage['dcu_esp_ip']` 取,无有效值回退到 `192.168.31.127`。
- 代码注释强调 “每个页面一致”“空值忽略”,对 `localStorage` 的访问被 try/catch 包裹(兼容隐私模式)。
### 3.2 端口与服务启动
- 端口优先级:`serve.bat` → `--port` → 默认 `2625` → `_bind_server` 自动递增重试(若占用则打印 `端口 xxx 已被占用, 尝试 xxx+1`)。
- 默认监听 `127.0.0.1`(不暴露公网)。
- Windows 下通过 Job Object 绑定子进程生命周期,父进程退出时内核连带杀掉服务子进程。
### 3.3 EtherCAT 后端自动发现与启动
- 使用内置端口数组 `ECAT_PORTS = (8090..8095)` 轮询检测正在运行的 `ecat_native.exe`。
- 首次需要时在 `g_ecat_lock` 保护下拉起子进程并传入 `--parent-pid`,避免独立实例清理逻辑误杀旧进程。
- 已运行实例通过 `_port_taken(p)` 复用,不再重复拉起。
### 3.4 多语言环境配置
- 所有中文字符串(日志、UI 文案、提示、注释中的路径与说明)均以 UTF-8 输出:`serve.bat` 先执行 `chcp 65001` 并将 `PYTHONUTF8=1` 写入子进程环境;`esp32_web.vbs` / `esp32_app.vbs` 同样设置 `PYTHONUTF8=1`。
- 前端 JS 侧无多语言文件,所有文案直接嵌入 HTML/JS 源文件中。
## 4. 约束与规则
- **设备 IP 键名唯一**:`dcu_esp_ip` 由 `js/common/base-url.js` 统一定义并通过 export 导出,所有功能页通过该共享 key 协作(OTA/CAN/电机页注释明确声明此约定)。
- **无外部配置文件的强制要求**:整个项目未使用 `.env`/`.yaml`/`*.cfg`/`*.ini` 等任何集中配置格式,如需调参必须修改源码常量或命令行参数。`esp32_server.py` 中除 `argparse` 外,其余行为均通过模块级变量(如 `ECAT_DIR`、`ECAT_PORTS`、`BASE_DIR`)与命令行参数组织。
- **安全边界**:服务默认仅监听 `127.0.0.1`;EtherCAT 原生后端也绑 `127.0.0.1` 且无 CORS,故页面需经本服务同源反向代理(`/ecat/api/*`)访问,避免跨域预检失败。
- **前端本地存储可容错**:每次 `localStorage.setItem/getItem` 都包裹 try/catch(应对无痕/隐私模式抛出异常);写前做 trim 校验,空值即忽略。
- **进程边界配置不可穿透**:VBScript 层通过命令行参数(`--window`)切换模式,但 Python 内部不会反查环境变量;子进程通过标准输出打印 `PORT={...}` 供父进程解析,而非通过共享配置文件通信。
## 5. 总结
这是一个**纯前端 + 简易 Python 静态服务器**场景下的轻量配置系统:设备地址和界面偏好完全落在浏览器的 `localStorage` 中,服务进程本身通过命令行参数与模块内常量硬编码驱动,不存在 YAML/环境变量等集中式配置机制。其优点是无依赖、可直连浏览器调试;代价是新增配置项需要同时修改多处 JS/Python 源码和脚本入口。