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();
}
}
}
}