using Aitex.Common.Util; using Aitex.Core.Common.DeviceData; using Aitex.Core.RT.DBCore; 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.Aitex.Core.Common.DeviceData.IoDevice; using MECF.Framework.Common.Equipment; using SicModules.PMs.Routines.Base; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Xml; using Aitex.Core.RT.Log; using Newtonsoft.Json; using System.Collections.ObjectModel; namespace SicModules.PMs.Routines { public delegate bool ConditionMethodDelegate(string name, double value, out string reason); public class PMMfcValueTestRoutine : PMBaseRoutine { enum RoutineStep { OpenOrClose, OpenMfc, TimeDelay, Inspect, CloseMfc, ResetState, WriteDatabase } /// /// XML配置中Mfc名称 /// public List MfcNameList = new List(); /// /// XML配置中气阀名称 /// public List ValueNameList = new List(); /// /// XML配置中PC名称 /// public List PCNameList = new List(); /// /// MFC所有测试数据 /// public List MfcTestList { get; set; } = new List(); /// /// 气阀所有测试数据 /// public List ValueTestList { get; set; } = new List(); /// /// PC所有测试数据 /// public List PCTestList { get; set; } = new List(); /// /// 单个MFC测试数据 /// public MfcTestData MfcTest = new MfcTestData(); /// /// 输入项数据,重要用来存储数据库操作对象,保存输入条件中,所有气阀/PC/MFC测试结果 /// public List AllControlNameDataList { get; set; } = new List(); private ControlNameData ControlNameData = new ControlNameData(); private List mfcDoTestList = new List(); private MfcTestCondition mfcDoTest = new MfcTestCondition(); ConditionMethodDelegate MethodDelegate; private string MfcName; private double _timeDelay; private double _scValue; private double _mfcDefaultValue; private double _upperLimit; private Stopwatch _swTimer = new Stopwatch(); private string _startTime; private string _endTime; private string _mfcValueConfigPath = PathManager.GetCfgDir() + @"PM\MfcDeviationValue\MfcTest.xml"; private string _controlUnitConfigPath = PathManager.GetCfgDir() + @"PM\MfcDeviationValue\ControlUnit.xml"; public PMMfcValueTestRoutine(ModuleName module, PMModule pm) : base(module, pm) { Name = "MfcValueTest"; MethodDelegate += SetValve; MethodDelegate += SetPC; MethodDelegate += SetMfcState; InitializeMfc(); InitializeValue(); InitializeDataList(); } private void InitializeMfc() { string reason = string.Empty; try { XmlDocument xml = new XmlDocument();//初始化一个xml实例 xml.Load(_mfcValueConfigPath); XmlElement root = xml.DocumentElement; XmlNodeList nodelist = root.ChildNodes; //遍历输出. foreach (XmlNode node in nodelist) { MfcTestCondition mfcDoTest = new MfcTestCondition(); var nodeBlocks = node.SelectNodes("Condition/Names/Name"); if (nodeBlocks != null) { foreach (var nodeBlock in nodeBlocks) { if (!(nodeBlock is XmlElement xmlBlock)) { continue; } mfcDoTest.Name = xmlBlock.GetAttribute("Name"); } } nodeBlocks = node.SelectNodes("Condition/Inputs/Input"); if (nodeBlocks != null) { foreach (var nodeBlock in nodeBlocks) { if (!(nodeBlock is XmlElement xmlBlock)) { continue; } NameValue keyValue = new NameValue() { Name = xmlBlock.GetAttribute("Name"), Value = Convert.ToDouble(xmlBlock.GetAttribute("Value")), ControlName = xmlBlock.GetAttribute("ControlName") }; mfcDoTest.StateList.Add(keyValue); } } nodeBlocks = node.SelectNodes("Condition/Outputs/Output"); if (nodeBlocks != null) { foreach (var nodeBlock in nodeBlocks) { if (!(nodeBlock is XmlElement xmlBlock)) { continue; } NameValue keyValue = new NameValue() { Name = xmlBlock.GetAttribute("Name"), Value = Convert.ToDouble(xmlBlock.GetAttribute("Value")), ControlName = xmlBlock.GetAttribute("ControlName") }; mfcDoTest.CarryOut = keyValue; } } if (mfcDoTest.Name is not null) mfcDoTestList.Add(mfcDoTest); } } catch (Exception ex) { LOG.Error(ex.Message, ex); } } private void InitializeValue() { string reason = string.Empty; try { XmlDocument xml = new XmlDocument();//初始化一个xml实例 xml.Load(_controlUnitConfigPath); XmlElement root = xml.DocumentElement; XmlNodeList nodelist = root.ChildNodes; //遍历输出. foreach (XmlNode node in nodelist) { var nodeBlocks = node.SelectNodes("Condition/Mfcs/Mfc"); if (nodeBlocks != null) { foreach (var nodeBlock in nodeBlocks) { if (!(nodeBlock is XmlElement xmlBlock)) { continue; } MfcNameList.Add(xmlBlock.GetAttribute("Name")); } } nodeBlocks = node.SelectNodes("Condition/Values/Value"); if (nodeBlocks != null) { foreach (var nodeBlock in nodeBlocks) { if (!(nodeBlock is XmlElement xmlBlock)) { continue; } ValueNameList.Add(xmlBlock.GetAttribute("Name")); } } nodeBlocks = node.SelectNodes("Condition/PCs/PC"); if (nodeBlocks != null) { foreach (var nodeBlock in nodeBlocks) { if (!(nodeBlock is XmlElement xmlBlock)) { continue; } PCNameList.Add(xmlBlock.GetAttribute("Name")); } } } } catch (Exception ex) { LOG.Error(ex.Message, ex); } } private void InitializeDataList() { //初始化所有MFC foreach (var name in MfcNameList) MfcTestList.Add(new MfcTestData() { MfcName = name }); QueryAllMfcTestData(); //初始化所有气阀 foreach (var name in ValueNameList) ValueTestList.Add(new ControlNameData() { ControlName = name }); //初始化所有PC foreach (var name in PCNameList) PCTestList.Add(new ControlNameData() { ControlName = name }); string str= JsonConvert.SerializeObject(ValueTestList); QueryAllControlNameData(); } public void DelectAllData() { foreach (var item in MfcTestList) item.Delect(); foreach (var item in ValueTestList) item.Delect(); foreach (var item in PCTestList) item.Delect(); //truncate table DB.ExcuteTransAction(new List { "truncate control_name_data", "truncate mfc_test_data" }); } public override Result Start(params object[] objs) { MfcTest = new MfcTestData(); AllControlNameDataList = new List(); Reset(); string selectedMfcName = (string)objs[0]; mfcDoTestList.ForEach(t => { if (t.Name == selectedMfcName) mfcDoTest = t; }); MfcName = selectedMfcName.Contains("s") ? selectedMfcName.Replace("s", "") : selectedMfcName; //开始测试 //有一个集合为空,不用循环 if (mfcDoTest.StateList.Count == 0 || mfcDoTest.CarryOut.Name == null) return Result.FAIL; _timeDelay = SC.GetValue($"PM.{Module}.MfcTestingDelayedTime"); _upperLimit = SC.GetValue($"PM.{Module}.ThrottlePressureTimeout"); _mfcDefaultValue = SC.GetValue($"PM.{Module}.MFC.{MfcName}.DefaultSetPoint") * mfcDoTest.CarryOut.Value;//将mfc设定到表XML中设定的倍数 _scValue = SC.GetValue($"PM.{Module}.MfcTestingPercentage");//上限参数 _startTime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.fff"); _swTimer.Restart(); //初始化MFC操作对象,做界面显示用 MfcTest.MfcName = selectedMfcName; MfcTest.Module = Module; MfcTest.Result = ""; MfcTest.Values = ""; MfcTest.Infor = ""; MfcTest.BaseValue = _mfcDefaultValue.ToString(); Notify($"Start {MfcName} Test"); return Result.RUN; } public override Result Monitor() { try { //根据XML配置测试气路,打开或关闭气阀、PC、MFC PreSetValve((int)RoutineStep.OpenOrClose, false); //根据XML配置打开要测试的MFC PreMfcRamp((int)RoutineStep.OpenMfc, _mfcDefaultValue); //延时等待气流上升 TimeDelay((int)RoutineStep.TimeDelay, _timeDelay); //统计数据,并分析结果 PreInspect((int)RoutineStep.Inspect); //根据XML配置关闭检测的MFC PreMfcRamp((int)RoutineStep.CloseMfc, 0); //根据XML配置测试气路,关闭气阀、PC、MFC PreSetValve((int)RoutineStep.ResetState, true); //数据结果写入数据库 PreWriteDatabase((int)RoutineStep.WriteDatabase); } catch (RoutineBreakException) { return Result.RUN; } catch (RoutineFaildException) { return Result.FAIL; } Notify($"Finished ! Elapsed time: {(int)(_swTimer.ElapsedMilliseconds / 1000)} s"); _swTimer.Stop(); return Result.DONE; } protected void PreSetValve(int id, bool isReset) { Tuple ret = Execute(id, () => { if (!SetInputs(isReset, out string reason)) { Stop(reason); return false; } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } private bool SetInputs(bool isReset, out string reason) { reason = ""; for (int i = 0; i < mfcDoTest.StateList.Count; i++) { if (!MethodDelegate(mfcDoTest.StateList[i].ControlName, isReset ? 0 : mfcDoTest.StateList[i].Value, out reason)) return false; } return true; } private bool SetValve(string ioValveName, double value, out string reason) { reason = ""; if (!ioValveName.Contains("V")) return true; bool isOpen = value == 1 ? true : false; var ioValve = DEVICE.GetDevice($"{Module}.{ioValveName}"); if (ioValve.TurnValve(isOpen, out reason)) return true; reason = $" {(isOpen ? "Open" : "Close")} {ioValve} failed , {reason}"; return false; } private bool SetPC(string pcName, double value, out string reason) { reason = ""; if (!pcName.Contains("P")) return true; var isOpen = value == 1 ? PcCtrlMode.Open : PcCtrlMode.Close; var pc = DEVICE.GetDevice($"{Module}.{pcName}"); if (pc.SetPcMode(isOpen, out reason)) { Notify($"{pcName} {isOpen}"); return true; } reason = $" {isOpen} {pcName} failed , {reason}"; return false; } private bool SetMfcState(string mfcName, double value, out string reason) { reason = ""; if (!mfcName.Contains("M")) return true; var isOpen = value == 1 ? MfcCtrlMode.Open : MfcCtrlMode.Close; var mfc = DEVICE.GetDevice($"{Module}.{mfcName}"); if (mfc.SetMfcMode(isOpen, out reason)) return true; reason = $" {isOpen} {mfcName} failed , {reason}"; return false; } protected void PreMfcRamp(int id, double value) { Tuple ret = Execute(id, () => { Notify($"{mfcDoTest.CarryOut.ControlName} ramp to {value} "); MfcRamp(value); return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } private void MfcRamp(double value) { var mfc = DEVICE.GetDevice($"{Module}.{MfcName}"); mfc.Ramp(value, 0); } protected void PreInspect(int id) { Tuple ret = Execute(id, () => { Notify($"Inspect values "); Inspect(); return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } /// /// 对结果进行检查,赋值各种数据作为显示使用 /// /// /// private void Inspect() { try { var mfc = DEVICE.GetDevice($"{Module}.{MfcName}"); double volue = 0; List volueList = new List(); StringBuilder strResult = new StringBuilder(); StringBuilder strValues = new StringBuilder(); for (int i = 0; i < 10; i++) { double feedBack = mfc.FeedBack; volue = (feedBack - _mfcDefaultValue) / _mfcDefaultValue * 100; volueList.Add(volue); strValues.Append($"<{i + 1}>{feedBack.ToString("0.00")} ; "); strResult.Append($"<{i + 1}>{volue.ToString("0.00")}% ; "); System.Threading.Thread.Sleep(500); } EV.PostInfoLog($"{Module}", $" {MfcName} FeedBack Value {strValues} "); EV.PostInfoLog($"{Module}", $" {MfcName} Deviation Value {strResult} "); MfcTest.Values = strValues.ToString(); MfcTest.Result = strResult.ToString(); strResult.Clear();//清空后存储气路元器件名称 foreach (var item in mfcDoTest.StateList) { string operation = item.Value == 1 ? "Open" : "Close"; strResult.Append(item.Name + $"-{operation}; ");//提取所有气阀名称,打印输出用 } for (int i = 0; i < volueList.Count; i++) { if (Math.Abs(volueList[i]) > _scValue)//循环判断是否有超设定值 { EV.PostInfoLog($"{Module}", $" {MfcName} test failed,Please check {strResult}"); MfcTest.Infor = strResult.ToString(); MfcTest.IsPass = "NG"; return; } } MfcTest.Infor = strResult.ToString(); MfcTest.IsPass = "OK"; } catch (Exception ex) { EV.PostAlarmLog($"{Module}", $" failed {ex}"); return; } } protected void PreWriteDatabase(int id) { Tuple ret = Execute(id, () => { if (!WriteDatabase(out string reason)) { Stop(reason); return false; } return true; }); if (ret.Item1) { if (ret.Item2 == Result.FAIL) { throw (new RoutineFaildException()); } else throw (new RoutineBreakException()); } } private bool WriteDatabase(out string reason) { try { reason = ""; Notify($"Test over updata to database"); MfcTest.Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); ReceiveMfcTestData();//MFC数据库操作 ReceiveControlNameData();//气阀数据库操作 return true; } catch (Exception ex) { reason = ex.Message; return false; } } #region MFC数据库操作 public void ReceiveMfcTestData() { UpdataMfcTestData(); UpdateMfcTestDataDatabase(); QueryAllMfcTestData(); } private void UpdataMfcTestData() { foreach (var data in MfcTestList) { if (data.MfcName == MfcTest.MfcName) { data.Update(MfcTest); return; } } } private void UpdateMfcTestDataDatabase() { string cmdID = $"select * from mfc_test_data where mfc_name = '{MfcTest.MfcName}'"; var dt = DB.ExecuteDataset(cmdID); if (dt is null || dt.Tables[0].Rows.Count == 0) DB.ExcuteTransAction(new List() { InsertMfcTestDataCmd() }); else DB.ExcuteTransAction(new List() { UpdateMfcTestDataCmd() }); } private string InsertMfcTestDataCmd() { string cmd_data_insert = "insert into mfc_test_data" + "(module,mfc_name,is_pass, result,values,base_value,infor,time)" + $"values ('{Module}'," + $"'{MfcTest.MfcName}'," + $"'{MfcTest.IsPass}'," + $"'{MfcTest.Result}'," + $"'{MfcTest.Values}'," + $"'{MfcTest.BaseValue}'," + $"'{MfcTest.Infor}'," + $"'{MfcTest.Time}')"; return cmd_data_insert; } private string UpdateMfcTestDataCmd() { string cmd_update = $"update mfc_test_data set " + $"is_pass= '{MfcTest.IsPass}'," + $"result = '{MfcTest.Result}', " + $"values= '{MfcTest.Values}'," + $"base_value= '{MfcTest.BaseValue}'," + $"infor= '{MfcTest.Infor}'," + $"time= '{MfcTest.Time}'" + $"where mfc_name = '{MfcTest.MfcName}' and module = '{Module}' "; return cmd_update; } private List QueryAllMfcTestData() { try { string cmd = $"select * from mfc_test_data where module = '{Module}'"; var dt = DB.ExecuteDataset(cmd); if (dt is null || dt.Tables[0].Rows.Count == 0) return null; for (int i = 0; i < dt.Tables[0].Rows.Count; i++) { if (dt.Tables[0].Rows[i].ItemArray.Length != 0) { MfcTestData mfcTestData = new MfcTestData() { Module = dt.Tables[0].Rows[i]["module"].ToString(), MfcName = dt.Tables[0].Rows[i]["mfc_name"].ToString(), IsPass = dt.Tables[0].Rows[i]["is_pass"].ToString(), Result = dt.Tables[0].Rows[i]["result"].ToString(), Values = dt.Tables[0].Rows[i]["values"].ToString(), BaseValue = dt.Tables[0].Rows[i]["base_value"].ToString(), Infor = dt.Tables[0].Rows[i]["infor"].ToString(), Time = dt.Tables[0].Rows[i]["time"].ToString() }; MfcTestList.ForEach(t => { if (t.MfcName == mfcTestData.MfcName) t.Update(mfcTestData); }); } } return MfcTestList; } catch (Exception) { return null; } } #endregion #region 气阀数据库操作 public void ReceiveControlNameData() { UpDataControlNameData(); foreach (var item in AllControlNameDataList) { UpdateControlNameDataDatabase(item); } QueryAllControlNameData(); } private void UpDataControlNameData() { string _time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); string str = MfcTest.IsPass == "NG" ? "NG" : "OK"; foreach (var item in mfcDoTest.StateList) { AllControlNameDataList.Add(new ControlNameData() { Module= Module,//这里是使用字段赋值所属PM名称 ControlName = item.Name, State = str, Time = _time });; } } private void UpdateControlNameDataDatabase(ControlNameData controlNameData) { string cmdID = $"select * from control_name_data where control_name = '{controlNameData.ControlName}'"; var dt = DB.ExecuteDataset(cmdID); if (dt is null || dt.Tables[0].Rows.Count == 0) DB.ExcuteTransAction(new List() { InsertControlNameDataCmd(controlNameData) }); else DB.ExcuteTransAction(new List() { UpdateControlNameDataCmd(controlNameData) }); } //public string ControlName { get; set; } //public string State { get; set; } //public string Time { get; set; } private string InsertControlNameDataCmd(ControlNameData controlNameData) { string cmd_data_insert = "insert into control_name_data" + "(module,control_name,state,time)" + $"values ('{Module}'," + $"'{controlNameData.ControlName}'," + $"'{controlNameData.State}'," + $"'{controlNameData.Time}')"; return cmd_data_insert; } private string UpdateControlNameDataCmd(ControlNameData controlNameData) { string cmd_update = $"update control_name_data set " + $"state= '{controlNameData.State}'," + $"time= '{controlNameData.Time}'" + $"where control_name = '{controlNameData.ControlName}' and module = '{Module}'"; return cmd_update; } private List QueryAllControlNameData() { try { string cmd = $"select * from control_name_data where module = '{Module}'"; var dt = DB.ExecuteDataset(cmd); if (dt is null || dt.Tables[0].Rows.Count == 0) return null; for (int i = 0; i < dt.Tables[0].Rows.Count; i++) { if (dt.Tables[0].Rows[i].ItemArray.Length != 0) { ControlNameData _controlNameData = new ControlNameData() { Module = dt.Tables[0].Rows[i]["module"].ToString(), ControlName = dt.Tables[0].Rows[i]["control_name"].ToString(), State = dt.Tables[0].Rows[i]["state"].ToString(), Time = dt.Tables[0].Rows[i]["time"].ToString() }; if (_controlNameData.ControlName.Contains("V")) { ValueTestList.ForEach(t => { if (t.ControlName == _controlNameData.ControlName) t.Update(_controlNameData); }); } else if (_controlNameData.ControlName.Contains("PC")) { PCTestList.ForEach(t => { if (t.ControlName == _controlNameData.ControlName) t.Update(_controlNameData); }); } } } return MfcTestList; } catch (Exception) { return null; } } #endregion } }