Files
Ayay/SHH.CameraService/CommandClientWorker.cs

97 lines
3.4 KiB
C#
Raw Normal View History

2026-01-05 14:54:06 +08:00
using Microsoft.Extensions.Hosting;
using NetMQ;
using NetMQ.Sockets;
using Newtonsoft.Json;
using SHH.CameraSdk;
using System.Text;
namespace SHH.CameraService;
public class CommandClientWorker : BackgroundService
{
private readonly ServiceConfig _config;
public CommandClientWorker(ServiceConfig config)
{
_config = config;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
// 1. 如果不是主动/混合模式,不需要连接
if (!_config.ShouldConnect) return;
// ★★★ 核心修正:直接读取解析好的指令地址列表 ★★★
// 这些地址来自参数 --uris "IP,VideoPort&CommandPort" 中的 CommandPort 部分
var cmdUris = _config.CommandEndpoints;
if (cmdUris.Count == 0)
{
Console.WriteLine("[指令] 未在参数中找到指令通道地址(位于&符号右侧),跳过连接。");
return;
}
// 2. 初始化 Dealer Socket
using var dealer = new DealerSocket();
// 设置身份 (Identity),让 Dashboard 知道我是 "CameraApp_01"
string myIdentity = _config.AppId;
dealer.Options.Identity = Encoding.UTF8.GetBytes(myIdentity);
// 3. 连接所有目标 (支持多点控制)
foreach (var uri in cmdUris)
{
Console.WriteLine($"[指令] 连接控制端: {uri}");
dealer.Connect(uri);
}
// 4. 发送登录包 (握手)
// 构造心跳包
var heartbeat = new
{
Type = "Login",
Id = myIdentity,
Time = DateTime.Now
};
string loginJson = JsonConvert.SerializeObject(heartbeat);
// 注意Dealer Socket 发送是负载均衡的 (Round-Robin)。
// 如果连接了多个 DashboardSendFrame 一次只会发给其中一个。
// 为了确保所有 Dashboard 都能收到上线通知,我们根据连接数循环发送几次。
// (注:这只是初始化时的权宜之计,心跳包后续可以定时发送)
for (int i = 0; i < cmdUris.Count; i++)
{
dealer.SendFrame(loginJson);
await Task.Delay(10); // 稍微间隔,给 ZMQ 内部调度一点时间
}
Console.WriteLine($"[指令] 已发送登录包 (ID: {myIdentity}),进入监听循环...");
// 5. 监听循环
while (!stoppingToken.IsCancellationRequested)
{
try
{
// 非阻塞接收 (500ms 超时),避免卡死线程
if (dealer.TryReceiveFrameString(TimeSpan.FromMilliseconds(500), out string msg))
{
Console.WriteLine($"[指令] 收到: {msg}");
// TODO: 在这里解析 JSON 并调用 CameraSDK 执行业务
// var cmd = JsonConvert.DeserializeObject<CommandModel>(msg);
// if (cmd.Action == "Reboot") ...
// 回复 ACK (确认收到)
// Dealer 会自动根据 Router 发来的 RoutingID 路由回去
dealer.SendFrame($"ACK: {msg} (From {myIdentity})");
}
}
catch (Exception ex)
{
Console.WriteLine($"[指令] 通信异常: {ex.Message}");
// 防止异常死循环刷屏
await Task.Delay(1000, stoppingToken);
}
}
}
}