sangwq 2 år sedan
förälder
incheckning
a5245356d0

+ 268 - 0
Venus/Venus_RT/Devices/IODevices/IoCylinder.cs

@@ -0,0 +1,268 @@
+using System;
+using System.Xml;
+using Aitex.Core.Common.DeviceData;
+using Aitex.Core.RT.DataCenter;
+using Aitex.Core.RT.Device;
+using Aitex.Core.RT.Event;
+using Aitex.Core.RT.IOCore;
+using Aitex.Core.RT.Log;
+using Aitex.Core.RT.OperationCenter;
+using Aitex.Core.Util;
+
+namespace Venus_RT.Devices
+{
+    public class IoCylinder : BaseDevice, IDevice
+    {
+        private readonly DIAccessor _diON;
+        private readonly DIAccessor _diOFF;
+
+        private readonly DOAccessor _doON;
+        private readonly DOAccessor _doOFF;
+
+        private CylinderState _operation;
+        private readonly DeviceTimer _timer = new DeviceTimer();
+        private readonly R_TRIG _trigReset = new R_TRIG();
+        private readonly R_TRIG _trigError = new R_TRIG();
+
+        public bool EnableOpen { get; set; }
+        public bool EnableClose { get; set; }
+
+        private string _error = null;
+
+        public int SetPoint
+        {
+            get
+            {
+                if (_doON.Value && _doOFF.Value) return (int)CylinderState.Error;
+                if (_doON.Value && !_doOFF.Value) return (int)CylinderState.Open;
+                if (!_doON.Value && _doOFF.Value) return (int)CylinderState.Close;
+                if (!_doON.Value && !_doOFF.Value) return (int)CylinderState.Unknown;
+
+                return (int)CylinderState.Unknown;
+            }
+        }
+
+        public CylinderState State
+        {
+            get
+            {
+                if (_diON != null && _diOFF != null)
+                {
+                    if (ONFeedback && _diOFF.Value)
+                        return CylinderState.Error;
+                    if (ONFeedback && !_diOFF.Value)
+                        return CylinderState.Open;
+                    if (!ONFeedback && _diOFF.Value)
+                        return CylinderState.Close;
+                    if (!ONFeedback && !_diOFF.Value)
+                        return CylinderState.Unknown;
+                }
+                return CylinderState.Unknown;
+            }
+        }
+
+        public bool ONFeedback
+        {
+            get { return _diON != null && _diON.Value; }
+        }
+        public bool OFFFeedback
+        {
+            get { return _diOFF != null && _diOFF.Value; }
+        }
+
+        public bool ONSetPoint
+        {
+            get
+            {
+                return _doON != null && _doON.Value;
+            }
+            private set
+            {
+                if (_doON != null && _doON.Check(value, out _error))
+                    _doON.Value = value;
+            }
+        }
+        public bool OFFSetPoint
+        {
+            get
+            {
+                return _doOFF != null && _doOFF.Value;
+            }
+            private set
+            {
+                if (_doOFF != null && _doOFF.Check(value, out _error))
+                    _doOFF.Value = value;
+            }
+        }
+
+        private AITCylinderData DeviceData
+        {
+            get
+            {
+                return new AITCylinderData
+                {
+                    Module            = Module,
+                    DeviceName        = Name,
+                    DeviceSchematicId = DeviceID,
+                    DisplayName       = Display,
+                    OpenFeedback      = ONFeedback,
+                    CloseFeedback     = OFFFeedback,
+                    OpenSetPoint      = ONSetPoint,
+                    CloseSetPoint     = OFFSetPoint
+                };
+            }
+        }
+
+        public IoCylinder(string module, XmlElement node, string ioModule = "")
+        {
+            base.Module = module;
+            base.Name = node.GetAttribute("id");
+            base.Display = node.GetAttribute("display");
+            base.DeviceID = node.GetAttribute("schematicId");
+            _operation = CylinderState.Unknown;
+
+            _diON = ParseDiNode("diON", node, ioModule);
+            _diOFF = ParseDiNode("diOFF", node, ioModule);
+            _doON = ParseDoNode("doON", node, ioModule);
+            _doOFF = ParseDoNode("doOFF", node, ioModule);
+        }
+
+        public bool Initialize()
+        {
+            DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData);
+
+            OP.Subscribe($"{Module}.{Name}.{AITCylinderOperation.Open}", (s, objects) => SetCylinder(true, out _));
+            OP.Subscribe($"{Module}.{Name}.{AITCylinderOperation.Close}", (s, objects) => SetCylinder(false, out _));
+            OP.Subscribe($"{Module}.{Name}.{AITCylinderOperation.SetState}", (out string reason, int time, object[] param) =>
+            {
+                bool isUp = (string)param[0] == "Up" ? true : false;
+                SetCylinder(isUp, out reason);
+                return true;
+            });
+            DEVICE.Register($"{Module}.{Name}.{AITCylinderOperation.Open}",
+                (out string reason, int time, object[] param) => SetCylinder(true, out reason));
+
+            DEVICE.Register($"{Module}.{Name}.{AITCylinderOperation.Close}",
+                (out string reason, int time, object[] param) => SetCylinder(false, out reason));
+
+            return true;
+        }
+
+        public void Terminate()
+        {
+            OFFSetPoint = false;
+            ONSetPoint = false;
+        }
+
+        public bool SetCylinder(bool isOpen, out string reason)
+        {
+            reason = "";
+
+            if (Name == "LoadLockArm")
+            {
+                if (isOpen && State == CylinderState.Open)
+                {
+                    EV.PostInfoLog(Module, $"检查到气缸 {Name} 已经开");
+                    return true;
+                }
+
+                if (!isOpen && State == CylinderState.Close)
+                {
+                    EV.PostInfoLog(Module, $"检查到气缸 {Name} 已经关");
+                    return true;
+                }
+            }
+
+            ONSetPoint = isOpen;
+            reason += _error;
+            reason += " ";
+
+            OFFSetPoint = !isOpen;
+            reason += _error;
+
+            _operation = isOpen ? CylinderState.Open : CylinderState.Close;
+            EV.PostInfoLog(Module, $"{(isOpen ? "打开" : "关闭")} 气缸 {Name}");
+
+            if (Name == "LoadLockArm")
+                _timer.Start(10 * 1000);
+            else if (Name == "SlitDoor")
+                _timer.Start(5 * 1000);
+            else
+                _timer.Start(2000);
+
+            return true;
+        }
+
+        public void Monitor()
+        {
+            try
+            {
+                if (_timer.IsTimeout())
+                {
+                    _timer.Stop();
+
+                    if (State != _operation)
+                    {
+                        if (_operation == CylinderState.Open)
+                        {
+                            if (!_doON.Check(true, out var reason))
+                                EV.PostAlarmLog(Module, "气缸信号无法打开, interlock, " + reason);
+                            else
+                                EV.PostAlarmLog(Module, "气缸信号仍然关闭");
+                        }
+                        else
+                        {
+                            if (!_doON.Check(false, out var reason))
+                                EV.PostAlarmLog(Module, "气缸信号无法关闭, interlock, " + reason);
+                            else
+                                EV.PostAlarmLog(Module, "气缸信号仍然打开");
+                        }
+                    }
+                    _operation = (CylinderState)SetPoint;
+                }
+                else if (_timer.IsIdle())
+                {
+                    _trigReset.CLK = SetPoint != (int)_operation;   // fire event only check at first, SetPoint set by interlock
+                    if (_trigReset.Q)
+                    {
+                        if (_operation == CylinderState.Open)
+                        {
+                            EV.PostAlarmLog(Module,!_doON.Check(true, out var reason)
+                                    ? $"气缸信号 {Display} was Close,Reason:{reason}"
+                                    : $"气缸信号 {Display} was Close,Reason PLC kept");
+                        }
+                        else
+                        {
+                            EV.PostAlarmLog(Module, !_doON.Check(false, out var reason)
+                                    ? $"气缸信号 {Display} was Open,Reason:{reason}"
+                                    : $"气缸信号 {Display} was Open,Reason PLC Kept");
+                        }
+                        _operation = (CylinderState)SetPoint;
+                    }
+                }
+
+                _trigError.CLK = State == CylinderState.Error;
+                if (_trigError.Q)
+                {
+                    //EV.PostAlarmLog(Module, "气缸状态错误");
+                }
+
+                //if ((SetPoint == (int)State) && (SetPoint == (int)CylinderState.Open || SetPoint == (int)CylinderState.Close))
+                //{
+                //    OFFSetPoint = false;
+                //    ONSetPoint = false;
+                //}
+            }
+            catch (Exception ex)
+            {
+                //LOG.Write(ex);
+            }
+        }
+
+        public void Reset()
+        {
+            _trigReset.RST = true;
+            _trigError.RST = true;
+        }
+    }
+}

