临时保存
添加仿真内容 修改旧的仿真调用
This commit is contained in:
parent
d930588fc2
commit
9ccbb49746
@ -1,13 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Eventing.Reader;
|
||||
using Aitex.Common.Util;
|
||||
using Aitex.Core.RT.DataCenter;
|
||||
using Aitex.Core.RT.IOCore;
|
||||
using Aitex.Core.RT.Log;
|
||||
using Aitex.Core.Util;
|
||||
using Aitex.Core.WCF;
|
||||
using MECF.Framework.Common.Equipment;
|
||||
using MECF.Framework.Common.PLC;
|
||||
using MECF.Framework.Simulator.Core;
|
||||
using SicSimulator.Views;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Eventing.Reader;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SicSimulator.Instances
|
||||
{
|
||||
@ -32,6 +36,10 @@ namespace SicSimulator.Instances
|
||||
|
||||
WcfServiceManager.Instance.Initialize(new Type[] { typeof(SimulatorAdsPlcService) });
|
||||
|
||||
//Singleton<SimulatorDeviceManager>.Instance.Initialize(PathManager.GetCfgDir() + "DevicePM.xml", "GaN", ModuleName.PM1, "PM1");
|
||||
//Singleton<SimulatorDeviceManager>.Instance.Initialize(PathManager.GetCfgDir() + "DevicePM.xml", "GaN", ModuleName.PM2, "PM2");
|
||||
//Singleton<SimulatorDeviceManager>.Instance.Initialize(PathManager.GetCfgDir() + "DeviceTM.xml", "GaN", ModuleName.TM, "TM");
|
||||
|
||||
_thread = new PeriodicJob(200, OnMonitor, nameof(SimulatorSystem), true);
|
||||
}
|
||||
|
||||
@ -350,34 +358,34 @@ namespace SicSimulator.Instances
|
||||
try
|
||||
{
|
||||
MonitorPressureTM();
|
||||
MonitorPressureLoad();
|
||||
MonitorPressureUnLoad();
|
||||
MonitorSlitValveFlow();
|
||||
MonitorTMValve();
|
||||
//MonitorPressureLoad();
|
||||
//MonitorPressureUnLoad();
|
||||
//MonitorSlitValveFlow();
|
||||
//MonitorTMValve();
|
||||
|
||||
MonitorPm("PM1");
|
||||
MonitorPm("PM2");
|
||||
MonitorValve("PM1");
|
||||
MonitorValve("PM2");
|
||||
|
||||
MonitorFlowRamp("PM1");
|
||||
//MonitorFlowRamp("PM1");
|
||||
//MonitorFlowRamp("PM2");
|
||||
MonitorGasConnector("PM1");
|
||||
MonitorLid("PM1");
|
||||
MonitorLidSwing("PM1");
|
||||
MonitorConfinementRing("PM1");
|
||||
MonitorGasConnector("PM2");
|
||||
MonitorLid("PM2");
|
||||
MonitorLidSwing("PM2");
|
||||
MonitorConfinementRing("PM2");
|
||||
MonitorChamberMoveBody("PM1");
|
||||
MonitorChamberMoveBodyUp("PM1");
|
||||
MonitorHeater("PM1");
|
||||
MonitorRotation("PM1");
|
||||
MonitorChamberMoveBody("PM2");
|
||||
MonitorChamberMoveBodyUp("PM2");
|
||||
MonitorHeater("PM2");
|
||||
MonitorRotation("PM2");
|
||||
//MonitorGasConnector("PM1");
|
||||
//MonitorLid("PM1");
|
||||
//MonitorLidSwing("PM1");
|
||||
//MonitorConfinementRing("PM1");
|
||||
//MonitorGasConnector("PM2");
|
||||
//MonitorLid("PM2");
|
||||
//MonitorLidSwing("PM2");
|
||||
//MonitorConfinementRing("PM2");
|
||||
//MonitorChamberMoveBody("PM1");
|
||||
//MonitorChamberMoveBodyUp("PM1");
|
||||
//MonitorHeater("PM1");
|
||||
//MonitorRotation("PM1");
|
||||
//MonitorChamberMoveBody("PM2");
|
||||
//MonitorChamberMoveBodyUp("PM2");
|
||||
//MonitorHeater("PM2");
|
||||
//MonitorRotation("PM2");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -915,6 +923,266 @@ namespace SicSimulator.Instances
|
||||
|
||||
}
|
||||
|
||||
private void PmMotion(string pm)
|
||||
{
|
||||
IO.DI[$"{pm}.DI_PMSlitValveCloseCompleted"].Value = IO.DI[$"TM.DI_PM{(pm == "PM1" ? "A" : "B")}SlitValveClose"].Value;
|
||||
|
||||
IO.DI[$"{pm}.DI_LockingCylinderLock"].Value = !IO.DO[$"{pm}.DO_LockingCylinderLockUnlock"].Value;
|
||||
|
||||
if (IO.DO[$"{pm}.DO_ChamLidMotorAUp"].Value)
|
||||
{
|
||||
IO.DI[$"{pm}.DI_PMChamberLidDownpositioning"].Value = true;
|
||||
Task.Delay(2000).ContinueWith(x =>
|
||||
{
|
||||
IO.DI[$"{pm}.DI_PMChamberLidUppositioning"].Value = false;
|
||||
});
|
||||
}
|
||||
|
||||
if (IO.DO[$"{pm}.DO_ChamLidMotorADown"].Value)
|
||||
{
|
||||
IO.DI[$"{pm}.DI_PMChamberLidUppositioning"].Value = true;
|
||||
Task.Delay(2000).ContinueWith(x =>
|
||||
{
|
||||
IO.DI[$"{pm}.DI_PMChamberLidDownpositioning"].Value = false;
|
||||
});
|
||||
}
|
||||
DelaySetDoToDi(pm, "DI_PMChamberLidTighten", "DO_ChamLidTighten");
|
||||
DelaySetDoToDi(pm, "DI_PMChamberLidLoosen", "DO_ChamLidLoosen");
|
||||
DelaySetDoToDi(pm, "DI_PMChamberLidSwingLock", "DO_ChamLidSwingLock");
|
||||
DelaySetDoToDi(pm, "DI_PMChamberLidSwingUnLock", "DO_ChamLidSwingUnLock");
|
||||
DelaySetDoToDi(pm, "DI_PMChamberLidLock", "DO_ChamLidLockPL");
|
||||
DelaySetDoToDi(pm, "DI_PMChamberLidUnLock", "DO_ChamLidUnLockPL");
|
||||
|
||||
//磁流体仿真
|
||||
int temp = pm == "PM1" ? 0 : 1;
|
||||
|
||||
if (!_pre_DO_SpindleHome[temp] && IO.DO[$"{pm}.DO_SpindleHome"].Value)
|
||||
{
|
||||
IO.DI[$"{pm}.DI_SpindleHomeFinish"].Value = false;
|
||||
Task.Delay(1000).ContinueWith(x =>
|
||||
{
|
||||
IO.AI[$"{pm}.AI_SpindleCurrentPosition"].Value = 0;
|
||||
IO.DI[$"{pm}.DI_SpindleHomeFinish"].Value = true;
|
||||
});
|
||||
}
|
||||
_pre_DO_SpindleHome[temp] = IO.DO[$"{pm}.DO_SpindleHome"].Value;
|
||||
|
||||
if (!_pre_DO_SpindleLoadAngleRun[temp] && IO.DO[$"{pm}.DO_SpindleLoadAngleRun"].Value)
|
||||
{
|
||||
IO.DI[$"{pm}.DI_SpindlePositionComplete"].Value = false;
|
||||
Task.Delay(2000).ContinueWith(x =>
|
||||
{
|
||||
IO.AI[$"{pm}.AI_SpindleCurrentPosition"].Value += IO.AO[$"{pm}.AO_SpindleLoadAngle"].Value;
|
||||
if (IO.AI[$"{pm}.AI_SpindleCurrentPosition"].Value >= 360)
|
||||
{
|
||||
IO.AI[$"{pm}.AI_SpindleCurrentPosition"].Value -= 360;
|
||||
}
|
||||
IO.DI[$"{pm}.DI_SpindlePositionComplete"].Value = true;
|
||||
});
|
||||
}
|
||||
_pre_DO_SpindleLoadAngleRun[temp] = IO.DO[$"{pm}.DO_SpindleLoadAngleRun"].Value;
|
||||
|
||||
if (!_pre_DO_SpindleMoveSlot[temp] && IO.DO[$"{pm}.DO_SpindleMoveSlot"].Value)
|
||||
{
|
||||
IO.AI[$"{pm}.AI_SpindleActualSlot"].Value = 0;
|
||||
Task.Delay(2000).ContinueWith(x =>
|
||||
{
|
||||
var s = (int)IO.AO[$"{pm}.AO_SpindleSlot"].Value;
|
||||
if (s > 0 && s < 9)
|
||||
{
|
||||
IO.AI[$"{pm}.AI_SpindleCurrentPosition"].Value = IO.AO[$"{pm}.AO_SpindlePosition{s}"].Value;
|
||||
IO.AI[$"{pm}.AI_SpindleActualSlot"].Value = s;
|
||||
}
|
||||
});
|
||||
}
|
||||
_pre_DO_SpindleMoveSlot[temp] = IO.DO[$"{pm}.DO_SpindleMoveSlot"].Value;
|
||||
|
||||
//shutter仿真
|
||||
if (IO.DO[$"{pm}.DO_ShutterUp"].Value)
|
||||
{
|
||||
Task.Delay(2000).ContinueWith(x =>
|
||||
{
|
||||
IO.DI[$"{pm}.DI_ShutterUp"].Value = true;
|
||||
IO.DI[$"{pm}.DI_ShutterDown"].Value = false;
|
||||
});
|
||||
}
|
||||
if (IO.DO[$"{pm}.DO_ShutterDown"].Value)
|
||||
{
|
||||
Task.Delay(2000).ContinueWith(x =>
|
||||
{
|
||||
IO.DI[$"{pm}.DI_ShutterUp"].Value = false;
|
||||
IO.DI[$"{pm}.DI_ShutterDown"].Value = true;
|
||||
});
|
||||
}
|
||||
if (IO.DO[$"{pm}.DO_ShutterForward"].Value)
|
||||
{
|
||||
Task.Delay(2000).ContinueWith(x =>
|
||||
{
|
||||
IO.DI[$"{pm}.DI_ShutterForward"].Value = true;
|
||||
IO.DI[$"{pm}.DI_ShutterBackward"].Value = false;
|
||||
});
|
||||
}
|
||||
if (IO.DO[$"{pm}.DO_ShutterBackward"].Value)
|
||||
{
|
||||
Task.Delay(2000).ContinueWith(x =>
|
||||
{
|
||||
IO.DI[$"{pm}.DI_ShutterForward"].Value = false;
|
||||
IO.DI[$"{pm}.DI_ShutterBackward"].Value = true;
|
||||
});
|
||||
}
|
||||
|
||||
////V99仿真
|
||||
//if (IO.DO[$"{pm}.DO_PMPressureRelief"].Value && !IO.DO[$"{pm}.DO_PMPressureReliefClose"].Value)
|
||||
//{
|
||||
// IO.DI[$"{pm}.DI_PMPressureReliefOpenFB"].Value = true;
|
||||
// IO.DI[$"{pm}.DI_PMPressureReliefCloseFB"].Value = false;
|
||||
//}
|
||||
|
||||
//if (IO.DO[$"{pm}.DO_PMPressureReliefClose"].Value && !IO.DO[$"{pm}.DO_PMPressureRelief"].Value)
|
||||
//{
|
||||
// IO.DI[$"{pm}.DI_PMPressureReliefOpenFB"].Value = false;
|
||||
// IO.DI[$"{pm}.DI_PMPressureReliefCloseFB"].Value = true;
|
||||
//}
|
||||
}
|
||||
|
||||
private void DelaySetDoToDi(string pm, string diName, string doName)
|
||||
{
|
||||
if (!IO.DO[$"{pm}.{doName}"].Value)
|
||||
{
|
||||
IO.DI[$"{pm}.{diName}"].Value = false;
|
||||
return;
|
||||
}
|
||||
if (IO.DI[$"{pm}.{diName}"].Value != IO.DO[$"{pm}.{doName}"].Value)
|
||||
{
|
||||
Task.Delay(2000).ContinueWith(x =>
|
||||
{
|
||||
IO.DI[$"{pm}.{diName}"].Value = IO.DO[$"{pm}.{doName}"].Value;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void MonitorTVPm(string pm)
|
||||
{
|
||||
IO.AI[$"{pm}.AI_ButterflyValveActualMode"].Value = IO.AO[$"{pm}.AO_ButterflyValveSetMode"].Value;
|
||||
//IO.AI[$"{pm}.AI_HeartBeat"].Value = IO.AO[$"{pm}.AO_HeartBeat"].Value;
|
||||
|
||||
IO.AI[$"{pm}.AI_ButterflyValveActualPosition"].Value = IO.AO[$"{pm}.AO_ButterflyValveSetPosition"].Value;
|
||||
|
||||
var mode = IO.AO[$"{pm}.AO_ButterflyValveSetMode"].Value;
|
||||
//蝶阀开启,跟着蝶阀的设置值走
|
||||
if (IO.DO[$"{pm}.DO_ButterflyEnable"].Value)
|
||||
{
|
||||
if (mode == 5)
|
||||
{
|
||||
if (IO.AI[$"{pm}.AI_ButterflyValveActualPressure"].Value > IO.AO[$"{pm}.AO_ButterflyValveSetPressure"].Value)
|
||||
{
|
||||
if (IO.AI[$"{pm}.AI_ButterflyValveActualPressure"].Value - 30 > IO.AO[$"{pm}.AO_ButterflyValveSetPressure"].Value)
|
||||
{
|
||||
IO.AI[$"{pm}.AI_ButterflyValveActualPressure"].Value -= 30;
|
||||
}
|
||||
else
|
||||
{
|
||||
IO.AI[$"{pm}.AI_ButterflyValveActualPressure"].Value = IO.AO[$"{pm}.AO_ButterflyValveSetPressure"].Value;
|
||||
}
|
||||
}
|
||||
else if (IO.AI[$"{pm}.AI_ButterflyValveActualPressure"].Value < IO.AO[$"{pm}.AO_ButterflyValveSetPressure"].Value)
|
||||
{
|
||||
if (IO.AI[$"{pm}.AI_ButterflyValveActualPressure"].Value + 10 < IO.AO[$"{pm}.AO_ButterflyValveSetPressure"].Value)
|
||||
{
|
||||
IO.AI[$"{pm}.AI_ButterflyValveActualPressure"].Value += 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
IO.AI[$"{pm}.AI_ButterflyValveActualPressure"].Value = IO.AO[$"{pm}.AO_ButterflyValveSetPressure"].Value;
|
||||
}
|
||||
}
|
||||
IO.AI[$"{pm}.AI_PMChamberPressure"].Value = IO.AI[$"{pm}.AI_ButterflyValveActualPressure"].Value;
|
||||
}
|
||||
if (mode == 2)
|
||||
{
|
||||
if (IO.AO[$"{pm}.AO_ButterflyValveSetPosition"].Value > 0)
|
||||
{
|
||||
if (IO.AI[$"{pm}.AI_ButterflyValveActualPressure"].Value > 0)
|
||||
{
|
||||
IO.AI[$"{pm}.AI_ButterflyValveActualPressure"].Value -= (IO.AO[$"{pm}.AO_ButterflyValveSetPosition"].Value) / 8;
|
||||
}
|
||||
else
|
||||
IO.AI[$"{pm}.AI_ButterflyValveActualPressure"].Value = 0;
|
||||
}
|
||||
IO.AI[$"{pm}.AI_PMChamberPressure"].Value = IO.AI[$"{pm}.AI_ButterflyValveActualPressure"].Value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool fontMfc = false;
|
||||
for (int i = 70; i <= 89; i++)
|
||||
{
|
||||
if (IO.AI[$"{pm}.AI_M{i}"].Value > 100)
|
||||
{
|
||||
fontMfc = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (fontMfc)
|
||||
{
|
||||
if (IO.AI[$"{pm}.AI_ButterflyValveActualPressure"].Value < 1200)
|
||||
{
|
||||
IO.AI[$"{pm}.AI_ButterflyValveActualPressure"].Value += 10;
|
||||
}
|
||||
IO.AI[$"{pm}.AI_PMChamberPressure"].Value = IO.AI[$"{pm}.AI_ButterflyValveActualPressure"].Value;
|
||||
}
|
||||
}
|
||||
|
||||
//蝶阀Ramp有Bug,设置AO值可以化解
|
||||
//if (IO.AI[$"{pm}.AI_ButterflyValveActualPressure"].Value >= 1100)
|
||||
//{
|
||||
// IO.AO[$"{pm}.AO_ButterflyValveSetPressure"].Value = IO.AI[$"{pm}.AI_ButterflyValveActualPressure"].Value;
|
||||
//}
|
||||
|
||||
//string s = pm == "PM1" ? "A" : "B";
|
||||
//if (IO.DI[$"TM.DI_TMPM{s}BanlanceFB"].Value || IO.DI[$"TM.DI_PM{s}GateValveOpen"].Value)
|
||||
//{
|
||||
// var v1 = IO.AI[$"{pm}.AI_PMChamberPressure"].Value;
|
||||
// var v2 = IO.AI[$"TM.AI_TMChamberPressure"].Value;
|
||||
// if (v1 > v2)
|
||||
// {
|
||||
// IO.AI[$"TM.AI_TMChamberPressure"].Value = v1;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// IO.AI[$"{pm}.AI_PMChamberPressure"].Value = v2;
|
||||
// }
|
||||
//}
|
||||
//else
|
||||
// IO.AI[$"{pm}.AI_PMChamberPressure"].Value = IO.AI[$"{pm}.AI_ButterflyValveActualPressure"].Value;
|
||||
|
||||
//V27自动打开
|
||||
//if (IO.AI[$"{pm}.AI_ChamPress"].Value > 1020 && IO.DO[$"{pm}.DO_PumpBypass(V27)"].Value != true)
|
||||
//{
|
||||
// IO.DO[$"{pm}.DO_PumpBypass(V27)"].Value = true;
|
||||
//}
|
||||
//if (IO.AI[$"{pm}.AI_ChamPress"].Value < 900 && IO.DO[$"{pm}.DO_PumpBypass(V27)"].Value)
|
||||
//{
|
||||
// IO.DO[$"{pm}.DO_PumpBypass(V27)"].Value = false;
|
||||
//}
|
||||
|
||||
if (IO.DO[$"{pm}.DO_SpindleSpeedRun"].Value)
|
||||
{
|
||||
IO.AI[$"{pm}.AI_SpindleCurrentSpeed"].Value = IO.AO[$"{pm}.AO_SpindleVelocity"].Value;
|
||||
}
|
||||
else
|
||||
IO.AI[$"{pm}.AI_SpindleCurrentSpeed"].Value = 0;
|
||||
|
||||
//设置PT2的压力比PT1的小20
|
||||
var pt2 = IO.AI[$"{pm}.AI_PMChamberPressure"].Value - 20;
|
||||
if (pt2 > 0)
|
||||
{
|
||||
IO.AI[$"{pm}.AI_ColdtrapExitPressure"].Value = pt2;
|
||||
}
|
||||
IO.AI[$"{pm}.AI_ColdtrapExitPressure"].Value = IO.AI[$"{pm}.AI_PMChamberPressure"].Value - 20 > 0 ? IO.AI[$"{pm}.AI_PMChamberPressure"].Value - 20 : 0;
|
||||
}
|
||||
|
||||
private void MonitorValve(string pm)
|
||||
{
|
||||
|
||||
|
||||
80
Framework/SimulatorCore/AI_AORandom/SimulatorAI_AORandom.cs
Normal file
80
Framework/SimulatorCore/AI_AORandom/SimulatorAI_AORandom.cs
Normal file
@ -0,0 +1,80 @@
|
||||
using Aitex.Core.RT.Device;
|
||||
using Aitex.Core.RT.IOCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace MECF.Framework.Simulator.Core
|
||||
{
|
||||
public class SimulatorAI_AORandom : BaseDevice, IDevice
|
||||
{
|
||||
protected List<AI_AORandomData> AI_AOList = new List<AI_AORandomData>();
|
||||
private readonly Random _rnd = new Random();
|
||||
|
||||
public SimulatorAI_AORandom(string module, XmlElement node, string ioModule = "") : base(module, node, ioModule)
|
||||
{
|
||||
InitializeIValve(node);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据XML配置创建MFC控制对象
|
||||
/// </summary>
|
||||
/// <param name="node"></param>
|
||||
protected virtual void InitializeIValve(XmlElement node)
|
||||
{
|
||||
XmlNodeList valveNodes = node.GetElementsByTagName("Random");
|
||||
foreach (XmlElement xmlElement in valveNodes)
|
||||
{
|
||||
AI_AORandomData randomData = new AI_AORandomData()
|
||||
{
|
||||
Type = xmlElement.GetAttribute("type"),
|
||||
Name = xmlElement.GetAttribute("ioName"),
|
||||
BaseValue = Convert.ToSingle(xmlElement.GetAttribute("baseValue"))
|
||||
};
|
||||
AI_AOList.Add(randomData);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void HandleMonitor()
|
||||
{
|
||||
Random();
|
||||
}
|
||||
|
||||
protected virtual void Random()
|
||||
{
|
||||
foreach (var ai_ao in AI_AOList)
|
||||
{
|
||||
if (ai_ao.Type == "AI")
|
||||
IO.AI[$"{Module}.{ai_ao.Name}"].Value = ai_ao.BaseValue + (float)_rnd.NextDouble();
|
||||
else if (ai_ao.Type == "AO")
|
||||
IO.AO[$"{Module}.{ai_ao.Name}"].Value = ai_ao.BaseValue + (float)_rnd.NextDouble();
|
||||
}
|
||||
}
|
||||
|
||||
public bool Initialize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class AI_AORandomData
|
||||
{
|
||||
public string Type { get; set; }
|
||||
public string Name { get; set; }
|
||||
public float BaseValue { get; set; }
|
||||
}
|
||||
}
|
||||
188
Framework/SimulatorCore/Device/SimulatorDeviceManager.cs
Normal file
188
Framework/SimulatorCore/Device/SimulatorDeviceManager.cs
Normal file
@ -0,0 +1,188 @@
|
||||
using Aitex.Core.RT.DataCenter;
|
||||
using Aitex.Core.RT.Device;
|
||||
using Aitex.Core.RT.Log;
|
||||
using Aitex.Core.Util;
|
||||
using MECF.Framework.Common.Equipment;
|
||||
using MECF.Framework.Common.Utilities;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace MECF.Framework.Simulator.Core
|
||||
{
|
||||
public class SimulatorDeviceManager
|
||||
{
|
||||
private readonly Dictionary<string, IDevice> _nameDevice = new Dictionary<string, IDevice>();
|
||||
private readonly object _lockerDevice = new object();
|
||||
private readonly R_TRIG _trigExceed500 = new R_TRIG();
|
||||
private readonly Dictionary<Type, List<IDevice>> _typeDevice = new Dictionary<Type, List<IDevice>>();
|
||||
private readonly ConcurrentBag<IDevice> _optionDevice = new ConcurrentBag<IDevice>();
|
||||
private PeriodicJob _thread;
|
||||
|
||||
/// <summary>
|
||||
/// 设置或返回是否以异步方式初始化当前管理器中的设备。
|
||||
/// </summary>
|
||||
public bool DisableAsyncInitialize { get; set; }
|
||||
/// <summary>
|
||||
/// 返回当前设备管理器映射的XML配置文件节点。
|
||||
/// </summary>
|
||||
protected XmlElement DeviceModelNodes { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 向设备管理器的设备字典中添加一个设备实例。
|
||||
/// </summary>
|
||||
/// <param name="device"></param>
|
||||
protected virtual void QueueDevice(IDevice device)
|
||||
{
|
||||
QueueDevice($"{device.Module}.{device.Name}", device);
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
|
||||
public void Initialize(string modelFile, string type, ModuleName mod, string ioModule = "")
|
||||
{
|
||||
if (!File.Exists(modelFile))
|
||||
{
|
||||
throw new ApplicationException($"did not find the device model file {modelFile} ");
|
||||
}
|
||||
var xmlDocument = new XmlDocument();
|
||||
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");
|
||||
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");
|
||||
if (string.IsNullOrEmpty(text))
|
||||
{
|
||||
text = "MECF.Framework.RT.EquipmentLibrary";
|
||||
}
|
||||
var text2 = xmlElement2.Name.Substring(0, xmlElement2.Name.Length - 1);
|
||||
var text3 = xmlElement2.GetAttribute("classType");
|
||||
if (string.IsNullOrEmpty(text3))
|
||||
{
|
||||
text3 = "Aitex.Core.RT.Device.Unit." + text2;
|
||||
}
|
||||
var assembly = Assembly.Load(text);
|
||||
var type2 = assembly.GetType(text3);
|
||||
if (type2 == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
foreach (var childNode2 in xmlElement2.ChildNodes)
|
||||
{
|
||||
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;
|
||||
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
|
||||
{
|
||||
InitDevice(device);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_thread = new PeriodicJob(200, Monitor, "SimulatorSystem", true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LOG.Write(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitDevice(IDevice device)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!device.Initialize())
|
||||
{
|
||||
LOG.Write(device.Name + " initialize failed.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LOG.Write(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 后台扫面线程调用的方法。
|
||||
/// </summary>
|
||||
public bool Monitor()
|
||||
{
|
||||
lock (_lockerDevice)
|
||||
{
|
||||
foreach (var value in _nameDevice.Values)
|
||||
{
|
||||
try
|
||||
{
|
||||
PerformanceMonitor.MonitorRun(() =>
|
||||
{
|
||||
value.Monitor();
|
||||
return true;
|
||||
}, 500, _trigExceed500, out _, $"{value.Module}.{value.Name} monitor");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LOG.Write(ex, $"{ModuleName.Diagnosis} Monitor {value.Name} Exception");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
70
Framework/SimulatorCore/IoAO_AI/SimulatorIoAO_AI.cs
Normal file
70
Framework/SimulatorCore/IoAO_AI/SimulatorIoAO_AI.cs
Normal file
@ -0,0 +1,70 @@
|
||||
using Aitex.Core.RT.Device;
|
||||
using Aitex.Core.RT.IOCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace MECF.Framework.Simulator.Core
|
||||
{
|
||||
public class SimulatorIoAO_AI : BaseDevice, IDevice
|
||||
{
|
||||
protected Dictionary<string, string> AO_AI = new Dictionary<string, string>();
|
||||
|
||||
public SimulatorIoAO_AI(string module, XmlElement node, string ioModule) : base(module, node, ioModule)
|
||||
{
|
||||
InitializeIValve(node);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据XML配置创建气阀控制对象
|
||||
/// </summary>
|
||||
/// <param name="node"></param>
|
||||
protected virtual void InitializeIValve(XmlElement node)
|
||||
{
|
||||
XmlNodeList valveNodes = node.GetElementsByTagName("AO_AI");
|
||||
foreach (XmlElement xmlElement in valveNodes)
|
||||
{
|
||||
string aiName = xmlElement.GetAttribute("ai");
|
||||
string aoName = xmlElement.GetAttribute("ao");
|
||||
if (!AO_AI.ContainsKey(aiName) && !AO_AI.ContainsKey(aoName))
|
||||
AO_AI.Add(aiName, aoName);
|
||||
|
||||
var isDefaultOpen = xmlElement.GetAttribute("aoDefault");
|
||||
if (!String.IsNullOrWhiteSpace(isDefaultOpen))
|
||||
IO.AO[$"{Module}.{aoName}"].Value = Convert.ToSingle(isDefaultOpen);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void HandleMonitor()
|
||||
{
|
||||
DoValueToDI();
|
||||
}
|
||||
|
||||
protected void DoValueToDI()
|
||||
{
|
||||
foreach (var ai_ao in AO_AI)
|
||||
{
|
||||
IO.AI[$"{Module}.{ai_ao.Key}"].Value = IO.AO[$"{Module}.{ai_ao.Value}"].Value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Initialize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
39
Framework/SimulatorCore/IoDO_DI/SimulatorIoDO_DI.cs
Normal file
39
Framework/SimulatorCore/IoDO_DI/SimulatorIoDO_DI.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using Aitex.Core.RT.IOCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace MECF.Framework.Simulator.Core
|
||||
{
|
||||
public class SimulatorIoDO_DI : SimulatorIoValve
|
||||
{
|
||||
public SimulatorIoDO_DI(string module, XmlElement node, string ioModule) : base(module, node, ioModule)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据XML配置创建气阀控制对象
|
||||
/// </summary>
|
||||
/// <param name="node"></param>
|
||||
protected override void InitializeIValve(XmlElement node)
|
||||
{
|
||||
XmlNodeList valveNodes = node.GetElementsByTagName("DO_DI");
|
||||
foreach (XmlElement xmlElement in valveNodes)
|
||||
{
|
||||
string diName = xmlElement.GetAttribute("di");
|
||||
string doName = xmlElement.GetAttribute("do");
|
||||
if (!DI_DOList.ContainsKey(diName) && !DI_DOList.ContainsKey(doName))
|
||||
DI_DOList.Add(diName, doName);
|
||||
|
||||
var isDefaultOpen = xmlElement.GetAttribute("doDefault");
|
||||
if (!String.IsNullOrWhiteSpace(isDefaultOpen))
|
||||
IO.DO[$"{Module}.{doName}"].Value = Convert.ToBoolean(isDefaultOpen);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
73
Framework/SimulatorCore/IoDefault/SimulatorIoDefault.cs
Normal file
73
Framework/SimulatorCore/IoDefault/SimulatorIoDefault.cs
Normal file
@ -0,0 +1,73 @@
|
||||
using Aitex.Core.RT.Device;
|
||||
using Aitex.Core.RT.IOCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace MECF.Framework.Simulator.Core
|
||||
{
|
||||
public class SimulatorIoDefault : BaseDevice, IDevice
|
||||
{
|
||||
protected Dictionary<string, object> IO_ValueList = new Dictionary<string, object>();
|
||||
private readonly Random _rnd = new Random();
|
||||
|
||||
public SimulatorIoDefault(string module, XmlElement node, string ioModule = "") : base(module, node, ioModule)
|
||||
{
|
||||
InitializeIValve(node);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据XML配置创建IO对象初始默认值
|
||||
/// </summary>
|
||||
/// <param name="node"></param>
|
||||
protected virtual void InitializeIValve(XmlElement node)
|
||||
{
|
||||
XmlNodeList valveNodes = node.GetElementsByTagName("IODefault");
|
||||
foreach (XmlElement xmlElement in valveNodes)
|
||||
{
|
||||
string type = xmlElement.GetAttribute("type");
|
||||
string ioName = xmlElement.GetAttribute("ioName");
|
||||
string value = xmlElement.GetAttribute("default");
|
||||
switch (type)
|
||||
{
|
||||
case "DI":
|
||||
IO.DI[$"{Module}.{ioName}"].Value = Convert.ToBoolean(value);
|
||||
break;
|
||||
|
||||
case "DO":
|
||||
IO.DO[$"{Module}.{ioName}"].Value = Convert.ToBoolean(value);
|
||||
break;
|
||||
|
||||
case "AI":
|
||||
IO.AI[$"{Module}.{ioName}"].Value = Convert.ToSingle(value);
|
||||
break;
|
||||
|
||||
case "AO":
|
||||
IO.AO[$"{Module}.{ioName}"].Value = Convert.ToSingle(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Initialize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
92
Framework/SimulatorCore/IoMFC/SimulatorMFC.cs
Normal file
92
Framework/SimulatorCore/IoMFC/SimulatorMFC.cs
Normal file
@ -0,0 +1,92 @@
|
||||
using Aitex.Core.RT.Device;
|
||||
using Aitex.Core.RT.IOCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace MECF.Framework.Simulator.Core
|
||||
{
|
||||
public class SimulatorMFC : BaseDevice, IDevice
|
||||
{
|
||||
protected Dictionary<string, string> AI_AOList = new Dictionary<string, string>();
|
||||
private readonly Random _rnd = new Random();
|
||||
|
||||
public SimulatorMFC(string module, XmlElement node, string ioModule = "") : base(module, node, ioModule)
|
||||
{
|
||||
InitializeIValve(node);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据XML配置创建MFC控制对象
|
||||
/// </summary>
|
||||
/// <param name="node"></param>
|
||||
protected virtual void InitializeIValve(XmlElement node)
|
||||
{
|
||||
XmlNodeList valveNodes = node.GetElementsByTagName("IoMfc");
|
||||
foreach (XmlElement xmlElement in valveNodes)
|
||||
{
|
||||
string aiFlow = xmlElement.GetAttribute("aiFlow");
|
||||
string aoFlow = xmlElement.GetAttribute("aoFlow");
|
||||
if (!AI_AOList.ContainsKey(aiFlow) && !AI_AOList.ContainsKey(aoFlow))
|
||||
AI_AOList.Add(aiFlow, aoFlow);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected override void HandleMonitor()
|
||||
{
|
||||
Ramp();
|
||||
}
|
||||
|
||||
protected virtual void Ramp()
|
||||
{
|
||||
foreach (var ai_ao in AI_AOList)
|
||||
{
|
||||
float setpoint = 0;
|
||||
float result = 0;
|
||||
float current = 0;
|
||||
if (IO.AI[$"{Module}.{ai_ao.Key}"] != null)
|
||||
{
|
||||
current = IO.AI[$"{Module}.{ai_ao.Key}"].Value;
|
||||
setpoint = IO.AO[$"{Module}.{ai_ao.Value}"].Value;
|
||||
}
|
||||
|
||||
|
||||
if (current >= setpoint)
|
||||
{
|
||||
result = current - 50;
|
||||
if (result < setpoint)
|
||||
result = setpoint;
|
||||
}
|
||||
if (current < setpoint)
|
||||
{
|
||||
result = current + 50;
|
||||
if (result > setpoint)
|
||||
result = setpoint;
|
||||
}
|
||||
|
||||
result = result + (float)_rnd.NextDouble();
|
||||
|
||||
IO.AI[$"{Module}.{ai_ao.Key}"].Value = result;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Initialize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
40
Framework/SimulatorCore/IoPressure/SimulatorPressure.cs
Normal file
40
Framework/SimulatorCore/IoPressure/SimulatorPressure.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using Aitex.Core.RT.Device;
|
||||
using Aitex.Core.RT.IOCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace MECF.Framework.Simulator.Core
|
||||
{
|
||||
public class SimulatorPressure : SimulatorMFC
|
||||
{
|
||||
public SimulatorPressure(string module, XmlElement node, string ioModule) : base(module, node, ioModule)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据XML配置创建PC控制对象
|
||||
/// </summary>
|
||||
/// <param name="node"></param>
|
||||
protected override void InitializeIValve(XmlElement node)
|
||||
{
|
||||
XmlNodeList valveNodes = node.GetElementsByTagName("IoPressureMeter");
|
||||
foreach (XmlElement xmlElement in valveNodes)
|
||||
{
|
||||
string aiValue = xmlElement.GetAttribute("aiValue");
|
||||
string aoValue = xmlElement.GetAttribute("aoValue");
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(aoValue))
|
||||
if (!AI_AOList.ContainsKey(aiValue) && !AI_AOList.ContainsKey(aoValue))
|
||||
AI_AOList.Add(aiValue, aoValue);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
69
Framework/SimulatorCore/IoValves/SimulatorIoValve.cs
Normal file
69
Framework/SimulatorCore/IoValves/SimulatorIoValve.cs
Normal file
@ -0,0 +1,69 @@
|
||||
using Aitex.Core.RT.Device;
|
||||
using Aitex.Core.RT.IOCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace MECF.Framework.Simulator.Core
|
||||
{
|
||||
public class SimulatorIoValve : BaseDevice, IDevice
|
||||
{
|
||||
protected Dictionary<string, string> DI_DOList = new Dictionary<string, string>();
|
||||
|
||||
public SimulatorIoValve(string module, XmlElement node, string ioModule) : base(module, node, ioModule)
|
||||
{
|
||||
InitializeIValve(node);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据XML配置创建气阀控制对象
|
||||
/// </summary>
|
||||
/// <param name="node"></param>
|
||||
protected virtual void InitializeIValve(XmlElement node)
|
||||
{
|
||||
XmlNodeList valveNodes = node.GetElementsByTagName("IoValve");
|
||||
foreach (XmlElement xmlElement in valveNodes)
|
||||
{
|
||||
string diName = xmlElement.GetAttribute("diOpen");
|
||||
string doName = xmlElement.GetAttribute("doOpen");
|
||||
if (!DI_DOList.ContainsKey(diName) && !DI_DOList.ContainsKey(doName))
|
||||
DI_DOList.Add(diName, doName);
|
||||
|
||||
var isDefaultOpen = xmlElement.GetAttribute("isDefaultOpen");
|
||||
if (!String.IsNullOrWhiteSpace(isDefaultOpen))
|
||||
IO.DO[$"{Module}.{doName}"].Value = Convert.ToBoolean(isDefaultOpen);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void HandleMonitor()
|
||||
{
|
||||
DoValueToDI();
|
||||
}
|
||||
|
||||
protected void DoValueToDI()
|
||||
{
|
||||
foreach (var di_do in DI_DOList)
|
||||
{
|
||||
IO.DI[$"{Module}.{di_do.Key}"].Value = IO.DO[$"{Module}.{di_do.Value}"].Value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Initialize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -62,6 +62,7 @@
|
||||
<Reference Include="WindowsBase" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AI_AORandom\SimulatorAI_AORandom.cs" />
|
||||
<Compile Include="Aligners\HPA48\HPA48Simulator.cs" />
|
||||
<Compile Include="Aligners\HPA48\HPA48View.xaml.cs">
|
||||
<DependentUpon>HPA48View.xaml</DependentUpon>
|
||||
@ -75,6 +76,13 @@
|
||||
<Compile Include="CarrierIDReader\HoneywellHf800\HoneywellBarcodeView.xaml.cs">
|
||||
<DependentUpon>HoneywellBarcodeView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Device\SimulatorDeviceManager.cs" />
|
||||
<Compile Include="IoAO_AI\SimulatorIoAO_AI.cs" />
|
||||
<Compile Include="IoDefault\SimulatorIoDefault.cs" />
|
||||
<Compile Include="IoDO_DI\SimulatorIoDO_DI.cs" />
|
||||
<Compile Include="IoMFC\SimulatorMFC.cs" />
|
||||
<Compile Include="IoPressure\SimulatorPressure.cs" />
|
||||
<Compile Include="IoValves\SimulatorIoValve.cs" />
|
||||
<Compile Include="LoadPorts\SG\SGLoadPortSimulator.cs" />
|
||||
<Compile Include="LoadPorts\SG\SGLoadPortView.xaml.cs">
|
||||
<DependentUpon>SGLoadPortView.xaml</DependentUpon>
|
||||
@ -575,7 +583,7 @@
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties robots_4hiratar4_4iosimulatoritems_1json__JsonSchema="https://jenkins-x.io/schemas/jx-schema.json" vce_4brooksvce_4iosimulatoritems_1json__JsonSchema="http://json.schemastore.org/apibuilder.json" />
|
||||
<UserProperties vce_4brooksvce_4iosimulatoritems_1json__JsonSchema="http://json.schemastore.org/apibuilder.json" robots_4hiratar4_4iosimulatoritems_1json__JsonSchema="https://jenkins-x.io/schemas/jx-schema.json" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
</Project>
|
||||
Loading…
Reference in New Issue
Block a user