using iWareCommon; using iWareCommon.Common.Globle; using iWareCommon.Utils; using iWareModel; using iWareSql; using iWareSql.DataAccess; using iWareSql.DBModel; using iWareSql.Orm; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using XiGang.Core.Model; namespace iWareCC { /// /// 设备线程服务 /// public class DeviceThreadServiceHandle { private static string _namespace = "iWareSda.DeviceThreadService"; public LogType currentLogType = default(LogType); /// /// 线程休眠的时间(毫秒) /// public int cycleDelay = 5000;//100,暂时 改成每次5秒一次循环 #region 启动服务 /// /// 启动服务 /// public virtual void StartService() { } #endregion #region 下发任务线程 /// /// 下发设备任务线程 /// /// public void IssueTaskThread(EDevice x) { ThreadHelper.StartThread(new Thread(new ParameterizedThreadStart(IssueTask)), (int)x); } /// /// 下发设备任务 /// /// public virtual void IssueTask(object deviceId) { } /// /// 下发设备任务处理 /// /// public virtual void IssueTaskHandle(int deviceId, out string errMsg) { errMsg = ""; } #endregion #region 任务完成确认线程 /// /// 任务完成确认线程 /// /// public void ConfirmFinishTaskThread(EDevice x) { ThreadHelper.StartThread(new Thread(new ParameterizedThreadStart(ConfirmFinishTask)), (int)x); } /// /// 任务完成确认 /// /// public virtual void ConfirmFinishTask(object deviceId) { } /// /// 任务完成确认处理 /// /// public virtual void ConfirmFinishTaskHandle(int deviceId, out string errMsg) { errMsg = ""; } #endregion #region 确认任务完成线程 #endregion #region 验证 /// /// 验证设备是否可以下发新任务 /// /// /// public virtual bool ValidateDeviceIsAllowSendTask(int int_deviceId, out string errMsg) { errMsg = ""; EDevice device = (EDevice)Enum.Parse(typeof(EDevice), int_deviceId.ToString()); if (Wms_EquipmentSituationHandler.IsEquipmentBreakdown(int_deviceId).result) {//如果设备已经设定为 故障状态,不允许下发任务!!! [EditBy shaocx,2020-12-07] errMsg = device.ToString() + "被设定为故障状态,不允许下发新任务"; return false; } return true; } /// /// 验证设备是否可以下发新任务 /// /// /// public virtual bool ValidateDeviceIsAllowSendTask(int int_deviceId, Task_Part task, out string errMsg) { errMsg = ""; return true; } /// /// 验证目标点是否已经有库存! /// /// /// public virtual bool ValidateIsHasStoreForToPlace(int int_deviceId, int placeId, string placeNo, out string errMsg) { errMsg = ""; EDevice device = (EDevice)Enum.Parse(typeof(EDevice), int_deviceId.ToString()); //增加验证-验证目标点是否有库存,如果有库存,则不允许下发新任务 【EditBy shaocx,2022-04-15】 using (DbModel edm = new DbModel()) { var store = StoreHandler.GetV_AllStoreByPlaceId(edm, placeId); if (store != null) { errMsg = "目标点" + placeNo + "系统显示已经有货,不允许给" + device.ToString() + "下发新任务,货物类型:" + store.MaterialTypeName + ",货物托盘号:" + store.SalverCode; return false; } } return true; } /// /// 验证前面存在同一个起点、目标点的任务 /// /// /// /// /// true:验证通过,false:验证不通过 public virtual bool ValidateIsHasNoFinishedSameTask(int int_deviceId, Task_Part part, out string errMsg) { errMsg = ""; EDevice device = (EDevice)Enum.Parse(typeof(EDevice), int_deviceId.ToString()); using (DbModel edm = new DbModel()) { var queryState1 = (int)DeviceTaskStatusEnum.已取消; var queryState2 = (int)DeviceTaskStatusEnum.已完成; var partList = edm.Task_Part.Where(x => x.Id != part.Id && x.DeviceId == int_deviceId //&& x.MainTaskSequence <= part.MainTaskSequence && x.CreateTime < part.CreateTime && x.SourcePlace == part.SourcePlace && x.ToPlace == part.ToPlace && x.TaskState != queryState1 && x.TaskState != queryState2 ).ToList(); if (partList != null && partList.Count > 0) { errMsg = "前面存在同一个起点、目标点的任务,不允许给" + device.ToString() + "下发新任务:" + part.PlcTaskId; return false; } } return true; } /// /// 验证设备是否可以接受任务 /// /// /// public virtual bool ValidateDeviceIsOK(int int_deviceId, Task_Part _task, int taskId, out string errMsg) { errMsg = ""; return true; } /// /// 验证根据设备号是否能找到设备 /// /// /// public virtual T ValidateIsExistDevice(int int_deviceId) { return default(T); } /// /// 验证设备是否任务完成 /// /// /// public virtual bool ValidateDeviceTaskIsFinsished(int int_deviceId, Task_Part _task, out string errMsg) { errMsg = ""; return false; } /// /// 验证设备是否任务完成 /// /// /// 0表示没有任务完成,其他表示任务完成,并返回任务号 public virtual bool ValidateDeviceTaskIsFinsished(int int_deviceId, Task_Part _task, int taskId, out string errMsg) { errMsg = ""; return false; } /// /// 验证设备是否任务完成 /// /// /// 0表示没有任务完成,其他表示任务完成,并返回任务号 public virtual bool ValidateDeviceTaskIsFinsished(int int_deviceId, Task_Part _task, int taskId, bool? isAllowSimulateExecute, out string errMsg) { errMsg = ""; return false; } /// /// 验证起点和终点是否正确 /// /// /// 起始点的主键ID /// 目标点的主键ID /// public bool ValdiatePalceIsRight(DbModel dbModel, int sourcePlace, int toPlace, ref RealPlaceEntity realPlaceEntity) { #region 新增异常信息表 【EditBy shaocx,2020-01-20】 IDictionary logDict = new Dictionary(); logDict.Add("sourcePlace", sourcePlace); logDict.Add("toPlace", toPlace); Base_SysExceptionInfo exception = SysExceptionInfoHandler.GetExceptionInfo>(currentLogType, _namespace, "ValdiatePalceIsRight", logDict); #endregion try { var db_fromPlace = dbModel.Base_Station.FirstOrDefault(x => x.Id.ToString() == sourcePlace.ToString()); var db_toPlace = dbModel.Base_Station.FirstOrDefault(x => x.Id.ToString() == toPlace.ToString()); if (db_fromPlace == null) { exception.exceptionMsg = "起点'" + sourcePlace + "'没有找到"; SysExceptionInfoHandler.InsertExceptionInfo(exception, true); return false; } if (db_toPlace == null) { exception.exceptionMsg = "终点'" + toPlace + "'没有找到"; SysExceptionInfoHandler.InsertExceptionInfo(exception, true); return false; } realPlaceEntity = new RealPlaceEntity(); realPlaceEntity.real_sourcePlace = db_fromPlace; realPlaceEntity.real_toPlace = db_toPlace; return true; } catch (Exception ex) { SysExceptionInfoHandler.GetExceptionInfoForError("验证起点和终点是否正确出现异常:" + ex.Message, ex, ref exception); SysExceptionInfoHandler.InsertExceptionInfo(exception); throw; } } /// /// 验证数据库中是否有任务要处理 /// /// 设备号 /// public virtual T ValidateIsExistTaskToDispose(DbModel dbModel, int int_deviceId, out string errMsg, TaskExcuteTypeEnum _TaskExcuteTypeEnum) { errMsg = ""; return default(T); } /// /// 验证数据库中是否有任务要处理 /// /// /// /// Rgv设备号 /// /// /// public Task_Part ValidateIsExistTaskToDispose(DbModel dbModel, int int_deviceId, out string errMsg, TaskExcuteTypeEnum _TaskExcuteTypeEnum) { errMsg = ""; iWareSql.DBModel.Task_Part currTask = null; switch (_TaskExcuteTypeEnum) { case TaskExcuteTypeEnum.执行任务: //看同一个设备,是否还有其他正在执行的任务! 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 default(Task_Part); } currTask = dbModel.Task_Part.Where(x => x.DeviceId == int_deviceId && x.TaskState == (int)DeviceTaskStatusEnum.未开始).ToList().OrderBy(x => x.CreateTime).FirstOrDefault();//按照主任务优先级的升序排序 break; case TaskExcuteTypeEnum.结束任务: currTask = dbModel.Task_Part.Where(x => x.DeviceId == int_deviceId && x.TaskState == (int)DeviceTaskStatusEnum.已下发).ToList().OrderBy(x => x.CreateTime).FirstOrDefault();//按照主任务优先级的升序排序 break; } return currTask; } /// /// 当设备任务完成后,验证站点是否有其他任务被占用 /// /// /// /// 本次任务排除 /// public bool ValdiatePalceIsUsedByTask(DbModel dbModel, int placeId, string excludeTaskId) { try { var queryState1 = (int)DeviceTaskStatusEnum.已取消; var queryState2 = (int)DeviceTaskStatusEnum.已完成; int srmCount = dbModel.Task_Part.Count(x => x.TaskState != queryState1 && x.TaskState != queryState2 && (x.SourcePlace == placeId || x.ToPlace == placeId) && x.Id != excludeTaskId); if (srmCount > 0) { return false; } int rgvCount = dbModel.Task_Part.Count(x => x.TaskState != queryState1 && x.TaskState != queryState2 && (x.SourcePlace == placeId || x.ToPlace == placeId) && x.Id != excludeTaskId); if (rgvCount > 0) { return false; } return true; } catch (Exception ex) { throw; } } #endregion /// /// 当设备任务结束时,更新库位的状态(任务占用、锁定) /// /// /// /// /// /// public void UpdateStationLockInfoWhenFinished(DbModel dbModel, Base_Station sourcePlace, Base_Station toPlace, string excludeTaskId, string remark) { #region 变更库位状态(任务占用、锁定) //目标的库位状态 if (ValdiatePalceIsUsedByTask(dbModel, toPlace.Id, excludeTaskId)) {//没有其他任务占用 toPlace.IsHasTaskDoing = false; StationHandler.SetPlaceLockStatus(false, SysGloble.WCSSystem, ref toPlace, remark); } if (ValdiatePalceIsUsedByTask(dbModel, sourcePlace.Id, excludeTaskId)) {//没有其他任务占用 sourcePlace.IsHasTaskDoing = false; StationHandler.SetPlaceLockStatus(false, SysGloble.WCSSystem, ref sourcePlace, remark); } #endregion } /// /// 当设备任务完成后,转移库存 /// /// /// /// /// public void TransferStoreWhenFinished(Task_Part partTask, DbModel dbModel, string salverId, Base_Station toPlace, string remark, DeviceTaskTypeEnum taskType, EDeviceType _EDeviceType) { #region 2、解除来源位置的托盘和库位的绑定关系 和绑定目标的CVP关系(注意:一定要在最后面执行!!) //解除CVP的关系 //绑定目标的CVP关系 Base_Salver_V_Station cvp = dbModel.Base_Salver_V_Station.Where(o => o.SalverId == salverId).FirstOrDefault(); if (cvp == null) { throw new Exception(string.Format("根据salverId{0}没有找到库位和托盘的关联信息!", salverId)); } //增加验证 【EditBy shaocx,2022-05-15】 Base_Salver_V_Material svm = dbModel.Base_Salver_V_Material.Where(o => o.SalverId == salverId).FirstOrDefault(); if (svm == null) { throw new Exception(string.Format("根据salverId{0}没有找到物料和托盘的关联信息!", salverId)); } //库位和托盘已有绑定关系 将托盘库位关系集合中第一个库位号设置为当前入库任务的目标库位 cvp.StationId = (int)toPlace.Id; cvp.StationCode = toPlace.SrmStationCode; //cvp.Old_State = cvp.State;//保存旧状态 [EditBy shaocx,20202-12-02] //var newState = DeviceTaskTypeEnumToC_V_P_StateEnumWhenTaskFinish(taskType, (int)cvp.State); //cvp.State = Convert.ToInt32(newState); //cvp.StateName = newState.ToString(); cvp.ModifyTime = DateTime.Now; cvp.ModifyBy = SysGloble.WCSSystem; cvp.OperationRemark = remark + ",重新绑定新的CVP关系"; //如果是入库,就记录入库时间 if (_EDeviceType == EDeviceType.堆垛机) { switch (taskType) { case DeviceTaskTypeEnum.组盘入库: case DeviceTaskTypeEnum.空托转运到立体库: var inTime = DateTime.Now; cvp.InStoreTime = inTime; //记录主表的入库时间 var mainTask = dbModel.Task_Main.Where(x => x.TaskNo == partTask.MainTaskNo).First(); mainTask.InStoreTime = inTime; break; } } #endregion } #region 获取指定任务阶段的某个设备的所有任务列表 /// /// 获取指定任务阶段的某个设备的所有任务列表 /// /// /// /// /// public List GetPartListByDevice(DbModel dbModel, int int_deviceId, TaskExcuteTypeEnum _TaskExcuteTypeEnum) { switch (_TaskExcuteTypeEnum) { case TaskExcuteTypeEnum.执行任务: return dbModel.Task_Part.Where(x => x.DeviceId == int_deviceId && x.TaskState == (int)DeviceTaskStatusEnum.未开始).ToList().OrderBy(x => x.CreateTime).ToList();//按照主任务的顺序升序 case TaskExcuteTypeEnum.结束任务: return dbModel.Task_Part.Where(x => x.DeviceId == int_deviceId && x.TaskState == (int)DeviceTaskStatusEnum.已下发).ToList().OrderBy(x => x.CreateTime).ToList();//按照主任务的顺序升序 default: return null; } } #endregion } }