using HslCommunication; using Quartz; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using WIDESEA_Common; using WIDESEA_Common.TaskEnum; using WIDESEA_Core.EFDbContext; using WIDESEA_Core.Utilities; using WIDESEA_Entity.CustomModels.RGVModel; using WIDESEA_Entity.DomainModels; using WIDESEA_Services; using WIDESEA_Services.IRepositories; using WIDESEA_Services.Repositories; using WIDESEA_Services.Services; using WIDESEA_Services.Services.APIInvoke.RGV; using WIDESEA_WCS.Jobs; using WIDESEA_Common.Tools; using WIDESEA_WCS.WCSClient; using static WIDESEA_Entity.CustomModels.RGVModel.RgvSendTaskModel; using static WIDESEA_Entity.CustomModels.RGVModel.RgvDeviceStatusModel; using WIDESEA_Core.Services; using WIDESEA_Core.Enums; namespace WIDESEA_WCS { [DisallowConcurrentExecution] public partial class RgvDispatchJob : JobBase, IJob { /// /// RGV(有轨小车)调度 /// /// /// public Task Execute(IJobExecutionContext context) { return Task.Run(() => { var executeLog = ExecuteJob(context, () => Run(context)); }); } public static bool TempHK = false; // 是否空托盘回库优先 public static int HKNumber = 0; // 空托盘回库的数量 如果已经回了四个了 那就不能限制出库的了 string[] endStationNo = new string[] { "70101", "70103", "70104", "70106" }; public string Run(IJobExecutionContext context) { using (VOLContext dbCcontext = new VOLContext()) { WebResponseContent content = new WebResponseContent(); IDt_TaskRGVinfoRepository taskRGVinfoRepository = new Dt_TaskRGVinfoRepository(dbCcontext); IDt_TaskWCSinfoRepository taskWCSinfoRepository = new Dt_TaskWCSinfoRepository(dbCcontext); //查看PLC连接的情况 PLCClient client = WCSService.Clients.Find(r => r.PLCName == "LineDevice"); if (!client.IsConnected) { // Console.WriteLine("RGV无法调度,线体PLC与WCS系统断开了连接"); return "RGV无法调度,线体PLC与WCS系统断开了连接"; } //发送任务之前,看是否有小车可用 content = RGVAPIInvokeGetRgvInfo.GetRgvInfo(); if (!content.Status) return $"获取小车状态出错,原因:{content.Message}"; RgvDeviceStatusModel rgvData = (RgvDeviceStatusModel)content.Data; int carCount = 0; List currentLayer = new List(); foreach (var item in rgvData.data) { if (item.rgvId == "1") { client.WriteValue(CLineInfoDBName.RGV01.ToString(), item.status); } if (item.rgvId == "2") { client.WriteValue(CLineInfoDBName.RGV02.ToString(), item.status); } if (item.rgvId == "3") { client.WriteValue(CLineInfoDBName.RGV03.ToString(), item.status); } //0离线 1正常 2故障 if (item.status != 1) carCount++; else currentLayer.Add(item.layer); } if (carCount == 3) { Console.WriteLine($"当前无小车可用,无法下发任务"); return $"当前无小车可用,无法下发任务"; } //找等待下发的任务 List rgvTaskList = taskRGVinfoRepository.Find(x => x.rgvtask_taskStatus == RGVTaskState.RgvTaskState_Wait_Send.ToString()).OrderBy(r => r.rgvtask_msgTime).ToList(); if (null != rgvTaskList && rgvTaskList.Count > 0) { //暂时注释 int modelValue = int.Parse(client.ReadValue(CLineInfoDBName.R_System_Inline_Run_Model.ToString(), "System").ToString()); //1=手动 2=单机 3=联机 if (modelValue != 3) rgvTaskList = rgvTaskList.Where(r => r.rgvtask_areaCode != "InboundArea").ToList(); modelValue = int.Parse(client.ReadValue(CLineInfoDBName.R_System_Inline_Run_Model.ToString(), "OutSystem").ToString()); if (modelValue != 3) rgvTaskList = rgvTaskList.Where(r => r.rgvtask_areaCode != "OutboundArea").ToList(); if (null != rgvTaskList) { List listTask = new List(); //优先出库区 List outboundArea = rgvTaskList.FindAll(r => r.rgvtask_areaCode != "InboundArea"); if (outboundArea.Count > 0) listTask.AddRange(outboundArea); List inboundArea = rgvTaskList.FindAll(r => r.rgvtask_areaCode != "OutboundArea"); if (inboundArea.Count > 0) { int layer = 0; List layerTask = new List(); List ortherTask = new List(); foreach (var item in inboundArea) { if (item.rgvtask_taskType.Equals(RGVTaskType.RgvTaskType_Inbound.ToString())) layer = int.Parse(item.rgvtask_startNode.Split('-')[0]); else if (item.rgvtask_taskType.Equals(RGVTaskType.RgvTaskType_Outbound.ToString())) layer = int.Parse(item.rgvtask_endNode.Split('-')[0]); if (currentLayer.Contains(layer)) layerTask.Add(item); else ortherTask.Add(item); } if (layerTask.Count > 0) listTask.AddRange(layerTask); if (ortherTask.Count > 0) listTask.AddRange(ortherTask); } rgvTaskList = listTask; } foreach (var rgvTask in rgvTaskList) { //找到RGV任务对应的WCS任务,看是否有会冲突的任务发生,如果有?先不下发:下发 //比如有一个入库任务正在执行,目的站台为:050301,那么走050301的出库测量任务RGV段的则不能下发,避免冲突 Dt_TaskWCSinfo wcsInfo = taskWCSinfoRepository.FindFirst(x => x.wcstask_taskNumber == rgvTask.rgvtask_wcsTaskNumber); if (null == wcsInfo) { //手动任务 if (rgvTask.rgvtask_wcsTaskNumber == 0 && rgvTask.rgvtask_taskId == "0") { SendRGVTaskAction(rgvTask, wcsInfo, taskRGVinfoRepository, taskWCSinfoRepository); } continue; } // 这里加一个判断,比如我有两个任务去70101 我任务A先下发 理应先到70101 但可能任务A受rgv换层的影响 任务B 先到出库区的缓存架 导致B先过去到了70101那边 // 这里要判断 如果我任务B的RGV任务要下发的时候,判断前面是否有任务,如果有,判断这个任务是否已到达缓存架或者是任务出库输送线执行中才能下发 if (endStationNo.Contains(wcsInfo.wcstask_endPoint)) // 证明是去压装台的 { Dt_TaskWCSinfo WcsTask = taskWCSinfoRepository.FindFirst(x => x.wcstask_endPoint == wcsInfo.wcstask_endPoint && x.wcstask_taskNumber != wcsInfo.wcstask_taskNumber && x.wcstask_type == TaskType.TaskType_Box_Pallet_Outbound.ToString() && x.wcstask_state != TaskState.TaskState_Assigned.ToString() && x.wcstask_state != TaskState.TaskState_Box_Out_Line_Executing.ToString() && x.wcstask_state != TaskState.TaskState_HoisterExecuting.ToString() ); if (WcsTask != null) { continue; } } //再做一个保护,查看对应的放货站台上是有有货,即读取站台是否处于负载待机的状态,如果是,说明有东西 if (wcsInfo.wcstask_type == TaskType.TaskType_Box_Pallet_Measure_Out.ToString() || wcsInfo.wcstask_type == TaskType.TaskType_Empty_Pallet_Outbound.ToString() || wcsInfo.wcstask_type == TaskType.TaskType_Box_Pallet_Outbound.ToString() || wcsInfo.wcstask_type == TaskType.TaskType_CheckOutbound.ToString() || //移库需要跨层 (wcsInfo.wcstask_type == TaskType.TaskType_MoveOutbound.ToString() && wcsInfo.wcstask_startPoint != wcsInfo.wcstask_endPoint) ) { //穿梭车放货站台 string targetStation = wcsInfo.wcstask_endLocation; //判断有到当前放货位置的就不执行 Dt_TaskWCSinfo executingTask = taskWCSinfoRepository.FindFirst(r => r.wcstask_endPoint == targetStation && r.wcstask_id != wcsInfo.wcstask_id && r.wcstask_state != TaskState.TaskState_Assigned.ToString()); if (null != executingTask) // 这个判断主要是判断空托盘回库的 如果空托盘回库到60101 那出库到60101的就不能下发 { continue; } // 这里获取一个空托盘回库的,如果我的空托已经在外面排队很长了 那我就不能下发库的任务了 // 这里要读取一个信号 int Return_Quantity = int.Parse(client.ReadValue(CLineInfoDBName.Return_Quantity.ToString()).ToString()); if (Return_Quantity >= 8) // 只要空托盘在路上的数量 >= 8 那么回空托盘的优先级就要提高了 { TempHK = true; } if (HKNumber == 4) { TempHK = false; HKNumber = 0; } if (TempHK) { if ((wcsInfo.wcstask_type == TaskType.TaskType_Box_Pallet_Outbound.ToString() || wcsInfo.wcstask_type == TaskType.TaskType_Empty_Pallet_Outbound.ToString()) && wcsInfo.wcstask_state == TaskState.TaskState_Assigned.ToString() && endStationNo.Contains(wcsInfo.wcstask_endPoint)) { continue; } } // 如果四个站台同时有负载,那我就要把我的TempHK 给设置为True 当设置为True了 我就会进入一个条件 //if (rgvTask.rgvtask_areaCode.Equals("OutboundArea")) //{ // //当前层有任务就不执行 // Dt_TaskRGVinfo rgvcurrentTask = taskRGVinfoRepository.FindFirst(r => (r.rgvtask_startNode == rgvTask.rgvtask_startNode || // rgvTask.rgvtask_endNode == r.rgvtask_endNode || rgvTask.rgvtask_startNode == r.rgvtask_endNode || // rgvTask.rgvtask_endNode == r.rgvtask_startNode) && r.rgvtask_taskStatus != RGVTaskState.RgvTaskState_Wait_Send.ToString()); // if (null != rgvcurrentTask) // continue; //} if (rgvTask.rgvtask_areaCode.Equals("InboundArea") && !rgvTask.rgvtask_taskType.Equals(RGVTaskType.RgvTaskType_Inbound.ToString())) { //读取负载待机,有货 bool flag = bool.Parse(client.ReadValue(CLineInfoDBName.R_Line_LoadSleep.ToString(), rgvTask.rgvtask_endNode).ToString()); bool noflag = bool.Parse(client.ReadValue(CLineInfoDBName.R_Line_NoLoadSleep.ToString(), rgvTask.rgvtask_endNode).ToString()); if (flag || !noflag) continue; else { Dt_TaskRGVinfo currentTask = taskRGVinfoRepository.FindFirst(r => r.rgvtask_endNode == rgvTask.rgvtask_endNode && r.rgvtask_taskStatus != RGVTaskState.RgvTaskState_Wait_Send.ToString()); if (null != currentTask) continue; } } //此处查看当前正在进行的测量任务条数,需要控制数量,线体缓存数量有限,测量需要时间,暂定2个 if (wcsInfo.wcstask_type == TaskType.TaskType_Box_Pallet_Measure_Out.ToString()) { List measureList = taskWCSinfoRepository.Find(x => x.wcstask_state != TaskState.TaskState_Assigned.ToString() && (x.wcstask_endPoint == "10301" || x.wcstask_startPoint == "10301")); if (measureList.Count > 1)//tx 0921 2->1 { //说明测量任务达到上限值,需要等待 Console.WriteLine("当前执行的测量任务已达到上限,其它测量任务需等待"); continue; } } } SendRGVTaskAction(rgvTask, wcsInfo, taskRGVinfoRepository, taskWCSinfoRepository); } } } return ""; } } }