using PlcSiemens.Core.Extension; using ServiceCenter.Extensions; using ServiceCenter.Logs; using ServiceCenter.Redis; using WCS.Core; using WCS.Entity.Protocol.BCR; using WCS.Entity.Protocol.Robot; using WCS.Entity.Protocol.Station; using WCS.Entity.Protocol.Truss; namespace WCS.WorkEngineering.Extensions { /// /// 设备扩展 /// public static class DeviceExtension { #region 设备类型 public static List ProtocolInfos = new List(); /// /// 是否是巷道 /// /// 设备信息 /// public static bool IsTunnel(this Device source) { return source.HasFlag(DeviceFlags.巷道); } #endregion 设备类型 #region 标签判断 public static bool HasFlag(this Device device, params DeviceFlags[] flag) { return flag.Any(device.HasFlag); } #endregion 标签判断 #region 协议操作扩展 public static void AddProtocol(this Device device, int position, ushort db, string ip) { var info = new ProtocolInfo { Position = position, DBInfo = new DBInfo { No = db, PLCInfo = new PLCInfo { IP = ip, Port = 102, Rack = 0, Slot = 1, Type = PLCType.Siemens } } }; ProtocolInfos.Add(info); device.AddProtocol(info); } #endregion 协议操作扩展 #region 设备扩展方法 /// /// 入库站点是否被禁止 /// /// public static void 入库站点是否被禁止(this Device device) { var config = RedisHub.Default.Check("ForbidTubuEnter") ?? throw new Exception("请在Redis中配置入库口禁用"); var configs = config.Split(","); if (configs.Contains(device.Entity.Code)) throw new KnownException("当前入库口已被禁用,请联系运维人员了解具体情况", LogLevelEnum.High); } /// /// 入库站点是否被禁止 /// /// public static void 入库站点是否被禁止(this Device device) { var config = RedisHub.Default.Check("ForbidTubuEnter") ?? throw new Exception("请在Redis中配置入库口禁用"); var configs = config.Split(","); if (configs.Contains(device.Entity.Code)) throw new KnownException("当前入库口已被禁用,请联系运维人员了解具体情况", LogLevelEnum.High); } /// /// 入库站点是否被禁止 /// /// public static void 入库站点是否被禁止(this Device device) { var config = RedisHub.Default.Check("ForbidTubuEnter") ?? throw new Exception("请在Redis中配置入库口禁用"); var configs = config.Split(","); if (configs.Contains(device.Entity.Code)) throw new KnownException("当前入库口已被禁用,请联系运维人员了解具体情况", LogLevelEnum.High); } /// /// 入库站点是否被禁止 /// /// public static void 入库站点是否被禁止(this Device device) { var config = RedisHub.Default.Check("ForbidTubuEnter") ?? throw new Exception("请在Redis中配置入库口禁用"); var configs = config.Split(","); if (configs.Contains(device.Entity.Code)) throw new KnownException("当前入库口已被禁用,请联系运维人员了解具体情况", LogLevelEnum.High); } /// /// 入库站点是否满足执行条件 /// /// public static void 入库站点是否满足执行条件(this Device device) { } /// /// 入库站点是否满足执行条件 /// /// public static void 入库站点是否满足执行条件(this Device device) { if (device.Data.VoucherNo != device.Data2.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{device.Data.VoucherNo}-DB521:{device.Data2.VoucherNo}", LogLevelEnum.High); if (device.Data3.Status.HasFlag(StationStatus.Run)) throw new KnownException("设备运行中", LogLevelEnum.Low); if (device.Data3.Status.HasFlag(StationStatus.PH_Status) && device.Data2.Request == 0) throw new KnownException("有光电无请求", LogLevelEnum.Mid); if (!device.Data3.Status.HasFlag(StationStatus.PH_Status) && device.Data2.Request == 1) throw new KnownException("无光电有请求", LogLevelEnum.Mid); if (!device.Data3.Status.HasFlag(StationStatus.OT_Status)) throw new KnownException("站台货物信息与实际占用不一致", LogLevelEnum.Low); if (!device.Data3.Status.HasFlag(StationStatus.PH_Status)) throw new KnownException("无光电", LogLevelEnum.Mid); if (device.Data2.Request != 1) throw new KnownException("无请求", LogLevelEnum.Mid); } /// /// 入库站点是否满足执行条件 /// /// public static void 入库站点是否满足执行条件(this Device device) { if (device.Data.VoucherNo != device.Data2.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{device.Data.VoucherNo}-DB521:{device.Data2.VoucherNo}", LogLevelEnum.High); if (device.Data3.Status.HasFlag(StationStatus.Run)) throw new KnownException("设备运行中", LogLevelEnum.Low); if (device.Data3.Status.HasFlag(StationStatus.PH_Status) && device.Data2.Request == 0) throw new KnownException("有光电无请求", LogLevelEnum.Mid); if (!device.Data3.Status.HasFlag(StationStatus.PH_Status) && device.Data2.Request == 1) throw new KnownException("无光电有请求", LogLevelEnum.Mid); if (!device.Data3.Status.HasFlag(StationStatus.OT_Status)) throw new KnownException("站台货物信息与实际占用不一致", LogLevelEnum.Low); if (!device.Data3.Status.HasFlag(StationStatus.PH_Status)) throw new KnownException("无光电", LogLevelEnum.Mid); if (device.Data2.Request != 1) throw new KnownException("无请求", LogLevelEnum.Mid); } /// /// 入库站点是否满足执行条件 /// /// public static void 入库站点是否满足执行条件(this Device device) { if (device.Data.VoucherNo != device.Data2.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{device.Data.VoucherNo}-DB521:{device.Data2.VoucherNo}", LogLevelEnum.High); if (device.Data3.Status.HasFlag(StationStatus.Run)) throw new KnownException("设备运行中", LogLevelEnum.Low); if (device.Data3.Status.HasFlag(StationStatus.PH_Status) && device.Data2.Request == 0) throw new KnownException("有光电无请求", LogLevelEnum.Mid); if (!device.Data3.Status.HasFlag(StationStatus.PH_Status) && device.Data2.Request == 1) throw new KnownException("无光电有请求", LogLevelEnum.Mid); if (!device.Data3.Status.HasFlag(StationStatus.OT_Status)) throw new KnownException("站台货物信息与实际占用不一致", LogLevelEnum.Low); if (device.Data2.Request != 1.ToShort()) throw new KnownException("无请求", LogLevelEnum.Mid); if (!device.Data3.Status.HasFlag(StationStatus.PH_Status)) throw new KnownException("无光电", LogLevelEnum.Mid); if (device.Data2.Request != 1) throw new KnownException("无请求", LogLevelEnum.Mid); } /// /// 获取BCR码 /// /// public static string GetBCRCode(this IBCR81 bCR) { var barcode = bCR.Content.RemoveEscapeCharacters(); return barcode; } /// /// 获取历史扫码记录 /// /// public static List GetBcrCodeList(this IBCR83 bCR) { return new List() { bCR.BcrCode1.RemoveEscapeCharacters(), bCR.BcrCode2.RemoveEscapeCharacters(), bCR.BcrCode3.RemoveEscapeCharacters(), bCR.BcrCode4.RemoveEscapeCharacters(), bCR.BcrCode5.RemoveEscapeCharacters(), bCR.BcrCode6.RemoveEscapeCharacters(), bCR.BcrCode7.RemoveEscapeCharacters(), bCR.BcrCode8.RemoveEscapeCharacters(), bCR.BcrCode9.RemoveEscapeCharacters(), bCR.BcrCode10.RemoveEscapeCharacters(), bCR.BcrCode11.RemoveEscapeCharacters() }; } /// /// 获取缓存列表 /// /// public static IEnumerable GetBcrCodeList(this IStation525 station525) { var properties = station525.GetType().GetProperties().ToArray(); var index = 1; for (var i = 1; i <= 50; i++) { var value = properties[index].GetValue(station525).ToString().RemoveEscapeCharacters(); if (!value.IsNullOrEmpty()) yield return value; index += 7; } } /// /// 获取缓存列表 /// /// public static IEnumerable GetTaskNoList(this ITruss531 station525) { var properties = station525.GetType().GetProperties().ToArray(); var index = 0; for (var i = 0; i <= 59; i++) { var value = properties[index].GetValue(station525)!.ToInt(); if (value > 0) yield return value; index += 1; } } /// /// 获取缓存列表 /// /// public static IEnumerable GetTaskNoList(this IRobot531 station525) { var properties = station525.GetType().GetProperties().ToArray(); var index = 0; for (var i = 0; i <= 29; i++) { var value = properties[index].GetValue(station525)!.ToInt(); if (value > 0) yield return value; index += 1; } } /// /// 通过仓库编码获取对应堆垛机信息 /// /// 仓库编码 /// public static string WarehouseToSrm(this string warehouseCode) { return warehouseCode switch { "1N" => "SRM1", "1S" => "SRM2", "2N" => "SRM3", "2S" => "SRM4", "3N" => "SRM5", "3S" => "SRM6", _ => "Error" }; } #endregion 设备扩展方法 /// /// 获取仓库号 /// public static string GetWareCode(this string add) { return add switch { #region 库一 //北 "SRM1" => "1N", "2532" => "1N", "2527" => "1N", "2528" => "1N", "418" => "1N", "1606" => "1N", "1666" => "1NR", "1661" => "1NR", "18" => "1N", //南 "SRM2" => "1S", "2732" => "1S", "2727" => "1S", "2728" => "1S", "618" => "1S", "1676" => "1SR", "1681" => "1SR", #endregion 库一 #region 库二 //北 "SRM3" => "2N", "818" => "2N", "1691" => "2NR", "1696" => "2NR", //南 "SRM4" => "2S", "1018" => "2S", "3128" => "2S", "1711" => "2SR", "1706" => "2SR", #endregion 库二 #region 库二 //北 "SRM5" => "3N", "1218" => "3N", "1721" => "3NR", "1726" => "3NR", //南 "SRM6" => "3S", "1418" => "3S", "1736" => "3SR", "1741" => "3SR", #endregion 库二 _ => "", }; } } /// /// 设备标签 /// [Flags] public enum DeviceFlags : ulong { 扫码 = 1L << 0, 称重 = 1L << 1, 外检 = 1L << 2, 顶升 = 1L << 3, 移栽 = 1L << 4, 旋转 = 1L << 5, 入库 = 1L << 6, 出库 = 1L << 7, 巷道口 = 1L << 8, RGV口 = 1L << 9, AGV取货站台口 = 1L << 10, 直轨 = 1L << 11, 弯轨 = 1L << 12, 环轨 = 1L << 13, 巷道 = 1L << 14, 堆垛机 = 1L << 15, 输送机 = 1L << 16, #region 一轨双车堆垛机 一列堆垛机 = 1L << 23, 二列堆垛机 = 1L << 24, #endregion 一轨双车堆垛机 RGV = 1L << 25, 桁架 = 1L << 26, 一楼扫码 = 1L << 27, 满轮主线第一次扫码 = 1L << 28, 主线分流点 = 1L << 29, 一楼叠盘机 = 1L << 30, 环形库分流点 = 1L << 31, 桁架分流点 = 1L << 32, 桁架缓存放行点 = 1L << 33, 桁架取货点 = 1L << 34, 拆盘机 = 1L << 35, 桁架码垛位 = 1L << 36, 环形库码垛工位 = 1L << 37, Robot = 1L << 38, 桁架09缓存放行点 = 1L << 39, 桁架18缓存放行点 = 1L << 40, 桁架09异常缓存放行点 = 1L << 41, 二次码垛RGV取货口 = 1L << 42, 无交互触发设备 = 1L << 43, } /// /// 输送机段信息 /// public class StationSegmentInfo { /// /// 构造函数 /// /// 起始设备号 /// 结束设备号 /// ip public StationSegmentInfo(int start, int end, string ip) { Start = start; End = end; Ip = ip; } /// /// 起始设备编号 /// public int Start { get; set; } /// ///结束设备编号 /// public int End { get; set; } /// /// 输送机段所属IP /// public string Ip { get; set; } } /// /// RGV信息 /// public class RgvSegmentInfo { /// /// 构造函数 /// /// /// ip public RgvSegmentInfo(int code, string ip) { Code = code; Ip = ip; } /// /// 设备编号 /// public int Code { get; set; } /// /// 输送机段所属IP /// public string Ip { get; set; } } /// /// 桁架信息 /// public class TrussSegmentInfo { /// /// 构造函数 /// /// /// ip public TrussSegmentInfo(int code, string ip) { Code = code; Ip = ip; } /// /// 设备编号 /// public int Code { get; set; } /// /// 输送机段所属IP /// public string Ip { get; set; } } /// /// 扫码器信息 /// public class BcrInfo { /// /// 构造函数 /// /// 设备编号 /// ip public BcrInfo(string[] deviceNo, string ip) { DeviceNo = deviceNo; Ip = ip; } /// /// 设备编号 /// public string[] DeviceNo { get; set; } /// /// ip /// public string Ip { get; set; } } /// /// 外形信息 /// public class ShapeInfo { /// /// 构造函数 /// /// 设备编号 /// ip public ShapeInfo(int[] deviceNo, string ip) { DeviceNo = deviceNo; Ip = ip; } /// /// 设备编号 /// public int[] DeviceNo { get; set; } /// /// ip /// public string Ip { get; set; } } /// /// 路径信息 /// public class RouteInfo { /// /// 构造函数 /// /// 起始点设备号 /// 下一个设备集合 public RouteInfo(string deviceCode, string[] nextList) { DeviceCode = deviceCode; NextList = nextList; } /// /// 设备号 /// public string DeviceCode { get; set; } /// /// 下一个设备 /// public string[] NextList { get; set; } } /// /// 缓存分流信息 /// public class CacheBcr { public CacheBcr(string bcrCode, short nextAdd) { BcrCode = bcrCode; NextAdd = nextAdd; } /// /// 条码 /// public string BcrCode { get; set; } /// /// 下一个地址 /// public short NextAdd { get; set; } } }