using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.SignalR; using RobotNet10.RobotApp.Detection; using RobotNet10.Shared; using RobotNet10.Shared.Detection; using RobotNet10.Shared.Geometry; namespace RobotNet10.RobotApp.Hubs; [Authorize] public class MarkerDetectorHub(IMarkerDetector markerDetector, ILogger logger) : Hub { private const string SessionKey = "DetectSessionId"; public async Task> CreateSession(MarkersSearchRequest request) { try { // If this client already has a session, dispose it first if (Context.Items.TryGetValue(SessionKey, out var existing) && existing is Guid existingSessionId) { var existingSession = markerDetector.GetSession(existingSessionId); existingSession?.Dispose(); Context.Items.Remove(SessionKey); logger.LogInformation("Disposed existing session {SessionId} for client {ConnectionId}", existingSessionId, Context.ConnectionId); } request.Yaw = Math.PI * request.Yaw / 180.0; var session = await markerDetector.CreateSessionAsync(request); Context.Items[SessionKey] = session.SessionId; logger.LogInformation("Created session {SessionId} for client {ConnectionId}", session.SessionId, Context.ConnectionId); return new MessageResult(true, session.SessionId); } catch (Exception ex) { logger.LogError(ex, "Failed to create detect session for client {ConnectionId}", Context.ConnectionId); return new MessageResult(false, Message: ex.Message); } } public MessageResult GetGoal(Guid sessionId) { var session = markerDetector.GetSession(sessionId); if (session == null) return new(false, Message: $"Session '{sessionId}' not found."); if (session.Goal.HasValue) { return new(true, session.Goal.Value.Pose); } else { return new(false); } } public override async Task OnDisconnectedAsync(Exception? exception) { if (Context.Items.TryGetValue(SessionKey, out var existing) && existing is Guid sessionId) { var session = markerDetector.GetSession(sessionId); session?.Dispose(); logger.LogInformation("Disposed session {SessionId} on disconnect of client {ConnectionId}", sessionId, Context.ConnectionId); } await base.OnDisconnectedAsync(exception); } }