+ 242 - 0
Venus/Venus_RT/Devices/IODevices/IoLid.cs

@@ -0,0 +1,242 @@
+using System;
+using System.Xml;
+using Aitex.Core.Common.DeviceData;
+using Aitex.Core.RT.DataCenter;
+using Aitex.Core.RT.Device;
+using Aitex.Core.RT.Event;
+using Aitex.Core.RT.IOCore;
+using Aitex.Core.RT.Log;
+using Aitex.Core.RT.OperationCenter;
+using Aitex.Core.Util;
+
+namespace Venus_RT.Devices.IODevices
+{
+    public class IoLid : BaseDevice, IDevice
+    {
+        private DIAccessor _diOFF;
+
+        private DOAccessor _doON;
+        private DOAccessor _doOFF;
+
+        private CylinderState _operation;
+        private DeviceTimer _timer = new DeviceTimer();
+        private R_TRIG _trigReset = new R_TRIG();
+        private R_TRIG _trigError = new R_TRIG();
+
+        public int SetPoint
+        {
+            get
+            {
+                return (int)CylinderState.Unknown;
+                /*
+                if (_doON.Value && _doOFF.Value) return (int)CylinderState.Error;
+                if (_doON.Value && !_doOFF.Value) return (int)CylinderState.Open;
+                if (!_doON.Value && _doOFF.Value) return (int)CylinderState.Close;
+                if (!_doON.Value && !_doOFF.Value) return (int)CylinderState.Unknown;
+                */
+            }
+        }
+
+        public CylinderState State
+        {
+            get
+            {
+                return _diOFF.Value ? CylinderState.Close : CylinderState.Open;
+            }
+        }
+
+        public bool OFFFeedback
+        {
+            get { return _diOFF.Value; }
+        }
+        public bool ONSetPoint
+        {
+            get
+            {
+                return _doON.Value;
+            }
+            set
+            {
+                if (_doON != null && _doON.Check(value, out _))
+                    _doON.Value = value;
+            }
+        }
+        public bool OFFSetPoint
+        {
+            get
+            {
+                return _doOFF.Value;
+            }
+            set
+            {
+                if (_doOFF != null && _doOFF.Check(value, out _))
+                    _doOFF.Value = value;
+            }
+        }
+
+        private AITCylinderData DeviceData
+        {
+            get
+            {
+                AITCylinderData deviceData = new AITCylinderData
+                {
+                    Module = Module,
+                    DeviceName = Name,
+                    DeviceSchematicId = DeviceID,
+                    DisplayName = Display,
+
+                    CloseFeedback = OFFFeedback,
+                };
+
+                return deviceData;
+            }
+        }
+
+        public IoLid(string module, XmlElement node, string ioModule = "")
+        {
+            base.Module = module;
+            base.Name = node.GetAttribute("id");
+            base.Display = node.GetAttribute("display");
+            base.DeviceID = node.GetAttribute("schematicId");
+
+            _diOFF = ParseDiNode("diOFF", node, ioModule);
+            _doON = ParseDoNode("doON", node, ioModule);
+            _doOFF = ParseDoNode("doOFF", node, ioModule);
+        }
+
+        public bool Initialize()
+        {
+            DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData);
+
+            OP.Subscribe($"{Module}.{Name}.{AITCylinderOperation.Open}", InvokeOpenCylinder);
+            OP.Subscribe($"{Module}.{Name}.{AITCylinderOperation.Close}", InvokeCloseCylinder);
+
+            DEVICE.Register($"{Module}.{Name}.{AITCylinderOperation.Open}", (out string reason, int time, object[] param) =>
+            {
+                bool ret = SetCylinder(true, out reason);
+                if (ret)
+                {
+                    reason = $"Open Cylinder {Name}";
+                    return true;
+                }
+
+                return false;
+            });
+
+            DEVICE.Register($"{Module}.{Name}.{AITCylinderOperation.Close}", (out string reason, int time, object[] param) =>
+            {
+                bool ret = SetCylinder(false, out reason);
+                if (ret)
+                {
+                    reason = $"Close Cylinder {Name}";
+                    return true;
+                }
+
+                return false;
+            });
+
+            return true;
+        }
+
+        private bool InvokeOpenCylinder(string arg1, object[] arg2)
+        {
+            if (!SetCylinder(true, out var reason))
+            {
+                EV.PostWarningLog(Module, $"Can not open cylinder {Module}.{Name}, {reason}");
+                return false;
+            }
+
+            EV.PostInfoLog(Module, $"Open cylinder {Module}.{Name}");
+
+            return true;
+        }
+
+        private bool InvokeCloseCylinder(string arg1, object[] arg2)
+        {
+            if (!SetCylinder(false, out var reason))
+            {
+                EV.PostWarningLog(Module, $"Can not close cylinder {Module}.{Name}, {reason}");
+                return false;
+            }
+
+            EV.PostInfoLog(Module, $"Close cylinder {Module}.{Name}");
+
+            return true;
+        }
+
+        public void Terminate()
+        {
+            OFFSetPoint = false;
+            ONSetPoint = false;
+        }
+
+        public bool SetCylinder(bool isOpen, out string reason)
+        {
+            reason = "";
+
+            ONSetPoint = isOpen;
+            OFFSetPoint = !isOpen;
+
+            _operation = isOpen ? CylinderState.Open : CylinderState.Close;
+            _timer.Start(1000 * 60 * 3);
+
+            return true;
+        }
+
+        public void Monitor()
+        {
+            try
+            {
+                if (_timer.IsTimeout())
+                {
+                    _timer.Stop();
+
+                    if (State != _operation)
+                    {
+                        if (_operation == CylinderState.Open)
+                        {
+                            if (!_doON.Check(true, out var reason))
+                                EV.PostAlarmLog(Module, "Open Cylinder Failed for interlock, " + reason);
+                            else
+                                EV.PostAlarmLog(Module, "Cylinder hold close status");
+                        }
+                        else
+                        {
+                            if (!_doON.Check(false, out var reason))
+                                EV.PostAlarmLog(Module, "Close Cylinder Failed for interlock, " + reason);
+                            else
+                                EV.PostAlarmLog(Module, "Cylinder hold open status");
+                        }
+                    }
+                    _operation = (CylinderState)SetPoint;
+                }
+                else if (_timer.IsIdle())
+                {
+                    return;
+                }
+
+                _trigError.CLK = State == CylinderState.Error;
+                if (_trigError.Q)
+                {
+                    EV.PostAlarmLog(Module, "Cylinder in error status");
+                }
+
+                if ((SetPoint == (int)State) && (SetPoint == (int)CylinderState.Open || SetPoint == (int)CylinderState.Close))
+                {
+                    OFFSetPoint = false;
+                    ONSetPoint = false;
+                }
+            }
+            catch (Exception ex)
+            {
+                //LOG.Write(ex);
+            }
+        }
+
+        public void Reset()
+        {
+            _trigReset.RST = true;
+            _trigError.RST = true;
+        }
+    }
+}

