using DeviceCommand.Base; using Logger; using Model.Models; using Prism.Ioc; using System; using System.Collections.Generic; using System.IO.Ports; using System.Linq; using System.Reflection; using UIShare.UIViewModel; namespace UIShare.GlobalVariable { /// /// 设备管理器:根据 反射实例化所有启用的设备, /// 通过 多态统一管理,避免为每种设备单独硬编码字段。 /// public class DeviceManager { public SystemConfig _systemConfig { get; set; } /// 按 DeviceName 索引的设备字典,便于业务层按名取实例。 public IDictionary DeviceMap { get; private set; } = new Dictionary(StringComparer.OrdinalIgnoreCase); /// 类名 → Type 的反射缓存(仅扫描一次)。 private static readonly IReadOnlyDictionary _deviceTypeMap = BuildDeviceTypeMap(); public DeviceManager(SystemConfig systemConfig) { _systemConfig = systemConfig; InitDevices(); } private void InitDevices() { DeviceMap = new Dictionary(StringComparer.OrdinalIgnoreCase); if (_systemConfig?.DeviceList == null) return; foreach (var config in _systemConfig.DeviceList) { if (config == null || !config.IsEnabled) continue; if (string.IsNullOrWhiteSpace(config.DeviceType) || !_deviceTypeMap.TryGetValue(config.DeviceType, out var deviceType)) { LoggerHelper.Warn($"未识别的设备类型 [{config.DeviceType}],已跳过 [{config.DeviceName}]。"); continue; } try { IBaseInterface? instance = config.ConnectionType switch { "Tcp" => CreateTcpDevice(deviceType, config.TcpConfig), "Serial" => CreateSerialDevice(deviceType, config.SerialPortConfig), _ => null }; if (instance == null) { LoggerHelper.Warn($"设备 [{config.DeviceName}] 连接方式 [{config.ConnectionType}] 不支持,已跳过。"); continue; } if (!string.IsNullOrWhiteSpace(config.DeviceName)) { DeviceMap[config.DeviceName] = instance; } LoggerHelper.Info($"已加载设备 [{config.DeviceName} / {config.DeviceType} / {config.ConnectionType}]"); } catch (Exception ex) { var inner = ex.InnerException?.Message ?? ex.Message; LoggerHelper.ErrorWithNotify($"设备 [{config.DeviceName}] 实例化失败:{inner}"); } } } public async Task ConnectAllDevices(CancellationToken ct = default) { if (_systemConfig?.DeviceList == null || DeviceMap.Count == 0) return; var tasks = new List(); foreach (var info in _systemConfig.DeviceList) { if (info == null || !info.IsEnabled) continue; if (string.IsNullOrWhiteSpace(info.DeviceName)) continue; if (!DeviceMap.TryGetValue(info.DeviceName, out var device)) continue; tasks.Add(ConnectInternalAsync(info, device, ct)); } await Task.WhenAll(tasks); } public async Task ConnectSpecifiedDevice(string deviceName, CancellationToken ct = default) { if (string.IsNullOrWhiteSpace(deviceName)) { LoggerHelper.Warn("ConnectSpecifiedDevice:设备名为空。"); return; } if (!DeviceMap.TryGetValue(deviceName, out var device)) { LoggerHelper.Warn($"ConnectSpecifiedDevice:未找到设备 [{deviceName}]。"); return; } var info = _systemConfig?.DeviceList? .FirstOrDefault(d => d != null && string.Equals(d.DeviceName, deviceName, StringComparison.OrdinalIgnoreCase)); await ConnectInternalAsync(info, device, ct); } private async Task ConnectInternalAsync(DeviceInfoVM? info, IBaseInterface device, CancellationToken ct) { string name = info?.DeviceName ?? device.GetType().Name; string conn = info?.ConnectionType ?? "?"; try { if (device.IsConnected) { if (info != null) info.IsConnected = true; LoggerHelper.Info($"设备 [{name}] 已连接,跳过。"); return; } bool ok = conn switch { "Tcp" => await ConnectTcpAsync(name, device, ct), "Serial" => await ConnectSerialAsync(name, device, ct), _ => false }; if (info != null) info.IsConnected = ok; if (ok) LoggerHelper.Info($"设备 [{name}/{conn}] 连接成功。"); else LoggerHelper.Warn($"设备 [{name}/{conn}] 连接失败。"); } catch (OperationCanceledException) { if (info != null) info.IsConnected = false; LoggerHelper.Warn($"设备 [{name}/{conn}] 连接已取消。"); } catch (Exception ex) { if (info != null) info.IsConnected = false; var inner = ex.InnerException?.Message ?? ex.Message; LoggerHelper.ErrorWithNotify($"设备 [{name}/{conn}] 连接异常:{inner}"); } } private static async Task ConnectTcpAsync(string name, IBaseInterface device, CancellationToken ct) { if (device is not ITcp tcp) { LoggerHelper.Warn($"设备 [{name}] 配置为 Tcp 但未实现 ITcp,实际类型为 {device.GetType().Name}。"); return false; } return await tcp.ConnectAsync(ct); } private static async Task ConnectSerialAsync(string name, IBaseInterface device, CancellationToken ct) { if (device is not ISerialPort sp) { LoggerHelper.Warn($"设备 [{name}] 配置为 Serial 但未实现 ISerialPort,实际类型为 {device.GetType().Name}。"); return false; } return await sp.ConnectAsync(ct); } #region 辅助方法 private static IReadOnlyDictionary BuildDeviceTypeMap() { try { return typeof(IBaseInterface).Assembly .GetTypes() .Where(t => t.IsClass && !t.IsAbstract && typeof(IBaseInterface).IsAssignableFrom(t)) .ToDictionary(t => t.Name, t => t, StringComparer.OrdinalIgnoreCase); } catch (ReflectionTypeLoadException ex) { LoggerHelper.Error($"扫描设备类型失败:{ex.Message}"); return new Dictionary(StringComparer.OrdinalIgnoreCase); } } private static IBaseInterface? CreateTcpDevice(Type type, TcpConfigVM? vm) { vm ??= new TcpConfigVM(); var cfg = new TcpConfig { IPAddress = vm.IPAddress, Port = vm.Port, SendTimeout = vm.SendTimeout, ReceiveTimeout = vm.ReceiveTimeout }; return Activator.CreateInstance(type, cfg) as IBaseInterface; } private static IBaseInterface? CreateSerialDevice(Type type, SerialPortConfigVM? vm) { vm ??= new SerialPortConfigVM(); var cfg = new SerialPortConfig { PortName = vm.PortName, BaudRate = vm.BaudRate, DataBits = vm.DataBits, StopBits = Enum.TryParse(vm.StopBits, true, out var sb) ? sb : StopBits.One, Parity = Enum.TryParse(vm.Parity, true, out var pa) ? pa : Parity.None, ReadTimeout = vm.ReadTimeout, WriteTimeout = vm.WriteTimeout }; return Activator.CreateInstance(type, cfg) as IBaseInterface; } #endregion } }