Files
Ayay/SHH.CameraService/Core/CmdClients/SyncCameraHandler.cs

103 lines
3.8 KiB
C#
Raw Normal View History

using Newtonsoft.Json.Linq;
using SHH.CameraSdk; // 引用包含 FrameController 和 FrameRequirement 的命名空间
using SHH.Contracts;
namespace SHH.CameraService;
public class SyncCameraHandler : ICommandHandler
{
private readonly CameraManager _cameraManager;
public string ActionName => "SyncCamera";
public SyncCameraHandler(CameraManager cameraManager)
{
_cameraManager = cameraManager;
}
public async Task ExecuteAsync(JToken payload)
{
// 1. 解析配置
var dto = payload.ToObject<CameraConfigDto>();
if (dto == null) return;
// 2. 添加设备到管理器 (这一步是必须的,不然没有 Device 就没有 Controller)
var videoConfig = new VideoSourceConfig
{
Id = dto.Id,
Name = dto.Name,
IpAddress = dto.IpAddress,
Port = dto.Port,
Username = dto.Username,
Password = dto.Password,
ChannelIndex = dto.ChannelIndex,
StreamType = dto.StreamType,
Brand = (DeviceBrand)dto.Brand,
RenderHandle = (IntPtr)dto.RenderHandle,
MainboardIp = dto.MainboardIp,
MainboardPort = dto.MainboardPort,
// 必须给个默认值,防止空引用
VendorArguments = new Dictionary<string, string>(),
};
// 如果设备不存在才添加,如果已存在,后续逻辑会直接获取
if (_cameraManager.GetDevice(videoConfig.Id) == null)
{
_cameraManager.AddDevice(videoConfig);
}
// 3. 核心:直接获取设备实例
var device = _cameraManager.GetDevice(dto.Id);
if (device == null)
{
Console.WriteLine($"[SyncError] 设备 {dto.Id} 创建失败,无法执行自动订阅。");
return;
}
// 4. 拿到你的“宝贝”控制器 (FrameController)
var controller = device.Controller;
if (controller == null)
{
Console.WriteLine($"[SyncError] 设备 {dto.Id} 不支持流控调度 (Controller is null)。");
return;
}
// 5. 暴力注册订阅需求 (Loop AutoSubscriptions)
if (dto.AutoSubscriptions != null && dto.AutoSubscriptions.Count > 0)
{
foreach (var subItem in dto.AutoSubscriptions)
{
// 生成 AppId (照抄你给的逻辑)
string finalAppId = string.IsNullOrWhiteSpace(subItem.AppId)
? $"SUB_{Guid.NewGuid().ToString("N").Substring(0, 8).ToUpper()}"
: subItem.AppId;
Console.WriteLine($"[自动化] 正在注册流控: {finalAppId}, 目标: {subItem.TargetFps} FPS");
// 构造 FrameRequirement 对象 (完全匹配你 FrameController 的入参)
// 这里的属性赋值对应你代码里 req.Type, req.SavePath 等逻辑
var requirement = new FrameRequirement
{
AppId = finalAppId,
TargetFps = subItem.TargetFps, // 8帧 或 1帧
Type = (SubscriptionType)subItem.Type, // 业务类型 (LocalWindow, NetworkTrans...)
Memo = subItem.Memo ?? "Auto Sync",
// 其它字段给默认空值,防止 Controller 内部逻辑报错
Handle = "",
SavePath = ""
};
// ★★★ 见证奇迹的时刻:直接调用 Register ★★★
controller.Register(requirement);
}
}
//// 6. 启动设备
//// 你的积分算法会在 device 内部的推流循环中被 MakeDecision 调用
if (dto.ImmediateExecution)
await device.StartAsync();
Console.WriteLine($"[SyncSuccess] 设备 {dto.Id} 同步完成,策略已下发。");
}
}