+ 321 - 0
Venus/Venus_RT/Devices/JetPM.cs

@@ -0,0 +1,321 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Aitex.Core.Common.DeviceData;
+using Aitex.Core.RT.DataCenter;
+using Aitex.Core.RT.Device;
+using Aitex.Core.RT.Device.Unit;
+using Aitex.Core.RT.Event;
+using Aitex.Core.RT.OperationCenter;
+using Aitex.Core.RT.SCCore;
+using Aitex.Core.Util;
+using MECF.Framework.Common.Device.Bases;
+using MECF.Framework.Common.Equipment;
+using MECF.Framework.Common.Schedulers;
+using MECF.Framework.Common.SubstrateTrackings;
+using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs;
+using Venus_RT.Devices.IODevices;
+using Venus_Core;
+namespace Venus_RT.Devices
+{
+    enum ValveType
+    {
+        PNV21,
+        PNV22,
+        PV11,
+        PV12,
+        PV21,
+        PV22,
+        PV31,
+        PV32,
+        PV41,
+        PV42,
+        N2,
+        Mfc1,
+        Mfc2,
+        Mfc3,
+        Mfc4,
+        Mfc5,
+        Mfc6,
+        Mfc7,
+        Mfc8,
+        PVHe1,
+        PVHe2,
+        GasFinal,
+        SoftPump,
+        FastPump,
+        CHBPurge,
+        CHBVent,
+        TurboPumpPurge,
+        Guage,
+        LoadlockVent,
+        LoadlockPumping
+    }
+    class JetPM : PM
+    {
+        private readonly IoLid _Lid;
+        private readonly IoLid _LidLoadlock;
+
+        private readonly IoCylinder _slitDoor;
+        private readonly IoCylinder _LiftPin;
+        private readonly IoCylinder _LoadLockArm;
+
+        private readonly IoSensor _CDAPressure;
+
+        private readonly IoValve _PNV21Valve;
+        private readonly IoValve _PNV22Valve;
+        private readonly IoValve _PV11Valve;
+        private readonly IoValve _PV12Valve;
+        private readonly IoValve _PV21Valve;
+        private readonly IoValve _PV22Valve;
+        private readonly IoValve _PV31Valve;
+        private readonly IoValve _PV32Valve;
+        private readonly IoValve _PV41Valve;
+        private readonly IoValve _PV42Valve;
+        private readonly IoValve _N2Valve;
+        private readonly IoValve _Mfc1Valve;
+        private readonly IoValve _Mfc2Valve;
+        private readonly IoValve _Mfc3Valve;
+        private readonly IoValve _Mfc4Valve;
+        private readonly IoValve _Mfc5Valve;
+        private readonly IoValve _Mfc6Valve;
+        private readonly IoValve _Mfc7Valve;
+        private readonly IoValve _Mfc8Valve;
+        private readonly IoValve _PVHe1Valve;
+        private readonly IoValve _PVHe2Valve;
+        private readonly IoValve _GasFinalValve;
+        private readonly IoValve _SoftPumpValve;
+        private readonly IoValve _FastPumpValve;
+        private readonly IoValve _CHBPurgeValve;
+        private readonly IoValve _CHBVentValve;
+        private readonly IoValve _TurboPumpPurgeValve;
+        private readonly IoValve _GuageValve;
+        private readonly IoValve _LoadlockVentValve;
+        private readonly IoValve _LoadlockPumpingValve;
+
+        private readonly PumpBase _MainPump;
+
+        // 盖子的状态
+        public bool IsLidClosed => _Lid.OFFFeedback;
+        public bool IsLidLoadlockClosed => _LidLoadlock.OFFFeedback;
+
+        public bool IsSlitDoorClosed => !_slitDoor.ONFeedback && _slitDoor.OFFFeedback;
+
+        public bool IsPumpRunning => _MainPump.IsRunning;
+        public bool HasPumpError => _MainPump.IsError || !_MainPump.IsRunning;
+
+        public bool IsCDA_OK => _CDAPressure.Value;
+
+        public new ModuleName Module { get; }
+
+        public JetPM(ModuleName mod) : base(mod.ToString())
+        {
+            Module = mod;
+
+
+            _Lid                = DEVICE.GetDevice<IoLid>($"{Module}.{VenusDevice.Lid}");
+            _LidLoadlock        = DEVICE.GetDevice<IoLid>($"{Module}.{VenusDevice.LidLoadlock}");
+
+            _slitDoor           = DEVICE.GetDevice<IoCylinder>($"{Module}.{VenusDevice.SlitDoor}");
+            _LiftPin            = DEVICE.GetDevice<IoCylinder>($"{Module}.{VenusDevice.LiftPin}");
+            _LoadLockArm        = DEVICE.GetDevice<IoCylinder>($"{Module}.{VenusDevice.LoadLockArm}");
+
+
+            _PNV21Valve             = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValvePVN21}");
+            _PNV22Valve             = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValvePVN22}");
+            _PV11Valve              = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValvePV11}");
+            _PV12Valve              = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValvePV12}");
+            _PV21Valve              = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValvePV21}");
+            _PV22Valve              = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValvePV22}");
+            _PV31Valve              = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValvePV31}");
+            _PV32Valve              = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValvePV32}");
+            _PV41Valve              = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValvePV41}");
+            _PV42Valve              = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValvePV42}");
+            _N2Valve                = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValveN2}");
+            _Mfc1Valve              = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValveMfc1}");
+            _Mfc2Valve              = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValveMfc2}");
+            _Mfc3Valve              = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValveMfc2}");
+            _Mfc4Valve              = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValveMfc2}");
+            _Mfc5Valve              = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValveMfc2}");
+            _Mfc6Valve              = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValveMfc2}");
+            _Mfc7Valve              = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValveMfc2}");
+            _Mfc8Valve              = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValveMfc2}");
+            _PVHe1Valve             = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValvePVHe1}");
+            _PVHe2Valve             = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValvePVHe2}");
+            _GasFinalValve          = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValveGasFinal}");
+            _SoftPumpValve          = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValveSoftPump}");
+            _FastPumpValve          = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValveFastPump}");
+            _CHBPurgeValve          = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValveCHBPurge}");
+            _CHBVentValve           = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValveCHBVent}");
+            _TurboPumpPurgeValve    = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValveTurboPumpPurge}");
+            _GuageValve             = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValveGuage}");
+            _LoadlockVentValve      = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValveLoadlockVent}");
+            _LoadlockPumpingValve   = DEVICE.GetDevice<IoValve>($"{Module}.{VenusDevice.ValveLoadlockPumping}");
+
+            _MainPump           = DEVICE.GetDevice<PumpBase>($"{Module}.{VenusDevice.MainPump}");
+
+            _CDAPressure = DEVICE.GetDevice<IoSensor>($"{Module}.SensorCDAPressureOk");
+
+
+            // RS232 Dry pump, SKY
+            if (SC.GetValue<int>($"{mod}.DryPump.CommunicationType") == (int)CommunicationType.RS232)
+            {
+                if (SC.GetValue<int>($"{mod}.DryPump.MFG") == (int)DryPumpMFG.SKY)
+                {
+                    _MainPump = DEVICE.GetDevice<SkyPump>($"{Module}.{VenusDevice.MainPump}");
+                }
+                else if (SC.GetValue<int>($"{mod}.DryPump.MFG") == (int)DryPumpMFG.Edwards)
+                {
+                    _MainPump = DEVICE.GetDevice<EdwardsPump>($"{Module}.{VenusDevice.MainPump}");
+                }
+            }
+
+        }
+
+
+        public void CloseValves()
+        {
+            _PNV21Valve.TurnValve(false, out _);
+            _PNV22Valve.TurnValve(false, out _);
+            _PV11Valve.TurnValve(false, out _);
+            _PV12Valve.TurnValve(false, out _);
+            _PV21Valve.TurnValve(false, out _);
+            _PV22Valve.TurnValve(false, out _);
+            _PV31Valve.TurnValve(false, out _);
+            _PV32Valve.TurnValve(false, out _);
+            _PV41Valve.TurnValve(false, out _);
+            _PV42Valve.TurnValve(false, out _);
+
+            _PVHe1Valve.TurnValve(false, out _);
+            _PVHe2Valve.TurnValve(false, out _);
+            _GasFinalValve.TurnValve(false, out _);
+            _SoftPumpValve.TurnValve(false, out _);
+            _FastPumpValve.TurnValve(false, out _);
+            _CHBPurgeValve.TurnValve(false, out _);
+            _CHBVentValve.TurnValve(false, out _);
+            _TurboPumpPurgeValve.TurnValve(false, out _);
+            _GuageValve.TurnValve(false, out _);
+            _LoadlockVentValve.TurnValve(false, out _);
+            _LoadlockPumpingValve.TurnValve(false, out _);
+
+            _N2Valve.TurnValve(false, out _);
+            _FastPumpValve.TurnValve(false, out _);
+
+            _Mfc1Valve.TurnValve(false, out _);
+            _Mfc2Valve.TurnValve(false, out _);
+            _Mfc3Valve.TurnValve(false, out _);
+            _Mfc4Valve.TurnValve(false, out _);
+            _Mfc5Valve.TurnValve(false, out _);
+            _Mfc6Valve.TurnValve(false, out _);
+            _Mfc7Valve.TurnValve(false, out _);
+            _Mfc8Valve.TurnValve(false, out _);
+
+            //foreach (var stick in _gasLines)
+            //{
+            //    stick.Stop();
+            //}
+        }
+
+        public void OpenValve(ValveType vlvType, bool on)
+        {
+            switch (vlvType)
+            {
+                case ValveType.PNV21:
+                    _PNV21Valve.TurnValve(on, out _);
+                    break;
+                case ValveType.PNV22:
+                    _PNV22Valve.TurnValve(on, out _);
+                    break;
+                case ValveType.PV11:
+                    _PV11Valve.TurnValve(on, out _);
+                    break;
+                case ValveType.PV12:
+                    _PV12Valve.TurnValve(on, out _);
+                    break;
+                case ValveType.PV21:
+                    _PV21Valve.TurnValve(on, out _);
+                    break;
+                case ValveType.PV22:
+                    _PV22Valve.TurnValve(on, out _);
+                    break;
+                case ValveType.PV31:
+                    _PV31Valve.TurnValve(on, out _);
+                    break;
+                case ValveType.PV32:
+                    _PV32Valve.TurnValve(on, out _);
+                    break;
+                case ValveType.PV41:
+                    _PV41Valve.TurnValve(on, out _);
+                    break;
+                case ValveType.PV42:
+                    _PV42Valve.TurnValve(on, out _);
+                    break;
+                case ValveType.N2:
+                    _N2Valve.TurnValve(on, out _);
+                    break;
+                case ValveType.PVHe1:
+                    _PVHe1Valve.TurnValve(on, out _);
+                    break;
+                case ValveType.PVHe2:
+                    _PVHe2Valve.TurnValve(on, out _);
+                    break;
+                case ValveType.GasFinal:
+                    _GasFinalValve.TurnValve(on, out _);
+                    break;
+                case ValveType.SoftPump:
+                    _SoftPumpValve.TurnValve(on, out _);
+                    break;
+                case ValveType.FastPump:
+                    _FastPumpValve.TurnValve(on, out _);
+                    break;
+                case ValveType.CHBPurge:
+                    _CHBPurgeValve.TurnValve(on, out _);
+                    break;
+                case ValveType.CHBVent:
+                    _CHBVentValve.TurnValve(on, out _);
+                    break;
+                case ValveType.TurboPumpPurge:
+                    _TurboPumpPurgeValve.TurnValve(on, out _);
+                    break;
+                case ValveType.Guage:
+                    _GuageValve.TurnValve(on, out _);
+                    break;
+                case ValveType.LoadlockVent:
+                    _LoadlockVentValve.TurnValve(on, out _);
+                    break;
+                case ValveType.LoadlockPumping:
+                    _LoadlockPumpingValve.TurnValve(on, out _);
+                    break;
+                case ValveType.Mfc1:
+                    _Mfc1Valve.TurnValve(on, out _);
+                    break;
+                case ValveType.Mfc2:
+                    _Mfc2Valve.TurnValve(on, out _);
+                    break;
+                case ValveType.Mfc3:
+                    _Mfc3Valve.TurnValve(on, out _);
+                    break;
+                case ValveType.Mfc4:
+                    _Mfc4Valve.TurnValve(on, out _);
+                    break;
+                case ValveType.Mfc5:
+                    _Mfc5Valve.TurnValve(on, out _);
+                    break;
+                case ValveType.Mfc6:
+                    _Mfc6Valve.TurnValve(on, out _);
+                    break;
+                case ValveType.Mfc7:
+                    _Mfc7Valve.TurnValve(on, out _);
+                    break;
+                case ValveType.Mfc8:
+                    _Mfc8Valve.TurnValve(on, out _);
+                    break;
+                default:
+                    throw new ArgumentOutOfRangeException($"Argument error {vlvType}-{on}");
+            }
+        }
+    }
+}

