103 lines
3.8 KiB
C#
103 lines
3.8 KiB
C#
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} 同步完成,策略已下发。");
|
|
}
|
|
} |