设备数量不对等适配

This commit is contained in:
hsc
2026-06-22 17:22:21 +08:00
parent cba9af2892
commit 1faae12822
2 changed files with 55 additions and 8 deletions

View File

@@ -19,6 +19,7 @@ namespace UIShare.GlobalVariable
{ {
private object _lockObj = new object(); private object _lockObj = new object();
public SystemConfig _systemConfig { get; set; } public SystemConfig _systemConfig { get; set; }
private readonly GlobalInfo _globalInfo;
/// <summary>按 DeviceName 索引的设备字典,便于业务层按名取实例。</summary> /// <summary>按 DeviceName 索引的设备字典,便于业务层按名取实例。</summary>
public IDictionary<string, IBaseInterface> DeviceMap { get; private set; } public IDictionary<string, IBaseInterface> DeviceMap { get; private set; }
@@ -27,11 +28,33 @@ namespace UIShare.GlobalVariable
/// <summary>类名 → Type 的反射缓存(仅扫描一次)。</summary> /// <summary>类名 → Type 的反射缓存(仅扫描一次)。</summary>
private static readonly IReadOnlyDictionary<string, Type> _deviceTypeMap = BuildDeviceTypeMap(); private static readonly IReadOnlyDictionary<string, Type> _deviceTypeMap = BuildDeviceTypeMap();
public DeviceManager(SystemConfig systemConfig) public DeviceManager(SystemConfig systemConfig, GlobalInfo globalInfo)
{ {
_systemConfig = systemConfig; _systemConfig = systemConfig;
_globalInfo = globalInfo;
InitDevices(); InitDevices();
} }
/// <summary>
/// 根据设备配置提取唯一的硬件指纹字符串。
/// <para>Tcp → "Tcp:IP:Port"Serial → "Serial:PortName";无法识别则返回空字符串。</para>
/// </summary>
private static string ExtractHardwareFingerprint(DeviceInfoVM config)
{
if (string.Equals(config.ConnectionType, "Tcp", StringComparison.OrdinalIgnoreCase)
&& config.TcpConfig != null)
{
return $"Tcp:{config.TcpConfig.IPAddress}:{config.TcpConfig.Port}";
}
if (string.Equals(config.ConnectionType, "Serial", StringComparison.OrdinalIgnoreCase)
&& config.SerialPortConfig != null)
{
return $"Serial:{config.SerialPortConfig.PortName}";
}
return string.Empty;
}
private void InitDevices() private void InitDevices()
{ {
DeviceMap = new Dictionary<string, IBaseInterface>(StringComparer.OrdinalIgnoreCase); DeviceMap = new Dictionary<string, IBaseInterface>(StringComparer.OrdinalIgnoreCase);
@@ -51,24 +74,41 @@ namespace UIShare.GlobalVariable
try try
{ {
IBaseInterface? instance = config.ConnectionType switch // 第一步:提取硬件指纹,为空则跳过
var fingerprint = ExtractHardwareFingerprint(config);
if (string.IsNullOrEmpty(fingerprint))
{ {
"Tcp" => CreateTcpDevice(deviceType, config.TcpConfig), LoggerHelper.Warn($"设备 [{config.DeviceName}] 无法提取硬件指纹(连接方式={config.ConnectionType}),已跳过。");
"Serial" => CreateSerialDevice(deviceType, config.SerialPortConfig), continue;
_ => null }
// 第二步:原子化获取或添加 Lazy 包装盒,确保同一指纹全局只创建一个实例
var lazy = _globalInfo.HardwarePool.GetOrAdd(fingerprint, key => new Lazy<IBaseInterface>(() =>
{
return config.ConnectionType switch
{
"Tcp" => CreateTcpDevice(deviceType, config.TcpConfig)!,
"Serial" => CreateSerialDevice(deviceType, config.SerialPortConfig)!,
_ => null!
}; };
}));
// 第三步安全拆盒Lazy 内部线程锁保证只实例化一次
var instance = lazy.Value;
if (instance == null) if (instance == null)
{ {
LoggerHelper.Warn($"设备 [{config.DeviceName}] 连接方式 [{config.ConnectionType}] 不支持,已跳过。"); LoggerHelper.Warn($"设备 [{config.DeviceName}] 连接方式 [{config.ConnectionType}] 不支持,已跳过。");
continue; continue;
} }
// 第四步:绑定逻辑名 → 同一物理设备可被多个台架名称映射
if (!string.IsNullOrWhiteSpace(config.DeviceName)) if (!string.IsNullOrWhiteSpace(config.DeviceName))
{ {
DeviceMap[config.DeviceName] = instance; DeviceMap[config.DeviceName] = instance;
} }
LoggerHelper.Info($"已加载设备 [{config.DeviceName} / {config.DeviceType} / {config.ConnectionType}]"); LoggerHelper.Info($"已加载设备 [{config.DeviceName} / {config.DeviceType} / {config.ConnectionType}] 指纹={fingerprint}");
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -1,4 +1,6 @@
using System; using DeviceCommand.Base;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@@ -13,6 +15,10 @@ namespace UIShare.GlobalVariable
public Dictionary<string,StepRunning> StepRunningDic { get; set; } public Dictionary<string,StepRunning> StepRunningDic { get; set; }
public Dictionary<string, SystemConfig> ConfigDic { get; set; } public Dictionary<string, SystemConfig> ConfigDic { get; set; }
public Dictionary<string, IScopedProvider> ScopeDic { get; set; } public Dictionary<string, IScopedProvider> ScopeDic { get; set; }
/// <summary>硬件指纹 → 设备实例的并发池,确保同一物理硬件全局只创建一个驱动实例。</summary>
public ConcurrentDictionary<string, Lazy<IBaseInterface>> HardwarePool { get; set; }
public String UserName { get; set; } = "Not Logged in"; public String UserName { get; set; } = "Not Logged in";
public bool IsAdmin { get; set; } = true; public bool IsAdmin { get; set; } = true;
public string CurrentOpeningScope; public string CurrentOpeningScope;
@@ -35,6 +41,7 @@ namespace UIShare.GlobalVariable
StepRunningDic = new(); StepRunningDic = new();
ConfigDic = new(); ConfigDic = new();
ScopeDic = new(); ScopeDic = new();
HardwarePool = new ConcurrentDictionary<string, Lazy<IBaseInterface>>(StringComparer.OrdinalIgnoreCase);
CurrentScope = "default"; CurrentScope = "default";
} }