Sic.Framework-Nanjing-Baishi/MECF.Framework.Common/Aitex/Core/RT/Device/DeviceManagerBase.cs

498 lines
13 KiB
C#
Raw Normal View History

#define DEBUG
2023-04-13 11:51:03 +08:00
using System;
using System.Collections.Concurrent;
2023-04-13 11:51:03 +08:00
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
2023-04-13 11:51:03 +08:00
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
2023-04-13 11:51:03 +08:00
using System.Threading.Tasks;
using System.Xml;
using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Log;
using Aitex.Core.Util;
using MECF.Framework.Common.Equipment;
namespace Aitex.Core.RT.Device
{
public class DeviceManagerBase : IDeviceManager
{
#region Variables
2023-04-13 11:51:03 +08:00
private readonly Dictionary<string, IDevice> _nameDevice = new();
private readonly Dictionary<Type, List<IDevice>> _typeDevice = new();
private readonly DeviceTimer _timer = new();
private readonly R_TRIG _trigExceed500 = new();
private readonly ConcurrentBag<IDevice> _optionDevice = new();
private readonly object _lockerDevice = new();
2023-04-13 11:51:03 +08:00
#endregion
2023-04-13 11:51:03 +08:00
#region MyRegion
2023-04-13 11:51:03 +08:00
public DeviceManagerBase()
{
DEVICE.Manager = this;
}
2023-04-13 11:51:03 +08:00
#endregion
#region Properties
/// <summary>
/// 返回当前设备管理器映射的XML配置文件节点。
/// </summary>
protected XmlElement DeviceModelNodes { get; private set; }
/// <summary>
/// 设置或返回是否以异步方式初始化当前管理器中的设备。
/// </summary>
2023-04-13 11:51:03 +08:00
public bool DisableAsyncInitialize { get; set; }
#endregion
#region Methods
private void InitDevice(IDevice device)
{
try
{
if (!device.Initialize())
{
LOG.Write(device.Name + " initialize failed.");
}
}
catch (Exception ex)
{
LOG.Write(ex);
}
}
/// <summary>
/// 向设备管理器的设备字典中添加一个设备实例。
/// </summary>
/// <param name="device"></param>
protected virtual void QueueDevice(IDevice device)
{
QueueDevice(device.Name, device);
}
2023-04-13 11:51:03 +08:00
/// <summary>
/// 向设备管理器的设备字典中添加一个设备实例并自定义该设备在字典中的Key。
/// </summary>
/// <param name="key"></param>
/// <param name="device"></param>
protected void QueueDevice(string key, IDevice device)
{
lock (_lockerDevice)
{
Debug.Assert(!_nameDevice.ContainsKey(key), "DeviceModel config file contains duplicated name " + key);
_nameDevice.Add(key, device);
}
}
/// <summary>
/// 终止当前对象。
/// </summary>
2023-04-13 11:51:03 +08:00
public virtual void Terminate()
{
lock (_lockerDevice)
{
foreach (var value in _nameDevice.Values)
2023-04-13 11:51:03 +08:00
{
value.Terminate();
}
}
}
/// <summary>
/// 后台扫面线程调用的方法。
/// </summary>
2023-04-13 11:51:03 +08:00
public void Monitor()
{
lock (_lockerDevice)
{
foreach (var value in _nameDevice.Values)
2023-04-13 11:51:03 +08:00
{
try
{
_timer.Start(0.0);
2023-04-13 11:51:03 +08:00
value.Monitor();
_trigExceed500.CLK = _timer.GetElapseTime() > 500.0;
2023-04-13 11:51:03 +08:00
if (_trigExceed500.Q)
{
LOG.Warning($"{value.Module}.{value.Name} monitor time {_timer.GetElapseTime()} ms");
2023-04-13 11:51:03 +08:00
}
}
catch (Exception ex)
{
LOG.Write(ex, $"Monitor {value.Name} Exception");
}
}
}
}
public void Reset()
{
lock (_lockerDevice)
{
foreach (var value in _nameDevice.Values)
2023-04-13 11:51:03 +08:00
{
value.Reset();
}
_trigExceed500.RST = true;
}
}
public void Initialize(string modelFile, string type, ModuleName mod = ModuleName.System, string ioModule = "", bool endCallInit = true)
{
if (!File.Exists(modelFile))
{
throw new ApplicationException($"did not find the device model file {modelFile} ");
}
var xmlDocument = new XmlDocument();
2023-04-13 11:51:03 +08:00
try
{
xmlDocument.Load(modelFile);
if (!(xmlDocument.SelectSingleNode("DeviceModelDefine") is XmlElement xmlElement))
{
throw new ApplicationException($"device mode file {modelFile} is not valid");
}
var attribute = xmlElement.GetAttribute("type");
2023-04-13 11:51:03 +08:00
if (attribute != type)
{
throw new ApplicationException($"the type {attribute} in device mode file {modelFile} is inaccordance with the system type {type}");
}
DeviceModelNodes = xmlElement;
foreach (XmlNode childNode in xmlElement.ChildNodes)
{
if (childNode.NodeType == XmlNodeType.Comment || !(childNode is XmlElement xmlElement2))
{
continue;
}
var text = xmlElement2.GetAttribute("assembly");
2023-04-13 11:51:03 +08:00
if (string.IsNullOrEmpty(text))
{
text = "MECF.Framework.RT.EquipmentLibrary";
}
var text2 = xmlElement2.Name.Substring(0, xmlElement2.Name.Length - 1);
var text3 = xmlElement2.GetAttribute("classType");
2023-04-13 11:51:03 +08:00
if (string.IsNullOrEmpty(text3))
{
text3 = "Aitex.Core.RT.Device.Unit." + text2;
}
var assembly = Assembly.Load(text);
var type2 = assembly.GetType(text3);
2023-04-13 11:51:03 +08:00
if (type2 == null)
{
continue;
}
foreach (var childNode2 in xmlElement2.ChildNodes)
2023-04-13 11:51:03 +08:00
{
if (!(childNode2 is XmlElement xmlElement3))
{
LOG.Write("Device Model File contains non element node, " + (childNode2 as XmlNode).Value);
continue;
}
var device = Activator.CreateInstance(type2, mod.ToString(), xmlElement3, ioModule) as IDevice;
2023-04-13 11:51:03 +08:00
if (xmlElement3.HasAttribute("option") && Convert.ToBoolean(xmlElement3.Attributes["option"].Value))
{
_optionDevice.Add(device);
continue;
}
QueueDevice(device);
DATA.Subscribe(device, $"{device.Module}.{text2}.{device.Name}");
if (!_typeDevice.ContainsKey(type2))
{
_typeDevice[type2] = new List<IDevice>();
}
_typeDevice[type2].Add(device);
if (DisableAsyncInitialize)
{
InitDevice(device);
continue;
}
var task = Task.Run(delegate
2023-04-13 11:51:03 +08:00
{
InitDevice(device);
});
}
}
if (endCallInit)
{
Initialize();
}
}
catch (Exception ex)
{
LOG.Write(ex);
}
}
public void Initialize(string modelFile, string modelType, string moduleName, string ioPath, string scPath)
{
if (!File.Exists(modelFile))
{
throw new ApplicationException($"did not find the device model file {modelFile} ");
}
var xmlDocument = new XmlDocument();
2023-04-13 11:51:03 +08:00
try
{
xmlDocument.Load(modelFile);
if (!(xmlDocument.SelectSingleNode("DeviceModelDefine") is XmlElement xmlElement))
{
throw new ApplicationException($"device mode file {modelFile} is not valid");
}
var attribute = xmlElement.GetAttribute("type");
2023-04-13 11:51:03 +08:00
if (attribute != modelType)
{
throw new ApplicationException($"the type {attribute} in device mode file {modelFile} is different with the system type {modelType}");
}
DeviceModelNodes = xmlElement;
foreach (XmlNode childNode in xmlElement.ChildNodes)
{
if (childNode.NodeType == XmlNodeType.Comment || !(childNode is XmlElement xmlElement2))
{
continue;
}
var text = xmlElement2.GetAttribute("assembly");
2023-04-13 11:51:03 +08:00
if (string.IsNullOrEmpty(text))
{
text = "MECF.Framework.RT.EquipmentLibrary";
}
var text2 = xmlElement2.Name.Substring(0, xmlElement2.Name.Length - 1);
var text3 = xmlElement2.GetAttribute("classType");
2023-04-13 11:51:03 +08:00
if (string.IsNullOrEmpty(text3))
{
text3 = "Aitex.Core.RT.Device.Unit." + text2;
}
var assembly = Assembly.Load(text);
var type = assembly.GetType(text3);
2023-04-13 11:51:03 +08:00
if (type == null)
{
continue;
}
foreach (var childNode2 in xmlElement2.ChildNodes)
2023-04-13 11:51:03 +08:00
{
if (!(childNode2 is XmlElement xmlElement3))
{
LOG.Write("Device Model File contains non element node, " + (childNode2 as XmlNode).Value);
continue;
}
xmlElement3.SetAttribute("ioPath", ioPath);
xmlElement3.SetAttribute("scPath", scPath);
var device = Activator.CreateInstance(type, moduleName, xmlElement3, ioPath) as IDevice;
2023-04-13 11:51:03 +08:00
if (xmlElement3.HasAttribute("option") && Convert.ToBoolean(xmlElement3.Attributes["option"]))
{
_optionDevice.Add(device);
continue;
}
DATA.Subscribe(device, $"{device.Module}.{text2}.{device.Name}");
QueueDevice(device);
if (!_typeDevice.ContainsKey(type))
{
_typeDevice[type] = new List<IDevice>();
}
_typeDevice[type].Add(device);
if (DisableAsyncInitialize)
{
InitDevice(device);
continue;
}
var task = Task.Run(delegate
2023-04-13 11:51:03 +08:00
{
InitDevice(device);
});
}
}
Initialize();
}
catch (Exception ex)
{
LOG.Write(ex);
}
}
/// <summary>
/// 向当前设备管理器中添加一个自定义设备。
/// </summary>
/// <param name="device">设备对象的实例。</param>
/// <param name="groupType"></param>
/// <param name="deviceType">设备对象实例的类型。</param>
/// <returns></returns>
2023-04-13 11:51:03 +08:00
public IDevice AddCustomDevice(IDevice device, string groupType, Type deviceType)
{
lock (_lockerDevice)
{
DATA.Subscribe(device, $"{device.Module}.{groupType}.{device.Name}");
if (!string.IsNullOrEmpty(device.Module) && device.Module != ModuleName.System.ToString())
2023-04-13 11:51:03 +08:00
{
_nameDevice.Add(device.Module + "." + device.Name, device);
}
else
{
_nameDevice.Add(device.Name, device);
}
if (!_typeDevice.ContainsKey(deviceType))
{
_typeDevice[deviceType] = new List<IDevice>();
}
_typeDevice[deviceType].Add(device);
device.Initialize();
}
return device;
}
public IDevice AddCustomDevice(IDevice device, Type deviceType)
{
lock (_lockerDevice)
{
try
{
DATA.Subscribe(device, $"{device.Module}.{device.Name}");
_nameDevice.Add(device.Name, device);
if (!_typeDevice.ContainsKey(deviceType))
{
_typeDevice[deviceType] = new List<IDevice>();
}
_typeDevice[deviceType].Add(device);
device.Initialize();
}
catch (Exception ex)
{
LOG.Write(ex);
}
}
return device;
}
public IDevice AddCustomDevice(IDevice device)
{
lock (_lockerDevice)
{
try
{
DATA.Subscribe(device, $"{device.Module}.{device.Name}");
_nameDevice.Add(device.Name, device);
if (!_typeDevice.ContainsKey(device.GetType()))
{
_typeDevice[device.GetType()] = new List<IDevice>();
}
_typeDevice[device.GetType()].Add(device);
device.Initialize();
}
catch (Exception ex)
{
LOG.Write(ex);
}
}
return device;
}
public IDevice AddCustomModuleDevice(IDevice device)
{
lock (_lockerDevice)
{
try
{
DATA.Subscribe(device, $"{device.Module}.{device.Name}");
_nameDevice.Add(device.Module + "." + device.Name, device);
if (!_typeDevice.ContainsKey(device.GetType()))
{
_typeDevice[device.GetType()] = new List<IDevice>();
}
_typeDevice[device.GetType()].Add(device);
device.Initialize();
}
catch (Exception ex)
{
LOG.Write(ex);
}
}
return device;
}
public virtual bool Initialize()
{
return true;
}
/// <summary>
/// 获取指定名称和类型的设备的实例。
/// </summary>
/// <param name="name">设备名称。</param>
/// <typeparam name="T">设备类型。</typeparam>
/// <returns></returns>
2023-04-13 11:51:03 +08:00
public T GetDevice<T>(string name) where T : class, IDevice
{
if (!_nameDevice.ContainsKey(name))
{
return null;
}
return _nameDevice[name] as T;
}
/// <summary>
/// 获取指定名称的设备的实例。
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public object GetDevice(string name)
2023-04-13 11:51:03 +08:00
{
if (!_nameDevice.ContainsKey(name))
{
return null;
}
return _nameDevice[name];
}
/// <summary>
/// 获取包含所有指定类型的设备实例的列表。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public List<T> GetDevice<T>() where T : class, IDevice
2023-04-13 11:51:03 +08:00
{
if (!_typeDevice.ContainsKey(typeof(T)))
{
return null;
}
var list = new List<T>();
foreach (var item in _typeDevice[typeof(T)])
2023-04-13 11:51:03 +08:00
{
list.Add(item as T);
}
return list;
}
/// <summary>
/// 获取当前设备管理器中的所有设备的列表。
/// </summary>
/// <returns></returns>
2023-04-13 11:51:03 +08:00
public List<IDevice> GetAllDevice()
{
return _nameDevice.Values.ToList();
}
public object GetOptionDevice(string name, Type type)
{
foreach (var item in _optionDevice)
2023-04-13 11:51:03 +08:00
{
if (item.Module + "." + item.Name == name && (type == null || item.GetType() == type))
{
return item;
}
}
return null;
}
#endregion
}
2023-04-13 11:51:03 +08:00
}