+ 55 - 0
Venus/Venus_RT/Modules/PMs/EventDefine.cs

@@ -0,0 +1,55 @@
+namespace Aitex.Core.RT.Event{
+	public enum EventEnum_S{
+		OperationAuthorization = 9;
+		UserLoggedOff = 10;
+		UserLoggedIn = 11;
+		AccountChanged = 12;
+		PasswordChanged = 13;
+		AccountDeleted = 14;
+		AccountCreated = 15;
+		PuttingWaferToChamberEnds = 19;
+		PuttingWaferToChamberBegins = 20;
+		PickingWaferFromChamberEnds = 21;
+		PickingWaferFromChamberBegins = 22;
+		AlignBegins = 25;
+		AlignEnds = 26;
+		AlignFailed = 27;
+		WaferMoved = 28;
+		WaferCreate = 36;
+		WaferDelete = 37;
+		LoadFOUPStart = 41;
+		LoadFOUPEnd = 42;
+		LoadFOUPFailed = 43;
+		UnloadFOUPStart = 44;
+		UnloadFOUPEnd = 45;
+		UnloadFOUPFailed = 46;
+		GeneralInfo = 1000;
+		ServiceRoutineAborted = 1023;
+		ServiceRoutineInfo = 1033;
+		GuiCmdExecSucc = 1040;
+		SwInterlock = 1052;
+		AccountWithoutAuthorization = 2052;
+		DefaultWarning = 2053;
+		GuiCmdExecFailed = 3027;
+		DbConnFailed = 3034;
+		SafePlcInterlock = 3038;
+		ValveOperationFail = 3039;
+		TransferPrepareFailed = 4050;
+		DefaultAlarm = 4093;
+		PlcHeartBeatFail = 5027;
+		TCPConnSucess = 5120;
+		CommunicationError = 5125;
+		ToleranceAlarm = 5126;
+		TCBroken = 5128;
+		HomeBegins = 5200;
+		HomeEnds = 5201;
+		HomeFailed = 5202;
+		CarrierArrived = 5203;
+		CarrierRemoved = 5204;
+		ManualOpAccess = 5205;
+		CarrierIdRead = 5206;
+		CarrierIdReadFailed = 5207;
+		SlotMapAvailable = 5208;
+		SlotMapAvailable_2 = 5308;
+	}
+}

