视频SDK新协议签入
This commit is contained in:
123
SHH.CameraService/Grpc/CommandReceiverWorker.cs
Normal file
123
SHH.CameraService/Grpc/CommandReceiverWorker.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
using Grpc.Core;
|
||||
using Grpc.Net.Client;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using SHH.CameraSdk;
|
||||
using SHH.Contracts;
|
||||
using SHH.Contracts.Grpc; // 引用 Proto 生成的命名空间
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SHH.CameraService
|
||||
{
|
||||
/// <summary>
|
||||
/// gRPC 指令接收后台服务
|
||||
/// 负责:1. 逻辑注册 2. 维持指令长连接 3. 指令分发
|
||||
/// </summary>
|
||||
public class GrpcCommandReceiverWorker : BackgroundService
|
||||
{
|
||||
private readonly ILogger<GrpcCommandReceiverWorker> _logger;
|
||||
private readonly ServiceConfig _config;
|
||||
private readonly IEnumerable<ICommandHandler> _handlers; // 自动注入所有指令处理器
|
||||
|
||||
public GrpcCommandReceiverWorker(
|
||||
ILogger<GrpcCommandReceiverWorker> logger,
|
||||
ServiceConfig config,
|
||||
IEnumerable<ICommandHandler> handlers)
|
||||
{
|
||||
_logger = logger;
|
||||
_config = config;
|
||||
_handlers = handlers;
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
// 给 SDK 和数据库留出几秒钟的加载时间
|
||||
_logger.LogInformation("[gRPC Bus] 后台 Worker 准备就绪,3秒后发起连接...");
|
||||
await Task.Delay(3000, stoppingToken);
|
||||
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 1. 地址预处理 (将 127.0.0.1 强制转换为 localhost 解决 Unimplemented 问题)
|
||||
var ep = _config.CommandEndpoints.First();
|
||||
string targetUrl = ep.Uri.Replace("tcp://", "http://").Replace("127.0.0.1", "localhost");
|
||||
|
||||
using var channel = GrpcChannel.ForAddress(targetUrl);
|
||||
var client = new GatewayProvider.GatewayProviderClient(channel);
|
||||
|
||||
// --- 第一步:发起逻辑注册 (Unary) ---
|
||||
_logger.LogInformation("[gRPC Bus] 正在发起逻辑注册: {Url}", targetUrl);
|
||||
var regResp = await client.RegisterInstanceAsync(new RegisterRequest
|
||||
{
|
||||
InstanceId = _config.AppId,
|
||||
Version = "2.0.0-grpc",
|
||||
ServerIp = "127.0.0.1",
|
||||
StartTimeTicks = DateTime.Now.Ticks
|
||||
}, cancellationToken: stoppingToken);
|
||||
|
||||
if (regResp.Success)
|
||||
{
|
||||
_logger.LogInformation("[gRPC Bus] 逻辑注册成功。正在开启长连接指令通道...");
|
||||
|
||||
// --- 第二步:开启物理指令流 (Server Streaming) ---
|
||||
using var call = client.OpenCommandChannel(new CommandStreamRequest
|
||||
{
|
||||
InstanceId = _config.AppId
|
||||
}, cancellationToken: stoppingToken);
|
||||
|
||||
// --- 第三步:阻塞式监听服务端推送 ---
|
||||
// 只要服务端通过 responseStream.WriteAsync 发消息,这里就会命中
|
||||
while (await call.ResponseStream.MoveNext(stoppingToken))
|
||||
{
|
||||
var protoMsg = call.ResponseStream.Current;
|
||||
_logger.LogInformation("[gRPC Bus] 收到远程指令: {CmdCode}", protoMsg.CmdCode);
|
||||
|
||||
// 异步分发,不阻塞接收循环
|
||||
_ = DispatchCommandAsync(protoMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException) { break; }
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("[gRPC Bus] 链路异常,5秒后重试: {Msg}", ex.Message);
|
||||
await Task.Delay(5000, stoppingToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 指令分发逻辑
|
||||
/// </summary>
|
||||
private async Task DispatchCommandAsync(CommandPayloadProto msg)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 1. 寻找匹配的处理器 (SyncCameraHandler / RemoveCameraHandler)
|
||||
var handler = _handlers.FirstOrDefault(h => h.ActionName == msg.CmdCode);
|
||||
|
||||
if (handler != null)
|
||||
{
|
||||
// 2. 将 Proto 的参数转为 JToken,保持与原有处理器兼容
|
||||
var jsonParams = JToken.Parse(msg.JsonParams);
|
||||
await handler.ExecuteAsync(jsonParams);
|
||||
_logger.LogInformation("[gRPC Bus] 指令 {CmdCode} 执行完成", msg.CmdCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning("[gRPC Bus] 未找到处理 {CmdCode} 的处理器", msg.CmdCode);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "[gRPC Bus] 指令执行失败: {CmdCode}", msg.CmdCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user