Files
FT479/WPFWCSDemo/Schedules/CircleRGV/Check.cs
2026-07-07 14:00:05 +08:00

448 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
{
/// <summary>
/// 任务校验
/// </summary>
public class Check
{
static int deviceCount = RGVStation.RGVCount;
/// <summary>
/// 生成【空托】任务条件校验
/// </summary>
/// <param name="sourceLocation">源站点(可表示某条输送线)</param>
/// <param name="targetLocation">目标站点(可表示某条输送线)</param>
/// <param name="isNotException">输送口是否正常 true-系统正常 false-系统异常</param>
/// <returns>是否满足生成任务条件 true-可生成 false-禁止生成</returns>
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, 120))
return false;
//校验---如果已经存在处于【取货阶段】的某个【空托】任务
//由于【空托任务】输送线的源站点唯一,因此必须等待该任务取货完成才能生成新的【空托】任务
if (!IsPalletLineHasTask())
return false;
//校验---当前输送线存在【空托】任务
if (!GetRGVTaskForPalletsIsExist(targetLocation))
return false;
//校验5.当前同一【目标站点】是否已经生成任务
if (!CheckSendTaskIsRepeat(sourceLocation, TaskType.Pallet))
return false;
//校验---上位是否手动禁止生成
if (LineTaskForPermission(targetLocation) == 0) return false;
return true;
}
/// <summary>
/// 生成【实垛】任务校验条件
/// </summary>
/// <param name="sourceLocation">源站点(可表示某条输送线)</param>
/// <param name="isNotException">输送口是否正常 true-系统正常 false-系统异常</param>
/// <returns>是否满足生成任务条件 true-可生成 false-禁止生成</returns>
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;
}
/// <summary>
/// 防错机制【用于避免请求延迟的重复下发】--- 检测上一条【实垛】任务放货时间与当前时间是否相差x秒以上
/// </summary>
/// <param name="location">站点</param>
/// <returns> true-相差大于x秒 false-相差小于x秒</returns>
public static bool CheckSendTaskTimeInterval(int location)
{
int diff = -20;
using var context = new AppDbContext();
var loadedState = context
.Set<LoadedState>()
.Where(t => t.Station == location)
.FirstOrDefault();
if (DateTime.Now.AddSeconds(diff) >= loadedState!.LoadingTime)
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// 防错机制【用于避免请求延迟的重复下发】--- 检测上一条【空托】任务放货时间(完成时间)与当前时间是否相差x秒以上
/// </summary>
/// <param name="location">站点</param>
/// <returns> true-相差大于x秒 false-相差小于x秒</returns>
public static bool CheckSendTaskTimeInterval(int location, int num)
{
int diff = -num;
using var context = new AppDbContext();
var loadedState = context
.Set<LoadedState>()
.Where(t => t.Station == location)
.FirstOrDefault();
if (DateTime.Now.AddSeconds(diff) >= loadedState!.PuttingTime)
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// 防错机制【重复下发】--- 检测是否有已经生成但未取货的实垛任务
/// </summary>
/// <param name="sourceLocation">源站点</param>
/// <returns> true-同目标站点生成任务时间间隔合法 false-时间间隔过短</returns>
public static bool CheckSendTaskIsRepeat(int location, int type)
{
using var context = new AppDbContext();
//实垛
if (type == TaskType.Goods)
{
//生成的上一条【实垛】任务且同一个源站点 ---> 查找符合条件的记录
var count = context
.Set<TaskRT>()
.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 == 0)
{
return true;
}
}
//空托
if (type == TaskType.Pallet)
{
//生成的上一条【空托】任务且同一个目标站点 ---> 查找符合条件的记录
var count1 = context
.Set<TaskRT>()
.Where(t => t.TargetLocation == location.ToString())
.Count();
if (count1 == 0)
{
return true;
}
}
return false;
}
static int sum;
/// <summary>
/// 计算某个输送口请求的值的和---用于确定该输送口在一定时间内请求是否已经复位
/// 用于避免信号可能的不稳定(跳变)的情况
/// </summary>
/// <param name="Location">源站点/目标站点---表示对应列</param>
/// <param name="count">计算的时间间隔(单位:秒)</param>
/// <returns>true-无请求---已复位 false-请求存在-未复位</returns>
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;
}
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;
}
}
/// <summary>
/// 手动禁止某条输送线下发任务(根据名称)
/// </summary>
/// <param name="name">输送线名称</param>
/// <returns>0-禁止 1-允许</returns>
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;
}
/// <summary>
/// 手动禁止某条输送线下发任务(根据目标站)
/// </summary>
/// <param name="source">源站点</param>
/// <returns>0-禁止 1-允许</returns>
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;
}
/// <summary>
/// 遍历环穿是否有某条输送线正在执行的(栈板)任务---即只要有该输送口的任务则不能生成新任务
/// 判断条件 1.站点 2.执行阶段 3.允许下发
/// (该方法会直接读取小车参数)
/// </summary>
/// <param name="sourceLocation">源站点(1至2位编号)</param>
/// <returns>false-存在执行中的任务的设备 true-无在执行任务的设备</returns>
public static bool GetRGVTaskForPalletsIsExist(int targetLocation)
{
List<CircleRGVState>? 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;
}
/// <summary>
/// 遍历环穿是否有某条输送线正在执行的(实垛)任务---某站点输送线存在【取货阶段】任务时不能生成新任务
/// 判断条件:
/// 1.站点匹配
/// 2.执行阶段--->取货阶段
/// 3.允许下发
/// (该方法会直接从地面站读取小车参数)
/// </summary>
/// <param name="sourceLocation">源站点(1至2位编号)</param>
/// <returns>false-存在执行任务的设备(不能下发) true-无执行中的任务的设备(可下发)</returns>
public static bool GetRGVTaskForGoodsIsExist(int sourceLocation)
{
List<CircleRGVState> 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)
.Count();
if (count > 0)
{
return false;
}
//无满足条件的小车则表示所有设备无此任务
return true;
}
/// <summary>
/// 检查是否存在已经生成的处于【取货阶段】的【栈板】任务 --- 源站点每次请求仅生成一条任务
/// </summary>
/// <returns>true-无符合条件的任务(即可生成新任务) false-存在符合条件的任务</returns>
public static bool IsPalletLineHasTask()
{
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;
}
}
}