+ 112 - 0
Venus/Venus_RT/Modules/PMs/PMRoutineBase.cs

@@ -0,0 +1,112 @@
+using System.Diagnostics;
+using Venus_RT.Devices;
+using Aitex.Core.RT.Log;
+using MECF.Framework.Common.Equipment;
+using MECF.Framework.Common.Routine;
+
+namespace Venus_RT.Modules.PMs
+{
+    class PMRoutineBase
+    {
+        public ModuleName Module { get; set; }
+        public string Name { get; set; }
+
+        protected readonly JetPM _chamber;
+
+        protected Stopwatch _timer = new Stopwatch();
+
+        protected RoutineRunner Runner = new RoutineRunner();
+
+        public PMRoutineBase(JetPM chamber)
+        {
+            Module = chamber.Module;
+            _chamber = chamber;
+            Runner.Reset();
+        }
+
+        protected void Notify(string message)
+        {
+            LOG.Write(eEvent.RoutineNotify, Module, Name, message);
+        }
+
+        protected void Stop(string failReason)
+        {
+            LOG.Write(eEvent.RoutineFailed, Module, Name, failReason);
+        }
+
+        public bool CheckLid()
+        {
+            if (!_chamber.IsLidClosed)
+            {
+                this.Stop("Chamber 盖子必须关");
+                return false;
+            }
+            return true;
+        }
+
+        public bool CheckLidLoadLock()
+        {
+            if (!_chamber.IsLidLoadlockClosed)
+            {
+                this.Stop("LoadLock 盖子必须关");
+                return false;
+            }
+            return true;
+        }
+
+        protected bool CheckSlitDoor()
+        {
+            if (!_chamber.IsSlitDoorClosed)
+            {
+                Stop("传送门必须关");
+                return false;
+            }
+            return true;
+        }
+
+        protected bool CheckDryPump()
+        {
+            if (!_chamber.IsPumpRunning)
+            {
+                Stop("泵没有启动");
+                return false;
+            }
+            if (_chamber.HasPumpError)
+            {
+                Stop("泵状态有错误");
+                return false;
+            }
+
+            return true;
+        }
+
+        protected bool CheckCDA()
+        {
+            if (!_chamber.IsCDA_OK)
+            {
+                Stop("CDA 压力信号不正确");
+                return false;
+            }
+            return true;
+        }
+
+        protected bool CloseAllValve()
+        {
+            Notify("关闭所有的阀门");
+            _chamber.CloseValves();
+            return true;
+        }
+
+        protected bool TurnValve(ValveType vlv, bool bOpen)
+        {
+            _chamber.OpenValve(vlv, bOpen);
+            Notify($"{(bOpen ? "打开" : "关闭")} {vlv} 阀");
+            return true;
+        }
+
+        protected bool CheckValve(ValveType vlv, bool bOpen)
+        {
+            return true;
+        }
+    }
+}

