From 559890c482f5973f06aafdfec9550fee5ba3c7f2 Mon Sep 17 00:00:00 2001
From: wenxiangchao <wenxiangchao@ihengxin.com.cn>
Date: 星期一, 09 十一月 2026 17:02:15 +0800
Subject: [PATCH] feat: CAN 模拟器 TCP 化 + 多设备并发调试 + 后台生命周期管理

---
 Aging.Infrastructure/InfrastructureBootstrapper.cs |   79 +++++++++++++++++++++++++++++++++++++--
 1 files changed, 75 insertions(+), 4 deletions(-)

diff --git a/Aging.Infrastructure/InfrastructureBootstrapper.cs b/Aging.Infrastructure/InfrastructureBootstrapper.cs
index aebb5b0..63169ee 100644
--- a/Aging.Infrastructure/InfrastructureBootstrapper.cs
+++ b/Aging.Infrastructure/InfrastructureBootstrapper.cs
@@ -1,5 +1,7 @@
+using System.IO;
 using log4net;
 using HMI.Core.Util;
+using Aging.Infrastructure.Broker;
 using Aging.Infrastructure.Contracts;
 using Aging.Infrastructure.Core;
 using Aging.Infrastructure.Services;
@@ -32,10 +34,16 @@
             {
                 log.Info("寮�濮嬪垵濮嬪寲鍩虹璁炬柦鏈嶅姟...");
 
-                // 1. 鍒涘缓 ResourceManager 鍗曚緥
-                var resourceManager = new ResourceManager();
+                // V3.0 MVP锛氫徊瑁佸簱 arb.db锛堜笌 data.db 鍚岀洰褰曪級
+                string arbPath = Path.Combine(Path.GetDirectoryName(deviceConfigDbPath)!, "arb.db");
+                var leaseStore = new DbLeaseStore(arbPath, "local-main");
+                // V3.0 INV-03锛氬惎鍔ㄥ璐︹�斺�斾笂娆¤繘绋嬪紓甯搁��鍑烘湭閲婃斁鐨勭绾﹀湪鏈満瀹夸富鏇存浛鍚庤嚜鍔ㄥ洖鏀讹紝
+                // 閬垮厤璋冭瘯/鐢熶骇缁存姢琚� RecoveryRequired 姘镐箙闃诲锛堣瘉鎹啓鍏� recovery_checkpoint锛�
+                leaseStore.ReconcileAfterBoot($"{Environment.MachineName}/{System.Diagnostics.Process.GetCurrentProcess().Id}");
+                var resourceManager = new LayeredResourceManager(leaseStore);
+                UtilContainer.RegisterUtil("LeaseCoordinator", leaseStore);
                 UtilContainer.RegisterUtil("ResourceManager", resourceManager);
-                log.Info("ResourceManager 宸叉敞鍐�");
+                log.Info("LayeredResourceManager (鍩轰簬 DbLeaseStore) 宸叉敞鍐�");
 
                 // 2. 鍒涘缓 DeviceManager 鍗曚緥
                 var deviceManager = new DeviceManager();
@@ -57,8 +65,21 @@
                 UtilContainer.RegisterUtil("PowerSupplyService", powerSupplyService);
                 log.Info("PowerSupplyService 宸叉敞鍐�");
 
-                // 6. 浠庢暟鎹簱鍔犺浇璁惧瀹氫箟骞舵敞鍐岄┍鍔�
+                // 6. 鍒涘缓 AutoDeviceFacade (鑷姩鍖栨祴璇曞叆鍙�)
+                var autoFacade = new AutoDeviceFacade(resourceManager, deviceService);
+                UtilContainer.RegisterUtil("AutoDeviceFacade", autoFacade);
+                log.Info("AutoDeviceFacade 宸叉敞鍐�");
+
+                // 7. 鍒涘缓 CanBusService (CAN 绫诲瀷鍖栨湇鍔�)
+                var canBusService = new CanBusService(autoFacade);
+                UtilContainer.RegisterUtil("CanBusService", canBusService);
+                log.Info("CanBusService 宸叉敞鍐�");
+
+                // 8. 浠庢暟鎹簱鍔犺浇璁惧瀹氫箟骞舵敞鍐岄┍鍔�
                 LoadDevicesFromConfig(deviceManager, mappingResolver);
+
+                // 8.5. V3.0 娣峰悎鏋舵瀯锛欱roker 鍩熻澶囨敞鍐屼唬鐞嗛┍鍔紙鐗╃悊浼氳瘽鐢� DeviceBroker.exe 瀹夸富鍞竴鎸佹湁锛�
+                RegisterBrokeredDrivers(deviceManager, deviceConfigDbPath);
 
                 _initialized = true;
                 log.Info("鍩虹璁炬柦鏈嶅姟鍒濆鍖栧畬鎴�");
@@ -71,6 +92,56 @@
         }
 
         /// <summary>
