using iWareCommon;
|
using iWareCommon.Utils;
|
using iWareSql;
|
using System;
|
using System.Collections.Generic;
|
using System.Threading;
|
|
using System.Linq;
|
using iWareSql.Orm;
|
using iWareCC.RgvService;
|
using System.Threading.Tasks;
|
using iWareSql.Entity.ParamModel;
|
using iWareCC.BLL;
|
using iWareSql.DataAccess;
|
|
using Newtonsoft.Json;
|
using iWareModel;
|
using iWareSql.DBModel;
|
using iWareCommon.Common.Globle;
|
using XiGang.Core.Model;
|
using iWareCC.Common.Helper;
|
using System.Runtime.Remoting.Contexts;
|
|
namespace iWareCC
|
{
|
/// <summary>
|
/// RGV任务服务线程类
|
/// </summary>
|
public class RgvTaskThreadService : DeviceThreadServiceHandle
|
{
|
|
private static string _namespace = "iWareCC.RgvThreadService";
|
|
private RgvTaskThreadService() { }
|
public RgvTaskThreadService(LogType logType)
|
{
|
base.currentLogType = logType;
|
}
|
public override void StartService()
|
{
|
Task.Run(() =>
|
{
|
try
|
{
|
//自动执行Rgv任务线程
|
Log4NetHelper.WriteInfoLog(base.currentLogType, "[自动执行Rgv任务线程] 启动了");
|
|
base.IssueTaskThread(EDevice.RGV);
|
base.ConfirmFinishTaskThread(EDevice.RGV);
|
|
ConfirmFinishTaskForCompensate(EDevice.RGV);//调用补偿线程
|
|
}
|
catch (Exception ex)
|
{
|
Log4NetHelper.WriteErrorLog(base.currentLogType, "RgvThreadService线程启动出现异常", ex);
|
}
|
});
|
}
|
|
#region 线程处理
|
|
#region 自动执行Rgv任务线程
|
|
/// <summary>
|
/// 自动执行Rgv任务
|
/// </summary>
|
/// <param name="srmName"></param>
|
public override void IssueTask(object deviceId)
|
{
|
var errMsg = "";
|
int i_deviceId = (int)deviceId;
|
while (true)
|
{
|
if (SystemValue.isAllowRuning_RgvThreadService && SystemValue.isStartedModel)
|
{
|
IssueTaskHandle(i_deviceId, out errMsg);
|
}
|
SystemWarningMsg._lbl_Alert_RgvRelease = errMsg;
|
Thread.Sleep(2000);//2秒一次
|
}
|
|
}
|
|
/// <summary>
|
/// 自动执行Rgv任务(线程)
|
/// </summary>
|
/// <param name="srmName"></param>
|
public override void IssueTaskHandle(int deviceId, out string errMsg)
|
{
|
errMsg = "";
|
string logHeader = "方法:DoRgvTaskByThead,参数deviceId:" + deviceId.ToString() + "===";
|
#region 新增异常信息表 【EditBy shaocx,2020-01-20】
|
IDictionary<string, object> logDict = new Dictionary<string, object>();
|
logDict.Add("deviceId", deviceId);
|
Base_SysExceptionInfo exception = SysExceptionInfoHandler.GetExceptionInfo<IDictionary<string, object>>(base.currentLogType, _namespace, "DoRgvTaskByThead", logDict);
|
#endregion
|
try
|
{
|
/*
|
* 执行发送给Rgv的指令任务
|
* 1、验证根据设备号是否找到Rgv
|
* 2、判断设备是否属于任务完成,如果属于任务完成,就继续走3
|
* 3、判断数据库中是否有可要下发的任务,如果有就下发+验证起始点和目标点是否正确
|
* 4、下发成功后,更新任务状态
|
*/
|
|
|
//2、判断设备是否属于空闲,如果属于空闲,就继续走2
|
bool isOk = ValidateDeviceIsAllowSendTask((int)EDevice.RGV, out errMsg);
|
if (!isOk)
|
{
|
errMsg = "不允许下发新任务," + errMsg;
|
return;
|
}
|
var newErrMsg = "";
|
using (DbModel dbModel = new DbModel())
|
{
|
var partList = GetPartListByDevice(dbModel, deviceId, TaskExcuteTypeEnum.执行任务);
|
if (partList != null && partList.Count > 0)
|
{
|
//首先处理模拟完成的任务
|
foreach (var item in partList)
|
{
|
if (item.IsAllowSimulateExecute == true)
|
{
|
Single_IssueTaskHandle(false, item, dbModel, deviceId, exception, false, out newErrMsg);
|
errMsg += newErrMsg + SysGloble.SPLIT_STR;
|
return;
|
}
|
}
|
//foreach (var currentTask in partList)
|
//{
|
// Single_IssueTaskHandle(currentTask, dbModel, deviceId, exception, out errMsg);
|
// Thread.Sleep(2000);//休眠2秒 【EditBy shaocx,2022-05-04】
|
//}
|
//*/
|
//分隔任务 RGV任务和输送线任务 [EditBy shaocx,2022-04-29]
|
var q_taskType_出库 = (int)DeviceTaskTypeEnum.出库;
|
var rgvOutTaskList_出库 = partList.Where(x => x.TaskType == q_taskType_出库).ToList();//rgv出库任务
|
|
var q_taskType_立库空托到拆盘机入口 = (int)DeviceTaskTypeEnum.立库空托到拆盘机入口;
|
var rgvOutTaskList_立库空托到拆盘机入口 = partList.Where(x => x.TaskType == q_taskType_立库空托到拆盘机入口).ToList();//rgv 立库空托到拆盘机入口任务
|
|
var q_taskType_组盘入库 = (int)DeviceTaskTypeEnum.组盘入库;
|
var q_taskType_空托转运到立体库 = (int)DeviceTaskTypeEnum.空托转运到立体库;
|
var rgvInTaskList = partList.Where(x => x.TaskType == q_taskType_组盘入库 || x.TaskType == q_taskType_空托转运到立体库).ToList();//rgv入库任务
|
|
|
var q_taskType_空托转运到拆盘机入口 = (int)DeviceTaskTypeEnum.空托转运到拆盘机入口;
|
var rgvTaskList_空托转运到拆盘机入口 = partList.Where(x => x.TaskType == q_taskType_空托转运到拆盘机入口).ToList();//rgv 空托转运到拆盘机入口 任务
|
|
//纯输送线任务
|
var q_taskType_拆盘机入口到拆盘机 = (int)DeviceTaskTypeEnum.拆盘机入口到拆盘机;
|
var q_taskType_空托缓存位转运 = (int)DeviceTaskTypeEnum.空托缓存位转运;
|
var lineTaskList = partList.Where(x => x.TaskType == q_taskType_拆盘机入口到拆盘机 || x.TaskType == q_taskType_空托缓存位转运).ToList();//纯输送线任务
|
|
|
/*
|
* 策略:
|
* 1、优先做发动机出库任务
|
* 2、如果发动机出库任务下发不成功,则做 立库空托到拆盘机入口 任务
|
* 3、其次做 组盘入库+空托转运到立体库任务,按顺序执行
|
* 4、其次做 空托转运到拆盘机入口 任务
|
* 5、其他纯输送线任务不受上述策略影响
|
*/
|
if (lineTaskList != null && lineTaskList.Count > 0)
|
{//纯输送线任务
|
foreach (var currentTask in lineTaskList)
|
{
|
Single_IssueTaskHandle(false, currentTask, dbModel, deviceId, exception, false, out newErrMsg);
|
errMsg += newErrMsg + SysGloble.SPLIT_STR;
|
}
|
}
|
|
if (rgvOutTaskList_出库 != null && rgvOutTaskList_出库.Count > 0)
|
{
|
//注意:出库任务下发就不要以CreateTime了,而是按照MainTaskSequence,因为在出库任务分解的时候,会出现那种 【EditBy shaocx,2022-05-19】
|
// 二号堆垛机、二号堆垛机、三号堆垛机出库情况,如果按照CreateTime,排序会变为 二号堆垛机、三号堆垛机、二号堆垛机
|
//var _partTask = rgvOutTaskList_出库.OrderBy(x => x.CreateTime).First();
|
var _partTask = rgvOutTaskList_出库.OrderBy(x => x.MainTaskSequence).ThenBy(x => x.CreateTime).First();
|
var validateLastSameToPlaceIsFinished = ValidateLastSameToPlaceIsFinished(dbModel, _partTask, true, ref newErrMsg);
|
//var vaidateIsMIN_OUTSTORE_RGV_TASK_JIANGE = VaidateIsMIN_OUTSTORE_RGV_TASK_JIANGE(dbModel, _partTask, ref newErrMsg);
|
if (validateLastSameToPlaceIsFinished == true)
|
{
|
//每次只下发第一个出库任务
|
Single_IssueTaskHandle(true, _partTask, dbModel, deviceId, exception, true, out newErrMsg);
|
errMsg += newErrMsg + SysGloble.SPLIT_STR;
|
if (string.IsNullOrEmpty(errMsg))
|
{//说明下发任务成功
|
return;//结束此次循环
|
}
|
}
|
else
|
{
|
errMsg += newErrMsg + SysGloble.SPLIT_STR;
|
}
|
}
|
//如果发动机出库任务下发不成功,则做 立库空托到拆盘机入口 任务
|
if (rgvOutTaskList_立库空托到拆盘机入口 != null && rgvOutTaskList_立库空托到拆盘机入口.Count > 0)
|
{
|
Single_IssueTaskHandle(true, rgvOutTaskList_立库空托到拆盘机入口.OrderBy(x => x.CreateTime).First(), dbModel, deviceId, exception, true, out newErrMsg);
|
errMsg += newErrMsg + SysGloble.SPLIT_STR;
|
if (string.IsNullOrEmpty(errMsg))
|
{//说明下发任务成功
|
return;//结束此次循环
|
}
|
}
|
//其次做 组盘入库+空托转运到立体库任务,按顺序执行
|
if (rgvInTaskList != null && rgvInTaskList.Count > 0)
|
{
|
var _partTask = rgvInTaskList.OrderBy(x => x.CreateTime).First();
|
var validateLastSameToPlaceIsFinished = ValidateLastSameToPlaceIsFinished(dbModel, _partTask, false, ref newErrMsg);
|
//var vaidateIsMIN_OUTSTORE_RGV_TASK_JIANGE = VaidateIsMIN_OUTSTORE_RGV_TASK_JIANGE22(dbModel, _partTask, ref newErrMsg);
|
if (validateLastSameToPlaceIsFinished == true)
|
{
|
//按顺序下发
|
Single_IssueTaskHandle(true, _partTask, dbModel, deviceId, exception, false, out newErrMsg);
|
errMsg += newErrMsg + SysGloble.SPLIT_STR;
|
if (string.IsNullOrEmpty(errMsg))
|
{//说明下发任务成功
|
return;//结束此次循环
|
}
|
}
|
else
|
{
|
errMsg += newErrMsg + SysGloble.SPLIT_STR;
|
}
|
}
|
//其次做 空托转运到拆盘机入口 任务
|
if (rgvTaskList_空托转运到拆盘机入口 != null && rgvTaskList_空托转运到拆盘机入口.Count > 0)
|
{
|
Single_IssueTaskHandle(true, rgvTaskList_空托转运到拆盘机入口.OrderBy(x => x.CreateTime).First(), dbModel, deviceId, exception, false, out newErrMsg);
|
errMsg += newErrMsg + SysGloble.SPLIT_STR;
|
if (string.IsNullOrEmpty(errMsg))
|
{//说明下发任务成功
|
return;//结束此次循环
|
}
|
}
|
//*/
|
/*
|
//分隔任务 RGV任务和输送线任务 [EditBy shaocx,2022-04-29]
|
var q_taskType1 = (int)DeviceTaskTypeEnum.拆盘机入口到拆盘机;
|
var q_taskType2 = (int)DeviceTaskTypeEnum.空托缓存位转运;
|
var lineTaskList = partList.Where(x => x.TaskType == q_taskType1 || x.TaskType == q_taskType2).ToList();//输送线任务
|
var rgvTaskList = partList.Where(x => x.TaskType != q_taskType1 && x.TaskType != q_taskType2).ToList();//rgv任务
|
|
if (rgvTaskList != null && rgvTaskList.Count > 0)
|
{
|
Single_IssueTaskHandle(true, rgvTaskList.First(), dbModel, deviceId, exception, out errMsg);
|
Thread.Sleep(2000);//休眠2秒 【EditBy shaocx,2022-05-04】
|
}
|
|
if (lineTaskList != null && lineTaskList.Count > 0)
|
{
|
foreach (var currentTask in lineTaskList)
|
{
|
Single_IssueTaskHandle(false, currentTask, dbModel, deviceId, exception, out errMsg);
|
}
|
}
|
//*/
|
}
|
else
|
{
|
errMsg = "没有任务要发送给Rgv";
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
errMsg = "出现异常:" + ex.Message;
|
SysExceptionInfoHandler.GetExceptionInfoForError("自动执行Rgv任务(线程)出现异常,deviceId:" + deviceId + ",异常:" + ex.Message, ex, ref exception);
|
SysExceptionInfoHandler.InsertExceptionInfo(exception, true);
|
}
|
}
|
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="isRgvTask"></param>
|
/// <param name="currentTask"></param>
|
/// <param name="dbModel"></param>
|
/// <param name="deviceId"></param>
|
/// <param name="exception"></param>
|
/// <param name="isOutStoreTask">是否是出库任务</param>
|
/// <param name="errMsg"></param>
|
private void Single_IssueTaskHandle(bool isRgvTask, Task_Part currentTask, DbModel dbModel, int deviceId, Base_SysExceptionInfo exception,
|
bool isOutStoreTask,
|
out string errMsg)
|
{
|
errMsg = "";
|
|
if (MyExtendHelper.IsAllowSimulatorHandle(currentTask))
|
{//如果是模拟完成
|
|
}
|
else
|
{//非模拟完成
|
#region //3、判断数据库中是否有可要下发的任务,如果有就下发
|
//验证起始点和目标点是否正确
|
RealPlaceEntity realPlaceEntity = null;
|
if (!ValdiatePalceIsRight(dbModel, (int)currentTask.SourcePlace, (int)currentTask.ToPlace, ref realPlaceEntity))
|
{
|
errMsg = "验证起始点和目标点是否正确失败";
|
PartTaskHandler.WriteOperationRemarkForPartTask(currentTask.Id, errMsg);
|
return;
|
}
|
|
//验证是否可以下发任务
|
var isOk = ValidateDeviceIsAllowSendTask(isRgvTask, (int)EDevice.RGV, currentTask, out errMsg);
|
if (!isOk)
|
{
|
errMsg = "不允许下发新任务," + errMsg;
|
PartTaskHandler.WriteOperationRemarkForPartTask(currentTask.Id, errMsg);
|
return;
|
}
|
//要判断起点是否有库存,如果起点没有库存,则报错 【EditBy shaocx,2022-05-15】
|
var sourcePlaceStore = dbModel.V_AllStore.Where(x => x.StationId == currentTask.SourcePlace).FirstOrDefault();
|
if (sourcePlaceStore == null)
|
{
|
errMsg = "不允许下发新任务," + string.Format("起点{0},{1}没有找到库存信息,无法下发RGV任务!", currentTask.SourcePlace.ToString(), currentTask.RealSourcePlace);
|
PartTaskHandler.WriteOperationRemarkForPartTask(currentTask.Id, errMsg);
|
return;
|
}
|
//验证目标点是否已经有库存 【EditBy shaocx,2022-04-15】
|
isOk = ValidateIsHasStoreForToPlace((int)EDevice.RGV, currentTask.ToPlace, currentTask.RealToPlace, out errMsg);
|
if (!isOk)
|
{
|
errMsg = "不允许下发新任务," + errMsg;
|
PartTaskHandler.WriteOperationRemarkForPartTask(currentTask.Id, errMsg);
|
return;
|
}
|
|
//if (isRgvTask)
|
if (currentTask.TaskType == (int)DeviceTaskTypeEnum.出库) //修改为只对出库任务的判断,因为我发现有次出现过,下发了去1012的任务,但当时1012竟然有货,导致rgv不执行任务,然后导致rgv不执行其他入库任务的情况 【EditBy shaocx,2022-05-21】
|
{
|
isOk = ValidateIsExistNoFinished(dbModel, currentTask, ref errMsg);
|
if (!isOk)
|
{
|
errMsg = "不允许下发新任务," + errMsg;
|
PartTaskHandler.WriteOperationRemarkForPartTask(currentTask.Id, errMsg);
|
return;
|
}
|
}
|
|
//增加验证 【EditBy shaocx,2022-05-07】
|
var vaidateIsExistNoIssuedTaskBeforeCurrTaskTo1012 = VaidateIsExistNoIssuedTaskBeforeCurrTaskTo1012(dbModel, currentTask, ref errMsg);
|
if (vaidateIsExistNoIssuedTaskBeforeCurrTaskTo1012)
|
{
|
PartTaskHandler.WriteOperationRemarkForPartTask(currentTask.Id, errMsg);
|
return;
|
}
|
var vaidateIsExistNoIssuedTaskBeforeCurrTaskToSameInStoreStation = VaidateIsExistNoIssuedTaskBeforeCurrTaskToSameInStoreStation(dbModel, currentTask, ref errMsg);
|
if (vaidateIsExistNoIssuedTaskBeforeCurrTaskToSameInStoreStation)
|
{
|
PartTaskHandler.WriteOperationRemarkForPartTask(currentTask.Id, errMsg);
|
return;
|
}
|
|
//验证起点光电是否有货存在 【EditBy shaocx,2022-05-11】
|
var isGD_HasCatogryForRgvStattion = MyExtendHelper.IsGD_HasCatogryForRgvStattion(currentTask.RealSourcePlace);
|
if (isGD_HasCatogryForRgvStattion == false)
|
{
|
errMsg = "不允许下发新任务,起点位置" + currentTask.RealSourcePlace + "有光电显示无货存在";
|
PartTaskHandler.WriteOperationRemarkForPartTask(currentTask.Id, errMsg);
|
return;
|
}
|
|
|
//如果目标位置有光电显示有货存在,则不允许下发任务,是为了防止1014到1020的任务的,如果1020上有货,就不发任务 【EditBy shaocx,2022-04-30】
|
//全部任务都要验证目标点是否有货 【EditBy shaocx,2022-05-08】
|
isGD_HasCatogryForRgvStattion = MyExtendHelper.IsGD_HasCatogryForRgvStattion(currentTask.RealToPlace);
|
if (isGD_HasCatogryForRgvStattion)
|
{
|
errMsg = "不允许下发新任务,目标位置" + currentTask.RealToPlace + "有光电显示有货存在";
|
PartTaskHandler.WriteOperationRemarkForPartTask(currentTask.Id, errMsg);
|
return;
|
}
|
|
|
if (isOutStoreTask)
|
{//如果是出库任务,则需要检测立体库出库口上面有货才可以下发任务 [EditBy shaocx,2022-05-11]
|
//休眠1秒
|
Thread.Sleep(3000);//增加休眠3秒的判断
|
var isGD_HasCatogryForSoruceRgvStattion = MyExtendHelper.IsGD_HasCatogryForRgvStattion(currentTask.RealSourcePlace);
|
if (!isGD_HasCatogryForSoruceRgvStattion)
|
{
|
errMsg = "不允许下发新任务,起始位置" + currentTask.RealSourcePlace + "有光电显示没有货存在!!";
|
PartTaskHandler.WriteOperationRemarkForPartTask(currentTask.Id, errMsg);
|
return;
|
}
|
//再次判断出库任务,目标位置是否有发动机
|
//因为我发现有次出现过,下发了去1012的任务,但当时1012竟然有货,导致rgv不执行任务,然后导致rgv不执行其他入库任务的情况 【EditBy shaocx,2022-07-24】
|
isGD_HasCatogryForRgvStattion = MyExtendHelper.IsGD_HasCatogryForRgvStattion(currentTask.RealToPlace);
|
if (isGD_HasCatogryForRgvStattion)
|
{
|
errMsg = "不允许下发新任务,目标位置" + currentTask.RealToPlace + "有光电显示有货存在";
|
PartTaskHandler.WriteOperationRemarkForPartTask(currentTask.Id, errMsg);
|
return;
|
}
|
}
|
|
|
//验证是否存在 同一个起点,同一个目标点,并且是 未完成的的任务
|
isOk = ValidateIsHasNoFinishedSameTask((int)EDevice.RGV, currentTask, out errMsg);
|
if (!isOk)
|
{
|
errMsg = "不允许下发新任务," + errMsg;
|
PartTaskHandler.WriteOperationRemarkForPartTask(currentTask.Id, errMsg);
|
return;
|
}
|
//同一个关联任务的其他设备任务
|
//判断和堆垛机的连接任务是不是已经完成了
|
var queryTaskState1 = (int)DeviceTaskStatusEnum.未开始;
|
var queryTaskState2 = (int)DeviceTaskStatusEnum.已下发;
|
var relevanceTask = dbModel.Task_Part.Where(x => x.MainTaskId == currentTask.MainTaskId && x.TaskSequence < currentTask.TaskSequence && (x.TaskState == queryTaskState1 || x.TaskState == queryTaskState2)).FirstOrDefault();
|
if (relevanceTask != null)
|
{
|
errMsg = string.Format("关联{0}任务未完成,所以RGV任务不允许下发!关联任务号:{1}", relevanceTask.DeviceName, relevanceTask.PlcTaskId);
|
PartTaskHandler.WriteOperationRemarkForPartTask(currentTask.Id, errMsg);
|
return;
|
}
|
|
#region 增加验证 【EditBy shaocx,2022-05-15】
|
//来源位置的库位状态
|
var sourcePlace = dbModel.Base_Station.Where(o => o.Id == currentTask.SourcePlace).FirstOrDefault();
|
if (sourcePlace == null)
|
{
|
throw new Exception(string.Format("根据库位号{0}没有找到库位信息!", currentTask.SourcePlace.ToString()));
|
}
|
var toPlace = dbModel.Base_Station.Where(o => o.Id == currentTask.ToPlace).FirstOrDefault();
|
if (toPlace == null)
|
{
|
throw new Exception(string.Format("根据库位号{0}没有找到库位信息!", currentTask.ToPlace.ToString()));
|
}
|
|
DeviceTaskTypeEnum _DeviceTaskTypeEnum;
|
if (EnumberHelper.GetEnumObject<DeviceTaskTypeEnum>(currentTask.TaskType.ToString(), out _DeviceTaskTypeEnum) == false)
|
{
|
throw new Exception("枚举值不正确!");
|
}
|
|
#endregion
|
|
|
//下发
|
SdaResEntity sdaResult = new SdaResEntity();
|
var log = TaskRequestLogHandler.GetTask(currentTask.Id,
|
(int)currentTask.DeviceId, currentTask.PlcTaskId, currentTask.RealSourcePlace.ToString(),
|
currentTask.RealToPlace.ToString(), "给RGV发送任务指令", "sys");
|
try
|
{
|
if (MyExtendHelper.IsAllowSimulatorHandle(currentTask))
|
{
|
sdaResult.result = true;
|
}
|
else
|
{
|
sdaResult = new RgvService.RgvServiceClient().SendRgvTask(deviceId, Convert.ToInt32(currentTask.PlcTaskId), Convert.ToString(currentTask.RealSourcePlace), Convert.ToString(currentTask.RealToPlace));
|
}
|
if (sdaResult.result == false)
|
{//给Rgv下发指令失败
|
errMsg = sdaResult.resMsg;
|
exception.exceptionMsg = string.Format("发送指令给Rgv失败,设备号{0},任务ID{1},起始位{2},目标位{3},errMsg{4}", deviceId, currentTask.Id, currentTask.SourcePlace.ToString(), currentTask.ToPlace.ToString(), errMsg);
|
SysExceptionInfoHandler.InsertExceptionInfo(exception, true);
|
TaskRequestLogHandler.InsertTask(base.currentLogType, RequestStatusEnum.请求失败, JsonConvert.SerializeObject(sdaResult).ToString(), log, null);
|
return;
|
}
|
else
|
{
|
TaskRequestLogHandler.InsertTask(base.currentLogType, RequestStatusEnum.请求成功, JsonConvert.SerializeObject(sdaResult).ToString(), log, null);
|
}
|
}
|
catch (Exception ex)
|
{
|
errMsg = "出现异常:" + ex.Message;
|
SysExceptionInfoHandler.GetExceptionInfoForError("给RGV发送任务指令出现异常,deviceId:" + deviceId + ",异常:" + ex.Message, ex, ref exception);
|
SysExceptionInfoHandler.InsertExceptionInfo(exception, true);
|
TaskRequestLogHandler.InsertTask(base.currentLogType, RequestStatusEnum.请求失败, JsonConvert.SerializeObject(sdaResult).ToString(), log, ex);
|
return;
|
}
|
|
#endregion
|
}
|
|
TranferStoreForRgv(currentTask, deviceId, dbModel, "RGV任务下发后", out errMsg);
|
if (!string.IsNullOrEmpty(errMsg))
|
{
|
PartTaskHandler.WriteOperationRemarkForPartTask(currentTask.Id, errMsg);
|
return;
|
}
|
|
//4、下发成功后,更新任务状态
|
currentTask.IsReleased = true;
|
currentTask.ModifyBy = SysGloble.WCSSystem;
|
currentTask.ModifyTime = DateTime.Now;
|
var changeState = DeviceTaskStatusEnum.已下发;
|
currentTask.TaskState = (int)changeState;
|
currentTask.TaskStateName = changeState.ToString();
|
currentTask.OperationRemark = "任务已下发给设备";
|
currentTask.IssueTime = DateTime.Now;//下发时间
|
//修改Task_Main的状态
|
UpdateMainTaskStatus(dbModel, currentTask.MainTaskId, currentTask.TaskType, "下发任务给RGV");
|
|
|
//推送MES
|
var mainTask = MainTaskHandler.GetMainTaskById(dbModel, currentTask.MainTaskId);
|
MesService.UpdateIsNeedOnLineForMainTask(mainTask);
|
|
int i = dbModel.SaveChanges();
|
if (i <= 0)
|
{
|
errMsg = "更新数据库失败,更新条数:" + i;
|
}
|
else
|
{
|
|
}
|
}
|
|
#endregion
|
|
#region 自动结束Rgv任务线程
|
|
/// <summary>
|
/// 自动结束Rgv任务线程
|
/// </summary>
|
/// <param name="srmName"></param>
|
public override void ConfirmFinishTask(object deviceId)
|
{
|
string errMsg = "";
|
int i_deviceId = (int)deviceId;
|
while (true)
|
{
|
if (SystemValue.isAllowRuning_RgvThreadService_Finish && SystemValue.isStartedModel)
|
{
|
ConfirmFinishTaskHandle(i_deviceId, out errMsg);
|
}
|
SystemWarningMsg._lbl_Alert_DataProcess_RobotBuffer_ModeChange = errMsg;
|
Thread.Sleep(2000);
|
}
|
|
}
|
|
/// <summary>
|
/// 自动结束Rgv任务线程(线程)
|
/// </summary>
|
/// <param name="srmName"></param>
|
public override void ConfirmFinishTaskHandle(int deviceId, out string errMsg)
|
{
|
errMsg = "";
|
var remark = "自动结束Rgv任务线程(线程)";
|
#region 新增异常信息表 【EditBy shaocx,2020-01-20】
|
IDictionary<string, object> logDict = new Dictionary<string, object>();
|
logDict.Add("deviceId", deviceId);
|
Base_SysExceptionInfo exception = SysExceptionInfoHandler.GetExceptionInfo<IDictionary<string, object>>(base.currentLogType, _namespace, "FinishRgvTaskByThead", logDict);
|
#endregion
|
try
|
{
|
/*
|
* 执行发送给Rgv的指令任务
|
* 1、验证根据设备号是否找到Rgv
|
* 2、判断设备是否属于任务完成,如果属于任务完成,就继续走3
|
* 3、判断数据库中是否有可要完成的任务,如果有判断是否跟Rgv中的完成任务相符,如果相符就处理
|
* 4、更新任务状态
|
*/
|
|
int int_deviceId = (int)deviceId;
|
|
|
//*/
|
using (DbModel dbModel = new DbModel())
|
{
|
var partList = GetPartListByDevice(dbModel, deviceId, TaskExcuteTypeEnum.结束任务);
|
if (partList != null && partList.Count > 0)
|
{
|
foreach (var currentTask in partList)
|
{
|
SingleConfirmFinishTaskHandle(currentTask, int_deviceId, dbModel, remark, out errMsg);
|
}
|
}
|
else
|
{
|
errMsg = "没有RGV任务要处理";
|
return;
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
errMsg = "出现异常:" + ex.Message;
|
SysExceptionInfoHandler.GetExceptionInfoForError("自动结束Rgv任务线程(线程)出现异常,deviceId:" + deviceId + ",异常:" + ex.Message, ex, ref exception);
|
SysExceptionInfoHandler.InsertExceptionInfo(exception, true);
|
}
|
}
|
|
|
private void SingleConfirmFinishTaskHandle(Task_Part currentTask, int int_deviceId, DbModel dbModel, string remark, out string errMsg)
|
{
|
#region //3、判断数据库中是否有可要完成的任务,如果有判断是否跟Rgv中的完成任务相符,如果相符就处理
|
|
DeviceTaskTypeEnum rgvTaskTypeEnum = (DeviceTaskTypeEnum)Enum.Parse(typeof(DeviceTaskTypeEnum), currentTask.TaskType.ToString());
|
|
//同一个关联任务的其他设备任务
|
//判断和堆垛机的连接任务是不是已经完成了
|
var queryTaskState1 = (int)DeviceTaskStatusEnum.未开始;
|
var queryTaskState2 = (int)DeviceTaskStatusEnum.已下发;
|
var relevanceTask = dbModel.Task_Part.Where(x => x.MainTaskId == currentTask.MainTaskId && x.TaskSequence < currentTask.TaskSequence && (x.TaskState == queryTaskState1 || x.TaskState == queryTaskState2)).FirstOrDefault();
|
if (relevanceTask != null)
|
{
|
errMsg = string.Format("关联{0}任务未完成,所以RGV任务不允许完成!关联任务号:{1}", relevanceTask.DeviceName, relevanceTask.PlcTaskId);
|
return;
|
}
|
|
#endregion
|
|
//注意:这里不需要判断设备是否完成,直接就结束任务
|
//2、判断设备是否属于任务完成,如果属于任务完成,就继续走2
|
var isTaskFinished = ValidateDeviceTaskIsFinsished(int_deviceId, currentTask, Convert.ToInt32(currentTask.PlcTaskId), currentTask.IsAllowSimulateExecute, out errMsg);
|
if (!isTaskFinished) return;
|
|
//4、更新任务状态
|
currentTask.FinishTime = DateTime.Now;//完成时间
|
currentTask.IsFinished = true;
|
currentTask.TaskState = (int)DeviceTaskStatusEnum.已完成;
|
currentTask.TaskStateName = DeviceTaskStatusEnum.已完成.ToString();
|
currentTask.OperationRemark = "已完成";
|
currentTask.ModifyBy = SysGloble.WCSSystem;
|
currentTask.ModifyTime = DateTime.Now;
|
|
|
using (var trans = dbModel.Database.BeginTransaction())
|
{
|
try
|
{
|
//推送MES
|
var mainTask = MainTaskHandler.GetMainTaskById(dbModel, currentTask.MainTaskId);
|
MesService.UpdateIsNeedOnLineForMainTask(mainTask);
|
|
//注意:一定是先要保存数据库,才再跟plc交互!!!!!
|
var i = dbModel.SaveChanges();
|
if (i <= 0)
|
{
|
throw new Exception("修改条数为0");
|
}
|
|
var isRgvTask = IsRgvTask(currentTask);
|
if (isRgvTask)
|
{//如果是RGV任务,则需要去给RGV任务确认
|
SdaResEntity confirmTaskFinish = null;
|
var log = TaskRequestLogHandler.GetTask(currentTask.Id,
|
(int)currentTask.DeviceId, currentTask.PlcTaskId, currentTask.RealSourcePlace.ToString(),
|
currentTask.RealToPlace.ToString(), "给RGV发送任务完成确认指令", "sys");
|
try
|
{
|
//任务完成处理成功,需要再给RGV发送任务完成确认信号
|
if (MyExtendHelper.IsAllowSimulatorHandle(currentTask))
|
{
|
confirmTaskFinish = new SdaResEntity()
|
{
|
result = true
|
};
|
}
|
else
|
{
|
confirmTaskFinish = new RgvService.RgvServiceClient().WriteRGV_FinishACK((int)EDevice.RGV, true, Convert.ToInt32(currentTask.PlcTaskId));
|
}
|
if (!confirmTaskFinish.result)
|
{
|
TaskRequestLogHandler.InsertTask(base.currentLogType, RequestStatusEnum.请求失败, JsonConvert.SerializeObject(confirmTaskFinish), log, null);
|
trans.Rollback();
|
return;
|
}
|
else
|
{
|
TaskRequestLogHandler.InsertTask(base.currentLogType, RequestStatusEnum.请求成功, JsonConvert.SerializeObject(confirmTaskFinish), log, null);
|
|
WriteRGV_XigangGetDataForOutAsync(int_deviceId, currentTask, mainTask);
|
}
|
}
|
catch (Exception ex)
|
{
|
errMsg = "出现异常:" + ex.Message;
|
Log4NetHelper.WriteErrorLog(LogType.StationThreadService, errMsg, ex);
|
TaskRequestLogHandler.InsertTask(base.currentLogType, RequestStatusEnum.请求失败, JsonConvert.SerializeObject(confirmTaskFinish), log, ex);
|
trans.Rollback();
|
return;
|
}
|
|
//*/
|
}
|
|
|
|
trans.Commit();
|
|
|
}
|
catch (Exception)
|
{
|
trans.Rollback();
|
throw;
|
}
|
}
|
}
|
|
|
#endregion
|
|
#region RGV任务完成确认补偿线程 【Editby shaocx,2023-05-04】
|
|
/// <summary>
|
/// RGV任务完成确认补偿线程
|
/// </summary>
|
/// <param name="srmName"></param>
|
private void ConfirmFinishTaskForCompensate(object deviceId)
|
{
|
string errMsg = "";
|
int i_deviceId = (int)deviceId;
|
while (true)
|
{
|
if (SystemValue.isAllowRuning_RgvThreadService_Finish_BuChang && SystemValue.isStartedModel)
|
{
|
SingleConfirmFinishTaskHandleForCompensate(i_deviceId, out errMsg);
|
}
|
SystemWarningMsg._lbl_Alert_RgvReleaseFinish_BuChang = errMsg;
|
Thread.Sleep(2000);
|
}
|
|
}
|
|
private void SingleConfirmFinishTaskHandleForCompensate(int int_deviceId, out string errMsg)
|
{
|
errMsg = "";
|
try
|
{
|
if (WCSConfigHelper.GetConfig_IsSimulationPLC())
|
{
|
errMsg = "PLC模拟模式!!!";
|
return;
|
}
|
|
var isRgvFinish = FormCC.rgvView.R_RGV_Finish;
|
var stationCode = ((int)EDevice.RGV1040).ToString();
|
var readData = FormCC.rgvView.R_RgvForReadCommList.Where(x => x.StationCode == stationCode).FirstOrDefault();
|
int rgvTaskId = readData.R_TaskID;
|
bool rgvFinishAck = FormCC.rgvView.W_RGV_FinishACK;
|
|
errMsg = $"RGV任务完成确认补偿线程信息,获取信息:rgvTaskId:{rgvTaskId},isRgvFinish:{isRgvFinish},rgvFinishAck:{rgvFinishAck}";
|
Log4NetHelper.WriteInfoLog(LogType.StationThreadService, errMsg);
|
|
//如果ack为false,finish为true,并且 wms的该任务为 已完成,则表示需要补偿
|
Task_Part currentTask = null;
|
if (rgvTaskId > 0 && rgvFinishAck == false && isRgvFinish == true)
|
{
|
errMsg = $"RGV任务完成确认补偿线程信息,初步符合条件:rgvTaskId:{rgvTaskId},isRgvFinish:{isRgvFinish},rgvFinishAck:{rgvFinishAck}";
|
Log4NetHelper.WriteInfoLog(LogType.StationThreadService, errMsg);
|
|
using (DbModel dbModel = new DbModel())
|
{
|
var str_rgvTaskId = rgvTaskId.ToString();
|
var queryDeviceId = (int)EDevice.RGV;
|
currentTask = dbModel.Task_Part.Where(x => x.PlcTaskId == str_rgvTaskId
|
&& x.DeviceId == queryDeviceId
|
).OrderByDescending(x => x.CreateTime).FirstOrDefault();
|
if (currentTask != null)
|
{
|
var isRgvTask = IsRgvTask(currentTask);
|
if (isRgvTask && currentTask.TaskState == (int)DeviceTaskStatusEnum.已完成)
|
{
|
var finsiTime = Convert.ToDateTime(currentTask.FinishTime);
|
var nowTime = DateTime.Now;
|
TimeSpan ts = DateTime.Now - finsiTime;
|
if (ts.Seconds > 10)
|
{//只有 已完成任务时间超出当前3秒后,才能处理!
|
errMsg = $"RGV任务完成确认补偿线程信息,准备处理:rgvTaskId:{rgvTaskId},isRgvFinish:{isRgvFinish},rgvFinishAck:{rgvFinishAck}";
|
Log4NetHelper.WriteInfoLog(LogType.StationThreadService, errMsg);
|
|
var confirmTaskFinish = new RgvService.RgvServiceClient().WriteRGV_FinishACK((int)EDevice.RGV, true, Convert.ToInt32(currentTask.PlcTaskId));
|
if (!confirmTaskFinish.result)
|
{
|
errMsg = $"RGV任务完成确认补偿线程失败:rgvTaskId:{rgvTaskId},SDA返回:" + confirmTaskFinish.resMsg;
|
Log4NetHelper.WriteErrorLog(LogType.StationThreadService, errMsg, null);
|
return;
|
}
|
else
|
{
|
errMsg = $"RGV任务完成确认补偿线程成功{rgvTaskId}:rgvTaskId:{rgvTaskId}";
|
Log4NetHelper.WriteInfoLog(LogType.StationThreadService, errMsg);
|
}
|
}
|
else
|
{
|
errMsg = $"RGV任务完成确认补偿线程信息,未超过3秒,不处理:rgvTaskId:{rgvTaskId},isRgvFinish:{isRgvFinish},rgvFinishAck:{rgvFinishAck}";
|
Log4NetHelper.WriteInfoLog(LogType.StationThreadService, errMsg);
|
return;
|
}
|
}
|
else
|
{
|
errMsg = "任务不符合补偿条件";
|
return;
|
}
|
}
|
else
|
{
|
errMsg = "任务为NULL,不符合补偿条件";
|
return;
|
}
|
}
|
}
|
else
|
{
|
errMsg = "不符合补偿条件";
|
return;
|
}
|
}
|
catch (Exception ex)
|
{
|
errMsg = "RGV任务完成确认补偿线程-出现异常:" + ex.Message;
|
Log4NetHelper.WriteErrorLog(LogType.StationThreadService, errMsg, ex);
|
return;
|
}
|
}
|
|
#endregion
|
|
#endregion
|
|
#region 库存处理
|
|
/// <summary>
|
/// 库存转移
|
/// </summary>
|
/// <param name="currentTask"></param>
|
/// <param name="int_deviceId"></param>
|
/// <param name="dbModel"></param>
|
/// <param name="remark"></param>
|
/// <param name="errMsg"></param>
|
private void TranferStoreForRgv(Task_Part currentTask, int int_deviceId, DbModel dbModel, string remark, out string errMsg)
|
{
|
|
//来源位置的库位状态
|
var sourcePlace = dbModel.Base_Station.Where(o => o.Id == currentTask.SourcePlace).FirstOrDefault();
|
if (sourcePlace == null)
|
{
|
throw new Exception(string.Format("根据库位号{0}没有找到库位信息!", currentTask.SourcePlace.ToString()));
|
}
|
var toPlace = dbModel.Base_Station.Where(o => o.Id == currentTask.ToPlace).FirstOrDefault();
|
if (toPlace == null)
|
{
|
throw new Exception(string.Format("根据库位号{0}没有找到库位信息!", currentTask.ToPlace.ToString()));
|
}
|
|
//验证目标点是否已经有库存 【EditBy shaocx,2022-04-15】
|
var isOk = ValidateIsHasStoreForToPlace((int)EDevice.RGV, currentTask.ToPlace, currentTask.RealToPlace, out errMsg);
|
if (!isOk)
|
{
|
errMsg = "不允许下发新任务," + errMsg;
|
return;
|
}
|
|
#region 3、变更库位状态(任务占用、锁定)
|
|
UpdateStationLockInfoWhenFinished(dbModel, sourcePlace, toPlace, currentTask.Id, "RGV任务完成,出库任务处理");
|
|
#endregion
|
|
toPlace.IsFull = true;
|
|
|
sourcePlace.IsFull = false;
|
|
DeviceTaskTypeEnum _DeviceTaskTypeEnum;
|
if (EnumberHelper.GetEnumObject<DeviceTaskTypeEnum>(currentTask.TaskType.ToString(), out _DeviceTaskTypeEnum) == false)
|
{
|
throw new Exception("枚举值不正确!");
|
}
|
//修改来源和目标的CVP关系,更新库存
|
UpdateStore(dbModel, sourcePlace, toPlace, _DeviceTaskTypeEnum, currentTask);
|
|
|
//5、如果是出库任务,则需要更新计划出库明细表和计划出库主表的信息
|
if (currentTask.TaskType == (int)DeviceTaskTypeEnum.出库)
|
{
|
//获取主表任务
|
var mainTask = MainTaskHandler.GetMainTaskById(dbModel, currentTask.MainTaskId);
|
PlanOutTaskHandler.UpdatePlanStateToFinished(dbModel, mainTask, remark);
|
}
|
}
|
|
#endregion
|
|
#region 公共处理
|
|
/// <summary>
|
/// 发动机出库,给西港PLC发送发动机数据 【Editby shaocx,2023-07-23】
|
/// </summary>
|
/// <param name="int_deviceId"></param>
|
/// <param name="currentTask"></param>
|
/// <param name="mainTask"></param>
|
private async void WriteRGV_XigangGetDataForOutAsync(int int_deviceId, Task_Part currentTask, Task_Main mainTask)
|
{
|
if (currentTask.TaskType != (int)DeviceTaskTypeEnum.出库)
|
{
|
return;
|
}
|
string errMsg = "";
|
try
|
{
|
iWareCC.RgvService.SdaResEntity sdaResult = new iWareCC.RgvService.SdaResEntity();
|
if (MyExtendHelper.IsAllowSimulatorHandle(currentTask))
|
{
|
sdaResult.result = true;
|
}
|
else
|
{
|
var sendOrderNo = mainTask.OrderNo.Replace("B-", "");//说是 需要去掉B-
|
sdaResult = await new RgvService.RgvServiceClient().WriteRGV_XigangGetDataForOutAsync(int_deviceId, mainTask.MaterialModel,
|
mainTask.SerialNumber,
|
sendOrderNo,
|
Convert.ToInt32(currentTask.PlcTaskId));
|
}
|
if (sdaResult.result == false)
|
{//给Rgv下发指令失败
|
errMsg = sdaResult.resMsg;
|
Log4NetHelper.WriteErrorLog(LogType.StationThreadService, errMsg, null);
|
return;
|
}
|
else
|
{
|
Log4NetHelper.WriteInfoLog(LogType.StationThreadService, "发动机出库,给西港PLC发送发动机数据,主任务号:" + mainTask.Id);
|
}
|
}
|
catch (Exception ex)
|
{
|
errMsg = "出现异常:" + ex.Message;
|
Log4NetHelper.WriteErrorLog(LogType.StationThreadService, errMsg, ex);
|
return;
|
}
|
}
|
|
/// <summary>
|
/// 是否是RGV任务
|
/// </summary>
|
/// <param name="_task"></param>
|
/// <returns></returns>
|
private bool IsRgvTask(Task_Part _task)
|
{
|
var isRgvTask = true;
|
if (_task.TaskType == (int)DeviceTaskTypeEnum.拆盘机入口到拆盘机 || _task.TaskType == (int)DeviceTaskTypeEnum.空托缓存位转运)
|
{
|
isRgvTask = false;
|
}
|
return isRgvTask;
|
}
|
|
/// <summary>
|
/// 判断相同目的地的RGV任务,上一个是否完成了
|
/// </summary>
|
/// <param name="dbModel"></param>
|
/// <param name="currentTask"></param>
|
/// <param name="errMsg"></param>
|
/// <returns></returns>
|
public bool ValidateLastSameToPlaceIsFinished(DbModel dbModel, Task_Part currentTask, bool isOutStoreForFDJ, ref string errMsg)
|
{
|
////判断和堆垛机(或RGV)的连接任务是不是已经完成了
|
var queryTaskState1 = (int)DeviceTaskStatusEnum.未开始;
|
var queryTaskState2 = (int)DeviceTaskStatusEnum.已下发;
|
var queryDeviceId = (int)EDevice.RGV;
|
//同一个RGV的,并且是同种类型的(即相同目的地的)
|
Task_Part otherSrmTask = null;
|
if (isOutStoreForFDJ)
|
{//是发动机出库
|
otherSrmTask = dbModel.Task_Part.Where(x => x.DeviceId == queryDeviceId
|
&& x.Id != currentTask.Id
|
&& (x.TaskState == queryTaskState1 || x.TaskState == queryTaskState2)
|
&& x.MainTaskSequence <= currentTask.MainTaskSequence
|
&& x.CreateTime < currentTask.CreateTime //增加这个条件,防止出现顺序号相同的出库任务问题 【EditBy shaocx,2022-10-27】
|
&& x.RealToPlace == currentTask.RealToPlace
|
).FirstOrDefault();
|
}
|
else
|
{//非发动机出库
|
otherSrmTask = dbModel.Task_Part.Where(x => x.DeviceId == queryDeviceId
|
&& x.Id != currentTask.Id
|
&& (x.TaskState == queryTaskState1 || x.TaskState == queryTaskState2)
|
&& x.CreateTime < currentTask.CreateTime
|
&& x.RealToPlace == currentTask.RealToPlace
|
).FirstOrDefault();
|
}
|
if (otherSrmTask != null)
|
{
|
errMsg = "上一个RGV任务(即相同目的地的" + currentTask.RealToPlace + ")未完成,所以本次任务不允许下发!上一个RGV任务号:" + otherSrmTask.PlcTaskId + ",本次RGV任务号:" + currentTask.PlcTaskId;
|
return false;
|
}
|
return true;
|
}
|
|
|
/// <summary>
|
/// 判断RGV任务,上一个RGV存在已下发的任务
|
/// </summary>
|
/// <param name="dbModel"></param>
|
/// <param name="currentTask"></param>
|
/// <param name="errMsg"></param>
|
/// <returns></returns>
|
public bool ValidateIsExistNoFinished(DbModel dbModel, Task_Part currentTask, ref string errMsg)
|
{
|
////判断和堆垛机(或RGV)的连接任务是不是已经完成了
|
var queryTaskState2 = (int)DeviceTaskStatusEnum.已下发;
|
var queryDeviceId = (int)EDevice.RGV;
|
|
var q_taskType_拆盘机入口到拆盘机 = (int)DeviceTaskTypeEnum.拆盘机入口到拆盘机;
|
var q_taskType_空托缓存位转运 = (int)DeviceTaskTypeEnum.空托缓存位转运;
|
|
//判断都是RGV任务,前面是否有 已下发 的任务,如果有,就报错
|
var otherSrmTask = dbModel.Task_Part.Where(x => x.DeviceId == queryDeviceId
|
&& x.Id != currentTask.Id
|
&& (x.TaskState == queryTaskState2)
|
//&& x.CreateTime < currentTask.CreateTime
|
&& (x.TaskType != q_taskType_拆盘机入口到拆盘机 && x.TaskType != q_taskType_空托缓存位转运)
|
).FirstOrDefault();
|
if (otherSrmTask != null)
|
{
|
errMsg = "上一个RGV任务是已下发状态,所以本次任务不允许下发!上一个RGV任务号:" + otherSrmTask.PlcTaskId + ",本次RGV任务号:" + currentTask.PlcTaskId;
|
return false;
|
}
|
return true;
|
}
|
|
/// <summary>
|
/// 是否 距离上一次出库任务的下发时间小于设定的值
|
/// </summary>
|
/// <param name="edm"></param>
|
/// <param name="partTask"></param>
|
/// <param name="errMsg"></param>
|
/// <returns></returns>
|
public bool VaidateIsMIN_OUTSTORE_RGV_TASK_JIANGE(DbModel edm, Task_Part partTask, ref string errMsg)
|
{
|
var queryToPlace = ((int)EDevice.出库口1012).ToString();
|
|
var queryTaskState1 = (int)DeviceTaskStatusEnum.已完成;
|
|
var queryDeviceId = (int)EDevice.RGV;
|
|
var task = edm.Task_Part.Where(x =>
|
x.DeviceId == queryDeviceId
|
&& x.RealToPlace == queryToPlace
|
&& x.TaskState == queryTaskState1).OrderByDescending(x => x.IssueTime).FirstOrDefault();//获取最新下发完成的出库任务
|
if (task != null)
|
{
|
//得到下发时间
|
var issueTime = (DateTime)task.IssueTime;
|
var nowTime = DateTime.Now;
|
TimeSpan ts = nowTime - issueTime;
|
if (ts.Seconds <= SysGloble.MIN_OUTSTORE_RGV_TASK_JIANGE)
|
{
|
errMsg = "距离上一次出库任务的下发时间小于设定的" + SysGloble.MIN_OUTSTORE_RGV_TASK_JIANGE + "秒";
|
return false;
|
}
|
}
|
return true;
|
}
|
|
/// <summary>
|
/// 是否 距离上一次出库任务的下发时间小于设定的值
|
/// </summary>
|
/// <param name="edm"></param>
|
/// <param name="partTask"></param>
|
/// <param name="errMsg"></param>
|
/// <returns></returns>
|
public bool VaidateIsMIN_OUTSTORE_RGV_TASK_JIANGE22(DbModel edm, Task_Part partTask, ref string errMsg)
|
{
|
var q_taskType_组盘入库 = (int)DeviceTaskTypeEnum.组盘入库;
|
var q_taskType_空托转运到立体库 = (int)DeviceTaskTypeEnum.空托转运到立体库;
|
|
var queryTaskState1 = (int)DeviceTaskStatusEnum.已完成;
|
|
var queryDeviceId = (int)EDevice.RGV;
|
|
var task = edm.Task_Part.Where(x =>
|
x.DeviceId == queryDeviceId
|
&& x.RealToPlace == partTask.RealToPlace
|
&& (x.TaskType == q_taskType_组盘入库 || x.TaskType == q_taskType_空托转运到立体库)
|
&& x.TaskState == queryTaskState1).OrderByDescending(x => x.IssueTime).FirstOrDefault();//获取上一次入库,并且是同一个目标点的任务
|
if (task != null)
|
{
|
//得到下发时间
|
var issueTime = (DateTime)task.IssueTime;
|
var nowTime = DateTime.Now;
|
TimeSpan ts = nowTime - issueTime;
|
if (ts.Seconds <= SysGloble.MIN_OUTSTORE_RGV_TASK_JIANGE)
|
{
|
errMsg = "距离上一次组盘入库/空托转运到立体库的任务下发时间小于设定的" + SysGloble.MIN_OUTSTORE_RGV_TASK_JIANGE + "秒";
|
return false;
|
}
|
}
|
return true;
|
}
|
|
|
/// <summary>
|
/// 是否存在 创建时间早于当前的任务的未结束的任务,去1012的任务
|
/// </summary>
|
/// <param name="edm"></param>
|
/// <param name="partTask"></param>
|
/// <param name="errMsg"></param>
|
/// <returns></returns>
|
public bool VaidateIsExistNoIssuedTaskBeforeCurrTaskTo1012(DbModel edm, Task_Part partTask, ref string errMsg)
|
{
|
var queryDeviceId = (int)EDevice.RGV;
|
var queryToPlace = ((int)EDevice.出库口1012).ToString();
|
if (partTask.RealToPlace == queryToPlace)
|
{
|
//判断创建时间早于当前的任务是否下发了,如果没下发,就也不允许下发
|
var queryTaskState1 = (int)DeviceTaskStatusEnum.未开始;
|
var queryTaskState2 = (int)DeviceTaskStatusEnum.已下发;
|
var list = edm.Task_Part.Where(x => x.RealToPlace == queryToPlace
|
&& (x.TaskState == queryTaskState1 || x.TaskState == queryTaskState2)
|
&& x.DeviceId == queryDeviceId
|
&& x.CreateTime < partTask.CreateTime //增加这个条件,防止出现顺序号相同的出库任务问题 【EditBy shaocx,2022-10-27】
|
&& x.Id != partTask.Id
|
&& x.MainTaskSequence <= partTask.MainTaskSequence
|
).FirstOrDefault();
|
if (list != null)
|
{
|
errMsg = "存在都是去向1012的任务,创建时间早于当前任务,但是未开始或已下发的任务" + list.PlcTaskId + ",因为要严格控制出库顺序,不允许下发当前任务:" + partTask.PlcTaskId;
|
return true;
|
}
|
}
|
return false;
|
}
|
|
/// <summary>
|
/// 是否存在 创建时间早于当前的任务的未结束的任务
|
/// </summary>
|
/// <param name="edm"></param>
|
/// <param name="partTask"></param>
|
/// <param name="errMsg"></param>
|
/// <returns></returns>
|
public bool VaidateIsExistNoIssuedTaskBeforeCurrTaskToSameInStoreStation(DbModel edm, Task_Part partTask, ref string errMsg)
|
{
|
var q_taskType_组盘入库 = (int)DeviceTaskTypeEnum.组盘入库;
|
var q_taskType_空托转运到立体库 = (int)DeviceTaskTypeEnum.空托转运到立体库;
|
var queryDeviceId = (int)EDevice.RGV;
|
|
|
//判断创建时间早于当前的任务是否下发了,如果没下发,就也不允许下发
|
var queryTaskState1 = (int)DeviceTaskStatusEnum.未开始;
|
var queryTaskState2 = (int)DeviceTaskStatusEnum.已下发;
|
var list = edm.Task_Part.Where(x =>
|
x.RealToPlace == partTask.RealToPlace
|
&& (x.TaskType == q_taskType_组盘入库 || x.TaskType == q_taskType_空托转运到立体库)
|
&& (x.TaskState == queryTaskState1 || x.TaskState == queryTaskState2)
|
&& x.DeviceId == queryDeviceId
|
&& x.CreateTime < partTask.CreateTime).FirstOrDefault();
|
if (list != null)
|
{
|
errMsg = "存在都是去向相同" + partTask.RealToPlace + "的入库任务,创建时间早于当前任务,但是未开始或已下发的任务" + list.PlcTaskId + ",因为要严格控制入库顺序,不允许下发当前任务:" + partTask.PlcTaskId;
|
return true;
|
}
|
|
return false;
|
}
|
|
|
/// <summary>
|
/// 更新主任务的状态
|
/// </summary>
|
/// <param name="edm"></param>
|
/// <param name="mainTaskId"></param>
|
/// <param name="rgvTaskTypeValue"></param>
|
/// <param name="remark"></param>
|
private void UpdateMainTaskStatus(DbModel edm, int mainTaskId, int rgvTaskTypeValue, string remark)
|
{
|
DeviceTaskTypeEnum rgvTaskTypeEnum = (DeviceTaskTypeEnum)Enum.Parse(typeof(DeviceTaskTypeEnum), rgvTaskTypeValue.ToString());
|
MainTaskStatusEnum changeTaskStatus = default(MainTaskStatusEnum);
|
switch (rgvTaskTypeEnum)
|
{
|
case DeviceTaskTypeEnum.组盘入库:
|
changeTaskStatus = MainTaskStatusEnum.入库中;
|
MainTaskHandler.UpdateTaskStatus(edm, mainTaskId, changeTaskStatus, remark);
|
break;
|
case DeviceTaskTypeEnum.出库:
|
changeTaskStatus = MainTaskStatusEnum.已完成;
|
MainTaskHandler.UpdateTaskStatus(edm, mainTaskId, changeTaskStatus, remark);
|
|
//如果是有计划的,需要处理下计划表的状态
|
UpdatePlanOut(edm, mainTaskId);
|
break;
|
case DeviceTaskTypeEnum.空托缓存位转运:
|
case DeviceTaskTypeEnum.空托转运到拆盘机入口:
|
case DeviceTaskTypeEnum.立库空托到拆盘机入口:
|
case DeviceTaskTypeEnum.拆盘机入口到拆盘机:
|
changeTaskStatus = MainTaskStatusEnum.已完成;
|
MainTaskHandler.UpdateTaskStatus(edm, mainTaskId, changeTaskStatus, remark);
|
break;
|
default:
|
return;//其他状态不予处理
|
}
|
|
}
|
|
private void UpdatePlanOut(DbModel edm, int mainTaskId)
|
{
|
var planDetail = edm.Plan_OutTaskDetail.FirstOrDefault(x => x.MainTaskId == mainTaskId);
|
if (planDetail != null)
|
{
|
planDetail.OutTaskDetailState = (int)OutTaskDetailStateEnum.完成;
|
planDetail.OutTaskDetailStateName = OutTaskDetailStateEnum.完成.ToString();
|
planDetail.FinishTime = DateTime.Now;//增加计划子表完成时间 【EditBy shaocx,2022-06-20】
|
planDetail.OperationRemark = "RGV任务完成,修改状态为完成";
|
//查找Main表
|
var outTask = edm.Plan_OutTask.FirstOrDefault(x => x.Id == planDetail.M_PlanId);
|
if (outTask != null)
|
{
|
var queryOutTaskDetailState1 = (int)OutTaskDetailStateEnum.完成;
|
var queryOutTaskDetailState2 = (int)OutTaskDetailStateEnum.已取消;
|
var allCount = edm.Plan_OutTaskDetail.Where(x => x.M_PlanId == outTask.Id).Count();//所有计划
|
outTask.Qty = allCount;//重新赋值总数量
|
|
var count = edm.Plan_OutTaskDetail.Where(x => x.M_PlanId == outTask.Id && (x.OutTaskDetailState == queryOutTaskDetailState1 || x.OutTaskDetailState == queryOutTaskDetailState2)).Count();//已下发的计划
|
var finishedCount = count + 1;
|
var changeOutPlanStateEnum = default(OutPlanStateEnum);
|
if (finishedCount >= outTask.Qty)
|
{
|
changeOutPlanStateEnum = OutPlanStateEnum.全部下发;
|
outTask.PlanState = (int)changeOutPlanStateEnum;
|
outTask.PlanStateName = changeOutPlanStateEnum.ToString();
|
outTask.OperationRemark = "RGV任务完成,全部下发";
|
|
outTask.Qty_Finish = outTask.Qty;
|
outTask.Qty_NoFinish = 0;
|
//修改齐套性为已齐套 [EditBy shaocx,2022-05-16]
|
outTask.IsPickFinished = true;
|
//更新计划进度
|
outTask.PlanRate = 100;
|
}
|
else
|
{
|
changeOutPlanStateEnum = OutPlanStateEnum.部分下发;
|
outTask.PlanState = (int)changeOutPlanStateEnum;
|
outTask.PlanStateName = changeOutPlanStateEnum.ToString();
|
outTask.OperationRemark = "RGV任务完成,部分下发";
|
outTask.Qty_Finish = finishedCount;
|
outTask.Qty_NoFinish = outTask.Qty - finishedCount;
|
//更新计划进度
|
outTask.PlanRate = CSharpHelper.ExecPercentRetInt(finishedCount, outTask.Qty);
|
}
|
}
|
}
|
}
|
|
/// <summary>
|
/// 修改CVP的数据
|
/// </summary>
|
/// <param name="edm"></param>
|
/// <param name="rgvTaskTypeEnum"></param>
|
/// <param name="rgvTask"></param>
|
private void UpdateStore(DbModel dbModel, Base_Station sourcePlace, Base_Station toPlace, DeviceTaskTypeEnum rgvTaskTypeEnum, Task_Part rgvTask)
|
{
|
switch (rgvTaskTypeEnum)
|
{
|
case DeviceTaskTypeEnum.组盘入库:
|
default://其他
|
|
TransferStoreWhenFinished(rgvTask, dbModel, rgvTask.SalverId, toPlace, "RGV任务被下发,重新绑定新的CVP关系", rgvTaskTypeEnum, EDeviceType.RGV);
|
break;
|
case DeviceTaskTypeEnum.拆盘机入口到拆盘机:
|
case DeviceTaskTypeEnum.出库://注意:RGV出库的时候,目前是将库存删除掉!!!!
|
StoreHandler.ClearStockByPlaceId(dbModel, sourcePlace, "RGV出库任务被下发,删除库存");
|
//记录主表的出库时间
|
var mainTask = dbModel.Task_Main.Where(x => x.TaskNo == rgvTask.MainTaskNo).First();
|
mainTask.OutStoreTime = DateTime.Now;
|
break;
|
}
|
}
|
|
|
public bool ValidateDeviceIsAllowSendTask(bool isRgvTask, int int_deviceId, Task_Part task, out string errMsg)
|
{
|
errMsg = "";
|
if (FormCC.IsSimulationPLC)
|
{
|
return true;
|
}
|
if (!base.ValidateDeviceIsAllowSendTask(int_deviceId, out errMsg))
|
{
|
return false;
|
}
|
bool isNeedValidateRealSourceAndToPlace = true;
|
if (task.RealSourcePlace == ((int)EDevice.堆垛机1出库口1001).ToString()
|
|| task.RealSourcePlace == ((int)EDevice.堆垛机2出库口1003).ToString()
|
|| task.RealSourcePlace == ((int)EDevice.堆垛机3出库口1005).ToString()
|
|| task.RealSourcePlace == ((int)EDevice.堆垛机4出库口1008).ToString()
|
)
|
{//如果是立体库出库口,则不需要校验起点和终点是否是自动模式啊,运行模式啊
|
isNeedValidateRealSourceAndToPlace = false;
|
}
|
using (var rgvServie = new RgvService.RgvServiceClient())
|
{
|
SdaResEntity sdaResult = rgvServie.IsAllowSendTask(isNeedValidateRealSourceAndToPlace, int_deviceId, task.RealSourcePlace, task.RealToPlace, isRgvTask);
|
if (sdaResult.result == false)
|
{
|
errMsg = sdaResult.resMsg;
|
Log4NetHelper.WriteErrorLog(currentLogType, "验证RGV不可以下发新任务,int_deviceId:" + int_deviceId + ",sdaResultStr:" + JsonConvert.SerializeObject(sdaResult));
|
}
|
return sdaResult.result;
|
}
|
}
|
|
/// <summary>
|
/// 验证Rgv是否可以接受任务
|
/// </summary>
|
/// <param name="int_deviceId">设备号,不需要</param>
|
/// <param name="taskId">任务号,需要</param>
|
/// <returns></returns>
|
public override bool ValidateDeviceIsOK(int int_deviceId, Task_Part _task, int taskId, out string errMsg)
|
{
|
errMsg = "";
|
// Rgv没有所谓的空闲状态,有任务直接发即可
|
if (Wms_EquipmentSituationHandler.IsEquipmentBreakdown(int_deviceId).result)
|
{//如果设备已经设定为 故障状态,不允许下发任务!!! [EditBy shaocx,2020-12-07]
|
return false;
|
}
|
return true;
|
}
|
|
/// <summary>
|
/// 验证Rgv是否任务完成
|
/// </summary>
|
/// <param name="int_deviceId"></param>
|
/// <returns>0表示没有任务完成,其他表示任务完成,并返回任务号</returns>
|
public override bool ValidateDeviceTaskIsFinsished(int int_deviceId, Task_Part _task, int taskId, bool? isAllowSimulateExecute, out string errMsg)
|
{
|
errMsg = "";
|
if (FormCC.IsSimulationPLC)
|
{
|
return true;
|
}
|
if (MyExtendHelper.IsAllowSimulatorHandle(_task))
|
{//模拟代码!发布时移除该代码
|
errMsg = "任务要求强制模拟完成";
|
return true;
|
}
|
var isRgvTask = IsRgvTask(_task);
|
|
if (isRgvTask == false)
|
{
|
//注意:这里不需要跟rgv确认完成,发送任务就自动完成任务了 【EditBy shaocx,2022-04-13】
|
return true;
|
}
|
else
|
{
|
var result = new RgvService.RgvServiceClient().IsTaskFinish(int_deviceId, taskId);
|
if (result.result) return true;
|
else
|
{
|
errMsg = result.resMsg;
|
return false;
|
}
|
}
|
}
|
#endregion
|
}
|
}
|