using Microsoft.AspNetCore.SignalR; using RobotNet.RobotManager.Hubs; using RobotNet.RobotShares.Dtos; namespace RobotNet.RobotManager.Services.Traffic; public class TrafficPublisher(TrafficManager TrafficManager, IHubContext TrafficHub, LoggerController Logger) : IHostedService { private const int intervalTime = 2000; private WatchTimer? Timer; public readonly Dictionary TrafficMapActive = []; public List GetAgents(Guid MapId) { if (TrafficManager.TrafficMaps.TryGetValue(MapId, out TrafficMap? trafficMap)) { List agents = []; List lockedNodes = []; foreach (var agent in trafficMap.Agents) { if (trafficMap.Locked.TryGetValue(agent.Key, out List? locked) && locked is not null) lockedNodes = locked; var trafficConflict = trafficMap.Conflicts.FirstOrDefault(c => c.AgentRequest.Robot.SerialNumber == agent.Key); agents.Add(new() { RobotId = agent.Key, State = agent.Value.State, ReleaseNode = agent.Value.ReleaseNode, Nodes = agent.Value.Nodes, InNode = agent.Value.Nodes[agent.Value.InNodeIndex], LockedNodes = lockedNodes, SubNodes = agent.Value.SubNodes, GiveWayNodes = agent.Value.GivewayNodes, ConflictAgentId = trafficConflict is null ? "" : trafficConflict.AgentConflict.Robot.SerialNumber, ConflictNode = trafficConflict?.NodeConflict, }); } foreach (var agent in trafficMap.Locked) { if (agents.Any(a => a.RobotId == agent.Key)) continue; agents.Add(new() { RobotId = agent.Key, LockedNodes = agent.Value, }); } return agents; } return []; } private void TimerHandler() { try { foreach (var mapActive in TrafficMapActive) { var agents = GetAgents(mapActive.Key); if (agents.Count > 0) { var pub = Task.Run(async () => await TrafficHub.Clients.Client(mapActive.Value).SendAsync("TrafficAgentUpdated", agents)); pub.Wait(); } } } catch (Exception ex) { Logger.Error($"Robot Publisher Error: {ex}"); } } public async Task StartAsync(CancellationToken cancellationToken) { Timer = new(intervalTime, TimerHandler, Logger); Timer.Start(); await Task.Yield(); } public Task StopAsync(CancellationToken cancellationToken) { Timer?.Dispose(); return Task.CompletedTask; } }