Initial commit
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace RobotNet10.FleetManager.Hubs;
|
||||
|
||||
/// <summary>
|
||||
/// SignalR Hub for real-time robot state and visualization updates.
|
||||
/// Manages client subscriptions to robot groups for receiving VDA5050 messages.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Clients subscribe to specific robots using SubscribeToRobot method.
|
||||
/// Messages are broadcast to groups named "robot:{robotId}".
|
||||
/// </remarks>
|
||||
public class RobotStateHub(
|
||||
Services.Logger<RobotStateHub> logger,
|
||||
RobotStateHubContext hubContext) : Hub
|
||||
{
|
||||
private readonly Services.Logger<RobotStateHub> _logger = logger;
|
||||
private readonly RobotStateHubContext _hubContext = hubContext;
|
||||
|
||||
/// <summary>
|
||||
/// Subscribe to receive updates for a specific robot
|
||||
/// </summary>
|
||||
/// <param name="robotId">Robot identifier (serialNumber)</param>
|
||||
public async Task SubscribeToRobot(string robotId)
|
||||
{
|
||||
var groupName = GetGroupName(robotId);
|
||||
await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unsubscribe from updates for a specific robot
|
||||
/// </summary>
|
||||
/// <param name="robotId">Robot identifier (serialNumber)</param>
|
||||
public async Task UnsubscribeFromRobot(string robotId)
|
||||
{
|
||||
var groupName = GetGroupName(robotId);
|
||||
await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
|
||||
}
|
||||
|
||||
private static string GetGroupName(string robotId)
|
||||
{
|
||||
return $"robot:{robotId}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribe to receive monitor updates for a specific levelId
|
||||
/// Each connection can only subscribe to one levelId at a time.
|
||||
/// Maximum 5 connections per levelId (FIFO).
|
||||
/// </summary>
|
||||
/// <param name="levelId">Level identifier (LayoutLevel.Id)</param>
|
||||
public async Task SubscribeToLevelForMonitor(Guid levelId)
|
||||
{
|
||||
var evictedConnectionId = _hubContext.SubscribeToLevel(Context.ConnectionId, levelId);
|
||||
|
||||
// If a connection was evicted, notify it
|
||||
if (evictedConnectionId != null)
|
||||
{
|
||||
_logger.Info($"Connection {evictedConnectionId} evicted from level {levelId} (max 5 connections reached)");
|
||||
await Clients.Client(evictedConnectionId).SendAsync("OnMonitorDeactivated");
|
||||
}
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unsubscribe from monitor updates for the current level
|
||||
/// </summary>
|
||||
public async Task UnsubscribeFromLevelForMonitor()
|
||||
{
|
||||
var removed = _hubContext.UnsubscribeFromLevel(Context.ConnectionId);
|
||||
if (removed)
|
||||
{
|
||||
_logger.Info($"Client {Context.ConnectionId} unsubscribed from level for monitor");
|
||||
}
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override async Task OnDisconnectedAsync(Exception? exception)
|
||||
{
|
||||
// Remove connection from subscription manager
|
||||
_hubContext.RemoveConnection(Context.ConnectionId);
|
||||
|
||||
if (exception != null)
|
||||
{
|
||||
_logger.Warning($"Client {Context.ConnectionId} disconnected with error: {exception.Message}");
|
||||
}
|
||||
await base.OnDisconnectedAsync(exception);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user