using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Models; namespace SHH.CameraSdk; /// /// A 方案:标准控制台结构 (动态窗口版) /// public class Program { [STAThread] public static async Task Main(string[] args) { // ============================================================================== // 1. 基础设施初始化 // ============================================================================== InitHardwareEnv(); // 核心设备管理器 using var cameraManager = new CameraManager(); // [新增] 动态窗口管理器 (不再直接 new FrameConsumer) // 这是一个单例服务,负责在运行期间管理所有弹出的窗口 var displayManager = new DisplayWindowManager(); // ============================================================================== // 2. 启动 Web 监控与诊断服务 (注入两个管理器) // ============================================================================== var app = await StartWebMonitoring(cameraManager, displayManager); // 启动网络哨兵 (后台 Ping) var sentinel = new ConnectivitySentinel(cameraManager); // ============================================================================== // 3. 业务编排:仅配置设备,不配置窗口 // ============================================================================== await ConfigureBusinessLogic(cameraManager); // ============================================================================== // 4. 启动引擎与交互 // ============================================================================== Console.WriteLine("\n[系统] 正在启动全局管理引擎..."); await cameraManager.StartAsync(); Console.WriteLine(">> 系统就绪。"); Console.WriteLine(">>当前无播放窗口。请通过 Web 界面 '新增订阅' -> 模式选 'UI_Preview' 来动态打开。"); Console.WriteLine(">> 按 'S' 键退出..."); // 阻塞主线程,保持程序运行 while (Console.ReadKey(true).Key != ConsoleKey.S) { Thread.Sleep(100); } Console.WriteLine("[系统] 正在停机..."); await app.StopAsync(); } // ============================================================================== // Static Methods // ============================================================================== static void InitHardwareEnv() { Console.WriteLine("=== 工业级视频 SDK 架构测试 (V3.3 动态窗口版) ==="); Console.WriteLine("[硬件] 海康驱动预热中..."); HikNativeMethods.NET_DVR_Init(); HikSdkManager.ForceWarmUp(); Console.WriteLine("[硬件] 预热完成。"); } // [修改] 签名增加 DisplayWindowManager 参数 static async Task StartWebMonitoring(CameraManager manager, DisplayWindowManager displayMgr) { var builder = WebApplication.CreateBuilder(); builder.Services.AddCors(options => { options.AddPolicy("AllowAll", policy => { policy.AllowAnyOrigin() .AllowAnyHeader() .AllowAnyMethod(); }); }); // 日志屏蔽 builder.Logging.AddFilter("Microsoft", LogLevel.Warning); builder.Logging.AddFilter("System", LogLevel.Warning); builder.Logging.AddFilter("Microsoft.AspNetCore.Hosting.Diagnostics", LogLevel.Warning); builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "SHH Camera Diagnostics", Version = "v1" }); }); builder.Services.AddCors(o => o.AddPolicy("AllowAll", p => p.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader())); // [关键] 注入两个单例服务,让 Controller 能调用它们 builder.Services.AddSingleton(manager); builder.Services.AddSingleton(displayMgr); var webApp = builder.Build(); webApp.UseSwagger(); webApp.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Diagnostics V1")); webApp.UseCors("AllowAll"); webApp.MapControllers(); _ = webApp.RunAsync("http://0.0.0.0:5000"); Console.WriteLine("[Web] 监控API已启动: http://localhost:5000"); return webApp; } // [修改] 移除 FrameConsumer 参数,不再进行硬编码订阅 static async Task ConfigureBusinessLogic(CameraManager manager) { // 1. 仅添加设备配置 var config = new VideoSourceConfig { Id = 101, Brand = DeviceBrand.HikVision, IpAddress = "172.16.41.206", Port = 8000, Username = "admin", Password = "abcd1234", StreamType = 0 }; manager.AddDevice(config); var config2 = new VideoSourceConfig { Id = 102, Brand = DeviceBrand.HikVision, IpAddress = "172.16.41.20", Port = 8000, Username = "admin", Password = "abcd1234", StreamType = 0 }; manager.AddDevice(config2); // 注意:此处不再调用 Register 或 Subscribe // 所有的播放请求都将由 WebAPI 收到前端指令后,调用 DisplayWindowManager 来动态发起 } }