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/ 运行态
This commit is contained in:
cbb
2026-09-20 22:58:00 +08:00
parent e91d53e0fc
commit 383535bd1d
23 changed files with 2060 additions and 283 deletions
+22
View File
@@ -55,6 +55,27 @@ function setWidthIfChanged(el, widthStr) {
}
// ==================== 连接管理 ====================
/**
* 无设备静默态:设备离线且没有传输在跑时,给 <html> 挂 data-dcu-calm="1",
* 由 responsive.css 统一掐掉常驻动画。160Hz 屏上这些动效每帧触发重算+重绘,
* 实测未接设备时 renderer+GPU 各占约一核的七成。
*/
export function setQuietMode(quiet) {
var v = quiet ? '1' : '0';
if (document.documentElement.dataset.dcuCalm !== v) {
document.documentElement.dataset.dcuCalm = v;
}
}
/** 本轮是否有传输/OTA 在跑(此时即使设备短暂不响应也要保留动效)。 */
function transferOngoing() {
try {
return !!(window.pollingPausedForUpload || window.currentOtaTarget ||
window.isEsp32Rebooting || window.bootEcatBusy ||
(typeof window.otaSessionActive === 'function' && window.otaSessionActive()));
} catch (_) { return false; }
}
export function updateConnectionUi(connected, text) {
/* DeviceLink 统一层:外壳 Owner 广播的新鲜快照优先于本页局部轮询结论,
避免 OTA「已连接」与 LAN9252「失败」同屏分裂。独立直开页无快照则用参数。 */
@@ -87,6 +108,7 @@ export function updateConnectionUi(connected, text) {
setTextIfChanged(bc, connected ? '在线' : '离线');
setClassIfChanged(bc, 'v ' + (connected ? 'ok' : 'err'));
}
setQuietMode(!connected && !transferOngoing());
}
export function updateHealthUi(healthCode, freeHeap) {
var healthNames = ['正常', '警告', '危险', '关机'];