using SqlSugar; using System; using System.Collections.Generic; using System.Linq; 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_Srm : Base_EquPlc { #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 Properties #region Constructor public Base_Srm() : base() { } #endregion Constructor #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); } } } /// /// 加载堆垛机刷新数据 /// 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(); } } /// /// 写入心跳 /// protected void WriteHandShake() { int heartbeat = 0; if (EquSignal.DB521_Handshake_to_wcs) { if (EquSignal.DB520_Handshake_from_wcs == 0) { heartbeat = 1; } } else { if (EquSignal.DB520_Handshake_from_wcs == 1) { heartbeat = 0; } } //写入心跳 if (WCS_PLCItem.Plc.WriteSignal((ushort)WriteDbName, 0, 2, heartbeat) == false) { Log4netHelper.Logger_Error.ErrorFormat(string.Format("堆垛机PLC[{0}]写入心跳失败", PlcName)); //throw new Exception(string.Format("堆垛机PLC[{0}]写入心跳失败", SrmNo)); } } /// /// 堆垛机任务完成 /// 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); }); DateTime lastfinishtime = SugarBase.DB.GetDate(); //更新最后完成时间 SugarBase.DB.Updateable(it => new WCS_PLC() { PLC_LASTFINISHTIME = lastfinishtime }).Where(it => it.PLC_NAME == task.TASK_SRMNO).ExecuteCommand(); 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); }); DateTime lastfinishtime = SugarBase.DB.GetDate(); //更新最后完成时间 SugarBase.DB.Updateable(it => new WCS_PLC() { PLC_LASTFINISHTIME = lastfinishtime }).Where(it => it.PLC_NAME == task.TASK_SRMNO).ExecuteCommand(); 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 SrmConvNoMoveToLast(string 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); } /// /// 任务完成 /// /// /// 设备编号 /// 任务号 /// 类型 1:入库任务完成 2:堆垛机出库任务完成 3.移库完成 4:出库任务完成 5.堆垛机码盘完成 //public void TaskComplete(string equNo, string task_id, int temptype) //{ // var param = new TASKCOMPLETEPARAM(); // param.TASK_ID = task_id; // param.FINISHTYPE = temptype; // RESULTINFO result = Current.WmsInterface.TASKCOMPLETE(param); // if (result.ISSUCCESS) // { // Log4netHelper.Logger_Info.InfoFormat(string.Format("堆垛机[{0}]完成WMS任务成功,传递参数:任务号[{1}]类型[{2}]反馈消息:[{3}]", equNo, task_id, temptype, result.MASSAGE)); // } // else // { // Log4netHelper.Logger_Error.ErrorFormat(string.Format("堆垛机[{0}]完成WMS任务失败,传递参数:任务号[{1}]类型[{2}]反馈消息:[{3}]", equNo, task_id, temptype, result.MASSAGE)); // } //} 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 (PlcName == "srm01") { var firsttask = SugarBase.DB.Queryable().Where(v => v.TASK_SRMNO == PlcName && v.TASK_COMTYPE == 2 && v.TASK_WKSTATUS <= 1).OrderBy(v => v.TASK_ADDDATETIME).First(); if (firsttask == null) { //移库 if (MoveStock(db)) return; } else { var dtime = SugarBase.DB.GetDate(); if (firsttask.TASK_ADDDATETIME.AddMinutes(20) > dtime)//出库任务在20分钟内 { //移库 if (MoveStock(db)) return; } } } else { //移库 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)); } }); } 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 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; } 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; } } private void SrmOutIn(WCSWriteToSrmSignal srmSignal, string startPos, string posIdnext) { 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 result = TryCachHelper.TryTranExecute((db) => { var task = db.Queryable().First(t => t.TASK_NO == srmSignal.TaskID); 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}]写入触发信号失败。", srmSignal.TaskID)); } } }); if (!string.IsNullOrWhiteSpace(result)) { throw new Exception(string.Format("任务[{0}]堆垛机执行失败,原因:[{1}]", srmSignal.TaskID, result)); } } else { WriteTaskToSrm(srmSignal); } } private void SrmOutIn2(WCSWriteToSrmSignal srmSignal, string startPos, string posIdnext) { string result = TryCachHelper.TryTranExecute((db) => { var task = db.Queryable().First(t => t.TASK_NO == srmSignal.TaskID); 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); 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()); ushort trigger = 1; list.AddRange(ExtendsUtil.UshortToByte(trigger).ToList()); Log4netHelper.Logger_Info.InfoFormat(string.Format("写入任务[{0}]信息", srmSignal.TaskID)); if (WCS_PLCItem.Plc.Write((ushort)WriteDbName, 2, list.ToArray())) { Log4netHelper.Logger_Info.InfoFormat(string.Format("堆垛机[{0}]写入任务[{1}]信息成功", PlcName, srmSignal.TaskID)); } else { throw new Exception(string.Format("堆垛机[{0}]写入任务[{1}]信息失败", PlcName, srmSignal.TaskID)); } }); if (!string.IsNullOrWhiteSpace(result)) { throw new Exception(string.Format("任务[{0}]堆垛机执行失败,原因:[{1}]", srmSignal.TaskID, result)); } } 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 void OutInStock(SqlSugarClient db, List tasks) { if (tasks.Count == 0) 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 task = QueryTask2(db, tasks_Temp); if (task != null) { if (task.TASK_COMTYPE == (int)ComTypeEnum.入库) { if (InStock(db, task)) break; } else if (task.TASK_COMTYPE == (int)ComTypeEnum.出库) { if (OutStock(db, task)) break; } else if (task.TASK_COMTYPE == (int)ComTypeEnum.搬运) { if (Carry(db, task)) break; } } } } } private WCS_TASK QueryTask2(SqlSugarClient db, List tasks) { WCS_TASK wcs_task = null; //克隆集合 List outininfoSet = SrmOutInInfoSet.GetRange(0, SrmOutInInfoSet.Count); foreach (var outininfo in outininfoSet) { if (outininfo.SRMOUTIN_OUTINTYPE == "in" || outininfo.SRMOUTIN_OUTINTYPE == "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_task = temptask; break; } } } if (outininfo.SRMOUTIN_OUTINTYPE == "out" || outininfo.SRMOUTIN_OUTINTYPE == "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(); WCS_EQUIPMENTROUTE routeitem = null; foreach (var task in taskList) { var routes = EquRouteHelper.QueryRoute(task.TASK_SRMNO, task.TASK_POSIDTO).Where(v => v.ROUTE_STARTPOS == PlcName).ToList(); routeitem = routes.FirstOrDefault(v => v.ROUTE_SONPOS == outininfo.SRMOUTIN_CONVNO); //if (CurrentRoute == null) //{ // LogMessageHelper.RecordLogMessage(string.Format("任务[{0}]目标地址[{1}]堆垛机[{2}]没有查询到路由。", task.TASK_NO, task.TASK_POSIDTO, PlcName)); //} if (routeitem != null && CheckAreaOutAddress(task, routeitem)) { if (task.TASK_WKSTATUS <= 1) { list.Add(task); } } } //有任务则调用虚方法并返回要执行的任务 var curouttask = QueryOutTask(db, list); if (curouttask != null) { wcs_task = curouttask; break; } } } } //无任务则移动到最后 SrmConvNoMoveToLast(outininfo.SRMOUTIN_CONVNO); } return wcs_task; } /// /// 查询堆垛机入库口任务 /// 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; } //private WCS_TASK QueryTask(SqlSugarClient db, List tasks) //{ // WCS_TASK wcs_task = null; // //查询最小优先级 // int priority = SrmOutInInfoSet.Max(v => v.SRMOUTIN_PRIORITY); // for (int index = 1; index <= priority; index++) // { // //查询相同优先级的出入口 // var outininfoSet_temp = SrmOutInInfoSet.Where(v => v.SRMOUTIN_PRIORITY == index && v.SRMOUTIN_ISSTOP == false).ToList(); // //克隆集合 // List outininfoSet = outininfoSet_temp.GetRange(0, outininfoSet_temp.Count); // foreach (var outininfo in outininfoSet) // { // if (outininfo.SRMOUTIN_OUTINTYPE == "in") // { // //检测入库口状态 // var convSignal = ConveyorHelper.GetConveyorSignal(outininfo.SRMOUTIN_CONVPLCNAME, outininfo.SRMOUTIN_CONVNO); // if (convSignal.DB521_Tasknum > 0 && // convSignal.DB521_Goodsend.ToString() == outininfo.SRMOUTIN_CONVNO) // { // var curtask = tasks.FirstOrDefault(v => v.TASK_NO == convSignal.DB521_Tasknum); // if (curtask != null && curtask.TASK_WKSTATUS != (int)WkStatus.堆垛机执行) // { // wcs_task = curtask; // break; // } // } // } // else if (outininfo.SRMOUTIN_OUTINTYPE == "out") // { // //检测出口状态 // var convSignal = ConveyorHelper.GetConveyorSignal(outininfo.SRMOUTIN_CONVPLCNAME, outininfo.SRMOUTIN_CONVNO); // if (convSignal.DB521_Request == false && convSignal.DB521_Tasknum <= 0) // { // var curOutTask = db.Queryable().First(v => v.TASK_POSIDCUR == outininfo.SRMOUTIN_CONVNO); // if (curOutTask == null || // ((curOutTask.TASK_WKSTATUS != (int)WkStatus.输送机执行) && (curOutTask.TASK_WKSTATUS != (int)WkStatus.堆垛机完成))) // { // //检测是否存在该出口的任务列表 // List list = new List(); // foreach (var task in tasks) // { // var route = EquRouteHelper.QueryRoute(task.TASK_SRMNO, task.TASK_POSIDTO).FirstOrDefault(v => v.ROUTE_STARTPOS == SrmNo); // if (route == null) // { // Log4netHelper.Logger_Error.ErrorFormat(string.Format("任务[{0}]目标地址[{1}]堆垛机[{2}]", task.TASK_NO, task.TASK_POSIDTO, SrmNo)); // } // if (outininfo.SRMOUTIN_CONVNO == route.ROUTE_NEXTPOS) // { // if (task.TASK_WKSTATUS <= 1) // { // list.Add(task); // } // } // } // //有任务则调用虚方法并返回要执行的任务 // var curouttask = QueryOutTask(db, list); // if (curOutTask != null) // { // wcs_task = curouttask; // break; // } // } // } // } // //无任务则移动到最后 // SrmConvNoMoveToLast(outininfo.SRMOUTIN_CONVNO); // } // } // return wcs_task; //} protected bool InStock(SqlSugarClient db, WCS_TASK task) { bool result = false; if (task != null) { //检测任务当前位置存在于srm当前入口输送线列表中 if (SrmOutInInfoSet.Any(v => v.SRMOUTIN_CONVNO == task.TASK_POSIDCUR && (v.SRMOUTIN_OUTINTYPE == "in" || v.SRMOUTIN_OUTINTYPE == "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); result = true; } } return result; } protected bool OutStock(SqlSugarClient db, WCS_TASK task) { bool result = false; if (task != null && task.FromDepth == 2 && task.TASK_POSIDCUR == task.TASK_POSIDFROM) { var tasktemps = db.Queryable().Where(v => v.TASK_SRMNO == PlcName).ToList(); var task_DepthOne = tasktemps.Where(v => Current.WareNameList.Contains(v.TASK_WHID)).ToList() .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) { if (string.IsNullOrWhiteSpace(task.TASK_POSIDMOVE)) { //调用生成移库任务接口 var moveTaskresult = Current.WmsInterface.I_WCS_GetMoveTask(new GetMoveTaskParam() { WMSTaskNum = task.TASK_WMSNO }); if (moveTaskresult.ResType == 0) { LogMessageHelper.RecordLogMessage(string.Format("任务[{0}]调用移库接口报错:[{1}]", task.TASK_NO, moveTaskresult.ResMessage)); return result; } else if (moveTaskresult.ResType == 2) { //创建移库任务并执行 var moveTask = new WCS_TASK(); moveTask.TASK_WMSNO = moveTaskresult.WMSTaskNum; moveTask.TASK_COMTYPE = 3; moveTask.TASK_SYSTYPE = "wcs"; moveTask.TASK_POSIDFROM = moveTaskresult.MoveStartWareCell; moveTask.TASK_POSIDCUR = moveTask.TASK_POSIDFROM; moveTask.TASK_POSIDNEXT = moveTask.TASK_POSIDFROM; moveTask.TASK_POSIDTO = moveTaskresult.MoveEndWareCell; moveTask.TASK_POSIDMOVE = moveTask.TASK_POSIDTO; moveTask.TASK_PRIORITY = 0; moveTask.TASK_WKSTATUS = 0; moveTask.TASK_WHID = moveTaskresult.WareHouseName; moveTask.TASK_ADDUSERNO = "wcs"; moveTask.TASK_ADDDATETIME = db.GetDate(); moveTask.TASK_EDITUSERNO = "wcs"; moveTask.TASK_EDITDATETIME = moveTask.TASK_ADDDATETIME; moveTask.TASK_NOTES = string.Empty; moveTask.TASK_SRMNO = PlcName; moveTask.TASK_BOXBARCODE = moveTaskresult.ContainerBarCode; moveTask.TASK_FromTunnelNum = moveTaskresult.FromTunnelNum; moveTask.TASK_EndTunnelNum = moveTaskresult.EndTunnelNum; 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 = 100, 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)); } task = db.Queryable().First(v => v.TASK_WMSNO == moveTask.TASK_WMSNO); } else if (moveTaskresult.ResType == 3) { if (string.IsNullOrWhiteSpace(moveTaskresult.Memo1.Trim())) { LogMessageHelper.RecordLogMessage(string.Format("调用移库接口报错:堆垛机[{0}]优先执行的入库任务号不能为空。", PlcName)); return result; } else { int task_no = Convert.ToInt32(moveTaskresult.Memo1.Trim()); if (task_no <= 0) { LogMessageHelper.RecordLogMessage(string.Format("调用移库接口报错:堆垛机[{0}]优先执行的入库任务号不能为零。", PlcName)); return result; } db.Updateable(it => new WCS_TASK() { TASK_PRIORITY = 10, TASK_EDITDATETIME = DateTime.Now }) .Where(it => it.TASK_NO == task_no) .ExecuteCommand(); return result; } } } } else if (task_DepthOne.TASK_WKSTATUS <= 1) { task = task_DepthOne; } } if (task == null) return result; 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 routes = Current.EquRouteSet.Where(v => v.ROUTE_STARTPOS == task.TASK_POSIDCUR).ToList(); var route = routes.FirstOrDefault(v => v.ROUTE_SONPOS == PlcName); 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); } result = true; return result; } protected virtual WCS_EQUIPMENTROUTE QueryOutEquRouteItem(WCS_TASK task, List routeSet) { return routeSet.Single(); } /// /// 检测区域出口地址(弯轨堆垛机,多项道转换堆垛机) /// protected virtual bool CheckAreaOutAddress(WCS_TASK task, WCS_EQUIPMENTROUTE route) { return true; } protected bool Carry(SqlSugarClient db, WCS_TASK task) { bool result = false; 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); result = true; return result; } protected virtual WCS_TASK QueryOutTask(SqlSugarClient db, List taskSet) { return taskSet.OrderBy(n => n.TASK_EDITDATETIME).ToList().FirstOrDefault(); } 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) { if (task.TASK_WKSTATUS != 7) { //入库任务分配货位 GetWareCell(task); } } } } } catch (Exception ex) { LogMessageHelper.RecordLogMessage(string.Format("分配入库货位异常:[{0}]", ex.Message), ex); } finally { Interlocked.Exchange(ref _assignInWareCell, 0); } } } #endregion Method #region 测试 private void SRMExecuteTask() { //var taskSet = Current.TaskSet.Where(v => v.TASK_SRMNO == SrmNo && v.TASK_WKSTATUS != 5).OrderByDescending(v => v.TASK_PRIORITY).ToList(); #region 准备堆垛机执行的入库任务 //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")) // { // if (string.IsNullOrWhiteSpace(task.TASK_POSIDTO) || task.TASK_POSIDTO == SrmNo) // { // //入库任务分配货位 // bool assignresult = GetWareCell(task); // } // } //} #endregion 准备堆垛机执行的入库任务 #region 准备堆垛机执行的出库任务 //var taskSet_Out = taskSet.Where(v => v.TASK_COMTYPE == 2 && v.TASK_WKSTATUS <= 1).ToList(); ////堆垛机出口列表 //var srmOutConvInfoSet = SrmOutInInfoSet.Where(v => v.SRMOUTIN_OUTINTYPE == "out").ToList(); //foreach (var outConv in srmOutConvInfoSet) //{ // if (!taskSet.Any(v => v.TASK_COMTYPE == 2 && v.TASK_WKSTATUS == 11 && v.TASK_SRMOUTCONVNO == outConv.SRMOUTIN_CONVNO)) // { // var outtaskSet = taskSet_Out.Where(v => v.TASK_SRMOUTCONVNO == outConv.SRMOUTIN_CONVNO).ToList(); // var outtasks = QueryOutTask(outtaskSet); // foreach (var outtask in outtasks) // { // if (outtask.FromDepth == 2) // { // var temptask = taskSet.First(v => v.FromRow == outtask.FromRow && v.FromLayer == outtask.FromLayer && v.FromDepth == 1); // if (temptask == null) // { // //调用生成移库任务接口 // break; // } // else if (temptask.TASK_WKSTATUS >= 1) // { // //1升位和2升位任务堆垛机出口不一致, // if (temptask.TASK_SRMOUTCONVNO != outConv.SRMOUTIN_CONVNO) // { // continue; // } // //outtask = temptask; // } // } // //修改任务状态 // break; // } // } //} #endregion 准备堆垛机执行的出库任务 } //internal virtual List QueryOutTask(List taskSet) //{ // return taskSet.OrderByDescending(v => v.TASK_PRIORITY).OrderBy(v => v.TASK_EDITDATETIME).ToList(); //} #endregion 测试 } //public class SrmList //{ // /// // /// Srm运行 // /// // public static void SrmRun() // { // try // { // foreach (var srm in Current.SrmSet) // { // //if (srm.SrmNo == "srm11" || srm.SrmNo == "srm10") // ThreadHelper.TaskThread(srm.ExecuteSrm); // } // } // catch (Exception ex) // { // Log4netHelper.Logger_Error.ErrorFormat(ex.ToString()); // } // } //} public class WCSWriteToSrmSignal { //码垛起始货位原有数量 public int Start_number; //码垛终点货位叉取数量 public int End_number; //货物类型 public int Goodtype; /// /// 速度模式 /// public int Runmode; //任务起始行 public int RowPos1; //任务行走起始列 public int Travelpos1; //任务提升起始层 public int Liftpos1; //任务起始深度(0:中位, 1:深度1, 2:深度2) public int Fork_start_pos1; //任务目标行 public int RowPos2; //任务行走目标列 public int Travelpos2; //任务提升目标层 public int Liftpos2; //任务目标深度(0:中位, 1:深度1, 2:深度2) public int Fork_dest_pos2; //任务ID public int TaskID; } }