using Quartz;
|
using System.Diagnostics.CodeAnalysis;
|
using WIDESEAWCS_Common.TaskEnum;
|
using WIDESEAWCS_ITaskInfoRepository;
|
using WIDESEAWCS_ITaskInfoService;
|
using WIDESEAWCS_Model.Models;
|
using WIDESEAWCS_QuartzJob;
|
using WIDESEAWCS_QuartzJob.Models;
|
using WIDESEAWCS_QuartzJob.Service;
|
using WIDESEAWCS_QuartzJob.StackerCrane.Enum;
|
using WIDESEAWCS_Tasks.StackerCraneJob;
|
|
namespace WIDESEAWCS_Tasks
|
{
|
[DisallowConcurrentExecution]
|
public class FormationCommonStackerCraneJob : IJob
|
{
|
private readonly ITaskService _taskService;
|
private readonly ITaskExecuteDetailService _taskExecuteDetailService;
|
private readonly ITaskRepository _taskRepository;
|
private readonly IRouterService _routerService;
|
|
public FormationCommonStackerCraneJob(ITaskService taskService, ITaskExecuteDetailService taskExecuteDetailService, ITaskRepository taskRepository, IRouterService routerService)
|
{
|
_taskService = taskService;
|
_taskExecuteDetailService = taskExecuteDetailService;
|
_taskRepository = taskRepository;
|
_routerService = routerService;
|
}
|
|
public Task Execute(IJobExecutionContext context)
|
{
|
try
|
{
|
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " FormationCommonStackerCraneJob Start");
|
|
bool flag = context.JobDetail.JobDataMap.TryGetValue("JobParams", out object? value);
|
if (!flag || value is not SpeFormationStackerCrane commonStackerCrane)
|
{
|
return Task.CompletedTask;
|
}
|
|
if (!commonStackerCrane.IsEventSubscribed)
|
{
|
commonStackerCrane.StackerCraneTaskCompletedEventHandler += CommonStackerCrane_StackerCraneTaskCompletedEventHandler;
|
}
|
|
if (commonStackerCrane.StackerCraneStatusValue != FormationStackerCraneRunStatus.Standby)
|
{
|
return Task.CompletedTask;
|
}
|
|
commonStackerCrane.CheckStackerCraneTaskCompleted();
|
|
if (commonStackerCrane.StackerCraneWorkStatusValue == FormationStackerCraneOperationStatus.Idle)
|
{
|
Dt_Task? task = GetTask(commonStackerCrane);
|
if (task != null)
|
{
|
FormationStackerCraneTaskCommand? stackerCraneTaskCommand = ConvertToStackerCraneTaskCommand(task);
|
if (stackerCraneTaskCommand != null)
|
{
|
bool sendFlag = commonStackerCrane.SendCommand(stackerCraneTaskCommand);
|
if (sendFlag)
|
{
|
commonStackerCrane.LastTaskType = task.TaskType;
|
_taskService.UpdateTaskStatusToNext(task.TaskNum);
|
}
|
}
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
Console.WriteLine($"FormationCommonStackerCraneJob Error: {ex.Message}");
|
}
|
return Task.CompletedTask;
|
}
|
|
/// <summary>
|
/// 任务完成事件订阅的方法
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void CommonStackerCrane_StackerCraneTaskCompletedEventHandler(object? sender, WIDESEAWCS_QuartzJob.StackerCrane.StackerCraneTaskCompletedEventArgs e)
|
{
|
SpeFormationStackerCrane? commonStackerCrane = sender as SpeFormationStackerCrane;
|
if (commonStackerCrane != null)
|
{
|
if (commonStackerCrane.GetValue<FormationStackerCraneDBName, short>(FormationStackerCraneDBName.WorkType) != 7)
|
{
|
Console.Out.WriteLine("TaskCompleted" + e.TaskNum);
|
_taskService.StackCraneTaskCompleted(e.TaskNum);
|
commonStackerCrane.SetValue(FormationStackerCraneDBName.WorkType, 4);
|
}
|
}
|
}
|
|
/// <summary>
|
/// 获取任务
|
/// </summary>
|
/// <param name="commonStackerCrane">堆垛机对象</param>
|
/// <returns></returns>
|
private Dt_Task? GetTask(SpeFormationStackerCrane commonStackerCrane)
|
{
|
Dt_Task? task = null;
|
|
if (commonStackerCrane.LastTaskType == null)
|
{
|
task = _taskService.QueryStackerCraneTask(commonStackerCrane.DeviceCode);
|
}
|
else
|
{
|
if (commonStackerCrane.LastTaskType.GetValueOrDefault().GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup)
|
{
|
task = _taskService.QueryStackerCraneInTask(commonStackerCrane.DeviceCode);
|
task ??= _taskService.QueryStackerCraneOutTask(commonStackerCrane.DeviceCode);
|
}
|
else
|
{
|
task = _taskService.QueryStackerCraneOutTask(commonStackerCrane.DeviceCode);
|
}
|
}
|
|
if (task != null && task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup)
|
{
|
if (IsOutTaskStationAvailable(task))
|
{
|
return task;
|
}
|
|
List<string> otherOutStationCodes = _routerService.QueryNextRoutes(commonStackerCrane.DeviceCode, task.NextAddress, task.TaskType)
|
.Select(x => x.ChildPosi).ToList();
|
|
List<Dt_Task> tasks = _taskService.QueryStackerCraneOutTasks(commonStackerCrane.DeviceCode, otherOutStationCodes);
|
|
foreach (var alternativeTask in tasks)
|
{
|
if (IsOutTaskStationAvailable(alternativeTask))
|
{
|
return alternativeTask;
|
}
|
}
|
|
task = _taskService.QueryStackerCraneInTask(commonStackerCrane.DeviceCode);
|
}
|
|
return task;
|
}
|
|
/// <summary>
|
/// 检查出库任务的出库站台是否可用
|
/// </summary>
|
/// <param name="task">任务实体</param>
|
/// <returns>如果站台可用返回true,否则返回false</returns>
|
private bool IsOutTaskStationAvailable([NotNull] Dt_Task task)
|
{
|
Dt_Router? router = _routerService.QueryNextRoute(task.Roadway, task.NextAddress, task.TaskType);
|
if (router == null)
|
{
|
_taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到站台【{task.NextAddress}】信息,无法校验站台");
|
return false;
|
}
|
|
IDevice? device = Storage.Devices.FirstOrDefault(x => x.DeviceCode == router.ChildPosiDeviceCode);
|
if (device == null)
|
{
|
_taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到出库站台【{router.ChildPosiDeviceCode}】对应的通讯对象,无法判断出库站台是否被占用");
|
return false;
|
}
|
|
CommonConveyorLine conveyorLine = (CommonConveyorLine)device;
|
return conveyorLine.IsOccupied(router.ChildPosi);
|
}
|
|
/// <summary>
|
/// 任务实体转换成命令Model
|
/// </summary>
|
/// <param name="task">任务实体</param>
|
/// <returns></returns>
|
public FormationStackerCraneTaskCommand? ConvertToStackerCraneTaskCommand([NotNull] Dt_Task task)
|
{
|
FormationStackerCraneTaskCommand stackerCraneTaskCommand = new FormationStackerCraneTaskCommand
|
{
|
Barcode = task.PalletCode,
|
TaskNum = task.TaskNum,
|
WorkType = 4,
|
WorkAction = 1,
|
FireAlarm = 0,
|
FieldName = ""
|
};
|
|
TaskTypeGroup taskTypeGroup = task.TaskType.GetTaskTypeGroup();
|
|
return taskTypeGroup switch
|
{
|
TaskTypeGroup.InboundGroup => BuildInboundCommand(task, stackerCraneTaskCommand),
|
TaskTypeGroup.OutbondGroup => BuildOutboundCommand(task, stackerCraneTaskCommand),
|
TaskTypeGroup.RelocationGroup => BuildRelocationCommand(task, stackerCraneTaskCommand),
|
_ => stackerCraneTaskCommand
|
};
|
}
|
|
/// <summary>
|
/// 构建入库命令
|
/// </summary>
|
private FormationStackerCraneTaskCommand? BuildInboundCommand(Dt_Task task, FormationStackerCraneTaskCommand command)
|
{
|
Dt_Router? router = _routerService.QueryNextRoute(task.CurrentAddress, task.Roadway, task.TaskType);
|
if (router == null)
|
{
|
_taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到站台【{task.CurrentAddress}】信息,无法获取对应的堆垛机取货站台信息");
|
return null;
|
}
|
|
command.StartRow = Convert.ToInt16(router.SrmRow);
|
command.StartColumn = Convert.ToInt16(router.SrmColumn);
|
command.StartLayer = Convert.ToInt16(router.SrmLayer);
|
|
if (!TryParseAddress(task.NextAddress, out short endRow, out short endColumn, out short endLayer))
|
{
|
_taskService.UpdateTaskExceptionMessage(task.TaskNum, $"入库任务终点错误,终点:【{task.NextAddress}】");
|
return null;
|
}
|
|
command.EndRow = endRow;
|
command.EndColumn = endColumn;
|
command.EndLayer = endLayer;
|
|
return command;
|
}
|
|
/// <summary>
|
/// 构建出库命令
|
/// </summary>
|
private FormationStackerCraneTaskCommand? BuildOutboundCommand(Dt_Task task, FormationStackerCraneTaskCommand command)
|
{
|
Dt_Router? router = _routerService.QueryNextRoute(task.Roadway, task.TargetAddress, task.TaskType);
|
if (router == null)
|
{
|
_taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到站台【{task.TargetAddress}】信息,无法获取对应的堆垛机放货站台信息");
|
return null;
|
}
|
|
command.EndRow = Convert.ToInt16(router.SrmRow);
|
command.EndColumn = Convert.ToInt16(router.SrmColumn);
|
command.EndLayer = Convert.ToInt16(router.SrmLayer);
|
|
if (!TryParseAddress(task.CurrentAddress, out short startRow, out short startColumn, out short startLayer))
|
{
|
_taskService.UpdateTaskExceptionMessage(task.TaskNum, $"出库任务起点错误,起点:【{task.CurrentAddress}】");
|
return null;
|
}
|
|
command.StartRow = startRow;
|
command.StartColumn = startColumn;
|
command.StartLayer = startLayer;
|
|
return command;
|
}
|
|
/// <summary>
|
/// 构建移库命令
|
/// </summary>
|
private FormationStackerCraneTaskCommand? BuildRelocationCommand(Dt_Task task, FormationStackerCraneTaskCommand command)
|
{
|
if (!TryParseAddress(task.NextAddress, out short endRow, out short endColumn, out short endLayer))
|
{
|
_taskService.UpdateTaskExceptionMessage(task.TaskNum, $"移库任务终点错误,终点:【{task.NextAddress}】");
|
return null;
|
}
|
|
command.EndRow = endRow;
|
command.EndColumn = endColumn;
|
command.EndLayer = endLayer;
|
|
if (!TryParseAddress(task.CurrentAddress, out short startRow, out short startColumn, out short startLayer))
|
{
|
_taskService.UpdateTaskExceptionMessage(task.TaskNum, $"移库任务起点错误,起点:【{task.CurrentAddress}】");
|
return null;
|
}
|
|
command.StartRow = startRow;
|
command.StartColumn = startColumn;
|
command.StartLayer = startLayer;
|
|
return command;
|
}
|
|
/// <summary>
|
/// 解析地址字符串(格式:行-列-层)
|
/// </summary>
|
private bool TryParseAddress(string address, out short row, out short column, out short layer)
|
{
|
row = column = layer = 0;
|
|
string[] parts = address.Split("-");
|
if (parts.Length != 3)
|
{
|
return false;
|
}
|
|
return short.TryParse(parts[0], out row)
|
&& short.TryParse(parts[1], out column)
|
&& short.TryParse(parts[2], out layer);
|
}
|
}
|
}
|