283 lines
12 KiB
C#
283 lines
12 KiB
C#
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;
|
||
|
||
/// <summary>
|
||
/// 执行仓库任务
|
||
/// </summary>
|
||
[Circulation]
|
||
public class ExecuteWmsTask(AppWmsTaskDao wmsTaskDao, StackerConveyOperation stackerConveyOperation, AGVWebApiAction agvAction, ShuttleWebApiAction containerAction, AppLiftInfoDao liftInfoDao)
|
||
{
|
||
/// <summary>
|
||
/// 开始执行任务
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[Circulation("执行任务", 1000)]
|
||
public bool ExecuteWmsTaskStarter()
|
||
{
|
||
/* 执行任务列表任务 */
|
||
List<AppWmsTask>? 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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行对应的任务
|
||
/// </summary>
|
||
/// <param name="wmsTask"></param>
|
||
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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行 AGV 任务
|
||
/// </summary>
|
||
/// <param name="wmsTask"></param>
|
||
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}");
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 执行入库任务 --- AGV搬运
|
||
/// </summary>
|
||
/// <param name="wmsTask"></param>
|
||
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}");
|
||
/* 四向车任务有接口返回给四向车 */
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行出库任务
|
||
/// </summary>
|
||
/// <param name="wmsTask"></param>
|
||
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接续任务由定时器触发 */
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 执行 四向车库移库任务
|
||
/// </summary>
|
||
/// <param name="wmsTask"></param>
|
||
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}");
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 执行AGV出库任务
|
||
/// </summary>
|
||
private void ExecuteAGVOutTask()
|
||
{
|
||
List<AppLiftInfo>? 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<AppWmsTask>? 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}");
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 获取一个空闲的入库站台
|
||
/// </summary>
|
||
/// <param name="destination"></param>
|
||
/// <returns></returns>
|
||
private string? GetEmptyInLift(string? destination)
|
||
{
|
||
if (string.IsNullOrEmpty(destination)) return default;
|
||
List<AppLiftInfo>? 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<AppWmsTask>? 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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取一个空闲的出库站台
|
||
/// </summary>
|
||
/// <param name="origin"></param>
|
||
/// <returns></returns>
|
||
private string? GetEmptyOutLift(string? origin)
|
||
{
|
||
if (string.IsNullOrEmpty(origin)) return default;
|
||
Dictionary<string, int> liftTaskCount = [];
|
||
List<AppLiftInfo>? 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<AppWmsTask>? 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<AppLiftInfo>? 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];
|
||
}
|
||
|
||
|
||
}
|