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/Core/DeviceManager.cs |  226 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 226 insertions(+), 0 deletions(-)

diff --git a/Aging.Infrastructure/Core/DeviceManager.cs b/Aging.Infrastructure/Core/DeviceManager.cs
new file mode 100644
index 0000000..7622a94
--- /dev/null
+++ b/Aging.Infrastructure/Core/DeviceManager.cs
@@ -0,0 +1,226 @@
+using System.Collections.Concurrent;
+using Aging.Infrastructure.Contracts;
+using log4net;
+
+namespace Aging.Infrastructure.Core
+{
+    /// <summary>
+    /// 璁惧绠$悊瀹炵幇銆�
+    /// 鎻愪緵璁惧椹卞姩鐨勬敞鍐屻�佽繛鎺ョ鐞嗗拰鐘舵�佹煡璇㈠姛鑳姐��
+    /// 浣跨敤 ConcurrentDictionary 绠$悊椹卞姩瀹炰緥鍜岀紦瀛樼姸鎬併��
+    /// </summary>
+    public sealed class DeviceManager : IDeviceManager
+    {
+        private static readonly ILog Log = LogManager.GetLogger(typeof(DeviceManager));
+
+        /// <summary>
+        /// 璁惧椹卞姩瀛楀吀锛坘ey = deviceId锛�
+        /// </summary>
+        private readonly ConcurrentDictionary<string, IDeviceDriver> _drivers = new();
+
+        /// <summary>
+        /// 璁惧鐘舵�佺紦瀛樺瓧鍏革紙key = deviceId锛�
+        /// </summary>
+        private readonly ConcurrentDictionary<string, DeviceDriverStatus> _statusCache = new();
+
+        /// <inheritdoc/>
+        public void RegisterDriver(string deviceId, IDeviceDriver driver)
+        {
+            if (string.IsNullOrWhiteSpace(deviceId))
+                throw new ArgumentException("璁惧ID涓嶈兘涓虹┖", nameof(deviceId));
+            if (driver == null) throw new ArgumentNullException(nameof(driver));
+
+            if (_drivers.ContainsKey(deviceId))
+            {
+                Log.Warn($"[DeviceManager] 璁惧 {deviceId} 宸叉敞鍐岋紝灏嗚鐩栫幇鏈夐┍鍔�");
+                UnregisterDriver(deviceId);
+            }
+
+            _drivers[deviceId] = driver;
+
+            // 鍒濆鍖栫姸鎬佺紦瀛�
+            var initialStatus = driver.GetStatus();
+            _statusCache[deviceId] = initialStatus;
+
+            // 璁㈤槄杩炴帴鐘舵�佸彉鍖栦簨浠�
+            driver.ConnectionChanged += OnConnectionChanged;
+
+            Log.Info($"[DeviceManager] 璁惧 {deviceId} 椹卞姩娉ㄥ唽鎴愬姛锛屽綋鍓嶈繛鎺ョ姸鎬�: {initialStatus.IsConnected}");
+        }
+
+        /// <inheritdoc/>
+        public void UnregisterDriver(string deviceId)
+        {
+            if (string.IsNullOrWhiteSpace(deviceId))
+                throw new ArgumentException("璁惧ID涓嶈兘涓虹┖", nameof(deviceId));
+
+            if (_drivers.TryRemove(deviceId, out var driver))
+            {
+                // 鍙栨秷浜嬩欢璁㈤槄
+                driver.ConnectionChanged -= OnConnectionChanged;
+
+                // 娓呯悊鐘舵�佺紦瀛�
+                _statusCache.TryRemove(deviceId, out _);
+
+                Log.Info($"[DeviceManager] 璁惧 {deviceId} 椹卞姩宸叉敞閿�");
+            }
+            else
+            {
+                Log.Warn($"[DeviceManager] 灏濊瘯娉ㄩ攢涓嶅瓨鍦ㄧ殑璁惧: {deviceId}");
+            }
+        }
+
+        /// <inheritdoc/>
+        public IDeviceDriver? GetDriver(string deviceId)
+        {
+            if (string.IsNullOrWhiteSpace(deviceId))
+                throw new ArgumentException("璁惧ID涓嶈兘涓虹┖", nameof(deviceId));
+
+            _drivers.TryGetValue(deviceId, out var driver);
+            return driver;
+        }
+
+        /// <inheritdoc/>
+        public DeviceDriverStatus GetStatus(string deviceId)
+        {
+            if (string.IsNullOrWhiteSpace(deviceId))
+                throw new ArgumentException("璁惧ID涓嶈兘涓虹┖", nameof(deviceId));
+
+            if (_statusCache.TryGetValue(deviceId, out var status))
+            {
+                return status;
+            }
+
+            // 濡傛灉缂撳瓨涓病鏈夛紝杩斿洖榛樿鐘舵��
+            Log.Warn($"[DeviceManager] 璁惧 {deviceId} 鐘舵�佺紦瀛樹笉瀛樺湪锛岃繑鍥為粯璁ょ姸鎬�");
+            return new DeviceDriverStatus
+            {
+                IsConnected = false,
+                IsHealthy = false,
+                LastError = "璁惧鏈敞鍐屾垨鐘舵�佹湭鍒濆鍖�"
+            };
+        }
+
+        /// <inheritdoc/>
+        public async Task ConnectAsync(string deviceId, CancellationToken ct)
+        {
+            if (string.IsNullOrWhiteSpace(deviceId))
+                throw new ArgumentException("璁惧ID涓嶈兘涓虹┖", nameof(deviceId));
+
+            if (!_drivers.TryGetValue(deviceId, out var driver))
+            {
+                throw new InvalidOperationException($"璁惧 {deviceId} 鏈敞鍐岄┍鍔�");
+            }
+
+            try
+            {
+                Log.Info($"[DeviceManager] 姝e湪杩炴帴璁惧: {deviceId}");
+                await driver.ConnectAsync(ct).ConfigureAwait(false);
+
+                // 鏇存柊鐘舵�佺紦瀛�
+                _statusCache[deviceId] = driver.GetStatus();
+
+                Log.Info($"[DeviceManager] 璁惧 {deviceId} 杩炴帴鎴愬姛");
+            }
+            catch (Exception ex)
+            {
+                // 鏇存柊閿欒鐘舵��
+                if (_statusCache.TryGetValue(deviceId, out var status))
+                {
+                    status.IsConnected = false;
+                    status.IsHealthy = false;
+                    status.LastError = ex.Message;
+                    status.LastErrorTime = DateTime.UtcNow;
+                    _statusCache[deviceId] = status;
+                }
+
+                Log.Error($"[DeviceManager] 璁惧 {deviceId} 杩炴帴澶辫触: {ex.Message}", ex);
+                throw;
+            }
+        }
+
+        /// <inheritdoc/>
+        public async Task DisconnectAsync(string deviceId)
+        {
+            if (string.IsNullOrWhiteSpace(deviceId))
+                throw new ArgumentException("璁惧ID涓嶈兘涓虹┖", nameof(deviceId));
+
+            if (!_drivers.TryGetValue(deviceId, out var driver))
+            {
+                Log.Warn($"[DeviceManager] 灏濊瘯鏂紑鏈敞鍐岀殑璁惧: {deviceId}");
+                return;
+            }
+
+            try
+            {
+                Log.Info($"[DeviceManager] 姝e湪鏂紑璁惧: {deviceId}");
+                await driver.DisconnectAsync().ConfigureAwait(false);
+
+                // 鏇存柊鐘舵�佺紦瀛�
+                _statusCache[deviceId] = driver.GetStatus();
+
+                Log.Info($"[DeviceManager] 璁惧 {deviceId} 宸叉柇寮�杩炴帴");
+            }
+            catch (Exception ex)
+            {
+                Log.Error($"[DeviceManager] 璁惧 {deviceId} 鏂紑杩炴帴澶辫触: {ex.Message}", ex);
+                throw;
+            }
+        }
+
+        /// <inheritdoc/>
+        public IReadOnlyList<string> GetRegisteredDevices()
+        {
+            return _drivers.Keys.ToList().AsReadOnly();
+        }
+
+        /// <inheritdoc/>
+        public bool IsDeviceRegistered(string deviceId)
+        {
+            if (string.IsNullOrWhiteSpace(deviceId))
+                return false;
+
+            return _drivers.ContainsKey(deviceId);
+        }
+
+        /// <summary>
+        /// 澶勭悊璁惧杩炴帴鐘舵�佸彉鍖栦簨浠�
+        /// </summary>
+        /// <param name="sender">浜嬩欢鍙戦�佽��</param>
+        /// <param name="e">浜嬩欢鍙傛暟</param>
+        private void OnConnectionChanged(object? sender, DeviceConnectionEventArgs e)
+        {
+            var deviceId = e.DeviceId;
+
+            if (string.IsNullOrWhiteSpace(deviceId))
+            {
+                Log.Warn("[DeviceManager] 鏀跺埌杩炴帴鍙樺寲浜嬩欢浣� DeviceId 涓虹┖");
+                return;
+            }
+
+            if (_statusCache.TryGetValue(deviceId, out var status))
+            {
+                status.IsConnected = e.IsConnected;
+                if (!e.IsConnected)
+                {
+                    status.IsHealthy = false;
+                    if (!string.IsNullOrEmpty(e.Reason))
+                    {
+                        status.LastError = e.Reason;
+                        status.LastErrorTime = DateTime.UtcNow;
+                    }
+                }
+                else
+                {
+                    status.IsHealthy = true;
+                    status.LastError = "";
+                }
+
+                _statusCache[deviceId] = status;
+
+                Log.Info($"[DeviceManager] 璁惧 {deviceId} 杩炴帴鐘舵�佸彉鍖�: {(e.IsConnected ? "宸茶繛鎺�" : "宸叉柇寮�")}" +
+                        (string.IsNullOrEmpty(e.Reason) ? "" : $", 鍘熷洜: {e.Reason}"));
+            }
+        }
+    }
+}

--
Gitblit v1.9.1