using Quartz; using System.Collections.Concurrent; using System.Net.Sockets; using WIDESEAWCS_Common.TaskEnum; using WIDESEAWCS_Core.Helper; using WIDESEAWCS_ITaskInfoRepository; using WIDESEAWCS_ITaskInfoService; using WIDESEAWCS_Model.Models; using WIDESEAWCS_QuartzJob; using WIDESEAWCS_QuartzJob.Service; using WIDESEAWCS_Tasks.SocketServer; namespace WIDESEAWCS_Tasks { [DisallowConcurrentExecution] public class StackerCraneJob : IJob { private readonly TcpSocketServer _TcpSocket; private static readonly ConcurrentDictionary _socketStates = new(); private static int _eventSubscribedFlag; private readonly ITaskService _taskService; private readonly ITaskExecuteDetailService _taskExecuteDetailService; private readonly ITaskRepository _taskRepository; private readonly IRouterService _routerService; public StackerCraneJob(TcpSocketServer TcpSocket, ITaskService taskService, ITaskExecuteDetailService taskExecuteDetailService, ITaskRepository taskRepository, IRouterService routerService) { _TcpSocket = TcpSocket; _taskService = taskService; _taskExecuteDetailService = taskExecuteDetailService; _taskRepository = taskRepository; _routerService = routerService; } public async Task Execute(IJobExecutionContext context) { bool flag = context.JobDetail.JobDataMap.TryGetValue("JobParams", out object? value); StackerCraneDevice Crane = (StackerCraneDevice?)value ?? new StackerCraneDevice(); if (!flag || Crane.IsNullOrEmpty()) { return; } string ipAddress = Crane.IPAddress; // 获取或创建状态 StackerSocketState state = _socketStates.GetOrAdd(ipAddress, _ => new StackerSocketState { IPAddress = ipAddress, StackerCrane = Crane }); // 更新设备信息 state.StackerCrane = Crane; // 检查是否有该客户端连接 var clientIds = _TcpSocket.GetClientIds(); if (!clientIds.Contains(ipAddress)) { return; } // 订阅一次 message 事件(全局一次) if (Interlocked.CompareExchange(ref _eventSubscribedFlag, 1, 0) == 0) { _TcpSocket.MessageReceived += _TcpSocket_MessageReceived; _TcpSocket.RobotReceived += _TcpSocket_RobotReceived; } if (!state.IsEventSubscribed) { _TcpSocket._clients.TryGetValue(ipAddress, out TcpClient client); Task clientTask = _TcpSocket.HandleClientAsync(client, Crane.IPAddress, _TcpSocket._cts.Token, state); state.IsEventSubscribed = true; } // 获取当前需下发任务并缓存到状态中 Dt_Task? task = GetTask(Crane); if (task != null && state.CurrentTask == null && state.StackerRunMode== && state.StackerTaskNum == 0) { SendStackerTask(task, state); } return; } /// /// 事件:客户端断开连接时触发 /// /// /// private Task _TcpSocket_RobotReceived(string clientId) { _socketStates.TryRemove(clientId, out _); return Task.FromResult(null); } /// /// 事件:收到消息时触发 /// /// /// /// /// /// private async Task _TcpSocket_MessageReceived(string message, bool isJson, TcpClient client, StackerSocketState state) { string messageLower = message.ToUpperInvariant(); //区分堆垛机发送命令 try { } catch { } return null; } /// /// 堆垛机任务下发 /// private bool SendStackerTask(Dt_Task task, StackerSocketState state) { string message = "<"; //获取对起始和终点位置进行解析 message += ">"; return _TcpSocket.SendToDeviceAsync(state.IPAddress, message).Result; } private Dt_Task? GetTask(StackerCraneDevice stackerCrane, TaskTypeGroup? taskTypeGroup = null) { return _taskService.QueryStackerTask(stackerCrane.DeviceCode,taskTypeGroup); } } public class StackerSocketState { public string IPAddress { get; set; } = string.Empty; /// /// 是否已订阅消息事件 /// public bool IsEventSubscribed { get; set; } /// /// 堆垛机当前任务号 /// public int? StackerTaskNum { get; set; } /// /// 堆垛机运行模式
/// 1:自动模式
/// 2:停止模式
/// 3:手动模式或离线模式
///
public int? StackerRunMode { get; set; } /// /// 堆垛机故障状态
/// 正常
/// 故障
///
public int? StackerError { get; set; } /// /// 堆垛机设备信息 /// public StackerCraneDevice? StackerCrane { get; set; } /// /// 取货位置 /// public string? PickPosition { get; set; } /// /// 放货位置 /// public string? PutPosition{ get; set; } /// /// 当前任务 /// public Dt_Task? CurrentTask { get; set; } } public enum StackerModeEnum { /// /// 自动模式 /// Automatic = 1, /// /// 停止模式 /// Unkonw = 2, /// /// 手动模式 /// Manual = 3 } public enum StackerErrorEnum { /// /// 正常 /// Normal = 1, /// /// 故障 /// Fault = 2 } }