|
@@ -4,6 +4,7 @@ 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
|
|
@@ -13,10 +14,32 @@ namespace WCS.Service.Extensions
|
|
|
/// </summary>
|
|
|
public class StationDeviceGroup : DeviceGroup<IStation520, IStation521, IStation523>
|
|
|
{
|
|
|
+ public StationDeviceGroup(WCS_DEVICE entity) : base(entity)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
private List<RGVDevice> RGVs;
|
|
|
|
|
|
- public StationDeviceGroup(WCS_DEVICE entity) : base(entity)
|
|
|
+ /// <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>
|
|
@@ -62,35 +85,55 @@ namespace WCS.Service.Extensions
|
|
|
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.ToString() == v.Entity.CODE && v.Data2.Goodsend != 0)
|
|
|
+ .Where(v => v.Data2.Goodsend != 0)
|
|
|
.ToList();
|
|
|
return a.Count == 0 ? null : a;
|
|
|
}
|
|
|
|
|
|
- public float Position { get; }
|
|
|
- public float Length { get; }
|
|
|
-
|
|
|
+ /// <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></returns>
|
|
|
+ /// <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;
|
|
|
}
|
|
|
}
|
|
@@ -116,35 +159,35 @@ namespace WCS.Service.Extensions
|
|
|
if (Data3.Status.HasFlag(StationStatus.运行状态位)) return true;
|
|
|
//上一次的任务还未执行
|
|
|
if (Data.VoucherNo != Data2.VoucherNo)
|
|
|
- throw new Exception(LogHelper.SpliceLogMessage($"等待任务[{Data2.Tasknum}]执行", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常));
|
|
|
+ throw new Exception(LogHelper.SpliceLogMessage($"等待任务[{Data2.Tasknum}]执行", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常, GetType()));
|
|
|
//没有光电
|
|
|
if (!Data2.Status.HasFlag(IstationStatus.光电状态)) return true;
|
|
|
+ //没有请求
|
|
|
+ if (type != IstationRequest.无 && Data2.Request != type)
|
|
|
+ throw new Exception(LogHelper.SpliceLogMessage($"有光电有任务无 {type}", Entity.CODE, WCS_EXCEPTIONTYPE.设备异常, GetType()));
|
|
|
//没有任务号
|
|
|
switch (type)
|
|
|
{
|
|
|
case IstationRequest.无:
|
|
|
- if (Data2.Tasknum > 10000)
|
|
|
- throw new Exception(LogHelper.SpliceLogMessage($"设备已有任务任务", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常));
|
|
|
+ if (Data2.Tasknum < 10000 && Data.Tasknum < 10000)
|
|
|
+ throw new Exception(LogHelper.SpliceLogMessage($"设备已有任务任务", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常, GetType()));
|
|
|
break;
|
|
|
|
|
|
case IstationRequest.扫码入库:
|
|
|
- if (Data2.Tasknum > 10000)
|
|
|
- throw new Exception(LogHelper.SpliceLogMessage($"设备已有任务任务", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常));
|
|
|
+ if (Data2.Tasknum < 10000 && Data.Tasknum < 10000)
|
|
|
+ throw new Exception(LogHelper.SpliceLogMessage($"设备已有任务任务", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常, GetType()));
|
|
|
break;
|
|
|
|
|
|
case IstationRequest.堆垛机放货完成请求目标地址:
|
|
|
- if (Data2.Tasknum < 10000)
|
|
|
- throw new Exception(LogHelper.SpliceLogMessage($"设备无任务信息", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常));
|
|
|
+ if (Data2.Tasknum < 10000 && Data.Tasknum < 10000)
|
|
|
+ throw new Exception(LogHelper.SpliceLogMessage($"设备无任务信息", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常, GetType()));
|
|
|
break;
|
|
|
|
|
|
case IstationRequest.请求分配目标地址:
|
|
|
- if (Data2.Tasknum < 10000)
|
|
|
- throw new Exception(LogHelper.SpliceLogMessage($"设备无任务信息", Entity.CODE, WCS_EXCEPTIONTYPE.逻辑异常));
|
|
|
+ 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.设备异常));
|
|
|
|
|
|
return false;
|
|
|
}
|
|
@@ -155,49 +198,62 @@ namespace WCS.Service.Extensions
|
|
|
/// </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();
|
|
|
+ }
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// 涂布环穿 位置配置
|
|
|
+ public RGVDevice(WCS_DEVICE entity) : base(entity)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 所有环穿RGV
|
|
|
/// </summary>
|
|
|
- private static List<RGVStationLocation> Coating = new List<RGVStationLocation>();
|
|
|
+ private static List<RGVDevice> AllRGVList { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
- /// 拉膜环穿 位置配置
|
|
|
+ /// 与当前RGV处于同一环穿的RGV
|
|
|
/// </summary>
|
|
|
- private static List<RGVStationLocation> PullFilm = new List<RGVStationLocation>();
|
|
|
-
|
|
|
- public float Position
|
|
|
+ public List<RGVDevice> RGVList
|
|
|
{
|
|
|
get
|
|
|
{
|
|
|
- return Data2.Position;
|
|
|
+ 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();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private static List<RGVDevice> AllRGVList
|
|
|
- {
|
|
|
- get; set;
|
|
|
- }
|
|
|
-
|
|
|
- static RGVDevice()
|
|
|
+ /// <summary>
|
|
|
+ /// RGV当前位置
|
|
|
+ /// </summary>
|
|
|
+ public float Position
|
|
|
{
|
|
|
- AllRGVList = Device.Where(v => v.IsRGV() && v.CODE != "RGV8").Select(v => v.Create<RGVDevice>()).ToList();
|
|
|
+ get
|
|
|
+ {
|
|
|
+ return Data2.Position;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- public float Length { get; }
|
|
|
-
|
|
|
- public List<RGVDevice> RGVList
|
|
|
+ /// <summary>
|
|
|
+ /// 与当前RGV处于同一环穿的RGV
|
|
|
+ /// </summary>
|
|
|
+ public List<StationLocation> LocationList
|
|
|
{
|
|
|
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();
|
|
|
+ return StationLocation.ALLlocations.Where(v => Entity.PROTOCOLS.Any(p => p.DB.PLC.CODE == v.PLC)).ToList();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public RGVDevice(WCS_DEVICE entity) : base(entity)
|
|
|
+ /// <summary>
|
|
|
+ /// 总长度
|
|
|
+ /// </summary>
|
|
|
+ public float Length
|
|
|
{
|
|
|
+ get
|
|
|
+ {
|
|
|
+ return LocationList.FirstOrDefault().Length;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
@@ -206,7 +262,8 @@ namespace WCS.Service.Extensions
|
|
|
/// <returns></returns>
|
|
|
public RGVDevice Before()
|
|
|
{
|
|
|
- var arr = AllRGVList.OrderBy(v => v.Position);
|
|
|
+ //按照位置排序
|
|
|
+ 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);
|
|
@@ -219,11 +276,15 @@ namespace WCS.Service.Extensions
|
|
|
/// <returns></returns>
|
|
|
public RGVDevice After()
|
|
|
{
|
|
|
- return new RGVDevice(new WCS_DEVICE());
|
|
|
+ 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与指定RGV之间的距离
|
|
|
/// </summary>
|
|
|
/// <param name="after"></param>
|
|
|
/// <returns></returns>
|
|
@@ -242,40 +303,67 @@ namespace WCS.Service.Extensions
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// 移动
|
|
|
+ /// 写入移动任务
|
|
|
/// </summary>
|
|
|
- /// <param name="addr"></param>
|
|
|
+ /// <param name="addr">目标地址</param>
|
|
|
public void Move(StationDeviceGroup addr)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// 选择出库
|
|
|
+ /// 写入取货任务
|
|
|
/// </summary>
|
|
|
- /// <param name="addr"></param>
|
|
|
+ /// <param name="addr">目标地址</param>
|
|
|
public void Pick(StationDeviceGroup addr)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
- public void Put()
|
|
|
+ /// <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 AllRGVList.Where(v => Distance(v) < distance).ToArray();
|
|
|
+ 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()
|
|
|
{
|
|
|
- return new StationDeviceGroup(new WCS_DEVICE());
|
|
|
+ //先取当前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>(); ;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -296,18 +384,49 @@ namespace WCS.Service.Extensions
|
|
|
return Entity.ROUTES.Select(v => v.NEXT) //巷道
|
|
|
.SelectMany(v => v.ROUTES.Select(d => d.NEXT)) //放货点
|
|
|
.Where(v => v.IsConv()) //必须是输送线
|
|
|
- .Select(v => new StationDevice(v)).ToList();
|
|
|
+ .Select(v => v.Create<StationDevice>()).ToList();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public class RGVStationLocation
|
|
|
+ /// <summary>
|
|
|
+ /// 站台位置信息
|
|
|
+ /// </summary>
|
|
|
+ public class StationLocation
|
|
|
{
|
|
|
- public RGVStationLocation(string station, string stationLocation, string startingPoint, string endPoint)
|
|
|
+ /// <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;
|
|
|
- StationLocation = stationLocation;
|
|
|
- StartingPoint = startingPoint;
|
|
|
- EndPoint = endPoint;
|
|
|
+ Location = location;
|
|
|
+ PLC = plc;
|
|
|
+ Length = length;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
@@ -318,16 +437,26 @@ namespace WCS.Service.Extensions
|
|
|
/// <summary>
|
|
|
/// 输送机在环轨中的位置
|
|
|
/// </summary>
|
|
|
- public string StationLocation { get; set; }
|
|
|
+ public int Location { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
- /// RGV起始
|
|
|
+ /// 所属PLC名称
|
|
|
/// </summary>
|
|
|
- public string StartingPoint { get; set; }
|
|
|
+ public string PLC { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
- /// RGV结束
|
|
|
+ /// 所属环穿轨道的长度
|
|
|
/// </summary>
|
|
|
- public string EndPoint { get; set; }
|
|
|
+ public int Length { get; set; }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 巷道信息
|
|
|
+ /// </summary>
|
|
|
+ public class TunnelInfo
|
|
|
+ {
|
|
|
+ public WCS_DEVICE Tunnel;
|
|
|
+ public WCS_DEVICE taskIN;
|
|
|
+ public Device<ISRM520, ISRM521, ISRM537> SRM;
|
|
|
}
|
|
|
}
|