using System.Data;
|
using Aging.Infrastructure.Contracts;
|
using HMI.Core.Util;
|
using log4net;
|
|
namespace Aging.Infrastructure.Services
|
{
|
/// <summary>
|
/// 电源端点信息,描述 Slot 映射到的具体设备通道
|
/// </summary>
|
public sealed class PowerEndpoint
|
{
|
/// <summary>
|
/// 设备标识符
|
/// </summary>
|
public string DeviceId { get; }
|
|
/// <summary>
|
/// 通道标识
|
/// </summary>
|
public int ChannelId { get; }
|
|
/// <summary>
|
/// 生效版本号
|
/// </summary>
|
public string EffectiveVersion { get; }
|
|
/// <summary>
|
/// 初始化电源端点实例
|
/// </summary>
|
/// <param name="deviceId">设备标识符</param>
|
/// <param name="channelId">通道标识</param>
|
/// <param name="effectiveVersion">生效版本号</param>
|
public PowerEndpoint(string deviceId, int channelId, string effectiveVersion)
|
{
|
DeviceId = deviceId ?? throw new ArgumentNullException(nameof(deviceId));
|
ChannelId = channelId;
|
EffectiveVersion = effectiveVersion ?? string.Empty;
|
}
|
|
/// <summary>
|
/// 转换为资源键,用于资源管理器的预约和租约操作
|
/// </summary>
|
/// <returns>对应的资源键实例</returns>
|
public ResourceKey ToResourceKey()
|
{
|
return new ResourceKey(DeviceId, "PowerSupply", ChannelId.ToString());
|
}
|
|
/// <inheritdoc/>
|
public override string ToString() => $"{DeviceId}:CH{ChannelId}(v{EffectiveVersion})";
|
}
|
|
/// <summary>
|
/// Slot-设备-通道映射解析器。
|
/// 从 Plugin.DeviceConfig 的 SQLite 数据库读取 Slot-Device-Channel 映射关系,
|
/// 提供根据 SlotId 和能力类型解析具体设备端点的功能。
|
/// </summary>
|
public sealed class SlotDeviceMappingResolver
|
{
|
private static readonly ILog Log = LogManager.GetLogger(typeof(SlotDeviceMappingResolver));
|
|
/// <summary>
|
/// DeviceConfig 的 SQLite 数据库文件路径
|
/// </summary>
|
private readonly string _deviceConfigDbPath;
|
|
/// <summary>
|
/// 初始化映射解析器实例
|
/// </summary>
|
/// <param name="deviceConfigDbPath">DeviceConfig 的 SQLite 数据库文件路径</param>
|
public SlotDeviceMappingResolver(string deviceConfigDbPath)
|
{
|
_deviceConfigDbPath = deviceConfigDbPath ?? throw new ArgumentNullException(nameof(deviceConfigDbPath));
|
Log.Info($"[SlotDeviceMappingResolver] 初始化完成,数据库路径: {deviceConfigDbPath}");
|
}
|
|
/// <summary>
|
/// 根据 SlotId 和能力类型解析具体的电源端点。
|
/// 从 slot_device_mapping 表查询匹配的最新版本映射记录。
|
/// </summary>
|
/// <param name="slotId">Slot 标识符</param>
|
/// <param name="capability">能力类型(如 "PowerSupply")</param>
|
/// <returns>解析后的电源端点;未找到匹配映射时返回 null</returns>
|
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();
|
}
|
}
|
|
/// <summary>
|
/// 获取数据库中所有的 Slot-设备-通道映射记录
|
/// </summary>
|
/// <returns>所有映射记录的列表</returns>
|
public List<PowerEndpoint> 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<PowerEndpoint>();
|
|
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();
|
}
|
}
|
|
/// <summary>
|
/// 按能力类型筛选映射记录
|
/// </summary>
|
/// <param name="capability">能力类型(如 "PowerSupply"、"CAN" 等)</param>
|
/// <returns>匹配指定能力类型的映射记录列表</returns>
|
public List<PowerEndpoint> 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<PowerEndpoint>();
|
|
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();
|
}
|
}
|
}
|
}
|