+ 35 - 0
Venus/Venus_RT/Modules/PMs/VentRoutine.cs

@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Aitex.Core.RT.Routine;
+
+using Venus_RT.Devices;
+
+namespace Venus_RT.Modules.PMs
+{
+    class VentRoutine : PMRoutineBase, IRoutine
+    {
+
+        public VentRoutine(JetPM chamber) : base(chamber)
+        {
+            Name = "vent";
+        }
+
+        public Result Start(params object[] objs)
+        {
+            return Result.DONE;
+        }
+        public Result Monitor()
+        {
+            return Result.DONE;
+        }
+
+        public void Abort()
+        {
+
+        }
+    }
+}

+ 321 - 0
Venus/Venus_RT/Modules/PMs/VenusRecipeFileContext.cs

@@ -0,0 +1,321 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml;
+using Aitex.Common.Util;
+using Aitex.Core.RT.Event;
+using Aitex.Core.RT.Log;
+using Aitex.Core.RT.RecipeCenter;
+using Aitex.Core.RT.SCCore;
+using Aitex.Core.Util;
+
+namespace Venus_RT.Modules.PMs
+{
+    public class VenusRecipeFileContext : IRecipeFileContext
+    {
+        public string GetRecipeDefiniton(string chamberId)
+        {
+            try
+            {
+                string recipeSchema = PathManager.GetCfgDir() + @"\RecipeFormat.xml";
+
+                XmlDocument xmlDom = new XmlDocument();
+                xmlDom.Load(recipeSchema);
+
+                bool epdInstalled = SC.ContainsItem("System.SetUp.EPDInstalled") && SC.GetValue<bool>($"System.SetUp.EPDInstalled");
+                if (!epdInstalled)
+                {
+                    var nodeEndPoint =
+                        xmlDom.SelectSingleNode(
+                                string.Format(
+                                    "/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='System.SetUp.EPDInstalled']"))
+                            as XmlElement;
+                    if (nodeEndPoint != null)
+                    {
+                        nodeEndPoint.ParentNode.RemoveChild(nodeEndPoint);
+                    }
+                }
+
+                double rfPowerRange = SC.GetValue<double>($"{chamberId}.Rf.PowerRange");
+                double rfPowerRangeBias = SC.GetValue<double>($"{chamberId}.BiasRf.PowerRange");
+                bool rfEnablePulsing = SC.GetValue<bool>($"{chamberId}.Rf.EnablePulsingFunction");
+                bool rfEnableBias = SC.GetValue<bool>($"{chamberId}.BiasRf.EnableBiasRF");
+
+                var nodeRfPowerBias = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='BiasRf.SetPower']")) as XmlElement;
+                var nodeMatchModeBias = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='BiasRf.SetMatchProcessMode']")) as XmlElement;
+                var nodeMatchC1Bias = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='BiasRf.SetMatchPositionC1']")) as XmlElement;
+                var nodeMatchC2Bias = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='BiasRf.SetMatchPositionC2']")) as XmlElement;
+                var nodeRfPower = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='Rf.SetPower']")) as XmlElement;
+                var nodeRfPowerBiasSoft = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='BiasRf.SoftTolerance']")) as XmlElement;
+                var nodeRfPowerBiasHard = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='BiasRf.HardTolerance']")) as XmlElement;
+
+                if (nodeRfPower != null)
+                {
+                    nodeRfPower.SetAttribute("Max", (int)rfPowerRange + "");
+                }
+                if (nodeRfPowerBias != null)
+                {
+                    nodeRfPowerBias.SetAttribute("Max", (int)rfPowerRangeBias + "");
+                    if (!rfEnableBias)
+                    {
+                        nodeRfPowerBias.ParentNode.RemoveChild(nodeRfPowerBias);
+                        nodeMatchModeBias.ParentNode.RemoveChild(nodeMatchModeBias);
+                        nodeMatchC1Bias.ParentNode.RemoveChild(nodeMatchC1Bias);
+                        nodeMatchC2Bias.ParentNode.RemoveChild(nodeMatchC2Bias);
+
+                        nodeRfPowerBiasSoft?.ParentNode.RemoveChild(nodeRfPowerBiasSoft);
+                        nodeRfPowerBiasHard?.ParentNode.RemoveChild(nodeRfPowerBiasHard);
+                    }
+                }
+                if (!rfEnablePulsing)
+                {
+                    var node1 = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='Rf.SetPulsingFrequency']")) as XmlElement;
+                    if (node1 != null)
+                        node1.ParentNode.RemoveChild(node1);
+
+                    var node2 = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='Rf.SetPulsingDuty']")) as XmlElement;
+                    if (node2 != null)
+                        node2.ParentNode.RemoveChild(node2);
+
+                    var node3 = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step/Item[@ControlName='PulsingMode']")) as XmlElement;
+                    if (node3 != null)
+                        node3.ParentNode.RemoveChild(node3);
+
+                }
+
+                string gas1Name = SC.GetStringValue($"{chamberId}.MfcGas1.GasName");
+                bool gas1Enable = SC.GetValue<bool>($"{chamberId}.MfcGas1.Enable");
+                int gas1N2Scale = SC.GetValue<int>($"{chamberId}.MfcGas1.MfcN2Scale");
+                double gas1ScaleFactor = SC.GetValue<double>($"{chamberId}.MfcGas1.MfcScaleFactor");
+
+                var nodeGas1 = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='MfcGas1']")) as XmlElement;
+                var nodeGas1Soft = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='MfcGas1.SoftTolerance']")) as XmlElement;
+                var nodeGas1Hard = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='MfcGas1.HardTolerance']")) as XmlElement;
+                //if (nodeGas1 != null)
+                //{
+                //    if (!gas1Enable)
+                //    {
+                //        nodeGas1.ParentNode.RemoveChild(nodeGas1);
+                //        nodeGas1Soft.ParentNode.RemoveChild(nodeGas1Soft);
+                //        nodeGas1Hard.ParentNode.RemoveChild(nodeGas1Hard);
+                //    }
+                //    else
+                //    {
+                //        nodeGas1.SetAttribute("DisplayName", gas1Name);
+                //        nodeGas1.SetAttribute("Max", (int)(gas1N2Scale * gas1ScaleFactor) + "");
+
+                //        nodeGas1Soft.SetAttribute("DisplayName", $"{gas1Name} (Soft)(%)");
+                //        nodeGas1Hard.SetAttribute("DisplayName", $"{gas1Name} (Hard)(%)");
+                //    }
+                //}
+
+                //string gas2Name = SC.GetStringValue($"{chamberId}.MfcGas2.GasName");
+                //bool gas2Enable = SC.GetValue<bool>($"{chamberId}.MfcGas2.Enable");
+                //int gas2N2Scale = SC.GetValue<int>($"{chamberId}.MfcGas2.MfcN2Scale");
+                //double gas2ScaleFactor = SC.GetValue<double>($"{chamberId}.MfcGas2.MfcScaleFactor");
+
+                //var nodeGas2 = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='MfcGas2']")) as XmlElement;
+                //var nodeGas2Soft = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='MfcGas2.SoftTolerance']")) as XmlElement;
+                //var nodeGas2Hard = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='MfcGas2.HardTolerance']")) as XmlElement;
+                //if (nodeGas2 != null)
+                //{
+                //    if (!gas2Enable)
+                //    {
+                //        nodeGas2.ParentNode.RemoveChild(nodeGas2);
+                //        nodeGas2Soft.ParentNode.RemoveChild(nodeGas2Soft);
+                //        nodeGas2Hard.ParentNode.RemoveChild(nodeGas2Hard);
+                //    }
+                //    else
+                //    {
+                //        nodeGas2.SetAttribute("DisplayName", gas2Name);
+                //        nodeGas2.SetAttribute("Max", (int)(gas2N2Scale * gas2ScaleFactor) + "");
+
+                //        nodeGas2Soft.SetAttribute("DisplayName", $"{gas2Name} (Soft)(%)");
+                //        nodeGas2Hard.SetAttribute("DisplayName", $"{gas2Name} (Hard)(%)");
+                //    }
+                //}
+
+                //string gas3Name = SC.GetStringValue($"{chamberId}.MfcGas3.GasName");
+                //bool gas3Enable = SC.GetValue<bool>($"{chamberId}.MfcGas3.Enable");
+                //int gas3N2Scale = SC.GetValue<int>($"{chamberId}.MfcGas3.MfcN2Scale");
+                //double gas3ScaleFactor = SC.GetValue<double>($"{chamberId}.MfcGas3.MfcScaleFactor");
+
+                //var nodeGas3 = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='MfcGas3']")) as XmlElement;
+                //var nodeGas3Soft = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='MfcGas3.SoftTolerance']")) as XmlElement;
+                //var nodeGas3Hard = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='MfcGas3.HardTolerance']")) as XmlElement;
+                //if (nodeGas3 != null)
+                //{
+                //    if (!gas3Enable)
+                //    {
+                //        nodeGas3.ParentNode.RemoveChild(nodeGas3);
+                //        nodeGas3Soft.ParentNode.RemoveChild(nodeGas3Soft);
+                //        nodeGas3Hard.ParentNode.RemoveChild(nodeGas3Hard);
+                //    }
+                //    else
+                //    {
+                //        nodeGas3.SetAttribute("DisplayName", gas3Name);
+                //        nodeGas3.SetAttribute("Max", (int)(gas3N2Scale * gas3ScaleFactor) + "");
+
+                //        nodeGas3Soft.SetAttribute("DisplayName", $"{gas3Name} (Soft)(%)");
+                //        nodeGas3Hard.SetAttribute("DisplayName", $"{gas3Name} (Hard)(%)");
+                //    }
+                //}
+
+
+                //string gas4Name = SC.GetStringValue($"{chamberId}.MfcGas4.GasName");
+                //bool gas4Enable = SC.GetValue<bool>($"{chamberId}.MfcGas4.Enable");
+                //int gas4N2Scale = SC.GetValue<int>($"{chamberId}.MfcGas4.MfcN2Scale");
+                //double gas4ScaleFactor = SC.GetValue<double>($"{chamberId}.MfcGas4.MfcScaleFactor");
+
+                //var nodeGas4 = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='MfcGas4']")) as XmlElement;
+                //var nodeGas4Soft = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='MfcGas4.SoftTolerance']")) as XmlElement;
+                //var nodeGas4Hard = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='MfcGas4.HardTolerance']")) as XmlElement;
+                //if (nodeGas4 != null)
+                //{
+                //    if (!gas4Enable)
+                //    {
+                //        nodeGas4.ParentNode.RemoveChild(nodeGas4);
+                //        nodeGas4Soft.ParentNode.RemoveChild(nodeGas4Soft);
+                //        nodeGas4Hard.ParentNode.RemoveChild(nodeGas4Hard);
+                //    }
+                //    else
+                //    {
+                //        nodeGas4.SetAttribute("DisplayName", gas4Name);
+                //        nodeGas4.SetAttribute("Max", (int)(gas4N2Scale * gas4ScaleFactor) + "");
+
+                //        nodeGas4Soft.SetAttribute("DisplayName", $"{gas4Name} (Soft)(%)");
+                //        nodeGas4Hard.SetAttribute("DisplayName", $"{gas4Name} (Hard)(%)");
+                //    }
+                //}
+
+                //string gas5Name = SC.GetStringValue($"{chamberId}.MfcGas5.GasName");
+                //bool gas5Enable = SC.GetValue<bool>($"{chamberId}.MfcGas5.Enable");
+                //int gas5N2Scale = SC.GetValue<int>($"{chamberId}.MfcGas5.MfcN2Scale");
+                //double gas5ScaleFactor = SC.GetValue<double>($"{chamberId}.MfcGas5.MfcScaleFactor");
+
+                //var nodeGas5 = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='MfcGas5']")) as XmlElement;
+                //var nodeGas5Soft = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='MfcGas5.SoftTolerance']")) as XmlElement;
+                //var nodeGas5Hard = xmlDom.SelectSingleNode(string.Format("/Aitex/TableRecipeFormat/Catalog/Group/Step[@ControlName='MfcGas5.HardTolerance']")) as XmlElement;
+                //if (nodeGas5 != null)
+                //{
+                //    if (!gas5Enable)
+                //    {
+                //        nodeGas5.ParentNode.RemoveChild(nodeGas5);
+                //        nodeGas5Soft.ParentNode.RemoveChild(nodeGas5Soft);
+                //        nodeGas5Hard.ParentNode.RemoveChild(nodeGas5Hard);
+                //    }
+                //    else
+                //    {
+                //        nodeGas5.SetAttribute("DisplayName", gas5Name);
+                //        nodeGas5.SetAttribute("Max", (int)(gas5N2Scale * gas5ScaleFactor) + "");
+
+                //        nodeGas5Soft.SetAttribute("DisplayName", $"{gas5Name} (Soft)(%)");
+                //        nodeGas5Hard.SetAttribute("DisplayName", $"{gas5Name} (Hard)(%)");
+                //    }
+                //}
+                //xmlDom.Save(recipeSchema);
+                return xmlDom.OuterXml;
+            }
+            catch (Exception ex)
+            {
+                //LOG.Write(ex);
+                return "";
+            }
+        }
+
+        public IEnumerable<string> GetRecipes(string chamberId, bool includingUsedRecipe)
+        {
+            try
+            {
+                string recipePath = PathManager.GetRecipeDir() + chamberId + "\\";
+                var di = new DirectoryInfo(recipePath);
+                var fis = di.GetFiles("*.rcp", SearchOption.AllDirectories);
+                var recipes = new List<string>();
+
+                foreach (var fi in fis)
+                {
+                    string str = fi.FullName.Substring(recipePath.Length);
+                    str = str.Substring(0, str.LastIndexOf('.'));
+                    if (includingUsedRecipe || (!includingUsedRecipe && !str.Contains("HistoryRecipe\\")))
+                    {
+                        recipes.Add(str);
+                    }
+                }
+                return recipes;
+            }
+            catch (Exception ex)
+            {
+                //LOG.Write(ex);
+                return new List<string>();
+            }
+        }
+
+        public void PostInfoEvent(string message)
+        {
+            EV.PostMessage("System", EventEnum.GeneralInfo, message);
+        }
+
+        public void PostWarningEvent(string message)
+        {
+            EV.PostMessage("System", EventEnum.DefaultWarning, message);
+        }
+
+        public void PostAlarmEvent(string message)
+        {
+            EV.PostMessage("System", EventEnum.DefaultAlarm, message);
+        }
+
+        public void PostDialogEvent(string message)
+        {
+            EV.PostNotificationMessage(message);
+        }
+
+        public void PostInfoDialogMessage(string message)
+        {
+            EV.PostMessage("System", EventEnum.GeneralInfo, message);
+
+            EV.PostPopDialogMessage(EventLevel.Information, "System Information", message);
+        }
+
+        public void PostWarningDialogMessage(string message)
+        {
+            EV.PostMessage("System", EventEnum.GeneralInfo, message);
+
+            EV.PostPopDialogMessage(EventLevel.Warning, "System Warning", message);
+        }
+
+        public void PostAlarmDialogMessage(string message)
+        {
+            EV.PostMessage("System", EventEnum.GeneralInfo, message);
+
+            EV.PostPopDialogMessage(EventLevel.Alarm, "System Alarm", message);
+        }
+
+        public string GetRecipeTemplate(string chamberId)
+        {
+            string schema = GetRecipeDefiniton(chamberId);
+
+            XmlDocument dom = new XmlDocument();
+
+            dom.LoadXml(schema);
+
+            XmlNode nodeTemplate = dom.SelectSingleNode("/Aitex/TableRecipeData");
+
+
+            return nodeTemplate.OuterXml;
+        }
+
+        public bool EnableEdit(string recipeName)
+        {
+            //if (Singleton<RouteManager>.Instance.CheckRecipeUsedInJob(recipeName))
+            //{
+            //    EV.PostWarningLog("System", "Recipe is used in auto running jobs, can not be modified");
+            //    return false;
+            //}
+            return true;
+        }
+    }
+}

