|
|
@@ -1,17 +1,9 @@
|
|
|
using FreeRedis;
|
|
|
-using System;
|
|
|
-using System.Collections.Concurrent;
|
|
|
-using System.Collections.Generic;
|
|
|
using System.ComponentModel;
|
|
|
using System.Diagnostics;
|
|
|
-using System.Drawing;
|
|
|
-using System.Linq;
|
|
|
using System.Reflection;
|
|
|
using System.Runtime.InteropServices;
|
|
|
-using System.Text;
|
|
|
using System.Text.RegularExpressions;
|
|
|
-using System.Threading.Tasks;
|
|
|
-using System.Xml.Schema;
|
|
|
|
|
|
namespace WCS.Core
|
|
|
{
|
|
|
@@ -19,15 +11,18 @@ namespace WCS.Core
|
|
|
/// 世界用来管理下属System的执行周期,此为默认世界。也可以通过继承此类创建多个不同世界,不同世界的执行周期相互独立,不受其它世界延迟干扰。
|
|
|
/// </summary>
|
|
|
[Description("默认世界")]
|
|
|
- public abstract class World: DescriptionClass
|
|
|
+ public abstract class World : DescriptionClass
|
|
|
{
|
|
|
[DllImport("winmm.dll", EntryPoint = "timeBeginPeriod")]
|
|
|
public static extern uint MM_BeginPeriod(uint uMilliseconds);
|
|
|
+
|
|
|
[DllImport("winmm.dll", EntryPoint = "timeEndPeriod")]
|
|
|
public static extern uint MM_EndPeriod(uint uMilliseconds);
|
|
|
|
|
|
#region Static
|
|
|
- static List<World> _Worlds;
|
|
|
+
|
|
|
+ private static List<World> _Worlds;
|
|
|
+
|
|
|
internal static List<World> Worlds
|
|
|
{
|
|
|
get
|
|
|
@@ -36,7 +31,7 @@ namespace WCS.Core
|
|
|
{
|
|
|
_Worlds = new List<World>();
|
|
|
//_Worlds.Add(new World());//默认世界
|
|
|
- var arr = Assembly.GetEntryAssembly().GetTypes().Where(v => typeof(World).IsAssignableFrom(v)).Select(v => Activator.CreateInstance(v)).OfType<World>().ToArray();//自定义世界
|
|
|
+ var arr = AppDomain.CurrentDomain.GetAssemblies().Select(v => v.GetTypes()).SelectMany(v => v).Where(v => typeof(World).IsAssignableFrom(v) && v != typeof(World)).Select(v => Activator.CreateInstance(v)).OfType<World>().ToArray();//自定义世界
|
|
|
_Worlds.AddRange(arr);
|
|
|
}
|
|
|
return _Worlds;
|
|
|
@@ -61,13 +56,13 @@ namespace WCS.Core
|
|
|
}
|
|
|
|
|
|
public static void StartAll()
|
|
|
- {
|
|
|
+ {
|
|
|
MM_BeginPeriod(1);
|
|
|
Worlds.ForEach(w => w.Init());
|
|
|
foreach (World w in Worlds)
|
|
|
{
|
|
|
if (w.SystemTypes.Length == 0)
|
|
|
- continue;
|
|
|
+ continue;
|
|
|
w.Start();
|
|
|
}
|
|
|
var arr = Worlds.SelectMany(v => v.SystemGroups).SelectMany(v => v.Value)
|
|
|
@@ -85,38 +80,38 @@ namespace WCS.Core
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
public static void StopAll()
|
|
|
{
|
|
|
MM_EndPeriod(1);
|
|
|
foreach (World w in Worlds)
|
|
|
w.Stop();
|
|
|
}
|
|
|
- #endregion
|
|
|
+
|
|
|
+ #endregion Static
|
|
|
|
|
|
#region Dynamic
|
|
|
+
|
|
|
public bool Stoped;
|
|
|
- Dictionary<Type, int> TypeOrder = new Dictionary<Type, int>();
|
|
|
- Dictionary<int, List<SystemBase>> SystemGroups = new Dictionary<int, List<SystemBase>>();
|
|
|
+ private Dictionary<Type, int> TypeOrder = new Dictionary<Type, int>();
|
|
|
+ private Dictionary<int, List<SystemBase>> SystemGroups = new Dictionary<int, List<SystemBase>>();
|
|
|
protected Type[] SystemTypes;
|
|
|
-
|
|
|
|
|
|
/// <summary>
|
|
|
/// 周期最小间隔时间(毫秒)
|
|
|
/// </summary>
|
|
|
- protected abstract int Interval {
|
|
|
+ protected abstract int Interval
|
|
|
+ {
|
|
|
get;
|
|
|
}
|
|
|
|
|
|
public World()
|
|
|
{
|
|
|
- SystemTypes = GetSystemTypes();
|
|
|
+ SystemTypes = GetSystemTypes();
|
|
|
}
|
|
|
|
|
|
protected virtual Type[] GetSystemTypes()
|
|
|
- {
|
|
|
- var sysTypes = Assembly.GetEntryAssembly().GetTypes()
|
|
|
+ {
|
|
|
+ var sysTypes = AppDomain.CurrentDomain.GetAssemblies().Select(v => v.GetTypes()).SelectMany(v => v)
|
|
|
.Where(v => !v.IsAbstract)
|
|
|
.Where(v => typeof(SystemBase).IsAssignableFrom(v))
|
|
|
.Where(v =>
|
|
|
@@ -128,19 +123,16 @@ namespace WCS.Core
|
|
|
return true;
|
|
|
return false;
|
|
|
}).ToArray();
|
|
|
- return sysTypes;
|
|
|
+ return sysTypes;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
//public List<Device> Devices;
|
|
|
-
|
|
|
|
|
|
/// <summary>
|
|
|
/// 初始化,实例化世界下的所有系统
|
|
|
/// </summary>
|
|
|
public virtual void Init()
|
|
|
{
|
|
|
-
|
|
|
try
|
|
|
{
|
|
|
//Devices = Protocols.Generate(this);
|
|
|
@@ -159,7 +151,7 @@ namespace WCS.Core
|
|
|
var sysArr = g.Select(v =>
|
|
|
{
|
|
|
var sysDesc = v.Key.GetCustomAttribute<DescriptionAttribute>()?.Description;
|
|
|
- Ltc.SetChannel(new Channel { World = Description, Stage="Init", System = sysDesc ?? v.Key.Name, Item = "构造" });
|
|
|
+ Ltc.SetChannel(new Channel { World = Description, Stage = "Init", System = sysDesc ?? v.Key.Name, Item = "构造" });
|
|
|
return Activator.CreateInstance(v.Key);
|
|
|
}).OfType<SystemBase>().ToArray();
|
|
|
list.AddRange(sysArr);
|
|
|
@@ -167,20 +159,20 @@ namespace WCS.Core
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
- {
|
|
|
+ {
|
|
|
throw;
|
|
|
}
|
|
|
- finally
|
|
|
- {
|
|
|
+ finally
|
|
|
+ {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- int Set(Type type,int level)
|
|
|
+ private int Set(Type type, int level)
|
|
|
{
|
|
|
if (!SystemTypes.Contains(type))
|
|
|
throw new Exception($"OrderAttribute设置错误,与目标不属于同一世界。类型:{type}。");
|
|
|
if (level > 10)
|
|
|
- {
|
|
|
+ {
|
|
|
throw new Exception($"OrderAttribute设置错误,导致死循环。类型:{type}。");
|
|
|
}
|
|
|
var attr = type.GetCustomAttribute<OrderAttribute>();
|
|
|
@@ -197,17 +189,17 @@ namespace WCS.Core
|
|
|
return TypeOrder[type];
|
|
|
}
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// 开启世界主循环
|
|
|
- /// </summary>
|
|
|
+ /// <summary>
|
|
|
+ /// 开启世界主循环
|
|
|
+ /// </summary>
|
|
|
public void Start()
|
|
|
- {
|
|
|
- Stoped = false;
|
|
|
+ {
|
|
|
+ Stoped = false;
|
|
|
Task.Run(Loop);//不要使用Thread,可以使用ThreadPool
|
|
|
}
|
|
|
|
|
|
- void Loop()
|
|
|
- {
|
|
|
+ private void Loop()
|
|
|
+ {
|
|
|
var sw = new Stopwatch();
|
|
|
while (!Stoped)
|
|
|
{
|
|
|
@@ -223,13 +215,13 @@ namespace WCS.Core
|
|
|
//sw.Start();
|
|
|
if (ms > 0)
|
|
|
{
|
|
|
- Thread.Sleep(ms);//不要使用Task.Delay().Wait()
|
|
|
+ Thread.Sleep(ms);//不要使用Task.Delay().Wait()
|
|
|
}
|
|
|
//sw.Stop();
|
|
|
//var total = sw.ElapsedMilliseconds;
|
|
|
wt.Total = workTimes;
|
|
|
FrameInfo(wt);
|
|
|
- }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public void Stop()
|
|
|
@@ -237,11 +229,11 @@ namespace WCS.Core
|
|
|
Stoped = true;
|
|
|
}
|
|
|
|
|
|
- void Update(List<WorkTimes> list)
|
|
|
+ private void Update(List<WorkTimes> list)
|
|
|
{
|
|
|
var wt = new WorkTimes();
|
|
|
wt.Key = "读取PLC数据";
|
|
|
- var sw=new Stopwatch();
|
|
|
+ var sw = new Stopwatch();
|
|
|
sw.Start();
|
|
|
LoadPlcData(wt.Items);
|
|
|
sw.Stop();
|
|
|
@@ -254,11 +246,11 @@ namespace WCS.Core
|
|
|
DoLogics(wt.Items);
|
|
|
sw.Stop();
|
|
|
wt.Total = sw.ElapsedMilliseconds;
|
|
|
- list.AddSafe(wt);
|
|
|
+ list.AddSafe(wt);
|
|
|
}
|
|
|
-
|
|
|
- void LoadPlcData(List<WorkTimes> list)
|
|
|
- {
|
|
|
+
|
|
|
+ private void LoadPlcData(List<WorkTimes> list)
|
|
|
+ {
|
|
|
Parallel.ForEach(this.GetDataBlocks(), db =>
|
|
|
{
|
|
|
var channel = new Channel
|
|
|
@@ -273,34 +265,35 @@ namespace WCS.Core
|
|
|
try
|
|
|
{
|
|
|
db.RefreshData();
|
|
|
- }
|
|
|
+ }
|
|
|
catch (Exception ex)
|
|
|
- {
|
|
|
- this.Ex().Publish(channel, ex.GetBaseException().Message);
|
|
|
+ {
|
|
|
+ this.Ex().Publish(channel, ex.GetBaseException().Message);
|
|
|
}
|
|
|
sw.Stop();
|
|
|
- list.AddSafe(new WorkTimes { Key = $"{db.Entity.PLCInfo.IP}/{db.Entity.No}", Total = sw.ElapsedMilliseconds });
|
|
|
- });
|
|
|
+ list.AddSafe(new WorkTimes { Key = $"{db.Entity.PLCInfo.IP}/{db.Entity.No}", Total = sw.ElapsedMilliseconds });
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
- void DoLogics(List<WorkTimes> list)
|
|
|
- {
|
|
|
- foreach(var group in SystemGroups)
|
|
|
+ private void DoLogics(List<WorkTimes> list)
|
|
|
+ {
|
|
|
+ foreach (var group in SystemGroups)
|
|
|
{
|
|
|
- var wt=new WorkTimes();
|
|
|
+ var wt = new WorkTimes();
|
|
|
wt.Key = $"组{group.Key}";
|
|
|
var sw = new Stopwatch();
|
|
|
- sw.Restart();
|
|
|
+ sw.Restart();
|
|
|
Parallel.ForEach(group.Value, sys =>
|
|
|
{
|
|
|
- var wt2=new WorkTimes();
|
|
|
+ var wt2 = new WorkTimes();
|
|
|
wt2.Key = sys.Description;
|
|
|
var sw2 = new Stopwatch();
|
|
|
sw2.Start();
|
|
|
try
|
|
|
{
|
|
|
sys.Update(wt2.Items);
|
|
|
- }catch (Exception ex)
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
{
|
|
|
Console.ForegroundColor = ConsoleColor.Red;
|
|
|
Console.WriteLine(ex.GetBaseException().Message);
|
|
|
@@ -309,25 +302,23 @@ namespace WCS.Core
|
|
|
sw2.Stop();
|
|
|
wt2.Total = sw2.ElapsedMilliseconds;
|
|
|
list.AddSafe(wt2);
|
|
|
- });
|
|
|
- sw.Stop();
|
|
|
- wt.Total= sw.ElapsedMilliseconds;
|
|
|
+ });
|
|
|
+ sw.Stop();
|
|
|
+ wt.Total = sw.ElapsedMilliseconds;
|
|
|
//list.AddSafe(wt);
|
|
|
- }
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
protected virtual void BeforeUpdate()
|
|
|
- {
|
|
|
-
|
|
|
+ {
|
|
|
}
|
|
|
|
|
|
protected virtual void AfterUpdate()
|
|
|
{
|
|
|
-
|
|
|
}
|
|
|
|
|
|
- #endregion
|
|
|
-
|
|
|
+ #endregion Dynamic
|
|
|
+
|
|
|
public T GetSystem<T>() where T : SystemBase
|
|
|
{
|
|
|
var sys = Systems.Where(v => v.GetType() == typeof(T)).FirstOrDefault() as T;
|
|
|
@@ -338,16 +329,17 @@ namespace WCS.Core
|
|
|
|
|
|
public SystemBase[] Systems
|
|
|
{
|
|
|
- get {
|
|
|
+ get
|
|
|
+ {
|
|
|
return SystemGroups.SelectMany(v => v.Value).ToArray();
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
protected virtual void FrameInfo(WorkTimes wt)
|
|
|
{
|
|
|
if (wt.Total > this.Interval)
|
|
|
{
|
|
|
- Console.ForegroundColor = ConsoleColor.Red;
|
|
|
+ Console.ForegroundColor = ConsoleColor.Red;
|
|
|
}
|
|
|
Console.WriteLine(wt.GetInfo());
|
|
|
Console.ResetColor();
|
|
|
@@ -358,12 +350,11 @@ namespace WCS.Core
|
|
|
OnLog(Ltc.GetChannel(), log);
|
|
|
}
|
|
|
|
|
|
- internal protected abstract void OnError(Channel channel, Exception exception);
|
|
|
- internal protected abstract void OnInternalLog(Channel channel, string msg);
|
|
|
+ protected internal abstract void OnError(Channel channel, Exception exception);
|
|
|
|
|
|
- protected abstract void OnLog(Channel channel, object logObj);
|
|
|
+ protected internal abstract void OnInternalLog(Channel channel, string msg);
|
|
|
|
|
|
-
|
|
|
+ protected abstract void OnLog(Channel channel, object logObj);
|
|
|
|
|
|
protected abstract IEnumerable<string> GetChannelMsg(Channel channel);
|
|
|
|
|
|
@@ -372,21 +363,19 @@ namespace WCS.Core
|
|
|
var channel = Ltc.GetChannel();
|
|
|
var msgs = GetChannelMsg(channel);
|
|
|
var msg = string.Join("\n", msgs);
|
|
|
- this.Ex().Publish(channel,msg);
|
|
|
+ this.Ex().Publish(channel, msg);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public interface ILog
|
|
|
- {
|
|
|
-
|
|
|
+ {
|
|
|
}
|
|
|
|
|
|
-
|
|
|
public class WorldEx : EntityEx<World>
|
|
|
- {
|
|
|
- RedisClient Redis = new RedisClient(Configs.DebugRedisUrl);
|
|
|
- List<string> ChannelList = new List<string>();
|
|
|
- DateTime SubTime = DateTime.Now;
|
|
|
+ {
|
|
|
+ private RedisClient Redis = new RedisClient(Configs.DebugRedisUrl);
|
|
|
+ private List<string> ChannelList = new List<string>();
|
|
|
+ private DateTime SubTime = DateTime.Now;
|
|
|
|
|
|
public WorldEx(World ent) : base(ent)
|
|
|
{
|
|
|
@@ -410,7 +399,7 @@ namespace WCS.Core
|
|
|
var flag = false;
|
|
|
lock (ChannelList)
|
|
|
{
|
|
|
- flag=ChannelList.Any(v =>
|
|
|
+ flag = ChannelList.Any(v =>
|
|
|
{
|
|
|
var b = Regex.Match(channel.ToString(), $"^{v.Replace("*", ".*")}$");
|
|
|
return b.Success;
|
|
|
@@ -424,7 +413,7 @@ namespace WCS.Core
|
|
|
public class WorkTimes
|
|
|
{
|
|
|
public string Key { get; set; } = "";
|
|
|
- public long Total { get; set; }
|
|
|
+ public long Total { get; set; }
|
|
|
public List<WorkTimes> Items { get; set; } = new List<WorkTimes>();
|
|
|
|
|
|
public override string ToString()
|
|
|
@@ -444,17 +433,18 @@ namespace WCS.Core
|
|
|
public abstract class AttrClass<T> where T : Attribute
|
|
|
{
|
|
|
public T? Attr { get; private set; }
|
|
|
+
|
|
|
public AttrClass()
|
|
|
{
|
|
|
Attr = GetType().GetCustomAttribute<T>();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public abstract class DescriptionClass:AttrClass<DescriptionAttribute>
|
|
|
+ public abstract class DescriptionClass : AttrClass<DescriptionAttribute>
|
|
|
{
|
|
|
public string Description
|
|
|
{
|
|
|
- get
|
|
|
+ get
|
|
|
{
|
|
|
if (Attr != null)
|
|
|
return Attr.Description;
|