Files
Ayay/SHH.CameraService/CommandClientWorker.cs
2026-01-05 14:54:06 +08:00

97 lines
3.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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);
}
}
}
}