Files
DCU_DesktopController/docs/compose/spec/device-link.md
T
cbb f9502579ef feat(link): 外壳启动强制 open+motor/start,不必等电机页切 EtherCAT
DeviceLink Owner 在控制台加载后自动 bootstrapEcatBus:status→open→
motor/start,沿用 hub 网卡与 period/spin 持久化。成功后不重复 start;
掉线 10s 退避重开。有线 ECAT 与 WiFi 不冲突。
2026-09-16 12:24:45 +08:00

4.4 KiB
Raw Blame History

feature, status, updated, branch, commits
feature status updated branch commits
device-link delivered 2026-09-16 feat/device-link 353d936..033ece2

Device Link / ConnectionHub(全链路统一连接层)

Report

What was built — 在既有 DeviceLink 健康广播之上扩展为 ConnectionHub:deviceLink 统一持有 WiFi IP、EtherCAT 网卡子串与 ecatPost,并保留 Owner/Client 快照。OTA(app.js)、CAN、 can_monitor、motor、ecat_load、LAN9252 改为从 Hub 读端点/订在线布尔;BLE 仍经 reportBle 上报。连接灯只覆盖布尔,不替换调用方语义文案。

Verification —

  • node --check 全部改动 JS → PASS
  • test_motor_transport.mjs 58/58 PASS
  • test_motor_refresh.mjs 62/62 PASS
  • test_ecat_autostart.mjs 19/19 PASS
  • 独立评审后修复 3 个 critical:读路径 setIp 风暴、CAN 文案覆盖、嵌入页误标轮询离线

Journey log —

  • 「共用 IP」≠「共用连接」——健康态必须有单一 Owner
  • Hub subscribe 只覆盖在线布尔,绝不替换调用方语义文案
  • 禁止在读路径调 setIp:Owner 会把每次 set-ip 当成立即重探
  • 嵌入 can.html 时 hub 不得写 fbPollStatus(那是 feedback 轮询自己的状态)

[S1] Problem

多 iframe 保活后,各页仍各自判定「设备连上了没有」,只是共用一个 IP 字符串:

  • OTA 页轮询 /system/status → 顶栏「WiFi 已连接」
  • LAN9252 页轮询 /spi/send → 同一 IP 却显示「连接失败」
  • EtherCAT 状态/负载又是一条独立轮询,网卡子串在 4 处重复读 localStorage
  • BLE 在页内 GATT,其它页完全不知
  • CAN / can_monitor / motor 各有一套 getBaseUrl 包装

用户直觉是「同一条设备连接」,实现却是 N 条互不证明的 HTTP/蓝牙会话和重复端点配置。

[S2] Design

原则

  1. 外壳持有链路健康轮询(tabs.html Owner),功能页不再各自判定「设备在线」。
  2. BroadcastChannel(dcu-device-link)广播快照;页内只订阅渲染。
  3. 端点配置只在 ConnectionHub:IP(dcu_esp_ip)、网卡(dcu_ecat_adapter)读写集中。
  4. 命令仍页内发,连接灯只认 DeviceLink 布尔(文案保留调用方语义)。
  5. BLE 为一等通道但单独适配:只广播状态,GATT 细节留在 ble/*。
  6. 外壳启动强制开总线:Owner 首轮即 status→open→motor/start;成功后不再重复 motor/start,掉线后 10s 退避重试。有线 EtherCAT 与 WiFi 不争网卡。
API 用途
subscribe / getSnapshot / channelOnline 健康快照
getIp / setIp / wifiBaseUrl WiFi 端点
getEcatAdapter / setEcatAdapter EtherCAT 网卡子串
ecatPost(path, body, timeoutMs) 统一 /ecat/api/* 代理请求
reportBle BLE 状态上报

Owner 消息:hello / snapshot / set-ip / ble-state。

接入

位置 行为
tabs.html Owner
Owner bootstrapEcatBus 外壳启动即 open+motor/start,不必等电机页切 EtherCAT
connection.js 快照新鲜时覆盖 connected 布尔
app.js IP/baseURL 走 deviceLink(保留 #espIp 输入回退)
can/dbc.js + can.js setDeviceIp 广播;顶栏灯订阅 hub
can_monitor.js baseURL 走 base-url/hub;灯订阅 hub
motor/main.js IP 订阅 hub 同步 state.ip
motor/transport-ecat.js 网卡子串经 hub 读写
ota/ecat_load.js deviceLink.ecatPost
lab/lan9252_pm.html 灯订阅 hub;open 网卡经 hub
lab/spi_test.html 共享 IP 键(自包含页不深耦合请求层)
js/ble/gatt.js 通知成功后 reportBle(true),失败/断 false

[S3] Out of Scope

  • 不串行化 SPI/CAN/OTA 命令队列
  • 不迁 SharedWorker
  • 不改固件协议
  • 不把 BLE GATT 强行对齐 HTTP/ECAT 请求接口
  • spi_test 保持可整文件删除,不注入业务请求逻辑

Tasks

  • T1: device-link.js Owner+Client + BC 协议 (covers: S2)
  • T2: tabs.html 启动 Owner (covers: S2)
  • T3: OTA connection.js 接入 DeviceLink (covers: S2)
  • T4: LAN9252 灯与 SPI 文案 (covers: S2)
  • T5: BLE 状态上报 (covers: S2)
  • T6: 语法检查 + 评审修复 (covers: S2)
  • T7: Hub 扩展 wifiBaseUrl/ecatPost/adapter API (covers: S2)
  • T8: OTA/CAN/motor/ecat_load/lab 迁到 Hub 端点 (covers: S2)