using DBHelper; using System; using System.Collections.Generic; using System.Linq; using WCS.Core; using WCS.Entity; using WCS.Entity.Protocol; using WCS.Entity.Protocol.RGV; using WCS.Service.Helpers; using WCS.Service.Log; namespace WCS.Service.Extensions { /// /// 输送机设备组 /// public class StationDeviceGroup : DeviceGroup { /// /// 当前设备可用的RGV /// private static List AllRGVList; static StationDeviceGroup() { AllRGVList = Device.Where(v => v.IsRGV() && v.CODE != "RGV8").Select(v => v.Create()).ToList(); } public StationDeviceGroup(WCS_DEVICE entity) : base(entity) { } /// /// 执行输送机设备组任务 单例锁 /// /// public void EX(Action act) { try { if (ExDevice.Any(v => v == Entity.CODE)) throw new WarnException($"[{Entity.CODE}]--触发并发管控"); OperateExDevice(Entity.CODE); act(this); } catch (DoException ex) { ex.DoExceptionEX(Entity); } catch (WarnException ex) { ex.WarnExceptionEX(Entity); } catch (Exception ex) { ex.ExceptionEx(Entity); } finally { OperateExDevice(Entity.CODE); } } /// /// 当前设备可用的RGV /// public List RgvList { get { return AllRGVList.Where(v => v.LocationList.Any(p => p.Entity == Entity)).ToList(); } } /// /// 当前设备环穿组 /// private List LoncationList { get { var dev = StationLocation.ALLlocations.FirstOrDefault(v => v.Station == Entity.CODE); return StationLocation.ALLlocations.Where(v => v.PLC == dev.PLC).ToList(); } } /// /// 设备组自身的位置 /// public float Position { get { return StationLocation.ALLlocations.FirstOrDefault(v => v.Station == Entity.CODE).Location; } } /// /// 设备组所在环穿的总长度 /// public float Length { get { return StationLocation.ALLlocations.FirstOrDefault(v => v.Station == Entity.CODE).Length; } } /// /// 设备组是否满足任务执行条件 /// /// 给当前设备组下发任务时需要的请求 /// true:不满足执行条件需要进行停止执行 false:表示满足条件不需要停止执行 /// public void WhetherToExecute(IstationRequest type = IstationRequest.无) { foreach (var item in Items) { if (item.Data.VoucherNo != item.Data2.VoucherNo) throw new WarnException($"等待{item.Entity.CODE}执行任务{item.Data.Tasknum},凭证号不一致"); if (item.Data3.Status.HasFlag(StationStatus.运行状态位)) throw new DoException($"{item.Entity.CODE}运行中"); if (!item.Data2.Status.HasFlag(IstationStatus.光电状态)) throw new DoException($"[{item.Entity.CODE}]无光电"); } } /// /// 获取设备组中需要取货的设备 /// /// /// public List> RGVGetTaskedDevice() { var a = Items.Where(v => v.Data2.Status.HasFlag(IstationStatus.光电状态) && v.Data2.Tasknum > 10000) .Where(v => v.Entity.CODE.ToShort() != v.Data2.Goodsend && v.Data2.Goodsend != 0) .ToList(); return a.Count == 0 ? null : a; } /// /// 获取设备组中需要分配目标地址的设备 /// /// /// public List> TaskedDeviceGetNextAddress() { var a = Items.Where(v => v.Data2.Status.HasFlag(IstationStatus.光电状态) && v.Data2.Tasknum > 10000) .Where(v => v.Data2.Goodsend != 0) .ToList(); return a.Count == 0 ? null : a; } /// /// /// /// public RGVDevice NextRGV() { return new RGVDevice(new WCS_DEVICE()); } /// /// 计算目标RGV与站台自身的距离 /// /// /// public float Distance(RGVDevice rgv) { return DevEX.Distance(Position, rgv.Position, Length); } /// /// 计算两个站台之间的距离 /// /// /// public float Distance(StationDeviceGroup dev) { return DevEX.Distance(Position, dev.Position, Length); } /// /// 当前RGV /// /// public RGVDevice CurrentRGV() { //RGV与站台距离误差为 正负50 var max = Position + 500; var min = Position - 500; return RgvList?.FirstOrDefault(v => v.Data2.Position < max && v.Data2.Position > min); } /// /// 是否需要RGV /// /// true:需要RGV false:不需要RGV public bool NeedRgv() { var rgvs = Device.Where(v => v.IsRGV()).Select(v => v.Device()); var code = Entity.CODE.Replace("G", "").ToShort(); if (rgvs.Any(v => v.Data.DestPosition_1 == code && v.Data.SystemStatus != RGVRunStatus.空闲)) throw new WarnException("已有RGV执行中"); foreach (var item in Items) { if (item.Data3.Status.HasFlag(StationStatus.运行状态位)) return false; if (!item.Data2.Status.HasFlag(IstationStatus.光电状态)) return false; } return true; } } /// /// 输送机设备 /// public class StationDevice : Device { public StationDevice(WCS_DEVICE entity) : base(entity) { } /// /// 设备组是否满足任务执行条件 /// /// 给当前设备组下发任务时需要的请求 /// true:不满足执行条件需要进行停止执行 false:表示满足条件不需要停止执行 /// public void WhetherToExecute(IstationRequest type = IstationRequest.无) { //正在运行 if (Data3.Status.HasFlag(StationStatus.运行状态位)) throw new DoException("运行中"); //上一次的任务还未执行 if (Data.VoucherNo != Data2.VoucherNo) throw new WarnException($"等待任务[{Data2.Tasknum}]执行"); //没有光电 if (!Data2.Status.HasFlag(IstationStatus.光电状态)) throw new DoException("无光电"); ; //没有任务号 switch (type) { case IstationRequest.无: if (Data2.Tasknum < 10000 && Data.Tasknum < 10000) throw new WarnException($"设备无任务"); break; case IstationRequest.扫码入库: if (Data2.Tasknum > 10000 && Data.Tasknum > 10000) throw new WarnException($"设备已有任务任务"); break; case IstationRequest.堆垛机放货完成请求目标地址: if (Data2.Tasknum < 10000 && Data.Tasknum < 10000) throw new WarnException($"设备无任务信息"); break; case IstationRequest.请求分配目标地址: if (Data2.Tasknum < 10000 && Data.Tasknum < 10000) throw new WarnException($"设备无任务信息"); break; } //没有请求 if (type != IstationRequest.无 && Data2.Request != type) throw new WarnException($"有光电无{type}请求"); } /// /// 执行输送机任务 单例锁 /// /// public void EX(Action act) { try { if (ExDevice.Any(v => v == Entity.CODE)) throw new WarnException($"[{Entity.CODE}]--触发并发管控"); OperateExDevice(Entity.CODE); act(this); } catch (DoException ex) { ex.DoExceptionEX(Entity); } catch (WarnException ex) { ex.WarnExceptionEX(Entity); } catch (Exception ex) { ex.ExceptionEx(Entity); } finally { OperateExDevice(Entity.CODE); } } } /// /// RGV设备 /// public class RGVDevice : Device { static RGVDevice() { AllRGVList = Device.Where(v => v.IsRGV() && v.CODE != "RGV8").Select(v => v.Create()).ToList(); } public RGVDevice(WCS_DEVICE entity) : base(entity) { } /// /// 所有环穿RGV /// private static List AllRGVList { get; set; } /// /// 与当前RGV处于同一环穿的RGV /// public List RGVList { get { return AllRGVList.Where(v => v.Entity.PROTOCOLS.Any(d => Entity.PROTOCOLS.Any(e => e.DB.PLC.IP == d.DB.PLC.IP))) .Where(v => v.Entity.CODE != Entity.CODE).ToList(); } } /// /// RGV当前位置 /// public float Position { get { return Data2.Position; } } /// /// 与当前RGV处于同一环穿的站台 /// public List LocationList { get { return StationLocation.ALLlocations.Where(v => Entity.PROTOCOLS.Any(p => p.DB.PLC.CODE == v.PLC)) .Select(v => Device.Find(v.Station).Create()).ToList(); } } /// /// 总长度 /// public float Length { get { return LocationList.FirstOrDefault().Length; } } /// /// 执行RGV任务 单例锁 /// /// public void EX(Action act) { try { if (ExDevice.Any(v => v == Entity.CODE)) throw new WarnException($"[{Entity.CODE}]--触发并发管控"); OperateExDevice(Entity.CODE); act(this); } catch (DoException ex) { ex.DoExceptionEX(Entity); } catch (WarnException ex) { ex.WarnExceptionEX(Entity); } catch (Exception ex) { ex.ExceptionEx(Entity); } finally { OperateExDevice(Entity.CODE); } } /// /// 获取前一个取货点 /// /// public StationDeviceGroup BeforeStation() { return LocationList.Where(v => v.Entity.Is(DF.涂布RGV取货设备组)).OrderBy(v => Distance(v)).FirstOrDefault(); } /// /// 前一个RGV /// /// public RGVDevice Before() { //按照位置排序 var arr = RGVList.OrderBy(v => v.Position); var rgv = arr.FirstOrDefault(v => v.Position > Position); if (rgv == null) rgv = arr.LastOrDefault(v => v.Position < Position); return rgv; } /// /// 后一个RGV /// /// public RGVDevice After() { //到当前RGV最近的一个RGV return RGVList.OrderBy(v => v.Distance(this)).FirstOrDefault(); } /// /// 获取当前所在的取货站台 /// /// public StationDeviceGroup CurrentStation() { return LocationList.Where(v => v.Entity.Is(DF.涂布RGV取货设备组) || v.Entity.Is(DF.涂布RGV放货设备组)).Where(v => { //RGV与站台距离误差为 正负50500 var max = v.Position + 500; var min = v.Position - 500; return Data2.Position < max && Data2.Position > min; }).FirstOrDefault(); } /// /// 计算当前RGV与指定RGV之间的距离 /// /// /// public float Distance(RGVDevice rgv) { //return Math.Abs((Position - rgv.Position + Length) % Length); return DevEX.Distance(Position, rgv.Position, Length); } /// /// 计算当前RGV与指定R站台之间的距离 /// /// /// public float Distance(StationDeviceGroup after) { return DevEX.Distance(Position, after.Position, Length); } /// /// 是否需要执行放货任务 /// /// public bool IsPut() { if (Data2.TaskType_1 != RGVTaskType.取货) return false; if (!Data2.Status_1.HasFlag(WCS.Entity.Protocol.RGVStatus.RGV到站)) return false; if (!Data2.Status_1.HasFlag(WCS.Entity.Protocol.RGVStatus.任务完成)) return false; if (!Data2.Status_1.HasFlag(WCS.Entity.Protocol.RGVStatus.光电)) return false; return true; } /// /// 写入移动任务 /// /// 目标地址 public void Move(StationDeviceGroup addr) { if (!Data2.WorkMode.HasFlag(RGVMode.自动)) throw new WarnException($"RGV状态{Data2.WorkMode},无法执行移动任务"); if (!Data2.SystemStatus.HasFlag(RGVRunStatus.空闲)) throw new WarnException($"rgv状态为{Data2.SystemStatus},无法执行移动任务"); Data.TaskID_1 = addr.Entity.CODE.Replace("G", "").ToShort(); Data.TaskType_1 = RGVTaskType.移动; Data.DestPosition_1 = addr.Entity.CODE.Replace("G", "").ToShort(); Data.Trigger_1++; } /// /// 写入取货任务 /// /// 目标地址 public void Pick(StationDeviceGroup addr, int task1 = 0, int task2 = 0) { Data.TaskType_1 = RGVTaskType.取货; Data.DestPosition_1 = addr.Entity.CODE.ToShort(); if (task1 != 0) Data.TaskID_1 = task1; if (task2 != 0) Data.TaskID_2 = task2; Data.Trigger_1++; } /// /// 写入放货任务 /// /// 目标地址 public void Put(StationDeviceGroup addr, int task1 = 0, int task2 = 0) { Data.TaskType_1 = RGVTaskType.放货; Data.DestPosition_1 = addr.Entity.CODE.Replace("G", "").ToShort(); if (task1 != 0) Data.TaskID_1 = task1; if (task2 != 0) Data.TaskID_2 = task2; Data.Trigger_1++; } /// /// 筛选出所有与当前RGV距离小于指定长度的RGV /// /// 指定长度 /// public RGVDevice[] RgvAfter(float distance) { return RGVList.Where(v => Distance(v) < distance).ToArray(); } /// /// 当前RGV是否有拦住其他RGV /// /// RGV /// public bool StopedByMe(RGVDevice rgv) { //目标站台 var target = rgv.Data2.DestPosition_1; //获取目标站台的设备组信息 var station = Device.Find($"G{target}").Create(); //当前RGV与目标站台的距离小于传入RGV到达目标站台的距离 return (this.Distance(station) < rgv.Distance(station)) || station.CurrentRGV()?.Entity.CODE == this.Entity.CODE; } /// /// 获取当前RGV的下一个站台,即距离最近的一个站台 /// /// public StationDeviceGroup NextStation() { //先取当前RGV与所有站台的距离 var dev = LocationList.OrderBy(v => v.Distance(this)).FirstOrDefault(); return dev; } } /// /// 堆垛机设备 /// public class SRMDevice : Device { public SRMDevice(WCS_DEVICE entity) : base(entity) { } /// /// 获取放货点 /// public List GetDeliveryPoint() { return Entity.ROUTES.Select(v => v.NEXT) //巷道 .SelectMany(v => v.ROUTES.Select(d => d.NEXT)) //放货点 .Where(v => v.IsConv()) //必须是输送线 .Select(v => v.Create()).ToList(); } /// /// 获取取货点 /// public List GetPickPoint() { return Device.Where(v => v.Is(DF.SRM二级品取货) || v.Is(DF.SRM涂布取货)) .Where(v => v.ROUTES.Any(p => p.NEXT.ROUTES.Any(d => d.NEXT == Entity))) .Select(v => v.Create()) .ToList(); } /// /// 处理完成任务 /// public void FinishedTaskHandle() { WCS_TASK task = new WCS_TASK(); DB.Do(db => { var taskIds = new List() { Data2.FinishedTask_1, Data2.FinishedTask_2 }.ToArray(); for (int i = 0; i < taskIds.Length; i++) { //判断当前工位是否有完成任务 if (taskIds[i] == 0) continue; //获取当前工位的目标地址 var ELine = i == 0 ? Data.ELine_1.ToString() : Data.ELine_2.ToString(); task = db.Default.Set().Single(v => taskIds[i] == v.ID); if (task.STATUS != TaskStatus.堆垛机执行 && task.STATUS != TaskStatus.堆垛机完成) continue; if (task.STATUS == TaskStatus.堆垛机完成) { if (i == 0) Data.FinishedACK_1 = 1; else Data.FinishedACK_2 = 1; throw new DoException("二次处理堆垛机完成任务"); } if (task.TYPE == TaskType.入库) { task.ENDTIME = DateTime.Now; task.STATUS = TaskStatus.已完成; task.UPDATETIME = DateTime.Now; db.Default.SaveChanges(); } else if (task.TYPE == TaskType.出库) { task.STATUS = TaskStatus.堆垛机完成; task.UPDATETIME = DateTime.Now; db.Default.SaveChanges(); Uploader.Upload(db); } else if (task.TYPE == TaskType.移库) { if (task.STATUS == TaskStatus.堆垛机执行) { task.STATUS = TaskStatus.已完成; task.UPDATETIME = DateTime.Now; db.Default.SaveChanges(); Uploader.Upload(db); } } else throw new Exception($"[{Entity.CODE}]任务类型错误"); task.CreateStatusLog(db, $"状态由[{TaskStatus.堆垛机执行}]变更为[{task.STATUS}]", this.GetType()); } }); DB.Do(db => { var taskIds = new List() { Data2.FinishedTask_1, Data2.FinishedTask_2 }.ToArray(); for (int i = 0; i < taskIds.Length; i++) { //判断当前工位是否有完成任务 if (taskIds[i] == 0) continue; //获取当前工位的目标地址 var ELine = i == 0 ? Data.ELine_1.ToString() : Data.ELine_2.ToString(); task = db.Default.Set().Single(v => taskIds[i] == v.ID); if (task.TYPE == TaskType.入库 && task.STATUS == TaskStatus.已完成) { if (i == 0) Data.FinishedACK_1 = 1; else Data.FinishedACK_2 = 1; } else if (task.TYPE == TaskType.出库 && task.STATUS == TaskStatus.堆垛机完成) { var target = Device.Find(ELine).Create(); target.Data.Tasknum = task.ID; target.Data.Goodsstart = ELine.ToShort(); target.Data.Goodsend = task.ADDRNEXT.ToShort(); if (i == 0) Data.FinishedACK_1 = 1; else Data.FinishedACK_2 = 1; } else if (task.TYPE == TaskType.移库 && task.STATUS == TaskStatus.堆垛机完成) { if (i == 0) Data.FinishedACK_1 = 1; else Data.FinishedACK_2 = 1; } else throw new Exception($"[{Entity.CODE}]任务类型错误"); task.CreateStatusLog(db, $"状态由[{TaskStatus.堆垛机执行}]变更为[{task.STATUS}]", this.GetType()); } }); } /// /// 执行堆垛机任务 单例锁 /// /// public void EX(Action act) { try { if (ExDevice.Any(v => v == Entity.CODE)) throw new WarnException($"[{Entity.CODE}]--触发并发管控"); OperateExDevice(Entity.CODE); act(this); } catch (DoException ex) { ex.DoExceptionEX(Entity); } catch (WarnException ex) { ex.WarnExceptionEX(Entity); } catch (Exception ex) { ex.ExceptionEx(Entity); } finally { OperateExDevice(Entity.CODE); } } /// /// 执行出库任务 出库单例锁 /// /// public void EXOutStock(Action act) { try { var code = ""; if (Entity.CODE == "SRM3" || Entity.CODE == "SRM4") { code = "SRM3-SRM4-Out"; if (ExDevice.Any(v => v == code)) throw new WarnException($"触发出库并发管控--[{code}]"); OperateExDevice(code); } if (Entity.CODE == "SRM5" || Entity.CODE == "SRM6") { code = "SRM5-SRM6-Out"; if (ExDevice.Any(v => v == code)) throw new WarnException($"触发出库并发管控--[{code}]"); OperateExDevice(code); } if (Entity.CODE == "SRM7" || Entity.CODE == "SRM8") { code = "SRM7-SRM8-Out"; if (ExDevice.Any(v => v == code)) throw new WarnException($"触发出库并发管控--[{code}]"); OperateExDevice(code); } act(this); } finally { if (Entity.CODE == "SRM3" || Entity.CODE == "SRM4") OperateExDevice("SRM3-SRM4-Out"); if (Entity.CODE == "SRM5" || Entity.CODE == "SRM6") OperateExDevice("SRM5-SRM6-Out"); if (Entity.CODE == "SRM7" || Entity.CODE == "SRM8") OperateExDevice("SRM7-SRM8-Out"); } } /// /// 一工位写任务 /// /// public void WriteTask1(Task task) { InfoLog.INFO_SRMINFO($"写入堆垛机[{Entity.CODE}]1工位-开始:[{Data.TaskID_1}][{Data.SLine_1}][{Data.SCol_1}][{Data.SLayer_1}][{Data.ELine_1}][{Data.VoucherNo_1}]"); Data.TaskID_1 = task.ID; Data.SLine_1 = task.Line; Data.SCol_1 = task.Col; Data.SLayer_1 = task.Layer; Data.ELine_1 = task.SRMSTATION.ToShort(); Data.ECol_1 = 0; Data.ELayer_1 = 0; Data.VoucherNo_1++; InfoLog.INFO_SRMINFO($"写入堆垛机[{Entity.CODE}]1工位-结束:[{Data.TaskID_1}][{Data.SLine_1}][{Data.SCol_1}][{Data.SLayer_1}][{Data.ELine_1}][{Data.VoucherNo_1}]"); } /// /// 二工位写任务 /// /// public void WriteTask2(Task task) { InfoLog.INFO_SRMINFO($"写入堆垛机[{Entity.CODE}]2工位-开始:[{Data.TaskID_2}][{Data.SLine_2}][{Data.SCol_2}][{Data.SLayer_2}][{Data.ELine_2}][{Data.VoucherNo_2}]"); Data.TaskID_2 = task.ID; Data.SLine_2 = task.Line; Data.SCol_2 = task.Col; Data.SLayer_2 = task.Layer; Data.ELine_2 = task.SRMSTATION.ToShort(); Data.ECol_2 = 0; Data.ELayer_2 = 0; Data.VoucherNo_2++; InfoLog.INFO_SRMINFO($"写入堆垛机[{Entity.CODE}]2工位-结束:[{Data.TaskID_2}][{Data.SLine_2}][{Data.SCol_2}][{Data.SLayer_2}][{Data.ELine_2}][{Data.VoucherNo_2}]"); } /// /// 获取任务对应的货叉 /// /// 任务信息 /// 任务在下发任务集合中的索引 /// public SrmFork GetFork(Task task, int index) { short maxCol = (short)(Entity.CODE == "SRM1" ? 112 : 102); short min = 1; if (index > 1) throw new WarnException("一次最多下发两个任务"); //如果索引是1,直接返回货叉2 if (index == 1) return SrmFork.货叉2; //判断任务列是多少 return task.Col switch { 102 => Entity.CODE switch { "SRM1" => SrmFork.货叉1, _ => SrmFork.货叉2, }, 112 => SrmFork.货叉2, _ => SrmFork.货叉1, }; } /// /// 检查同组堆垛机是否有出库任务正在执行 /// public void CheckOutTask() { //检查同组堆垛机是否有正在执行出库任务的 DB.Do(db => { switch (Entity.CODE) { case "SRM3": if (db.Default.Set().Any(v => v.STATUS == TaskStatus.堆垛机执行 && v.DEVICE == "SRM4" && v.TYPE == TaskType.出库)) throw new DoException("SRM4正在执行出库任务"); break; case "SRM4": if (db.Default.Set().Any(v => v.STATUS == TaskStatus.堆垛机执行 && v.DEVICE == "SRM3" && v.TYPE == TaskType.出库)) throw new DoException("SRM3正在执行出库任务"); break; case "SRM5": if (db.Default.Set().Any(v => v.STATUS == TaskStatus.堆垛机执行 && v.DEVICE == "SRM6" && v.TYPE == TaskType.出库)) throw new DoException("SRM6正在执行出库任务"); break; case "SRM6": if (db.Default.Set().Any(v => v.STATUS == TaskStatus.堆垛机执行 && v.DEVICE == "SRM5" && v.TYPE == TaskType.出库)) throw new DoException("SRM5正在执行出库任务"); break; case "SRM7": if (db.Default.Set().Any(v => v.STATUS == TaskStatus.堆垛机执行 && v.DEVICE == "SRM7" && v.TYPE == TaskType.出库)) throw new DoException("SRM7正在执行出库任务"); break; case "SRM8": if (db.Default.Set().Any(v => v.STATUS == TaskStatus.堆垛机执行 && v.DEVICE == "SRM8" && v.TYPE == TaskType.出库)) throw new DoException("SRM8正在执行出库任务"); break; } }); } } /// /// 异常处理 /// public static class DevEX { /// /// 计算两点距离 /// /// 起始点 /// 结束点 /// 总长 /// public static float Distance(float start, float end, float total) { float distance = 0; if (start > end) distance = (total - start) + end; else distance = end - start; return distance; } public static void DoExceptionEX(this DoException ex, WCS_DEVICE Entity) { InfoLog.INFO_INFO($"[{Entity.CODE}]--{ex.Message}"); } public static void WarnExceptionEX(this WarnException ex, WCS_DEVICE Entity) { InfoLog.INFO_WARN($"[{Entity.CODE}]--{ex.Message}"); if (ex.Message.Contains("The database operation was expected")) return; LogHelper.AddWCS_EXCEPTION(ex.Message, Entity.CODE, WCS_EXCEPTIONTYPE.无.ToString()); //排除部分频繁触发的异常上报 if (ex.Message.Contains("触发并发管控")) return; Ltc.Log(ex.GetBaseException().Message); throw new Exception($"[{Entity.CODE}]--{ex.Message}"); } public static void ExceptionEx(this Exception ex, WCS_DEVICE Entity) { InfoLog.INFO_ERROR($"[{Entity.CODE}]--{ex.Message}"); //排除部分频繁触发的异常上报 if (ex.Message.Contains("Collection was modified; enumeration operation may not execute.")) return; Ltc.Log(ex.GetBaseException().Message); } } /// /// 堆垛机货叉/工位 /// public enum SrmFork { 货叉1 = 0, 货叉2 = 1, } /// /// 站台位置信息 /// public class StationLocation { /// /// 所有环穿站台的信息 /// public static List ALLlocations { get; set; } = new List(); static StationLocation() { ALLlocations.AddRange(new List() { //new StationLocation("G1187",0,"RGV1",0), //new StationLocation("G1196",0,"RGV1",0), //new StationLocation("G1205",0,"RGV1",0), //new StationLocation("G1214",0,"RGV1",0), //new StationLocation("G1222",0,"RGV1",0), //new StationLocation("G1164",0,"RGV1",0), new StationLocation("G1",486326,"RGV3",1567770), new StationLocation("G2",693631,"RGV3",1567770), new StationLocation("G3",789931,"RGV3",1567770), new StationLocation("G4",961595,"RGV3",1567770), new StationLocation("G5",1013350,"RGV3",1567770), new StationLocation("G6",1069938,"RGV3",1567770), new StationLocation("G7",1126338,"RGV3",1567770), new StationLocation("G8",1178355,"RGV3",1567770), new StationLocation("G9",1256875,"RGV3",1567770), new StationLocation("G10",1313239,"RGV3",1567770), new StationLocation("G11",1369970,"RGV3",1567770), }); } public StationLocation(string station, int location, string plc, int length) { Station = station; Location = location; PLC = plc; Length = length; } /// /// 输送机设备组编号 /// public string Station { get; set; } /// /// 输送机在环轨中的位置 /// public int Location { get; set; } /// /// 所属RGV组 PLC名称 /// public string PLC { get; set; } /// /// 所属环穿轨道的长度 /// public int Length { get; set; } } /// /// 巷道信息 /// public class TunnelInfo { public WCS_DEVICE Tunnel; public WCS_DEVICE taskIN; public Device SRM; } }