using HslCommunication; using Newtonsoft.Json; using Quartz; using System.Collections.Concurrent; using System.Net.Sockets; using System.Text.Json; using WIDESEAWCS_Common.HttpEnum; using WIDESEAWCS_Core; using WIDESEAWCS_Core.Helper; using WIDESEAWCS_Core.Http; using WIDESEAWCS_DTO.Stock; using WIDESEAWCS_DTO.TaskInfo; 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 RobotJob : IJob { private readonly TcpSocketServer _TcpSocket; private static readonly ConcurrentDictionary _socketStates = new(); private static int _eventSubscribedFlag; private readonly IRobotTaskService _taskService; private readonly ITaskExecuteDetailService _taskExecuteDetailService; private readonly ITaskRepository _taskRepository; private readonly IRouterService _routerService; public RobotJob(TcpSocketServer TcpSocket, IRobotTaskService taskService) { _TcpSocket = TcpSocket; _taskService = taskService; } 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 = _socketStates.GetOrAdd(ipAddress, _ => new RobotSocketState { IPAddress = ipAddress, RobotCrane = robotCrane }); // 更新设备信息 state.RobotCrane = robotCrane; // 检查是否有该客户端连接 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, robotCrane.IPAddress, _TcpSocket._cts.Token, state); state.IsEventSubscribed = true; } // 获取任务并缓存到状态中 Dt_RobotTask? task = GetTask(robotCrane); if (task != null) { state.CurrentTask = task; if (task.RobotTaskTotalNum != 48) { // 处理正在执行的任务 if (state.RobotRunMode == 1 && state.RobotControlMode == 1) { await Task.Delay(1000); if ((state.CurrentAction == "Homed" || state.CurrentAction == "PickFinished" || state.CurrentAction == "PutFinished") && state.OperStatus == "Running") { // TODO 读取线体电池条码,发送取电池指令 if (true) { // 模拟读取条码 state.CellBarcode = new string[] { "CellBarcode1", "CellBarcode2", "CellBarcode3", "CellBarcode4" }; string taskString = $"Pickbattery,{task.RobotSourceAddress}"; // 发送任务指令 bool result = await _TcpSocket.SendToClientAsync(ipAddress, taskString); } } } } } 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, RobotSocketState state) { WebResponseContent content = new WebResponseContent(); string messageLower = message.ToLowerInvariant(); if (IsSimpleCommand(messageLower, state)) { return null; } if (IsPrefixCommand(messageLower)) { try { var parts = message.Split(','); if (parts.Length >= 1) { var cmd = parts[0].ToLowerInvariant(); int[] positions = new int[4]; for (int i = 1; i <= 4 && i < parts.Length; i++) { int.TryParse(parts[i], out positions[i - 1]); } if (cmd.StartsWith("pickfinished")) { StockDTO stockDTO = new StockDTO { SourceLineNo = state.CurrentTask?.RobotSourceAddressLineCode, SourcePalletNo = state.CurrentTask?.RobotSourceAddressPalletCode, TargetPalletNo = state.CurrentTask?.RobotTargetAddressPalletCode, TargetLineNo = state.CurrentTask?.RobotTargetAddressLineCode, Details = positions .Where(x => x > 0) .OrderBy(x => x) .Select((x, idx) => new StockDetailDTO { Quantity = state.CurrentTask?.RobotTaskTotalNum ?? 1, Channel = x > 0 ? x : throw new ArgumentOutOfRangeException(nameof(x), "Channel must be positive"), CellBarcode = state.CellBarcode[idx] }) .ToList() }; state.LastPickPositions = positions; var result = await HttpRequestHelper.HTTPPostAsync(nameof(Category.WMS), stockDTO.ToJsonString(), state.CurrentTask?.RobotTaskType == 2 ? nameof(ConfigKey.ChangePalletAsync) : nameof(ConfigKey.SplitPalletAsync)); content = JsonConvert.DeserializeObject(result); if (content.Status) { state.CurrentAction = "PickFinished"; } } else if (cmd.StartsWith("putfinished")) { state.LastPutPositions = positions; if (state.CurrentTask?.RobotTaskType == 1) { // 发送数据给WMS组盘/换盘 StockDTO stockDTO = new StockDTO { SourceLineNo = state.CurrentTask?.RobotSourceAddressLineCode, SourcePalletNo = state.CurrentTask?.RobotSourceAddressPalletCode, TargetPalletNo = state.CurrentTask?.RobotTargetAddressPalletCode, TargetLineNo = state.CurrentTask?.RobotTargetAddressLineCode, Details = positions .Where(x => x > 0) .OrderBy(x => x) .Select((x, idx) => new StockDetailDTO { Quantity = state.CurrentTask?.RobotTaskTotalNum ?? 1, Channel = x > 0 ? x : throw new ArgumentOutOfRangeException(nameof(x), "Channel must be positive"), CellBarcode = state.CellBarcode[idx] }) .ToList() }; var result = await HttpRequestHelper.HTTPPostAsync(nameof(Category.WMS), stockDTO.ToJsonString(), nameof(ConfigKey.GroupPalletAsync)); content = JsonConvert.DeserializeObject(result); if (content.Status) { state.CurrentAction = "PutFinished"; } } } } } catch { } return null; } return null; } /// /// 机械手简单命令处理 /// /// /// /// private bool IsSimpleCommand(string message, RobotSocketState state) { switch (message) { case "homing": state.CurrentAction = "Homing"; return true; case "homed": state.CurrentAction = "Homed"; return true; case "picking": state.CurrentAction = "Picking"; return true; case "puting": state.CurrentAction = "Putting"; return true; case "allpickfinished": state.CurrentAction = "AllPickFinished"; if (state.CurrentTask?.RobotTaskType == 2 || state.CurrentTask?.RobotTaskType == 3) { // TODO 机械手取货完成,判断是否换盘、拆盘任务,创建空托盘回库任务 } return true; case "allputfinished": state.CurrentAction = "AllPutFinished"; if (state.CurrentTask?.RobotTaskType == 1) { // TODO 机械手取货完成,判断是否组盘任务,创建组盘入库任务 CreateTaskDto taskDto = new CreateTaskDto() { PalletCode = state.CurrentTask?.RobotTargetAddressPalletCode ?? string.Empty, SourceAddress = state.CurrentTask?.RobotTargetAddress ?? string.Empty, TargetAddress = state.CurrentTask?.RobotTargetAddress ?? string.Empty, Roadway = state.CurrentTask?.RobotRoadway == "1" ? "GWSC001" : state.CurrentTask?.RobotRoadway == "2" ? "HCSC001" : "SC001" ?? string.Empty, WarehouseId = state.CurrentTask?.RobotRoadway == "1" ? 1 : state.CurrentTask?.RobotRoadway == "2" ? 2 : 3, PalletType = 1, TaskType = 4 }; } return true; case "running": state.OperStatus = "Running"; return true; case "pausing": state.OperStatus = "Pausing"; return true; case "warming": state.OperStatus = "Warming"; return true; case "emstoping": state.OperStatus = "Emstoping"; return true; case "runmode,1": state.RobotRunMode = 1; return true; case "runmode,2": state.RobotRunMode = 2; return true; case "controlmode,1": state.RobotControlMode = 1; return true; case "controlmode,2": state.RobotControlMode = 2; return true; case "armobject,1": state.RobotArmObject = 1; return true; case "armobject,0": state.RobotArmObject = 0; return true; default: return false; } } /// /// 机械手前缀命令处理 /// /// /// private static bool IsPrefixCommand(string message) { return message.StartsWith("pickfinished") || message.StartsWith("putfinished"); } private Dt_RobotTask? GetTask(RobotCraneDevice robotCrane) { return _taskService.QueryRobotCraneTask(robotCrane.DeviceCode); } } public class RobotSocketState { public string IPAddress { get; set; } = string.Empty; /// /// 是否已订阅消息事件 /// public bool IsEventSubscribed { get; set; } /// /// 机械手运行模式 /// public int? RobotRunMode { get; set; } /// /// 机械手控制模式 /// public int? RobotControlMode { get; set; } /// /// 机械手抓取对象 /// public int? RobotArmObject { get; set; } /// /// 机械手设备信息 /// public RobotCraneDevice? RobotCrane { get; set; } /// /// 当前动作 /// public string? CurrentAction { get; set; } /// /// 当前状态 /// public string? OperStatus { get; set; } /// /// 取货完成位置 /// public int[]? LastPickPositions { get; set; } /// /// 放货完成位置 /// public int[]? LastPutPositions { get; set; } /// /// 抓取位置条码 /// public string[] CellBarcode { get; set; } /// /// 当前抓取任务 /// public Dt_RobotTask? CurrentTask { get; set; } } }