Files
DCU_DesktopController/js/common/desktop-bridge.js
T
cbb 383535bd1d feat(web): 桌面原生桥 + 配置落盘 + 无设备静默态;排除调试脚本
变更点:
1. esp32_server.py
   - /api/motor/ui-state、/api/lab/ui-state:配置原子落盘 data/*.json(WebView2 清存储仍在)
   - _GuiApi.ecat_api/bridge_info:桌面壳经 GUI 进程裸 socket 直连 ecat_native,不经浏览器 HTTP
2. js/common/desktop-bridge.js(新)
   - 探测 pywebview.api(含 iframe top/parent),transport-ecat 优先走原生桥
3. connection.js + responsive.css + components.css
   - setQuietMode:离线且无传输时 html[data-dcu-calm=1] 掐常驻动画
   - 进度条斜纹仅 .live 挂载,空闲不再按刷新率空转重绘
4. device-link.js
   - 先查 native/health,已健康跳过 motor/start,避免 loop_stop 重进 OP 假超时
   - 周期强制 0.25ms + DC SYNC0 对齐;轮询自愈被配错的 DC/周期
5. motor/main.js + transport-ecat.js
   - 配置双写 localStorage + 磁盘 ui-state;pagehide/sendBeacon 刷盘;导入导出
   - 探测代际 probeGen;ECAT 失败阈值 12;跟踪 bootActive/slaveAl/slaveOp
6. lab/spi_test.html、ota/boot_ecat.js、can_monitor 等跟随桥/静默态
7. .gitignore
   - 排除 scripts/_* 与 anal/collect/measure/trace 等调试脚本、lab 产物、data/ 运行态
2026-09-20 22:58:00 +08:00

66 lines
2.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。
*/
"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);
}
/** @description 状态栏用:当前 ECAT 控制通道形态。 */
export function desktopBridgeLabel() {
return getDesktopEcatApi() ? "APP 原生桥" : "HTTP 代理";
}