using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using HslCommunication.WebSocket; using Quartz; using WIDESEAWCS_Common; using WIDESEAWCS_Core.Helper; using WIDESEAWCS_IBasicInfoRepository; using WIDESEAWCS_IBasicInfoService; using WIDESEAWCS_ITaskInfoRepository; using WIDESEAWCS_ITaskInfoService; using WIDESEAWCS_Model.Models; using WIDESEAWCS_QuartzJob; using WIDESEAWCS_QuartzJob.DTO; namespace WIDESEAWCS_Tasks { /// /// 龙门架作业任务,继承自JobBase并实现IJob接口。
/// 通过[DisallowConcurrentExecution]特性禁止并发执行。 ///
/// /// 主要功能:
/// 1. 根据设备状态(gantryStatus/gantryAutoStatus/gantryWorkStatus)触发任务执行逻辑
/// 2. 处理任务坐标计算与范围校验
/// 3. 更新设备PLC寄存器值和任务状态
/// 4. 完成任务后向MES系统上报数据
/// 依赖服务:
/// - ITaskRepository: 任务仓储服务
/// - ITaskService: 任务业务服务
/// - IContainerItemRepository: 容器物品仓储
/// - WebSocketServer: WebSocket服务
/// - IOrderDetailsService: 订单详情服务
///
[DisallowConcurrentExecution] public class GantryFJob : JobBase, IJob { private readonly ITaskRepository _taskRepository; private readonly ITaskService _taskService; private readonly IContainerItemRepository _containerItemRepository; private readonly WebSocketServer _webSocketServer; private readonly IOrderDetailsService _orderDetailsService; public GantryFJob(ITaskRepository taskRepository, ITaskService taskService, IContainerItemRepository containerItemRepository, WebSocketServer webSocketServer, IOrderDetailsService orderDetailsService) { _taskRepository = taskRepository; _taskService = taskService; _containerItemRepository = containerItemRepository; _webSocketServer = webSocketServer; _orderDetailsService = orderDetailsService; } public Task Execute(IJobExecutionContext context) { bool flag = context.JobDetail.JobDataMap.TryGetValue("JobParams", out object? value); if (flag && value != null && value is OtherDevice otherDevice) { try { byte gantryStatus = otherDevice.GetValue(GantryDBName.GantryStatus); byte gantryAutoStatus = otherDevice.GetValue(GantryDBName.GantryAutoStatus); byte gantryWorkStatus = otherDevice.GetValue(GantryDBName.GantryWorkStatus); if (gantryStatus == 1 && gantryAutoStatus == 3 && gantryWorkStatus == 0) { // 逻辑处理 // 1. 读取任务 // 2. 任务执行 // 3. 任务完成 Dt_Task? task = _taskService.QueryAGantryUnExecuteTask(otherDevice.DeviceCode); if (task != null) { string[] takePositions = task.CurrentAddress.Split("*"); if (takePositions.Length != 5) { //WriteError return Task.CompletedTask; } string[] putPositions = task.NextAddress.Split("*"); if (putPositions.Length != 5) { //WriteError return Task.CompletedTask; } Dt_ContainerItem containerItem = _containerItemRepository.QueryFirst(x => x.ItemCode == task.PalletCode); if (containerItem == null) { //WriteError return Task.CompletedTask; } if (LightStatusStorage.LightStatusDic.TryGetValue(putPositions[0], out LightStatusEnum lightStatusDic)) { if (lightStatusDic != LightStatusEnum.LightWorking) { LightStatusStorage.LightStatusDic[putPositions[0]] = LightStatusEnum.LightWorking; } } otherDevice.SetValue(GantryDBName.TwoHand, true); otherDevice.SetValue(GantryDBName.TaskNum, task.TaskNum); int takePoX = Convert.ToInt32(takePositions[1]); int takePoY = Convert.ToInt32(takePositions[2]); int takePoZ = OPositions.HPositions[takePositions[0]].PositionZ + 30 * 1000 - Convert.ToInt32(takePositions[3]) * 1000; if (OPositions.HPositions[takePositions[0]].PositionZ == 0) { WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}", "取货Z坐标读取为0"); return Task.CompletedTask; } int takePoR = 0; int putPoX = Convert.ToInt32(putPositions[1]); int putPoY = Convert.ToInt32(putPositions[2]); int putPoZ = OPositions.HPositions[putPositions[0]].PositionZ - Convert.ToInt32(putPositions[3]) * 1000; if (OPositions.HPositions[takePositions[0]].PositionZ == 0) { WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}", "放货Z坐标读取为0"); return Task.CompletedTask; } int putPoR = 0; if (Convert.ToInt32(takePositions[4]) == 1 || Convert.ToInt32(takePositions[4]) == 2) { takePoX = takePoX * 1000 + OPositions.HPositions[takePositions[0]].PositionX; takePoY = takePoY * 1000 + OPositions.HPositions[takePositions[0]].PositionY; putPoX = putPoX * 1000 + OPositions.HPositions[putPositions[0]].PositionX; putPoY = putPoY * 1000 + OPositions.HPositions[putPositions[0]].PositionY; takePoR = OPositions.HPositions[takePositions[0]].PositionR; if (Convert.ToInt32(takePositions[4]) == 1) putPoR = OPositions.HPositions[putPositions[0]].PositionR; else { if (otherDevice.DeviceCode == "GT03") putPoR = otherDevice.Communicator.Read("DB10.840"); else if (otherDevice.DeviceCode == "GT02") putPoR = otherDevice.Communicator.Read("DB10.836"); else if (otherDevice.DeviceCode == "GT01") putPoR = otherDevice.Communicator.Read("DB10.832"); else { WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}", "R坐标错误"); return Task.CompletedTask; } } WriteDebug($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}-坐标", $"取货位:{takePositions[0]},放货位:{putPositions[0]}{Environment.NewLine}取货坐标:X:{takePoX} Y:{takePoY} Z:{takePoZ} R:{takePoR}{Environment.NewLine}放货坐标:X:{putPoX} Y:{putPoY} Z:{putPoZ} R:{putPoR}{Environment.NewLine}读取PLC取货坐标:X:{OPositions.HPositions[takePositions[0]].PositionX} Y:{OPositions.HPositions[takePositions[0]].PositionY} Z:{OPositions.HPositions[takePositions[0]].PositionZ} R:{OPositions.HPositions[takePositions[0]].PositionR}{Environment.NewLine}读取PLC放货坐标:X:{OPositions.HPositions[putPositions[0]].PositionX} Y:{OPositions.HPositions[putPositions[0]].PositionY} Z:{OPositions.HPositions[putPositions[0]].PositionZ} R:{OPositions.HPositions[putPositions[0]].PositionR}"); } else { takePoX = takePoX * 1000 + OPositions.ZPositions[takePositions[0]].PositionX; takePoY = takePoY * 1000 + OPositions.ZPositions[takePositions[0]].PositionY; putPoX = putPoX * 1000 + OPositions.ZPositions[putPositions[0]].PositionX; putPoY = putPoY * 1000 + OPositions.ZPositions[putPositions[0]].PositionY; takePoR = OPositions.ZPositions[takePositions[0]].PositionR; putPoR = OPositions.ZPositions[putPositions[0]].PositionR; WriteDebug($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}-坐标", $"取货位:{takePositions[0]},放货位:{putPositions[0]}{Environment.NewLine}取货坐标:X:{takePoX} Y:{takePoY} Z:{takePoZ} R:{takePoR}{Environment.NewLine}放货坐标:X:{putPoX} Y:{putPoY} Z:{putPoZ} R:{putPoR}{Environment.NewLine}读取PLC取货坐标:X:{OPositions.ZPositions[takePositions[0]].PositionX} Y:{OPositions.ZPositions[takePositions[0]].PositionY} Z:{OPositions.ZPositions[takePositions[0]].PositionZ} R:{OPositions.ZPositions[takePositions[0]].PositionR}{Environment.NewLine}读取PLC放货坐标:X:{OPositions.ZPositions[putPositions[0]].PositionX} Y:{OPositions.ZPositions[putPositions[0]].PositionY} Z:{OPositions.ZPositions[putPositions[0]].PositionZ} R:{OPositions.ZPositions[putPositions[0]].PositionR}"); } #region List devicePros = otherDevice.DeviceProDTOs.Where(x => x.DeviceProParamType == "MaxPosition").ToList(); DeviceProDTO? devicePro = devicePros.OrderBy(x => x.DeviceProOffset).FirstOrDefault(); if(devicePro == null) { WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}", "设备协议参数错误,未找到最大最小坐标地址"); return Task.CompletedTask; } int[] data = otherDevice.Communicator.Read(devicePro.DeviceProAddress, (ushort)(devicePros.Count)); int maxX = data[0]; int minX = data[1]; int maxY = data[2]; int minY = data[3]; int maxZ = data[4]; int minZ = data[5]; int maxR = data[6]; int minR = data[7]; //int maxX = otherDevice.GetValue(GantryDBName.MaxX); //int minX = otherDevice.GetValue(GantryDBName.MinX); //int maxY = otherDevice.GetValue(GantryDBName.MaxY); //int minY = otherDevice.GetValue(GantryDBName.MinY); //int maxZ = otherDevice.GetValue(GantryDBName.MaxZ); //int minZ = otherDevice.GetValue(GantryDBName.MinZ); //int maxR = otherDevice.GetValue(GantryDBName.MaxR); //int minR = otherDevice.GetValue(GantryDBName.MinR); if (takePoX < minX || takePoX > maxX) { WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}-坐标", $"X取货坐标超出范围,取货坐标:{takePoX},最大值:{maxX},最小值:{minX}"); return Task.CompletedTask; } if (putPoX < minX || putPoX > maxX) { WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}-坐标", $"X放货坐标超出范围,取货坐标:{putPoX},最大值:{maxX},最小值:{minX}"); return Task.CompletedTask; } if (takePoY < minY || takePoY > maxY) { WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}-坐标", $"Y取货坐标超出范围,取货坐标:{takePoY},最大值:{maxY},最小值:{minY}"); return Task.CompletedTask; } if (putPoY < minY || putPoY > maxY) { WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}-坐标", $"Y放货坐标超出范围,取货坐标:{putPoY},最大值:{maxY},最小值:{minY}"); return Task.CompletedTask; } if (takePoZ < minZ || takePoZ > maxZ) { WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}-坐标", $"Z取货坐标超出范围,取货坐标:{takePoZ},最大值:{maxZ},最小值:{minZ}"); return Task.CompletedTask; } if (putPoZ < minZ || putPoZ > maxZ) { WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}-坐标", $"Z放货坐标超出范围,取货坐标:{putPoZ},最大值:{maxZ},最小值:{minZ}"); return Task.CompletedTask; } if (takePoR < minR || takePoR > maxR) { WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}-坐标", $"R取货坐标超出范围,取货坐标:{takePoR},最大值:{maxR},最小值:{minR}"); return Task.CompletedTask; } if (putPoR < minR || putPoR > maxR) { WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}-坐标", $"R放货坐标超出范围,取货坐标:{putPoR},最大值:{maxR},最小值:{minR}"); return Task.CompletedTask; } #endregion otherDevice.SetValue(GantryDBName.TakePositionX, takePoX); otherDevice.SetValue(GantryDBName.TakePositionY, takePoY); otherDevice.SetValue(GantryDBName.TakePositionZ, takePoZ); otherDevice.SetValue(GantryDBName.TakePositionR, takePoR); otherDevice.SetValue(GantryDBName.PutPositionX, putPoX); otherDevice.SetValue(GantryDBName.PutPositionY, putPoY); otherDevice.SetValue(GantryDBName.PutPositionZ, putPoZ); otherDevice.SetValue(GantryDBName.PutPositionR, putPoR); otherDevice.SetValue(GantryDBName.Length, containerItem.ItemLength); otherDevice.SetValue(GantryDBName.Width, containerItem.ItemWidth); otherDevice.SetValue(GantryDBName.Height, containerItem.ItemHeight); otherDevice.SetValue(GantryDBName.WorkType, 1); otherDevice.SetValue(GantryDBName.StartCommand, 1); task.TaskState = TaskStatusEnum.Gantry_Executing.ObjToInt(); _taskRepository.UpdateData(task); } } else if (gantryWorkStatus == 5) { int currentTaskNum = otherDevice.GetValue(GantryDBName.TaskNum); if (currentTaskNum > 0) { Dt_Task task = _taskRepository.QueryFirst(x => x.TaskNum == currentTaskNum); if (task != null) { _taskService.TaskComplete(task); _orderDetailsService.ToMes(task.PalletCode, 4); string[] putPositions = task.NextAddress.Split("*"); if (putPositions.Length != 5) { //WriteError return Task.CompletedTask; } if (LightStatusStorage.LightStatusDic.TryGetValue(putPositions[0], out LightStatusEnum lightStatusDic)) { if (lightStatusDic != LightStatusEnum.Ready) { LightStatusStorage.LightStatusDic[putPositions[0]] = LightStatusEnum.Ready; } } } } otherDevice.SetValue(GantryDBName.WorkType, 5); } } catch (Exception ex) { WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}", ex.Message, ex); } } else { WriteError(nameof(GantryJob), "参数错误,未传递设备参数或设备类型错误"); } return Task.CompletedTask; } public Dt_Task GetTask() { return new Dt_Task(); } } }