74 lines
2.8 KiB
C#
74 lines
2.8 KiB
C#
|
|
using Microsoft.AspNetCore.SignalR;
|
|||
|
|
using SHH.Contracts;
|
|||
|
|
using System.Collections.Concurrent;
|
|||
|
|
|
|||
|
|
namespace SHH.CameraDashboard
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// [SignalR 中心]
|
|||
|
|
/// 职责:负责物理链路的维护,将网络消息路由到业务层 (CommandServer)
|
|||
|
|
/// </summary>
|
|||
|
|
public class CameraHub : Hub
|
|||
|
|
{
|
|||
|
|
// 静态映射表:InstanceId -> ConnectionId (用于定向发指令)
|
|||
|
|
private static readonly ConcurrentDictionary<string, string> _instanceMapping = new();
|
|||
|
|
|
|||
|
|
// =================================================================
|
|||
|
|
// 1. 注册逻辑 (替代原 CommandServer.HandleRegistration)
|
|||
|
|
// =================================================================
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 供 CameraService 调用
|
|||
|
|
/// </summary>
|
|||
|
|
public async Task Register(RegisterPayload payload)
|
|||
|
|
{
|
|||
|
|
string connectionId = Context.ConnectionId;
|
|||
|
|
|
|||
|
|
// 1. 记录映射关系
|
|||
|
|
_instanceMapping[payload.InstanceId] = connectionId;
|
|||
|
|
|
|||
|
|
// 2. 将连接加入组 (按 InstanceId 组队,方便 CommandServer 发指令)
|
|||
|
|
await Groups.AddToGroupAsync(connectionId, payload.InstanceId);
|
|||
|
|
|
|||
|
|
// 3. 回调业务单例处理 UI 逻辑
|
|||
|
|
CommandServer.Instance.HandleClientRegister(payload);
|
|||
|
|
|
|||
|
|
Console.WriteLine($"[Hub] 收到注册: {payload.InstanceId}, 连接ID: {connectionId}");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// =================================================================
|
|||
|
|
// 2. 指令回执
|
|||
|
|
// =================================================================
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 供 CameraService 执行完指令后调用
|
|||
|
|
/// </summary>
|
|||
|
|
public void ReportCommandResult(CommandResult result)
|
|||
|
|
{
|
|||
|
|
CommandServer.Instance.HandleCommandResult(result);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// =================================================================
|
|||
|
|
// 3. 视频流中转
|
|||
|
|
// =================================================================
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 供 CameraService 上传图片
|
|||
|
|
/// </summary>
|
|||
|
|
public async Task UploadFrame(VideoPayload payload)
|
|||
|
|
{
|
|||
|
|
// 转发给订阅了该摄像头的组 (例如 Dashboard UI 订阅了该组)
|
|||
|
|
await Clients.Group($"Watch_{payload.CameraId}").SendAsync("OnFrameRecv", payload);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// =================================================================
|
|||
|
|
// 生命周期管理
|
|||
|
|
// =================================================================
|
|||
|
|
|
|||
|
|
public override async Task OnDisconnectedAsync(Exception? exception)
|
|||
|
|
{
|
|||
|
|
// 清理映射逻辑可以在这里扩展
|
|||
|
|
await base.OnDisconnectedAsync(exception);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|