Browse Source

update wcs.core

林豪 左 2 years ago
parent
commit
c423a403c6

+ 8 - 8
WCS.Core/Data.cs

@@ -22,22 +22,22 @@ namespace WCS.Core
 
     public struct PLCInfo
     {
-        public string IP;
-        public int Port;
-        public int Slot;
-        public int Rack;
-        public PLCType Type;
+        public string IP { get; set; }
+        public int Port { get; set; }
+        public int Slot { get; set; }
+        public int Rack { get; set; }
+        public PLCType Type { get; set; }
     }
 
     public struct DBInfo
     {
-        public PLCInfo PLCInfo;
-        public ushort No;
+        public PLCInfo PLCInfo { get; set; }
+        public ushort No { get; set; }
     }
 
     public struct ProtocolInfo
     {
-        public DBInfo DBInfo;
+        public DBInfo DBInfo { get; set; }
         public int Position { get; set; } 
     }
 

+ 199 - 26
WCS.Core/Device.cs

@@ -2,7 +2,10 @@
 using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Linq;
+using System.Net.Http.Headers;
+using System.Runtime.Serialization;
 using System.Text;
+using System.Text.Json.Serialization;
 using System.Threading.Tasks;
 
 namespace WCS.Core
@@ -19,68 +22,238 @@ namespace WCS.Core
 
     public class Device
     {
+        static ConcurrentDictionary<string, Device> all = new ConcurrentDictionary<string, Device>();
+        public static IEnumerable<Device> All
+        {
+            get
+            {
+                return all.Values;
+            }
+        }
+
+        public static Device Find(string code)
+        {
+            if (all.TryGetValue(code, out var dev))
+                return dev;
+            else
+                throw new Exception($"未找到设备{code}");
+        }
+
+
         public string Code { get; set; } = "";
-        public World World { get; set; }
 
-        ConcurrentDictionary<Type, object> ProtocolObjs = new ConcurrentDictionary<Type, object>();
+        public Dictionary<string, ProtocolInfo> Protocols { get; private set; } = new Dictionary<string, ProtocolInfo>();
+
+        public Device(string code)
+        {
+            if (all.ContainsKey(code))
+                throw new Exception($"{code}设备号重复");
+            this.Code = code;
+            all[code] = this;
+        }
+
+        ConcurrentDictionary<Type, object> ProtocolObjs(World world)
+        {
+            if (!ProtocolObjsOfWorld.TryGetValue(world, out var pobjs))
+            {
+                pobjs = new ConcurrentDictionary<Type, object>();
+                ProtocolObjsOfWorld[world] = pobjs;
+            }
+            return pobjs;
+        }
+
+        ConcurrentDictionary<World, ConcurrentDictionary<Type, object>> ProtocolObjsOfWorld = new ConcurrentDictionary<World, ConcurrentDictionary<Type, object>>();
+
+        public void AddProtocol(Type type, ProtocolInfo info)
+        {
+            if (!Protocols.TryAdd(type.AssemblyQualifiedName, info))
+                throw new Exception($"{Code}重复添加协议{type.Name}"); 
+        }
+        public void AddProtocol<T>(ProtocolInfo info)
+        {
+            AddProtocol(typeof(T), info);
+        }
 
         public bool HasProtocol(Type type)
         {
-            return Protocols.HasProtocol(type, Code);
-            //return ProtocolObjs.ContainsKey(type);
+            return Protocols.ContainsKey(type.AssemblyQualifiedName);
         }
         public bool HasProtocol<T>()
-        { 
+        {
             return HasProtocol(typeof(T));
         }
 
-        public T Protocol<T>()
+        public T Protocol<T>(World world)
         {
-            return (T)Protocol(typeof(T));
+            return (T)Protocol(typeof(T), world);
         }
 
-        public object Protocol(Type protocolType)
+        public object Protocol(Type protocolType, World world)
         {
-            if (!ProtocolObjs.ContainsKey(protocolType))
+            if (!HasProtocol(protocolType))
+                throw new Exception($"{Code}不包含协议:{protocolType.Name}");
+
+            if (!ProtocolObjs(world).ContainsKey(protocolType))
             {
                 var type = typeof(Generator<,>);
                 type = type.MakeGenericType(protocolType, Configs.ProtocolProxyBaseType);
                 var m = type.GetMethod("Create", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
 
-                var info = Protocols.Get(protocolType, Code);
-                var obj = m.Invoke(null, new object[] { new object[] { this, info, protocolType } });
-                ProtocolObjs[protocolType] = obj;
+                var info = Protocols[protocolType.AssemblyQualifiedName];
+                var obj = m.Invoke(null, new object[] { new object[] { this, info, protocolType, world } });
+                ProtocolObjs(world)[protocolType] = obj;
             }
-            return ProtocolObjs[protocolType];
+            return ProtocolObjs(world)[protocolType];
         }
 
         public override string ToString()
         {
             return Code;
+        }
+
+         
+        [JsonIgnore]
+        public IEnumerable<Device> Targets
+        {
+            get
+            {
+                return GetFlags("Target").Select(v => Device.all[v]).ToList(); 
+            }
+        }
+
+        [JsonIgnore]
+        public IEnumerable<Device> Sources
+        {
+            get 
+            {
+                return Device.All.Where(v => v.GetFlags("Target").Contains(this.Code)).ToArray();
+            }
+        }
+
+        public void AddTarget(params string[] codes)
+        {           
+            foreach (var code in codes)
+            {
+                if (HasFlag("Target", code))
+                    throw new Exception($"{this.Code}已经存在目的地:{code}");
+                AddFlag("Target", code);
+            }            
+        }
+
+
+        [JsonIgnore]
+        public Device? Parent
+        {
+            get
+            {
+                var code = GetFlag("Parent");
+                if (string.IsNullOrEmpty(code))
+                    return null;
+                return Device.Find(code);
+            }
+            set
+            {
+                SetFlag("Parent", value.Code);
+            }
         } 
          
+
+        public Dictionary<string, List<string>> Flags { get; private set; } = new Dictionary<string, List<string>>();
+
+        public void AddFlag(string key,string flag)
+        {
+            if (!Flags.ContainsKey(key))
+                Flags[key] = new List<string>();
+            Flags[key].Add(flag);
+        }
+
+        public void SetFlag(string key, string flag)
+        { 
+            var list=new List<string>();
+            list.Add(flag);
+            Flags[key] = list;
+        }
+
+        public IEnumerable<string> GetFlags(string key)
+        {
+            if (!Flags.ContainsKey(key))
+                return new List<string>();
+            return Flags[key];
+        }
+
+        public string? GetFlag(string key)
+        {
+            return GetFlags(key).FirstOrDefault();
+        }
+
+
+        public bool HasFlag(string key, string flag)
+        {
+            if(!Flags.ContainsKey(key))
+                return false;
+            return Flags[key].Contains(flag);
+        }
+
+        public void AddFlag(string flag)
+        {
+            SetFlag("Globals", flag);
+        }
+
+        public bool HasFlag(string flag)
+        {
+            return HasFlag("Globals", flag);
+        } 
+
+        public void AddFlag<T>(T flag) where T : struct, Enum
+        {
+            var key = typeof(T).AssemblyQualifiedName;
+            if (Flags.ContainsKey(key))
+            {
+                dynamic value = Enum.Parse<T>(Flags[key].First());
+                var str = (value | flag).ToString(); 
+                SetFlag(key, str);
+            }
+            else
+            {
+                var str = flag.ToString();
+                SetFlag(key, str);
+            }
+        }
+
+        public bool HasFlag<T>(T flag) where T : struct, Enum
+        {
+            var key = typeof(T).AssemblyQualifiedName;
+            if (!Flags.ContainsKey(key))
+                return false;
+            dynamic value = Enum.Parse<T>(Flags[key].First());
+            return value.HasFlag(flag);
+        }
+
+
+
     }
 
+ 
     public class Device<T> : EntityEx<Device>
     {
         public T Data { get; set; }
-        public Device(Device device) : base(device)
+        public Device(Device device,World world) : base(device)
         {
-            Data = Entity.Protocol<T>();
+            Data = Entity.Protocol<T>(world);
         }
 
         public override string ToString()
         {
             return Entity.Code;
-        }
+        } 
     }
 
     public class Device<T, T2> : Device<T>
     {
         public T2 Data2 { get; set; }
-        public Device(Device device) : base(device)
+        public Device(Device device, World world) : base(device, world)
         {
-            Data2 = Entity.Protocol<T2>();
+            Data2 = Entity.Protocol<T2>(world);
         }
 
     }
@@ -88,36 +261,36 @@ namespace WCS.Core
     public class Device<T, T2, T3> : Device<T, T2>
     {
         public T3 Data3 { get; set; }
-        public Device(Device device) : base(device)
+        public Device(Device device, World world) : base(device, world)
         {
-            Data3 = Entity.Protocol<T3>();
+            Data3 = Entity.Protocol<T3>(world);
         }
     }
 
     public class Device<T, T2, T3, T4> : Device<T, T2, T3>
     {
         public T4 Data4 { get; set; }
-        public Device(Device device) : base(device)
+        public Device(Device device, World world) : base(device, world)
         {
-            Data4 = Entity.Protocol<T4>();
+            Data4 = Entity.Protocol<T4>(world);
         }
     }
 
     public class Device<T, T2, T3, T4, T5> : Device<T, T2, T3, T4>
     {
         public T5 Data5 { get; set; }
-        public Device(Device device) : base(device)
+        public Device(Device device, World world) : base(device, world)
         {
-            Data5 = Entity.Protocol<T5>();
+            Data5 = Entity.Protocol<T5>(world);
         }
     }
 
     public class Device<T, T2, T3, T4, T5, T6> : Device<T, T2, T3, T4, T5>
     {
         public T6 Data6 { get; set; }
-        public Device(Device device) : base(device)
+        public Device(Device device, World world) : base(device, world)
         {
-            Data6 = Entity.Protocol<T6>();
+            Data6 = Entity.Protocol<T6>(world);
         }
     }
 }

