using DBHelper; using System; using System.Collections.Generic; using System.Linq; using WCS.Core; using WCS.Entity; using WCS.Entity.Protocol.RGV; using WCS.Service.Extensions; using WCS.Service.Handlers; namespace WCS.Service.Works.RGV { [WorkTitle(typeof(RGVHandler), "直穿RGV")] public class 直穿RGV : DeviceWork { private readonly string ConvGroup_1030 = "G1030"; private readonly string RGV8 = "RGV8"; protected override void Do(RGVDevice rgv) { rgv.EX(rgv => { //RGV是自动且空闲的 if (rgv.Data2.WorkMode != RGVMode.自动) throw new DoException($"{rgv.Data2.WorkMode}"); if (rgv.Data2.SystemStatus != RGVRunStatus.空闲) throw new DoException($"{rgv.Data2.SystemStatus}"); //RGV状态为 RGV到站&&任务完成 时程序认为RGV当前不在取货点 if (rgv.Data2.Status_1.HasFlag(WCS.Entity.Protocol.RGVStatus.RGV到站) && rgv.Data2.Status_1.HasFlag(WCS.Entity.Protocol.RGVStatus.任务完成)) { //下达一个目标为1030的移动任务 rgv.Data.TaskID_1 = 1030; rgv.Data.DestPosition_1 = 1030; rgv.Data.TaskType_1 = RGVTaskType.移动; rgv.Data.Trigger_1++; } var obj = Device.Find(ConvGroup_1030).Create(); obj.WhetherToExecute(); //筛选出有任务号和起始及目标地址的设备 var dev = obj.RGVGetTaskedDevice() ?? throw new WarnException("无可用任务"); DB.Do(db => { var taskids = dev.Select(v => v.Data2.Tasknum); var tasks = db.Default.Set().Where(p => taskids.Contains(p.ID)); if (tasks.GroupBy(p => p.TaskGroupKey).Count() > 1) throw new WarnException("任务组ID不一致"); if (tasks.GroupBy(p => p.TaskGroupKey).Count() == 0) throw new WarnException("无任务组ID"); var gw1 = obj.Items.ToArray()[0]; var gw2 = obj.Items.ToArray()[1]; if (gw1.Data2.Tasknum != 0 && gw2.Data2.Tasknum != 0) { if (gw1.Data2.Goodsend != gw2.Data2.Goodsend) throw new WarnException($"{obj.Entity.CODE}目标地址不一致"); } rgv.Data.TaskID_1 = gw1.Data2.Tasknum; rgv.Data.TaskID_2 = gw2.Data2.Tasknum; if (gw1.Data2.Tasknum != 0) { rgv.Data.StartPosition_1 = gw1.Entity.CODE.ToShort(); rgv.Data.DestPosition_1 = gw1.Data2.Goodsend; } else { rgv.Data.StartPosition_1 = gw1.Entity.CODE.ToShort(); rgv.Data.DestPosition_1 = gw2.Data2.Goodsend; } rgv.Data.Trigger_1++; foreach (var task in tasks) { var msg = $"下达从{rgv.Data.StartPosition_1}移动至{rgv.Data.DestPosition_1}的RGV PLC指令。"; msg += $"[{task.ID}][{rgv.Data.StartPosition_1}][{rgv.Data.DestPosition_1}[{rgv.Data.Trigger_1}]"; task.CreateStatusLog(db, msg, this.GetType()); } }); }); } protected override bool SelectDevice(WCS_DEVICE dev) { return dev.CODE == RGV8; } } [WorkTitle(typeof(RGVHandler), "涂布环穿")] public class 涂布环穿 : DeviceWork { protected override void Do(RGVDevice obj) { //11号站台是取货点,但不是待命点,如需取货,从九号站台调车 //2号站台是一个待命点,但是为了保证入库取货效率,所有后面会跟一个车 //如果3号站台的小车拦住了后一个小车的放货任务,检测一次最近的空车距离值,如果大于或等于618500并且小于被拦住小车的位置值再进行调车,用于避免无效空跑 obj.EX(obj => { if (obj.Data2.Trigger_1 != obj.Data.Trigger_1) throw new WarnException($"等待执行任务{obj.Data2.TaskID_1}--{obj.Data2.TaskID_2}"); if (obj.Data2.WorkMode != RGVMode.自动) throw new DoException(obj.Data2.WorkMode.ToString()); if (obj.Data2.SystemStatus != RGVRunStatus.空闲) throw new DoException(obj.Data2.SystemStatus.ToString()); //RGV当前是否刚刚完成取货任务,等待放货 if (obj.IsPut()) { if (!obj.Data2.Status_1.HasFlag(WCS.Entity.Protocol.RGVStatus.光电)) throw new WarnException("RGV无光电,无法放货,请检查实际情况"); //取小车上的任务 DB.Do(db => { List taskids = new List() { obj.Data2.TaskID_1, obj.Data2.TaskID_2 }; var tasks = db.Default.Set().Where(p => taskids.Contains(p.ID)); if (tasks.GroupBy(p => p.TaskGroupKey).Count() > 1) throw new WarnException("任务组ID不一致"); if (!tasks.GroupBy(p => p.TaskGroupKey).Any()) throw new WarnException("无任务组ID"); var destStation = Device.Find(tasks.FirstOrDefault().ADDRNEXT).Create(); obj.Put(destStation, obj.Data2.TaskID_1, obj.Data2.TaskID_2); }); return; } var pickStation = obj.CurrentStation(); //RGV是否在任何一个站台 if (pickStation != null) { //是否是取货站台 if (pickStation.Entity.Is(DF.涂布RGV取货设备组)) { // 筛选出有任务号和起始及目标地址的设备 var devs = pickStation.RGVGetTaskedDevice(); //是否需要取货 if (devs != null && devs.Count > 0) { //开始下达取货任务 DB.Do(db => { if (obj.Data2.TaskType_1 != RGVTaskType.移动) throw new WarnException($"RGV正在执行{obj.Data2.TaskType_1}"); if (obj.Data2.Status_1.HasFlag(WCS.Entity.Protocol.RGVStatus.光电)) throw new WarnException("RGV有光电,无法取货,请检查实际情况"); if (!obj.Data2.Status_1.HasFlag(WCS.Entity.Protocol.RGVStatus.RGV到站)) throw new WarnException("RGV无到站状态,请检查RGV实际状态"); var taskids = devs.Select(v => v.Data2.Tasknum); var tasks = db.Default.Set().Where(p => taskids.Contains(p.ID)); if (tasks.GroupBy(p => p.TaskGroupKey).Count() > 1) throw new WarnException("任务组ID不一致"); if (!tasks.GroupBy(p => p.TaskGroupKey).Any()) throw new WarnException("无任务组ID"); var gw1 = pickStation.Items.ToArray()[0]; var gw2 = pickStation.Items.ToArray()[1]; if (gw1.Data2.Tasknum != 0 && gw2.Data2.Tasknum != 0) { if (gw1.Data2.Goodsend != gw2.Data2.Goodsend) throw new WarnException($"{obj.Entity.CODE}目标地址不一致"); } obj.Data.TaskID_1 = gw1.Data2.Tasknum; obj.Data.TaskID_2 = gw2.Data2.Tasknum; obj.Data.TaskType_1 = RGVTaskType.取货; obj.Data.DestPosition_1 = pickStation.Entity.CODE.Replace("G", "").ToShort(); obj.Data.Trigger_1++; foreach (var task in tasks) { var msg = $"下达从{obj.Data.StartPosition_1}移动至{obj.Data.DestPosition_1}的RGV PLC指令。"; msg += $"[{task.ID}][{obj.Data.StartPosition_1}][{obj.Data.DestPosition_1}[{obj.Data.Trigger_1}]"; task.CreateStatusLog(db, msg, this.GetType()); } }); return; } else if (pickStation.Entity.CODE == "G9") { //九站台的小车需要额外检测一下11站台是否需要取货 var station11 = Device.Find("G11").Create(); var station11Dev = station11.RGVGetTaskedDevice(); if (station11Dev != null && station11Dev.Count > 0) { obj.Move(station11); return; } } //找到自己的后一个小车 var afterRgv = obj.After(); //自己是否阻挡了该小车 if (afterRgv.Data2.WorkMode == RGVMode.自动 && afterRgv.Data2.SystemStatus != RGVRunStatus.空闲 && obj.StopedByMe(afterRgv)) { if (pickStation.Entity.CODE == "G2") { //此站台因需要进行排队,因此是否需要赶车取决于是否拦住了两个小车的任务 var afterRgv1 = afterRgv.After(); //如果是空闲或者没有拦住他,就不执行赶车 if (afterRgv1.Data2.WorkMode == RGVMode.自动 && (afterRgv1.Data2.SystemStatus == RGVRunStatus.空闲 || !afterRgv.StopedByMe(afterRgv1))) return; } else if (pickStation.Entity.CODE == "G3") { //为了减少空跑,需要被阻拦的小车后面的小车任务类型为移动并且位置值要大于618500小于被阻拦小车的位置值 var afterRgv1 = afterRgv.After(); if (afterRgv1.Data2.WorkMode == RGVMode.自动 && afterRgv.Data2.TaskType_1 == RGVTaskType.放货 && !(afterRgv1.Position < afterRgv.Position && afterRgv1.Position > 618500)) return; } //找到当前所在站台的下一个取货点 var beforeStation = Device.Where(v => v.Is(DF.涂布RGV取货设备组) && v.CODE != pickStation.Entity.CODE) .Select(v => v.Create()) .OrderBy(v => pickStation.Distance(v)) .FirstOrDefault(); //写入移动任务 obj.Move(beforeStation); return; } else if (pickStation.Entity.CODE == "G11") { obj.Move(Device.Find("G2").Create()); return; } else { //找到自己前面的 有货 没有小车 没有正在过来的小车 距离自己最近的 的站台 var station = Device.Where(v => v.Is(DF.涂布RGV取货设备组)) .Select(v => v.Create()) .Where(v => v.Position > obj.Position) //前面的 .Where(v => v.CurrentRGV() == null) .Where(v => !v.RgvList.Any(c => c.Data2.SystemStatus != RGVRunStatus.空闲 && c.Data2.DestPosition_1 == v.Entity.CODE.GetShortCode())) .Where(v => { // 筛选出有任务号和起始及目标地址的设备 var b = pickStation.RGVGetTaskedDevice(); //是否需要取货 if (b != null && b.Count > 0) return true; else return false; }) .OrderBy(v => obj.Distance(v)).FirstOrDefault();//取当前小车最近 if (obj.Data2.TaskType_1 == RGVTaskType.移动 && obj.Distance(station) > 100000) { obj.Move(station); return; } } } //是否在一个放货站台 if (pickStation.Entity.Is(DF.涂布RGV放货设备组)) { pickStation = obj.BeforeStation(); obj.Move(pickStation); } return; } //此时RGV即没有等待执行的放货任务,也不在任何一个取货点,因此需要调往最近的一个取货点 //找到距离这个RGV最近的一个取货点 //必须所有RGV都是空闲状态时才可以进行初始化 if (obj.RGVList.Any(v => v.Data2.SystemStatus != RGVRunStatus.空闲)) return; pickStation = obj.BeforeStation(); obj.Move(pickStation); }); } protected override bool SelectDevice(WCS_DEVICE dev) { return dev.Is(DF.涂布RGV); } } [WorkTitle(typeof(RGVHandler), "BOPP环穿")] public class BOPP环穿 : DeviceWork { protected override void Do(RGVDevice obj) { obj.EX(obj => { if (obj.Data2.Trigger_1 != obj.Data.Trigger_1) throw new WarnException($"等待执行任务{obj.Data2.TaskID_1}--{obj.Data2.TaskID_2}"); if (obj.Data2.WorkMode != RGVMode.自动) throw new DoException(obj.Data2.WorkMode.ToString()); if (obj.Data2.SystemStatus != RGVRunStatus.空闲) throw new DoException(obj.Data2.SystemStatus.ToString()); //RGV当前是否刚刚完成取货任务,等待放货 if (obj.IsPut()) { if (!obj.Data2.Status_1.HasFlag(WCS.Entity.Protocol.RGVStatus.光电)) throw new WarnException("RGV无光电,无法放货,请检查实际情况"); //取小车上的任务 DB.Do(db => { List taskids = new List() { obj.Data2.TaskID_1, obj.Data2.TaskID_2 }; var tasks = db.Default.Set().Where(p => taskids.Contains(p.ID)); if (tasks.GroupBy(p => p.TaskGroupKey).Count() > 1) throw new WarnException("任务组ID不一致"); if (!tasks.GroupBy(p => p.TaskGroupKey).Any()) throw new WarnException("无任务组ID"); var destStation = Device.Find(tasks.FirstOrDefault().ADDRNEXT).Create(); obj.Put(destStation, obj.Data2.TaskID_1, obj.Data2.TaskID_2); }); return; } var pickStation = obj.CurrentStation(); //RGV是否在任何一个站台 if (pickStation != null) { //是否是取货站台 if (pickStation.Entity.Is(DF.BOPPRGV取货设备组)) { // 筛选出有任务号和起始及目标地址的设备 var devs = pickStation.RGVGetTaskedDevice(); //是否需要取货 if (devs != null && devs.Count() > 0) { //开始下达取货任务 DB.Do(db => { if (obj.Data2.TaskType_1 != RGVTaskType.移动) throw new WarnException($"RGV正在执行{obj.Data2.TaskType_1}"); if (obj.Data2.Status_1.HasFlag(WCS.Entity.Protocol.RGVStatus.光电)) throw new WarnException("RGV有光电,无法取货,请检查实际情况"); if (!obj.Data2.Status_1.HasFlag(WCS.Entity.Protocol.RGVStatus.RGV到站)) throw new WarnException("RGV无到站状态,请检查RGV实际状态"); var taskids = devs.Select(v => v.Data2.Tasknum); var tasks = db.Default.Set().Where(p => taskids.Contains(p.ID)); if (tasks.GroupBy(p => p.TaskGroupKey).Count() > 1) throw new WarnException("任务组ID不一致"); if (!tasks.GroupBy(p => p.TaskGroupKey).Any()) throw new WarnException("无任务组ID"); var gw1 = pickStation.Items.ToArray()[0]; var gw2 = pickStation.Items.ToArray()[1]; if (gw1.Data2.Tasknum != 0 && gw2.Data2.Tasknum != 0) { if (gw1.Data2.Goodsend != gw2.Data2.Goodsend) throw new WarnException($"{obj.Entity.CODE}目标地址不一致"); } obj.Pick(pickStation, gw1.Data2.Tasknum, gw2.Data2.Tasknum); foreach (var task in tasks) { var msg = $"下达从{obj.Data.StartPosition_1}移动至{obj.Data.DestPosition_1}的RGV PLC指令。"; msg += $"[{task.ID}][{obj.Data.StartPosition_1}][{obj.Data.DestPosition_1}[{obj.Data.Trigger_1}]"; task.CreateStatusLog(db, msg, this.GetType()); } }); return; } ////找到自己的后一个小车 //var afterRgv = obj.After(); ////自己是否阻挡了该小车 //if (afterRgv.Data2.WorkMode == RGVMode.自动 && afterRgv.Data2.SystemStatus != RGVRunStatus.空闲 && obj.StopedByMe(afterRgv)) //{ // //找到当前所在站台的下一个取货点 // var beforeStation = Device.Where(v => v.Is(DF.BOPPRGV取货设备组) && v.CODE != pickStation.Entity.CODE) // .Select(v => v.Create()) // .OrderBy(v => pickStation.Distance(v)) // .FirstOrDefault(); // //写入移动任务 // obj.Move(beforeStation); // return; //} //else //{ // //取前一个取货点 // pickStation = obj.BeforeStation(); // //前一个取货点的小车 // var rgv = pickStation.CurrentRGV(); // //前一个取货点没有车 且没有非空闲目的地为前一个取货点的小车 // if (rgv == null && !obj.RGVList.Any(v => v.Data2.SystemStatus != RGVRunStatus.空闲 && v.Data2.DestPosition_1 == pickStation.Entity.CODE.Replace("G", "").ToShort())) // { // obj.Move(pickStation); // return; // } //} //计算当前RGV拦住小车的数量 var max = obj.RGVList.Count(v => v.Data2.WorkMode == RGVMode.自动 && v.Data2.SystemStatus != RGVRunStatus.空闲 && obj.StopedByMe(v)); if (pickStation.Entity.CODE == "G19" && max > 2) { obj.Move(Device.Find("G23").Create()); } else if (pickStation.Entity.CODE == "G23" && max > 3) { obj.Move(Device.Find("G19").Create()); } } //是否在一个放货站台 if (pickStation.Entity.Is(DF.BOPPRGV放货设备组)) { pickStation = obj.BeforeStation(); obj.Move(pickStation); } return; } //此时RGV即没有等待执行的放货任务,也不在任何一个取货点,因此需要调往最近的一个取货点 //找到距离这个RGV最近的一个取货点 //必须所有RGV都是空闲状态时才可以进行初始化 if (obj.RGVList.Any(v => v.Data2.SystemStatus != RGVRunStatus.空闲 || v.Data2.WorkMode != RGVMode.自动)) return; pickStation = obj.BeforeStation(); obj.Move(pickStation); }); } protected override bool SelectDevice(WCS_DEVICE dev) { return dev.Is(DF.BOPPRGV); } } }