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 已空。
58 lines
2.5 KiB
JavaScript
58 lines
2.5 KiB
JavaScript
/**
|
||
* 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 (_) {}
|
||
}
|