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 } }