using iWareCommon; using iWareCommon.Utils; using iWareSql; using System; using System.Collections.Generic; using System.Threading; using System.Linq; using iWareSql.Orm; using System.Threading.Tasks; using Newtonsoft.Json; using iWareSql.DataAccess; using iWareModel; namespace iWareCC { /// /// 立库输送线任务服务线程类 /// public class ConveyorThreadService : DeviceThreadServiceHandle { //private static string _namespace = "iWareCC.ConveyorThreadService"; //private ConveyorThreadService() { } //public ConveyorThreadService(LogType logType) //{ // base.currentLogType = logType; //} //public void StartService() //{ // Task.Run(() => // { // try // { // //自动执行立库输送线任务线程 // Log4NetHelper.WriteInfoLog(base.currentLogType, "[自动执行立库输送线任务线程] 启动了"); // ThreadHelper.StartThread(new Thread(new ParameterizedThreadStart(DoConveyorsTask)), (int)EDeviceId222.立库输送线); // //自动结束立库输送线任务线程 // ThreadHelper.StartThread(new Thread(new ParameterizedThreadStart(FinishTask)), (int)EDeviceId222.立库输送线); // } // catch (Exception ex) // { // Log4NetHelper.WriteErrorLog(base.currentLogType, "ConveyorThreadService线程启动出现异常", ex); // } // }); //} //#region 线程处理 //#region 自动执行立库输送线任务线程 ///// ///// 自动执行立库输送线任务 ///// ///// //private void DoConveyorsTask(object deviceId) //{ // string errMsg = ""; // while (true) // { // if (SystemValue.isAllowRuning_ConveyorsTaskThreadService && SystemValue.isStartedModel) // { // DoConveyorsTaskByThead(deviceId, out errMsg); // } // SystemWarningMsg._lbl_Alert_ConveyorsRelease = errMsg; // Thread.Sleep(cycleDelay); // } //} ///// ///// 自动执行立库输送线任务(线程) ///// ///// //private void DoConveyorsTaskByThead(object deviceId, out string errMsg) //{ // errMsg = ""; // string logHeader = "方法:DoConveyorsTaskByThead,参数deviceId:" + deviceId.ToString() + "==="; // #region 新增异常信息表 【EditBy shaocx,2020-01-20】 // IDictionary logDict = new Dictionary(); // logDict.Add("deviceId", deviceId); // UDT_SYS_ExceptionInfo exception = ExceptionHandels.GetExceptionInfo>(base.currentLogType, _namespace, "DoConveyorsTaskByThead", logDict); // #endregion // try // { // /* // * 执行发送给立库输送线的指令任务 // * 1、验证根据设备号是否找到立库输送线 // * 2、判断设备是否属于任务完成,如果属于任务完成,就继续走3 // * 3、判断数据库中是否有可要下发的任务,如果有就下发+验证起始点和目标点是否正确 // * 4、下发成功后,更新任务状态 // */ // int int_deviceId = (int)deviceId; // //1、验证根据设备号是否找到立库输送线 // SrmConveyorEntity deviceEntity = null; // deviceEntity = ValidateIsExistDevice(int_deviceId); // if (deviceEntity == null) return; // //暂时记录文本日志,正式环境要去掉 // TestStruct.WriteTempLog(base.currentLogType, logHeader + "执行结束ValidateIsExistDevice,根据设备号找到了输送线"); // //2、判断设备是否属于空闲,如果属于空闲,就继续走2 // bool isOk = ValidateDeviceIsOK((int)EDeviceId222.立库输送线, 0, out errMsg); // //暂时记录文本日志,正式环境要去掉 // TestStruct.WriteTempLog(base.currentLogType, logHeader + "执行结束ValidateDeviceIsOK,输送线是否可以接受任务:" + isOk); // if (!isOk) return; // using (Edm dbModel = new Edm()) // { // #region //3、判断数据库中是否有可要下发的任务,如果有就下发 // var currentTask = ValidateIsExistTaskToDispose(dbModel, int_deviceId, out errMsg, TaskExcuteTypeEnum.执行任务); // if (currentTask == null) // {//表示DB中没有任务要发送给立库输送线 // //暂时记录文本日志,正式环境要去掉 // TestStruct.WriteTempLog(base.currentLogType, logHeader + "执行ValidateIsExistTaskToDispose完,表示DB中没有任务要发送给立库输送线"); // return; // } // //判断输送线任务是否可以允许下发开始任务 // var isAllowStatrt = ValidateDeviceTaskIsAllowStart(currentTask, dbModel); // if (!isAllowStatrt) // {//防止过早给输送线发任务,导致输送线超时 // return; // } // //验证起始点和目标点是否正确 // RealPlaceEntity realPlaceEntity = null; // if (!ValdiatePalceIsRight(dbModel, (int)currentTask.SourcePlace, (int)currentTask.ToPlace, ref realPlaceEntity)) return; // //暂时记录文本日志,正式环境要去掉 // TestStruct.WriteTempLog(base.currentLogType, logHeader + "执行ValdiatePalceIsRight完,验证起始点和目标点正确,任务是srmTask的ID:" + currentTask.TackId); // //下发 // //注意:第四个参数没有值 // var barcode = "1";//二维码写死位1 // var log = ConveyorTaskRequestLogHandles.GetTask(currentTask.TackId, // currentTask.DeviceId.ToString(), currentTask.PlcTaskId, currentTask.RealSourcePlace.ToString(), // currentTask.RealToPlace.ToString(), "给立库输送线发送任务指令", "sys"); // SdaResEntity sdaResult = new SdaResEntity(); // try // { // if (WCSConfigHelper.GetConfig_IsSimulationPLC()) // { // sdaResult.result = true; // } // else // { // String sdaResultStr = new SrmConveyorService.SrmConveyorServiceClient().SendSrmTransTask(int_deviceId, Convert.ToInt32(currentTask.PlcTaskId), Convert.ToInt32(currentTask.RealSourcePlace), Convert.ToInt32(currentTask.RealToPlace), barcode); // sdaResult = JsonConvert.DeserializeObject(sdaResultStr); // } // if (sdaResult.result == false) // {//给立库输送线下发指令失败 // exception.exceptionMsg = string.Format("发送指令给立库输送线失败,设备号{0},任务ID{1},起始位{2},目标位{3},errMsg{4}", int_deviceId, currentTask.PlcTaskId, currentTask.RealSourcePlace.ToString(), currentTask.RealToPlace.ToString(), errMsg); // ExceptionHandels.InsertExceptionInfo(exception, true); // ConveyorTaskRequestLogHandles.InsertTask(base.currentLogType, RequestStatusEnum.请求失败, JsonConvert.SerializeObject(sdaResult), log, null); // return; // } // else // { // ConveyorTaskRequestLogHandles.InsertTask(base.currentLogType, RequestStatusEnum.请求成功, JsonConvert.SerializeObject(sdaResult), log, null); // } // } // catch (Exception ex) // { // ConveyorTaskRequestLogHandles.InsertTask(base.currentLogType, RequestStatusEnum.请求失败, JsonConvert.SerializeObject(sdaResult), log, ex); // ExceptionHandels.GetExceptionInfoForError("给立库输送线发送任务指令出现异常,deviceId:" + deviceId + ",异常:" + ex.Message, ex, ref exception); // ExceptionHandels.InsertExceptionInfo(exception, true); // return; // } // #endregion // //4、下发成功后,更新任务状态 // currentTask.IsReleased = (int)EYesOrNo.是; // currentTask.UpdateTime = DateTime.Now; // currentTask.TaskState = (int)ETaskStatus.已下发; // currentTask.IssueTime = DateTime.Now;//下发时间 // //只更新着三个字段! // //更新 进出库记录表的时间 // var srm_InOutStoreRecord = dbModel.Srm_InOutStoreRecord.Where(x => x.TaskGuid == currentTask.TaskGuid).FirstOrDefault(); // if (srm_InOutStoreRecord != null) // { // srm_InOutStoreRecord.TaskStartTime = DateTime.Now; // srm_InOutStoreRecord.LastModifyTime = DateTime.Now; // srm_InOutStoreRecord.LastModifier = "输送机任务下发"; // srm_InOutStoreRecord.Remark = "输送机任务下发"; // } // /* // //如果任务类型是配板原料入库,需要更新 mes的上料清单表 // ConveyorTaskTypeEnum _ConveyorTaskTypeEnum = (ConveyorTaskTypeEnum)Enum.Parse(typeof(ConveyorTaskTypeEnum), currentTask.TaskType.ToString()); // switch (_ConveyorTaskTypeEnum) // { // case ConveyorTaskTypeEnum.配板原料入库: // if (!string.IsNullOrEmpty(currentTask.ToNumber)) // { // } // break; // default: // break; // } // //*/ // dbModel.SaveChanges(); // } // } // catch (Exception ex) // { // ExceptionHandels.GetExceptionInfoForError("自动执行立库输送线任务(线程)出现异常,deviceId:" + deviceId + ",异常:" + ex.Message, ex, ref exception); // ExceptionHandels.InsertExceptionInfo(exception, true); // } //} //#endregion //#region 自动结束立库输送线任务线程 ///// ///// 自动结束立库输送线任务线程 ///// ///// //private void FinishTask(object deviceId) //{ // string errMsg = ""; // while (true) // { // if (SystemValue.isAllowRuning_ConveyorsTaskThreadService_Finish && SystemValue.isStartedModel) // { // FinishConveyorTaskByThead(deviceId, out errMsg); // } // SystemWarningMsg._lbl_Alert_ConveyorsReleaseFinish = errMsg; // Thread.Sleep(cycleDelay); // } //} ///// ///// 自动结束立库输送线任务线程(线程) ///// ///// //public void FinishConveyorTaskByThead(object deviceId, out string errMsg) //{ // errMsg = ""; // #region 新增异常信息表 【EditBy shaocx,2020-01-20】 // IDictionary logDict = new Dictionary(); // logDict.Add("deviceId", deviceId); // UDT_SYS_ExceptionInfo exception = ExceptionHandels.GetExceptionInfo>(base.currentLogType, _namespace, "FinishConveyorTaskByThead", logDict); // #endregion // try // { // /* // * 执行发送给立库输送线的指令任务 // * 1、验证根据设备号是否找到立库输送线 // * 2、判断设备是否属于任务完成,如果属于任务完成,就继续走3 // * 3、判断数据库中是否有可要完成的任务,如果有判断是否跟立库输送线中的完成任务相符,如果相符就处理 // * 4、更新任务状态 // */ // int int_deviceId = (int)deviceId; // //1、验证根据设备号是否找到立库输送线 // SrmConveyorEntity srmEntity = null; // srmEntity = ValidateIsExistDevice(int_deviceId); // if (srmEntity == null) return; // //注意:这里不需要判断设备是否完成,直接就结束任务 // /* // 2、判断设备是否属于任务完成,如果属于任务完成,就继续走2 // var isTaskFinished = ValidateSrmDeviceTaskIsFinsished(int_deviceId); // if (!isTaskFinished) return; // //*/ // using (Edm dbModel = new Edm()) // { // #region //3、判断数据库中是否有可要完成的任务,如果有判断是否跟立库输送线中的完成任务相符,如果相符就处理 // var currentTask = ValidateIsExistTaskToDispose(dbModel, int_deviceId, out errMsg, TaskExcuteTypeEnum.结束任务); // if (currentTask == null) // {//表示DB中没有任务要发送给立库输送线 // return; // } // #endregion // //输送线的完成,要判断和他绑定的堆垛机的任务是否完成 // var isAllowFinish = ValidateDeviceTaskIsAllowFinsished(currentTask, dbModel); // if (!isAllowFinish) // {//不允许执行结束 // return; // } // using (var trans = dbModel.Database.BeginTransaction()) // { // try // { // //4、更新任务状态 // currentTask.FinishTime = DateTime.Now;//完成时间 // currentTask.IsFinished = (int)EYesOrNo.是; // currentTask.TaskState = (int)ETaskStatus.已完成; // currentTask.UpdateTime = DateTime.Now; // //如果是出库任务,需要更改库存 [EditBy shaocx,2020-10-22] // if (currentTask.TaskType == (int)ConveyorTaskTypeEnum.人工出库) // { // var cvp = CvP_Handles.GetCVPByPlaceId(dbModel, Convert.ToInt32(currentTask.SourcePlace)); // cvp.PlaceId = (int)currentTask.ToPlace; // cvp.LastModifier = "输送线任务完成线程"; // cvp.UpdateTime = DateTime.Now; // cvp.Remark = "输送线任务完成线程,更改CVP的库位"; // } // //注意:输送线任务完成,不需要给输送线发完成确认指令,因为输送线由多个节点组成!!!! // /* // //任务完成处理成功,需要再给堆垛机发送任务完成确认信号 // bool isSendFinish = new iWareSda.ConveyorService.SrmConveyorService().SendTaskFinishConfirm(Convert.ToInt32(currentTask.PlcTaskId)); // if (!isSendFinish) // { // throw new Exception(string.Format("任务完成处理成功,需要再给立库输送线发送任务完成确认信号失败, 任务号{0}", currentTask.PlcTaskId)); // } // //*/ // dbModel.SaveChanges(); // trans.Commit(); // } // catch (Exception) // { // trans.Rollback(); // throw; // } // } // } // } // catch (Exception ex) // { // ExceptionHandels.GetExceptionInfoForError("自动结束立库输送线任务线程(线程)出现异常,deviceId:" + deviceId + ",异常:" + ex.Message, ex, ref exception); // ExceptionHandels.InsertExceptionInfo(exception, true); // } //} //#endregion //#endregion //#region 公共处理 ///// ///// 验证立库输送线是否可以接受任务 ///// ///// 设备号,不需要 ///// 任务号,需要 ///// //public override bool ValidateDeviceIsOK(int int_deviceId, int taskId, out string errMsg) //{ // errMsg = ""; // // 立库输送线没有所谓的空闲状态,有任务直接发即可 // if (SrmEquipmentSituationHandels222.IsEquipmentBreakdown(int_deviceId).result) // {//如果设备已经设定为 故障状态,不允许下发任务!!! [EditBy shaocx,2020-12-07] // return false; // } // return true; //} ///// ///// 验证立库输送线是否任务完成 ///// ///// ///// 0表示没有任务完成,其他表示任务完成,并返回任务号 //public override bool ValidateDeviceTaskIsFinsished(int int_deviceId, int taskId,out string errMsg) //{ // errMsg = ""; // String sdaResultStr = new SrmConveyorService.SrmConveyorServiceClient().IsTaskFinish(taskId); // SdaResEntity sdaResult = JsonConvert.DeserializeObject(sdaResultStr); // if (sdaResult.result == false) // { // errMsg = sdaResult.resMsg; // } // return sdaResult.result; // //*/ //} ///// ///// 验证立库输送线是否允许任务完成 ///// ///// ///// 0表示没有任务完成,其他表示任务完成,并返回任务号 //public bool ValidateDeviceTaskIsAllowFinsished(Conveyor_Task task, Edm edm) //{ // Srm_Task srmTask = null; // var queryTaskStatus_HasIssue = (int)ETaskStatus.已下发; // var queryTaskStatus_Finish = (int)ETaskStatus.已完成; // ConveyorTaskTypeEnum taskType = (ConveyorTaskTypeEnum)Enum.Parse(typeof(ConveyorTaskTypeEnum), task.TaskType.ToString()); // switch (taskType) // { // case ConveyorTaskTypeEnum.配板原料入库: // case ConveyorTaskTypeEnum.线下配板原料入库: // //要判断和他同一个任务的堆垛机任务是不是已经发送任务了,任务状态是 进行中或已完成,如果是就允许完成,如果不是,就不允许完成 // srmTask = edm.Srm_Task.Where(x => x.TaskGuid == task.TaskGuid && ( // x.TaskState == queryTaskStatus_HasIssue || x.TaskState == queryTaskStatus_Finish // )).FirstOrDefault(); // if (srmTask != null) // { // return true; // } // break; // case ConveyorTaskTypeEnum.人工出库: // //要判断和他同一个任务的堆垛机任务是不是已经已完成,如果是就允许完成,如果不是,就不允许完成 // srmTask = edm.Srm_Task.Where(x => x.TaskGuid == task.TaskGuid && ( // x.TaskState == queryTaskStatus_Finish // )).FirstOrDefault(); // if (srmTask != null) // { // return true; // } // break; // } // return false; //} ///// ///// 验证立库输送线是否允许任务开始 ///// ///// ///// 0表示没有任务完成,其他表示任务完成,并返回任务号 //public bool ValidateDeviceTaskIsAllowStart(Conveyor_Task task, Edm edm) //{ // Srm_Task srmTask = null; // var queryTaskStatus_Finish = (int)ETaskStatus.已完成; // ConveyorTaskTypeEnum taskType = (ConveyorTaskTypeEnum)Enum.Parse(typeof(ConveyorTaskTypeEnum), task.TaskType.ToString()); // switch (taskType) // { // default: // return true; // case ConveyorTaskTypeEnum.人工出库: // //要判断和他同一个任务的堆垛机任务是不是已经已完成,如果是就允许开始任务,如果不是,就不允许开始 // srmTask = edm.Srm_Task.Where(x => x.TaskGuid == task.TaskGuid && ( // x.TaskState == queryTaskStatus_Finish // )).FirstOrDefault(); // if (srmTask != null) // { // return true; // } // break; // } // return false; //} ///// ///// 验证根据设备号是否找到立库输送线 ///// ///// ///// //public override SrmConveyorEntity ValidateIsExistDevice(int int_deviceId) //{ // iWareCC.SrmConveyorService.SrmConveyorEntity item = new SrmConveyorService.SrmConveyorServiceClient().GetSrmConveyorInfo(int_deviceId); // var isExist = item.DeviceId == int_deviceId; // if (!isExist) // { // Log4NetHelper.WriteErrorLog(base.currentLogType, "未找到立库输送线deviceId=" + int_deviceId); // } // return (SrmConveyorEntity)(object)item; //} ///// ///// 验证数据库中是否有任务要处理 ///// ///// ///// ///// 立库输送线设备号 ///// ///// ///// //public override Conveyor_Task ValidateIsExistTaskToDispose(Edm dbModel, int int_deviceId, out string errMsg, TaskExcuteTypeEnum _TaskExcuteTypeEnum) //{ // errMsg = ""; // iWareSql.Orm.Conveyor_Task currTask = null; // switch (_TaskExcuteTypeEnum) // { // case TaskExcuteTypeEnum.执行任务: // var process_count = dbModel.Conveyor_Task.Where(x => x.DeviceId == int_deviceId && x.TaskState == (int)ETaskStatus.已下发).ToList().Count; // if (process_count > 0) // { // errMsg = string.Format("deviceId={0}的正在执行任务", int_deviceId); // return default(Conveyor_Task); // } // currTask = dbModel.Conveyor_Task.Where(x => x.DeviceId == int_deviceId && x.TaskState == (int)ETaskStatus.未开始).ToList().OrderBy(x => x.TackId).FirstOrDefault(); // break; // case TaskExcuteTypeEnum.结束任务: // currTask = dbModel.Conveyor_Task.Where(x => x.DeviceId == int_deviceId && x.TaskState == (int)ETaskStatus.已下发).ToList().OrderBy(x => x.TackId).FirstOrDefault(); // break; // } // return (Conveyor_Task)(object)currTask; //} //#endregion } }