From 559890c482f5973f06aafdfec9550fee5ba3c7f2 Mon Sep 17 00:00:00 2001
From: wenxiangchao <wenxiangchao@ihengxin.com.cn>
Date: 星期一, 09 十一月 2026 17:02:15 +0800
Subject: [PATCH] feat: CAN 模拟器 TCP 化 + 多设备并发调试 + 后台生命周期管理
---
CanSimulatorServer/CanSimulatorServer.Core/CanBusManager.cs | 71 +++++++++++++++++++++++++++++++++++
1 files changed, 71 insertions(+), 0 deletions(-)
diff --git a/CanSimulatorServer/CanSimulatorServer.Core/CanBusManager.cs b/CanSimulatorServer/CanSimulatorServer.Core/CanBusManager.cs
new file mode 100644
index 0000000..b599e8d
--- /dev/null
+++ b/CanSimulatorServer/CanSimulatorServer.Core/CanBusManager.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Concurrent;
+using CanSimulator;
+
+namespace CanSimulatorServer
+{
+ /// <summary>
+ /// 鏈嶅姟绔�荤嚎娉ㄥ唽琛細鎸夊悕绉版噿鍒涘缓 CanBusSimulator锛堝鐢ㄨ繘绋嬪唴璺敱/鑷姩鍝嶅簲閫昏緫锛夛紝
+ /// 骞朵互 (bus, nodeIndex) 涓哄叏灞�鍞竴閿徊瑁佽妭鐐规寕杞姐��
+ /// 鎬荤嚎鍦ㄩ娆¤鎸傝浇鏃惰嚜鍔ㄥ惎鍔紙涓庢棫杩涚▼鍐呴┍鍔ㄨ涓轰竴鑷达紱UI 鍚仠鎸夐挳鍙悗缁帴鍏ワ級銆�
+ /// </summary>
+ public sealed class CanBusManager
+ {
+ private readonly ConcurrentDictionary<string, CanBusSimulator> _buses =
+ new(StringComparer.OrdinalIgnoreCase);
+
+ /// <summary>鎸傝浇鑺傜偣锛氬悓 (bus,nodeIndex) 宸茶鍗犵敤鏃惰繑鍥� false锛圢ODE_BUSY 璇箟锛夈��</summary>
+ /// <param name="onFrameReceived">甯у埌杈捐鑺傜偣鏃剁殑鍥炶皟锛堟湇鍔$鐢ㄤ簬 TCP 鎺ㄩ�侊級</param>
+ public bool TryAttach(string busName, int nodeIndex, string clientTag,
+ Action<CanFrame> onFrameReceived, out CanNode? node, out CanBusSimulator? bus)
+ {
+ bus = GetOrCreateBus(busName);
+ string nodeId = NodeIdOf(nodeIndex);
+
+ // 鍞竴鎬т徊瑁侊細宸插瓨鍦ㄥ悓缂栧彿鑺傜偣鍒欐嫆缁�
+ var existing = bus.GetNode(nodeId);
+ if (existing != null)
+ {
+ node = null;
+ return false;
+ }
+
+ var n = bus.RegisterNode(nodeId, $"{busName}/N{nodeIndex}({clientTag})");
+ n.SetPromiscuousMode(); // 鏈嶅姟绔妭鐐归粯璁ゆ敹鎵�鏈夊抚锛堟护娉㈠櫒鍛戒护鍙湪鍏跺悗瑕嗙洊锛�
+ n.Activate();
+ n.FrameReceived += (_, f) => onFrameReceived(f);
+
+ node = n;
+ return true;
+ }
+
+ /// <summary>娉ㄩ攢鑺傜偣锛堣繛鎺ユ柇寮�鏃惰皟鐢級锛岀┖鎬荤嚎淇濈暀锛堝啀娆℃寕杞介浂寮�閿�锛夈��</summary>
+ public void Detach(string busName, CanNode node)
+ {
+ if (_buses.TryGetValue(busName, out var bus))
+ {
+ bus.UnregisterNode(node.NodeId);
+ }
+ }
+
+ public CanBusSimulator? FindBus(string busName)
+ => _buses.TryGetValue(busName, out var b) ? b : null;
+
+ public System.Collections.Generic.IReadOnlyCollection<CanBusSimulator> AllBuses()
+ => (System.Collections.Generic.IReadOnlyCollection<CanBusSimulator>)_buses.Values;
+
+ private CanBusSimulator GetOrCreateBus(string busName)
+ {
+ var bus = _buses.GetOrAdd(busName, name =>
+ {
+ var b = new CanBusSimulator(name);
+ b.Start(); // 鑷姩鍚姩锛歍CP 妯″紡涓嬫�荤嚎鐢熷懡鍛ㄦ湡鐢辨寕杞介┍鍔�
+ return b;
+ });
+ return bus;
+ }
+
+ /// <summary>鑺傜偣鍦ㄦ�荤嚎涓婄殑韬唤锛氫互缂栧彿瀵诲潃锛堜笌鐪熷疄 CAN 鑺傜偣鍦板潃璇箟涓�鑷达級</summary>
+ public static string NodeIdOf(int nodeIndex) => $"{nodeIndex}";
+ }
+}
--
Gitblit v1.9.1