using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using WCS.Data; using WCS.Data.Models; using WCS.Data.Utils; using WCS.PLC.Model.Equipment; namespace WCS.PLC { public class Base_Srm2 : Base_EquPlc { private int task_no_Last = 0;//上一次的任务号 private readonly string SrmOutInInfo_in = "in"; private readonly string SrmOutInInfo_out = "out"; private readonly string SrmOutInInfo_outIn = "outIn"; private readonly string WriteSrmSignalException = "520写入取放货信号失败"; private readonly string WriteSrmTriggerException = "520写入触发信号失败"; #region Properties /// /// 任务要执行的当前路由信息 /// //protected WCS_EQUIPMENTROUTE CurrentRoute { get; set; } /// /// 堆垛机信号 /// protected SrmSignal EquSignal { get { return WCS_PLCItem.WCS_EquipmentInfoSet[0].EquSignal_Srm; } } /// /// 写入DB名称 /// protected int WriteDbName { get { return WCS_PLCItem.WCS_DBSet[0].DB_NAME; } } /// /// 堆垛机出入库口设置列表 /// protected List SrmOutInInfoSet = new List(); #endregion; #region Constructor public Base_Srm2() : base() { } #endregion; #region Method private int _locExecute = 0; public override void Run() { if (Interlocked.Exchange(ref _locExecute, 1) == 0) { try { //加载刷新堆垛机执行需要的最新参数设置 Init_Refresh(); //分配入库货位 ThreadHelper.TaskThread(AssignInWareCell); if (WCS_PLCItem.IsConnSuccess == false) return; if (string.IsNullOrWhiteSpace(PlcName)) return; //写入心跳 //WriteHandShake(); //完成任务 SRMCompleteTask(); //执行任务 SRMStartExecuteTask(); } catch (Exception ex) { string errormsg = string.Format("堆垛机[{0}]执行异常,消息:{1}", PlcName, ex.ToString()); LogMessageHelper.RecordLogMessage(errormsg, ex); } finally { Interlocked.Exchange(ref _locExecute, 0); } } } /// /// 堆垛机任务完成 /// protected virtual void SRMCompleteTask() { try { //当前任务完成 if (EquSignal.DB521_Task_Finishi == false) return; //查询任务 var task = SugarBase.DB.Queryable().First(v => v.TASK_NO == EquSignal.DB521_Taskfinishi_ID); if (task == null) return; if (task.TASK_WKSTATUS >= 99) return; if ((task.TASK_COMTYPE == (int)ComTypeEnum.入库 && task.TASK_POSIDTO.Length > 5) || task.TASK_COMTYPE == (int)ComTypeEnum.移库) { //完成任务 string result = TryCachHelper.TryTranExecute((db) => { //修改任务的状态 db.Updateable(it => new WCS_TASK() { TASK_WKSTATUS = 99, TASK_EDITUSERNO = "WCS", TASK_EDITDATETIME = DateTime.Now }) .Where(it => it.TASK_NO == task.TASK_NO) .ExecuteCommand(); //添加修改明细 string msg = string.Format("任务[{0}]完成", task.TASK_NO); CommonData.AddWCS_TASK_DTL(db, task.TASK_NO, task.TASK_NO, task.TASK_POSIDCUR, task.TASK_POSIDTO, msg); }); if (string.IsNullOrWhiteSpace(result)) { if (task.TASK_COMTYPE == (int)ComTypeEnum.入库) { SrmConvNoMoveToLast(task.TASK_POSIDCUR); } } } else if (task.TASK_COMTYPE == (int)ComTypeEnum.出库 || task.TASK_COMTYPE == (int)ComTypeEnum.搬运) { if (task.TASK_WKSTATUS == (int)WkStatus.堆垛机执行) { //var routeSet = EquRouteHelper.QueryRoute(task.TASK_SRMNO, task.TASK_POSIDTO); //var routes = routeSet.Where(v => v.ROUTE_STARTPOS == task.TASK_SRMNO).ToList(); //var route = QueryOutEquRouteItem(task, routes); int wksstatus = 6; //if (route.ISEND) //{ // wksstatus = 99; //} string result = TryCachHelper.TryTranExecute((db) => { //修改任务的状态 db.Updateable(it => new WCS_TASK() { TASK_WKSTATUS = wksstatus, TASK_POSIDCUR = task.TASK_POSIDNEXT, TASK_EDITUSERNO = "WCS", TASK_EDITDATETIME = DateTime.Now }) .Where(it => it.TASK_NO == task.TASK_NO) .ExecuteCommand(); //添加修改明细 string msg = string.Format("任务[{0}]堆垛机完成,修改当前地址为[{1}]", task.TASK_NO, task.TASK_POSIDNEXT); CommonData.AddWCS_TASK_DTL(db, task.TASK_NO, task.TASK_NO, task.TASK_POSIDNEXT, task.TASK_POSIDNEXT, msg); }); if (string.IsNullOrWhiteSpace(result)) { SrmConvNoMoveToLast(task.TASK_POSIDNEXT); } } } //TaskComplete(task.TASK_SRMNO, task.TASK_ID, task.TASK_COMTYPE); } catch (Exception ex) { LogMessageHelper.RecordLogMessage(ex); } } private void SRMStartExecuteTask() { //检测堆垛机模式 if (EquSignal.DB521_Auto_status != (int)SrmModeEnum.远程) return; //检测堆垛机报警 if (EquSignal.SrmDB541_Alarm) return; //检测堆垛机状态 if (EquSignal.DB521_Srm_Status != (int)SrmStateFork1Enum.空闲) return; if (EquSignal.DB520_Task_trigger != 0) return; //检测堆垛机禁用 //if (Current.SysSets.FirstOrDefault(v => v.SET_ID == SrmNo).SET_VALUE.Trim() == "1") return; TryCachHelper.TryExecute((db) => { var taskSet = db.Queryable().Where(v => v.TASK_SRMNO == PlcName).ToList(); var task = taskSet.FirstOrDefault(v => (v.TASK_WKSTATUS == (int)WkStatus.堆垛机执行)); if (task == null) { //移库 if (MoveStock(db)) return; taskSet = taskSet.Where(v => v.TASK_WKSTATUS <= 2).ToList(); OutInStock(db, taskSet); } else { Log4netHelper.Logger_Error.ErrorFormat(string.Format("堆垛机[{0}]状态正常,但是存在执行中的任务[{1}]", PlcName, task.TASK_NO)); } }); } private void OutInStock(SqlSugarClient db, List tasks) { if (tasks.Count == 0) return; var tasktemp = tasks.FirstOrDefault(v => v.TASK_NO == task_no_Last); if (tasktemp != null) { if ((tasktemp.TASK_COMTYPE == 1 && tasktemp.TASK_WKSTATUS == 2) || (tasktemp.TASK_COMTYPE == 2 && tasktemp.TASK_WKSTATUS <= 1) || (tasktemp.TASK_COMTYPE == 3 && tasktemp.TASK_WKSTATUS <= 1) || (tasktemp.TASK_COMTYPE == 4 && tasktemp.TASK_WKSTATUS == 2)) { if (ExecuteTask(db, tasktemp)) return; } } else { tasktemp = SugarBase.DB.Queryable() .First(v => !SqlFunc.IsNullOrEmpty(v.TASK_POSIDMOVE) && v.TASK_COMTYPE == 2 && v.TASK_WKSTATUS <= 1 && v.TASK_WMSNO == PlcName); if (tasktemp != null) { if (ExecuteTask(db, tasktemp)) return; } } int taskMaxPriority = tasks.Max(v => v.TASK_PRIORITY); for (int index = taskMaxPriority; index >= 0; index--) { var tasks_Temp = tasks.Where(v => v.TASK_PRIORITY == index).ToList(); if (tasks_Temp.Count > 0) { //查询硬件条件满足的可用出入库任务 var taskSet = QueryTask(db, tasks_Temp); //调用扩展函数返回可用出入库任务 var taskList = QueryOutTasks(db, taskSet); //克隆集合 List outininfoSet = SrmOutInInfoSet.GetRange(0, SrmOutInInfoSet.Count); bool isEixt = false; foreach (var outininfo in outininfoSet) { if (outininfo.SRMOUTIN_OUTINTYPE == SrmOutInInfo_in || outininfo.SRMOUTIN_OUTINTYPE == SrmOutInInfo_outIn) { var taskitem = taskList.SingleOrDefault(v => v.TASK_POSIDCUR == outininfo.SRMOUTIN_CONVNO); if (taskitem != null) { if (taskitem.TASK_COMTYPE == (int)TaskTypeEnum.TaskType_InStorage) { if (InStock(db, taskitem)) { task_no_Last = taskitem.TASK_NO; isEixt = true; break; } } else if (taskitem.TASK_COMTYPE == (int)TaskTypeEnum.TaskType_Carry) { if (Carry(db, taskitem)) { task_no_Last = taskitem.TASK_NO; isEixt = true; break; } } } } if (outininfo.SRMOUTIN_OUTINTYPE == SrmOutInInfo_out || outininfo.SRMOUTIN_OUTINTYPE == SrmOutInInfo_outIn) { var tasktempList = taskList.Where(v => v.TASK_COMTYPE == (int)TaskTypeEnum.TaskType_OutStorage).ToList(); bool iscreateSuccess = false; foreach (var item in tasktempList) { //检测是否允许出库 if (QueryOutTask(db, item)) { if (OutStock(db, item)) { task_no_Last = item.TASK_NO; iscreateSuccess = true; break; } } } if (iscreateSuccess) { isEixt = true; break; } } } if (isEixt) { break; } } } } protected virtual bool QueryOutTask(SqlSugarClient db, WCS_TASK task) { return true; } private bool ExecuteTask(SqlSugarClient db, WCS_TASK task) { bool isExecuteFinish = false; if (task.TASK_COMTYPE == (int)ComTypeEnum.入库) { if (InStock(db, task)) isExecuteFinish = true; } else if (task.TASK_COMTYPE == (int)ComTypeEnum.出库) { if (OutStock(db, task)) isExecuteFinish = true; } else if (task.TASK_COMTYPE == (int)ComTypeEnum.搬运) { if (Carry(db, task)) isExecuteFinish = true; } return isExecuteFinish; } protected virtual List QueryOutTasks(SqlSugarClient db, List taskSet) { return taskSet.OrderBy(n => n.TASK_ADDDATETIME).ToList(); } private List QueryTask(SqlSugarClient db, List tasks) { List wcs_taskSet = new List(); //克隆集合 List outininfoSet = SrmOutInInfoSet.GetRange(0, SrmOutInInfoSet.Count); foreach (var outininfo in outininfoSet) { if (outininfo.SRMOUTIN_OUTINTYPE == SrmOutInInfo_in || outininfo.SRMOUTIN_OUTINTYPE == SrmOutInInfo_outIn) { var intasks = tasks.SingleOrDefault(v => v.TASK_WKSTATUS != (int)WkStatus.堆垛机执行 && v.TASK_POSIDCUR == outininfo.SRMOUTIN_CONVNO && //v.TASK_POSIDNEXT == outininfo.SRMOUTIN_CONVNO && (v.TASK_COMTYPE == 1 || v.TASK_COMTYPE == 4)); if (intasks != null) { var temptask = QueryInConvTask(outininfo, intasks); if (temptask != null) { wcs_taskSet.Add(temptask); continue; } } } if (outininfo.SRMOUTIN_OUTINTYPE == SrmOutInInfo_out || outininfo.SRMOUTIN_OUTINTYPE == SrmOutInInfo_outIn) { //检测出口状态 var convSignal = ConveyorHelper.GetConveyorSignal(outininfo.SRMOUTIN_CONVPLCNAME, outininfo.SRMOUTIN_CONVNO); if (convSignal.DB521_Request == false && convSignal.DB521_Tasknum <= 0 && convSignal.CvDB51_PH_Status == false) { var outTask = db.Queryable().First(v => v.TASK_POSIDCUR == outininfo.SRMOUTIN_CONVNO); if (outTask == null || ((outTask.TASK_WKSTATUS != (int)WkStatus.输送机执行) && (outTask.TASK_WKSTATUS != (int)WkStatus.堆垛机完成))) { //检测是否存在该出口的任务列表 List list = new List(); var taskList = tasks.Where(v => v.TASK_COMTYPE == 2 && v.TASK_WKSTATUS <= 1).ToList(); foreach (var task in taskList) { var routes = EquRouteHelper.QueryRoute(task.TASK_SRMNO, task.TASK_POSIDTO).Where(v => v.ROUTE_STARTPOS == PlcName).ToList(); var routeitem = routes.FirstOrDefault(v => v.ROUTE_SONPOS == outininfo.SRMOUTIN_CONVNO); if (routeitem != null && CheckAreaOutAddress(task, routeitem)) { if (wcs_taskSet.Any(v => v.TASK_NO == task.TASK_NO) == false) { list.Add(task); } } } if (list.Count() > 0) wcs_taskSet.AddRange(list); } } } } return wcs_taskSet; } /// /// 检测区域出口地址(弯轨堆垛机,多项道转换堆垛机) /// protected virtual bool CheckAreaOutAddress(WCS_TASK task, WCS_EQUIPMENTROUTE route) { return true; } protected virtual WCS_EQUIPMENTROUTE QueryOutEquRouteItem(WCS_TASK task, List routeSet) { return routeSet.Single(); } /// /// 查询堆垛机入库口任务 /// protected virtual WCS_TASK QueryInConvTask(WCS_SrmOutInInfo outininfo, WCS_TASK task) { WCS_TASK wcs_task = null; var convSignal = ConveyorHelper.GetConveyorSignal(outininfo.SRMOUTIN_CONVPLCNAME, outininfo.SRMOUTIN_CONVNO); if (convSignal.DB521_Tasknum == task.TASK_NO && convSignal.CvDB51_PH_Status //&& convSignal.DB521_Goodsend.ToString() == outininfo.SRMOUTIN_CONVNO ) { if (task.TASK_COMTYPE == 1) { if (string.IsNullOrWhiteSpace(task.TASK_POSIDTO) || task.TASK_POSIDTO == PlcName) { wcs_task = null; } else { wcs_task = task; } } else if (task.TASK_COMTYPE == 4) { var route = EquRouteHelper.QueryRoute(task.TASK_SRMNO, task.TASK_POSIDTO).FirstOrDefault(v => v.ROUTE_STARTPOS == PlcName); var srmoutin = SrmOutInInfoSet.SingleOrDefault(v => v.SRMOUTIN_CONVNO == route.ROUTE_NEXTPOS && v.SRMOUTIN_SRMNO == PlcName); //检测出口状态 var outConv = ConveyorHelper.GetConveyorSignal(srmoutin.SRMOUTIN_CONVPLCNAME, srmoutin.SRMOUTIN_CONVNO); if (outConv.DB521_Tasknum == 0 && outConv.CvDB51_PH_Status == false) { wcs_task = task; } } } return wcs_task; } protected bool InStock(SqlSugarClient db, WCS_TASK task) { bool result = true; try { if (task != null) { //检测任务当前位置存在于srm当前入口输送线列表中 if (SrmOutInInfoSet.Any(v => v.SRMOUTIN_CONVNO == task.TASK_POSIDCUR && (v.SRMOUTIN_OUTINTYPE == SrmOutInInfo_in || v.SRMOUTIN_OUTINTYPE ==SrmOutInInfo_outIn))) { if (string.IsNullOrWhiteSpace(task.TASK_POSIDTO) || task.TASK_POSIDTO == PlcName) { //分配货位 //bool assignresult = GetWareCell(task); //WareCell_Assign(db, task); //if (assignresult == false) return false; Log4netHelper.Logger_Error.ErrorFormat(string.Format("任务[{0}]未分配货位,堆垛机不能执行", task.TASK_NO)); return false; } //task = db.Queryable().First(v => v.TASK_NO == task.TASK_NO); //if (string.IsNullOrWhiteSpace(task.TASK_POSIDTO) || task.TASK_POSIDTO == SrmNo) //{ // throw new Exception(string.Format("任务[{0}]未分配货位。", task.TASK_NO)); //} //else //{ // Log4netHelper.Logger_Info.InfoFormat("任务[{0}]货位分配成功", task.TASK_NO); //} var writeSignal = new WCSWriteToSrmSignal(); writeSignal.Start_number = 0; writeSignal.Goodtype = 0; if (task.TASK_COMTYPE == 4)//移动 { //var startCvToEnd = ConveyorHelper.SrmMoveCvSet.FirstOrDefault(v => v.StartConveyor == task.TASK_POSIDCUR); //writeSignal.RowPos1 = startCvToEnd.SrmStartRow; //writeSignal.Travelpos1 = startCvToEnd.SrmStartColumn; //writeSignal.Liftpos1 = startCvToEnd.SrmStartLayer; //writeSignal.Fork_start_pos1 = startCvToEnd.SrmStartDepth; //writeSignal.RowPos2 = startCvToEnd.SrmEndRow; //writeSignal.Travelpos2 = startCvToEnd.SrmEndColumn; //writeSignal.Liftpos2 = startCvToEnd.SrmEndLayer; //writeSignal.Fork_dest_pos2 = startCvToEnd.SrmEndDepth; } else { var route = Current.EquRouteSet.FirstOrDefault(v => v.ROUTE_STARTPOS == task.TASK_POSIDCUR); writeSignal.RowPos1 = (int)route.SRMROW; writeSignal.Travelpos1 = (int)route.SRMCOLUMN; writeSignal.Liftpos1 = (int)route.SRMLAYER; //writeSignal.Fork_start_pos1 = (int)route.DEPTH; //查询货位表巷道,深度 //var location = db.Queryable().First(v => v.Loc_No == task.TASK_POSIDTO); writeSignal.RowPos2 = task.ToRow;// location.Loc_Tunnel; writeSignal.Travelpos2 = task.ToCol; writeSignal.Liftpos2 = task.ToLayer; //writeSignal.Fork_dest_pos2 = task.ToDepth; //location.Loc_Depth; } //if (task.TASK_COMTYPE == 5) //{ // var warecell = db.Queryable().First(v => v.F_NO == task.TASK_POSIDTO); // int count = db.Queryable().Where(v => v.F_CONTRGRPNO == warecell.F_CNTRGRPNO).Count(); // writeSignal.End_number = count; //} writeSignal.TaskID = task.TASK_NO; //执行任务 SrmOutIn(writeSignal, task.TASK_POSIDCUR, task.TASK_POSIDTO); } } } catch (Exception ex) { if (ex.Message.Contains(WriteSrmSignalException) == false && ex.Message.Contains(WriteSrmTriggerException) == false) { result = false; } } return result; } protected bool OutStock(SqlSugarClient db, WCS_TASK task) { bool result = true; try { var writeSignal = new WCSWriteToSrmSignal(); writeSignal.Start_number = 0; writeSignal.End_number = 0; writeSignal.Goodtype = 0; //查询货位表巷道,深度 //var location = db.Queryable().First(v => v.Loc_No == outtask.TASK_POSIDFROM); if (task.TASK_POSIDCUR == task.TASK_POSIDFROM) { //堆垛机出库 writeSignal.RowPos1 = task.FromRow;//location.Loc_Tunnel; writeSignal.Travelpos1 = task.FromCol;//outtask.ToCol; writeSignal.Liftpos1 = task.FromLayer;//outtask.ToLayer; } else { //堆垛机搬运任务 var routeSet = Current.EquRouteSet.Where(v => v.ROUTE_STARTPOS == task.TASK_POSIDCUR).ToList(); var routes = routeSet.Where(v => v.ROUTE_SONPOS == PlcName).ToList(); var route = QueryOutEquRouteItem(task, routes); writeSignal.RowPos1 = (int)route.SRMROW;//location.Loc_Tunnel; writeSignal.Travelpos1 = (int)route.SRMCOLUMN;//outtask.ToCol; writeSignal.Liftpos1 = (int)route.SRMLAYER;//outtask.ToLayer; } //writeSignal.Fork_start_pos1 = outtask.FromDepth;// location.Loc_Depth; location.Loc_EquimentNo if (task.TASK_COMTYPE == 2) { var routeSet = EquRouteHelper.QueryRoute(task.TASK_SRMNO, task.TASK_POSIDTO); var routes = routeSet.Where(v => v.ROUTE_STARTPOS == task.TASK_SRMNO).ToList(); var route = QueryOutEquRouteItem(task, routes); writeSignal.RowPos2 = (int)route.SRMROW; writeSignal.Travelpos2 = (int)route.SRMCOLUMN; writeSignal.Liftpos2 = (int)route.SRMLAYER; //writeSignal.Fork_dest_pos2 = (int)route.DEPTH; writeSignal.TaskID = task.TASK_NO; //执行任务 SrmOutIn(writeSignal, task.TASK_POSIDFROM, route.ROUTE_SONPOS); } else if (task.TASK_COMTYPE == 3) { if (string.IsNullOrWhiteSpace(task.TASK_POSIDTO) || task.TASK_POSIDTO == WCS_PLCItem.PLC_NAME) { bool assignresult = GetWareCell(task); if (assignresult == false) return result; } writeSignal.RowPos2 = task.ToRow; writeSignal.Travelpos2 = task.ToCol; writeSignal.Liftpos2 = task.ToLayer; //writeSignal.Fork_dest_pos2 = outtask.ToDepth; writeSignal.TaskID = task.TASK_NO; //执行任务 SrmOutIn(writeSignal, task.TASK_POSIDFROM, task.TASK_POSIDTO); } } catch (Exception ex) { LogMessageHelper.RecordLogMessage(ex); if (ex.Message.Contains(WriteSrmSignalException) == false && ex.Message.Contains(WriteSrmTriggerException) == false) { result = false; } } return result; } protected bool Carry(SqlSugarClient db, WCS_TASK task) { bool result = true; try { var writeSignal = new WCSWriteToSrmSignal(); writeSignal.Start_number = 0; writeSignal.End_number = 0; writeSignal.Goodtype = 0; var routeItem = Current.EquRouteSet.SingleOrDefault(v => v.ROUTE_STARTPOS == task.TASK_POSIDNEXT && v.ROUTE_SONPOS == PlcName); //查询货位表巷道,深度 //var location = db.Queryable().First(v => v.Loc_No == outtask.TASK_POSIDFROM); writeSignal.RowPos1 = (int)routeItem.SRMROW;//task.FromRow;//location.Loc_Tunnel; writeSignal.Travelpos1 = (int)routeItem.SRMCOLUMN; //task.FromCol;//outtask.ToCol; writeSignal.Liftpos1 = (int)routeItem.SRMLAYER;//task.FromLayer;//outtask.ToLayer; //writeSignal.Fork_start_pos1 = outtask.FromDepth;// location.Loc_Depth; location.Loc_EquimentNo var routeSet = EquRouteHelper.QueryRoute(task.TASK_SRMNO, task.TASK_POSIDTO); var route = routeSet.FirstOrDefault(v => v.ROUTE_STARTPOS == task.TASK_SRMNO); writeSignal.RowPos2 = (int)route.SRMROW; writeSignal.Travelpos2 = (int)route.SRMCOLUMN; writeSignal.Liftpos2 = (int)route.SRMLAYER; //writeSignal.Fork_dest_pos2 = (int)route.DEPTH; writeSignal.TaskID = task.TASK_NO; //执行任务 SrmOutIn(writeSignal, task.TASK_POSIDNEXT, route.ROUTE_SONPOS); } catch (Exception ex) { LogMessageHelper.RecordLogMessage(ex); if (ex.Message.Contains(WriteSrmSignalException) == false && ex.Message.Contains(WriteSrmTriggerException) == false) { result = false; } } return result; } protected bool MoveStock(SqlSugarClient db) { bool result = false; var task = QueryMoveTask(db); if (task == null) return result; if (string.IsNullOrWhiteSpace(task.TASK_POSIDTO) || task.TASK_POSIDTO == WCS_PLCItem.PLC_NAME) { //分配货位 bool assignresult = GetWareCell(task); if (assignresult == false) return result; //分配货位 //bool assignresult = WareCell_Assign(db, task); //if (assignresult == false) return result; } var writeSignal = new WCSWriteToSrmSignal(); writeSignal.Start_number = 0; writeSignal.End_number = 0; writeSignal.Goodtype = 0; //查询货位表巷道,深度 //var location1 = db.Queryable().First(v => v.F_NO == task.TASK_POSIDFROM); writeSignal.RowPos1 = task.FromRow; // location1.F_LINE; writeSignal.Travelpos1 = task.FromCol; writeSignal.Liftpos1 = task.FromLayer; //writeSignal.Fork_start_pos1 = location1.F_DEPTH; writeSignal.End_number = 0; //查询货位表巷道,深度 //var location2 = db.Queryable().First(v => v.F_NO == task.TASK_POSIDTO); writeSignal.RowPos2 = task.ToRow;//location2.F_LINE; writeSignal.Travelpos2 = task.ToCol; writeSignal.Liftpos2 = task.ToLayer; //writeSignal.Fork_dest_pos2 = location2.F_DEPTH; writeSignal.TaskID = task.TASK_NO; writeSignal.End_number = 0; //执行任务 SrmOutIn(writeSignal, task.TASK_POSIDFROM, task.TASK_POSIDTO); result = true; return result; } private void SrmOutIn(WCSWriteToSrmSignal srmSignal, string startPos, string posIdnext) { var task = Current.TaskSet.First(v => v.TASK_NO == srmSignal.TaskID); WCS_CacheInfo cahcheinfo = null;//Current.WCS_CacheInfoSet.FirstOrDefault(v => v.Cache_ConvNo == task.TASK_POSIDTO || v.Cache_AreaName == task.TASK_POSIDTO); string cacheAreaName = cahcheinfo == null ? srmSignal.TaskID.ToString() : cahcheinfo.Cache_AreaName; //string errorMsg = ThreadLockHelper.SrmOutIn(EquSignal, srmSignal, WCS_PLCItem.Plc, WriteDbName, startPos, posIdnext, cacheAreaName, PlcName); string errorMsg = SrmOutIn(EquSignal, srmSignal, startPos, posIdnext, cacheAreaName); if (!string.IsNullOrWhiteSpace(errorMsg)) throw new Exception(errorMsg); } public string SrmOutIn(SrmSignal equSignal, WCSWriteToSrmSignal srmSignal, string startPos, string posIdnext, string cacheAreaName) { using (var mutex = new Mutex(false, cacheAreaName)) { string resultMsg = string.Empty; try { if (mutex.WaitOne(-1, false)) { SrmTaskRun(equSignal, srmSignal, startPos, posIdnext, cacheAreaName); } } catch (Exception ex) { resultMsg = ex.Message; } finally { mutex.ReleaseMutex(); } return resultMsg; } } private void SrmTaskRun(SrmSignal equSignal, WCSWriteToSrmSignal srmSignal, string startPos, string posIdnext, string cacheAreaName) { //检测并生成移库任务 CheckCreateMoveTask(srmSignal,ref startPos,ref posIdnext); bool isExecute = CheckIsExecuteTask(cacheAreaName); if (isExecute) { if (equSignal.DB520_Start_number == srmSignal.Start_number && equSignal.DB520_End_number == srmSignal.End_number && equSignal.DB520_Goodtype == srmSignal.Goodtype && equSignal.DB520_Runmode == srmSignal.Runmode && equSignal.DB520_FromRowPos == srmSignal.RowPos1 && equSignal.DB520_FromColumnPos == srmSignal.Travelpos1 && equSignal.DB520_FromLayerPos == srmSignal.Liftpos1 && equSignal.DB520_Fork_start_pos1 == srmSignal.Fork_start_pos1 && equSignal.DB520_ToRowPos == srmSignal.RowPos2 && equSignal.DB520_ToColumnPos == srmSignal.Travelpos2 && equSignal.DB520_ToLayerPos == srmSignal.Liftpos2 && equSignal.DB520_Fork_dest_pos2 == srmSignal.Fork_dest_pos2 && equSignal.DB520_TaskID == srmSignal.TaskID) { string convNo = string.Empty; string result = TryCachHelper.TryTranExecute((db) => { var task = db.Queryable().First(t => t.TASK_NO == srmSignal.TaskID); if (task.TASK_COMTYPE == (int)TaskTypeEnum.TaskType_OutStorage) { convNo = posIdnext; } else if (task.TASK_COMTYPE == (int)TaskTypeEnum.TaskType_InStorage || task.TASK_COMTYPE == (int)TaskTypeEnum.TaskType_Carry) { convNo = task.TASK_POSIDCUR; } db.Updateable(it => new WCS_TASK() { TASK_WKSTATUS = (int)WkStatus.堆垛机执行, TASK_POSIDNEXT = posIdnext, TASK_EDITUSERNO = "WCS", TASK_EDITDATETIME = DateTime.Now }) .Where(it => it.TASK_NO == srmSignal.TaskID).ExecuteCommand(); string msg = string.Format("任务[{0}]已下发给堆垛机执行,起点位置[{1}]目标地址[{2}]", task.TASK_NO, startPos, posIdnext); CommonData.AddWCS_TASK_DTL(db, task.TASK_NO, task.TASK_NO, task.TASK_POSIDCUR, posIdnext, msg); if (equSignal.DB520_Task_trigger != 1) { string mes = string.Format("读取plc信息:任务号[{0}]起始行[{1}]起始列[{2}]起始层[{3}]目标行[{4}]目标列[{5}]目标层[{6}]", equSignal.DB520_TaskID, equSignal.DB520_FromRowPos, equSignal.DB520_FromColumnPos, equSignal.DB520_FromLayerPos, equSignal.DB520_ToRowPos, equSignal.DB520_ToColumnPos, equSignal.DB520_ToLayerPos); Log4netHelper.Logger_Info.InfoFormat(mes); if (WCS_PLCItem.Plc.WriteSignal((ushort)WriteDbName, 30, 2, 1)) { Log4netHelper.Logger_Info.InfoFormat(string.Format("任务[{0}]写入触发信号成功。", srmSignal.TaskID)); } else { throw new Exception(string.Format("任务[{0}]520写入触发信号失败。", srmSignal.TaskID)); } } }); if (string.IsNullOrWhiteSpace(result)) { task_no_Last = 0; //移动到最后 SrmConvNoMoveToLast(convNo); } else { throw new Exception(string.Format("任务[{0}]堆垛机执行失败,原因:[{1}]", srmSignal.TaskID, result)); } } else { WriteTaskToSrm(srmSignal); } } else { throw new Exception(string.Format("目标地址[{0}]交通管制,暂无法执行出库任务,将优先执行其它任务。", cacheAreaName)); } } private void CheckCreateMoveTask(WCSWriteToSrmSignal srmSignal,ref string startPos,ref string posIdnext) { var task = SugarBase.DB.Queryable().Single(v => v.TASK_NO == srmSignal.TaskID); if (task != null && task.FromDepth == 2 && task.TASK_POSIDCUR == task.TASK_POSIDFROM && string.IsNullOrWhiteSpace(task.TASK_POSIDMOVE)) { var tasktemps = SugarBase.DB.Queryable().Where(v => v.TASK_SRMNO == PlcName).ToList(); var task_DepthOne = tasktemps.FirstOrDefault(v => v.FromNo == task.FromNo && v.FromCol == task.FromCol && v.FromLayer == task.FromLayer && v.FromDepth == 1 && v.TASK_WKSTATUS <= 1 && v.TASK_COMTYPE == 2 || v.TASK_COMTYPE == 3); if (task_DepthOne == null) { //调用生成移库任务接口 var moveTaskresult = Current.WmsInterface.I_WCS_GetMoveTask(new GetMoveTaskParam() { WMSTaskNum = task.TASK_WMSNO }); if (moveTaskresult.ResType == 0) { throw new Exception(string.Format("任务[{0}]调用移库接口报错:[{1}]", task.TASK_NO, moveTaskresult.ResMessage)); } else if (moveTaskresult.ResType == 2) { //创建移库任务并执行 var moveTask = new WCS_TASK() { TASK_WMSNO = moveTaskresult.WMSTaskNum, TASK_COMTYPE = 3, TASK_SYSTYPE = "wcs", TASK_POSIDFROM = moveTaskresult.MoveStartWareCell, TASK_POSIDCUR = moveTaskresult.MoveStartWareCell, TASK_POSIDNEXT = moveTaskresult.MoveStartWareCell, TASK_POSIDTO = moveTaskresult.MoveEndWareCell, TASK_POSIDMOVE = moveTaskresult.MoveEndWareCell, TASK_PRIORITY = 0, TASK_WKSTATUS = 0, TASK_WHID = moveTaskresult.WareHouseName, TASK_ADDUSERNO = "wcs", TASK_ADDDATETIME = SugarBase.DB.GetDate(), TASK_EDITUSERNO = "wcs", TASK_EDITDATETIME = SugarBase.DB.GetDate(), TASK_NOTES = string.Empty, TASK_SRMNO = PlcName, TASK_BOXBARCODE = moveTaskresult.ContainerBarCode, TASK_FromTunnelNum = moveTaskresult.FromTunnelNum, TASK_EndTunnelNum = moveTaskresult.EndTunnelNum }; string result = TryCachHelper.TryTranExecute((db) => { int inserttask = db.Insertable(moveTask).ExecuteCommand(); if (inserttask <= 0) { throw new Exception(string.Format("任务[{0}]生成移库添加移库任务失败.", task.TASK_NO)); } //修改任务的移库字段 int updatetask = db.Updateable(it => new WCS_TASK() { TASK_POSIDMOVE = moveTask.TASK_POSIDMOVE, TASK_PRIORITY = 111, TASK_EDITUSERNO = "WCS", TASK_EDITDATETIME = DateTime.Now }) .Where(it => it.TASK_NO == task.TASK_NO) .ExecuteCommand(); if (updatetask <= 0) { throw new Exception(string.Format("任务[{0}]生成移库时修改需要移库的任务失败.", task.TASK_NO)); } }); if (!string.IsNullOrWhiteSpace(result)) { throw new Exception(result); } task = SugarBase.DB.Queryable().First(v => v.TASK_WMSNO == moveTask.TASK_WMSNO); } else if (moveTaskresult.ResType == 3) { if (string.IsNullOrWhiteSpace(moveTaskresult.Memo1.Trim())) { throw new Exception(string.Format("调用移库接口报错:堆垛机[{0}]优先执行的入库任务号不能为空。", PlcName)); } else { int task_no = Convert.ToInt16(moveTaskresult.Memo1.Trim()); if (task_no <= 0) { throw new Exception(string.Format("调用移库接口报错:堆垛机[{0}]优先执行的入库任务号不能为零。", PlcName)); } SugarBase.DB.Updateable(it => new WCS_TASK() { TASK_PRIORITY = 10, TASK_EDITDATETIME = DateTime.Now }) .Where(it => it.TASK_NO == task_no) .ExecuteCommand(); } } } else if (task_DepthOne.TASK_WKSTATUS <= 1) { task = task_DepthOne; } } if (task == null) { throw new Exception(string.Format("堆垛机[{0}]执行的任务[{1}]不存在", PlcName, srmSignal.TaskID)); } if (task.TASK_COMTYPE == 3) { #region 堆垛机取货地址 srmSignal.RowPos1 = task.FromRow; srmSignal.Travelpos1 = task.FromCol; srmSignal.Liftpos1 = task.FromLayer; #endregion; #region 堆垛机放货地址 if (string.IsNullOrWhiteSpace(task.TASK_POSIDTO) || task.TASK_POSIDTO == WCS_PLCItem.PLC_NAME) { bool assignresult = GetWareCell(task); if (assignresult == false) throw new Exception(string.Format("移库任务[{0}]分配货位失败。", task.TASK_NO)); } var routeSet = EquRouteHelper.QueryRoute(task.TASK_SRMNO, task.TASK_POSIDTO); var routes = routeSet.Where(v => v.ROUTE_STARTPOS == task.TASK_SRMNO).ToList(); var route = QueryOutEquRouteItem(task, routes); srmSignal.RowPos2 = (int)route.SRMROW; srmSignal.Travelpos2 = (int)route.SRMCOLUMN; srmSignal.Liftpos2 = (int)route.SRMLAYER; //writeSignal.Fork_dest_pos2 = (int)route.DEPTH; srmSignal.TaskID = task.TASK_NO; #endregion; startPos = task.TASK_POSIDFROM; posIdnext = task.TASK_POSIDTO; } } private static bool CheckIsExecuteTask(string cacheAreaName) { bool isExecute = false; var cacheInfoSet = Current.WCS_CacheInfoSet.Where(v => v.Cache_AreaName == cacheAreaName).ToList(); if (cacheInfoSet.Count <= 0) { isExecute = true; } else { int cacheCount = cacheInfoSet.Sum(v => v.Cache_Count); var tasks = SugarBase.DB.Queryable() .Where(v => v.TASK_COMTYPE == (int)TaskTypeEnum.TaskType_OutStorage && (v.TASK_WKSTATUS > 1 || (v.TASK_WKSTATUS <= 1 && SqlFunc.IsNullOrEmpty(v.TASK_POSIDMOVE) == false))) .ToList(); int curTaskCount = tasks.Count(v => v.TASK_POSIDTO == cacheAreaName || cacheInfoSet.Any(t => t.Cache_ConvNo == v.TASK_POSIDNEXT || t.Cache_ConvNo == v.TASK_POSIDTO)); if (curTaskCount < cacheCount) { int ph_StatusCount = 0;//光电信号数量 foreach (var item in cacheInfoSet) { var cv = ConveyorHelper.GetConveyorSignal(item.Cache_PlcName, item.Cache_ConvNo); if (cv.DB521_Tasknum > 0 || cv.CvDB51_PH_Status) { if (tasks.Any(v => v.TASK_NO == cv.DB521_Tasknum) == false) { ph_StatusCount++; } } } if ((curTaskCount + ph_StatusCount) < cacheCount) { isExecute = true; } } } return isExecute; } private void WriteTaskToSrm(WCSWriteToSrmSignal srmSignal) { List list = new List(); list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.Start_number).ToList()); list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.End_number).ToList()); list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.Goodtype).ToList()); list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.Runmode).ToList()); list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.RowPos1).ToList()); list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.Travelpos1).ToList()); list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.Liftpos1).ToList()); list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.Fork_start_pos1).ToList()); list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.RowPos2).ToList()); list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.Travelpos2).ToList()); list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.Liftpos2).ToList()); list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.Fork_dest_pos2).ToList()); list.AddRange(ExtendsUtil.UintToByte((uint)srmSignal.TaskID).ToList()); Log4netHelper.Logger_Info.InfoFormat(string.Format("写入任务[{0}]信息", srmSignal.TaskID)); bool result = WCS_PLCItem.Plc.Write((ushort)WriteDbName, 2, list.ToArray()); if (result) { Log4netHelper.Logger_Info.InfoFormat(string.Format("堆垛机[{0}]写入任务[{1}]信息成功", PlcName, srmSignal.TaskID)); } else { throw new Exception(string.Format("堆垛机[{0}]写入任务[{1}]信息失败", PlcName, srmSignal.TaskID)); } } private WCS_TASK QueryMoveTask(SqlSugarClient db) { WCS_TASK task = null; var movetaskSet = db.Queryable().Where(v => v.TASK_COMTYPE == (int)ComTypeEnum.移库 && v.TASK_WKSTATUS <= 1 && v.TASK_SRMNO == WCS_PLCItem.PLC_NAME).ToList(); if (movetaskSet.Count > 0) task = movetaskSet[0]; return task; } /// /// 调整堆垛机出入口顺序 /// /// private void SrmConvNoMoveToLast(string convNo) { try { if (!string.IsNullOrWhiteSpace(convNo)) { //检测是否是最后一项 if (SrmOutInInfoSet[SrmOutInInfoSet.Count() - 1].SRMOUTIN_CONVNO == convNo) return; //查询要调整执行顺序的输送线 var outininfo = SrmOutInInfoSet.FirstOrDefault(v => v.SRMOUTIN_CONVNO == convNo); //删除当前 SrmOutInInfoSet.Remove(outininfo); //添加到最后 SrmOutInInfoSet.Add(outininfo); } } catch (Exception ex) { Log4netHelper.Logger_Info.ErrorFormat(ex.ToString()); } } /// /// 加载堆垛机刷新数据 /// private void Init_Refresh() { var srmconvinfoset = Current.WCS_SrmOutInInfoSet.Where(v => v.SRMOUTIN_SRMNO == PlcName && v.SRMOUTIN_ISSTOP == false).OrderBy(p => p.SRMOUTIN_PRIORITY).OrderBy(t => t.SRMOUTIN_SEQUENCE).ToList(); if (SrmOutInInfoSet.Count != srmconvinfoset.Count || //元素个数不相同 srmconvinfoset.Any(v => v.SRMOUTIN_ISUPDATE)) //元素已更新 { SrmOutInInfoSet = srmconvinfoset; SugarBase.DB.Updateable(it => new WCS_SrmOutInInfo() { SRMOUTIN_ISUPDATE = false }) .Where(it => it.SRMOUTIN_SRMNO == PlcName) .ExecuteCommand(); } } private int _assignInWareCell = 0; /// /// 分配入库货位 /// private void AssignInWareCell() { if (Interlocked.Exchange(ref _assignInWareCell, 1) == 0) { try { var taskSet = SugarBase.DB.Queryable().Where(v => v.TASK_SRMNO == PlcName && v.TASK_WKSTATUS != 5 && v.TASK_WKSTATUS > 1).ToList().OrderByDescending(v => v.TASK_PRIORITY).ToList(); var taskSet_In = taskSet.Where(v => v.TASK_COMTYPE == 1).ToList(); foreach (var task in taskSet_In) { if (SrmOutInInfoSet.Any(v => v.SRMOUTIN_CONVNO == task.TASK_POSIDCUR && (v.SRMOUTIN_OUTINTYPE == "in" || v.SRMOUTIN_OUTINTYPE == "outIn")) || task.TASK_POSIDCUR == "1025") { if (string.IsNullOrWhiteSpace(task.TASK_POSIDTO) || task.TASK_POSIDTO == PlcName) { //入库任务分配货位 GetWareCell(task); } } } } catch (Exception ex) { LogMessageHelper.RecordLogMessage(string.Format("分配入库货位异常:[{0}]", ex.Message), ex); } finally { Interlocked.Exchange(ref _assignInWareCell, 0); } } } public bool GetWareCell(WCS_TASK task) { string resultMsg = string.Empty; //调度接口获取货位 var getWareCell = Current.WmsInterface.I_WCS_GetWareCell(new GetWareCellParam() { WMSTaskNum = task.TASK_WMSNO.ToString(), TunnelNum = task.TASK_EndTunnelNum, PickUpEquipmentNo = task.TASK_POSIDNEXT }); if (getWareCell.ResType) { resultMsg = TryCachHelper.TryTranExecute((db) => { //修改任务分配货位 db.Updateable(it => new WCS_TASK() { TASK_WKSTATUS = 2, TASK_POSIDNEXT = getWareCell.CellNo, TASK_POSIDTO = getWareCell.CellNo, TASK_EDITUSERNO = "WCS", TASK_EDITDATETIME = DateTime.Now }) .Where(it => it.TASK_NO == task.TASK_NO) .ExecuteCommand(); //添加修改明细 string msg = string.Format("任务[{0}]分配货位[{1}]成功。", task.TASK_NO, getWareCell.CellNo); CommonData.AddWCS_TASK_DTL(db, task.TASK_NO, task.TASK_NO, task.TASK_POSIDCUR, task.TASK_POSIDNEXT, msg); }); } else { resultMsg = string.Format("任务[{0}]调用接口分配货位[{1}]失败,原因:{2}", task.TASK_NO, getWareCell.CellNo, getWareCell.ResMessage); LogMessageHelper.RecordLogMessage(resultMsg); } if (string.IsNullOrWhiteSpace(resultMsg)) { task.TASK_POSIDNEXT = getWareCell.CellNo; task.TASK_POSIDTO = getWareCell.CellNo; return true; } else { return false; } } #endregion; } }