Files
Ayay/SHH.CameraSdk/Program.cs

166 lines
7.0 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.Extensions.Logging;
using Microsoft.OpenApi.Models;
using OpenCvSharp;
using SHH.CameraSdk;
using System.Diagnostics;
namespace SHH.CameraSdk
{
/// <summary>
/// A 方案:标准控制台结构 (显式 Main 方法 + STAThread)
/// </summary>
public class Program
{
// [关键点 1] 显式声明 STA 线程模式,确保 OpenCV/GUI 窗口消息循环正常
[STAThread]
public static async Task Main(string[] args)
{
// ==============================================================================
// 1. 基础设施初始化
// ==============================================================================
InitHardwareEnv();
using var cameraManager = new CameraManager();
// [关键点 2] 提升变量作用域
// 将渲染器(消费者)在 Main 中声明,确保它与主程序同寿命,不会被中途回收
using var remoteRenderer = new FrameConsumer("Process A Remote Preview");
remoteRenderer.Start();
// ==============================================================================
// 2. 启动 Web 监控与诊断服务
// ==============================================================================
var app = await StartWebMonitoring(cameraManager);
// [新增] 启动网络哨兵 (它会自动在后台跑)
// 就像保安一样你不需要管它它每3秒会把所有摄像头的 IsOnline 状态刷一遍
var sentinel = new ConnectivitySentinel(cameraManager);
// ==============================================================================
// 3. 业务编排:配置设备与流控策略 (8+2 演示)
// ==============================================================================
// [关键点 3] 将渲染器作为参数传递进去
await ConfigureBusinessLogic(cameraManager, remoteRenderer);
// ==============================================================================
// 4. 启动引擎与交互
// ==============================================================================
Console.WriteLine("\n[系统] 正在启动全局管理引擎...");
await cameraManager.StartAsync();
Console.WriteLine(">> 系统就绪。访问 http://localhost:5000/swagger 查看诊断信息。");
Console.WriteLine(">> 按 'S' 键退出...");
// [关键点 4] 阻塞主线程
// 只要这个循环在跑remoteRenderer 就不会被 Dispose窗口就会一直存在
while (Console.ReadKey(true).Key != ConsoleKey.S)
{
Thread.Sleep(100);
}
Console.WriteLine("[系统] 正在停机...");
await app.StopAsync();
}
// ==============================================================================
// Static Methods (原 Local Functions 转换为类的静态方法)
// ==============================================================================
static void InitHardwareEnv()
{
Console.WriteLine("=== 工业级视频 SDK 架构测试 (V3.3 分层版 - STA模式) ===");
Console.WriteLine("[硬件] 海康驱动预热中...");
HikNativeMethods.NET_DVR_Init();
HikSdkManager.ForceWarmUp(); // 强制加载 PlayCtrl.dll
Console.WriteLine("[硬件] 预热完成。");
}
static async Task<WebApplication> StartWebMonitoring(CameraManager manager)
{
var builder = WebApplication.CreateBuilder();
// [新增] 屏蔽日志配置
builder.Logging.AddFilter("Microsoft", Microsoft.Extensions.Logging.LogLevel.Warning);
builder.Logging.AddFilter("System", Microsoft.Extensions.Logging.LogLevel.Warning);
builder.Logging.AddFilter("Microsoft.AspNetCore.Hosting.Diagnostics", Microsoft.Extensions.Logging.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()));
// 关键:注入单例 Manager
builder.Services.AddSingleton(manager);
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;
}
// [关键点 5] 方法签名修改:接收 FrameConsumer 参数
static async Task ConfigureBusinessLogic(CameraManager manager, FrameConsumer renderer)
{
// 1. 配置设备
var config = new VideoSourceConfig
{
Id = 101,
Brand = DeviceBrand.HikVision,
IpAddress = "172.16.41.206",
//IpAddress = "192.168.5.9",
Port = 8000,
Username = "admin",
Password = "abcd1234",
//Password = "RRYFOA",
StreamType = 0 // 主码流
};
manager.AddDevice(config);
if (manager.GetDevice(101) is HikVideoSource hikCamera)
{
// 1. 注册差异化需求 (给每个消费者唯一的 AppId)
// ----------------------------------------------------
// 1. 注册需求时,手动加上 _Display 后缀
hikCamera.Controller.Register("Process_A_Remote_Display", 20);
// 2. 订阅时,也改用带后缀的名称
GlobalStreamDispatcher.Subscribe("Process_A_Remote_Display", 101, frame =>
{
frame.AddRef();
renderer.Enqueue(frame);
});
}
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);
//if (manager.GetDevice(102) is HikVideoSource hikCamera2)
//{
//}
}
}
}