using System.Data; using Aging.Infrastructure.Contracts; using HMI.Core.Util; using log4net; namespace Aging.Infrastructure.Services { /// /// 电源端点信息,描述 Slot 映射到的具体设备通道 /// public sealed class PowerEndpoint { /// /// 设备标识符 /// public string DeviceId { get; } /// /// 通道标识 /// public int ChannelId { get; } /// /// 生效版本号 /// public string EffectiveVersion { get; } /// /// 初始化电源端点实例 /// /// 设备标识符 /// 通道标识 /// 生效版本号 public PowerEndpoint(string deviceId, int channelId, string effectiveVersion) { DeviceId = deviceId ?? throw new ArgumentNullException(nameof(deviceId)); ChannelId = channelId; EffectiveVersion = effectiveVersion ?? string.Empty; } /// /// 转换为资源键,用于资源管理器的预约和租约操作 /// /// 对应的资源键实例 public ResourceKey ToResourceKey() { return new ResourceKey(DeviceId, "PowerSupply", ChannelId.ToString()); } /// public override string ToString() => $"{DeviceId}:CH{ChannelId}(v{EffectiveVersion})"; } /// /// Slot-设备-通道映射解析器。 /// 从 Plugin.DeviceConfig 的 SQLite 数据库读取 Slot-Device-Channel 映射关系, /// 提供根据 SlotId 和能力类型解析具体设备端点的功能。 /// public sealed class SlotDeviceMappingResolver { private static readonly ILog Log = LogManager.GetLogger(typeof(SlotDeviceMappingResolver)); /// /// DeviceConfig 的 SQLite 数据库文件路径 /// private readonly string _deviceConfigDbPath; /// /// 初始化映射解析器实例 /// /// DeviceConfig 的 SQLite 数据库文件路径 public SlotDeviceMappingResolver(string deviceConfigDbPath) { _deviceConfigDbPath = deviceConfigDbPath ?? throw new ArgumentNullException(nameof(deviceConfigDbPath)); Log.Info($"[SlotDeviceMappingResolver] 初始化完成,数据库路径: {deviceConfigDbPath}"); } /// /// 根据 SlotId 和能力类型解析具体的电源端点。 /// 从 slot_device_mapping 表查询匹配的最新版本映射记录。 /// /// Slot 标识符 /// 能力类型(如 "PowerSupply") /// 解析后的电源端点;未找到匹配映射时返回 null public PowerEndpoint? ResolveEndpoint(string slotId, string capability) { if (string.IsNullOrWhiteSpace(slotId)) throw new ArgumentException("SlotId 不能为空", nameof(slotId)); if (string.IsNullOrWhiteSpace(capability)) throw new ArgumentException("能力类型不能为空", nameof(capability)); SqliteHelper? sqliteHelper = null; try { sqliteHelper = new SqliteHelper(_deviceConfigDbPath); var sql = $"SELECT slot_id, capability, version, device_id, channel_id, mapping_version " + $"FROM slot_device_mapping " + $"WHERE slot_id = '{slotId}' AND capability = '{capability}' " + $"ORDER BY mapping_version DESC LIMIT 1"; var dataTable = sqliteHelper.GetDataTable(sql); if (dataTable.Rows.Count == 0) { Log.Warn($"[SlotDeviceMappingResolver] 未找到 Slot={slotId}, Capability={capability} 的映射记录"); return null; } var row = dataTable.Rows[0]; var deviceId = row["device_id"]?.ToString() ?? string.Empty; var channelId = Convert.ToInt32(row["channel_id"]); var effectiveVersion = row["mapping_version"]?.ToString() ?? string.Empty; var endpoint = new PowerEndpoint(deviceId, channelId, effectiveVersion); Log.Info($"[SlotDeviceMappingResolver] 解析映射: Slot={slotId}, Capability={capability} → {endpoint}"); return endpoint; } catch (Exception ex) { Log.Error($"[SlotDeviceMappingResolver] 解析映射失败: Slot={slotId}, Capability={capability}, 错误: {ex.Message}", ex); throw; } finally { sqliteHelper?.Close(); } } /// /// 获取数据库中所有的 Slot-设备-通道映射记录 /// /// 所有映射记录的列表 public List GetAllMappings() { SqliteHelper? sqliteHelper = null; try { sqliteHelper = new SqliteHelper(_deviceConfigDbPath); var sql = "SELECT slot_id, capability, version, device_id, channel_id, mapping_version " + "FROM slot_device_mapping " + "ORDER BY slot_id, capability, mapping_version DESC"; var dataTable = sqliteHelper.GetDataTable(sql); var results = new List(); foreach (DataRow row in dataTable.Rows) { var deviceId = row["device_id"]?.ToString() ?? string.Empty; var channelId = Convert.ToInt32(row["channel_id"]); var effectiveVersion = row["mapping_version"]?.ToString() ?? string.Empty; results.Add(new PowerEndpoint(deviceId, channelId, effectiveVersion)); } Log.Info($"[SlotDeviceMappingResolver] 获取全部映射记录,共 {results.Count} 条"); return results; } catch (Exception ex) { Log.Error($"[SlotDeviceMappingResolver] 获取全部映射记录失败: {ex.Message}", ex); throw; } finally { sqliteHelper?.Close(); } } /// /// 按能力类型筛选映射记录 /// /// 能力类型(如 "PowerSupply"、"CAN" 等) /// 匹配指定能力类型的映射记录列表 public List GetMappingsByCapability(string capability) { if (string.IsNullOrWhiteSpace(capability)) throw new ArgumentException("能力类型不能为空", nameof(capability)); SqliteHelper? sqliteHelper = null; try { sqliteHelper = new SqliteHelper(_deviceConfigDbPath); var sql = $"SELECT slot_id, capability, version, device_id, channel_id, mapping_version " + $"FROM slot_device_mapping " + $"WHERE capability = '{capability}' " + $"ORDER BY slot_id, mapping_version DESC"; var dataTable = sqliteHelper.GetDataTable(sql); var results = new List(); foreach (DataRow row in dataTable.Rows) { var deviceId = row["device_id"]?.ToString() ?? string.Empty; var channelId = Convert.ToInt32(row["channel_id"]); var effectiveVersion = row["mapping_version"]?.ToString() ?? string.Empty; results.Add(new PowerEndpoint(deviceId, channelId, effectiveVersion)); } Log.Info($"[SlotDeviceMappingResolver] 按能力类型 {capability} 筛选映射记录,共 {results.Count} 条"); return results; } catch (Exception ex) { Log.Error($"[SlotDeviceMappingResolver] 按能力类型筛选映射记录失败: {ex.Message}", ex); throw; } finally { sqliteHelper?.Close(); } } } }