CAN驱动修改优化
This commit is contained in:
@@ -13,7 +13,6 @@ using System.Reflection;
|
||||
using TSMasterCAN;
|
||||
using UIShare.PubEvent;
|
||||
using UIShare.UIViewModel;
|
||||
using TSMasterCAN;
|
||||
|
||||
namespace UIShare.GlobalVariable
|
||||
{
|
||||
@@ -25,6 +24,7 @@ namespace UIShare.GlobalVariable
|
||||
{
|
||||
private object _lockObj = new object();
|
||||
public SystemConfig _systemConfig { get; set; }
|
||||
public CANMonitoringService _CANMonitoringService { get; set; }
|
||||
private readonly GlobalInfo _globalInfo;
|
||||
private readonly string _scopeName;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
@@ -35,7 +35,6 @@ namespace UIShare.GlobalVariable
|
||||
|
||||
/// <summary>类名 → Type 的反射缓存(仅扫描一次)。</summary>
|
||||
private static readonly IReadOnlyDictionary<string, Type> _deviceTypeMap = BuildDeviceTypeMap();
|
||||
public CAN CANFD { get; set; }
|
||||
public IOBoardGroup IOGroup { get; set; }
|
||||
|
||||
public DeviceManager(SystemConfig systemConfig, GlobalInfo globalInfo, IEventAggregator eventAggregator)
|
||||
@@ -43,11 +42,17 @@ namespace UIShare.GlobalVariable
|
||||
_systemConfig = systemConfig;
|
||||
_globalInfo = globalInfo;
|
||||
_eventAggregator = eventAggregator;
|
||||
_CANMonitoringService=new CANMonitoringService(_systemConfig);
|
||||
// 用 SystemConfig.Title 作为作用域唯一标识,无需反查 ConfigDic
|
||||
_scopeName = _systemConfig.Title;
|
||||
InitDevices();
|
||||
InitCAN();
|
||||
}
|
||||
|
||||
public void InitCAN()
|
||||
{
|
||||
var re1 = _CANMonitoringService.Init();
|
||||
}
|
||||
/// <summary>
|
||||
/// 根据设备配置提取唯一的硬件指纹字符串。
|
||||
/// <para>Tcp → "Tcp:IP:Port";Serial → "Serial:PortName";无法识别则返回空字符串。</para>
|
||||
@@ -98,55 +103,6 @@ namespace UIShare.GlobalVariable
|
||||
{
|
||||
if (config == null || !config.IsEnabled) continue;
|
||||
|
||||
// CAN 设备:ZLGCANFD 不实现 IBaseInterface,通过 SystemConfig.CANFD 单独管理,
|
||||
// 按指纹从全局 CanPool 创建/复用实例,并注册作用域引用计数。
|
||||
if (string.Equals(config.ConnectionType, "CAN", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var fingerprint = ExtractHardwareFingerprint(config);
|
||||
if (string.IsNullOrEmpty(fingerprint))
|
||||
{
|
||||
LoggerHelper.Warn($"设备 [{config.DeviceName}] 无法提取硬件指纹(连接方式={config.ConnectionType}),已跳过。");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (config.CANConfig == null)
|
||||
{
|
||||
LoggerHelper.Warn($"设备 [{config.DeviceName}] 缺少 CAN 连接参数,已跳过。");
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// 按指纹全局唯一创建同星 CAN 实例(maxChannels 默认 4,对应 USBCANFD-400U)
|
||||
// 波特率与终端电阻从 CANConfigVM 传入,初始化并启动通道 时直接使用
|
||||
var canLazy = _globalInfo.CanPool.GetOrAdd(fingerprint, key => new Lazy<CAN>(() =>
|
||||
new CAN(config.CANConfig.DeviceType, config.CANConfig.DeviceIndex, 4,
|
||||
config.CANConfig.ABitBaud, config.CANConfig.DBitBaud, config.CANConfig.EnableTerminalResistance)));
|
||||
|
||||
_systemConfig.CANFD = canLazy.Value;
|
||||
CANFD = canLazy.Value;
|
||||
|
||||
// 注册作用域引用计数
|
||||
if (!string.IsNullOrEmpty(_scopeName))
|
||||
{
|
||||
var scopeList = _globalInfo.DeviceAndScopeDic.GetOrAdd(fingerprint,
|
||||
_ => new Lazy<List<string>>(() => new List<string>())).Value;
|
||||
lock (scopeList)
|
||||
{
|
||||
if (!scopeList.Contains(_scopeName))
|
||||
scopeList.Add(_scopeName);
|
||||
}
|
||||
}
|
||||
|
||||
LoggerHelper.Info($"已加载 CAN 设备 [{config.DeviceName}] 指纹={fingerprint}(通过 SystemConfig.CANFD 管理)");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify(_scopeName, $"CAN 设备 [{config.DeviceName}] 实例化失败:{ex.Message}");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(config.DeviceType) ||
|
||||
!_deviceTypeMap.TryGetValue(config.DeviceType, out var deviceType))
|
||||
{
|
||||
@@ -302,7 +258,7 @@ namespace UIShare.GlobalVariable
|
||||
// CAN 设备:直接关闭 CAN 卡
|
||||
if (info != null && string.Equals(info.ConnectionType, "CAN", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await CloseCanAsync(info);
|
||||
CloseCan();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -325,7 +281,7 @@ namespace UIShare.GlobalVariable
|
||||
|
||||
lock (_lockObj)
|
||||
{
|
||||
if (DeviceMap.Count == 0 && (CANFD == null)) return;
|
||||
if (DeviceMap.Count == 0 ) return;
|
||||
|
||||
foreach (var kvp in DeviceMap)
|
||||
{
|
||||
@@ -338,17 +294,7 @@ namespace UIShare.GlobalVariable
|
||||
}
|
||||
}
|
||||
|
||||
// CAN 设备:直接关闭 CAN 卡
|
||||
if (CANFD != null)
|
||||
{
|
||||
var canInfo = _systemConfig?.DeviceList?
|
||||
.FirstOrDefault(d => d != null && string.Equals(d.ConnectionType, "CAN", StringComparison.OrdinalIgnoreCase));
|
||||
if (canInfo != null)
|
||||
{
|
||||
tasks.Add(CloseCanAsync(canInfo));
|
||||
}
|
||||
}
|
||||
|
||||
CAN.DisConnect();
|
||||
await Task.WhenAll(tasks);
|
||||
LoggerHelper.Info("所有设备已执行关闭操作。");
|
||||
}
|
||||
@@ -456,26 +402,11 @@ namespace UIShare.GlobalVariable
|
||||
/// </summary>
|
||||
private async Task<bool> ConnectCanAsync(DeviceInfoVM info)
|
||||
{
|
||||
string name = info.DeviceName ?? "CAN";
|
||||
|
||||
try
|
||||
{
|
||||
if (CANFD == null)
|
||||
{
|
||||
LoggerHelper.Warn($"CAN 设备 [{name}] 尚未实例化,无法连接。");
|
||||
info.IsConnected = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (info.IsConnected)
|
||||
{
|
||||
LoggerHelper.Info($"CAN 设备 [{name}] 已连接,跳过。");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ok = await Task.Run(() =>
|
||||
{
|
||||
if (!CANFD.打开设备()) return false;
|
||||
// 自动加载 DBC 文件
|
||||
if (_systemConfig?.DBCAutoLoadList != null)
|
||||
{
|
||||
@@ -495,8 +426,7 @@ namespace UIShare.GlobalVariable
|
||||
LoggerHelper.Warn($"CAN 通道 {item.DBCChannel} 自动加载 DBC 失败:文件不存在 [{item.DBCFilePath}]");
|
||||
continue;
|
||||
}
|
||||
CANFD.初始化并启动通道((uint)item.DBCChannel);
|
||||
bool loadOk = CANFD.加载通道DBC文件((uint)item.DBCChannel, item.DBCFilePath);
|
||||
bool loadOk = CAN.LoadDBC(item.DBCFilePath,new int[] { item.DBCChannel },out _ )==0;
|
||||
if (loadOk)
|
||||
{
|
||||
LoggerHelper.Info($"CAN 通道 {item.DBCChannel} 已自动加载 DBC:{item.DBCFilePath}");
|
||||
@@ -518,16 +448,16 @@ namespace UIShare.GlobalVariable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CAN.Connect() != 0) return false;
|
||||
return true;
|
||||
});
|
||||
|
||||
info.IsConnected = ok;
|
||||
|
||||
if (ok)
|
||||
LoggerHelper.Info($"CAN 设备 [{name}] 连接成功,已初始化 {CANFD.DBCParser.MaxChannels} 个通道。");
|
||||
LoggerHelper.Info($"CAN 设备 连接成功");
|
||||
else
|
||||
LoggerHelper.Warn($"CAN 设备 [{name}] 连接失败。");
|
||||
LoggerHelper.Warn($"CAN 设备连接失败。");
|
||||
|
||||
return ok;
|
||||
}
|
||||
@@ -535,7 +465,7 @@ namespace UIShare.GlobalVariable
|
||||
{
|
||||
info.IsConnected = false;
|
||||
var inner = ex.InnerException?.Message ?? ex.Message;
|
||||
LoggerHelper.ErrorWithNotify(_scopeName, $"CAN 设备 [{name}] 连接异常:{inner}");
|
||||
LoggerHelper.ErrorWithNotify(_scopeName, $"CAN 设备 连接异常:{inner}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -543,36 +473,9 @@ namespace UIShare.GlobalVariable
|
||||
/// <summary>
|
||||
/// 关闭 CAN 卡
|
||||
/// </summary>
|
||||
private async Task CloseCanAsync(DeviceInfoVM info)
|
||||
private void CloseCan()
|
||||
{
|
||||
string name = info.DeviceName ?? "CAN";
|
||||
|
||||
try
|
||||
{
|
||||
if (CANFD == null)
|
||||
{
|
||||
info.IsConnected = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info.IsConnected)
|
||||
{
|
||||
LoggerHelper.Info($"CAN 设备 [{name}] 本就处于断开状态。");
|
||||
return;
|
||||
}
|
||||
|
||||
await Task.Run(() => CANFD.关闭CAN卡设备());
|
||||
LoggerHelper.Info($"CAN 设备 [{name}] 已成功关闭连接。");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var inner = ex.InnerException?.Message ?? ex.Message;
|
||||
LoggerHelper.Error($"CAN 设备 [{name}] 关闭连接时出现异常: {inner}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
info.IsConnected = false;
|
||||
}
|
||||
CAN.DisConnect();
|
||||
}
|
||||
|
||||
private static IReadOnlyDictionary<string, Type> BuildDeviceTypeMap()
|
||||
@@ -620,6 +523,9 @@ namespace UIShare.GlobalVariable
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// 停止 CAN 信号监测服务
|
||||
_CANMonitoringService?.Stop();
|
||||
|
||||
if (string.IsNullOrEmpty(_scopeName)) return;
|
||||
|
||||
// 遍历当前作用域用到的所有指纹,逐一移除本作用域的引用
|
||||
@@ -655,16 +561,6 @@ namespace UIShare.GlobalVariable
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试从 CanPool 取出并销毁
|
||||
if (_globalInfo.CanPool.TryRemove(fingerprint, out var canLazy))
|
||||
{
|
||||
if (canLazy.IsValueCreated)
|
||||
{
|
||||
try { canLazy.Value.Dispose(); }
|
||||
catch { /* 销毁时忽略异常 */ }
|
||||
LoggerHelper.Info($"指纹 [{fingerprint}] 无作用域引用,已销毁 CAN 设备实例。");
|
||||
}
|
||||
}
|
||||
|
||||
// 同步清除 DeviceAndScopeDic 中的空条目
|
||||
_globalInfo.DeviceAndScopeDic.TryRemove(fingerprint, out _);
|
||||
|
||||
Reference in New Issue
Block a user