using Newtonsoft.Json; using PlcSiemens.Core.Extension; using ServiceCenter.Extensions; using ServiceCenter.Logs; using ServiceCenter.Redis; using ServiceCenter.SqlSugars; using SqlSugar; using System.ComponentModel; using System.Linq.Expressions; using System.Threading.Tasks; using WCS.Core; using WCS.Entity; using WCS.WorkEngineering.Extensions; using WCS.WorkEngineering.Protocol.SRM; using WCS.WorkEngineering.Protocol.Station; using WCS.WorkEngineering.WebApi.Controllers; using WCS.WorkEngineering.WebApi.Models.AGV.Response; using WCS.WorkEngineering.Worlds; using DeviceFlags = WCS.WorkEngineering.Extensions.DeviceFlags; using KnownException = ServiceCenter.Logs.KnownException; using TaskStatus = WCS.Entity.TaskStatus; namespace WCS.WorkEngineering.Systems { /// /// 堆垛机 /// [BelongTo(typeof(MainWorld))] [Description("堆垛机")] public class 堆垛机 : DeviceSystem { /// /// 取货点设备集合 /// private Dictionary> PickUpDevices = new Dictionary>(); /// /// 放货设备 /// private Dictionary> PutDevices = new Dictionary>(); public 堆垛机() { //获取所有的巷道集合 var devices = Device.All.Where(v => v.HasFlag(DeviceFlags.巷道)); //开始分配 foreach (var item in devices) { //取货设备 var srm = item.Targets.Where(v => v.HasFlag(DeviceFlags.堆垛机)).FirstOrDefault(); PickUpDevices.Add(srm.Code, item.Sources.Where(v => v.HasFlag(DeviceFlags.输送机)).Select(v => new Station(v, this.World)).ToList()); //放货设备 srm = item.Sources.Where(v => v.HasFlag(DeviceFlags.堆垛机)).FirstOrDefault(); PutDevices.Add(srm.Code, item.Targets.Where(v => v.HasFlag(DeviceFlags.输送机)).Select(v => new Station(v, this.World)).ToList()); } } protected override bool ParallelDo => false; protected override bool SaveLogsToFile => true; public override void Do(SRM obj) { #region 处理完成任务 //判断DB520 完成任务确认清除信号 是否为1 if (obj.Data.OkAck == 1) throw new KnownException($"WCS任务完成确认信号[DB520.OkAck]未清除,请检查堆垛机处理异常原因", LogLevelEnum.Mid); if (obj.Data2.VoucherNo != obj.Data.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{obj.Data.VoucherNo},DB521:{obj.Data2.VoucherNo}", LogLevelEnum.Mid); if (obj.Data2.AutoStatus != SrmAutoStatus.Automatic) throw new KnownException($"堆垛机处于{obj.Data2.AutoStatus.GetDescription()}模式", LogLevelEnum.Low); if (obj.Data2.TaskFinishiId > 0) { //处理完成的任务信息 WCS_TaskInfo taskInfo = null; //开始处理 SqlSugarHelper.Do(db => { World.Log($"堆垛机任务处理:开始--完成任务{obj.Data2.TaskFinishiId}", LogLevelEnum.Low); #region 获取完成任务 //根据DB521任务号获取对应任务 var task = db.Default.Queryable().First(v => v.ID == obj.Data2.TaskFinishiId); if (task == null) { //如果在历史任务已经完成,则回复成功,否则抛异 if (db.Default.Queryable().SplitTable(tabs => tabs.Take(2)).Where(v => v.ID == obj.Data2.TaskFinishiId && v.Status == TaskStatus.Finish).Any()) { obj.Data.OkAck = 1; World.Log($"兼容给堆垛机完成确认信号,{obj.Data2.TaskFinishiId}", LogLevelEnum.Low); return; } else { throw new KnownException($"堆垛机完成任务号{obj.Data2.TaskFinishiId},在WCS当前任务信息中未找到对应任务。", LogLevelEnum.High); } } if (task.Status != Entity.TaskStatus.StackerExecution) throw new KnownException($"任务{task.ID}状态是{task.Status.GetDescription()}.堆垛机完成任务需要对应任务状态处于堆垛机执行中", LogLevelEnum.High); #endregion 获取完成任务 //根据任务类型做不同的处理 switch (task.Type) { case TaskType.EnterDepot: task.Status = Entity.TaskStatus.Finish; task.EedTime = DateTime.Now; db.Default.Updateable(task).ExecuteCommand(); task.AddWCS_TASK_DTL(db, task.AddrTo, "入库任务结束"); World.Log($"第一次处理任务完成成功,{obj.Data2.TaskFinishiId}", LogLevelEnum.Low); //完成任务 break; case TaskType.OutDepot: switch (task.OutType) { case OutTypeEnum.自动出库任务: var dev = new Station(Device.All.FirstOrDefault(v => v.Code == task.SrmStation), this.World); if (task.SrmStation == "8271" || task.SrmStation == "8272" || task.SrmStation == "8273" || task.SrmStation == "8274" || task.SrmStation == "8275") //库尾 { task.Status = Entity.TaskStatus.ConveyorExecution; task.AddrNext = "8278"; //task.Status = Entity.TaskStatus.Finish; dev.Data.GoodsStart = task.SrmStation.ToShort(); dev.Data.GoodsEnd = 8278; } else if (task.AddrTo == "8028") { task.Status = Entity.TaskStatus.Finish; dev.Data.GoodsEnd = 8028; } else { task.Status = TaskStatus.ConveyorExecution; dev.Data.GoodsEnd = task.AddrTo.ToShort(); dev.Data.GoodsStart = task.SrmStation.ToShort(); } dev.Data.TaskNumber = task.ID; dev.Data.VoucherNo++; db.Default.Updateable(task).ExecuteCommand(); task.AddWCS_TASK_DTL(db, task.SrmStation, "出库任务到达放货站台"); db.Default.Ado.CommitTran(); World.Log($"出库执行记录:taskid{dev.Data.TaskNumber}-" + $"GoodsStart{dev.Data.GoodsStart}-" + $"GoodsEnd{dev.Data.GoodsEnd}-" + $"VoucherNo{dev.Data.VoucherNo}"); break; case OutTypeEnum.全自动手动出库任务: var dev1 = new Station(Device.All.FirstOrDefault(v => v.Code == task.SrmStation), this.World); if (task.SrmStation == "8271" || task.SrmStation == "8272" || task.SrmStation == "8273" || task.SrmStation == "8274" || task.SrmStation == "8275") //库尾 { //task.Status = Entity.TaskStatus.Finish; task.Status = Entity.TaskStatus.ConveyorExecution; task.AddrNext = "8278"; dev1.Data.GoodsStart = task.SrmStation.ToShort(); dev1.Data.GoodsEnd = 8278; } else if (task.AddrTo == "8028") { task.Status = Entity.TaskStatus.Finish; dev1.Data.GoodsEnd = 8028; } else { task.Status = TaskStatus.ConveyorExecution; dev1.Data.GoodsEnd = task.AddrTo.ToShort(); dev1.Data.GoodsStart = task.SrmStation.ToShort(); } dev1.Data.TaskNumber = task.ID; dev1.Data.VoucherNo++; db.Default.Updateable(task).ExecuteCommand(); task.AddWCS_TASK_DTL(db, task.SrmStation, "手动出库任务到达放货站台"); db.Default.Ado.CommitTran(); World.Log($"出库执行记录:taskid{dev1.Data.TaskNumber}-" + $"GoodsStart{dev1.Data.GoodsStart}-" + $"GoodsEnd{dev1.Data.GoodsEnd}-" + $"VoucherNo{dev1.Data.VoucherNo}"); break; case OutTypeEnum.半自动手动出库任务: task.Status = Entity.TaskStatus.Finish; task.EditTime = DateTime.Now; db.Default.Updateable(task).ExecuteCommand(); task.AddWCS_TASK_DTL(db, task.SrmStation, "半自动手动出库任务结束"); break; default: break; } break; case TaskType.TransferDepot: task.Status = Entity.TaskStatus.Finish; task.EedTime = DateTime.Now; db.Default.Updateable(task).ExecuteCommand(); task.AddWCS_TASK_DTL(db, task.AddrTo, "移库任务结束"); World.Log($"第一次处理移库任务完成成功,{obj.Data2.TaskFinishiId}", LogLevelEnum.Low); break; } //通知WMS任务完成 if (task.Status == TaskStatus.Finish) WmsApi.CompleteTask(task.ID); if (task.Type == TaskType.OutDepot && task.Status == TaskStatus.ConveyorExecution && task.SrmStation != "8271" && task.SrmStation != "8272" && task.SrmStation != "8273" && task.SrmStation != "8274" && task.SrmStation != "8275") WmsApi.SrmPickOutCompleted(task.ID); if (task.Status >= TaskStatus.Finish) task.CompleteOrCancelTasks(db); taskInfo = task; obj.Data.OkAck = 1; World.Log($"堆垛机回复成功,{obj.Data2.TaskFinishiId}", LogLevelEnum.Low); }); if (taskInfo == null) throw new KnownException("数据库提交事务错误", LogLevelEnum.High); // 写入信号 //通知WMS任务完成 //if (taskInfo.Status == TaskStatus.Finish) WmsApi.CompleteTask(taskInfo.ID); //if (taskInfo.Type == TaskType.OutDepot && taskInfo.Status == TaskStatus.ConveyorExecution) WmsApi.SrmPickOutCompleted(taskInfo.ID); World.Log($"堆垛机任务处理:结束--完成任务{obj.Data2.TaskFinishiId}", LogLevelEnum.Mid); return; } #endregion 处理完成任务 //堆垛机是否可以下发任务 if (obj.Data2.RunStatus != SrmRunStatus.Idle) throw new KnownException($"堆垛机处于{obj.Data2.RunStatus.GetDescription()}状态", LogLevelEnum.High); //默认没有移库任务 bool isTransfer = false; //出入库优先级任务 1:无优先 2:入库 3:出库 int enterOrOut = 1; var key = $"WCS:Lock:出入库管制SRM"; //再检查是否有等待执行的货物 SqlSugarHelper.Do(db => { //获取当前堆垛机的所有未完成任务 var tasks = db.Default.Queryable().Where(v => v.Status < Entity.TaskStatus.Finish && (v.Device == obj.Entity.Code)); //任务集合是否有处于堆垛机执行状态的任务 if (tasks.Any(v => v.Status == Entity.TaskStatus.StackerExecution)) throw new KnownException($"有任务处于堆垛机执行状态", LogLevelEnum.High); //不存在调整优先级任务,判断是否存在移库任务 isTransfer = tasks.Any(v => v.Type == TaskType.TransferDepot && v.Status == Entity.TaskStatus.NewBuild); if (!isTransfer) //存在调整优先级任务 { //获取出库任务中新建状态最大优先级 var outPriorityNewBuild = tasks.Where(v => v.Type == TaskType.OutDepot && v.Status == Entity.TaskStatus.WaitingToExecute).Max(v => v.Priority); //获取入库任务中最大优先级 var enterPriority = tasks.Where(v => v.Type == TaskType.EnterDepot && v.Status < Entity.TaskStatus.StackerExecution).Max(v => v.Priority); //出入库最大优先级相加大于零 if (outPriorityNewBuild >0 || enterPriority > 0) { //出入库优先级任务 1:无优先 2:入库 3:出库 enterOrOut = enterPriority > outPriorityNewBuild ? 2 : (enterPriority == outPriorityNewBuild ? 1 : 3); } } }); #region 移库 if (isTransfer) { WCS_TaskInfo taskInfo = null; SqlSugarHelper.Do(db => { //获取一条当前堆垛机优先级最高的新建移库任务 var task = db.Default.Queryable().Where(v => v.Device == obj.Entity.Code && v.Type == TaskType.TransferDepot && v.Status == Entity.TaskStatus.NewBuild) .OrderByDescending(v => v.Priority) .First() ?? throw new KnownException("未找到移库任务", LogLevelEnum.High); //任务状态改为堆垛机执行中 task.Status = Entity.TaskStatus.StackerExecution; task.StartTime = DateTime.Now; db.Default.Updateable(task).ExecuteCommand(); task.AddWCS_TASK_DTL(db, task.AddrFrom, task.Device, $"堆垛机{obj.Entity.Code}开始执行任务"); taskInfo = task; }); if (taskInfo == null) throw new KnownException("数据更新错误", LogLevelEnum.High); var addrFrom = taskInfo.AddrFrom.Split("-"); var addrTo = taskInfo.AddrTo.Split("-"); World.Log($"堆垛机任务处理:开始--下发移库任务[{obj.Data.TaskNumber}][{obj.Data.SLine}][{obj.Data.SCol}][{obj.Data.SLayer}][{obj.Data.ELine}][{obj.Data.ECol}][{obj.Data.ELayer}][{obj.Data.TaskType}][{obj.Data.VoucherNo}]", LogLevelEnum.Mid); //下发任务 obj.Data.TaskNumber = taskInfo.ID; obj.Data.SLine = addrFrom[0].ToShort(); obj.Data.SCol = addrFrom[1].ToShort(); obj.Data.SLayer = addrFrom[2].ToShort(); obj.Data.ELine = addrTo[0].ToShort(); obj.Data.ECol = addrTo[1].ToShort(); obj.Data.ELayer = addrTo[2].ToShort(); obj.Data.TaskType = SrmTaskType.MoveGoods; obj.Data.VoucherNo++; World.Log($"堆垛机任务处理:结束---下发移库任务[{obj.Data.TaskNumber}][{obj.Data.SLine}][{obj.Data.SCol}][{obj.Data.SLayer}][{obj.Data.ELine}][{obj.Data.ECol}][{obj.Data.ELayer}][{obj.Data.TaskType}][{obj.Data.VoucherNo}]", LogLevelEnum.Mid); return; } #endregion 移库 #region 出入库 //上一个周期是不是出库任务 第一次获取返回结果会是false var lastIsOut = obj.Entity.GetFlag("LastIsOut"); List inlist = new List(); List outlist = new List(); obj.Entity.SetFlag("LastIsOut", !lastIsOut); //入库任务优先 或 上一个周期是出库任务并且出库任务无优先 if (enterOrOut == 2 || (lastIsOut && enterOrOut == 1)) //入库任务 { //判断本次优先执行楼层,并设置下次执行时优先楼层 //var floor = obj.Entity.GetFlag("FloorIn"); //floor = floor % 2 + 1; //obj.Entity.SetFlag("FloorIn", floor); //获取当前堆垛机所有的取货站台 var arrIn = PickUpDevices.First(v => v.Key == obj.Entity.Code).Value; if (!arrIn.Any()) throw new KnownException($"堆垛机{obj.Entity.Code}无取货路径点", LogLevelEnum.High); foreach (var device in arrIn) { try { var CmdType = device.Data.CmdType; inlist.Add(device); } catch (Exception) { continue; } } arrIn = inlist; inlist = null; ////获取有货的设备 arrIn = arrIn.Where(v => v.Data2.TaskNumber > 0 && v.Data3.Status.HasFlag(StationStatus.PH_Status) && !v.Data3.Status.HasFlag(StationStatus.Run)).ToList(); if (!arrIn.Any()) throw new KnownException($"[{obj.Entity.Code}]等待入库任务输送到位", LogLevelEnum.Mid); WCS_TaskInfo taskInfo = null; Station station = null; SqlSugarHelper.Do(db => { //根据有货设备的任务号获取所有类型为入库状态为输送机执行中的任务 var tasks = db.Default.Queryable().Where(v => (v.Type == TaskType.EnterDepot) && v.Status == TaskStatus.ConveyorExecution && arrIn.Select(p => p.Data2.TaskNumber).Contains(v.ID)).ToList(); //World.Log("可用任务集合:" + JsonConvert.SerializeObject(tasks)); if (tasks.Count == 0) return; //按条件先后排序获取一条排序后第一条结果1.优先级2.所在楼层与本次优先执行楼层 TODO:待验证排序结果 var task = tasks.OrderByDescending(v => v.Priority).First() ?? throw new KnownException($"{obj.Entity.Code}未找到入库任务", LogLevelEnum.High); //获取任务所有设备 station = arrIn.First(v => v.Data2.TaskNumber == task.ID); if(station == null) throw new KnownException($"{obj.Entity.Code}未找到满足条件的入库任务", LogLevelEnum.High); //获取当前货物巷道 var res = WmsApi.GetLocalIn(task.ID, task.Device, station.Entity.Code); var loc = res.ResData.CellNo.Split("-"); task.Status = TaskStatus.StackerExecution; task.AddrTo = $"{loc[0]}-{loc[1]}-{loc[2]}"; task.LastInteractionPoint = station.Entity.Code; task.EditWho = "WCS"; if (db.Default.Updateable(task).ExecuteCommand() > 1) { World.Log($"更新成功", LogLevelEnum.Mid); } else { World.Log($"更新失败", LogLevelEnum.Mid); db.Connect.Updateable().SetColumns(p => new WCS_TaskInfo() { AddrTo = task.AddrTo }).Where(p => p.ID == task.ID); } task.AddWCS_TASK_DTL(db, station.Entity.Code, task.AddrTo, "任务下发堆垛机执行"); taskInfo = task; }); if (taskInfo == null) throw new KnownException("未找到满足条件的入库任务", LogLevelEnum.High); var addrTo = taskInfo.AddrTo.Split("-"); World.Log($"堆垛机任务处理:开始--下发入库任务[{obj.Data.TaskNumber}][{obj.Data.SLine}][{obj.Data.SCol}][{obj.Data.SLayer}][{obj.Data.ELine}][{obj.Data.ECol}][{obj.Data.ELayer}][{obj.Data.TaskType}][{obj.Data.VoucherNo}]", LogLevelEnum.Mid); //下发任务 obj.Data.TaskNumber = taskInfo.ID; obj.Data.TaskType = SrmTaskType.Default; obj.Data.SLine = station.Entity.Code.ToShort(); obj.Data.SCol = 0; obj.Data.SLayer = 0; obj.Data.ELine = addrTo[0].ToShort(); obj.Data.ECol = addrTo[1].ToShort(); obj.Data.ELayer = addrTo[2].ToShort(); obj.Data.VoucherNo++; World.Log($"堆垛机任务处理:结束---下发入库任务[{obj.Data.TaskNumber}][{obj.Data.SLine}][{obj.Data.SCol}][{obj.Data.SLayer}][{obj.Data.ELine}][{obj.Data.ECol}][{obj.Data.ELayer}][{obj.Data.TaskType}][{obj.Data.VoucherNo}]", LogLevelEnum.Mid); } else if (enterOrOut == 3 || !lastIsOut) //出库任务 { //获取当前堆垛机所有的放货站台 var arrOut = PutDevices.First(v => v.Key == obj.Entity.Code).Value; if (!arrOut.Any()) throw new KnownException($"堆垛机{obj.Entity.Code}无放货路径点", LogLevelEnum.High); foreach (var device in arrOut) { try { var CmdType = device.Data.CmdType; outlist.Add(device); } catch (Exception) { continue; } } arrOut = outlist; outlist = null; //获取可以放货的设备集合 arrOut = arrOut.Where(v => !v.Data3.Status.HasFlag(StationStatus.PH_Status) //无光电 && !v.Data3.Status.HasFlag(StationStatus.Run) //未运行 && !v.Data3.Status.HasFlag(StationStatus.OT_Status) //无任务 && !v.Data3.Status.HasFlag(StationStatus.UnassignedTask) //未分配任务 && v.Data3.Status.HasFlag(StationStatus.Auto)).ToList(); //自动 if (!arrOut.Any()) throw new KnownException($"[{obj.Entity.Code}]无可用放货站台", LogLevelEnum.Mid); WCS_TaskInfo taskInfo = null; SqlSugarHelper.Do(db => { string resmeg = ""; var allOutCode = arrOut.Select(v => v.Entity.Code).ToList(); if (!db.Default.Queryable().Where(v => v.Type == TaskType.OutDepot && v.Status == TaskStatus.WaitingToExecute) .Where(v => allOutCode.Contains(v.SrmStation)).Any()) { throw new KnownException($"{obj.Entity.Code}无满足出库条件的任务", LogLevelEnum.High); } Expression> expression8278 = null; Expression> expression8263 = null; Expression> expression8257 = null; var cur8278taskInlist = db.Default.Queryable().With(SqlWith.NoLock).Where(v => v.Type == TaskType.EnterDepot && v.Status >= TaskStatus.WaitingToExecute && v.AddrFrom == "8277" && obj.Entity.Code == v.Device).ToList(); if (cur8278taskInlist.Any() || RedisHub.Default.Get(key) != null) { //if (task.AddrTo == "8278") //{ // throw new KnownException($"{obj.Entity. // Code}库尾正存在入库任务,禁止库尾出库。", LogLevelEnum.High); //} expression8278 = p => p.AddrTo != "8278"; resmeg = $"{obj.Entity.Code}库尾正存在该堆垛机入库任务,暂停库尾出库。"; } //控制出货口任务数量 var cur8263tasklist = db.Default.Queryable().Where(v => v.Type == TaskType.OutDepot && v.Status >= TaskStatus.ConveyorExecution && v.AddrTo == "8263").ToList(); if (cur8263tasklist.Any()) { if (cur8263tasklist.Count() >= 4) { //tasklist = tasklist.Where(p => p.AddrTo != "8263"); expression8263 = p => p.AddrTo != "8263"; resmeg = resmeg + $"{obj.Entity.Code}库前出库口8263输送中任务数已经大于4,堆垛机停止出库。"; } } var cur8257tasklist = db.Default.Queryable().Where(v => v.Type == TaskType.OutDepot && v.Status >= TaskStatus.ConveyorExecution && v.AddrTo == "8257").ToList(); if (cur8257tasklist.Any()) { if (cur8257tasklist.Count() >= 4) { expression8257 = p => p.AddrTo != "8257"; resmeg = resmeg + $"{obj.Entity.Code}库前出库口8257输送中任务数已经大于4,堆垛机停止出库。"; } //tasklist = tasklist.Where(p => p.AddrTo != "8257"); } var task = db.Default.Queryable().Where(v => v.Type == TaskType.OutDepot && v.Status == TaskStatus.WaitingToExecute) .Where(v => allOutCode.Contains(v.SrmStation)) .WhereIF(expression8278 != null, expression8278) .WhereIF(expression8263 != null, expression8263) .WhereIF(expression8257 != null, expression8257) .OrderByDescending(v => v.Priority) .OrderBy(v => v.AddTime) .First(); if (task == null) throw new KnownException($"{obj.Entity.Code}" + resmeg, LogLevelEnum.High); if (expression8278 != null && task.AddrTo == "8278" && task.Device == obj.Entity.Code) { World.Log($"{obj.Entity.Code},强卡控埋点1,任务号:{task.ID},目标地址:{task.AddrTo}", LogLevelEnum.High); task = db.Default.Queryable().Where(v => v.Type == TaskType.OutDepot && v.Status == TaskStatus.WaitingToExecute && v.AddrTo != "8278") .Where(v => allOutCode.Contains(v.SrmStation)) .WhereIF(expression8263 != null, expression8263) .WhereIF(expression8257 != null, expression8257) .OrderByDescending(v => v.Priority) .OrderBy(v => v.AddTime) .First(); } if (task == null) throw new KnownException($"{obj.Entity.Code}" + resmeg, LogLevelEnum.High); //判断是否是二深位任务 var addrFrom = task.AddrFrom.Split("-"); if (addrFrom[4] == "2") { var res = WmsApi.AddWcsMoveTask(task.ID); switch (res.ResData.ResType) { case WmsApiMoveTask.允许2升位执行: break; case WmsApiMoveTask.执行移库任务: throw new KnownException($"堆垛机{obj.Entity.Code}需要先执行移库任务", LogLevelEnum.Mid); case WmsApiMoveTask.一深位有出库任务: task = db.Default.Queryable() .Where(v => v.Type == TaskType.OutDepot && v.Status == TaskStatus.WaitingToExecute) .Where(v => allOutCode.Contains(v.SrmStation) && v.AddrFrom == res.ResData.CellNo) .First() ?? throw new KnownException($"任务{task.ID}一深位有出库任务,等待一深位任务执行完成", LogLevelEnum.Mid); break; }; if (res.ResData.ResType == WmsApiMoveTask.执行移库任务) return; if (res.ResData.ResType == WmsApiMoveTask.一深位有出库任务 && res.ResData.CellNo != task.AddrFrom) return; } task.Status = TaskStatus.StackerExecution; task.LastInteractionPoint = task.Device; task.EditWho = "WCS"; db.Default.Updateable(task).ExecuteCommand(); task.AddWCS_TASK_DTL(db, task.Device, task.SrmStation, "任务下发堆垛机执行"); taskInfo = task; }); if (taskInfo == null) throw new KnownException("不满足出库条件,执行下一周期", LogLevelEnum.High); var addrFrom = taskInfo.AddrFrom.Split("-"); obj.Data.TaskNumber = taskInfo.ID; obj.Data.SLine = addrFrom[0].ToShort(); obj.Data.SCol = addrFrom[1].ToShort(); obj.Data.SLayer = addrFrom[2].ToShort(); obj.Data.ELine = taskInfo.SrmStation.ToShort(); obj.Data.ECol = 0; obj.Data.ELayer = 0; obj.Data.TaskType = SrmTaskType.Default; obj.Data.VoucherNo++; World.Log($"堆垛机任务处理:结束---下发出库任务[{obj.Data.TaskNumber}][{obj.Data.SLine}][{obj.Data.SCol}][{obj.Data.SLayer}][{obj.Data.ELine}][{obj.Data.ECol}][{obj.Data.ELayer}][{obj.Data.TaskType}][{obj.Data.VoucherNo}]", LogLevelEnum.Mid); } #endregion 出入库 } public override bool Select(Device dev) { return dev.HasProtocol(typeof(ISRM520)); } } }