using iWareCommon;
using iWareCommon.Utils;
using iWareSql;
using System;
using System.Collections.Generic;
using System.Threading;
using iWareCC.SrmService;
using System.Linq;
using iWareSql.Orm;
using System.Threading.Tasks;
using iWareSql.DataAccess;
using iWareSql.Entity.ParamModel;
using Newtonsoft.Json;
using iWareCC.BLL;
using iWareCC.Common;
using iWareModel;
using iWareSql.DBModel;
using iWareCommon.Common.Globle;
using XiGang.Core.Model;
using iWareCC.Common.Helper;
namespace iWareCC
{
///
/// 堆垛机任务服务线程类
///
public class SrmTaskThreadService : DeviceThreadServiceHandle
{
private static string _namespace = "iWareCC.SrmTaskThreadService";
private SrmTaskThreadService() { }
public SrmTaskThreadService(iWareCommon.Utils.LogType logType)
{
base.currentLogType = logType;
}
public override void StartService()
{
Task.Run(() =>
{
try
{
//自动执行堆垛机任务线程
Log4NetHelper.WriteInfoLog(base.currentLogType, "自动执行堆垛机任务线程启动了");
//var srmList = new SrmService.SrmServiceClient().GetSrm_CacheEntity();
var srmList = FormCC.SrmDeviceList;
foreach (var x in srmList)
{
IssueTaskThread(x);
ConfirmFinishTaskThread(x);
}
}
catch (Exception ex)
{
Log4NetHelper.WriteErrorLog(base.currentLogType, "SrmTaskThreadService线程启动出现异常", ex);
}
});
}
#region 线程处理
#region 自动执行堆垛机任务线程
///
/// 自动执行堆垛机任务
///
///
public override void IssueTask(object deviceId)
{
string errMsg1 = "", errMsg2 = "", errMsg3 = "", errMsg4 = "";
int i_deviceId = (int)deviceId;
while (true)
{
if ((int)deviceId == (int)EDevice.一号堆垛机 && SystemValue.isAllowRuning_SrmTaskThreadService_1 && SystemValue.isStartedModel)
{
IssueTaskHandle(i_deviceId, out errMsg1);
}
else if ((int)deviceId == (int)EDevice.二号堆垛机 && SystemValue.isAllowRuning_SrmTaskThreadService_2 && SystemValue.isStartedModel)
{
IssueTaskHandle(i_deviceId, out errMsg2);
}
else if ((int)deviceId == (int)EDevice.三号堆垛机 && SystemValue.isAllowRuning_SrmTaskThreadService_3 && SystemValue.isStartedModel)
{
IssueTaskHandle(i_deviceId, out errMsg3);
}
else if ((int)deviceId == (int)EDevice.四号堆垛机 && SystemValue.isAllowRuning_SrmTaskThreadService_4 && SystemValue.isStartedModel)
{
IssueTaskHandle(i_deviceId, out errMsg4);
}
SystemWarningMsg._lbl_Alert_DataProcess_BZ39_IssueInboundTask = errMsg1;
SystemWarningMsg._lbl_Alert_DataProcess_RobotBuffer_ForceOutbound = errMsg2;
SystemWarningMsg._lbl_Alert_Srm4Release = errMsg4;
Thread.Sleep(2000);//2秒一次
}
}
///
/// 自动执行堆垛机任务(线程)
///
///
public override void IssueTaskHandle(int deviceId, out string errMsg)
{
errMsg = "";
string logHeader = "方法:DoSrmTaskByThead,参数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, "DoSrmTaskByThead", logDict);
#endregion
try
{
/*
* 执行发送给堆垛机的指令任务
* 1、验证根据设备号是否找到堆垛机
* 2、判断设备是否属于任务完成,如果属于任务完成,就继续走3
* 3、判断数据库中是否有可要下发的任务,如果有就下发+验证起始点和目标点是否正确
* 4、下发成功后,更新任务状态
*/
errMsg = "";
int int_deviceId = (int)deviceId;
//2、判断堆垛机是否可以下发新任务
bool isOk = ValidateDeviceIsAllowSendTask(int_deviceId, out errMsg);
if (!isOk)
{
errMsg = "不允许下发新任务," + errMsg;
return;
}
using (DbModel dbModel = new DbModel())
{
//var srmTask = ValidateIsExistTaskToDispose(dbModel, int_deviceId, out errMsg, TaskExcuteTypeEnum.执行任务);
//if (srmTask == null)
//{//表示DB中没有任务要发送给堆垛机
// return;
//}
var srmTaskList = ValidateIsExistTaskToDisposeForIssued(dbModel, int_deviceId, out errMsg);
if (srmTaskList == null || srmTaskList.Count == 0)
{//表示DB中没有任务要发送给堆垛机
return;
}
foreach (var item in srmTaskList)
{
SingleIssueTaskHandle(item, exception, dbModel, int_deviceId, out errMsg);
if (!string.IsNullOrEmpty(errMsg))
{//说明报错了,继续走下一个循环
continue;
}
else
{//说明执行成功了,跳出循环
break;
}
}
}
}
catch (Exception ex)
{
errMsg = "异常,请联系管理员:" + ex.Message;
SysExceptionInfoHandler.GetExceptionInfoForError("自动执行堆垛机任务(线程)出现异常,deviceId:" + deviceId + ",异常:" + ex.Message, ex, ref exception);
SysExceptionInfoHandler.InsertExceptionInfo(exception, true);
}
}
///
/// 单个堆垛机任务下发处理
///
///
///
///
///
///
private void SingleIssueTaskHandle(Task_Part srmTask, Base_SysExceptionInfo exception, DbModel dbModel, int int_deviceId, out string errMsg)
{
#region //3、判断数据库中是否有可要下发的任务,如果有就下发
DeviceTaskTypeEnum _DeviceTaskTypeEnum = (DeviceTaskTypeEnum)Enum.Parse(typeof(DeviceTaskTypeEnum), srmTask.TaskType.ToString());
//验证起始点和目标点是否正确
RealPlaceEntity realPlaceEntity = null;
if (!ValdiatePalceIsRight(dbModel, (int)srmTask.SourcePlace, (int)srmTask.ToPlace, ref realPlaceEntity))
{
errMsg = "验证起始点和目标点是否正确失败";
PartTaskHandler.WriteOperationRemarkForPartTask(srmTask.Id, errMsg);
return;
}
//验证目标点是否已经有库存 【EditBy shaocx,2022-04-15】
var isOk = ValidateIsHasStoreForToPlace(int_deviceId, srmTask.ToPlace, srmTask.RealToPlace, out errMsg);
if (!isOk)
{
errMsg = "不允许下发新任务," + errMsg;
PartTaskHandler.WriteOperationRemarkForPartTask(srmTask.Id, errMsg);
return;
}
#region 增加校验 [EditBy shaocx,2022-05-15]
//去掉这个验证 【EditBy shaocx,2022-05-19】
/*
Base_Station toPlaceObject = dbModel.Base_Station.Where(o => o.Id == (int)srmTask.ToPlace).FirstOrDefault();
if (toPlaceObject == null)
{
throw new Exception(string.Format("根据目标库位ID {0},{1}没有找到库位信息!", srmTask.ToPlace, srmTask.RealToPlace));
}
//*/
var sourcePlace = dbModel.Base_Station.Where(o => o.Id == srmTask.SourcePlace).FirstOrDefault();
if (sourcePlace == null)
{
throw new Exception(string.Format("根据库位号{0},{1}没有找到堆垛机的来源库位信息!", srmTask.SourcePlace.ToString(), srmTask.RealSourcePlace));
}
//要判断起点是否有库存,如果起点没有库存,则报错
var sourcePlaceStore = dbModel.V_AllStore.Where(x => x.StationId == sourcePlace.Id).FirstOrDefault();
if (sourcePlaceStore == null)
{
throw new Exception(string.Format("起点{0},{1}没有找到库存信息,无法下发堆垛机任务!任务号{2}", srmTask.SourcePlace.ToString(), srmTask.RealSourcePlace, srmTask.Id));
}
#endregion
//同一个关联任务的其他设备任务
var queryTaskState1 = (int)DeviceTaskStatusEnum.未开始;
//var queryTaskState2 = (int)DeviceTaskStatusEnum.已下发;
var relevanceTask = dbModel.Task_Part.Where(x => x.MainTaskId == srmTask.MainTaskId && x.TaskSequence < srmTask.TaskSequence
&& (x.TaskState == queryTaskState1)
).FirstOrDefault();
if (relevanceTask != null)
{
errMsg = string.Format("关联{0}任务未开始,所以堆垛机任务不允许下发!关联任务号:{1}", relevanceTask.DeviceName, relevanceTask.PlcTaskId);
PartTaskHandler.WriteOperationRemarkForPartTask(srmTask.Id, errMsg);
return;
}
//去掉验证 【EditBy shaocx,2022-05-19】
/*
var validateIsAllowNewTaskForRgvStattion = ValidateIsAllowNewTaskForRgvStattion(dbModel, _DeviceTaskTypeEnum, srmTask.RealToPlace, ref errMsg);
if (!validateIsAllowNewTaskForRgvStattion)
{
PartTaskHandler.WriteOperationRemarkForPartTask(srmTask.Id, errMsg);
return;
}
//*/
var log = TaskRequestLogHandler.GetTask(srmTask.Id,
int_deviceId, srmTask.PlcTaskId, srmTask.RealSourcePlace,
srmTask.RealToPlace, "给堆垛机发送任务指令", "sys");
SdaResEntity sdaResult = new SdaResEntity();
try
{
if (MyExtendHelper.IsAllowSimulatorHandle(srmTask))
{
sdaResult.result = true;
}
else
{
if (Convert.ToInt32(srmTask.PlcTaskId) <= 0)
{
throw new Exception("任务号不能小于等于0,PlcTaskId:" + srmTask.PlcTaskId);
}
sdaResult = new SrmService.SrmServiceClient().SendSrmTask(int_deviceId, Convert.ToInt32(srmTask.PlcTaskId), srmTask.RealSourcePlace, srmTask.RealToPlace, (short)ESrmCmd.库内搬运);
}
if (sdaResult.result == false)
{//给堆垛机下发指令失败
exception.exceptionMsg = string.Format("发送指令给堆垛机失败,设备号{0},任务ID{1},起始位{2},目标位{3},ContainerId{4}", int_deviceId,
Convert.ToInt32(srmTask.PlcTaskId), srmTask.RealSourcePlace, srmTask.RealToPlace, srmTask.SalverId);
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);
SystemValueUtil.DelayExcuteForSrmTaskThreadService(int_deviceId, ThreadDirectionEnum.任务开始下发线程);
}
}
catch (Exception ex)
{
TaskRequestLogHandler.InsertTask(base.currentLogType, RequestStatusEnum.请求失败, JsonConvert.SerializeObject(sdaResult).ToString(), log, ex);
throw ex;
}
#endregion
//只更新着三个字段!
//任务完成后的库存转移工作
isOk = DealWithCurrentTaskWhenFinished(srmTask, dbModel);
if (isOk == false)
{
throw new Exception("DealWithCurrentTaskWhenFinished处理失败");
}
}
///
/// 当前任务完成后进行状态修改
///
/// 当前任务
///
private bool DealWithCurrentTaskWhenFinished(Task_Part currentTask, DbModel dbModel)
{
#region 新增异常信息表 【EditBy shaocx,2020-01-20】
IDictionary logDict = new Dictionary();
logDict.Add("currentTask.tackId", currentTask.Id);
logDict.Add("currentTask.plcTaskId", currentTask.PlcTaskId);
Base_SysExceptionInfo exception = SysExceptionInfoHandler.GetExceptionInfo>(base.currentLogType, _namespace, "DealWithCurrentTask", logDict);
#endregion
try
{
bool rtn = false;
var taskType = (DeviceTaskTypeEnum)Enum.Parse(typeof(DeviceTaskTypeEnum), currentTask.TaskType.ToString());
switch (taskType)
{
case DeviceTaskTypeEnum.组盘入库:
case DeviceTaskTypeEnum.空托转运到立体库:
rtn = DealFor_Srm_Store_In(currentTask, dbModel, taskType);//入库执行后增加库存
break;
case DeviceTaskTypeEnum.出库:
case DeviceTaskTypeEnum.立库空托到拆盘机入口:
rtn = DealFor_Srm_Store_Out(currentTask, dbModel, taskType);//出库
break;
default:
break;
}
//库存发生变化时,发送库存给MES
//switch (taskType)
//{
// case DeviceTaskTypeEnum22.配板原料入库:
// case DeviceTaskTypeEnum22.线下配板原料入库:
// case DeviceTaskTypeEnum22.配板余料回库:
// case DeviceTaskTypeEnum22.配板原料出库:
// case DeviceTaskTypeEnum22.人工出库:
// //MesBLL.SendSysnStockToMes();
// break;
// default:
// break;
//}
return rtn;
}
catch (Exception ex)
{
SysExceptionInfoHandler.GetExceptionInfoForError("当前任务完成后进行状态修改出现异常:" + ex.Message, ex, ref exception);
SysExceptionInfoHandler.InsertExceptionInfo(exception);
throw ex;
}
}
///
/// 入库任务处理
///
///
///
private bool DealFor_Srm_Store_In(Task_Part currentTask, DbModel dbModel, DeviceTaskTypeEnum taskType)
{
#region 新增异常信息表 【EditBy shaocx,2020-01-20】
IDictionary logDict = new Dictionary();
logDict.Add("currentTask.tackId", currentTask.Id);
logDict.Add("currentTask.plcTaskId", currentTask.PlcTaskId);
Base_SysExceptionInfo exception = SysExceptionInfoHandler.GetExceptionInfo>(base.currentLogType, _namespace, "DealFor_Srm_Store_In", logDict);
#endregion
try
{
/**
* 1、当前任务状态修改为已完成
* 2、添加托盘和库位的绑定关系
* 3、变更库位状态
*/
#region 准备数据
#region 增加校验 [EditBy shaocx,2022-05-15]
Base_Station toPlaceObject = dbModel.Base_Station.Where(o => o.Id == (int)currentTask.ToPlace).FirstOrDefault();
if (toPlaceObject == null)
{
throw new Exception(string.Format("根据目标库位ID {0},{1}没有找到库位信息!", currentTask.ToPlace, currentTask.RealToPlace));
}
var sourcePlace = dbModel.Base_Station.Where(o => o.Id == currentTask.SourcePlace).FirstOrDefault();
if (sourcePlace == null)
{
throw new Exception(string.Format("根据库位号{0},{1}没有找到堆垛机的来源库位信息!", currentTask.SourcePlace.ToString(), currentTask.RealSourcePlace));
}
//要判断起点是否有库存,如果起点没有库存,则报错
var sourcePlaceStore = dbModel.V_AllStore.Where(x => x.StationId == sourcePlace.Id).FirstOrDefault();
if (sourcePlaceStore == null)
{
throw new Exception(string.Format("起点{0},{1}没有找到库存信息,无法下发堆垛机任务!这里任务号{2}", currentTask.SourcePlace.ToString(), currentTask.RealSourcePlace, currentTask.Id));
}
#endregion
toPlaceObject.IsHasTaskDoing = false;
toPlaceObject.IsFull = true;
StationHandler.SetPlaceLockStatus(false, SysGloble.WCSSystem, ref toPlaceObject, "堆垛机任务完成,入库任务处理,任务类型:" + taskType.ToString());
StationHandler.SetPlaceLockStatus(false, SysGloble.WCSSystem, ref sourcePlace, "堆垛机任务完成,入库任务处理,任务类型:" + taskType.ToString());
#endregion
return CommonTransForThreadFinish(dbModel, currentTask, "入库任务完成处理成功,任务类型:" + taskType.ToString(), sourcePlace, toPlaceObject, taskType);
}
catch (Exception ex)
{
SysExceptionInfoHandler.GetExceptionInfoForError("入库任务处理出现异常:" + ex.Message, ex, ref exception);
SysExceptionInfoHandler.InsertExceptionInfo(exception);
throw ex;
}
}
///
/// 出库任务处理
///
///
///
private bool DealFor_Srm_Store_Out(Task_Part currentTask, DbModel dbModel, DeviceTaskTypeEnum taskType)
{
#region 新增异常信息表 【EditBy shaocx,2020-01-20】
IDictionary logDict = new Dictionary();
logDict.Add("currentTask.tackId", currentTask.Id);
logDict.Add("currentTask.plcTaskId", currentTask.PlcTaskId);
Base_SysExceptionInfo exception = SysExceptionInfoHandler.GetExceptionInfo>(base.currentLogType, _namespace, "DealFor_Srm_Store_Out", logDict);
#endregion
try
{
/**
* 1、当前任务状态修改为已完成
* 2、解除来源位置的托盘和库位的绑定关系
* 3、变更库位状态
*/
#region 准备数据
Base_Station toPlaceObject = dbModel.Base_Station.Where(o => o.Id == (int)currentTask.ToPlace).FirstOrDefault();
if (toPlaceObject == null)
{
throw new Exception(string.Format("根据库位ID {0}没有找到库位信息!", currentTask.ToPlace));
}
#region 3、变更库位状态
//目标的库位状态
toPlaceObject.IsHasTaskDoing = false;
toPlaceObject.IsFull = true;
StationHandler.SetPlaceLockStatus(false, SysGloble.WCSSystem, ref toPlaceObject, "堆垛机任务完成,出库任务处理");
//来源位置的库位状态
var sourcePlace = dbModel.Base_Station.Where(o => o.Id == currentTask.SourcePlace).FirstOrDefault();
if (sourcePlace == null)
{
throw new Exception(string.Format("根据库位号{0}没有找到库位信息!", currentTask.SourcePlace.ToString()));
}
sourcePlace.IsHasTaskDoing = false;
sourcePlace.IsFull = false;
StationHandler.SetPlaceLockStatus(false, SysGloble.WCSSystem, ref sourcePlace, "堆垛机任务完成,出库任务处理");
#endregion
#endregion
return CommonTransForThreadFinish(dbModel, currentTask, "出库任务处理成功", sourcePlace, toPlaceObject, taskType);
}
catch (Exception ex)
{
SysExceptionInfoHandler.GetExceptionInfoForError("出库任务处理出现异常:" + ex.Message, ex, ref exception);
SysExceptionInfoHandler.InsertExceptionInfo(exception);
return false;
}
}
private bool CommonTransForThreadFinish(DbModel dbModel, Task_Part currentTask,
string business, Base_Station sourcePlace, Base_Station toPlaceObject, DeviceTaskTypeEnum taskType)
{
#region 新增异常信息表 【EditBy shaocx,2020-01-20】
IDictionary logDict = new Dictionary();
logDict.Add("currentTask.tackId", currentTask.Id);
logDict.Add("currentTask.plcTaskId", currentTask.PlcTaskId);
Base_SysExceptionInfo exception = SysExceptionInfoHandler.GetExceptionInfo>(base.currentLogType, _namespace, "CommonTransForThreadFinish", logDict);
#endregion
try
{
try
{
#region 当设备任务完成后,转移库存(注意:一定要在最后面执行!!)
try
{
TransferStoreWhenFinished(currentTask, dbModel, currentTask.SalverId, toPlaceObject, business, taskType, EDeviceType.堆垛机);
}
catch (Exception ex)
{
throw new Exception("转移库存时抛出异常,方法(TransferStoreWhenFinished),message:" + ex.Message, ex);
}
#endregion
UpdateMainTaskStatus(dbModel, currentTask.MainTaskId, currentTask.TaskType, "堆垛机任务完成时");
//4、下发成功后,更新任务状态
currentTask.IsReleased = true;
currentTask.ModifyBy = SysGloble.WCSSystem;
currentTask.ModifyTime = DateTime.Now;
currentTask.TaskState = (int)DeviceTaskStatusEnum.已下发;
currentTask.TaskStateName = DeviceTaskStatusEnum.已下发.ToString();
currentTask.OperationRemark = "任务已下发给设备";
currentTask.IssueTime = DateTime.Now;//下发时间
//注意:一定是先要保存数据库,才再跟plc交互!!!!!
int i = dbModel.SaveChanges();
if (i <= 0)
{
throw new Exception("更新的条数为" + i);
}
}
catch (Exception ex)
{
throw ex;
}
return true;
}
catch (Exception)
{
throw;
}
}
#endregion
#region 自动结束堆垛机任务线程
///
/// 自动结束堆垛机任务线程
///
///
public override void ConfirmFinishTask(object deviceId)
{
string errMsg1 = "", errMsg2 = "", errMsg3 = "", errMsg4 = "";
int i_deviceId = (int)deviceId;
while (true)
{
if ((int)deviceId == (int)EDevice.一号堆垛机 && SystemValue.isAllowRuning_SrmTaskThreadService_1_Finish && SystemValue.isStartedModel)
{
ConfirmFinishTaskHandle(i_deviceId, out errMsg1);
}
else if ((int)deviceId == (int)EDevice.二号堆垛机 && SystemValue.isAllowRuning_SrmTaskThreadService_2_Finish && SystemValue.isStartedModel)
{
ConfirmFinishTaskHandle(i_deviceId, out errMsg2);
}
else if ((int)deviceId == (int)EDevice.三号堆垛机 && SystemValue.isAllowRuning_SrmTaskThreadService_3_Finish && SystemValue.isStartedModel)
{
ConfirmFinishTaskHandle(i_deviceId, out errMsg3);
}
else if ((int)deviceId == (int)EDevice.四号堆垛机 && SystemValue.isAllowRuning_SrmTaskThreadService_4_Finish && SystemValue.isStartedModel)
{
ConfirmFinishTaskHandle(i_deviceId, out errMsg4);
}
SystemWarningMsg._lbl_Alert_Srm1ReleaseFinish = errMsg1;
SystemWarningMsg._lbl_Alert_DataProcess_BZ12_FinishTask = errMsg2;
SystemWarningMsg._lbl_Alert_DataProcess_BZ21_FinishTask = errMsg3;
Thread.Sleep(2000);//设置2秒一次
}
}
///
/// 自动结束堆垛机任务线程(线程)
///
///
public override void ConfirmFinishTaskHandle(int deviceId, out string errMsg)
{
errMsg = "";
string logHeader = "自动结束堆垛机任务线程(线程),设备号:" + deviceId;
#region 新增异常信息表 【EditBy shaocx,2020-01-20】
IDictionary logDict = new Dictionary();
logDict.Add("deviceId", deviceId);
Base_SysExceptionInfo exception = SysExceptionInfoHandler.GetExceptionInfo>(base.currentLogType, _namespace, "FinishSrmTaskByThead", logDict);
#endregion
try
{
/*
* 执行发送给堆垛机的指令任务
* 1、验证根据设备号是否找到堆垛机
* 2、判断设备是否属于任务完成,如果属于任务完成,就继续走3
* 3、判断数据库中是否有可要完成的任务,如果有判断是否跟堆垛机中的完成任务相符,如果相符就处理
* 4、更新任务状态
*/
int int_deviceId = (int)deviceId;
//SystemValueUtil.DelayExcuteForSrmTaskThreadService((int)deviceId, ThreadDirectionEnum.任务完成线程);
using (DbModel dbModel = new DbModel())
{
#region //3、判断数据库中是否有可要完成的任务,如果有判断是否跟堆垛机中的完成任务相符,如果相符就处理
var currentTask = ValidateIsExistTaskToDispose(dbModel, int_deviceId, out errMsg, TaskExcuteTypeEnum.结束任务);
if (currentTask == null)
{//表示DB中没有任务要发送给堆垛机
//注释以下代码,手动发的任务,不要自动确认
////可以完成 非系统发送的自动任务 [EditBy shaocx,2022-04-04]
//if (FormCC.IsSimulationPLC == false && FormCC.srmViewDict[int_deviceId].R_TaskFinish == 1 && FormCC.srmViewDict[int_deviceId].R_TaskNo > 0)
//{//只有当堆垛机是任务完成的时候
// ConfirmTaskFinishToSda(deviceId, FormCC.srmViewDict[int_deviceId].R_TaskNo);
//}
errMsg = "没有堆垛机任务数据要处理";
return;
}
#endregion
//2、判断设备是否任务完成
var isFinished = ValidateDeviceTaskIsFinsished(int_deviceId, currentTask, Convert.ToInt32(currentTask.PlcTaskId), (DeviceTaskTypeEnum)Enum.Parse(typeof(DeviceTaskTypeEnum), currentTask.TaskType.ToString()), currentTask.IsAllowSimulateExecute, out errMsg);
if (!isFinished) return;
////判断和堆垛机(或RGV)的连接任务是不是已经完成了
var queryTaskState1 = (int)DeviceTaskStatusEnum.未开始;
var queryTaskState2 = (int)DeviceTaskStatusEnum.已下发;
/*
//注释以下方法,因为出现了 某个任务MainTaskSequence 比他小,但是某个任务还未执行的问题 【EditBy shaocx,2022-04-28】
//同一个堆垛机的前面未结束的任务,且同种类型
var otherSrmTask = dbModel.Task_Part.Where(x => x.DeviceId == int_deviceId
&& x.Id != currentTask.Id
&& (x.TaskState == queryTaskState1 || x.TaskState == queryTaskState2)
&& x.CreateTime < currentTask.CreateTime
).FirstOrDefault();
if (otherSrmTask != null)
{
errMsg = "上一个堆垛机任务未完成,所以堆垛机任务不允许完成!上一个堆垛机任务号:" + otherSrmTask.PlcTaskId + ",本次堆垛机任务号:" + currentTask.PlcTaskId;
return;
}
//*/
//同一个关联任务的其他设备任务
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}任务未完成,所以堆垛机任务不允许完成!关联任务号:{1}", relevanceTask.DeviceName, relevanceTask.PlcTaskId);
return;
}
//4、处理任务完成状态
var isOk = ConfirmTaskFinishToSrm(currentTask, "堆垛机任务完成", exception);
if (isOk)
{
//堆垛机完成了当前任务后进行任务状态的修改
ChangeTaskStateWhenTaskFinish(currentTask);
dbModel.SaveChanges();
}
}
}
catch (Exception ex)
{
errMsg = "出现异常:" + ex.Message;
SysExceptionInfoHandler.GetExceptionInfoForError("自动结束堆垛机任务线程(线程)出现异常,deviceId:" + deviceId + ",异常:" + ex.Message, ex, ref exception);
SysExceptionInfoHandler.InsertExceptionInfo(exception, true);
}
}
///
/// 判断是人工发送给任务,单独给堆垛机发送任务完成信号
///
///
///
///
private bool ConfirmTaskFinishToSda(int deviceId, int taskId)
{
//任务完成处理成功,需要再给堆垛机发送任务完成确认信号
SdaResEntity sdaResult = new SdaResEntity();
try
{
sdaResult = new SrmService.SrmServiceClient().ConfirmTaskFinish(deviceId, taskId);
if (!sdaResult.result)
{
Log4NetHelper.WriteInfoLog(iWareCommon.Utils.LogType.DataProcess_BZ39_IssueInboundTask, "判断是人工发送的任务,单独给堆垛机发送任务完成信号,【失败】,设备号:" + deviceId + ",任务号:" + taskId);
return false;
}
else
{
Log4NetHelper.WriteInfoLog(iWareCommon.Utils.LogType.DataProcess_BZ39_IssueInboundTask, "判断是人工发送的任务,单独给堆垛机发送任务完成信号,【成功】,设备号:" + deviceId + ",任务号:" + taskId);
return true;
}
}
catch (Exception ex)
{
Log4NetHelper.WriteErrorLog(iWareCommon.Utils.LogType.DataProcess_BZ39_IssueInboundTask, "判断是人工发送的任务,单独给堆垛机发送任务完成信号,【异常】,设备号:" + deviceId + ",任务号:" + taskId + ",ex:" + ex.Message, ex);
throw ex;
}
}
#region 向堆垛机发送任务完成确认信号
///
/// 向堆垛机发送任务完成确认信号
///
///
///
///
///
private bool ConfirmTaskFinishToSrm(Task_Part currentTask, string business, Base_SysExceptionInfo exception)
{
//任务完成处理成功,需要再给堆垛机发送任务完成确认信号
SdaResEntity sdaResult = new SdaResEntity();
var log = TaskRequestLogHandler.GetTask(currentTask.Id,
(int)currentTask.DeviceId, currentTask.PlcTaskId, currentTask.RealSourcePlace.ToString(),
currentTask.RealToPlace.ToString(), "给堆垛机发送任务完成确信指令", "sys");
try
{
if (MyExtendHelper.IsAllowSimulatorHandle(currentTask))
{
sdaResult.result = true;
}
else
{
sdaResult = new SrmService.SrmServiceClient().ConfirmTaskFinish((int)currentTask.DeviceId, Convert.ToInt32(currentTask.PlcTaskId));
}
if (!sdaResult.result)
{
TaskRequestLogHandler.InsertTask(base.currentLogType, RequestStatusEnum.请求失败, JsonConvert.SerializeObject(sdaResult), log, null);
exception.exceptionMsg = string.Format(business + ",需要再给堆垛机发送任务完成确认信号失败,设备号{0} 任务号{1}", (int)currentTask.DeviceId, currentTask.PlcTaskId);
SysExceptionInfoHandler.InsertExceptionInfo(exception, true);
return false;
}
else
{
TaskRequestLogHandler.InsertTask(base.currentLogType, RequestStatusEnum.请求成功, JsonConvert.SerializeObject(sdaResult), log, null);
Log4NetHelper.WriteInfoLog(base.currentLogType, string.Format(business + ",再给堆垛机发送任务完成确认信号成功,设备号{0} 任务号{1}", (int)currentTask.DeviceId, currentTask.PlcTaskId));
return true;
}
}
catch (Exception ex)
{
TaskRequestLogHandler.InsertTask(base.currentLogType, RequestStatusEnum.请求失败, JsonConvert.SerializeObject(sdaResult), log, ex);
throw ex;
}
}
#endregion
#endregion
#endregion
#region 公共处理
///
/// 验证RGV站点上是否允许下发堆垛机新任务
///
///
///
///
///
/// true:允许,false:不允许
private bool ValidateIsAllowNewTaskForRgvStattion(DbModel model, DeviceTaskTypeEnum _DeviceTaskTypeEnum, string realToPlace, ref string errMsg)
{
MainInOutFlagEnum _MainInOutFlagEnum = GetMainInOutFlagForSrm(_DeviceTaskTypeEnum);
if (_MainInOutFlagEnum == MainInOutFlagEnum.出库)
{
//判断目标点是否有光电占用
var rgv_stationCode = model.Base_Station.Where(x => x.SrmStationCode == realToPlace).First();
var isGD_HasCatogryForRgvStattion = MyExtendHelper.IsGD_HasCatogryForRgvStattion(rgv_stationCode.RgvStationCode);
if (isGD_HasCatogryForRgvStattion)
{
errMsg = "RGV出库口站点" + rgv_stationCode.RgvStationCode + "上面光电显示有货,不允许下发堆垛机的出库任务";
return false;
}
}
return true;
}
///
/// 根据堆垛机任务类型判断出是出库还是入库
///
///
///
private MainInOutFlagEnum GetMainInOutFlagForSrm(DeviceTaskTypeEnum _DeviceTaskTypeEnum)
{
switch (_DeviceTaskTypeEnum)
{
case DeviceTaskTypeEnum.组盘入库:
case DeviceTaskTypeEnum.空托转运到立体库:
return MainInOutFlagEnum.入库;
case DeviceTaskTypeEnum.立库空托到拆盘机入口:
case DeviceTaskTypeEnum.出库:
return MainInOutFlagEnum.出库;
}
throw new Exception("堆垛机不支持的任务类型" + _DeviceTaskTypeEnum.ToString());
}
///
/// 更新主任务的状态
///
///
///
///
///
private void UpdateMainTaskStatus(DbModel edm, int mainTaskId, int srmTaskTypeValue, string remark)
{
DeviceTaskTypeEnum srmTaskTypeEnum = (DeviceTaskTypeEnum)Enum.Parse(typeof(DeviceTaskTypeEnum), srmTaskTypeValue.ToString());
MainTaskStatusEnum changeTaskStatus = default(MainTaskStatusEnum);
switch (srmTaskTypeEnum)
{
case DeviceTaskTypeEnum.组盘入库:
case DeviceTaskTypeEnum.空托转运到立体库:
changeTaskStatus = MainTaskStatusEnum.已完成;
MainTaskHandler.UpdateTaskStatus(edm, mainTaskId, changeTaskStatus, remark);
break;
}
}
///
/// 堆垛机任务完成后修改任务状态
///
///
private void ChangeTaskStateWhenTaskFinish(Task_Part currentTask)
{
//堆垛机完成了当前任务后进行任务状态的修改
currentTask.FinishTime = DateTime.Now;//完成时间
currentTask.IsFinished = true;
currentTask.TaskState = (int)DeviceTaskStatusEnum.已完成;
currentTask.TaskStateName = DeviceTaskStatusEnum.已完成.ToString();
currentTask.OperationRemark = "已完成";
currentTask.ModifyTime = DateTime.Now;
currentTask.ModifyBy = SysGloble.WCSSystem;
//currentTask.IsLastTask = (int)EYesOrNo.否;//设置不是最新的任务
}
///
/// 堆垛机任务完成后,根据堆垛机的任务类型去判断Base_Salver_V_Station 的State
///
/// 堆垛机任务类型
/// 原先的Base_Salver_V_Station 的State
///
private Salver_V_Station_StateEnum DeviceTaskTypeEnumToC_V_P_StateEnumWhenTaskFinish(DeviceTaskTypeEnum _DeviceTaskTypeEnum, int old_int_C_V_P_StateEnum)
{
Salver_V_Station_StateEnum old_C_V_P_StateEnum = (Salver_V_Station_StateEnum)Enum.Parse(typeof(Salver_V_Station_StateEnum), old_int_C_V_P_StateEnum.ToString());
Salver_V_Station_StateEnum _C_V_P_StateEnum = old_C_V_P_StateEnum;
switch (_DeviceTaskTypeEnum)
{
case DeviceTaskTypeEnum.组盘入库:
_C_V_P_StateEnum = Salver_V_Station_StateEnum.在库物料;
break;
//case DeviceTaskTypeEnum22.线下其他垛入库:
// _C_V_P_StateEnum = C_V_P_StateEnum.在库其他料;
// break;
//case DeviceTaskTypeEnum22.线下垫板垛入库:
// _C_V_P_StateEnum = C_V_P_StateEnum.在库垫板;
// break;
//case DeviceTaskTypeEnum22.成品料配板完成回库:
// _C_V_P_StateEnum = C_V_P_StateEnum.在库成品料;
// break;
//case DeviceTaskTypeEnum22.待拆垛回库:
// _C_V_P_StateEnum = C_V_P_StateEnum.在库待拆垛;
// break;
//case DeviceTaskTypeEnum22.桁架垫板垛入立库垫板库位:
//case DeviceTaskTypeEnum22.锯切垫板垛入立体库:
// _C_V_P_StateEnum = C_V_P_StateEnum.在库垫板;
// break;
//case DeviceTaskTypeEnum22.移库://移库,状态不变
//case DeviceTaskTypeEnum22.成品料上锯切线出库://成品料出库,状态不变
//case DeviceTaskTypeEnum22.垫板上料出库://垫板出库,状态不变
// _C_V_P_StateEnum = old_C_V_P_StateEnum;
// break;
//case DeviceTaskTypeEnum22.配板原料出库:
// _C_V_P_StateEnum = C_V_P_StateEnum.原料配板中;
// break;
//case DeviceTaskTypeEnum22.人工出库://出库后会将表Base_Salver_V_Station 清掉
// break;
}
return _C_V_P_StateEnum;
}
public override bool ValidateDeviceIsAllowSendTask(int int_deviceId, out string errMsg)
{
errMsg = "";
if (!base.ValidateDeviceIsAllowSendTask(int_deviceId, out errMsg))
{
return false;
}
if (FormCC.IsSimulationPLC)
{
return true;
}
using (var srmService = new SrmService.SrmServiceClient())
{
SdaResEntity sdaResult = srmService.IsAllowSendTask(int_deviceId, out errMsg);
if (sdaResult.result == false)
{
errMsg = "非自动、有任务未确认或有报警," + sdaResult.resMsg;
Log4NetHelper.WriteErrorLog(currentLogType, "验证堆垛机不可以下发新任务,int_deviceId:" + int_deviceId + ",sdaResultStr:" + JsonConvert.SerializeObject(sdaResult));
}
return sdaResult.result;
}
}
///
/// 验证堆垛机是否自动
///
///
///
public override bool ValidateDeviceIsOK(int int_deviceId, Task_Part _task, int taskId, out string errMsg)
{
errMsg = "";
if (Wms_EquipmentSituationHandler.IsEquipmentBreakdown(int_deviceId).result)
{//如果设备已经设定为 故障状态,不允许下发任务!!! [EditBy shaocx,2020-12-07]
errMsg = "设备被设为故障";
return false;
}
if (MyExtendHelper.IsAllowSimulatorHandle(_task))
{
errMsg = "模拟PLC";
return true;
}
using (var srmService = new SrmService.SrmServiceClient())
{
SdaResEntity sdaResult = srmService.IsReady(int_deviceId, out errMsg);
errMsg = sdaResult.resMsg;
return sdaResult.result;
}
}
///
/// 验证堆垛机是否任务完成
///
///
///
public override bool ValidateDeviceTaskIsFinsished(int int_deviceId, Task_Part _task, int taskId, out string errMsg)
{
errMsg = "";
if (MyExtendHelper.IsAllowSimulatorHandle(_task))
{//模拟代码!发布时移除该代码
errMsg = "任务要求强制模拟完成";
return true;
}
SdaResEntity sdaResult = new SrmService.SrmServiceClient().IsTaskFinish(int_deviceId, taskId);
if (sdaResult.result == false)
{
errMsg = sdaResult.resMsg;
}
return sdaResult.result;
}
///
/// 验证堆垛机是否任务完成
///
///
///
private bool ValidateDeviceTaskIsFinsished(int int_deviceId, Task_Part _task, int taskId, DeviceTaskTypeEnum _DeviceTaskTypeEnum, bool? isAllowSimulateExecute, out string errMsg)
{
errMsg = "";
if (MyExtendHelper.IsAllowSimulatorHandle(_task))
{
errMsg = "模拟PLC完成或任务要求强制模拟完成";
return true;
}
SdaResEntity sdaResult = new SrmService.SrmServiceClient().IsTaskFinish(int_deviceId, taskId);
if (sdaResult.result == false)
{
errMsg = "验证堆垛机是否任务完成 失败:" + JsonConvert.SerializeObject(sdaResult);
//Log4NetHelper.WriteErrorLog(currentLogType, "验证堆垛机是否任务完成 失败:" + JsonConvert.SerializeObject(sdaResult));
}
switch (_DeviceTaskTypeEnum)
{
//涉及到最后到输送线的任务,都要再加上输送线的任务是否完成
case DeviceTaskTypeEnum.组盘入库:
//using (var srmConveyorService = new SrmConveyorService.SrmConveyorServiceClient())
//{
// sdaResultStr = srmConveyorService.IsTaskFinish(taskId);
// sdaResult = JsonConvert.DeserializeObject(sdaResultStr);
// if (sdaResult.result == false)
// {
// errMsg = "验证输送线是否任务完成 失败:" + sdaResultStr;
// Log4NetHelper.WriteErrorLog(currentLogType, "验证输送线是否任务完成 失败:" + sdaResultStr);
// }
//}
break;
}
return sdaResult.result;
}
#endregion
#region 私有方法
///
/// 验证数据库中是否有任务要处理
///
///
///
/// Rgv设备号
///
///
///
private List ValidateIsExistTaskToDisposeForIssued(DbModel dbModel, int int_deviceId, out string errMsg)
{
errMsg = "";
List partList = new List();
//看同一个设备,是否还有其他正在执行的任务!
var partTask = dbModel.Task_Part.Where(x => x.DeviceId == int_deviceId && x.TaskState == (int)DeviceTaskStatusEnum.已下发).
OrderBy(x => x.CreateTime).FirstOrDefault();//按照主任务的顺序升序
if (partTask != null)
{
errMsg = string.Format("deviceId={0}的正在执行任务,任务ID:" + partTask.Id + ",主任务:" + partTask.MainTaskNo + ",PLC任务号:" + partTask.PlcTaskId, int_deviceId);
return null;
}
//1、查询
var currTaskList = dbModel.Task_Part.Where(x => x.DeviceId == int_deviceId && x.TaskState == (int)DeviceTaskStatusEnum.未开始).ToList().OrderBy(x => x.CreateTime).ToList();//按照主任务优先级的升序排序
if (currTaskList == null || currTaskList.Count == 0)
{
errMsg = "没有需要处理的任务";
return null;
}
var firstTask = currTaskList.First();//第一个待执行的任务
partList.Add(firstTask);
//判断如果这个任务是出库任务的话,就再查询第一个待执行的入库任务
DeviceTaskTypeEnum _DeviceTaskTypeEnum = (DeviceTaskTypeEnum)Enum.Parse(typeof(DeviceTaskTypeEnum), firstTask.TaskType.ToString());
//查询 出库和入库的两个任务,优先执行出库任务 【EditBy shaocx,2022-05-09】
MainInOutFlagEnum _MainInOutFlagEnum = GetMainInOutFlagForSrm(_DeviceTaskTypeEnum);
if (_MainInOutFlagEnum == MainInOutFlagEnum.出库)
{
//查询第一个待执行的入库任务
var queryInOutFlag = (int)MainInOutFlagEnum.入库;
var fisrtTaskForIn = currTaskList.Where(x => x.InOutFlag == queryInOutFlag).ToList().OrderBy(x => x.CreateTime).FirstOrDefault();
if (fisrtTaskForIn != null)
{
partList.Add(fisrtTaskForIn);
}
}
return partList;
}
#endregion
}
}