From 9d1660270272180cd71147d6ddd53d1382643d2e Mon Sep 17 00:00:00 2001
From: wenxiangchao <wenxiangchao@ihengxin.com.cn>
Date: 星期一, 02 十一月 2026 18:00:14 +0800
Subject: [PATCH] merge: 并入远程 Initial commit 作为历史根节点

---
 Aging.Infrastructure/Services/SlotDeviceMappingResolver.cs |  218 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 218 insertions(+), 0 deletions(-)

diff --git a/Aging.Infrastructure/Services/SlotDeviceMappingResolver.cs b/Aging.Infrastructure/Services/SlotDeviceMappingResolver.cs
new file mode 100644
index 0000000..15b34cc
--- /dev/null
+++ b/Aging.Infrastructure/Services/SlotDeviceMappingResolver.cs
@@ -0,0 +1,218 @@
+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-璁惧-閫氶亾鏄犲皠瑙f瀽鍣ㄣ��
+    /// 浠� 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>瑙f瀽鍚庣殑鐢垫簮绔偣锛涙湭鎵惧埌鍖归厤鏄犲皠鏃惰繑鍥� 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] 瑙f瀽鏄犲皠: Slot={slotId}, Capability={capability} 鈫� {endpoint}");
+                return endpoint;
+            }
+            catch (Exception ex)
+            {
+                Log.Error($"[SlotDeviceMappingResolver] 瑙f瀽鏄犲皠澶辫触: 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();
+            }
+        }
+    }
+}

--
Gitblit v1.9.1