using MessagePack; using Microsoft.Extensions.Hosting; using NetMQ; using NetMQ.Sockets; using SHH.CameraSdk; using SHH.Contracts; using System.Text; namespace SHH.CameraService; public class CommandClientWorker : BackgroundService { private readonly ServiceConfig _config; private readonly CommandDispatcher _dispatcher; // ★ 1. 注入拦截器管道管理器 private readonly InterceptorPipeline _pipeline; public CommandClientWorker( ServiceConfig config, CommandDispatcher dispatcher, InterceptorPipeline pipeline) // <--- 注入 { _config = config; _dispatcher = dispatcher; _pipeline = pipeline; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { await Task.Yield(); if (!_config.ShouldConnect) return; if (_config.CommandEndpoints.Count == 0) return; using var dealer = new DealerSocket(); string myIdentity = _config.AppId; dealer.Options.Identity = Encoding.UTF8.GetBytes(myIdentity); foreach (var ep in _config.CommandEndpoints) { try { dealer.Connect(ep.Uri); } catch (Exception ex) { Console.WriteLine($"[指令] 连接失败 {ep.Uri}: {ex.Message}"); } } string localIp = "127.0.0.1"; // ... (获取 IP 代码省略,保持不变) ... // ================================================================= // 构建注册包 // ================================================================= var registerPayload = new RegisterPayload { Protocol = ProtocolHeaders.ServerRegister, InstanceId = _config.AppId, ProcessId = Environment.ProcessId, Version = "1.0.0", ServerIp = localIp, WebApiPort = _config.BasePort, StartTime = DateTime.Now }; try { byte[] regData = MessagePackSerializer.Serialize(registerPayload); // ============================================================= // ★ 2. 拦截点 A: 发送注册包 (Outbound) // ============================================================= var ctx = await _pipeline.ExecuteSendAsync(ProtocolHeaders.ServerRegister, regData); if (ctx != null) // 如果未被拦截 { // 注意:这里使用 ctx.Protocol 和 ctx.Data,允许拦截器修改内容 dealer.SendMoreFrame(ctx.Protocol) .SendFrame(ctx.Data); Console.WriteLine($"[指令] 注册包已发送 ({ctx.Data.Length} bytes)"); } } catch (Exception ex) { Console.WriteLine($"[致命错误] 注册流程异常: {ex.Message}"); return; } // ================================================================= // 定义 ACK 发送逻辑 (包含拦截器) // ================================================================= // 注意:这里需要 async,因为拦截器是异步的 Action sendAckHandler = async (result) => { try { byte[] resultBytes = MessagePackSerializer.Serialize(result); // ========================================================= // ★ 3. 拦截点 B: 发送 ACK 回执 (Outbound) // ========================================================= // 协议头是 COMMAND_RESULT var ctx = await _pipeline.ExecuteSendAsync(ProtocolHeaders.CommandResult, resultBytes); if (ctx != null) { dealer.SendMoreFrame(ctx.Protocol) .SendFrame(ctx.Data); Console.WriteLine($"[指令] 已回复 ACK -> Req: {result.RequestId}"); } } catch (Exception ex) { Console.WriteLine($"[ACK Error] 回执发送失败: {ex.Message}"); } }; // 订阅事件 (需要适配 async void,注意异常捕获) _dispatcher.OnResponseReady += async (res) => await Task.Run(() => sendAckHandler(res)); // ================================================================= // 接收循环 // ================================================================= try { while (!stoppingToken.IsCancellationRequested) { NetMQMessage incomingMsg = new NetMQMessage(); if (dealer.TryReceiveMultipartMessage(TimeSpan.FromMilliseconds(500), ref incomingMsg)) { if (incomingMsg.FrameCount >= 2) { string rawProtocol = incomingMsg[0].ConvertToString(); byte[] rawData = incomingMsg[1].ToByteArray(); // ================================================= // ★ 4. 拦截点 C: 接收指令 (Inbound) // ================================================= var ctx = await _pipeline.ExecuteReceiveAsync(rawProtocol, rawData); if (ctx != null) // 如果未被拦截 { // 将处理后的数据交给 Dispatcher await _dispatcher.DispatchAsync(ctx.Protocol, ctx.Data); } } } } } catch (Exception ex) { Console.WriteLine($"[指令] 接收循环异常: {ex.Message}"); } } }