+ 2 - 0
WCS.Core/Extentions.cs

@@ -58,6 +58,8 @@ namespace WCS.Core
         public static DataBlock[] GetDataBlocks(this World source)
         {
             ExObjsOfWorld.TryGetValue(source, out var dic);
+            if (dic == null)
+                return new DataBlock[0];
             var res= dic.Values.OfType<DataBlock>().ToArray();
             return res;
         } 

+ 32 - 0
WCS.Core/Flags.cs

@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WCS.Core
+{
+    [Flags]
+    public enum DeviceFlags
+    {
+        扫码 = 1 << 0,
+        称重 = 1 << 1,
+        外检 = 1 << 2,
+
+        顶升 = 1 << 3,
+        移栽 = 1 << 4,
+        旋转 = 1 << 5,
+
+        入库 = 1 << 6,
+        出库 = 1 << 7,
+
+        巷道口 = 1 << 8,
+        RGV口 = 1 << 9,
+        AGV口 = 1 << 10,
+
+        直轨 = 1 << 11,
+        弯轨 = 1 << 12,
+        环轨 = 1 << 13,
+
+    }
+}

+ 67 - 0
WCS.Core/Path.cs

@@ -0,0 +1,67 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WCS.Core;
+
+namespace WCS.Core
+{ 
+    public class DevicePath
+    {
+        public string From { get; set; } = "";
+        public string To { get; set; } = "";
+
+        List<string> points = new List<string>();
+
+        public List<Device> Points
+        {
+            get 
+            {
+                var list = points.Select(v => Device.Find(v)).ToList();
+                return list;
+            }
+        }
+
+        public static DevicePath[] GetPaths(string from, string to)
+        {
+            var all = Device.All.ToDictionary(v => v.Code, v => v.Targets.Select(d => d.Code).ToList());
+
+            List<List<string>> pathList = new List<List<string>>();
+            recursion(from, to, all, pathList, new List<string>());
+            pathList.ForEach(path => path.Remove(from));
+
+            var arr = pathList.Select(v => new DevicePath { From = from, To = to, points = v }).ToArray();
+            return arr;
+        }
+
+        public static DevicePath? GetPath(string from, string to)
+        {
+            return GetPaths(from, to).OrderBy(v => v.Points.Count).FirstOrDefault();
+        }
+
+        static void recursion(string from, string to, Dictionary<string, List<string>> all,List<List<string>> pathList, List<string> points)
+        {
+            if (points.Count > 100)
+                return;
+            points.Add(from);
+            if (from == to)
+            {
+                pathList.Add(points);
+                return;
+            }
+            if (!all.ContainsKey(from))
+            {
+                return;
+            }
+            foreach (var code in all[from])
+            {
+                if (points.Contains(code))
+                    continue;
+                recursion(code, to, all, pathList, new List<string>(points));
+            }
+        }
+    }
+
+
+}