+ 78 - 0
Venus/Venus_RT/Modules/PMs/VenusSequenceFileContext.cs

@@ -0,0 +1,78 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml;
+using Aitex.Common.Util;
+using Aitex.Core.RT.Event;
+using Aitex.Core.RT.Log;
+using Aitex.Core.Util;
+using MECF.Framework.Common.RecipeCenter;
+
+namespace Venus_RT.Modules.PMs
+{
+    public class VenusSequenceFileContext : ISequenceFileContext
+    {
+        public string GetConfigXml()
+        {
+            try
+            {
+                string configContent = PathManager.GetCfgDir() + @"\SequenceFormat.xml";
+
+                XmlDocument xmlDom = new XmlDocument();
+                xmlDom.Load(configContent);
+
+                CustomSequenceItem(xmlDom);
+
+                return xmlDom.OuterXml;
+            }
+            catch (Exception ex)
+            {
+                //LOG.Write(ex);
+                return "";
+            }
+
+        }
+
+        public virtual bool Validation(string content)
+        {
+            try
+            {
+
+                XmlDocument xmlDom = new XmlDocument();
+                xmlDom.LoadXml(content);
+
+                CustomValidation(xmlDom);
+
+                return CustomValidation(xmlDom);
+            }
+            catch (Exception ex)
+            {
+                //LOG.Write(ex);
+                EV.PostWarningLog("Recipe", "sequence file not valid, " + ex.Message);
+                return false;
+            }
+        }
+
+        public bool EnableEdit(string sequencePathName)
+        {
+            //if (Singleton<RouteManager>.Instance.CheckSequenceUsedInJob(sequencePathName))
+            //{
+            //    EV.PostWarningLog("System", "Sequence is used in auto running jobs, can not be modified");
+            //    return false;
+            //}
+            return true;
+        }
+
+        public virtual void CustomSequenceItem(XmlDocument xmlContent)
+        {
+
+        }
+
+        public virtual bool CustomValidation(XmlDocument xmlContent)
+        {
+            return true;
+        }
+    }
+}

BIN
Venus/Venus_RT/Resources/default_rt.ico


BIN
Venus/Venus_RT/Resources/defaultrt.ico