Files
Ayay/SHH.CameraService/Program.cs
2026-01-16 17:45:27 +08:00

148 lines
6.2 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 Ayay.SerilogLogs;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Serilog;
using SHH.CameraSdk;
namespace SHH.CameraService;
public class Program
{
/// <summary>
/// 主程序
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
public static async Task Main(string[] args)
{
// 1. [核心环境] 必须在所有网络操作前开启
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
// 2. 解析配置与初始化日志
var (config, opts, isDebugArgs) = Bootstrapper.ParseConfigAndInitLogger(args);
var sysLog = Log.ForContext("SourceContext", LogModules.Core);
// =============================================================
// 1. 启动日志
// =============================================================
sysLog.Warning($"[Core] 🚀 视频取流进程启动, 日志组件初始化完毕 => 进程: {opts.AppId}");
string argString = string.Join(" ", args);
sysLog.Debug($"[Core] 🚀 启动参数({(isDebugArgs ? "" : "")}: {argString}");
// =============================================================
// 2. 硬件预热、端口扫描、gRpc链接
// =============================================================
Bootstrapper.WarmUpHardware(sysLog);
// 端口自动扫描 (必须做,否则端口冲突)
int activePort = Bootstrapper.ScanForAvailablePort(config, sysLog);
if (activePort == -1)
{
sysLog.Fatal("[Core] 💀 无法启动:配置范围内无可用端口");
Bootstrapper.Shutdown("无法启动:配置范围内无可用端口", exitCode: 1);
return;
}
config.UpdateActualPort(activePort); // 回填端口
// 具体的 gRpc 链接逻辑封装在 Bootstrapper 中,保持 Main 清爽但逻辑可见
await Bootstrapper.RegisterToGatewayAsync(config);
// =============================================================
// 3. 构建 Web 主机环境
// =============================================================
var builder = WebApplication.CreateBuilder(args);
// 👇👇👇 核心修复开始 👇👇👇
// ★ 1. 接管日志系统:告诉 Host 使用我们刚才配置好的 Serilog
// dispose: true 表示程序结束时自动刷新日志
builder.Host.UseSerilog(dispose: true);
// ★ 2. 斩草除根:清除 .NET 默认注入的 Console/Debug 日志提供程序
// 这一步是解决 "info: Microsoft.Hosting.Lifetime..." 重复输出的关键
builder.Logging.ClearProviders();
// ★ 3. (可选) 彻底静音:禁止 Kestrel 打印 "Now listening on..." 这种启动横幅
// 如果你只想看你自己的 "[WebApi] 🚀 服务启动...",就把这行加上
builder.WebHost.SuppressStatusMessages(true);
// ★ 核心改动:一行代码注册所有业务 (SDK, Workers, gRpc, 视频流)
builder.Services.AddCameraBusinessServices(config, sysLog);
// ★ 核心改动:注册 Web 基础 (Controller, Swagger, Cors)
builder.Services.AddWebSupport(config);
// =============================================================
// 6. 启动服务
// =============================================================
var app = builder.Build();
// 激活 SDK 管理器并启动业务点火
await StartBusinessLogic(app, sysLog);
// ★ 核心改动:配置 HTTP 管道 (Swagger, MapControllers 等)
app.ConfigurePipeline(config);
// 启动监听
string url = $"http://0.0.0.0:{config.BasePort}";
sysLog.Information($"[WebApi] 🚀 服务启动,监听: {url}");
await app.RunAsync(url);
}
/// <summary>
/// 激活单例并启动相机管理器
/// </summary>
/// <param name="app"></param>
/// <param name="logger"></param>
static async Task StartBusinessLogic(WebApplication app, Serilog.ILogger logger)
{
var manager = app.Services.GetRequiredService<CameraManager>();
// 激活哨兵
_ = app.Services.GetRequiredService<ConnectivitySentinel>();
await manager.StartAsync();
var sysLog = Log.ForContext("SourceContext", LogModules.Core);
sysLog.Information($"[Core] 🚀 核心业务逻辑已激活, 设备管理器已就绪.");
}
}
/*
🚀 启动/发布 程序启动、服务预热、开始监听
🏁 结束/终点 批量任务全部完成、程序正常退出
🔄 重试/循环 正在重试连接、定时任务触发、同步数据中
⏳ 等待/耗时 长耗时操作开始、排队中
💤 休眠/闲置 线程挂起、服务进入待机模式
🌐 网络/HTTP HTTP 请求、API 调用、Web 服务
🔌 连接 数据库连接建立、Socket 连接
📡 信号/广播 发送 MQ 消息、广播通知、取流
💾 存储/磁盘 写入文件、数据库落盘、缓存读写
🔒 安全/锁 加密、解密、登录成功、获取分布式锁
⚙️ 配置/系统 加载配置、系统底层操作
🐞 Bug/调试 捕捉到的异常、临时调试信息
🧪 测试/实验 单元测试环境、灰度测试代码
🔍 搜索/检查 查询数据库、检查文件是否存在
💡 提示/发现 逻辑分支提示、参数值打印
🔴 红:致命/严重 (Fatal/Error)
🟡 黄:警告 (Warning)
🟢 绿:正常/成功 (Info/Success)
🔵 蓝:数据/网络 (Data/Network)
⚪ 灰:细节/忽略 (Debug/Verbose)
✅ Check Mark Button \u{2705} &#x2705;
🆗 OK Button \u{1F197} &#x1F197;
🔚 END Arrow (逻辑结束) \u{1F51A} &#x1F51A;
💯 Hundred Points (完美结束) \u{1F4AF} &#x1F4AF;
🛑 Stop Sign (最强提示) \u{1F6D1} &#x1F6D1;
⛔ No Entry (禁止/中断) \u{26D4} &#x26D4;
🚫 Prohibited (非法操作终止) \u{1F6AB} &#x1F6AB;
⏹️ Stop Button (播放器风格) \u{23F9} &#x23F9;
❌ Cross Mark (任务失败结束) \u{274C} &#x274C;
💀 Skull (进程被 Kill) \u{1F480} &#x1F480;
⚰️ Coffin (彻底销毁) \u{26B0} &#x26B0;
👻 Ghost (变成孤儿进程) \u{1F47B} &#x1F47B;
*/