using Quartz; using WIDESEA_Core; using WIDESEAWCS_Core.Caches; using WIDESEAWCS_Core.Helper; using WIDESEAWCS_ITaskInfoService; using WIDESEAWCS_QuartzJob; using WIDESEAWCS_Tasks.Workflow.Abstractions; using WIDESEAWCS_Tasks.Workflow; using WIDESEAWCS_Tasks.SocketServer; namespace WIDESEAWCS_Tasks { /// /// 机器人任务作业:负责调度与生命周期管理,具体状态机流程交给编排器。 /// [DisallowConcurrentExecution] public class RobotJob : IJob { private const int MaxTaskTotalNum = 48; private static int _messageSubscribedFlag; private readonly RobotClientManager _clientManager; private readonly RobotStateManager _stateManager; private readonly IRobotMessageRouter _messageRouter; private readonly RobotTaskProcessor _taskProcessor; private readonly IRobotWorkflowOrchestrator _workflowOrchestrator; public RobotJob( TcpSocketServer tcpSocket, IRobotTaskService robotTaskService, ITaskService taskService, ICacheService cache, HttpClientHelper httpClientHelper) { _stateManager = new RobotStateManager(cache); // 收口 Socket 访问,后续若替换通信实现只需替换网关层。 ISocketClientGateway socketGateway = new SocketClientGateway(tcpSocket); _taskProcessor = new RobotTaskProcessor(socketGateway, _stateManager, robotTaskService, taskService, httpClientHelper); _clientManager = new RobotClientManager(tcpSocket, _stateManager); var simpleCommandHandler = new RobotSimpleCommandHandler(_taskProcessor); var prefixCommandHandler = new RobotPrefixCommandHandler(robotTaskService, _taskProcessor, _stateManager, socketGateway); _messageRouter = new RobotMessageHandler(socketGateway, _stateManager, cache, simpleCommandHandler, prefixCommandHandler); _workflowOrchestrator = new RobotWorkflowOrchestrator(_stateManager, _clientManager, _taskProcessor, robotTaskService); _clientManager.OnClientDisconnected += OnClientDisconnected; // 全局只订阅一次消息事件,保持原有行为。 if (System.Threading.Interlocked.CompareExchange(ref _messageSubscribedFlag, 1, 0) == 0) { tcpSocket.MessageReceived += _messageRouter.HandleMessageReceivedAsync; Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 机器手TCP消息事件已订阅"); } } private void OnClientDisconnected(object? sender, RobotSocketState state) { Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 客户端已断开连接: {state.IPAddress}"); } public async Task Execute(IJobExecutionContext context) { bool flag = context.JobDetail.JobDataMap.TryGetValue("JobParams", out object? value); RobotCraneDevice robotCrane = (RobotCraneDevice?)value ?? new RobotCraneDevice(); if (!flag || robotCrane.IsNullOrEmpty()) { return; } string ipAddress = robotCrane.IPAddress; RobotSocketState state = _stateManager.GetOrCreateState(ipAddress, robotCrane); state.RobotCrane = robotCrane; try { if (!_clientManager.EnsureClientSubscribed(ipAddress, robotCrane)) { return; } var task = _taskProcessor.GetTask(robotCrane); if (task != null) { var latestState = _stateManager.GetState(ipAddress); if (latestState == null) { return; } if (latestState.RobotTaskTotalNum < MaxTaskTotalNum) { await _workflowOrchestrator.ExecuteAsync(latestState, task, ipAddress); } } } catch (Exception) { // 异常处理已在组件内部进行,Job 层保持兜底吞吐语义。 } } } }