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. 检查龙门吊状态(自动状态/工作状态)
/// 2. 处理取货/放货任务:
/// - 验证位置坐标格式
/// - 获取板材尺寸信息
/// - 校验工位和容器信息
/// - 计算并校验坐标范围
/// - 更新PLC控制参数
/// 3. 处理任务完成状态:
/// - 更新任务状态
/// - 通知MES系统
/// - 重置工位状态
/// 4. 错误处理:记录各种校验失败的异常情况
/// 依赖多个仓储和服务接口进行数据操作
///
[DisallowConcurrentExecution]
public class GantryJob : JobBase, IJob
{
private readonly ITaskRepository _taskRepository;
private readonly ITaskService _taskService;
private readonly IContainerItemRepository _containerItemRepository;
private readonly WebSocketServer _webSocketServer;
private readonly IOrderDetailsService _orderDetailsService;
private readonly IContainerRepository _containerRepository;
private readonly IOrderContainerRepository _orderContainerRepository;
public GantryJob(ITaskRepository taskRepository, ITaskService taskService, IContainerItemRepository containerItemRepository, WebSocketServer webSocketServer, IOrderDetailsService orderDetailsService, IContainerRepository containerRepository, IOrderContainerRepository orderContainerRepository)
{
_taskRepository = taskRepository;
_taskService = taskService;
_containerItemRepository = containerItemRepository;
_webSocketServer = webSocketServer;
_orderDetailsService = orderDetailsService;
_containerRepository = containerRepository;
_orderContainerRepository = orderContainerRepository;
}
public Task Execute(IJobExecutionContext context)
{
bool flag = context.JobDetail.JobDataMap.TryGetValue("JobParams", out object? value);
if (flag && 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)
{
Dt_Task? task = _taskService.QueryAGantryUnExecuteTask(otherDevice.DeviceCode);
if (task != null)
{
#region 取货位置判断
string[] takePositions = task.CurrentAddress.Split("*");
if (takePositions.Length != 5)
{
WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}", "取货位置错误");
if (task.ExceptionMessage?.Contains("取货位置错误") ?? true)
{
task.ExceptionMessage = "取货位置错误";
_taskRepository.UpdateData(task);
}
return Task.CompletedTask;
}
#endregion
#region 放货位置判断
string[] putPositions = task.NextAddress.Split("*");
if (putPositions.Length != 5)
{
WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}", "放货位置错误");
if (task.ExceptionMessage?.Contains("放货位置错误") ?? true)
{
task.ExceptionMessage = "放货位置错误";
_taskRepository.UpdateData(task);
}
return Task.CompletedTask;
}
#endregion
#region 板材尺寸获取
Dt_ContainerItem containerItem = _containerItemRepository.QueryFirst(x => x.ItemCode == task.PalletCode);
if (containerItem == null)
{
WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}", "板材尺寸获取错误");
if (task.ExceptionMessage?.Contains("板材尺寸获取错误") ?? true)
{
task.ExceptionMessage = "板材尺寸获取错误";
_taskRepository.UpdateData(task);
}
if (LightStatusStorage.LightStatusDic.ContainsKey(putPositions[0]))
{
LightStatusStorage.LightStatusDic[putPositions[0]] = LightStatusEnum.LightError;
}
return Task.CompletedTask;
}
#endregion
#region 放货工位判断
Dt_Container container = _containerRepository.QueryFirst(x => x.ContainerCode == putPositions[0]);
if (container == null)
{
WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}", $"放货工位【{takePositions[0]}】未找到");
if (task.ExceptionMessage?.Contains($"放货工位【{takePositions[0]}】未找到") ?? true)
{
task.ExceptionMessage = $"放货工位【{takePositions[0]}】未找到";
_taskRepository.UpdateData(task);
}
if (LightStatusStorage.LightStatusDic.ContainsKey(putPositions[0]))
{
LightStatusStorage.LightStatusDic[putPositions[0]] = LightStatusEnum.LightError;
}
return Task.CompletedTask;
}
#endregion
#region 工位订单信息判断
Dt_OrderContainer orderContainer = _orderContainerRepository.QueryFirst(x => x.ContainerCode == putPositions[0] && x.ContainerId == container.Id);
if (orderContainer == null && container.ContainerType != ContainerTypeEnum.ExceptionContainer.ObjToInt())
{
WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}", $"放货工位【{takePositions[0]}】未找到订单信息");
if (task.ExceptionMessage?.Contains($"放货工位【{takePositions[0]}】未找到订单信息") ?? true)
{
task.ExceptionMessage = $"放货工位【{takePositions[0]}】未找到订单信息";
_taskRepository.UpdateData(task);
}
if (LightStatusStorage.LightStatusDic.ContainsKey(putPositions[0]))
{
LightStatusStorage.LightStatusDic[putPositions[0]] = LightStatusEnum.LightError;
}
return Task.CompletedTask;
}
#endregion
#region 工位垫板读取数据判断
if (!LightStatusStorage.StationStautsDic.TryGetValue(putPositions[0], out bool stationStatus))
{
WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}", $"工位【{putPositions[0]}】有无垫板数据错误,{LightStatusStorage.StationStautsDic.Serialize()}");
if (task.ExceptionMessage?.Contains($"工位【{putPositions[0]}】有无垫板数据错误") ?? true)
{
task.ExceptionMessage = $"工位【{putPositions[0]}】有无垫板数据错误";
_taskRepository.UpdateData(task);
}
if (LightStatusStorage.LightStatusDic.ContainsKey(putPositions[0]))
{
LightStatusStorage.LightStatusDic[putPositions[0]] = LightStatusEnum.LightError;
}
return Task.CompletedTask;
}
#endregion
#region 工位垫板状态判断
if (!stationStatus)
{
WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}", $"工位【{putPositions[0]}】无垫板,{LightStatusStorage.StationStautsDic.Serialize()}");
if (task.ExceptionMessage?.Contains($"工位【{putPositions[0]}】无垫板") ?? true)
{
task.ExceptionMessage = $"工位【{putPositions[0]}】无垫板";
_taskRepository.UpdateData(task);
}
return Task.CompletedTask;
}
#endregion
#region 取货Z坐标判断
if (OPositions.HPositions[takePositions[0]].PositionZ == 0)
{
WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}", "读取取货Z坐标读取为0");
if (task.ExceptionMessage?.Contains($"读取取货Z坐标读取为0") ?? true)
{
task.ExceptionMessage = $"读取取货Z坐标读取为0";
_taskRepository.UpdateData(task);
}
if (LightStatusStorage.LightStatusDic.ContainsKey(putPositions[0]))
{
LightStatusStorage.LightStatusDic[putPositions[0]] = LightStatusEnum.LightError;
}
return Task.CompletedTask;
}
#endregion
#region 放货Z坐标判断
if (OPositions.HPositions[putPositions[0]].PositionZ == 0)
{
WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}", "读取放货Z坐标读取为0");
if (task.ExceptionMessage?.Contains($"读取放货Z坐标读取为0") ?? true)
{
task.ExceptionMessage = $"读取放货Z坐标读取为0";
_taskRepository.UpdateData(task);
}
if (LightStatusStorage.LightStatusDic.ContainsKey(putPositions[0]))
{
LightStatusStorage.LightStatusDic[putPositions[0]] = LightStatusEnum.LightError;
}
return Task.CompletedTask;
}
#endregion
#region 任务实体参数转换处理
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;
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;
int putPoR = 0;
#endregion
#region 坐标乘以1000处理,2#龙门架取反(乘以-1000)
int temp = 1000;
if (otherDevice.DeviceCode == "GT02")
{
temp = -1000;
}
#endregion
#region 坐标计算
if (Convert.ToInt32(takePositions[4]) == 1 || Convert.ToInt32(takePositions[4]) == 2)
{
takePoX = takePoX * temp + OPositions.HPositions[takePositions[0]].PositionX;
takePoY = takePoY * temp + OPositions.HPositions[takePositions[0]].PositionY;
putPoX = putPoX * temp + OPositions.HPositions[putPositions[0]].PositionX;
putPoY = putPoY * temp + 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坐标错误");
if (task.ExceptionMessage?.Contains($"R坐标错误") ?? true)
{
task.ExceptionMessage = $"R坐标错误";
_taskRepository.UpdateData(task);
}
if (LightStatusStorage.LightStatusDic.ContainsKey(putPositions[0]))
{
LightStatusStorage.LightStatusDic[putPositions[0]] = LightStatusEnum.LightError;
}
return Task.CompletedTask;
}
}
}
else
{
takePoX = takePoX * temp + OPositions.ZPositions[takePositions[0]].PositionX;
takePoY = takePoY * temp + OPositions.ZPositions[takePositions[0]].PositionY;
putPoX = putPoX * temp + OPositions.ZPositions[putPositions[0]].PositionX;
putPoY = putPoY * temp + OPositions.ZPositions[putPositions[0]].PositionY;
takePoR = OPositions.ZPositions[takePositions[0]].PositionR;
putPoR = OPositions.ZPositions[putPositions[0]].PositionR;
}
#endregion
#region Debug日志记录,记录取货和放货坐标信息
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}");
#endregion
#region 超过容器宽度处理
bool isMoreWidth = orderContainer == null ? false : orderContainer.MaxWidth > container.ContainerWidth;
if (isMoreWidth)
{
putPoX = putPoX - (orderContainer.MaxWidth - container.ContainerWidth) / 2 * temp;
}
#endregion
#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}", "设备协议参数错误,未找到最大最小坐标地址");
if (task.ExceptionMessage?.Contains($"设备协议参数错误,未找到最大最小坐标地址") ?? true)
{
task.ExceptionMessage = $"设备协议参数错误,未找到最大最小坐标地址";
_taskRepository.UpdateData(task);
}
if (LightStatusStorage.LightStatusDic.ContainsKey(putPositions[0]))
{
LightStatusStorage.LightStatusDic[putPositions[0]] = LightStatusEnum.LightError;
}
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];
if (takePoX < minX || takePoX > maxX)
{
WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}-坐标", $"X取货坐标超出范围,取货坐标:{takePoX},最大值:{maxX},最小值:{minX}");
if (task.ExceptionMessage?.Contains($"X取货坐标超出范围,取货坐标:{takePoX},最大值:{maxX},最小值:{minX}") ?? true)
{
task.ExceptionMessage = $"X取货坐标超出范围,取货坐标:{takePoX},最大值:{maxX},最小值:{minX}";
_taskRepository.UpdateData(task);
}
if (LightStatusStorage.LightStatusDic.ContainsKey(putPositions[0]))
{
LightStatusStorage.LightStatusDic[putPositions[0]] = LightStatusEnum.LightError;
}
return Task.CompletedTask;
}
if (putPoX < minX || putPoX > maxX)
{
WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}-坐标", $"X放货坐标超出范围,取货坐标:{putPoX},最大值:{maxX},最小值:{minX}");
if (task.ExceptionMessage?.Contains($"X放货坐标超出范围,取货坐标:{putPoX},最大值:{maxX},最小值:{minX}") ?? true)
{
task.ExceptionMessage = $"X放货坐标超出范围,取货坐标:{putPoX},最大值:{maxX},最小值:{minX}";
_taskRepository.UpdateData(task);
}
if (LightStatusStorage.LightStatusDic.ContainsKey(putPositions[0]))
{
LightStatusStorage.LightStatusDic[putPositions[0]] = LightStatusEnum.LightError;
}
return Task.CompletedTask;
}
if (takePoY < minY || takePoY > maxY)
{
WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}-坐标", $"Y取货坐标超出范围,取货坐标:{takePoY},最大值:{maxY},最小值:{minY}");
if (task.ExceptionMessage?.Contains($"Y取货坐标超出范围,取货坐标:{takePoY},最大值:{maxY},最小值:{minY}") ?? true)
{
task.ExceptionMessage = $"Y取货坐标超出范围,取货坐标:{takePoY},最大值:{maxY},最小值:{minY}";
_taskRepository.UpdateData(task);
}
if (LightStatusStorage.LightStatusDic.ContainsKey(putPositions[0]))
{
LightStatusStorage.LightStatusDic[putPositions[0]] = LightStatusEnum.LightError;
}
return Task.CompletedTask;
}
if (putPoY < minY || putPoY > maxY)
{
WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}-坐标", $"Y放货坐标超出范围,取货坐标:{putPoY},最大值:{maxY},最小值:{minY}");
if (task.ExceptionMessage?.Contains($"Y放货坐标超出范围,取货坐标:{putPoY},最大值:{maxY},最小值:{minY}") ?? true)
{
task.ExceptionMessage = $"Y放货坐标超出范围,取货坐标:{putPoY},最大值:{maxY},最小值:{minY}";
_taskRepository.UpdateData(task);
}
if (LightStatusStorage.LightStatusDic.ContainsKey(putPositions[0]))
{
LightStatusStorage.LightStatusDic[putPositions[0]] = LightStatusEnum.LightError;
}
return Task.CompletedTask;
}
if (takePoZ < minZ || takePoZ > maxZ)
{
WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}-坐标", $"Z取货坐标超出范围,取货坐标:{takePoZ},最大值:{maxZ},最小值:{minZ}");
if (task.ExceptionMessage?.Contains($"Z取货坐标超出范围,取货坐标:{takePoZ},最大值:{maxZ},最小值:{minZ}") ?? true)
{
task.ExceptionMessage = $"Z取货坐标超出范围,取货坐标:{takePoZ},最大值:{maxZ},最小值:{minZ}";
_taskRepository.UpdateData(task);
}
if (LightStatusStorage.LightStatusDic.ContainsKey(putPositions[0]))
{
LightStatusStorage.LightStatusDic[putPositions[0]] = LightStatusEnum.LightError;
}
return Task.CompletedTask;
}
if (putPoZ < minZ || putPoZ > maxZ)
{
WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}-坐标", $"Z放货坐标超出范围,取货坐标:{putPoZ},最大值:{maxZ},最小值:{minZ}");
if (task.ExceptionMessage?.Contains($"Z放货坐标超出范围,取货坐标:{putPoZ},最大值:{maxZ},最小值:{minZ}") ?? true)
{
task.ExceptionMessage = $"Z放货坐标超出范围,取货坐标:{putPoZ},最大值:{maxZ},最小值:{minZ}";
_taskRepository.UpdateData(task);
}
if (LightStatusStorage.LightStatusDic.ContainsKey(putPositions[0]))
{
LightStatusStorage.LightStatusDic[putPositions[0]] = LightStatusEnum.LightError;
}
return Task.CompletedTask;
}
if (takePoR < minR || takePoR > maxR)
{
WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}-坐标", $"R取货坐标超出范围,取货坐标:{takePoR},最大值:{maxR},最小值:{minR}");
if (task.ExceptionMessage?.Contains($"R取货坐标超出范围,取货坐标:{takePoR},最大值:{maxR},最小值:{minR}") ?? true)
{
task.ExceptionMessage = $"R取货坐标超出范围,取货坐标:{takePoR},最大值:{maxR},最小值:{minR}";
_taskRepository.UpdateData(task);
}
if (LightStatusStorage.LightStatusDic.ContainsKey(putPositions[0]))
{
LightStatusStorage.LightStatusDic[putPositions[0]] = LightStatusEnum.LightError;
}
return Task.CompletedTask;
}
if (putPoR < minR || putPoR > maxR)
{
WriteError($"{otherDevice.DeviceCode}-{otherDevice.DeviceName}-坐标", $"R放货坐标超出范围,取货坐标:{putPoR},最大值:{maxR},最小值:{minR}");
if (task.ExceptionMessage?.Contains($"R放货坐标超出范围,取货坐标:{putPoR},最大值:{maxR},最小值:{minR}") ?? true)
{
task.ExceptionMessage = $"R放货坐标超出范围,取货坐标:{putPoR},最大值:{maxR},最小值:{minR}";
_taskRepository.UpdateData(task);
}
if (LightStatusStorage.LightStatusDic.ContainsKey(putPositions[0]))
{
LightStatusStorage.LightStatusDic[putPositions[0]] = LightStatusEnum.LightError;
}
return Task.CompletedTask;
}
#endregion
#region 任务发送
otherDevice.SetValue(GantryDBName.TwoHand, true);
otherDevice.SetValue(GantryDBName.TaskNum, task.TaskNum);
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);
#endregion
#region 任务状态更新
task.TaskState = TaskStatusEnum.Gantry_Executing.ObjToInt();
_taskRepository.UpdateData(task);
#endregion
#region 三色灯状态更新
if (LightStatusStorage.LightStatusDic.TryGetValue(putPositions[0], out LightStatusEnum lightStatusDic))
{
if (lightStatusDic != LightStatusEnum.LightWorking)
{
LightStatusStorage.LightStatusDic[putPositions[0]] = LightStatusEnum.LightWorking;
}
}
#endregion
}
}
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);
Task.Run(() =>
{
_orderDetailsService.ToMes(task.PalletCode, 4);
});
string[] putPositions = task.NextAddress.Split("*");
if (putPositions.Length != 5)
{
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;
}
}
}