175 lines
6.2 KiB
C#
175 lines
6.2 KiB
C#
using Microsoft.AspNetCore.Builder;
|
||
using Microsoft.Extensions.DependencyInjection;
|
||
using Microsoft.Extensions.Hosting;
|
||
using Microsoft.OpenApi.Models;
|
||
using SHH.CameraSdk;
|
||
|
||
// 确保 namespace 与 Program.cs 的引用一致
|
||
namespace SHH.CameraService;
|
||
|
||
public static class ServiceCollectionExtensions
|
||
{
|
||
// ========================================================================
|
||
// 1. 核心聚合方法 (对应 Program.cs 中的调用)
|
||
// ========================================================================
|
||
|
||
#region AddCameraBusinessServices
|
||
|
||
/// <summary>
|
||
/// [聚合] 注册所有核心业务 (包含逻辑处理、SDK、Gateway、视频流)
|
||
/// </summary>
|
||
public static void AddCameraBusinessServices(this IServiceCollection services, ServiceConfig config, Serilog.ILogger logger)
|
||
{
|
||
// 1.1 注册基础业务逻辑
|
||
services.AddBusinessServices(config);
|
||
|
||
// 1.2 注册视频流相关 (因为需要 Logger,所以单独传)
|
||
services.AddStreamTargets(config, logger);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region AddBusinessServices
|
||
|
||
/// <summary>
|
||
/// 集中注册 SDK、Workers、Gateway 等纯业务服务
|
||
/// </summary>
|
||
private static void AddBusinessServices(this IServiceCollection services, ServiceConfig config)
|
||
{
|
||
// 基础单例
|
||
services.AddSingleton(config);
|
||
services.AddSingleton<ProcessingConfigManager>();
|
||
|
||
// 图像处理集群
|
||
services.AddSingleton(sp => new ImageScaleCluster(4, sp.GetRequiredService<ProcessingConfigManager>()));
|
||
services.AddSingleton(sp => new ImageEnhanceCluster(4, sp.GetRequiredService<ProcessingConfigManager>()));
|
||
services.AddHostedService<PipelineConfigurator>();
|
||
|
||
// SDK 与核心引擎
|
||
services.AddCameraSdk(config.NumericId);
|
||
services.AddHostedService<CameraEngineWorker>();
|
||
|
||
// 监控与网关
|
||
services.AddHostedService<DeviceStatusHandler>();
|
||
services.AddHostedService<ParentProcessSentinel>();
|
||
services.AddHostedService<GatewayService>();
|
||
|
||
// 指令分发系统
|
||
services.AddSingleton<InterceptorPipeline>();
|
||
services.AddSingleton<CommandDispatcher>();
|
||
services.AddSingleton<ICommandHandler, DeviceConfigHandler>();
|
||
services.AddSingleton<ICommandHandler, RemoveCameraHandler>();
|
||
services.AddSingleton<ICommandHandler, PtzControlHandler>();
|
||
services.AddSingleton<ICommandHandler, DeviceRebootHandler>();
|
||
services.AddSingleton<ICommandHandler, TimeSyncHandler>();
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region AddStreamTargets
|
||
|
||
/// <summary>
|
||
/// 注册视频流目标 (StreamTargets & GrpcSender)
|
||
/// </summary>
|
||
private static void AddStreamTargets(this IServiceCollection services, ServiceConfig config, Serilog.ILogger logger)
|
||
{
|
||
var netTargets = new List<StreamTarget>();
|
||
if (config.VideoEndpoints != null)
|
||
{
|
||
foreach (var cfgVideo in config.VideoEndpoints)
|
||
{
|
||
netTargets.Add(new StreamTarget(new PushTargetConfig
|
||
{
|
||
Name = cfgVideo.Description,
|
||
Endpoint = cfgVideo.Uri,
|
||
QueueCapacity = 10,
|
||
}));
|
||
}
|
||
}
|
||
|
||
logger.Information("[Core] 📋 加载视频流目标: {Count} 个", netTargets.Count);
|
||
if (netTargets.Count > 0)
|
||
{
|
||
foreach (var item in netTargets)
|
||
logger.Debug("[Core] 🔍 视频流目标详情: {@Targets}", new { item.Config });
|
||
}
|
||
|
||
services.AddSingleton<IEnumerable<StreamTarget>>(netTargets);
|
||
services.AddHostedService<ImageMonitorController>();
|
||
|
||
//// 动态注册 Sender Worker
|
||
//foreach (var target in netTargets)
|
||
//{
|
||
// // 注意:这里需要使用 Microsoft.Extensions.Logging.ILogger 来适配构造函数
|
||
// services.AddHostedService(sp =>
|
||
// new GrpcSenderWorker(target));
|
||
//}
|
||
|
||
foreach (var target in netTargets)
|
||
{
|
||
// Modified: 显式声明局部变量,防止 Lambda 捕获循环变量导致的引用重复
|
||
var currentTarget = target;
|
||
|
||
logger.Information("[DI] 准备启动 Worker 实例: {Name} -> {Url}",
|
||
currentTarget.Config.Name, currentTarget.Config.Endpoint);
|
||
|
||
// 使用工厂模式注册,确保传入的是当前的 currentTarget
|
||
services.AddSingleton<IHostedService>(sp => new GrpcSenderWorker(currentTarget));
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
// ========================================================================
|
||
// 2. Web 支持与管道 (Program.cs 调用的另外两个方法)
|
||
// ========================================================================
|
||
|
||
#region AddWebSupport
|
||
|
||
/// <summary>
|
||
/// 注册 Controller, Swagger, Cors
|
||
/// </summary>
|
||
public static void AddWebSupport(this IServiceCollection services, ServiceConfig config)
|
||
{
|
||
services.AddCors(options =>
|
||
{
|
||
options.AddPolicy("AllowAll", p => p.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
|
||
});
|
||
|
||
// 注册 Controller 并添加过滤器
|
||
services.AddControllers(options =>
|
||
{
|
||
options.Filters.Add<UserActionFilter>();
|
||
})
|
||
.AddApplicationPart(typeof(CamerasController).Assembly) // 确保能扫描到 Controller
|
||
.AddApplicationPart(typeof(MonitorController).Assembly);
|
||
|
||
services.AddEndpointsApiExplorer();
|
||
services.AddSwaggerGen(c =>
|
||
{
|
||
c.SwaggerDoc("v1", new OpenApiInfo { Title = $"SHH Gateway #{config.AppId}", Version = "v1" });
|
||
});
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region ConfigurePipeline
|
||
|
||
/// <summary>
|
||
/// 配置 HTTP 中间件管道
|
||
/// </summary>
|
||
public static void ConfigurePipeline(this WebApplication app, ServiceConfig config)
|
||
{
|
||
// 开启 Swagger
|
||
app.UseSwagger();
|
||
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", $"SHH Gateway #{config.AppId}"));
|
||
|
||
// 简单健康检查端点
|
||
app.MapGet("/", () => $"SHH Gateway {config.AppId} is running.");
|
||
|
||
app.UseCors("AllowAll");
|
||
app.MapControllers();
|
||
}
|
||
|
||
#endregion
|
||
} |