81 lines
3.2 KiB
Markdown
81 lines
3.2 KiB
Markdown
---
|
||
feature: device-link
|
||
status: delivered
|
||
updated: 2026-09-16
|
||
branch: feat/device-link
|
||
commits: be26f4daa27cba70b4baeaeb3865f38ed51b2e71..6b5a9f9
|
||
---
|
||
|
||
# Device Link(全链路统一连接层)
|
||
|
||
## Report
|
||
|
||
**What was built** — `js/common/device-link.js` 在 `tabs.html` 以 Owner 身份常驻轮询
|
||
ESP32 `/system/status` 与 EtherCAT `/ecat/api/status`+`app/load`,经
|
||
`BroadcastChannel('dcu-device-link')` 广播快照;功能页 Client 订阅。
|
||
`connection.js` 的连接灯在快照 <5s 时只覆盖**在线布尔**,保留「设备忙」等语义文案。
|
||
LAN9252 页 SPI 失败显示「设备在线 · SPI 失败」,不再误标设备离线。
|
||
BLE GATT 在通知开启成功后 `reportBle(true)`,失败/断开上报 false。
|
||
|
||
**Verification** —
|
||
- `node --check`:device-link.js / connection.js / gatt.js PASS
|
||
- tabs.html、lan9252_pm 内联 script 抽出 `node --check` PASS
|
||
- 独立评审后修复:ECAT `Promise.all` 补 `.catch`+必重挂;去掉跨 iframe 无效的
|
||
`window.__dcuDeviceLinkSnap`;BLE 半开连接不再 sticky online
|
||
|
||
**Journey log** —
|
||
- 「共用 IP」≠「共用连接」——健康态必须有单一 Owner
|
||
- 外壳 Owner + 页内 Client 双 BC 实例符合 BroadcastChannel 语义(同上下文不自发自收)
|
||
- SPI/业务失败与设备离线必须分文案,否则子系统故障会伪装成掉线
|
||
- ECAT 轮询的 reschedule 必须在 `.catch` 之后,否则一次异常永久停摆
|
||
|
||
## [S1] Problem
|
||
|
||
多 iframe 保活后,各页仍**各自** `fetch` 设备,只是共用 `localStorage.dcu_esp_ip`:
|
||
|
||
- OTA 页轮询 `/system/status` → 顶栏「WiFi 已连接」
|
||
- LAN9252 页轮询 `/spi/send` → 同一 IP 却显示「连接失败 · signal timed out」
|
||
- EtherCAT 负载/状态又是一条独立轮询
|
||
- BLE 在页内 GATT,其它页完全不知
|
||
|
||
用户直觉是「同一条设备连接」,实现却是 N 条互不证明的 HTTP/蓝牙会话。
|
||
|
||
## [S2] Design
|
||
|
||
### 原则
|
||
|
||
1. **外壳持有链路健康轮询**(tabs.html 常驻),功能页不再各自判定「设备在线」。
|
||
2. **BroadcastChannel**(`dcu-device-link`)广播快照;页内只订阅渲染。
|
||
3. **命令仍页内发**,但**连接灯只认 DeviceLink**(布尔优先,文案保留调用方语义)。
|
||
4. SPI 失败 →「设备在线 · SPI 失败」;DeviceLink offline 才显示离线。
|
||
5. 独立直开页:无快照时回退本地轮询。
|
||
|
||
### 模块
|
||
|
||
`js/common/device-link.js` Owner+Client;消息:`hello` / `snapshot` / `set-ip` / `ble-state`。
|
||
|
||
### 接入
|
||
|
||
| 位置 | 行为 |
|
||
|------|------|
|
||
| `tabs.html` | Owner |
|
||
| `connection.js` | 快照新鲜时覆盖 connected 布尔 |
|
||
| `lan9252_pm.html` | 订阅灯 + `setSpiFail` |
|
||
| `js/ble/gatt.js` | 通知成功后 reportBle(true),失败/断 false |
|
||
|
||
## [S3] Out of Scope
|
||
|
||
- 不串行化 SPI/CAN/OTA 命令队列
|
||
- 不迁 SharedWorker
|
||
- 不改固件协议
|
||
- BLE GATT 仍留在页内(只广播状态)
|
||
|
||
## Tasks
|
||
|
||
- [x] T1: device-link.js Owner+Client + BC 协议 (covers: S2)
|
||
- [x] T2: tabs.html 启动 Owner (covers: S2)
|
||
- [x] T3: OTA connection.js 接入 DeviceLink (covers: S2)
|
||
- [x] T4: LAN9252 灯与 SPI 文案 (covers: S2)
|
||
- [x] T5: BLE 状态上报 (covers: S2)
|
||
- [x] T6: 语法检查 + 评审修复 (covers: S2)
|