Files
DCU_DesktopController/js/common/desktop-bridge.js
T
cbb 2c6235d920 feat(ecat): PDO 快发 ESF1 桌面强制直通,堵死慢发回落
桌面 APP 下 ECAT motor 发送只走 pywebview ESF1→native TCP;
删除桥内 HTTP/JSON 回落。附延迟测量与 pack 自测脚本与规格文档。
2026-09-21 02:11:49 +08:00

88 lines
3.2 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.
/**
* desktop-bridge.js — 桌面壳(pywebview)原生桥探测与调用
*
* 形态约定:
* esp32_app.vbs → --window → WebView2:JS 可经 window.pywebview.api 调到
* GUI 进程 Python,由它直连 ecat_native(不经浏览器 fetch、不经页面服务子进程代理)。
* esp32_web.vbs / 浏览器标签:无 pywebview,本模块返回 null,调用方回落 HTTP。
*
* 电机页在 tabs.html 的 iframe 内:pywebview 只注入顶层窗口,同源 iframe
* 必须向上找 window.parent / window.top 上的 pywebview.api。
*
* PDO 快发(pdo-fast-send):桌面壳且 native 带 fast_send_port 时,ECAT
* motor 发送优先 desktopEcatSendRaw(GUI 侧 ESF1 二进制直通入队)。
*/
"use strict";
function collectApi() {
const roots = [];
try { roots.push(window); } catch (_) {}
try {
if (window.parent && window.parent !== window) roots.push(window.parent);
} catch (_) {}
try {
if (window.top && window.top !== window) roots.push(window.top);
} catch (_) {}
for (const w of roots) {
try {
const api = w.pywebview && w.pywebview.api;
if (api && typeof api.ecat_api === "function") return api;
} catch (_) { /* 跨源 parent 会抛 */ }
}
return null;
}
let _api = null;
/** @description 取桌面桥 API;没有则 null(不缓存失败,pywebview 可能稍后注入)。 */
export function getDesktopEcatApi() {
if (_api && typeof _api.ecat_api === "function") return _api;
_api = collectApi();
return _api;
}
/** @description 是否跑在 pywebview 桌面壳里(有壳但桥方法未就绪时也可能 true)。 */
export function isDesktopShell() {
try {
return !!(window.pywebview ||
(window.parent && window.parent !== window && window.parent.pywebview) ||
(window.top && window.top !== window && window.top.pywebview));
} catch (_) {
return false;
}
}
/**
* 桌面桥 POST。path 接受 "motor/send" / "/api/motor/send" / "/ecat/api/motor/send"。
* @returns {Promise<object>} 与 native 同构的 JSON
*/
export async function desktopEcatPost(path, body, timeoutMs) {
const api = getDesktopEcatApi();
if (!api) throw new Error("desktop bridge unavailable");
return api.ecat_api(path, body == null ? {} : body, timeoutMs || 4000);
}
/**
* 桌面桥 PDO 快发(ESF1)。frames=[{ch,id,dlc,data(hex)}]。
* @returns {Promise<object>} {ok,queued,backlog,path,log};path=fast_tcp|http_send_raw|http_motor_send
*/
export async function desktopEcatSendRaw(frames, timeoutMs) {
const api = getDesktopEcatApi();
if (!api || typeof api.ecat_send_raw !== "function") {
throw new Error("desktop fast-send unavailable");
}
return api.ecat_send_raw(frames, timeoutMs || 2000);
}
/** @description 桌面桥是否暴露 ecat_send_raw(方法在,不代表 native 快发口一定在)。 */
export function hasDesktopFastSend() {
const api = getDesktopEcatApi();
return !!(api && typeof api.ecat_send_raw === "function");
}
/** @description 状态栏用:当前 ECAT 控制通道形态。 */
export function desktopBridgeLabel() {
if (!getDesktopEcatApi()) return "HTTP 代理";
return hasDesktopFastSend() ? "APP 二进制快发" : "APP 原生桥";
}