+ 23 - 18
WCS.Core/ProtocolProxyBase.cs

@@ -1,28 +1,37 @@
-using System.ComponentModel.DataAnnotations;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Net.Sockets;
 using System.Reflection;
 using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Channels;
+using System.Threading.Tasks;
 
 namespace WCS.Core
 {
     public abstract class ProtocolProxyBase : IProtocolProxy
     {
-        private string Id = Guid.NewGuid().ToString();
+        string Id = Guid.NewGuid().ToString();
         public ProtocolInfo Info { get; private set; }
         public ushort BytesCount { get; private set; }
-        private Dictionary<string, PlcItem> Items = new Dictionary<string, PlcItem>();
-        private Type ProtocolType, ProtocolDataType;
+        Dictionary<string, PlcItem> Items = new Dictionary<string, PlcItem>();
+        Type ProtocolType, ProtocolDataType;
         public Device Device { get; private set; }
 
-        private DataBlock Db;
+        DataBlock Db;
 
-        public ProtocolProxyBase(Device dev, ProtocolInfo info, Type protocolType)
+        public ProtocolProxyBase(Device dev, ProtocolInfo info,Type protocolType,World world)
         {
             this.Device = dev;
             this.Info = info;
-            Db = info.DBInfo.Ex(Device.World);
+            Db = info.DBInfo.Ex(world);
             Db.DbChanged += Db_DbChanged;
             ProtocolType = protocolType;
 
+
             var bitStart = info.Position * 8;//偏移量,按位算
 
             //this.Start = start;
@@ -62,7 +71,7 @@ namespace WCS.Core
                     bitStart += modeNum - mod;
                 }
 
-                #endregion 计算偏移量
+                #endregion
 
                 byte arrlen = 0;
                 byte strLen = 0;
@@ -83,13 +92,11 @@ namespace WCS.Core
                 Items.Add(p.Name, item);
                 bitStart += item.DataSizeOfBits;
                 BytesCount += item.DataSize;
-            }
-            //ProtocolType = this.PROTOCOL.DB.GetProtocolType();
-            ProtocolDataType = ProtocolType.Assembly.GetTypes().Where(v => v.IsClass).Where(v => v.GetInterface(ProtocolType.Name) != null && v != this.GetType()).First();
+            } 
+            //ProtocolDataType = ProtocolType.Assembly.GetTypes().Where(v => v.IsClass).Where(v => v.GetInterface(ProtocolType.Name) != null && v != this.GetType()).First();
         }
 
