| New file |
| | |
| | | # CAN 全局应答器 + 硬件调试页多设备并发 — 设计规格 |
| | | |
| | | 日期:2026-11-09 |
| | | 状态:已与用户逐节确认 |
| | | 关联基线:CAN 模拟器 TCP 服务化 + 统一 `CanDeviceDriver`(已完成,47 单测通过) |
| | | |
| | | ## 1. 需求 |
| | | |
| | | 两个独立特性: |
| | | - **特性一(应答器)**:当前"自动响应"仅在"有第二个节点且该节点开了自动响应"时才回复。 |
| | | 用户需要:客户端单独发一条请求,模拟器就能自动回复,无需第二节点。 |
| | | - **特性二(多设备并发调试)**:硬件调试页(DeviceDebug)当前单设备单会话, |
| | | 用户需要同时在多个 Tab 里调试多个 CAN 设备,各自独立会话与维护租约。 |
| | | |
| | | ## 2. 已确认决策 |
| | | |
| | | | 点 | 结论 | |
| | | |---|---| |
| | | | 应答器语义 | 总线级开关,把发送帧回显给发送者(回波),无需第二节点 | |
| | | | 应答内容 | 回显同帧(相同帧ID+数据),来源标记 `RESPONDER` | |
| | | | 应答器开关入口 | 服务窗口每总线一个复选框;并支持命令 `BUS_ECHO:ON/OFF` | |
| | | | 与节点自动响应关系 | 二者独立并存,互不触发、互不干扰,用户按需开启 | |
| | | | 多设备形态 | DeviceDebug 改为 TabControl,每 Tab 一个 `DeviceDebugTab`,各自独立会话 | |
| | | | 一会一设备 | 设备下拉只列未打开设备;已打开则聚焦其 Tab,不重复开会话 | |
| | | | 会话生命周期 | 加入→OpenSession(ReadOnly);关 Tab→CloseSession(经 token 缓存复用正常释放维护租约) | |
| | | | 设备范围 | 通用(CAN/电源/PLC 同结构),主场景多个 CAN;复用 `LoadPanel(kind)` | |
| | | |
| | | ## 3. 特性一设计:总线级应答器 |
| | | |
| | | ### 3.1 CanBusSimulator |
| | | - 新增 `public bool EchoResponderToSender { get; set; }`(默认 false)。 |
| | | - `OnNodeFrameSent` 路由末尾:若 `EchoResponderToSender` 且源节点存在, |
| | | 复制该帧投递回**源节点自身**(`sourceNode.ReceiveFrame(echoCopy)`,直接调用绕过"不回源"), |
| | | 回显帧 `SourceNodeId = "RESPONDER"`,`Timestamp = now`,`FrameId/Data` 同原帧。 |
| | | - 与现有 `SendAutoResponse`(接收节点回复别人)互不影响:应答器面向"发送者回环", |
| | | 节点自动响应面向"接收者答复"。 |
| | | |
| | | ### 3.2 命令与 UI |
| | | - `CanCommandExecutor` 增加 `BUS_ECHO` 查询:`BUS_ECHO:ON|OFF` 设置 `_bus.EchoResponderToSender`; |
| | | 裸 `BUS_ECHO` 查询当前状态,返回 `OK:BUS_ECHO:ON|OFF`。 |
| | | - 服务窗口 `MainWindow` 每总线节点行/工具区加"应答器"复选框,绑定 `CanBusSimulator.EchoResponderToSender`。 |
| | | - 传输/驱动层零改动:命令走既有 `QUERY:` 通道(Local 直发 / Broker 经 RPC 到宿主再转 TCP)。 |
| | | |
| | | ### 3.3 数据流 |
| | | ``` |
| | | 客户端 SEND:0x100:AA → 服务端路由 → (应答器开) 回显帧 EV:RECV:0x100:AA:...:RESPONDER |
| | | → 同一 TCP 连接推送回发送节点 → 客户端 DriverFrameReceived 上屏(来源 RESPONDER) |
| | | ``` |
| | | 无额外轮询;与节点自动响应同用一路事件模型,不产生重复行(来源不同)。 |
| | | |
| | | ## 4. 特性二设计:DeviceDebug 多标签多会话 |
| | | |
| | | ### 4.1 结构 |
| | | ``` |
| | | DeviceDebug(壳) |
| | | ├─ 顶栏:设备下拉(仅未打开设备) + [加入调试] + [关闭当前页] |
| | | └─ TabControl |
| | | └─ DeviceDebugTab × N(新 UserControl,自带独立会话) |
| | | · 绑定自身 CurrentDeviceId / ConnectionState / SessionState / Reservation / CanEnter|ExitMaintenance |
| | | · panelContainer:LoadPanel(kind)(CAN→CanDebugPanel 壳;PowerSupply;PLC) |
| | | · 自身操作日志 |
| | | · 进入/退出维护只作用于本设备会话(sessionId 复用 token,逻辑沿用 DebugSessionManager) |
| | | ``` |
| | | |
| | | ### 4.2 会话与租约 |
| | | - `DebugSessionManager` **不改**:`_activeSessions` 已按 sessionId、`GetActiveSessionByDevice` |
| | | 按设备支持多设备并发会话。 |
| | | - 每 `DeviceDebugTab` 持有一个 sessionId,调用 `OpenSession/RequestMaintenance/ActivateMaintenance/ |
| | | CloseSession`,各自资源键为自身 deviceId → 不同设备租约天然独立、无冲突。 |
| | | - 关闭 Tab 必须 `CloseSession`(正常释放维护租约,杜绝 Token 泄漏型"第二次进维护失败")。 |
| | | - 同设备不可能出现两个 Tab(下拉过滤 + 聚焦既有 Tab 拦截)。 |
| | | |
| | | ### 4.3 迁移与影响面 |
| | | - `DeviceDebug.xaml`:把现"信息栏+维护按钮+panelContainer+操作日志"整体移入 `DeviceDebugTab`; |
| | | DeviceDebug 顶层改为 顶栏 + TabControl。 |
| | | - `DeviceDebug.xaml.cs`:拆分——壳负责设备列表/加入/关闭 Tab 路由; |
| | | 原单会话状态机方法迁入 `DeviceDebugTab.xaml.cs`(每个 Tab 一个实例)。 |
| | | - 对外契约(插件入口 `InitFinish`、`ForceRefreshForTest`)保留在壳上,行为不变。 |
| | | - 现有 CAN 通道事件接收、应答器、Broker 代理均复用,无回退。 |
| | | |
| | | ## 5. 测试策略 |
| | | - 单测(应答器):`SimulatorServerCoreTests` 增例——开 `BUS_ECHO:ON` 后单节点 `SEND` 收到 |
| | | 来源 `RESPONDER` 的回显;关后无回显;与节点自动响应并存时来源区分正确、无重复帧。 |
| | | - 单测(命令):`BUS_ECHO:ON/OFF/查询` 走通 `CanCommandExecutor`;Broker 经 RPC 亦生效。 |
| | | - DeviceDebug 多会话为 UI 重构,以 MSBuild 编译 + 手动验收覆盖: |
| | | 同时开 CAN-001/002/003 三个 Tab,各自进入维护互不阻塞;关闭某 Tab 后其设备可再次进入维护 |
| | | (证明租约正确释放);应答器开启后任一 Tab 单独发帧即收到回显 RX。 |
| | | - 回归:现有 47 单测保持全绿。 |
| | | |
| | | ## 6. 构建与约束 |
| | | - 沿用 VS 完整版 MSBuild 编译 WPF 链路(不加 /p:Platform=x64); |
| | | 服务端核心可用 dotnet。 |
| | | - 不引入新外部依赖;应答器仅在 CanSimulator 库与执行器内扩展,Broker/驱动层不动。 |