Product_Wms/WcsMain/CirculationJob/Stacker/ExecuteWmsTask.cs
2024-11-23 09:35:06 +08:00

288 lines
13 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Text.RegularExpressions;
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) || Regex.IsMatch(wmsTask.Origin, "^\\d+$")) 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 = [];
tasks.AddRange(wmsTaskDao.Select(new() { MidPoint = liftInfo.Tag!.Split(',')[0], TaskStatus = (int)WmsTaskStatusEnum.toMid }) ?? []);
tasks.AddRange(wmsTaskDao.Select(new() { MidPoint = liftInfo.Tag!.Split(',')[1], 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 = [];
tasks.AddRange(wmsTaskDao.Select(new() { MidPoint = liftInfo.Tag!.Split(',')[0], TaskStatus = (int)WmsTaskStatusEnum.toMid }) ?? []);
tasks.AddRange(wmsTaskDao.Select(new() { MidPoint = liftInfo.Tag!.Split(',')[1], 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];
}
}