2026-01-09 12:30:36 +08:00
|
|
|
|
// 文件: Core\CmdClients\CommandDispatcher.cs
|
|
|
|
|
|
|
|
|
|
|
|
using MessagePack;
|
|
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
|
|
using SHH.Contracts;
|
|
|
|
|
|
using System.Text;
|
2026-01-07 10:59:03 +08:00
|
|
|
|
|
|
|
|
|
|
namespace SHH.CameraService;
|
|
|
|
|
|
|
|
|
|
|
|
public class CommandDispatcher
|
|
|
|
|
|
{
|
2026-01-09 12:30:36 +08:00
|
|
|
|
// 1. 注入路由表
|
2026-01-07 10:59:03 +08:00
|
|
|
|
private readonly Dictionary<string, ICommandHandler> _handlers;
|
|
|
|
|
|
|
2026-01-09 12:30:36 +08:00
|
|
|
|
// 2. 定义回执事件 (ACK闭环的核心)
|
|
|
|
|
|
public event Action<CommandResult>? OnResponseReady;
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 构造函数:注入所有 Handler
|
2026-01-07 10:59:03 +08:00
|
|
|
|
public CommandDispatcher(IEnumerable<ICommandHandler> handlers)
|
|
|
|
|
|
{
|
2026-01-09 12:30:36 +08:00
|
|
|
|
// 将注入的 Handler 转换为字典,Key = ActionName (e.g. "SyncCamera")
|
|
|
|
|
|
_handlers = handlers.ToDictionary(h => h.ActionName, h => h, StringComparer.OrdinalIgnoreCase);
|
2026-01-07 10:59:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-09 12:30:36 +08:00
|
|
|
|
public async Task DispatchAsync(string protocol, byte[] data)
|
2026-01-07 10:59:03 +08:00
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
2026-01-09 12:30:36 +08:00
|
|
|
|
// 只处理 COMMAND 协议
|
|
|
|
|
|
if (protocol != ProtocolHeaders.Command) return;
|
|
|
|
|
|
|
|
|
|
|
|
// 反序列化信封
|
|
|
|
|
|
var envelope = MessagePackSerializer.Deserialize<CommandPayload>(data);
|
|
|
|
|
|
if (envelope == null) return;
|
2026-01-07 10:59:03 +08:00
|
|
|
|
|
2026-01-09 12:30:36 +08:00
|
|
|
|
string cmdCode = envelope.CmdCode; // e.g. "SyncCamera"
|
|
|
|
|
|
Console.WriteLine($"[分发] 收到指令: {cmdCode} (ID: {envelope.RequestId})");
|
2026-01-07 10:59:03 +08:00
|
|
|
|
|
2026-01-09 12:30:36 +08:00
|
|
|
|
bool isSuccess = true;
|
|
|
|
|
|
string message = "OK";
|
|
|
|
|
|
|
|
|
|
|
|
// --- 路由匹配逻辑 ---
|
|
|
|
|
|
if (_handlers.TryGetValue(cmdCode, out var handler))
|
2026-01-07 10:59:03 +08:00
|
|
|
|
{
|
2026-01-09 12:30:36 +08:00
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
// 数据适配:你的 Handler 需要 JToken
|
|
|
|
|
|
// 如果 envelope.JsonParams 是空的,传个空对象防止报错
|
|
|
|
|
|
var jsonStr = string.IsNullOrEmpty(envelope.JsonParams) ? "{}" : envelope.JsonParams;
|
|
|
|
|
|
var token = JToken.Parse(jsonStr);
|
|
|
|
|
|
|
|
|
|
|
|
// ★★★ 核心:调用 SyncCameraHandler.ExecuteAsync ★★★
|
|
|
|
|
|
await handler.ExecuteAsync(token);
|
|
|
|
|
|
|
|
|
|
|
|
message = $"Executed {cmdCode}";
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
isSuccess = false;
|
|
|
|
|
|
message = $"Handler Error: {ex.Message}";
|
|
|
|
|
|
Console.WriteLine($"[业务异常] {message}");
|
|
|
|
|
|
}
|
2026-01-07 10:59:03 +08:00
|
|
|
|
}
|
2026-01-09 12:30:36 +08:00
|
|
|
|
else
|
2026-01-07 10:59:03 +08:00
|
|
|
|
{
|
2026-01-09 12:30:36 +08:00
|
|
|
|
isSuccess = false;
|
|
|
|
|
|
message = $"No handler found for {cmdCode}";
|
|
|
|
|
|
Console.WriteLine($"[警告] {message}");
|
2026-01-07 10:59:03 +08:00
|
|
|
|
}
|
2026-01-09 12:30:36 +08:00
|
|
|
|
|
|
|
|
|
|
// --- ACK 闭环逻辑 ---
|
|
|
|
|
|
if (envelope.RequireAck)
|
2026-01-07 10:59:03 +08:00
|
|
|
|
{
|
2026-01-09 12:30:36 +08:00
|
|
|
|
var result = new CommandResult
|
|
|
|
|
|
{
|
|
|
|
|
|
Protocol = ProtocolHeaders.CommandResult,
|
|
|
|
|
|
RequestId = envelope.RequestId, // 必须带回 ID
|
|
|
|
|
|
Success = isSuccess,
|
|
|
|
|
|
Message = message,
|
|
|
|
|
|
Timestamp = DateTime.Now.Ticks
|
|
|
|
|
|
};
|
|
|
|
|
|
// 触发事件
|
|
|
|
|
|
OnResponseReady?.Invoke(result);
|
2026-01-07 10:59:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
2026-01-09 12:30:36 +08:00
|
|
|
|
Console.WriteLine($"[Dispatcher] 致命错误: {ex.Message}");
|
2026-01-07 10:59:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|