123 lines
5.5 KiB
C#
123 lines
5.5 KiB
C#
|
|
using Newtonsoft.Json;
|
|||
|
|
using SHH.CameraSdk;
|
|||
|
|
using SHH.Contracts;
|
|||
|
|
|
|||
|
|
namespace SHH.CameraService
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 指令业务逻辑分发器 (纯逻辑层)
|
|||
|
|
/// <para>职责:解析业务参数 -> 调用 CameraManager -> 返回执行结果</para>
|
|||
|
|
/// <para>注意:本类不处理网络协议,也不负责 RequestId 的回填,只关注业务本身</para>
|
|||
|
|
/// </summary>
|
|||
|
|
public static class CommandBusProcessor
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 核心业务入口
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="manager">相机管理器实例</param>
|
|||
|
|
/// <param name="payload">已解析的指令包</param>
|
|||
|
|
/// <returns>执行结果 (不含 RequestId,由调用方补充)</returns>
|
|||
|
|
public static CommandResult ProcessBusinessLogic(CameraManager manager, CommandPayload payload)
|
|||
|
|
{
|
|||
|
|
string cmd = payload.CmdCode.ToUpper();
|
|||
|
|
|
|||
|
|
// 忽略客户端发回的 ACK (如果是双向确认模式)
|
|||
|
|
if (cmd == "REGISTER_ACK") return CommandResult.Ok();
|
|||
|
|
|
|||
|
|
// 解析 TargetId (CameraId)
|
|||
|
|
long deviceId = 0;
|
|||
|
|
// 只有非 SYSTEM 指令才需要解析设备ID
|
|||
|
|
if (payload.TargetId != "SYSTEM" && !long.TryParse(payload.TargetId, out deviceId))
|
|||
|
|
{
|
|||
|
|
return CommandResult.Fail($"Invalid Device ID: {payload.TargetId}");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
switch (cmd)
|
|||
|
|
{
|
|||
|
|
// ==========================================
|
|||
|
|
// 1. PTZ 云台控制
|
|||
|
|
// ==========================================
|
|||
|
|
case "PTZ":
|
|||
|
|
{
|
|||
|
|
var device = manager.GetDevice(deviceId);
|
|||
|
|
if (device == null) return CommandResult.Fail("Device Not Found");
|
|||
|
|
if (!device.IsOnline) return CommandResult.Fail("Device Offline");
|
|||
|
|
|
|||
|
|
// 检查设备是否支持 PTZ 能力 (接口模式匹配)
|
|||
|
|
if (device is IPtzFeature ptzFeature)
|
|||
|
|
{
|
|||
|
|
var ptzDto = JsonConvert.DeserializeObject<PtzControlDto>(payload.JsonParams);
|
|||
|
|
if (ptzDto == null) return CommandResult.Fail("Invalid PTZ Params");
|
|||
|
|
|
|||
|
|
// 异步转同步执行 (Task.Wait 在后台线程是安全的)
|
|||
|
|
if (ptzDto.Duration > 0)
|
|||
|
|
{
|
|||
|
|
// 点动模式 (例如:向左转 500ms)
|
|||
|
|
ptzFeature.PtzStepAsync(ptzDto.Action, ptzDto.Duration, ptzDto.Speed).Wait();
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// 持续模式 (开始转/停止转)
|
|||
|
|
ptzFeature.PtzControlAsync(ptzDto.Action, ptzDto.Stop, ptzDto.Speed).Wait();
|
|||
|
|
}
|
|||
|
|
return CommandResult.Ok("PTZ Executed");
|
|||
|
|
}
|
|||
|
|
return CommandResult.Fail("Device does not support PTZ");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==========================================
|
|||
|
|
// 2. 远程重启
|
|||
|
|
// ==========================================
|
|||
|
|
case "REBOOT":
|
|||
|
|
{
|
|||
|
|
var device = manager.GetDevice(deviceId);
|
|||
|
|
if (device == null) return CommandResult.Fail("Device Not Found");
|
|||
|
|
|
|||
|
|
if (device is IRebootFeature rebootFeature)
|
|||
|
|
{
|
|||
|
|
rebootFeature.RebootAsync().Wait();
|
|||
|
|
return CommandResult.Ok("Reboot command sent");
|
|||
|
|
}
|
|||
|
|
return CommandResult.Fail("Device does not support Reboot");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==========================================
|
|||
|
|
// 3. 时间同步
|
|||
|
|
// ==========================================
|
|||
|
|
case "SYNC_TIME":
|
|||
|
|
{
|
|||
|
|
var device = manager.GetDevice(deviceId);
|
|||
|
|
if (device == null) return CommandResult.Fail("Device Not Found");
|
|||
|
|
|
|||
|
|
if (device is ITimeSyncFeature timeFeature)
|
|||
|
|
{
|
|||
|
|
timeFeature.SetTimeAsync(DateTime.Now).Wait();
|
|||
|
|
return CommandResult.Ok("Time synced");
|
|||
|
|
}
|
|||
|
|
return CommandResult.Fail("Device does not support TimeSync");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==========================================
|
|||
|
|
// 4. 系统级指令 (心跳/诊断)
|
|||
|
|
// ==========================================
|
|||
|
|
case "PING":
|
|||
|
|
return CommandResult.Ok("PONG");
|
|||
|
|
|
|||
|
|
default:
|
|||
|
|
return CommandResult.Fail($"Unknown Command: {cmd}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (AggregateException ae)
|
|||
|
|
{
|
|||
|
|
// 捕获异步任务内部的异常
|
|||
|
|
return CommandResult.Fail($"Execution Error: {ae.InnerException?.Message}");
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
return CommandResult.Fail($"Execution Error: {ex.Message}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|