using CirculateTool.Attribute;
using WcsMain.ApiClient.AGV;
using WcsMain.ApiClient.Shuttle;
using WcsMain.Constant.Enum.General;
using WcsMain.Constant.Enum.Stacker;
using WcsMain.DataBase.Dao;
using WcsMain.DataBase.TableEntity;
using WcsMain.EquipOperation.StackerConvey;
namespace WcsMain.CirculationJob.Stacker;
///
/// 执行仓库任务
///
[Circulation]
public class ExecuteWmsTask(AppWmsTaskDao wmsTaskDao, StackerConveyOperation stackerConveyOperation, AGVWebApiAction agvAction, ShuttleWebApiAction containerAction, AppLiftInfoDao liftInfoDao)
{
///
/// 开始执行任务
///
///
[Circulation("执行任务", 1000)]
public bool ExecuteWmsTaskStarter()
{
/* 执行任务列表任务 */
List? wmsTasks = wmsTaskDao.Select(new AppWmsTask() { TaskStatus = (int)WmsTaskStatusEnum.create });
if (wmsTasks == default)
{
ConsoleLog.Error("【异常】解析Wms任务时拉取任务列表失败,与数据库连接中断");
Thread.Sleep(5000);
return true;
}
wmsTasks.ForEach(ExecuteTask);
/* 出库站台发送AGV接续任务 */
ExecuteAGVOutTask();
return true;
}
///
/// 执行对应的任务
///
///
private void ExecuteTask(AppWmsTask wmsTask)
{
switch (wmsTask.TaskType)
{
case (int)WmsTaskTypeEnum.agv: // AGV 点对点搬运
ExecuteAGVTask(wmsTask);
break;
case (int)WmsTaskTypeEnum.outTask:
ExecuteOutTask(wmsTask);
break;
case (int)WmsTaskTypeEnum.inTask:
ExecuteInTask(wmsTask);
break;
case (int)WmsTaskTypeEnum.moveTask:
ExecuteMoveTask(wmsTask);
break;
default:
break;
}
}
///
/// 执行 AGV 任务
///
///
private void ExecuteAGVTask(AppWmsTask wmsTask)
{
string errText = agvAction.Send_NO_VERIFY_BUCKET_MOVE(wmsTask);
if (!string.IsNullOrEmpty(errText))
{
ConsoleLog.Warning($"【警告】AGV点对点搬运请求AGV服务失败,任务号:{wmsTask.TaskId},异常信息:{errText}");
return;
}
ConsoleLog.Success($"AGV点对点搬运请求AGV服务成功,任务号:{wmsTask.TaskId}");
/* 更新任务状态为执行中 */
var updateResult = wmsTaskDao.Update(new() { TaskId = wmsTask.TaskId, TaskStatus = (int)WmsTaskStatusEnum.running, StartTime = DateTime.Now, ModifyTime = DateTime.Now });
ConsoleLog.Success($"更新任务状态结果:{(updateResult > 0 ? "成功" : "失败")},任务号:{wmsTask.TaskId}");
}
///
/// 执行入库任务 --- AGV搬运
///
///
private void ExecuteInTask(AppWmsTask wmsTask)
{
string? midPoint = wmsTask.MidPoint;
if (string.IsNullOrEmpty(wmsTask.Origin)) return;
if (string.IsNullOrEmpty(midPoint))
{
midPoint = GetEmptyInLift(wmsTask.Destination);
}
if (string.IsNullOrEmpty(midPoint)) return; // 没有可用的站台
/* 发送AGV 搬运任务 */
string errText = agvAction.Send_AGV_TASK(wmsTask.TaskId, wmsTask.Origin, midPoint, 1);
if (!string.IsNullOrEmpty(errText))
{
ConsoleLog.Warning($"【警告】入库请求AGV搬运失败,任务号:{wmsTask.TaskId},异常信息:{errText}");
return;
}
ConsoleLog.Success($"入库搬运请求AGV成功,任务号:{wmsTask.TaskId}");
/* 更新任务状态为前往中间点,更新中间点 */
var updateResult = wmsTaskDao.Update(new() { TaskId = wmsTask.TaskId, MidPoint = midPoint, TaskStatus = (int)WmsTaskStatusEnum.toMid, StartTime = DateTime.Now, ModifyTime = DateTime.Now });
ConsoleLog.Success($"更新任务状态结果:{(updateResult > 0 ? "成功" : "失败")},任务号:{wmsTask.TaskId}");
/* 四向车任务有接口返回给四向车 */
}
///
/// 执行出库任务
///
///
private void ExecuteOutTask(AppWmsTask wmsTask)
{
string? midPoint = wmsTask.MidPoint;
if(string.IsNullOrEmpty(midPoint))
{
midPoint = GetEmptyOutLift(wmsTask.Origin);
}
if (string.IsNullOrEmpty(midPoint)) return; // 没有可用站台
/* 发送四向车搬运任务 */
string? errText = containerAction.ExecuteOutTask(wmsTask.WcsId, wmsTask.Origin, midPoint, wmsTask.VehicleNo);
if (!string.IsNullOrEmpty(errText))
{
ConsoleLog.Warning($"【警告】出库请求四向车搬运失败,任务号:{wmsTask.TaskId},异常信息:{errText}");
return;
}
ConsoleLog.Success($"出库搬运请求四向车成功,任务号:{wmsTask.TaskId}/{wmsTask.WcsId}");
/* 更新任务状态为前往中间点,更新中间点 */
var updateResult = wmsTaskDao.Update(new() { TaskId = wmsTask.TaskId, MidPoint = midPoint, TaskStatus = (int)WmsTaskStatusEnum.toMid, StartTime = DateTime.Now, ModifyTime = DateTime.Now });
ConsoleLog.Success($"更新任务状态结果:{(updateResult > 0 ? "成功" : "失败")},任务号:{wmsTask.TaskId}");
/* AGV接续任务由定时器触发 */
}
///
/// 执行 四向车库移库任务
///
///
private void ExecuteMoveTask(AppWmsTask wmsTask)
{
string errText = containerAction.ExecuteMoveTask(wmsTask);
if (!string.IsNullOrEmpty(errText))
{
ConsoleLog.Warning($"四向车移库任务请求四向车服务失败,任务号:{wmsTask.TaskId}/{wmsTask.WcsId},异常信息:{errText}");
return;
}
ConsoleLog.Success($"四向车移库任务请求四向车服务成功,任务号:{wmsTask.TaskId}/{wmsTask.WcsId}");
/* 更新任务状态为执行中 */
var updateResult = wmsTaskDao.Update(new() { TaskId = wmsTask.TaskId, TaskStatus = (int)WmsTaskStatusEnum.running, StartTime = DateTime.Now, ModifyTime = DateTime.Now });
ConsoleLog.Success($"更新任务状态结果:{(updateResult > 0 ? "成功" : "失败")},任务号:{wmsTask.TaskId}");
}
///
/// 执行AGV出库任务
///
private void ExecuteAGVOutTask()
{
List? liftInfos = liftInfoDao.Query(new() { Status = (int)TrueFalseEnum.TRUE });
if (liftInfos == default || liftInfos.Count < 1) return;
foreach (var liftInfo in liftInfos)
{
(string errText, short model, short allowAction, short errCode, string code) = stackerConveyOperation.GetLiftInfo(liftInfo.LiftId ?? "");
if (!string.IsNullOrEmpty(errText))
{
//ConsoleLog.Warning($"【警告】提升机站台信息获取失败,异常信息:{errText}");
continue;
}
if (model != 2 || allowAction != (short)TrueFalseEnum.TRUE || errCode != 0) continue; // 不满足执行条件
/* 查找出库任务 */
List? tasks = wmsTaskDao.Select(new() { VehicleNo = code, TaskStatus = (int)WmsTaskStatusEnum.arriveMid })?.OrderByDescending(o => o.CreateTime).ToList();
if (tasks == null || tasks.Count == 0) continue;
var task = tasks.First();
if (string.IsNullOrEmpty(task.Destination)) continue;
/* 下发任务 */
string agvErrText = agvAction.Send_AGV_TASK(task.TaskId, GetAgvNo(task.MidPoint), task.Destination);
if (!string.IsNullOrEmpty(agvErrText))
{
ConsoleLog.Warning($"【警告】AGV出库任务请求AGV服务失败,任务号:{task.TaskId},异常信息:{agvErrText}");
return;
}
/* 更新任务状态为前往终点 */
var updateResult = wmsTaskDao.Update(new() { TaskId = task.TaskId, TaskStatus = (int)WmsTaskStatusEnum.toDestination, ModifyTime = DateTime.Now });
ConsoleLog.Success($"更新任务状态结果:{(updateResult > 0 ? "成功" : "失败")},任务号:{task.TaskId}");
}
}
///
/// 获取一个空闲的入库站台
///
///
///
private string? GetEmptyInLift(string? destination)
{
if (string.IsNullOrEmpty(destination)) return default;
List? liftInfos = liftInfoDao.Query(new() { Status = (int)TrueFalseEnum.TRUE });
if (liftInfos == default || liftInfos.Count < 1) return default;
foreach (var liftInfo in liftInfos)
{
(string errText, short model, short allowAction, short errCode, string code) = stackerConveyOperation.GetLiftInfo(liftInfo.LiftId ?? "");
if (!string.IsNullOrEmpty(errText))
{
//ConsoleLog.Warning($"【警告】提升机站台信息获取失败,异常信息:{errText}");
continue;
}
if (model != 1 || allowAction != (short)TrueFalseEnum.TRUE || errCode != 0) continue;
/* 检验任务是否是第一层,若是不是第一层不能分配第一层出入口 */
if (destination.EndsWith("1"))
{
if (liftInfo.LiftMode != 2) continue;
}
/* 获取这个站台的任务.没有占用任务即可重新使用 */
List? tasks = wmsTaskDao.Select(new() { MidPoint = liftInfo.Tag, TaskStatus = (int)WmsTaskStatusEnum.toMid });
if (tasks == default || tasks.Count > 0) continue;
string location = "";
if (!string.IsNullOrEmpty(liftInfo.Tag))
{
location = liftInfo.Tag.Split(',')[1];
}
return location;
}
return default;
}
///
/// 获取一个空闲的出库站台
///
///
///
private string? GetEmptyOutLift(string? origin)
{
if (string.IsNullOrEmpty(origin)) return default;
Dictionary liftTaskCount = [];
List? liftInfos = liftInfoDao.Query(new() { Status = (int)TrueFalseEnum.TRUE });
if (liftInfos == default || liftInfos.Count < 1) return default;
foreach (var liftInfo in liftInfos)
{
(string errText, short model, short allowAction, short errCode, string code) = stackerConveyOperation.GetLiftInfo(liftInfo.LiftId ?? "");
if (!string.IsNullOrEmpty(errText))
{
//ConsoleLog.Warning($"【警告】提升机站台信息获取失败,异常信息:{errText}");
continue;
}
if (model != 2 || allowAction != (short)TrueFalseEnum.FALSE || errCode != 0) continue;
/* 检验任务是否是第一层,若是不是第一层不能分配第一层出入口 */
if (!origin.EndsWith("1"))
{
if (liftInfo.LiftMode == 2) continue;
}
/* 获取这个站台的任务.并计数 */
List? tasks = wmsTaskDao.Select(new() { MidPoint = liftInfo.Tag, TaskStatus = (int)WmsTaskStatusEnum.toMid });
if (tasks == default) continue;
string location = "";
if(!string.IsNullOrEmpty(liftInfo.Tag))
{
location = liftInfo.Tag.Split(',')[0];
}
liftTaskCount.TryAdd(location, tasks.Count);
}
var sortLiftInfos = liftTaskCount.OrderBy(o => o.Value).ToDictionary();
if (sortLiftInfos.Count > 0) return sortLiftInfos.First().Key;
return default;
}
private string? GetAgvNo(string? lift)
{
List? liftInfos = liftInfoDao.Query(new() { Status = (int)TrueFalseEnum.TRUE });
if (liftInfos == default || liftInfos.Count < 1) return default;
AppLiftInfo? appLiftInfo = liftInfos.Find(f => f.Tag!.Contains(lift!));
if (appLiftInfo == null) return default;
return appLiftInfo.Tag?.Split(',')[1];
}
}