diff --git a/js/ble/gatt.js b/js/ble/gatt.js index 45ad39a..25282e9 100644 --- a/js/ble/gatt.js +++ b/js/ble/gatt.js @@ -105,19 +105,21 @@ export async function connectBle() { setBleStage(2, '已就绪', null); setConnectionState(true); - try { deviceLink.reportBle(true, device.name || ''); } catch (_) {} bleLog('BLE', 'GATT 服务与特征获取完成'); await enableNotifications(); // ★ enableNotifications 内部已包含重试 + 主动断开逻辑; // 若返回时仍为 false,说明连接半死,UI 已被断开事件重置,不要继续推进到 Stage 3 if (!state.notificationsEnabled) { + try { deviceLink.reportBle(false, ''); } catch (_) {} bleLog('BLE', '连接就绪但 DATA_OUT 通知开启失败,等待用户重连', 'E'); return; } + try { deviceLink.reportBle(true, device.name || ''); } catch (_) {} // Mark stages 1-2 as done setBleStage(3, '', null); setBleStageText('BLE 连接就绪,请选择固件文件'); } catch (err) { + try { deviceLink.reportBle(false, ''); } catch (_) {} bleLog('BLE', `连接失败: ${err.message}`, 'E'); if (err.name !== 'NotFoundError') { setBleStageError(err.message); diff --git a/js/common/connection.js b/js/common/connection.js index 41899f9..5b7d2d5 100644 --- a/js/common/connection.js +++ b/js/common/connection.js @@ -61,8 +61,9 @@ export function updateConnectionUi(connected, text) { try { var snap = deviceLink.getSnapshot(); if (snap && snap.ts && (Date.now() - snap.ts) < 5000) { + /* 只覆盖在线布尔,保留调用方语义文案(设备忙/诊断中/STA…) */ connected = !!snap.links.esp32.online; - text = connected ? '已连接' : '离线'; + if (!text) text = connected ? '已连接' : '离线'; } } catch (_) {} var label = text || (connected ? '已连接' : '未连接'); diff --git a/js/common/device-link.js b/js/common/device-link.js index 9cdb3d8..c7ca260 100644 --- a/js/common/device-link.js +++ b/js/common/device-link.js @@ -68,8 +68,6 @@ function createOwner() { if (ch) { try { ch.postMessage({ type: "snapshot", snap: snap }); } catch (_) {} } - /* 同源 iframe 也可读 window 顶层缓存(BC 不可用时的弱备份) */ - try { window.__dcuDeviceLinkSnap = snap; } catch (_) {} } function setEsp32(status, ok) { @@ -133,15 +131,17 @@ function createOwner() { e.online = !!(st && st.ok && st.slave); e.busOpen = e.online; /* native status 不直接给 op/loop;用 load valid + slave state 粗判 */ - e.op = !!(st && st.slave && (st.slave.state & 0x0F) === 8); + e.op = !!(st && st.slave && st.slave.state != null && (st.slave.state & 0x0F) === 8); e.loadValid = !!(ld && ld.ok && ld.valid === true && Number.isFinite(ld.age_ms) && ld.age_ms >= 0 && ld.age_ms <= 3000); e.loop = e.loadValid || e.op; e.loadPerm = (ld && Number.isFinite(ld.load_perm)) ? ld.load_perm : 0; e.ageMs = (ld && Number.isFinite(ld.age_ms)) ? ld.age_ms : -1; publish(); + }).catch(function () { + /* 字段访问/异常不得让 ECAT 轮询永久停摆 */ }).then(function () { - ecatTimer = setTimeout(pollEcat, ECAT_POLL_MS); + if (!stopped) ecatTimer = setTimeout(pollEcat, ECAT_POLL_MS); }); } @@ -190,7 +190,6 @@ function createClient() { try { ch = new BroadcastChannel(CH_NAME); } catch (_) { ch = null; } var listeners = []; var last = null; - try { last = window.__dcuDeviceLinkSnap || null; } catch (_) {} function emit() { for (var i = 0; i < listeners.length; i++) { @@ -203,7 +202,6 @@ function createClient() { var m = ev && ev.data; if (!m || m.type !== "snapshot" || !m.snap) return; last = m.snap; - try { window.__dcuDeviceLinkSnap = last; } catch (_) {} emit(); }); try { ch.postMessage({ type: "hello" }); } catch (_) {}