123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473 |
- 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;
- namespace WCS.Service.Extensions
- {
- /// <summary>
- /// 输送机设备组
- /// </summary>
- public class StationDeviceGroup : DeviceGroup<IStation520, IStation521, IStation523>
- {
- public StationDeviceGroup(WCS_DEVICE entity) : base(entity)
- {
- }
- private List<RGVDevice> RGVs;
- /// <summary>
- /// 设备组自身的位置
- /// </summary>
- public float Position
- {
- get
- {
- return StationLocation.ALLlocations.FirstOrDefault(v => v.Station == Entity.CODE).Location;
- }
- }
- /// <summary>
- /// 设备组所在环穿的总长度
- /// </summary>
- public float Length
- {
- get
- {
- return StationLocation.ALLlocations.FirstOrDefault(v => v.Station == Entity.CODE).Length;
- }
- }
- /// <summary>
- /// 设备组是否满足任务执行条件
- /// </summary>
- /// <param name="type">给当前设备组下发任务时需要的请求</param>
- /// <returns>true:不满足执行条件需要进行停止执行 false:表示满足条件不需要停止执行 </returns>
- /// <exception cref="Exception"></exception>
- public bool WhetherToExecute(IstationRequest type = IstationRequest.无)
- {
- //当前组有一个运行的设备就停止执行
- if (Items.Any(v => v.Data3.Status.HasFlag(StationStatus.运行状态位))) return true;
- //设备组中没有设备有光带信息
- if (!Items.Any(v => v.Data2.Status.HasFlag(IstationStatus.光电状态))) return true;
- ////有光电无任务
- //if (Items.Any(v => v.Data2.Status.HasFlag(IstationStatus.光电状态) && v.Data2.Tasknum < 10000))
- // throw new Exception(LogHelper.SpliceLogMessage("有光电无任务", Entity.CODE, WCS_EXCEPTIONTYPE.设备异常));
- ////有光电有任务无请求
- //if (Items.Any(v => v.Data2.Status.HasFlag(IstationStatus.光电状态) && v.Data2.Tasknum < 10000 && (type != IstationRequest.无 && v.Data2.Request != type)))
- // throw new Exception(LogHelper.SpliceLogMessage($"有光电有任务无 {type} 请求", Entity.CODE, WCS_EXCEPTIONTYPE.设备异常));
- return false;
- }
- /// <summary>
- /// 获取设备组中需要取货的设备
- /// </summary>
- /// <param name="obj"></param>
- /// <returns></returns>
- public List<Device<IStation520, IStation521, IStation523>> 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;
- }
- /// <summary>
- /// 获取设备组中需要分配目标地址的设备
- /// </summary>
- /// <param name="obj"></param>
- /// <returns></returns>
- public List<Device<IStation520, IStation521, IStation523>> 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;
- }
- /// <summary>
- ///
- /// </summary>
- /// <returns></returns>
- public RGVDevice NextRGV()
- {
- return new RGVDevice(new WCS_DEVICE());
- }
- /// <summary>
- /// 计算目标RGV与站台自身的距离
- /// </summary>
- /// <param name="rgv"></param>
- /// <returns></returns>
- public float Distance(RGVDevice rgv)
- {
- return Math.Abs((Position - rgv.Position + Length) % Length);
- }
- /// <summary>
- /// 当前RGV
- /// </summary>
- /// <returns></returns>
- public RGVDevice CurrentRGV()
- {
- return new RGVDevice(new WCS_DEVICE());
- }
- /// <summary>
- /// 是否需要RGV
- /// </summary>
- /// <returns>true:需要RGV false:不需要RGV</returns>
- public bool NeedRgv()
- {
- var rgvs = Device.Where(v => v.IsRGV()).Select(v => v.Device<IRGV521>());
- var code = Entity.CODE.Replace("G", "").ToShort();
- if (rgvs.Any(v => v.Data.DestPosition_1 == code && v.Data.SystemStatus != RGVRunStatus.空闲))
- throw new Exception(LogHelper.SpliceLogMessage("已有RGV执行中", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常, GetType()));
- foreach (var item in Items)
- {
- if (item.Data3.Status.HasFlag(StationStatus.运行状态位)) return false;
- if (!item.Data2.Status.HasFlag(IstationStatus.光电状态)) return false;
- }
- return true;
- }
- }
- /// <summary>
- /// 输送机设备
- /// </summary>
- public class StationDevice : Device<IStation520, IStation521, IStation523>
- {
- public StationDevice(WCS_DEVICE entity) : base(entity)
- {
- }
- /// <summary>
- /// 设备组是否满足任务执行条件
- /// </summary>
- /// <param name="type">给当前设备组下发任务时需要的请求</param>
- /// <returns>true:不满足执行条件需要进行停止执行 false:表示满足条件不需要停止执行 </returns>
- /// <exception cref="Exception"></exception>
- public bool WhetherToExecute(IstationRequest type = IstationRequest.无)
- {
- //正在运行
- if (Data3.Status.HasFlag(StationStatus.运行状态位)) return true;
- //上一次的任务还未执行
- if (Data.VoucherNo != Data2.VoucherNo)
- throw new Exception(LogHelper.SpliceLogMessage($"等待任务[{Data2.Tasknum}]执行", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常, GetType()));
- //没有光电
- if (!Data2.Status.HasFlag(IstationStatus.光电状态)) return true;
- //没有任务号
- switch (type)
- {
- case IstationRequest.无:
- if (Data2.Tasknum < 10000 && Data.Tasknum < 10000)
- throw new Exception(LogHelper.SpliceLogMessage($"设备无任务", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常, GetType()));
- break;
- case IstationRequest.扫码入库:
- if (Data2.Tasknum > 10000 && Data.Tasknum > 10000)
- throw new Exception(LogHelper.SpliceLogMessage($"设备已有任务任务", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常, GetType()));
- break;
- case IstationRequest.堆垛机放货完成请求目标地址:
- if (Data2.Tasknum < 10000 && Data.Tasknum < 10000)
- throw new Exception(LogHelper.SpliceLogMessage($"设备无任务信息", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常, GetType()));
- break;
- case IstationRequest.请求分配目标地址:
- if (Data2.Tasknum < 10000 && Data.Tasknum < 10000)
- throw new Exception(LogHelper.SpliceLogMessage($"设备无任务信息", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常, GetType()));
- break;
- }
- //没有请求
- if (type != IstationRequest.无 && Data2.Request != type)
- throw new Exception(LogHelper.SpliceLogMessage($"有光电无{type}请求", Entity.CODE, WCS_EXCEPTIONTYPE.设备异常, GetType()));
- return false;
- }
- }
- /// <summary>
- /// RGV设备
- /// </summary>
- public class RGVDevice : Device<IRGV520, IRGV521, IRGV523>
- {
- static RGVDevice()
- {
- AllRGVList = Device.Where(v => v.IsRGV() && v.CODE != "RGV8").Select(v => v.Create<RGVDevice>()).ToList();
- }
- public RGVDevice(WCS_DEVICE entity) : base(entity)
- {
- }
- /// 所有环穿RGV
- /// </summary>
- private static List<RGVDevice> AllRGVList { get; set; }
- /// <summary>
- /// 与当前RGV处于同一环穿的RGV
- /// </summary>
- public List<RGVDevice> RGVList
- {
- get
- {
- return AllRGVList.Where(v => v.Entity.PROTOCOLS.Any(d => Entity.PROTOCOLS.Any(e => e.DB.ID == d.DB.ID)))
- .Where(v => v.Entity.CODE != Entity.CODE).ToList();
- }
- }
- /// <summary>
- /// RGV当前位置
- /// </summary>
- public float Position
- {
- get
- {
- return Data2.Position;
- }
- }
- /// <summary>
- /// 与当前RGV处于同一环穿的RGV
- /// </summary>
- public List<StationLocation> LocationList
- {
- get
- {
- return StationLocation.ALLlocations.Where(v => Entity.PROTOCOLS.Any(p => p.DB.PLC.CODE == v.PLC)).ToList();
- }
- }
- /// <summary>
- /// 总长度
- /// </summary>
- public float Length
- {
- get
- {
- return LocationList.FirstOrDefault().Length;
- }
- }
- /// <summary>
- /// 前一个RGV
- /// </summary>
- /// <returns></returns>
- 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;
- }
- /// <summary>
- /// 后一个RGV
- /// </summary>
- /// <returns></returns>
- public RGVDevice After()
- {
- 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;
- }
- /// <summary>
- /// 计算当前RGV与指定RGV之间的距离
- /// </summary>
- /// <param name="after"></param>
- /// <returns></returns>
- public float Distance(RGVDevice after)
- {
- return Math.Abs((Position - after.Position + Length) % Length);
- }
- /// <summary>
- /// 是否可用
- /// </summary>
- /// <returns></returns>
- public bool Valid()
- {
- return true;
- }
- /// <summary>
- /// 写入移动任务
- /// </summary>
- /// <param name="addr">目标地址</param>
- public void Move(StationDeviceGroup addr)
- {
- }
- /// <summary>
- /// 写入取货任务
- /// </summary>
- /// <param name="addr">目标地址</param>
- public void Pick(StationDeviceGroup addr)
- {
- }
- /// <summary>
- /// 写入放货任务
- /// </summary>
- /// <param name="addr">目标地址</param>
- public void Put(StationDeviceGroup addr)
- {
- }
- /// <summary>
- /// 筛选出所有与当前RGV距离小于指定长度的RGV
- /// </summary>
- /// <param name="distance">指定长度</param>
- /// <returns></returns>
- public RGVDevice[] RgvAfter(float distance)
- {
- return RGVList.Where(v => Distance(v) < distance).ToArray();
- }
- /// <summary>
- /// 当前RGV是否有拦住传入RGV
- /// </summary>
- /// <param name="rgv">RGV</param>
- /// <returns></returns>
- public bool StopedByMe(RGVDevice rgv)
- {
- //目标站台
- var target = rgv.Data2.DestPosition_1;
- //获取目标站台的设备组信息
- var station = Device.Find($"G{target}").Create<StationDeviceGroup>();
- //当前RGV与目标站台的距离小于传入RGV到达目标站台的距离
- return station.Distance(this) < station.Distance(rgv);
- }
- /// <summary>
- /// 获取当前RGV的下一个站台,即距离最近的一个站台
- /// </summary>
- /// <returns></returns>
- public StationDeviceGroup NextStation()
- {
- //先取当前RGV与所有站台的距离
- var dev = LocationList.OrderBy(v =>
- {
- var dev = Device.Find(v.Station).Create<StationDeviceGroup>();
- return dev.Distance(this);
- }).FirstOrDefault();
- return Device.Find(dev.Station).Create<StationDeviceGroup>(); ;
- }
- }
- /// <summary>
- /// 堆垛机设备
- /// </summary>
- public class SRMDevice : Device<ISRM520, ISRM521, ISRM537>
- {
- public SRMDevice(WCS_DEVICE entity) : base(entity)
- {
- }
- /// <summary>
- /// 获取放货点
- /// </summary>
- public List<StationDevice> GetDeliveryPoint()
- {
- return Entity.ROUTES.Select(v => v.NEXT) //巷道
- .SelectMany(v => v.ROUTES.Select(d => d.NEXT)) //放货点
- .Where(v => v.IsConv()) //必须是输送线
- .Select(v => v.Create<StationDevice>()).ToList();
- }
- /// <summary>
- /// 获取取货点
- /// </summary>
- public List<StationDevice> GetPickPoint()
- {
- return Device.Where(v => v.Is(DF.SRM取货))
- .Where(v => v.ROUTES.Any(p => p.NEXT.ROUTES.Any(d => d.NEXT == Entity)))
- .Select(v => v.Create<StationDevice>())
- .ToList();
- }
- }
- /// <summary>
- /// 站台位置信息
- /// </summary>
- public class StationLocation
- {
- /// <summary>
- /// 所有环穿站台的信息
- /// </summary>
- public static List<StationLocation> ALLlocations { get; set; }
- static StationLocation()
- {
- ALLlocations.AddRange(new List<StationLocation>() {
- 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("G1285",0,"RGV3",0),
- new StationLocation("G1401",0,"RGV3",0),
- new StationLocation("G1294",0,"RGV3",0),
- new StationLocation("G1410",0,"RGV3",0),
- new StationLocation("G1303",0,"RGV3",0),
- new StationLocation("G1417",0,"RGV3",0),
- new StationLocation("G1412",0,"RGV3",0),
- new StationLocation("G1426",0,"RGV3",0),
- new StationLocation("G1332",0,"RGV3",0),
- new StationLocation("G1391",0,"RGV3",0),
- new StationLocation("G1399",0,"RGV3",0),
- });
- }
- public StationLocation(string station, int location, string plc, int length)
- {
- Station = station;
- Location = location;
- PLC = plc;
- Length = length;
- }
- /// <summary>
- /// 输送机设备组编号
- /// </summary>
- public string Station { get; set; }
- /// <summary>
- /// 输送机在环轨中的位置
- /// </summary>
- public int Location { get; set; }
- /// <summary>
- /// 所属PLC名称
- /// </summary>
- public string PLC { get; set; }
- /// <summary>
- /// 所属环穿轨道的长度
- /// </summary>
- public int Length { get; set; }
- }
- /// <summary>
- /// 巷道信息
- /// </summary>
- public class TunnelInfo
- {
- public WCS_DEVICE Tunnel;
- public WCS_DEVICE taskIN;
- public Device<ISRM520, ISRM521, ISRM537> SRM;
- }
- }
|