97 lines
3.4 KiB
C#
97 lines
3.4 KiB
C#
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)。
|
||
// 如果连接了多个 Dashboard,SendFrame 一次只会发给其中一个。
|
||
// 为了确保所有 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);
|
||
}
|
||
}
|
||
}
|
||
} |