using Aitex.Core.RT.Device.Devices; using Aitex.Core.RT.Device; using Aitex.Core.RT.Event; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using MECF.Framework.Common.Equipment; using SicModules.PMs.Routines.Base; using System; using System.Collections.Generic; using System.Diagnostics; using Aitex.Core.RT.DBCore; using Aitex.Core.Common.DeviceData; using Aitex.Common.Util; using Aitex.Core.RT.Log; using System.Xml; using System.Collections.ObjectModel; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts.TDK; using Aitex.Core.RT.OperationCenter; using Aitex.Core.UI.Control; using System.Xml.Linq; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.MFCs; using MECF.Framework.Common.Device.Bases; using MECF.Framework.Common.DBCore; using System.Data; using System.Reflection; using System.Linq; using MECF.Framework.Common.Aitex.Core.Common.DeviceData.IoDevice; using Newtonsoft.Json; using Aitex.Core.RT.DataCenter; namespace SicModules.PMs.Routines { public class MfcRorAction { public string Name { get; set; } public string Value { get; set; } } public class PMMfcRorRoutine : PMBaseRoutine { private enum RoutineStep { TimeDelay1, TimeDelay2, TimeDelay3, TimeDelay4, TimeDelay5, TimeDelay6, TimeDelay7, TimeDelay8, TimeDelay9, TimeDelay10, SetEPV2_1, SetEPV2_2, SetEPV2_3, SetTVEnable_1, SetTVEnable_2, SetTVPressMode_1, SetTVPressMode_2, SetTV_1, SetTV_2, WaitTV_1, WaitTV_2, SetM2toM40, SetTVCloseMode_1, SetTVCloseMode_2, CloseTV_1, CloseTV_2, PreSetMfcFlow, SetMfcFlow_1, SetMfcFlow_2, SetMfcFlow_3, PostSetMfcFlow, SetPressure1, SetPressure2, SetPressure3, SetPressure4, SetMaintainPressure1, SetMaintainPressure2, CalStandardMfc, CalTestMfc, CalBasePressure1, CalBasePressure2, } private ModuleName moduleName; private PMModule _pmModule; private MfcRorData _mfcData; private Stopwatch _swTimer = new Stopwatch(); //Mfc Name列表 public List MfcNameList { get; set; } = new List(); //标准Mfc public MfcRorData StandardMfcRorData { get; set; } public List MfcRorList { get; set; } = new List(); //摩尔气体常数 private const double R = 8.314; //气体摩尔体积 private const double Vm = 22.414; private IoThrottleValve2 _IoThrottle; private int _IoValueTimeout = 10; private double _pressureMaxDiff; private int _throttleTimeout; private double _ventBasePressure; private double _pumpBasePressure; private bool _flag1; private bool _flag2; private string _startTime; private string _endTime; private string _mfcRorConfigPath = PathManager.GetCfgDir() + @"PM\MfcRor\MfcRor.xml"; private Dictionary> _preActionList = new Dictionary>(); private Dictionary> _postActionList = new Dictionary>(); public PMMfcRorRoutine(ModuleName module, PMModule pm) : base(module, pm) { moduleName = module; _pmModule = pm; Name = "MfcRor"; _IoThrottle = DEVICE.GetDevice($"{Module}.TV"); InitializeXml(); InitializeMfcRorList(); InitStandardMfc(); } private void InitializeXml() { string reason = string.Empty; try { XmlDocument xmlDocument = new XmlDocument(); xmlDocument.Load(_mfcRorConfigPath); XmlNode xmlNode = xmlDocument.SelectSingleNode("Items"); foreach (XmlNode childNode in xmlNode.ChildNodes) { if (childNode.NodeType == XmlNodeType.Comment || !(childNode is XmlElement xmlElement)) { continue; } if (xmlElement.Name != "Item") { if (xmlElement.NodeType != XmlNodeType.Comment) { reason += "mfcRor config file contains no comments content, " + xmlElement.InnerXml; } continue; } if (!xmlElement.HasAttribute("Name")) { reason += "action node has no [Name] attribute \r\n"; continue; } string name = xmlElement.GetAttribute("Name"); //PreAction List preActionList = new List(); XmlNode xmlNode1 = childNode.SelectSingleNode("PreAction"); foreach (XmlElement childNode1 in xmlNode1.ChildNodes) { if (childNode1.Name != "Action") { if (childNode1.NodeType != XmlNodeType.Comment) { LOG.Error("MfcRor config file contains no comments content, " + childNode1.InnerXml); } continue; } if (!childNode1.HasAttribute("Name") || !childNode1.HasAttribute("Value")) { reason += "MfcRor node lack of Name or Value attribute \r\n"; continue; } string actionName = childNode1.GetAttribute("Name"); string value = childNode1.GetAttribute("Value"); preActionList.Add(new MfcRorAction() { Name = actionName, Value = value }); } _preActionList[name] = preActionList; //PostAction List postActionList = new List(); XmlNode xmlNode2 = childNode.SelectSingleNode("PostAction"); foreach (XmlElement childNode2 in xmlNode2.ChildNodes) { if (childNode2.Name != "Action") { if (childNode2.NodeType != XmlNodeType.Comment) { LOG.Error("MfcRor config file contains no comments content, " + childNode2.InnerXml); } continue; } if (!childNode2.HasAttribute("Name") || !childNode2.HasAttribute("Value")) { reason += "MfcRor node lack of Name or Value attribute \r\n"; continue; } string actionName = childNode2.GetAttribute("Name"); string value = childNode2.GetAttribute("Value"); postActionList.Add(new MfcRorAction() { Name = actionName, Value = value }); } _postActionList[name] = postActionList; } } catch (Exception ex) { LOG.Error(ex.Message, ex); } } private void InitializeMfcRorList() { //初始化所有MFC foreach (var item in _preActionList) { MfcNameList.Add(item.Key); MfcRorList.Add( new MfcRorData() { Name= item.Key}); } QueryMfcRorListData(); } private void QueryMfcRorListData() { try { string cmd = $"select * from pm_mfcror where module = '{Module}' order by \"endtime\" ASC"; var dt = DB.ExecuteDataset(cmd); if (dt is null || dt.Tables[0].Rows.Count == 0) return; for (int i = 0; i < dt.Tables[0].Rows.Count; i++) { if (dt.Tables[0].Rows[i].ItemArray.Length != 0) { //if(bool.Parse(dt.Tables[0].Rows[i]["isstandardMfc"].ToString())) //{ // continue; //} MfcRorList.ForEach(t => { if (t.Name == dt.Tables[0].Rows[i]["name"].ToString()) { t.StartTime = Convert.ToDateTime(dt.Tables[0].Rows[i]["starttime"].ToString()); t.EndTime = Convert.ToDateTime(dt.Tables[0].Rows[i]["endtime"].ToString()); t.Module = dt.Tables[0].Rows[i]["module"].ToString(); t.Pressure1 = double.Parse(dt.Tables[0].Rows[i]["pressure1"].ToString()); t.Pressure2 = double.Parse(dt.Tables[0].Rows[i]["pressure2"].ToString()); t.Pressure3 = double.Parse(dt.Tables[0].Rows[i]["pressure3"].ToString()); t.Pressure4 = double.Parse(dt.Tables[0].Rows[i]["pressure4"].ToString()); t.ActualFlow = double.Parse(dt.Tables[0].Rows[i]["actualflow"].ToString()); t.SetFlow = double.Parse(dt.Tables[0].Rows[i]["setflow"].ToString()); t.Temperature = double.Parse(dt.Tables[0].Rows[i]["temperature"].ToString()); t.Interval = double.Parse(dt.Tables[0].Rows[i]["interval"].ToString()); t.IsStandardMfc = bool.Parse(dt.Tables[0].Rows[i]["isstandardMfc"].ToString()); t.MaintainPressure1 = double.Parse(dt.Tables[0].Rows[i]["maintainpressure1"].ToString()); t.MaintainPressure2 = double.Parse(dt.Tables[0].Rows[i]["maintainpressure2"].ToString()); t.MaintainPressureDifference = double.Parse(dt.Tables[0].Rows[i]["maintainpressuredifference"].ToString()); t.Volume = double.Parse(dt.Tables[0].Rows[i]["volume"].ToString()); t.MeanDifferencePressure = double.Parse(dt.Tables[0].Rows[i]["meandifferencepressure"].ToString()); t.BasePressure = double.Parse(dt.Tables[0].Rows[i]["basepressure"].ToString()); t.Deviation = double.Parse(dt.Tables[0].Rows[i]["deviation"].ToString()); t.Result = dt.Tables[0].Rows[i]["result"].ToString(); } }); } } } catch (Exception ex) { LOG.Error(ex.Message, ex); } } public void InitStandardMfc() { try { string sql = $"select * from \"pm_mfcror\" where \"module\" = '{Module}' and \"isstandardmfc\" = 't' order by \"endtime\" DESC"; DataTable dbData = DataQuery.Query(sql); if (dbData != null) { StandardMfcRorData = TableToListModel(dbData).FirstOrDefault(); } } catch (Exception ex) { LOG.Error(ex.Message, ex); } } public void ClearMfcRorData() { MfcRorList.Clear(); foreach (var item in _preActionList) { MfcRorList.Add(new MfcRorData() { Name = item.Key }); } //DB.ExcuteTransAction(new List { $"delete from pm_mfcror where \"module\" = '{Module}'" }); } public List TableToListModel(DataTable dt) where T : new() { // 定义集合 List ts = new List(); // 获得此模型的类型 Type type = typeof(T); string tempName = ""; foreach (DataRow dr in dt.Rows) { T t = new T(); // 获得此模型的公共属性 PropertyInfo[] propertys = t.GetType().GetProperties(); foreach (PropertyInfo pi in propertys) { tempName = pi.Name; // 检查DataTable是否包含此列 if (dt.Columns.Contains(tempName)) { // 判断此属性是否有Setter if (!pi.CanWrite) continue; object value = dr[tempName]; if (value != DBNull.Value) pi.SetValue(t, value, null); } } ts.Add(t); } return ts; } public override Result Start(params object[] objs) { Reset(); _mfcData = JsonConvert.DeserializeObject(objs[0].ToString()); _pressureMaxDiff = SC.GetValue($"PM.{Module}.ThrottlePressureMaxDiff"); _throttleTimeout = SC.GetValue($"PM.{Module}.ThrottlePressureTimeout"); _flag1 = _pmModule.GetChamberPressure() > _mfcData.BasePressure; _startTime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.fff"); _swTimer.Restart(); Notify($"Start {_mfcData.Name} ROR"); return Result.RUN; } public override Result Monitor() { try { //检查是否退出 if (_pmModule.GetChamberPressure() > 980) { //设置对应的MFC流量为0 SetMfcFlow((int)RoutineStep.SetMfcFlow_3, _mfcData.Name, 0, 3); TimeDelay((int)RoutineStep.TimeDelay10, 3); EV.PostWarningLog(Module, "Chamber Pressure above 980mbar,Mfc Ror Routine Abort!"); throw (new RoutineFaildException()); } if (_flag1) { //打开EPV2 SetIoValueByGroup((int)RoutineStep.SetEPV2_1, IoGroupName.EPV2, true, _IoValueTimeout); //设置蝶阀Enable SetThrottleEnableAndWait((int)RoutineStep.SetTVEnable_1, _IoThrottle, 5); //设置蝶阀为压力模式 SetThrottleToPressModeAndWait((int)RoutineStep.SetTVPressMode_1, _IoThrottle, 5); //伺服压力设定值到0mbar SetThrottlePressureAndWaitSetPoint((int)RoutineStep.SetTV_1, _IoThrottle, _pumpBasePressure, _pressureMaxDiff, _throttleTimeout); //等待腔体压力Pump到设定值 WaitChamberPressDownTo((int)RoutineStep.WaitTV_1, _pumpBasePressure, _pressureMaxDiff, _throttleTimeout); } //关闭蝶阀,再关闭EPV2 SetThrottleToCloseMode((int)RoutineStep.SetTVCloseMode_1, _IoThrottle, 8); SetThrottleDisable((int)RoutineStep.CloseTV_1, _IoThrottle, 8); TimeDelay((int)RoutineStep.TimeDelay1, 1); SetIoValueByGroup((int)RoutineStep.SetEPV2_2, IoGroupName.EPV2, false, _IoValueTimeout); TimeDelay((int)RoutineStep.TimeDelay2, 3); if (_mfcData.IsStandardMfc) { //记录第一次保压值 TimeDelay((int)RoutineStep.TimeDelay3, _mfcData.Interval); SetRorMaintainPressure((int)RoutineStep.SetMaintainPressure1, 1); //记录第二次保压值 TimeDelay((int)RoutineStep.TimeDelay4, _mfcData.Interval); SetRorMaintainPressure((int)RoutineStep.SetMaintainPressure2, 2); } //设定MFC流量前执行动作 PreSetMfcFlow((int)RoutineStep.PreSetMfcFlow); //设定MFC流量 SetMfcFlow((int)RoutineStep.SetMfcFlow_1, _mfcData.Name, _mfcData.SetFlow, 3); TimeDelay((int)RoutineStep.TimeDelay5, 3); //记录第一次压力值 TimeDelay((int)RoutineStep.TimeDelay6, _mfcData.Interval); SetRorPressure((int)RoutineStep.SetPressure1, 1); //记录第二次压力值 TimeDelay((int)RoutineStep.TimeDelay7, _mfcData.Interval); SetRorPressure((int)RoutineStep.SetPressure2, 2); //记录第三次压力值 TimeDelay((int)RoutineStep.TimeDelay8, _mfcData.Interval); SetRorPressure((int)RoutineStep.SetPressure3, 3); //记录第四次压力值 TimeDelay((int)RoutineStep.TimeDelay9, _mfcData.Interval); SetRorPressure((int)RoutineStep.SetPressure4, 4); //设定MFC流量后执行动作 PostSetMfcFlow((int)RoutineStep.PostSetMfcFlow); CalBasePressure((int)RoutineStep.CalBasePressure2); if (_flag2) { //打开EPV2 SetIoValueByGroup((int)RoutineStep.SetEPV2_3, IoGroupName.EPV2, true, _IoValueTimeout); //设置蝶阀Enable SetThrottleEnableAndWait((int)RoutineStep.SetTVEnable_2, _IoThrottle, 5); //设置蝶阀为压力模式 SetThrottleToPressModeAndWait((int)RoutineStep.SetTVPressMode_2, _IoThrottle, 5); //伺服压力设定值到0mbar SetThrottlePressureAndWaitSetPoint((int)RoutineStep.SetTV_2, _IoThrottle, _pumpBasePressure, _pressureMaxDiff, _throttleTimeout); //等待腔体压力Pump到设定值 WaitChamberPressDownTo((int)RoutineStep.WaitTV_2, _pumpBasePressure, _pressureMaxDiff, _throttleTimeout); } //计算 if(_mfcData.IsStandardMfc) { CalStandardMfc((int)RoutineStep.CalStandardMfc); } else { CalTestMfc((int)RoutineStep.CalTestMfc); } } catch (RoutineBreakException) { return Result.RUN; } catch (RoutineFaildException) { return Result.FAIL; } _swTimer.Stop(); return Result.DONE; } //设定保压压力 private void SetRorMaintainPressure(int id, int index) { Tuple ret = Execute(id, () => { switch (index) { case 1: { _mfcData.MaintainPressure1 = _pmModule.GetChamberPressure(); } break; case 2: { _mfcData.MaintainPressure2 = _pmModule.GetChamberPressure(); _mfcData.MaintainPressureDifference = _mfcData.MaintainPressure2 - _mfcData.MaintainPressure1; _mfcData.MaintainPressureDifference = Math.Round(_mfcData.MaintainPressureDifference, 2); } break; } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } //设定压力 private void SetRorPressure(int id, int index) { Tuple ret = Execute(id, () => { switch (index) { case 1: { _mfcData.Pressure1 = _pmModule.GetChamberPressure(); } break; case 2: { _mfcData.Pressure2 = _pmModule.GetChamberPressure(); } break; case 3: { _mfcData.Pressure3 = _pmModule.GetChamberPressure(); } break; case 4: { _mfcData.Pressure4 = _pmModule.GetChamberPressure(); _mfcData.MeanDifferencePressure = (_mfcData.Pressure4 - _mfcData.Pressure1) / 3.0; _mfcData.MeanDifferencePressure = Math.Round(_mfcData.MeanDifferencePressure, 2); } break; } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void PreSetMfcFlow(int id) { Tuple ret = Execute(id, () => { if (!_preActionList.ContainsKey(_mfcData.Name)) { return false; } foreach (MfcRorAction action in _preActionList[_mfcData.Name]) { if (action.Name.Contains("Mfc")) { SetMfc(action.Name, action.Value); } else if (action.Name.Contains("V")) { SetValve(action.Name, action.Value); } else if (action.Name.Contains("PC")) { SetPC(action.Name, action.Value); } } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } protected void PostSetMfcFlow(int id) { Tuple ret = Execute(id, () => { if (!_postActionList.ContainsKey(_mfcData.Name)) { return false; } foreach (MfcRorAction action in _postActionList[_mfcData.Name]) { if (action.Name.Contains("Mfc")) { SetMfc(action.Name, action.Value); } else if (action.Name.Contains("V")) { SetValve(action.Name, action.Value); } else if (action.Name.Contains("PC")) { SetPC(action.Name, action.Value); } } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } private bool SetValve(string valveName, string value) { IoValve valve = DEVICE.GetDevice($"{Module}.{valveName}"); if (valve == null) { EV.PostAlarmLog(Module, $"{valveName} is null"); return false; } bool isOpen = value == "Open"; if (valve.TurnValve(isOpen, out string reason)) { EV.PostInfoLog(Module, $"{valveName} Set {value} Succeed , {reason}"); return true; } else { EV.PostAlarmLog(Module, $"{valveName} Set {value} Failed"); return false; } } private bool SetPC(string pcName, string value) { IoPressure pc = DEVICE.GetDevice($"{Module}.{pcName}"); if (pc == null) { EV.PostAlarmLog(Module, $"{pcName} is null"); return false; } string reason; if (value == "Open") { if(pc.SetPcMode(PcCtrlMode.Open, out reason)) { EV.PostInfoLog(Module, $"{pcName} Set {value} Succeed"); return true; } } else if (value == "Close") { if (pc.SetPcMode(PcCtrlMode.Close, out reason)) { EV.PostInfoLog(Module, $"{pcName} Set {value} Succeed"); return true; } } else if (value == "Default") { pc.Ramp(pc.DefaultValue, 3000); EV.PostInfoLog(Module, $"{pcName} Set {value} Succeed"); return true; } EV.PostAlarmLog(Module, $"{pcName} Set {value} Failed"); return false; } private bool SetMfc(string mfcName, string value) { IoMFC mfc = DEVICE.GetDevice($"{Module}.{mfcName}"); if (mfc == null) { EV.PostAlarmLog(Module, $"{mfcName} is null"); return false; } string reason; if (value == "Open") { if(mfc.SetMfcMode(MfcCtrlMode.Open, out reason)) { EV.PostInfoLog(Module, $"{mfcName} Set {value} Succeed"); return true; } } else if (value == "Close") { if (mfc.SetMfcMode(MfcCtrlMode.Close, out reason)) { EV.PostInfoLog(Module, $"{mfcName} Set {value} Succeed"); return true; } } else if (value == "Default") { mfc.SetToDefaultByRamp(3000); return true; } else { if(double.TryParse(value,out double dValue)) { mfc.Ramp(dValue,3000,out reason); return true; } } EV.PostAlarmLog(Module, $"{mfcName} Set {value} Failed"); return false; } private void CalBasePressure(int id) { Tuple ret = Execute(id, () => { _flag2 = _pmModule.GetChamberPressure() > _mfcData.BasePressure; return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } //计算标准MFC,求得反应腔压力 private void CalStandardMfc(int id) { Tuple ret = Execute(id, () => { if (_mfcData.MeanDifferencePressure - _mfcData.MaintainPressureDifference > 0) { _mfcData.Volume = 1000000 * (_mfcData.SetFlow * 0.001 / Vm * R * _mfcData.Temperature) / ((_mfcData.MeanDifferencePressure - _mfcData.MaintainPressureDifference) / (_mfcData.Interval / 60.0) / 0.01); //保留2位小数 _mfcData.Volume = Math.Round(_mfcData.Volume, 2); _mfcData.Result = "OK"; _endTime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"); //数据保存至数据库 string sql = string.Format($"insert into \"pm_mfcror\"(\"starttime\",\"endtime\",\"name\",\"module\",\"scale\",\"pressure1\",\"pressure2\",\"pressure3\",\"pressure4\",\"actualflow\",\"setflow\",\"temperature\",\"interval\",\"isstandardmfc\",\"maintainpressure1\",\"maintainpressure2\",\"maintainpressuredifference\",\"volume\",\"meandifferencepressure\",\"basepressure\",\"deviation\",\"result\") values('{_startTime}','{_endTime}','{_mfcData.Name}','{_mfcData.Module}','{_mfcData.Scale}','{_mfcData.Pressure1}','{_mfcData.Pressure2}','{_mfcData.Pressure3}','{_mfcData.Pressure4}','{_mfcData.ActualFlow}','{_mfcData.SetFlow}','{_mfcData.Temperature}','{_mfcData.Interval}','{_mfcData.IsStandardMfc}','{_mfcData.MaintainPressure1}','{_mfcData.MaintainPressure2}','{_mfcData.MaintainPressureDifference}','{_mfcData.Volume}','{_mfcData.MeanDifferencePressure}','{_mfcData.BasePressure}','{_mfcData.Deviation}','{_mfcData.Result}')"); List cmdList = new List() { sql }; if(DB.ExcuteTransAction(cmdList)) { //设置基准MFC StandardMfcRorData = _mfcData; MfcRorList.ForEach(mfc => { if (mfc.Name == _mfcData.Name) { mfc.Update(_mfcData); } }); Notify($"{_mfcData.Name} ROR Finished! Chamber Volume is {_mfcData.Volume};Elapsed time: {(int)(_swTimer.ElapsedMilliseconds / 1000)} s"); } else { EV.PostWarningLog(Module, $"{_mfcData.Name} ROR Failed! Elapsed time: {(int)(_swTimer.ElapsedMilliseconds / 1000)} s"); } } else { EV.PostWarningLog(Module, $"{_mfcData.Name} ROR Failed! MeanDifferencePressure Less Than MaintainPressureDifference !Elapsed time: {(int)(_swTimer.ElapsedMilliseconds / 1000)} s"); } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } //计算测试MFC,求得实际流量 private void CalTestMfc(int id) { Tuple ret = Execute(id, () => { if (_mfcData.SetFlow != 0) { _mfcData.ActualFlow = ((_mfcData.MeanDifferencePressure - _mfcData.MaintainPressureDifference) / (0.01 * (_mfcData.Interval / 60.0))) * (_mfcData.Volume / 1000000.0 / (R * _mfcData.Temperature)) * Vm * 1000; _mfcData.Deviation = (_mfcData.ActualFlow / _mfcData.SetFlow - 1) * 100; //保留2位小数 _mfcData.Deviation = Math.Round(_mfcData.Deviation, 2); _mfcData.Volume = Math.Round(_mfcData.Volume, 2); //大于3%的MFC为超标 _mfcData.Result = Math.Abs(_mfcData.Deviation) <= 3 ? "OK" : "NG"; _endTime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"); //数据保存至数据库 string sql = string.Format($"insert into \"pm_mfcror\"(\"starttime\",\"endtime\",\"name\",\"module\",\"scale\",\"pressure1\",\"pressure2\",\"pressure3\",\"pressure4\",\"actualflow\",\"setflow\",\"temperature\",\"interval\",\"isstandardmfc\",\"maintainpressure1\",\"maintainpressure2\",\"maintainpressuredifference\",\"volume\",\"meandifferencepressure\",\"basepressure\",\"deviation\",\"result\") values('{_startTime}','{_endTime}','{_mfcData.Name}','{_mfcData.Module}','{_mfcData.Scale}','{_mfcData.Pressure1}','{_mfcData.Pressure2}','{_mfcData.Pressure3}','{_mfcData.Pressure4}','{_mfcData.ActualFlow}','{_mfcData.SetFlow}','{_mfcData.Temperature}','{_mfcData.Interval}','{_mfcData.IsStandardMfc}','{_mfcData.MaintainPressure1}','{_mfcData.MaintainPressure2}','{_mfcData.MaintainPressureDifference}','{_mfcData.Volume}','{_mfcData.MeanDifferencePressure}','{_mfcData.BasePressure}','{_mfcData.Deviation}','{_mfcData.Result}')"); List cmdList = new List() { sql }; if (DB.ExcuteTransAction(cmdList)) { MfcRorList.ForEach(mfc => { if (mfc.Name == _mfcData.Name) { mfc.Update(_mfcData); } }); Notify($"{_mfcData.Name} ROR Finished! {_mfcData.Name} Deviation is {_mfcData.Deviation}%;Elapsed time: {(int)(_swTimer.ElapsedMilliseconds / 1000)} s"); } else { EV.PostWarningLog(Module, $"{_mfcData.Name} ROR Failed! Elapsed time: {(int)(_swTimer.ElapsedMilliseconds / 1000)} s"); } } else { EV.PostWarningLog(Module, $"{_mfcData.Name} ROR Failed! Elapsed time: {(int)(_swTimer.ElapsedMilliseconds / 1000)} s"); } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } public override void Abort() { base.Abort(); } //private void CheckRoutineTimeOut() //{ // if (_routineTimeOut > 10) // { // if ((int)(_swTimer.ElapsedMilliseconds / 1000) > _routineTimeOut) // { // EV.PostAlarmLog(Module,$"Routine TimeOut! over {_routineTimeOut} s"); // throw (new RoutineFaildException()); // } // } //} } }