using Autofac.Core; using Microsoft.AspNetCore.Components.Routing; using Microsoft.AspNetCore.Hosting; using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime; using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup; using Quartz; using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel.Design; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Eventing.Reader; using System.Linq; using System.Reflection.Metadata; using System.Text; using System.Threading.Tasks; using WIDESEA_Common.Log; using WIDESEAWCS_Common.TaskEnum; using WIDESEAWCS_Core; using WIDESEAWCS_Core.Enums; using WIDESEAWCS_DTO.Enum; using WIDESEAWCS_ISystemServices; using WIDESEAWCS_ITaskInfoRepository; using WIDESEAWCS_ITaskInfoService; using WIDESEAWCS_Model.Models; using WIDESEAWCS_Model.Models.System; using WIDESEAWCS_QuartzJob; using WIDESEAWCS_QuartzJob.DeviceBase; using WIDESEAWCS_QuartzJob.DTO; using WIDESEAWCS_QuartzJob.Models; using WIDESEAWCS_QuartzJob.Service; using WIDESEAWCS_QuartzJob.StackerCrane; using WIDESEAWCS_QuartzJob.StackerCrane.Enum; using WIDESEAWCS_TaskInfoService; using WIDESEAWCS_Tasks.ConveyorLineJob; using WIDESEAWCS_Tasks.StackerCraneJob; namespace WIDESEAWCS_Tasks { [DisallowConcurrentExecution] public class SpeStackerCraneJob : IJob { private readonly ITaskService _taskService; private readonly ITaskExecuteDetailService _taskExecuteDetailService; private readonly ITaskRepository _taskRepository; private readonly IRouterService _routerService; private readonly IAgvStationService _agvStationService; public SpeStackerCraneJob(ITaskService taskService, ITaskExecuteDetailService taskExecuteDetailService, ITaskRepository taskRepository, IRouterService routerService, IAgvStationService agvStationService) { _taskService = taskService; _taskExecuteDetailService = taskExecuteDetailService; _taskRepository = taskRepository; _routerService = routerService; _agvStationService = agvStationService; } public Task Execute(IJobExecutionContext context) { try { SpeStackerCrane speStackerCrane = (SpeStackerCrane)context.JobDetail.JobDataMap.Get("JobParams"); if (speStackerCrane != null) { GetStackerObject getStackerObject = new GetStackerObject(speStackerCrane); //读取设备完成信息 if (getStackerObject.StaclerkJobJobStatusValue == RgvJobCraneStatus.Completed && getStackerObject.CurrentRgvtaskid != 0) { _taskService.UpdateTaskStatus(getStackerObject.CurrentRgvtaskid,2); } if (getStackerObject.RgvCraneAutoStatusValue == RgvCraneAutoStatus.Automatic && getStackerObject.StaclerkJobJobStatusValue == RgvJobCraneStatus.Ready && getStackerObject.RgvCraneWorkStatusValue == RGVStepprocess.NoAction) { //下发RGV任务之前,先读取一下安全门状态 //查找RGV进行下发任务 Dt_Task task = GetTask(speStackerCrane.DeviceCode); if (task != null) { //调取写入RGV小车任务 RgvCraneTaskCommand? stackerCraneTaskCommand = ConvertToStackerCraneTaskCommand(task); bool sendFlag = getStackerObject.SendCommand(stackerCraneTaskCommand); if (sendFlag) { //修改任务状态 _taskService.UpdateTaskStatusToNext(task); } } } } } catch (Exception ex) { //Console.WriteLine(nameof(CommonStackerCraneJob) + ":" + ex.ToString()); } return Task.CompletedTask; } private Dt_Task? GetTask(string DeviceCode) { Dt_Task task = _taskService.QueryStackerCraneTask(DeviceCode); if (task == null) return null; return task.TaskType switch { (int)TaskInboundTypeEnum.Inbound => HandleInboundTask(task), (int)TaskOutboundTypeEnum.Outbound => HandleOutboundTask(task), _ => null }; } private Dt_Task? HandleInboundTask(Dt_Task task) { return task.TaskState switch { (int)TaskInStatusEnum.RGV_InNew => task, (int)TaskInStatusEnum.RGV_InPickupFinish => HandlePickupFinish(task), (int)TaskInStatusEnum.RGV_InReleaseFinish => HandInneRouterSides(task), (int)TaskInStatusEnum.RGV_InZicheFinish => HandleZicheFinish(task), (int)TaskInStatusEnum.RGV_InZicheReleaseFinish => HandleZicheReleaseFinish(task), (int)TaskInStatusEnum.RGV_InZichemoveFinish => HandleZicheMoveFinish(task), _ => null }; } private Dt_Task? HandleOutboundTask(Dt_Task task) { // 出库任务的状态判断相对简单,可以直接返回 int[] validStates = { (int)TaskOutStatusEnum.OutNew, (int)TaskOutStatusEnum.RGV_OutMothercarFinish, (int)TaskOutStatusEnum.RGV_OutZicheFinish, (int)TaskOutStatusEnum.RGV_OutZicheReleaseFinish, (int)TaskOutStatusEnum.RGV_OutPickupFinish }; return validStates.Contains(task.TaskState) ? task : null; } #region 入库方法 private Dt_Task? HandInneRouterSides(Dt_Task task) { // 验证输入 if (task == null) throw new ArgumentNullException(nameof(task)); if (string.IsNullOrEmpty(task.CurrentAddress)) return null; // 获取当前站台信息 AGVStation currentStation = _agvStationService.GetAllStationByDeviceCode(int.Parse(task.CurrentAddress)); if (currentStation == null) return null; // 只处理特定类型的站台 if (currentStation.Station_material != (int)AgvStationEnum.HCJAisleplatform) return task; // 获取子车位置 int zicheAddress = GetZichelocation(task, task.CurrentAddress); if (zicheAddress == 0) return null; AGVStation zicheStation = _agvStationService.GetAllStationByDeviceCode(zicheAddress); if (zicheStation == null) return null; // 根据子车位置处理不同情况 switch (zicheStation.Station_material) { case (int)AgvStationEnum.Aisleplatform_Outside: // 子车在外侧 - 直接返回任务 return task; case (int)AgvStationEnum.Aisleplatform_Medial: // 子车在内侧 - 检查母车位置 return HandleMedialCase(task, currentStation, zicheStation); default: // 未知的子车位置状态 return null; } } private Dt_Task? HandleMedialCase(Dt_Task task, AGVStation currentStation, AGVStation zicheStation) { int motherCarAddress = GetMothercarlocation(task.TaskNum, currentStation.MotherCarDeviceCode); if (motherCarAddress == 0) return null; // 如果母车不在预期位置,下发移动任务 if (motherCarAddress != int.Parse(currentStation.MotherCarDeviceCode)) { RGVMovetask(zicheStation.Motherinlaw, currentStation.ChildPosiDeviceCode, task.TaskId); return null; // 母车需要移动,暂不返回任务 } // 母车已在正确位置 return task; } private Dt_Task? HandlePickupFinish(Dt_Task task) { try { //获取需要区分是否去入库与去不合格载货台任务 IDevice? device = Storage.Devices.FirstOrDefault(x => x.DeviceCode == "HCJ2000"); CommonStackerCrane Commonstacker = (CommonStackerCrane)device; DeviceProDTO? deviceProDTO = GetDeviceProDTO(Commonstacker, task.NextAddress, "HCJ_GoodsStatus"); int HCJGStatus = GetLine(Commonstacker, deviceProDTO.DeviceProAddress); if (HCJGStatus == 0) //为无货 { return task; } } catch (Exception ex) { //记录异常情况 _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"判断HCJ站台是否有货信息出错,出错信息:{ex.Message}"); throw; } return null; } private Dt_Task? HandleZicheFinish(Dt_Task task) { //获取放货地址 AGVStation aGVStation = _agvStationService.GetAllStationByDeviceCode(int.Parse(task.NextAddress)); //分3区域进行放货 return aGVStation.Station_Area switch { 1 => CheckMotherCarMove(task, aGVStation, MotherCarMoves), //外侧放货 2 => CheckMotherCarMove(task, aGVStation, MotherCarMovesinside), //内侧放货 3 => CheckMotherCarMove(task, aGVStation, HCJMotherCarMovesinside), //交接点放货 _ => null }; } private Dt_Task? CheckMotherCarMove(Dt_Task task, AGVStation station, Func moveFunc) { return moveFunc(task, station) ? task : null; } private Dt_Task? HandleZicheReleaseFinish(Dt_Task task) { AGVStation aGVStation = _agvStationService.GetAllStationByDeviceCode(int.Parse(task.CurrentAddress)); //当前地址,母车上,下一个地址堆垛机取货口 if (aGVStation.Station_Area == 1 && aGVStation.Station_Area == 2) { return task; //返回子车移动任务 } else if (aGVStation.Station_Area == 3) //当前地址为HCJ站台,且AGV任务为取货 { return task; //去取货位,需要判断子车当前位子,(后续优化) } return null; } private Dt_Task? HandleZicheMoveFinish(Dt_Task task) { AGVStation aGVStation = _agvStationService.GetAllStationByDeviceCode(int.Parse(task.CurrentAddress)); int zicheAddress = GetZichelocation(task, task.CurrentAddress); //如果子车在母车上,则需要移库母车(待优化) return zicheAddress != int.Parse(aGVStation.ZicheMotherinlaw) ? task : null; } #endregion //区域一判断母车是否到位,可立即放货 private bool MotherCarMoves(Dt_Task _Task, AGVStation aGVStation) { int mcadder = GetMothercarlocation(_Task.TaskNum, aGVStation.Motherinlaw); //获取到母车外侧位置 if (mcadder != 0) { if (mcadder == int.Parse(_Task.CurrentAddress)) { return true; } RGVMovetask(_Task.CurrentAddress, aGVStation.ChildPosiDeviceCode, _Task.TaskId); } return false; } /// /// 子母车移动任务 /// /// 目标地址 /// 设备编号 /// private bool RGVMovetask(string RGVAdders, string ChildPosiDeviceCode, int taskid) { RgvCraneTaskCommand standardCommands = ConvertMotherCarTaskCommand(RGVAdders); bool sendFlag = SendCommand2(standardCommands, ChildPosiDeviceCode); return sendFlag; } /// /// 判断内侧母车位置 /// /// /// /// private bool MotherCarMovesinside(Dt_Task _Task, AGVStation aGVStation) { //获取外侧母车位置 int mcadder = GetMothercarlocation(_Task.TaskNum, aGVStation.MotherCarDeviceCode); //获取内侧母车位置 int ncadder = GetMothercarlocation(_Task.TaskNum, _Task.NextAddress); if (mcadder != int.Parse(aGVStation.MotherCarDeviceCode) && ncadder == aGVStation.Station_code) { return true; } else { if (mcadder == int.Parse(aGVStation.MotherCarDeviceCode)) { AGVStation aGVSta = _agvStationService.GetMothercarCode(aGVStation.MotherCarDeviceCode); RGVMovetask(aGVSta.ChildPosiDeviceCode, aGVSta.Station_code.ToString(), _Task.TaskId); } if (ncadder != aGVStation.Station_code) { RGVMovetask(aGVStation.ChildPosiDeviceCode, aGVStation.Station_code.ToString(), _Task.TaskId); } } return false; } private bool HCJMotherCarMovesinside(Dt_Task _Task, AGVStation aGVStation) { //获取外侧母车位置 int mcadder = GetMothercarlocation(_Task.TaskNum, aGVStation.MotherCarDeviceCode); //获取内侧母车位置 int ncadder = GetMothercarlocation(_Task.TaskNum, aGVStation.MotherCardeputy); if (mcadder != int.Parse(aGVStation.MotherCarDeviceCode) && ncadder != int.Parse(aGVStation.MotherCardeputy)) { return true; } else { if (mcadder == int.Parse(aGVStation.MotherCarDeviceCode)) { AGVStation aGVSta = _agvStationService.GetMothercarCode(aGVStation.MotherCarDeviceCode); RGVMovetask(aGVSta.ChildPosiDeviceCode, aGVSta.Station_code.ToString(), _Task.TaskId); } if (ncadder == int.Parse(aGVStation.MotherCardeputy)) { AGVStation aGVSta = _agvStationService.GetMothercarCode(aGVStation.MotherCardeputy); RGVMovetask(aGVSta.ChildPosiDeviceCode, aGVSta.Station_code.ToString(), _Task.TaskId); } } return false; } //判断是否 public bool GetMotherCarCurrentAdder(Dt_Task task) { try { IDevice? device = Storage.Devices.FirstOrDefault(x => x.DeviceCode == "HCJ2000"); CommonStackerCrane Commonstacker = (CommonStackerCrane)device; DeviceProDTO? deviceProDTO = GetDeviceProDTO(Commonstacker, task.CurrentAddress, "HCJ_GoodsStatus"); int HCJGStatus = GetLine(Commonstacker, deviceProDTO.DeviceProAddress); if (HCJGStatus == 0) //为无货 { return true; } } catch (Exception ex) { //记录异常情况 _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"判断HCJ站台是否有货信息出错,出错信息:{ex.Message}"); throw; } return false; } /// /// 传入过道地址,获取母车位置 /// /// /// 过道地址 /// public int GetMothercarlocation(int TaskNum, string MotherCarDeviceCode) { try { //利用入库站台地址获取母车plc AGVStation aGVStation = _agvStationService.GetMothercarCode(MotherCarDeviceCode); IDevice? device = Storage.Devices.FirstOrDefault(x => x.DeviceCode == aGVStation.ChildPosiDeviceCode); CommonStackerCrane Commonstacker = (CommonStackerCrane)device; DeviceProDTO? deviceProDTO = GetDeviceProDTO(Commonstacker, aGVStation.ChildPosiDeviceCode, "RGVCurrentlocation"); int HCJGStatus = GetLine(Commonstacker, deviceProDTO.DeviceProAddress); return HCJGStatus; } catch (Exception ex) { //记录异常情况 _taskService.UpdateTaskExceptionMessage(TaskNum, $"判断母车位置信息出错,出错信息:{ex.Message}"); throw; } } /// /// 传入过道地址,获取子车车位置 /// /// /// 入库站台地址 /// public int GetZichelocation(Dt_Task task, string ChildPosiDeviceCode) { try { IDevice? device = Storage.Devices.FirstOrDefault(x => x.DeviceCode == ChildPosiDeviceCode); CommonStackerCrane Commonstacker = (CommonStackerCrane)device; DeviceProDTO? deviceProDTO = GetDeviceProDTO(Commonstacker, ChildPosiDeviceCode, "RGVCurrentlocation"); int HCJGStatus = GetLine(Commonstacker, deviceProDTO.DeviceProAddress); return HCJGStatus; } catch (Exception ex) { //记录异常情况 _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"判断子车位置信息出错,出错信息:{ex.Message}"); throw; } } /// /// 任务实体转换成命令Model /// /// 任务实体 /// /// public RgvCraneTaskCommand? ConvertToStackerCraneTaskCommand([NotNull] Dt_Task task) { RgvCraneTaskCommand stackerCraneTaskCommand = new RgvCraneTaskCommand(); short locaticurr = task.RGVTaskType switch { _ when task.RGVTaskType == (short)RGVTaskTypeEnum.PickingUp || task.RGVTaskType == (short)RGVTaskTypeEnum.TravelingOnly => short.Parse(task.CurrentAddress), _ when task.RGVTaskType == (short)RGVTaskTypeEnum.Placing => short.Parse(task.NextAddress), _ => (short)0 }; stackerCraneTaskCommand.RGV_RGVTasklocation = locaticurr; stackerCraneTaskCommand.RGV_RGVtasktype = (short)task.RGVTaskType; stackerCraneTaskCommand.RGV_Rgvtaskid = (short)task.TaskNum; stackerCraneTaskCommand.RGV_Lanjiantaskid = (short)task.TaskNum; return stackerCraneTaskCommand; } /// /// 下发移动任务 /// /// 任务实体 /// /// public RgvCraneTaskCommand? ConvertMotherCarTaskCommand(string RGVAddress) { RgvCraneTaskCommand stackerCraneTaskCommand = new RgvCraneTaskCommand(); stackerCraneTaskCommand.RGV_RGVTasklocation = short.Parse(RGVAddress); stackerCraneTaskCommand.RGV_RGVtasktype = 3; stackerCraneTaskCommand.RGV_Rgvtaskid = 999; //rgv任务号 stackerCraneTaskCommand.RGV_Lanjiantaskid = 999; //兰剑任务id return stackerCraneTaskCommand; } public void wcsWriteLog(string SCLLinStack, string Logtype, string Magessadd) { WriteLog.Write_Log("RGV", SCLLinStack + "号RGV", Logtype, new { 信息 = Magessadd }); } //===========================================================HCJ协议读写查============================================================================= /// /// 查询具体地址 /// /// /// /// /// public DeviceProDTO? GetDeviceProDTO(CommonStackerCrane Commonstacker, string SCAddress, string Interactivet) { return Commonstacker.DeviceProDTOs.FirstOrDefault(x => x.DeviceChildCode == SCAddress && x.DeviceProParamName == Interactivet && x.DeviceProParamType == "ReadDeviceCommand"); } /// /// 根地址读取输送线信息 /// /// /// /// public int GetLine(CommonStackerCrane Commonstacker, string DeviceProDataBlock) { return Commonstacker.Communicator.Read(DeviceProDataBlock); } //===========================================================HCJ协议读写查=============================================================================== public bool SendCommand2(RgvCraneTaskCommand command, string DeviceCode) { try { IDevice? device = Storage.Devices.FirstOrDefault(x => x.DeviceCode == DeviceCode); CommonStackerCrane Commonstacker = (CommonStackerCrane)device; DeviceProDTO? deviceProDTO = GetDeviceProDTO(Commonstacker, DeviceCode, "RGV_Rgvtaskstutas"); int MCGStatus = GetLine(Commonstacker, deviceProDTO.DeviceProAddress); if (Commonstacker.IsConnected) { if (MCGStatus == (int)RgvJobCraneStatus.Ready) { Commonstacker.SetValue(RgvCraneDBName.RGV_RGVTasklocation, command.RGV_RGVTasklocation); Commonstacker.SetValue(RgvCraneDBName.RGV_RGVtasktype, command.RGV_RGVtasktype); Commonstacker.SetValue(RgvCraneDBName.RGV_Rgvtaskid, command.RGV_Rgvtaskid); Commonstacker.SetValue(RgvCraneDBName.RGV_Lanjiantaskid, command.RGV_Lanjiantaskid); return true; } } return false; } catch (Exception ex) { return false; } } } }