-        private byte[] Data = new byte[0];
-
+        byte[] Data = new byte[0];
         private void Db_DbChanged(byte[] data)
         {
             var pos = Info.Position - Db.Start;
@@ -104,12 +111,10 @@ namespace WCS.Core
         protected abstract void DataChanged();
 
         #region
-
         public void AddEvent(string eventName, Delegate delgate)
         {
             throw new NotImplementedException();
         }
-
         public void RemoveEvent(string eventName, Delegate delgate)
         {
             throw new NotImplementedException();
@@ -125,12 +130,13 @@ namespace WCS.Core
             throw new NotImplementedException();
         }
 
+
         public T Get<T>(string propertyName)
         {
             var item = Items[propertyName] as PlcItem<T>;
             var res = item.Value;
             var channel = Ltc.GetChannel();
-            Device.World.OnInternalLog(channel, $"{Device.Code}:{propertyName}:{res}");
+            //Device.World.OnInternalLog(channel, $"获取{Device.Code}.{propertyName} 值:{res}");
             return res;
         }
 
@@ -139,9 +145,8 @@ namespace WCS.Core
             var item = Items[propertyName] as PlcItem<T>;
             item.Value = value;
             var channel = Ltc.GetChannel();
-            Device.World.OnInternalLog(channel, $"{Device.Code}:{propertyName}={value}");
+            //Device.World.OnInternalLog(channel, $"设置{Device.Code}.{propertyName} 值:{value}");
         }
