using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Routing;
using Quartz;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Communicator;
using WIDESEAWCS_Core.Enums;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_ITaskInfoRepository;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
using WIDESEAWCS_QuartzJob.DeviceBase;
using WIDESEAWCS_QuartzJob.Models;
using WIDESEAWCS_QuartzJob.Service;
using WIDESEAWCS_QuartzJob.StackerCrane.Enum;
using WIDESEAWCS_TaskInfoService;
using WIDESEAWCS_Tasks.StackerCraneJob;
namespace WIDESEAWCS_Tasks
{
[DisallowConcurrentExecution]
public class CommonStackerCraneJob : IJob
{
private readonly ITaskService _taskService;
private readonly ITaskExecuteDetailService _taskExecuteDetailService;
private readonly ITaskRepository _taskRepository;
private readonly IRouterService _routerService;
public CommonStackerCraneJob(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") + " CommonStackerCraneJob Start");
bool flag = context.JobDetail.JobDataMap.TryGetValue("JobParams", out object? value);
if (!flag || value is not IStackerCrane commonStackerCrane)
{
return Task.CompletedTask;
}
if (!commonStackerCrane.IsEventSubscribed)
{
commonStackerCrane.StackerCraneTaskCompletedEventHandler += CommonStackerCrane_StackerCraneTaskCompletedEventHandler;
}
if (commonStackerCrane.IsCanSendTask(commonStackerCrane.Communicator, commonStackerCrane.DeviceProDTOs, commonStackerCrane.DeviceProtocolDetailDTOs))
{
commonStackerCrane.CheckStackerCraneTaskCompleted();
Dt_Task? task = GetTask(commonStackerCrane);
if (task != null)
{
StackerCraneTaskCommand? 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($"CommonStackerCraneJob Error: {ex.Message}");
}
return Task.CompletedTask;
}
///
/// 任务完成事件订阅的方法
///
///
///
private void CommonStackerCrane_StackerCraneTaskCompletedEventHandler(object? sender, WIDESEAWCS_QuartzJob.StackerCrane.StackerCraneTaskCompletedEventArgs e)
{
CommonStackerCrane? commonStackerCrane = sender as CommonStackerCrane;
if (commonStackerCrane != null)
{
if (commonStackerCrane.GetValue(StackerCraneDBName.WorkType) != 5)
{
Console.Out.WriteLine("TaskCompleted" + e.TaskNum);
_taskService.StackCraneTaskCompleted(e.TaskNum);
commonStackerCrane.SetValue(StackerCraneDBName.WorkType, 5);
}
}
}
///
/// 获取任务
///
/// 堆垛机对象
///
private Dt_Task? GetTask(IStackerCrane 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 otherOutStationCodes = _routerService.QueryNextRoutes(commonStackerCrane.DeviceCode, task.NextAddress, task.TaskType)
.Select(x => x.ChildPosi).ToList();
List tasks = _taskService.QueryStackerCraneOutTasks(commonStackerCrane.DeviceCode, otherOutStationCodes);
foreach (var alternativeTask in tasks)
{
if (IsOutTaskStationAvailable(alternativeTask))
{
return alternativeTask;
}
}
task = _taskService.QueryStackerCraneInTask(commonStackerCrane.DeviceCode);
}
return task;
}
///
/// 出库任务判断出库站台是否可用
///
/// 任务实体
/// 如果站台可用返回true,否则返回false
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);
}
///
/// 任务实体转换成命令Model
///
/// 任务实体
///
public StackerCraneTaskCommand? ConvertToStackerCraneTaskCommand([NotNull] Dt_Task task)
{
StackerCraneTaskCommand stackerCraneTaskCommand = new StackerCraneTaskCommand
{
Barcode = task.PalletCode,
TaskNum = task.TaskNum,
WorkType = 1,
TrayType = 0
};
TaskTypeGroup taskTypeGroup = task.TaskType.GetTaskTypeGroup();
return taskTypeGroup switch
{
TaskTypeGroup.InboundGroup => BuildInboundCommand(task, stackerCraneTaskCommand),
TaskTypeGroup.OutbondGroup => BuildOutboundCommand(task, stackerCraneTaskCommand),
TaskTypeGroup.RelocationGroup => BuildRelocationCommand(task, stackerCraneTaskCommand),
_ => stackerCraneTaskCommand
};
}
///
/// 构建入库命令
///
private StackerCraneTaskCommand? BuildInboundCommand(Dt_Task task, StackerCraneTaskCommand 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;
}
///
/// 构建出库命令
///
private StackerCraneTaskCommand? BuildOutboundCommand(Dt_Task task, StackerCraneTaskCommand 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;
}
///
/// 构建移库命令
///
private StackerCraneTaskCommand? BuildRelocationCommand(Dt_Task task, StackerCraneTaskCommand 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;
}
///
/// 解析地址字符串(格式:行-列-层)
///
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);
}
}
}