Files
DCU_DesktopController/js/motor/transport.js
T
cbb c189a8563e feat(motor): ESP32 侧适配 EtherCAT native 后端, 清理 Python 时代残留
tools/ecat 后端已从 Python(ecat_server.py, 已删除)切到原生守护进程
build_native/ecat_native.exe。本仓(ESP32 电机控制台)的 EtherCAT 传输经
/ecat/api/* 代理打它, 这次把代理实现与全部相关措辞对齐到 native。

代理与自启(esp32_server.py):
- ECAT_ENTRY/ECAT_PYW(src/ecat_server.py + venv/pythonw) → ECAT_NATIVE_EXE
  (build_native/ecat_native.exe); autostart 直接 Popen 单文件 exe, 不再经
  venv/pythonw; 清场/--parent-pid/端口漂移三条契约 native 原样镜像, 注释同步
- 文件头与代理段里 ecat_server.py 措辞订正为 native

传输层注释(js/motor/*):
- main/transport/transport-ecat/refresh-rate 里"后端是 ecat_server.py /
  用 venv 拉起"等 Python 时代说法统一改为 ecat_native.exe
- MOT_SLOTS_PER_PDO/MOTOR_SLOT_COUNT 引用改指 ecat_native.c(同名存在);
  MOTOR_SCAN_CYCLES native 无此常量, 改按真实来源写 ⌈27/7⌉=4
- main.js 环境错误分类正则 /venv|pysoem|Npcap/ → /Npcap|build_native|
  守护进程|全被占/: 前两者 native 永不吐给前端(死分支), 后者对齐 autostart
  真实文案, 让"exe 没编译"这类错误不被 140 字截断

README/motor.html 同步; 新增 scripts/browser_check_period.mjs(内核级 PDO
周期热调的浏览器实测, 与既有 browser_check_*.mjs 同族)。

验证: py_compile esp32_server.py 通过; 6 个改动 JS + 新脚本 node --check
(ESM)全过; 正则对三类 native 错误命中、对废弃 venv/pysoem 不命中;
js/ 与 scripts/ 重扫 ecat_server|venv|pysoem 已空。
2026-09-05 03:56:52 +08:00

58 lines
2.5 KiB
JavaScript
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.
/**
* transport.js — 电机控制台的传输选择层
*
* 电机页支持两条链路,业务逻辑(解码、节点列表、STATUS 面板、波形、命令序列、
* 流控)**完全共用**,只有"数据怎么进出"这一层不同:
*
* wifi ESP32 固件 80 端口的 HTTP API(原有实现,行为未变)
* ecat EtherCAT 过程数据,经本地页面服务器 /ecat/api/* 代理到
* tools/ecat 的 ecat_native.exe(C/SOEM 守护进程)
*
* 传输实例必须实现的接口(详见两个实现文件的注释):
* id / label / supportsOta / supportsPeriodSync
* sendHint(ch) -> string
* probe() -> statusData 连接探测,抛错=没连上
* fetchStatus(wantFull) -> statusData 健康检查
* describeStatus(data) -> string[] #devStatus 文本片段
* reportedIp(data) -> string|null 设备回报 IP(ECAT 恒 null)
* fetchMotorState() -> {have_data, age_ms, active_count, boot_active, motors[]}
* fetchFeedback() -> {channels:[{ch,enabled,valid,rx,tx,err,tec,rec,bus_state}]}
* sendFrames(frames, {ch}) -> results[] frames=[{id,dlc,data}]
* sendBurst(frames, {suffix,dlc}) -> results[]
* fetchVersionNode(node) -> {node,seq,version}|null
* setPeriod(ms) -> void 不支持则空实现
* teardown() -> void 切走时收尾
* 可选:takeNodeIdReport(node)、debug()
*
* motors[] 每项的字段契约(ECAT 实现负责补平差异):
* {node, ch, online, dlc, rx_count, seq, data(64hex), config_data(48hex|"")}
*/
"use strict";
import { createWifiTransport } from "./transport-wifi.js";
import { createEcatTransport } from "./transport-ecat.js";
/** localStorage key:记住上次选的传输,刷新页面后保持 */
export const LS_TRANSPORT = "dcu_motor_transport";
export const TRANSPORT_IDS = ["wifi", "ecat"];
/** @description 按 id 创建传输实例。未知 id 回退到 wifi。 */
export function createTransport(id, ctx) {
return (id === "ecat") ? createEcatTransport(ctx) : createWifiTransport(ctx);
}
/** @description 读上次选择的传输 id(默认 wifi —— 不改变老用户的既有行为)。 */
export function loadTransportId() {
try {
const v = localStorage.getItem(LS_TRANSPORT);
if (v && TRANSPORT_IDS.includes(v)) return v;
} catch (_) {}
return "wifi";
}
/** @description 保存传输选择。 */
export function saveTransportId(id) {
try { localStorage.setItem(LS_TRANSPORT, id); } catch (_) {}
}