using CirculateTool; using WcsMain.Business.CommonAction; using WcsMain.Common; using WcsMain.DataBase.Dao; using WcsMain.DataBase.TableEntity; using WcsMain.Enum.Stacker; using WcsMain.Enum.TaskEnum; using WcsMain.EquipOperation.Entity.Stacker; using WcsMain.EquipOperation.Entity.StackerConvey; using WcsMain.EquipOperation.Stacker; using WcsMain.EquipOperation.StackerConvey; using WcsMain.ExtendMethod; namespace WcsMain.Business.CirculationTask.Stacker; /// /// 执行堆垛机任务类 /// [Circulation(tags: ["stacker"])] public class ExecuteWcsTask(StackerOperation stackerOperation, AppWcsTaskDao wcsTaskDao, WCSTaskExecuteEvent wcsTaskEvent, StackerConveyOperation stackerConveyOperation) { private readonly WCSTaskExecuteEvent _wcsTaskEvent = wcsTaskEvent; private readonly AppWcsTaskDao _wcsTaskDao = wcsTaskDao; private readonly StackerOperation _stackerOperation = stackerOperation; private readonly StackerConveyOperation _stackerConveyOperation = stackerConveyOperation; /// /// 执行堆垛机任务 /// /// [Circulation("执行堆垛机任务")] public bool ExecuteStackerTask() { foreach (var stacker in CommonData.AppStackers.Open()) { var stackerUseStatus = _stackerOperation.StackerCanUse(stacker.StackerId, out int _, out int _); if (stackerUseStatus == StackerUseStatusEnum.Free) { /* 空闲时正常执行任务 */ // 入库 if (!CommonData.AppConfig.ExcuteStackerInTaskWithScan.ToBool()) // 不是扫码入库 { bool exeInTask = ExecuteInTask(stacker.StackerId); if (exeInTask) continue; } // 出库 bool exeOutTask = ExecuteOutTask(stacker.StackerId); if (exeOutTask) continue; // 拣选 //bool exePickTask = ExecutePickTask(stacker.StackerId); //if (exePickTask) continue; // 移库 bool exeMoveTask = ExecuteMoveTask(stacker.StackerId); if (exeMoveTask) continue; } //if (stackerUseStatus == StackerUseStatusEnum.waitTask) //{ // /* 重复入库时执行任务 */ // bool exeDoubleInTask = ExecuteDoubleInTask(stacker.StackerId, plcId); // if (exeDoubleInTask) continue; //} } return true; } /// /// 执行堆垛机入库任务,若执行了任务则返回 true /// /// /// private bool ExecuteInTask(int? stackerId) { if (stackerId == default) return false; var wcsTasks = _wcsTaskDao.SelectInTaskWithStacker((int)stackerId!); // 此处方法内已经判断状态 if (wcsTasks == default) { ConsoleLog.Error($"【异常】{stackerId} 号输送机入库任务查询失败,与数据库连接异常"); Thread.Sleep(5000); return false; } if (wcsTasks.Count == 0) return false; var wcsTask = wcsTasks[0]; // 取第一条任务 /* 校验入库站台是否可以取货 */ (bool isSuccess, uint value) = _stackerConveyOperation.ReadSenserStatus(wcsTask.Origin); if (!isSuccess) return false; //站台不允许取货 if (value == 0) return false; //站台不允许取货 // TODO /* 检验并返回起点终点信息 */ var originLocationInfo = CommonData.AppLocations.DetailWithWcsLocation(wcsTask.Origin); var destinationLocationInfo = CommonData.AppLocations.DetailWithWcsLocation(wcsTask.Destination); if (destinationLocationInfo == default || originLocationInfo == default) // 起点终点错误,直接标记错误 { // 已经在接口内做了检查,按道理此处不会出错。直接返回异常,任务直接取消 ConsoleLog.Warning($"【警告】任务号:{wcsTask.TaskId},Plc任务号:{wcsTask.PlcId} 无法执行,起点或者终点存在异常"); _wcsTaskEvent.ErrTaskEvent(wcsTask, $"起点或者终点存在异常"); return false; } StackerConveyPlcTask conveyTask = new() { //StackerId = stackerId, StackerConveyId = wcsTask.Origin, PlcId = wcsTask.PlcId, TaskType = Convert.ToInt16(wcsTask.TaskType), GetStand = wcsTask.Origin == "111" ? (short)111 : (short)106, InTunnelId = 3, OutTunnelId = 3, SetStand = 0, GetQueue = 1, GetLine = 1, GetLayer = 1, GetDeep = 1, SetQueue = Convert.ToInt16(destinationLocationInfo.Queue), SetLine = Convert.ToInt16(destinationLocationInfo.Line), SetLayer = Convert.ToInt16(destinationLocationInfo.Layer), SetDeep = Convert.ToInt16(destinationLocationInfo.Depth), Size = Convert.ToInt16(wcsTask.VehicleSize), Weight = Convert.ToInt16(wcsTask.Weight), Code = wcsTask.PlcVehicleNo ?? 0, }; // 调用输送机操作类的方法,将任务写入输送机,获取写入任务的错误信息 var writeStackerTaskErrText = _stackerConveyOperation.WriteTask(conveyTask); if (string.IsNullOrEmpty(writeStackerTaskErrText)) { ConsoleLog.Success($"输送机:{stackerId} 写入入库任务成功,箱号:{wcsTask.VehicleNo},PlcId:{wcsTask.PlcId};{wcsTask.Origin} => {wcsTask.Destination}"); _wcsTaskEvent.StartTaskEvent(wcsTask); return true; } else { ConsoleLog.Warning($"【警告】输送机:{stackerId} 写入入库任务失败,箱号:{wcsTask.VehicleNo},PlcId:{wcsTask.PlcId};{wcsTask.Origin} => {wcsTask.Destination},异常信息:{writeStackerTaskErrText}"); _wcsTaskEvent.ErrTaskEvent(wcsTask, $"写入任务失败,异常信息:{writeStackerTaskErrText}"); } return false; } /// /// 执行堆垛机出库任务,若执行了任务则返回 true /// /// /// public bool ExecuteOutTask(int? stackerId) { if (stackerId == default) return false; var wcsTasks = _wcsTaskDao.SelectOutTaskWithStacker((int)stackerId!); if (wcsTasks == default) { ConsoleLog.Error($"【异常】{stackerId} 号堆垛机出库任务查询失败,与数据库连接异常"); Thread.Sleep(5000); return false; } if (wcsTasks.Count == 0) return false; var wcsTask = wcsTasks[0]; // 取第一条任务 /* 校验出库站台是否可以卸货 */ // TODO /* 检验并返回起点终点信息 */ var originLocationInfo = CommonData.AppLocations.DetailWithWcsLocation(wcsTask.Origin); var destinationLocationInfo = CommonData.AppLocations.DetailWithWcsLocation(wcsTask.Destination); if (destinationLocationInfo == default || originLocationInfo == default) // 起点终点错误,直接标记错误 { // 已经在接口内做了检查,按道理此处不会出错。直接返回异常,任务直接取消 ConsoleLog.Warning($"【警告】任务号:{wcsTask.TaskId},Plc任务号:{wcsTask.PlcId} 无法执行,起点或者终点存在异常"); _wcsTaskEvent.ErrTaskEvent(wcsTask, $"起点或者终点存在异常"); return false; } StackerPlcTask stackerTask = new() { StackerId = stackerId, PlcId = wcsTask.PlcId, TaskType = Convert.ToInt16(wcsTask.TaskType), GetStand = 0, InTunnelId = 3, OutTunnelId = 3, SetStand = Convert.ToInt16(wcsTask.Destination), GetQueue = Convert.ToInt16(originLocationInfo.Queue), GetLine = Convert.ToInt16(originLocationInfo.Line), GetLayer = Convert.ToInt16(originLocationInfo.Layer), GetDeep = Convert.ToInt16(originLocationInfo.Depth), SetQueue = 2, SetLine = 1, SetLayer = 1, SetDeep = 1, Size = Convert.ToInt16(wcsTask.VehicleSize), Weight = Convert.ToInt16(wcsTask.Weight), Code = wcsTask.PlcVehicleNo ?? 0, }; var writeStackerTaskErrText = _stackerOperation.WriteTask(stackerTask); if (string.IsNullOrEmpty(writeStackerTaskErrText)) { ConsoleLog.Success($"堆垛机:{stackerId} 写入出库任务成功,箱号:{wcsTask.VehicleNo},PlcId:{wcsTask.PlcId};{wcsTask.Origin} => {wcsTask.Destination}"); _wcsTaskEvent.StartTaskEvent(wcsTask); return true; } else { ConsoleLog.Warning($"【警告】堆垛机:{stackerId} 写入出库任务失败,箱号:{wcsTask.VehicleNo},PlcId:{wcsTask.PlcId};{wcsTask.Origin} => {wcsTask.Destination},异常信息:{writeStackerTaskErrText}"); _wcsTaskEvent.ErrTaskEvent(wcsTask, $"写入任务失败,异常信息:{writeStackerTaskErrText}"); } return false; } /// /// 执行堆垛机拣选任务,若执行了任务则返回 true /// /// /// public bool ExecutePickTask(int? stackerId) { if (stackerId == default) return false; var wcsTasks = _wcsTaskDao.SelectPickOutTaskWithStacker((int)stackerId!); if (wcsTasks == default) { ConsoleLog.Error($"【异常】{stackerId} 号堆垛机拣选任务查询失败,与数据库连接异常"); Thread.Sleep(5000); return false; } if (wcsTasks.Count == 0) return false; var wcsTask = wcsTasks[0]; // 取第一条任务 /* 校验出库站台是否可以卸货 */ // TODO /* 检验并返回起点终点信息 */ var originLocationInfo = CommonData.AppLocations.DetailWithWcsLocation(wcsTask.Origin); var destinationLocationInfo = CommonData.AppLocations.DetailWithWcsLocation(wcsTask.Destination); if (destinationLocationInfo == default || originLocationInfo == default) // 起点终点错误,直接标记错误 { // 已经在接口内做了检查,按道理此处不会出错。直接返回异常,任务直接取消 ConsoleLog.Warning($"【警告】任务号:{wcsTask.TaskId},Plc任务号:{wcsTask.PlcId} 无法执行,起点或者终点存在异常"); _wcsTaskEvent.ErrTaskEvent(wcsTask, $"起点或者终点存在异常"); return false; } StackerPlcTask stackerTask = new() { StackerId = stackerId, PlcId = wcsTask.PlcId, TaskType = Convert.ToInt16(wcsTask.TaskType), GetStand = 0, InTunnelId = 3, OutTunnelId = 3, SetStand = 0, GetQueue = Convert.ToInt16(originLocationInfo.Queue), GetLine = Convert.ToInt16(originLocationInfo.Line), GetLayer = Convert.ToInt16(originLocationInfo.Layer), GetDeep = Convert.ToInt16(originLocationInfo.Depth), SetQueue = Convert.ToInt16(destinationLocationInfo.Queue), SetLine = Convert.ToInt16(destinationLocationInfo.Line), SetLayer = Convert.ToInt16(destinationLocationInfo.Layer), SetDeep = Convert.ToInt16(destinationLocationInfo.Depth), Size = Convert.ToInt16(wcsTask.VehicleSize), Weight = Convert.ToInt16(wcsTask.Weight), Code = wcsTask.PlcVehicleNo ?? 0, }; var writeStackerTaskErrText = _stackerOperation.WriteTask(stackerTask); if (string.IsNullOrEmpty(writeStackerTaskErrText)) { ConsoleLog.Success($"堆垛机:{stackerId} 写入拣选任务成功,箱号:{wcsTask.VehicleNo},PlcId:{wcsTask.PlcId};{wcsTask.Origin} => {wcsTask.Destination}"); _wcsTaskEvent.StartTaskEvent(wcsTask); return true; } else { ConsoleLog.Warning($"【警告】堆垛机:{stackerId} 写入拣选任务失败,箱号:{wcsTask.VehicleNo},PlcId:{wcsTask.PlcId};{wcsTask.Origin} => {wcsTask.Destination},异常信息:{writeStackerTaskErrText}"); _wcsTaskEvent.ErrTaskEvent(wcsTask, $"写入任务失败,异常信息:{writeStackerTaskErrText}"); } return false; } /// /// 执行堆垛机移库任务,若执行了任务则返回 true /// /// /// public bool ExecuteMoveTask(int? stackerId) { if (stackerId == default) return false; var wcsTasks = _wcsTaskDao.SelectMoveTaskWithStacker((int)stackerId!); if (wcsTasks == default) { ConsoleLog.Error($"【异常】{stackerId} 号堆垛机移库任务查询失败,与数据库连接异常"); Thread.Sleep(5000); return false; } if (wcsTasks.Count == 0) return false; var wcsTask = wcsTasks[0]; // 取第一条任务 /* 检验并返回起点终点信息 */ var originLocationInfo = CommonData.AppLocations.DetailWithWcsLocation(wcsTask.Origin); var destinationLocationInfo = CommonData.AppLocations.DetailWithWcsLocation(wcsTask.Destination); if (destinationLocationInfo == default || originLocationInfo == default) // 起点终点错误,直接标记错误 { // 已经在接口内做了检查,按道理此处不会出错。直接返回异常,任务直接取消 ConsoleLog.Warning($"【警告】任务号:{wcsTask.TaskId},Plc任务号:{wcsTask.PlcId} 无法执行,起点或者终点存在异常"); _wcsTaskEvent.ErrTaskEvent(wcsTask, $"起点或者终点存在异常"); return false; } StackerPlcTask stackerTask = new() { StackerId = stackerId, PlcId = wcsTask.PlcId, TaskType = Convert.ToInt16(wcsTask.TaskType), GetStand = 0, InTunnelId = 3, OutTunnelId = 3, SetStand = 0, GetQueue = Convert.ToInt16(originLocationInfo.Queue), GetLine = Convert.ToInt16(originLocationInfo.Line), GetLayer = Convert.ToInt16(originLocationInfo.Layer), GetDeep = Convert.ToInt16(originLocationInfo.Depth), SetQueue = Convert.ToInt16(destinationLocationInfo.Queue), SetLine = Convert.ToInt16(destinationLocationInfo.Line), SetLayer = Convert.ToInt16(destinationLocationInfo.Layer), SetDeep = Convert.ToInt16(destinationLocationInfo.Depth), Size = Convert.ToInt16(wcsTask.VehicleSize), Weight = Convert.ToInt16(wcsTask.Weight), Code = wcsTask.PlcVehicleNo ?? 0, }; var writeStackerTaskErrText = _stackerOperation.WriteTask(stackerTask); if (string.IsNullOrEmpty(writeStackerTaskErrText)) { ConsoleLog.Success($"堆垛机:{stackerId} 写入移库任务成功,箱号:{wcsTask.VehicleNo},PlcId:{wcsTask.PlcId};{wcsTask.Origin} => {wcsTask.Destination}"); _wcsTaskEvent.StartTaskEvent(wcsTask); return true; } else { ConsoleLog.Warning($"【警告】堆垛机:{stackerId} 写入移库任务失败,箱号:{wcsTask.VehicleNo},PlcId:{wcsTask.PlcId};{wcsTask.Origin} => {wcsTask.Destination},异常信息:{writeStackerTaskErrText}"); _wcsTaskEvent.ErrTaskEvent(wcsTask, $"写入任务失败,异常信息:{writeStackerTaskErrText}"); } return false; } /// /// 执行重复入库新任务,若执行了返回true /// /// /// /// public bool ExecuteDoubleInTask(int? stackerId, int plcId) { if (stackerId == default || plcId == 0) return false; /* 查找这个PlcId对应的wms任务 */ List? doubleInTasks = _wcsTaskDao.Select(new AppWcsTask { PlcId = plcId }); if (doubleInTasks == default) { ConsoleLog.Error($"【异常】{stackerId} 号堆垛机重复入库任务检验失败,与数据库连接异常"); Thread.Sleep(5000); return false; } if (doubleInTasks.Count == 0) return false; // 找不到对应的PlcId的任务 var doubleTask = doubleInTasks[0]; /* 查找这个任务的新任务 */ List? newTasks = _wcsTaskDao.Select(new AppWcsTask { TaskId = doubleTask.TaskId, TaskType = (int)TaskTypeEnum.newTaskForDoubleIn, TaskStatus = (int)WmsTaskStatusEnum.create }); if (newTasks == default) { ConsoleLog.Error($"【异常】{stackerId} 号堆垛机重复入库任务新任务查询失败,与数据库连接异常"); Thread.Sleep(5000); return false; } if (newTasks.Count == 0) return false; var newTask = newTasks[0]; var destinationLocationInfo = CommonData.AppLocations.DetailWithWcsLocation(newTask.Destination); if (destinationLocationInfo == default) // 终点错误,直接标记错误 { // 已经在接口内做了检查,按道理此处不会出错。直接返回异常,任务直接取消 ConsoleLog.Warning($"【警告】任务号:{newTask.TaskId},Plc任务号:{newTask.PlcId} 无法执行,新终点存在异常"); _wcsTaskEvent.ErrTaskEvent(newTask, $"新终点存在异常"); return false; } StackerPlcTask stackerTask = new() { StackerId = stackerId, PlcId = newTask.PlcId, TaskType = Convert.ToInt16(TaskTypeEnum.inTask), GetStand = 0, InTunnelId = Convert.ToInt16(stackerId), OutTunnelId = Convert.ToInt16(stackerId), SetStand = 0, GetQueue = 0, GetLine = 0, GetLayer = 0, GetDeep = 0, SetQueue = Convert.ToInt16(destinationLocationInfo.Queue), SetLine = Convert.ToInt16(destinationLocationInfo.Line), SetLayer = Convert.ToInt16(destinationLocationInfo.Layer), SetDeep = Convert.ToInt16(destinationLocationInfo.Depth), Size = Convert.ToInt16(newTask.VehicleSize), Weight = Convert.ToInt16(newTask.Weight), Code = newTask.PlcVehicleNo ?? 0, }; var writeStackerTaskErrText = _stackerOperation.WriteTask(stackerTask); if (string.IsNullOrEmpty(writeStackerTaskErrText)) { ConsoleLog.Success($"堆垛机:{stackerId} 写入重复入库新任务成功,箱号:{newTask.VehicleNo},PlcId:{newTask.PlcId};新目的地:{newTask.Destination}"); _wcsTaskEvent.StartTaskEvent(newTask); return true; } else { ConsoleLog.Warning($"【警告】堆垛机:{stackerId} 写入重复入库新任务失败,箱号:{newTask.VehicleNo},PlcId:{newTask.PlcId};新目的地:{newTask.Destination},异常信息:{writeStackerTaskErrText}"); _wcsTaskEvent.ErrTaskEvent(newTask, $"写入任务失败,异常信息:{writeStackerTaskErrText}"); } return false; } }