using Grpc.Net.Client; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.OpenApi.Models; using SHH.CameraSdk; using SHH.Contracts.Grpc; using Microsoft.Extensions.Logging; namespace SHH.CameraService; public class Program { public static async Task Main(string[] args) { // 2. 硬件预热 (静态方法保留) HikNativeMethods.NET_DVR_Init(); HikSdkManager.ForceWarmUp(); // 1. [核心环境] 必须在所有网络操作前开启 AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); // 2. 模拟/解析配置 if (args.Length == 0) { string serviceArgs = "--appid CameraApp_01 " + "--uris localhost,9001,video,调试PC; " + "--uris localhost,9001,command,调试PC; " + "--mode 1 --ports 5000,100"; args = serviceArgs.Split(' ', StringSplitOptions.RemoveEmptyEntries); } var config = ServiceConfig.BuildFromArgs(args); // ============================================================= // 3. 【强行复刻成功逻辑】 在 Web 容器启动前直接执行注册 // ============================================================= if (config.CommandEndpoints.Any()) { try { // 将 tcp:// 转换为 http:// 以适配 gRPC string targetUrl = config.CommandEndpoints.First().Uri.Replace("tcp://", "http://"); using var channel = GrpcChannel.ForAddress(targetUrl); var client = new GatewayProvider.GatewayProviderClient(channel); Console.WriteLine($"[gRPC] 正在执行预注册 (环境: 纯净): {targetUrl}"); var resp = await client.RegisterInstanceAsync(new RegisterRequest { InstanceId = config.AppId, Version = "2.0.0-grpc", ServerIp = "127.0.0.1", WebApiPort = config.BasePort, StartTimeTicks = DateTime.Now.Ticks, ProcessId = Environment.ProcessId, Description = "Camera Service" }); Console.WriteLine($"[gRPC] 预注册成功: {resp.Message}"); } catch (Exception ex) { Console.WriteLine($"[gRPC] 预注册尝试失败 (不影响启动): {ex.Message}"); } } // ============================================================= // 4. 构建 Web 主机环境 // ============================================================= var builder = WebApplication.CreateBuilder(args); // 基础业务单例注册 builder.Services.AddSingleton(config); builder.Services.AddSingleton(); builder.Services.AddSingleton(sp => new ImageScaleCluster(4, sp.GetRequiredService())); builder.Services.AddSingleton(sp => new ImageEnhanceCluster(4, sp.GetRequiredService())); builder.Services.AddHostedService(); // 接入 SDK 核心逻辑 builder.Services.AddCameraSdk(config.NumericId); builder.Services.AddHostedService(); // ★ 注册 gRPC 版本的状态监控工作者 (不讲道理,直接注册) builder.Services.AddHostedService(); builder.Services.AddHostedService(); builder.Services.AddHostedService(); // ============================================================= // 5. 视频流 Target 注册 (gRPC 模式) // ============================================================= var netTargets = new List(); if (config.VideoEndpoints != null) { foreach (var cfgVideo in config.VideoEndpoints) { netTargets.Add(new StreamTarget(new PushTargetConfig { Name = cfgVideo.Description, Endpoint = cfgVideo.Uri, QueueCapacity = 10, })); } } builder.Services.AddSingleton>(netTargets); builder.Services.AddHostedService(); // 为每个 Target 绑定一个 gRPC 流发送者 foreach (var target in netTargets) { builder.Services.AddHostedService(sp => new GrpcSenderWorker(target, sp.GetRequiredService>())); } // 注册指令分发 (不再使用 NetMQ 的 CommandClientWorker) builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); ConfigureWebServices(builder, config); // ============================================================= // 6. 启动服务 // ============================================================= var app = builder.Build(); // 激活 SDK 管理器并启动业务点火 await StartBusinessLogic(app); app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", $"SHH Gateway #{config.AppId}")); app.MapGet("/", () => $"SHH Gateway {config.AppId} is running (gRPC Mode)."); app.UseCors("AllowAll"); app.MapControllers(); Console.WriteLine($"[System] 正在启动 Web 服务,监听端口: {config.BasePort}"); await app.RunAsync($"http://0.0.0.0:{config.BasePort}"); } /// /// 激活单例并启动相机管理器 /// static async Task StartBusinessLogic(WebApplication app) { var manager = app.Services.GetRequiredService(); _ = app.Services.GetRequiredService(); await manager.StartAsync(); Console.WriteLine("[System] 核心业务逻辑已激活。"); } /// /// 注册 Web API 支持 /// static void ConfigureWebServices(WebApplicationBuilder builder, ServiceConfig cfg) { builder.Services.AddCors(options => { options.AddPolicy("AllowAll", p => p.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()); }); builder.Services.AddControllers(options => { options.Filters.Add(); }) .AddApplicationPart(typeof(CamerasController).Assembly) .AddApplicationPart(typeof(MonitorController).Assembly); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = $"SHH Gateway #{cfg.AppId}", Version = "v1" }); }); } }