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
{
///
/// RGV任务服务线程类
///
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任务线程
///
/// 自动执行Rgv任务
///
///
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秒一次
}
}
///
/// 自动执行Rgv任务(线程)
///
///
public override void IssueTaskHandle(int deviceId, out string errMsg)
{
errMsg = "";
string logHeader = "方法:DoRgvTaskByThead,参数deviceId:" + deviceId.ToString() + "===";
#region 新增异常信息表 【EditBy shaocx,2020-01-20】
IDictionary logDict = new Dictionary();
logDict.Add("deviceId", deviceId);
Base_SysExceptionInfo exception = SysExceptionInfoHandler.GetExceptionInfo>(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);
}
}
///
///
///
///
///
///
///
///
/// 是否是出库任务
///
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(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任务线程
///
/// 自动结束Rgv任务线程
///
///
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);
}
}
///
/// 自动结束Rgv任务线程(线程)
///
///
public override void ConfirmFinishTaskHandle(int deviceId, out string errMsg)
{
errMsg = "";
var remark = "自动结束Rgv任务线程(线程)";
#region 新增异常信息表 【EditBy shaocx,2020-01-20】
IDictionary logDict = new Dictionary();
logDict.Add("deviceId", deviceId);
Base_SysExceptionInfo exception = SysExceptionInfoHandler.GetExceptionInfo>(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】
///
/// RGV任务完成确认补偿线程
///
///
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 库存处理
///
/// 库存转移
///
///
///
///
///
///
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(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 公共处理
///
/// 发动机出库,给西港PLC发送发动机数据 【Editby shaocx,2023-07-23】
///
///
///
///
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;
}
}
///
/// 是否是RGV任务
///
///
///
private bool IsRgvTask(Task_Part _task)
{
var isRgvTask = true;
if (_task.TaskType == (int)DeviceTaskTypeEnum.拆盘机入口到拆盘机 || _task.TaskType == (int)DeviceTaskTypeEnum.空托缓存位转运)
{
isRgvTask = false;
}
return isRgvTask;
}
///
/// 判断相同目的地的RGV任务,上一个是否完成了
///
///
///
///
///
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;
}
///
/// 判断RGV任务,上一个RGV存在已下发的任务
///
///
///
///
///
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;
}
///
/// 是否 距离上一次出库任务的下发时间小于设定的值
///
///
///
///
///
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;
}
///
/// 是否 距离上一次出库任务的下发时间小于设定的值
///
///
///
///
///
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;
}
///
/// 是否存在 创建时间早于当前的任务的未结束的任务,去1012的任务
///
///
///
///
///
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;
}
///
/// 是否存在 创建时间早于当前的任务的未结束的任务
///
///
///
///
///
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;
}
///
/// 更新主任务的状态
///
///
///
///
///
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);
}
}
}
}
///
/// 修改CVP的数据
///
///
///
///
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;
}
}
///
/// 验证Rgv是否可以接受任务
///
/// 设备号,不需要
/// 任务号,需要
///
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;
}
///
/// 验证Rgv是否任务完成
///
///
/// 0表示没有任务完成,其他表示任务完成,并返回任务号
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
}
}