-
         #endregion
     }
 }

+ 81 - 4
WCS.Core/System.cs

@@ -116,10 +116,24 @@ namespace WCS.Core
     {
         public override List<T> Create()
         {
-            var types = typeof(T).GetGenericArguments();
-            var list= World.Devices.Where(v => types.All(d => v.HasProtocol(d)))
+            var t = typeof(T);
+            while (true)
+            {
+                if (t.IsGenericType)
+                {
+                    break;
+                }
+                t = t.BaseType;
+            }
+
+            var types = t.GetGenericArguments();
+            var list= Device.All.Where(v => types.All(d => v.HasProtocol(d)))
                 .Where(v => Select(v))
-                .Select(v => Activator.CreateInstance(typeof(T), v)).OfType<T>().ToList();//此时才实例化Protocol            
+                .Select(v => Activator.CreateInstance(typeof(T), v,this.World)).OfType<T>().ToList();//此时才实例化Protocol
+            if (list.Count == 0)
+            {
+                //throw new Exception($"{this.GetType().Name}未匹配到任何Device");
+            }
             return list;
         }
 
@@ -198,5 +212,68 @@ namespace WCS.Core
                 World.Publish();
             }
         }
-    } 
+    }
+
+    public abstract class ServiceSystem<T> :SystemBase
+    {
+        ConcurrentQueue<Action<List<WorkTimes>>> Actions = new ConcurrentQueue<Action<List<WorkTimes>>>();
+        public void Invoke(T obj)
+        {
+            Actions.Enqueue(list =>
+            {
+                var sw = new Stopwatch();
+                sw.Start();
+                try
+                {
+                    InvokeDo(obj);
+                }
+                finally
+                {
+                    sw.Stop();
+                    list.AddSafe(new WorkTimes { Key = $"{obj?.ToString()}", Total = sw.ElapsedMilliseconds }); 
+                }
+            });
+        }
+
+        protected abstract void Do(T obj);
+
+        void InvokeDo(T obj)
+        {
+            var channel = new Channel
+            {
+                World = World.Description,
+                Stage = "DoLogics",
+                System = Description,
+                Item = obj.ToString()
+            };
+            try
+            {
+                Ltc.SetChannel(channel);
+                World.OnInternalLog(channel, "开始");
+                Do(obj);
+            }
+            catch (Exception ex)
+            {
+                throw;
+            }
+            finally
+            {
+                World.OnInternalLog(channel, "结束");
+                World.Publish();
+            }
+        }
+
+        public override List<object> GetObjects()
+        {
+            return new List<object>();
+        }
+
+        public override void Update(List<WorkTimes> list)
+        {
+            while (Actions.TryDequeue(out var act))
+            {
+                act(list);
+            }
+        }
+    }
 }

