using Microsoft.AspNetCore.SignalR;
namespace AmtScanner.Api.Hubs;
///
/// 屏幕流信令 Hub - 用于控制设备推流质量和状态
///
public class StreamSignalingHub : Hub
{
private readonly ILogger _logger;
private static readonly Dictionary> _deviceWatchers = new();
private static readonly object _lock = new();
public StreamSignalingHub(ILogger logger)
{
_logger = logger;
}
///
/// 教师端开始监控(进入监控墙页面)
///
public async Task StartMonitoring(List deviceUuids)
{
var connectionId = Context.ConnectionId;
_logger.LogInformation("教师端 {ConnectionId} 开始监控 {Count} 台设备", connectionId, deviceUuids.Count);
lock (_lock)
{
foreach (var uuid in deviceUuids)
{
if (!_deviceWatchers.ContainsKey(uuid))
{
_deviceWatchers[uuid] = new HashSet();
}
_deviceWatchers[uuid].Add(connectionId);
}
}
// 通知所有设备开始低质量推流
await Clients.All.SendAsync("DevicesNeedStream", deviceUuids, "low");
}
///
/// 教师端停止监控(离开监控墙页面)
///
public async Task StopMonitoring()
{
var connectionId = Context.ConnectionId;
_logger.LogInformation("教师端 {ConnectionId} 停止监控", connectionId);
List devicesToStop = new();
lock (_lock)
{
// 移除该连接对所有设备的监控
foreach (var (uuid, watchers) in _deviceWatchers)
{
if (watchers.Remove(connectionId) && watchers.Count == 0)
{
devicesToStop.Add(uuid);
}
}
// 清理空的监控记录
foreach (var uuid in devicesToStop)
{
_deviceWatchers.Remove(uuid);
}
}
// 通知设备停止推流
if (devicesToStop.Count > 0)
{
await Clients.All.SendAsync("DevicesStopStream", devicesToStop);
}
}
///
/// 教师端选中某台设备(切换到高质量)
///
public async Task SelectDevice(string deviceUuid)
{
_logger.LogInformation("教师端 {ConnectionId} 选中设备 {DeviceUuid}", Context.ConnectionId, deviceUuid);
// 通知该设备切换到高质量
await Clients.All.SendAsync("DeviceQualityChange", deviceUuid, "high");
}
///
/// 教师端取消选中设备(切换回低质量)
///
public async Task DeselectDevice(string deviceUuid)
{
_logger.LogInformation("教师端 {ConnectionId} 取消选中设备 {DeviceUuid}", Context.ConnectionId, deviceUuid);
// 通知该设备切换回低质量
await Clients.All.SendAsync("DeviceQualityChange", deviceUuid, "low");
}
///
/// 设备端注册(Agent 启动时调用)
///
public async Task RegisterDevice(string deviceUuid)
{
_logger.LogInformation("设备 {DeviceUuid} 注册到 SignalR Hub", deviceUuid);
// 加入设备专属组
await Groups.AddToGroupAsync(Context.ConnectionId, $"device_{deviceUuid}");
// 检查是否有人正在监控该设备
bool isBeingWatched;
lock (_lock)
{
isBeingWatched = _deviceWatchers.ContainsKey(deviceUuid) && _deviceWatchers[deviceUuid].Count > 0;
}
// 如果有人监控,通知设备开始推流
if (isBeingWatched)
{
await Clients.Caller.SendAsync("StartStream", "low");
}
}
///
/// 设备端取消注册(Agent 关闭时调用)
///
public async Task UnregisterDevice(string deviceUuid)
{
_logger.LogInformation("设备 {DeviceUuid} 从 SignalR Hub 取消注册", deviceUuid);
await Groups.RemoveFromGroupAsync(Context.ConnectionId, $"device_{deviceUuid}");
}
///
/// 连接断开时清理
///
public override async Task OnDisconnectedAsync(Exception? exception)
{
var connectionId = Context.ConnectionId;
_logger.LogInformation("连接 {ConnectionId} 断开", connectionId);
// 清理监控记录
List devicesToStop = new();
lock (_lock)
{
foreach (var (uuid, watchers) in _deviceWatchers)
{
if (watchers.Remove(connectionId) && watchers.Count == 0)
{
devicesToStop.Add(uuid);
}
}
foreach (var uuid in devicesToStop)
{
_deviceWatchers.Remove(uuid);
}
}
// 通知设备停止推流
if (devicesToStop.Count > 0)
{
await Clients.All.SendAsync("DevicesStopStream", devicesToStop);
}
await base.OnDisconnectedAsync(exception);
}
///
/// 获取当前监控状态(调试用)
///
public Dictionary GetMonitoringStatus()
{
lock (_lock)
{
return _deviceWatchers.ToDictionary(
kvp => kvp.Key,
kvp => kvp.Value.Count
);
}
}
}