using Serilog; using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using WPFWCSDemo.Common; using WPFWCSDemo.Data; using WPFWCSDemo.Models.Devices.CircleRGV; using WPFWCSDemo.Models.Tables; using WPFWCSDemo.StateCode; using WPFWCSDemo.Utilities; using WPFWCSDemo.ViewModels; namespace WPFWCSDemo.Schedules.CircleRGV { /// /// 任务校验 /// public class Check { static int deviceCount = RGVStation.RGVCount; /// /// 生成【空托】任务条件校验 /// /// 源站点(可表示某条输送线) /// 目标站点(可表示某条输送线) /// 输送口是否正常 true-系统正常 false-系统异常 /// 是否满足生成任务条件 true-可生成 false-禁止生成 public static bool CanTaskGenerated(int sourceLocation, int targetLocation, bool isNotException) { //校验---源站点请求 if (QueryForIsRequestReset(sourceLocation, 3)) return false; //校验---目标站点请求 if (QueryForIsRequestReset(targetLocation, 3)) return false; //校验---系统异常 if (!isNotException) return false; //校验---同输送口相邻任务生成时间间隔过短 if (!CheckSendTaskTimeInterval(targetLocation, 999)) return false; //校验---如果已经存在处于【取货阶段】的某个【空托】任务 //由于【空托任务】输送线的源站点唯一,因此必须等待该任务取货完成才能生成新的【空托】任务 if (!IsPalletConvHasGettingTask()) return false; //校验---当前输送线存在【空托】任务 if (!GetRGVTaskForPalletsIsExist(targetLocation)) return false; //校验5.当前同一【目标站点】是否已经生成任务 if (!CheckSendTaskIsRepeat(sourceLocation, TaskType.Pallet)) return false; //校验---上位是否手动禁止生成 if (LineTaskForPermission(targetLocation) == 0) return false; return true; } /// /// 生成【实垛】任务校验条件 /// /// 源站点(可表示某条输送线) /// 输送口是否正常 true-系统正常 false-系统异常 /// 是否满足生成任务条件 true-可生成 false-禁止生成 public static bool CanTaskGenerated(int sourceLocation, bool isNotException) { //校验0 放货口无允许 //2025.9新增 //1003-1009输送口校验 if (sourceLocation == RGVStation.LineM_Goods_In) { if (QueryForIsRequestReset(RGVStation.LineToWarehouse1_Out, 3)) return false; } //2025.9新增 //1005-1010输送口校验 if (sourceLocation == RGVStation.LineL_Goods_In) { if (QueryForIsRequestReset(RGVStation.LineToWarehouse2_Out, 3)) return false; } //校验1.输送口无请求 if (QueryForIsRequestReset(sourceLocation, 3)) return false; //校验2.输送口系统异常 if (!isNotException) return false; //校验3.同输送口相邻任务生成时间间隔过短 if (!CheckSendTaskTimeInterval(sourceLocation)) return false; //校验4.当前输送线存在取货阶段的任务 if (!GetRGVTaskForGoodsIsExist(sourceLocation)) return false; //校验5.当前同一【源站点】是否已经生成【取货阶段】任务 if (!CheckSendTaskIsRepeat(sourceLocation, TaskType.Goods)) return false; return true; } /// /// 防错机制【用于避免请求延迟的重复下发】--- 检测上一条【实垛】任务放货时间与当前时间是否相差x秒以上 /// /// 站点 /// true-相差大于x秒 false-相差小于x秒 public static bool CheckSendTaskTimeInterval(int location) { int diff = -15; using var context = new AppDbContext(); var loadedState = context .Set() .Where(t => t.Station == location) .FirstOrDefault(); if (DateTime.Now.AddSeconds(diff) >= loadedState!.LoadingTime) { return true; } else { return false; } } /// /// 防错机制【用于避免请求延迟的重复下发】--- 检测上一条【空托】任务放货时间(完成时间)与当前时间是否相差x秒以上 /// /// 站点 /// true-相差大于x秒 false-相差小于x秒 public static bool CheckSendTaskTimeInterval(int location, int num) { int diff = -30; using var context = new AppDbContext(); var loadedState = context .Set() .Where(t => t.Station == location) .FirstOrDefault(); if (DateTime.Now.AddSeconds(diff) >= loadedState!.PuttingTime) { return true; } else { return false; } } /// /// 防错机制【重复下发】--- 检测已经生成但未下发的任务是否存在 /// /// 源站点 /// true-同目标站点生成任务时间间隔合法 false-时间间隔过短 public static bool CheckSendTaskIsRepeat(int location, int type) { using var context = new AppDbContext(); //实垛 if (type == TaskType.Goods) { //生成的上一条【实垛】任务且同一个源站点 ---> 查找符合条件的记录 var count = context .Set() .Where(t => t.SourceLocation == location.ToString() && (t.ScheduleState==ScheduleStateCode.Trans_CircleRGV_Ready || t.ScheduleState == ScheduleStateCode.Trans_CircleRGV_PickOnTheWay || t.ScheduleState == ScheduleStateCode.Trans_CircleRGV_Picking)) .Count(); if (count < 1) { return true; } } //空托 if (type == TaskType.Pallet) { //生成的上一条【空托】任务且同一个目标站点 ---> 查找符合条件的记录 var count1 = context .Set() .Where(t => t.TargetLocation == location.ToString()) .Count(); if (count1 < 1) { return true; } } return false; } /// /// 计算某个输送口请求的值的和---用于确定该输送口在一定时间内请求是否已经复位 /// 用于避免信号也许存在的不稳定(跳变)的情况 /// /// 源站点/目标站点---表示对应列 /// 计算的时间间隔(单位:秒) /// true-无请求---已复位 false-请求存在-未复位 public static bool QueryForIsRequestReset(int location, int count) { var context = new AppDbContext(); string s = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"); var timeIsExist = context.ConvRequest .Where(a => a.Time == s) .Count(); if (timeIsExist == 0) { return false; } string line = ""; switch (location) { case RGVStation.LineH_Goods_In: line = "Conv_Goods_In_1001"; break; case RGVStation.LineM_Goods_In: line = "Conv_Goods_In_1003"; break; case RGVStation.LineL_Goods_In: line = "Conv_Goods_In_1005"; break; case RGVStation.LineG1_Goods_In: line = "Conv_Goods_In_1007"; break; case RGVStation.LineG2_Goods_In: line = "Conv_Goods_In_1008"; break; case RGVStation.LineGH_Pallets_In: line = "Conv_Pallets_In_1013"; break; case RGVStation.LineH_Pallets_Out: line = "Conv_Pallets_Out_1002"; break; case RGVStation.LineG_Pallets_Out: line = "Conv_Pallets_Out_1004"; break; case RGVStation.LineLM_Pallets_Out: line = "Conv_Pallets_Out_1006"; break; case RGVStation.LineToWarehouse1_Out: line = "Conv_Goods_Out_1009"; break; case RGVStation.LineToWarehouse2_Out: line = "Conv_Goods_Out_1010"; break; } if (string.IsNullOrEmpty(line)) { return false; } //获取当前时间节点前x行请求记录值 using DataTable? dt = SqlHelper.ExecuteTable($"SELECT TOP {count} * FROM CONVREQUEST ORDER BY [time] DESC"); //无结果则返回 if (dt is null || dt.Rows.Count == 0) { return false; } int sum = 0; //计算源站点对应某列3行请求(允许)值的和 for (int i = 0; i < dt.Rows.Count; i++) { sum += (int)dt.Rows[i][line]; } if (sum == 0) { //为0---无请求 return true; } else { //不等于0,请求存在或存在值跳变情况 return false; } } /// /// 手动禁止某条输送线下发任务(根据名称) /// /// 输送线名称 /// 0-禁止 1-允许 public static int LineTaskForPermission(string name) { using var context = new AppDbContext(); var lineState = context.LineState .Where(p => p.Name == name) .Select(p => p.IsEnable) .FirstOrDefault(); return lineState; } /// /// 手动禁止某条输送线下发任务(根据目标站) /// /// 源站点 /// 0-禁止 1-允许 public static int LineTaskForPermission(int target) { using var context = new AppDbContext(); var lineState = context.LineState .Where(p => p.Target == target) .Select(p => p.IsEnable) .FirstOrDefault(); return lineState; } /// /// 遍历环穿是否有某条输送线正在执行的(栈板)任务---即只要有该输送口的任务则不能生成新任务 /// 判断条件 1.站点 2.执行阶段 3.允许下发 /// (该方法会直接读取小车参数) /// /// 源站点(1至2位编号) /// false-存在执行中的任务的设备 true-无在执行任务的设备 public static bool GetRGVTaskForPalletsIsExist(int targetLocation) { List? states = CircleRGVsViewModel.GetAllCircleRGVState(); if (states is null) return false; //检查是否有符合条件的小车,如果有则标 //【源站点】匹配 // 任务处于【取货阶段】 // 无【允许下发】---表示小车在工作中 var count = states .Where(a => a.Read_TargetLocation == (targetLocation - 1000).ToString() && !a.Read_Permission) .Count(); if (count > 0) { return false; } //无满足条件的小车则表示所有设备无此任务 return true; } /// /// 遍历环穿是否有某条输送线正在执行的(实垛)任务---某站点输送线存在【取货阶段】任务时不能生成新任务 /// 判断条件: /// 1.站点匹配 /// 2.执行阶段--->取货阶段 /// 3.允许下发 /// (该方法会直接从地面站读取小车参数) /// /// 源站点(1至2位编号) /// false-存在执行任务的设备(不能下发) true-无执行中的任务的设备(可下发) public static bool GetRGVTaskForGoodsIsExist(int sourceLocation) { List states = CircleRGVsViewModel.GetAllCircleRGVState(); if (states is null) return false; //检查是否有符合条件的小车,如果有则标 //【源站点】匹配 // 任务处于【取货阶段】 // 无【允许下发】---表示小车在工作中 var count = states .Where(a => a.Read_SourceLocation == (sourceLocation - 1000).ToString() && a.Read_Phase < 3 && a.Read_Phase > 0 && !a.Read_Permission) .Count(); if (count > 0) { return false; } //无满足条件的小车则表示所有设备无此任务 return true; } /// /// 检查是否存在已经生成的处于【取货阶段】的【栈板】任务 --- 源站点每次请求仅生成一条任务 /// /// true-无符合条件的任务(即可生成新任务) false-存在符合条件的任务 public static bool IsPalletConvHasGettingTask() { var context = new AppDbContext(); var count =context.Tasks .Where(a=>a.SourceLocation == RGVStation.LineGH_Pallets_In.ToString() && (a.ScheduleState == ScheduleStateCode.Trans_CircleRGV_Ready || a.ScheduleState == ScheduleStateCode.Trans_CircleRGV_PickOnTheWay || a.ScheduleState == ScheduleStateCode.Trans_CircleRGV_Picking)) .Count(); if (count > 0) { return false; } return true; } } }