+ 42 - 0
WCS.Core/VitrualRedisPLC.cs

@@ -0,0 +1,42 @@
+using FreeRedis;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WCS.Core
+{
+    public class VitrualRedisPLC : IPLCAccessor
+    {
+        RedisClient redis;
+        PLCInfo plcInfo;
+        int dbLen = 50000;
+        public VitrualRedisPLC(PLCInfo plcInfo, string redisConnStr)
+        {
+            this.plcInfo = plcInfo;
+            redis = new RedisClient(redisConnStr);
+        }
+
+        public byte[] ReadBytes(ushort db, ushort address, ushort length)
+        {
+            var key = $"{plcInfo.IP}-{db}";
+            if (!redis.Exists(key))
+            {
+                redis.SetRange(key, 0, new byte[dbLen]);
+            }
+            var res = redis.GetRange<byte[]>(key, address, address + length - 1);
+            return res;
+        }
+
+        public void WriteBytes(ushort db, ushort address, byte[] data)
+        {
+            var key = $"{plcInfo.IP}-{db}";
+            if (!redis.Exists(key))
+            {
+                redis.SetRange(key, 0, new byte[dbLen]);
+            }
+            redis.SetRange(key, address, data);
+        }
+    }
+}

+ 1 - 2
WCS.Core/WCS.Core.csproj

@@ -3,12 +3,11 @@
   <PropertyGroup>
     <TargetFramework>net7.0</TargetFramework>
     <ImplicitUsings>enable</ImplicitUsings>
-    <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <Nullable>enable</Nullable>
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="FreeRedis" Version="1.0.10" />
+    <PackageReference Include="FreeRedis" Version="1.0.8" />
   </ItemGroup>
 
 </Project>

+ 6 - 6
WCS.Core/World.cs

@@ -62,7 +62,7 @@ namespace WCS.Core
 
         public static void StartAll()
         { 
-            //MM_BeginPeriod(1);
+            MM_BeginPeriod(1);
             Worlds.ForEach(w => w.Init());
             foreach (World w in Worlds)
             {
@@ -89,7 +89,7 @@ namespace WCS.Core
 
         public static void StopAll()
         {
-            //MM_EndPeriod(1);
+            MM_EndPeriod(1);
             foreach (World w in Worlds)
                 w.Stop();
         }
@@ -132,7 +132,7 @@ namespace WCS.Core
         }
 
 
-        public List<Device> Devices;
+        //public List<Device> Devices;
         
 
         /// <summary>
@@ -143,7 +143,7 @@ namespace WCS.Core
          
             try
             {
-                Devices = Protocols.Generate(this);
+                //Devices = Protocols.Generate(this);
                 foreach (var type in SystemTypes)
                 {
                     var sysDesc = type.GetCustomAttribute<DescriptionAttribute>()?.Description;
@@ -212,7 +212,7 @@ namespace WCS.Core
             while (!Stoped)
             {
                 WorkTimes wt = new WorkTimes();
-                wt.Key = $"{this.GetType().Name} 周期:{Interval}";
+                wt.Key = $"{this.Description} 周期:{Interval}";
                 sw.Restart();
                 BeforeUpdate();
                 Update(wt.Items);
@@ -294,7 +294,7 @@ namespace WCS.Core
                 Parallel.ForEach(group.Value, sys =>
                 {
                     var wt2=new WorkTimes();
-                    wt2.Key = sys.GetType().Name;
+                    wt2.Key = sys.Description;
                     var sw2 = new Stopwatch();
                     sw2.Start();
                     try