Files
Ayay/SHH.CameraService/Program.cs
twice109 3d47c8f009 增加了通过网络主动上报图像的支持
增加了指令维护通道的支持
2026-01-07 10:59:03 +08:00

160 lines
6.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using SHH.CameraSdk;
namespace SHH.CameraService;
public class Program
{
public static async Task Main(string[] args)
{
// 1. 理由:缓冲时间 10 秒, 供附加调试工具使用
for (var i = 1; i < 10; i++)
Thread.Sleep(1000);
// =============================================================
// 2. 基础环境与配置 (理由:明确身份 ID 和 监听端口)
// =============================================================
var config = ServiceConfig.BuildFromArgs(args);
// 硬件预热 (理由:确保底层驱动库在 Web 容器启动前完全就绪)
HikNativeMethods.NET_DVR_Init();
HikSdkManager.ForceWarmUp();
var builder = WebApplication.CreateBuilder(args);
// =============================================================
// 3. 依赖注入注册 (DI)
// =============================================================
builder.Services.AddSingleton(config);
// 注册缩放与增亮业务(不注册则不实现)
builder.Services.AddSingleton<ProcessingConfigManager>();
builder.Services.AddSingleton(sp => new ImageScaleCluster(4, sp.GetRequiredService<ProcessingConfigManager>()));
builder.Services.AddSingleton(sp => new ImageEnhanceCluster(4, sp.GetRequiredService<ProcessingConfigManager>()));
builder.Services.AddHostedService<PipelineConfigurator>();
// 接入 SDK 核心逻辑
builder.Services.AddCameraSdk(config.NumericId);
// 注册后台引擎 (理由:托管长周期的硬件状态监控)
builder.Services.AddHostedService<CameraEngineWorker>();
// 配置 Web 相关的服务
ConfigureWebServices(builder, config);
// 配置进程守护
builder.Services.AddHostedService<ParentProcessSentinel>();
// =============================================================
// 4. 接受启动传参, 并支持将视频进行网络广播
// =============================================================
// 1. 读取配置创建 targets (可以是 1 个,也可以是 10 个)
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,
}));
}
}
// 2. 注册 Targets (供采集者用)
builder.Services.AddSingleton<IEnumerable<StreamTarget>>(netTargets);
// 3. 注册采集者 (它会注入上面的 targets进行编码和分发)
builder.Services.AddHostedService<NetworkStreamingWorker>();
// 4. 为每个 Target 注册一个独立的发送者
foreach (var target in netTargets)
{
builder.Services.AddHostedService(sp => new NetMqSenderWorker(target));
}
// =============================================================
// 5. 命令管道配置
// =============================================================
// 负责连接 Dashboard注册身份接收重启/控制指令
builder.Services.AddHostedService<CommandClientWorker>();
// 1. 注册分发器
builder.Services.AddSingleton<CommandDispatcher>();
// 2. 注册具体的指令处理器 (每写一个新的 Handler就在这里注册一下或者用反射批量注册)
builder.Services.AddSingleton<ICommandHandler, SyncCameraHandler>();
// =============================================================
// 6. 构建与管道配置
// =============================================================
var app = builder.Build();
// 核心修复:同步点火逻辑 (理由:在 Web 开启前完成设备池的初步构建)
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.");
app.UseCors("AllowAll");
// 理由:正式映射控制器路由
app.MapControllers();
// =============================================================
// 5. 正式启动
// =============================================================
await app.RunAsync($"http://0.0.0.0:{config.BasePort}");
}
/// <summary>
/// 对齐业务启动:激活单例并启动相机管理器
/// </summary>
static async Task StartBusinessLogic(WebApplication app)
{
var manager = app.Services.GetRequiredService<CameraManager>();
// 激活哨兵逻辑 (理由:显式 Get 触发单例构造,否则不工作)
_ = app.Services.GetRequiredService<ConnectivitySentinel>();
// 启动相机任务加载
await manager.StartAsync();
Console.WriteLine("[System] 核心业务逻辑已激活。");
}
/// <summary>
/// 注册 Web API 支持
/// </summary>
static void ConfigureWebServices(WebApplicationBuilder builder, ServiceConfig cfg)
{
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAll", p => p.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
});
// ★★★★★ 补全点:跨项目控制器加载 ★★★★★
// 理由Controller 定义在 SDK 项目中,必须通过 AddApplicationPart 显式挂载
builder.Services.AddControllers(options =>
{
options.Filters.Add<UserActionFilter>();
})
.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" });
});
}
}