+        /// V3.0锛氭壂鎻忛厤缃簱涓� ExecutionMode=Broker 鐨勮澶囷紝娉ㄥ唽缁熶竴 CanDeviceDriver锛圔rokerRpc 浠g悊鍚庣锛夈��
+        /// Local 璁惧淇濇寔鐜版湁鐩撮┍璺緞涓嶅彉锛汢roker 瀹夸富鏈惎鍔ㄦ椂浠g悊浠呭湪鍙戣捣 I/O 鏃跺け璐ワ紝涓嶉樆濉炲垵濮嬪寲銆�
+        /// </summary>
+        private static void RegisterBrokeredDrivers(IDeviceManager deviceManager, string deviceConfigDbPath)
+        {
+            try
+            {
+                if (!File.Exists(deviceConfigDbPath)) return;
+
+                var brokeredDevices = new System.Collections.Generic.List<(string DeviceId, string BrokerId, string Endpoint)>();
+                using (var conn = new System.Data.SQLite.SQLiteConnection(
+                           $"Data Source={deviceConfigDbPath};Version=3;Read Only=True;"))
+                {
+                    conn.Open();
+                    using var cmd = conn.CreateCommand();
+                    cmd.CommandText = "SELECT DeviceId, BrokerId, Endpoint FROM DeviceDefinition WHERE ExecutionMode = 'Broker';";
+                    using var rd = cmd.ExecuteReader();
+                    while (rd.Read())
+                    {
+                        string id = rd.GetString(0);
+                        string brokerId = rd.IsDBNull(1) ? "" : rd.GetString(1);
+                        string endpoint = rd.IsDBNull(2) ? "" : rd.GetString(2);
+                        if (!string.IsNullOrWhiteSpace(brokerId))
+                            brokeredDevices.Add((id, brokerId, endpoint));
+                    }
+                }
+
+                if (brokeredDevices.Count == 0) return;
+
+                // INV-04锛氬鎴风渚х敓鏁堥厤缃揩鐓э紝闅忔瘡娆� RPC 鎻愪氦渚� Broker 瀵硅处
+                string configHash;
+                try { configHash = DeviceConfigHash.Compute(deviceConfigDbPath); }
+                catch { configHash = ""; }
+
+                foreach (var (deviceId, brokerId, endpoint) in brokeredDevices)
+                {
+                    if (deviceManager.GetDriver(deviceId) != null) continue;
+                    var driver = CanDeviceDriver.CreateBrokerProxy(deviceId, endpoint, BrokerPipeName.For(brokerId), configHash);
+                    deviceManager.RegisterDriver(deviceId, driver);
+                    log.Info($"[Bootstrapper] 璁惧 {deviceId} 宸叉敞鍐� Broker 浠g悊椹卞姩 (绠¢亾={BrokerPipeName.For(brokerId)}, hash={configHash.Substring(0, Math.Min(8, configHash.Length))})");
+                }
+            }
+            catch (Exception ex)
+            {
+                // 浠g悊娉ㄥ唽澶辫触闄嶇骇锛氫笉褰卞搷 Local 鐩撮┍璁惧閾捐矾
+                log.Warn($"[Bootstrapper] Broker 浠g悊椹卞姩娉ㄥ唽澶辫触锛圔roker 閾捐矾涓嶅彲鐢紝Local 璁惧涓嶅彈褰卞搷锛�: {ex.Message}", ex);
+            }
+        }
+
+        /// <summary>
         /// 浠� DeviceConfig 鏁版嵁搴撳姞杞借澶囧畾涔夊苟娉ㄥ唽椹卞姩
         /// </summary>
         private static void LoadDevicesFromConfig(IDeviceManager deviceManager, SlotDeviceMappingResolver mappingResolver)

--
Gitblit v1.9.1