using HMI.Core.Entity; using HMI.Core.Manager; using HMI.Core.Util; using HMI.UI.Util; using NationalInstruments.TestStand.Interop.API; using NationalInstruments.TestStand.Interop.UI.Ax; using Plugin.TestResult_WPF.Model; using Plugin.TsSupport; using System; using System.Collections.Generic; using System.Windows; using System.Windows.Controls; namespace Plugin.TestResult_WPF { /// /// TestResultView.xaml 的交互逻辑 /// public partial class TestResultView : UserControl { private int rowCount; private int colCount; private int cellCount; public static DataTable[] tables { get; private set; } public static Dictionary nameTables { get; private set; } = new Dictionary(); private readonly BaseConfig config; public AxApplicationMgr testApp; public string testModelFile; public string testSeqFile; /// /// 测试序列 /// private SequenceFile testSeq = null; public Engine engine; private Execution execution = null; /// /// 测试序列操作句柄 /// public SequenceContext SequenceContext { get; private set; } = null; /// /// 测试模型序列 /// private SequenceFile modeSeq; public TestResultView() : this(new BaseConfig { testing = false }) { } public bool IsRunning { get; set; } = false; public void RefreshCooler() { } private void RefreshNumberConfig(BaseConfig config) { ParameterData value = null; try { value = ParameterManager.GetCommonParameterByName("BurnInOvenCount"); string[] datas = value.Value.Trim().Split(','); config.Row = int.Parse(datas[0]); config.Column = int.Parse(datas[1]); } catch (Exception ex) { } try { value = ParameterManager.GetCommonParameterByName("BurnInOvenName"); config.NameStr = value.Value; } catch (Exception ex) { } try { value = ParameterManager.GetCommonParameterByName("BurnInOvenPort"); config.PortStart = int.Parse(value.Value); } catch (Exception ex) { } try { value = ParameterManager.GetCommonParameterByName("BurnInCellCount"); string[] datas = value.Value.Trim().Split(','); config.PositionColumn = int.Parse(datas[0]); config.PositionCount = int.Parse(datas[1]); } catch (Exception ex) { } } public TestResultView(BaseConfig config) { try { var value = ParameterManager.GetCommonParameterByName("TsModelPath"); testModelFile = value?.Value ?? @"C:\Users\Public\Documents\National Instruments\TestStand 2020 (64-bit)\Components\Models\ParallelModel.seq"; } catch { //@"C:\Program Files\National Instruments\TestStand 2020\Components\Models\TestStandModels\ParallelModel.seq" testModelFile = @"C:\Users\Public\Documents\National Instruments\TestStand 2020 (64-bit)\Components\Models\ParallelModel.seq"; } RefreshNumberConfig(config); this.rowCount = config.Row; this.colCount = config.Column; this.config = config; if (config.CellCount < 0) { this.cellCount = rowCount * colCount; } else { this.cellCount = config.CellCount; } tables = new DataTable[this.cellCount]; InitializeComponent(); testApp = TestAppManager.GetAxApplicationMgr(); testApp.ExitApplication += this.axApplicationMgr_ExitApplication; testApp.UIMessageEvent += this.axApplicationMgr_UIMessageEvent; testApp.ExecutionClosed += this.axApplicationMgr_ExecutionClosed; ((System.ComponentModel.ISupportInitialize)(this.testApp)).BeginInit();//myClient为第三方控件名 host.Child = testApp; ((System.ComponentModel.ISupportInitialize)(this.testApp)).EndInit(); //InitTestStandEngine(); //StartTestSequence(); } private void Refresh() { } /// /// 探针计数配置路径 /// private string CountIniPath; public void SetCountIniPath(string countIniPath) { CountIniPath = countIniPath; } public void InitMainGrid() { nameTables = new Dictionary(); for (int r = 0; r < rowCount; r++) { RowDefinition row = new RowDefinition(); mainGrid.RowDefinitions.Add(row); } for (int c = 0; c < colCount; c++) { ColumnDefinition col = new ColumnDefinition(); mainGrid.ColumnDefinitions.Add(col); } string[] names = config.NameStr.Split(','); for (int n = 0; n < cellCount; n++) { string name = n < names.Length ? names[n] : ""; DataTable child = new DataTable(this, n, name, CountIniPath, config); mainGrid.Children.Add(child); tables[n] = child; nameTables[name] = child; int row = n / colCount; int col = n % colCount; Grid.SetRow(child, row); Grid.SetColumn(child, col); } if (config.testing) Refresh(); } public DataTable GetDataTable(int index) { if (index >= 0 && index < tables.Length) return tables[index]; return null; } /// /// 启动测试序列 /// public void InitTestStandEngine() { try { this.engine = this.testApp.GetEngine(); this.engine.PersistBreakpoints = false; this.testApp.IsEditor = true; this.testApp.LoginOnStart = false; this.testApp.Start(); this.modeSeq = this.engine.GetSequenceFileEx(testModelFile); } catch (Exception ex) { ViewControl.Logger.Error("InitTestStandEngine Failed.", ex); throw new Exception($"{this.lang("Ts.InitTestStandEngineFail")}: {ex.Message}"); } } public void StartTestSequence() { try { if (string.IsNullOrEmpty(testSeqFile)) return; this.modeSeq = this.engine.GetSequenceFileEx(@"C:\Program Files\National Instruments\TestStand 2020\Components\Models\TestStandModels\ParallelModel.seq"); this.testSeq = this.engine.GetSequenceFileEx(this.testSeqFile, 0, TypeConflictHandlerTypes.ConflictHandler_UseGlobalType); this.execution = this.engine.NewExecution(this.testSeq, "Test UUTs", this.modeSeq, false, 0, null, null, null); this.engine.Globals.SetValBoolean("StationState.StopTest", 0, false); } catch (Exception ex) { ViewControl.Logger.Error("StartTestSequence Failed.", ex); throw new Exception($"{this.lang("Ts.StartTestSequenceFailed")}: {ex.Message}"); } } public void StopTest() { try { if (this.SequenceContext == null) return; bool val = this.SequenceContext.StationGlobals.Exists("StationState.StopTest", 0); if (val) { this.SequenceContext.StationGlobals.SetValBoolean("StationState.StopTest", 0, true); bool isStop = this.execution.WaitForEndEx(2000, true, null, null); } } catch (Exception ex) { ViewControl.Logger.Error("StopTest Failed.", ex); throw new Exception($"{this.lang("Ts.StopTestSequenceFailed")}: {ex.Message}"); } } private void axApplicationMgr_ExitApplication(object sender, EventArgs e) { Environment.ExitCode = testApp.ExitCode; //TSHelper.DoSynchronousGCForCOMObjectDestruction(); } private void axApplicationMgr_ExecutionClosed(object sender, _ApplicationMgrEvents_ExecutionClosedEvent e) { try { //this.ReleaseSequenceFile(); } catch (Exception ex) { MsgBoxHelper.Error(Window.GetWindow(this), $"{this.lang("Ts.ReleaseSequenceFileFail")}: {ex.Message}"); } } private void axApplicationMgr_UIMessageEvent(object sender, _ApplicationMgrEvents_UIMessageEventEvent e) { try { int EventCase = Convert.ToInt32(e.uiMsg.Event); int MethodCode = Convert.ToInt16(e.uiMsg.NumericData); string strData; if (EventCase != 10014) return; if (MethodCode == 0) { /// 设置句柄 this.SequenceContext = (SequenceContext)e.uiMsg.ActiveXData; return; } if (MethodCode == 1) { /// 更新炉子状态 strData = e.uiMsg.StringData; string[] datas_10014 = strData.Split(';'); int ovenIndex = int.Parse(datas_10014[0]); string status = datas_10014[1]; tables[ovenIndex].SetStatus(status); return; } if (MethodCode == 2) { /// 更新炉子数量信息 strData = e.uiMsg.StringData; string[] datas_10014 = strData.Split(';'); int ovenIndex = int.Parse(datas_10014[0]); string okCount = datas_10014[1]; string ngCount = datas_10014[2]; tables[ovenIndex].SetOkCount(int.Parse(okCount)); tables[ovenIndex].SetNgCount(int.Parse(ngCount)); return; } if (MethodCode == 3) { /// 更新炉子时间信息 strData = e.uiMsg.StringData; string[] datas_10014 = strData.Split(';'); int ovenIndex = int.Parse(datas_10014[0]); string startTime = datas_10014[1]; string consumeTime = datas_10014[2]; string planEndTime = datas_10014[3]; tables[ovenIndex].SetStartTime(startTime); tables[ovenIndex].SetEndTime(planEndTime); double? leftTime = null; /// 为了兼容旧版本,如果有剩余时间就传,没有就传null if (datas_10014.Length >= 5) { leftTime = double.Parse(datas_10014[4]); } tables[ovenIndex].UpdateConsumeTime(double.Parse(consumeTime), leftTime); return; } if (MethodCode == 4) { /// 更新老化炉底部状态栏 strData = e.uiMsg.StringData; string[] datas_10014 = strData.Split(';'); int ovenIndex = int.Parse(datas_10014[0]); string statusBar = datas_10014[1]; tables[ovenIndex].SetStatusText(statusBar); return; } if (MethodCode == 5) { /// 采集炉温度 strData = e.uiMsg.StringData; string[] datas_10016 = strData.Split(';'); int ovenIndex = int.Parse(datas_10016[0]); string[] names = datas_10016[1].Split(','); string[] values = datas_10016[2].Split(','); for (int x = 0; x < values.Length; x++) { if (x == 0) tables[ovenIndex].SetTemperature(double.Parse(values[x])); else tables[ovenIndex].SetTemperature(names[x - 1], double.Parse(values[x])); } return; } if (MethodCode == 6) { /// 更新穴位状态 strData = e.uiMsg.StringData; string[] datas_10015 = strData.Split(';'); int ovenIndex = int.Parse(datas_10015[0]); int cellIndex = int.Parse(datas_10015[1]); string status_10015 = datas_10015[2]; tables[ovenIndex].GetSingleCell(cellIndex).SetStatus(status_10015); if (status_10015 == "OK" || status_10015 == "ok") { tables[ovenIndex].RefreshCount(1, 0); } else if (status_10015 == "ng" || status_10015 == "NG") { tables[ovenIndex].RefreshCount(0, 1); } return; } if (MethodCode == 7) { /// 更新穴位参数 strData = e.uiMsg.StringData; string[] datas_10015 = strData.Split(';'); int ovenIndex = int.Parse(datas_10015[0]); int cellIndex = int.Parse(datas_10015[1]); string strs = datas_10015[2]; string[] values = strs.Split(','); //string step = datas_10015[2]; //string result = datas_10015[3]; tables[ovenIndex].GetSingleCell(cellIndex).SetInfos(new Info { step = values[0], value = values[1], limitUp = values[2], limitDown = values[3], unit = values[4], result = values[5], updateTime = values[6] }); return; } if (MethodCode == 10) { /// 清空炉子的温度图表 strData = e.uiMsg.StringData; int ovenIndex = int.Parse(strData); tables[ovenIndex].ClearChartData(); return; } if (MethodCode == 11) { /// 清除穴位参数 strData = e.uiMsg.StringData; string[] datas_10015 = strData.Split(';'); int ovenIndex = int.Parse(datas_10015[0]); int cellIndex = int.Parse(datas_10015[1]); tables[ovenIndex].GetSingleCell(cellIndex).ClearInfo(); return; } if (MethodCode == 12) { /// 保存炉体温度文件 strData = e.uiMsg.StringData; string[] datas = strData.Split(';'); int ovenIndex = int.Parse(datas[0]); string folder = datas[1]; tables[ovenIndex].SaveTempFile(folder); return; } if (MethodCode == 13) { /// 添加电流数据 strData = e.uiMsg.StringData; string[] datas = strData.Split(';'); int ovenIndex = int.Parse(datas[0]); int cellIndex = int.Parse(datas[1]); double eData = double.Parse(datas[2]); tables[ovenIndex].GetSingleCell(cellIndex).AddElectricData(eData); return; } if (MethodCode == 14) { /// 清空电流和电压数据 strData = e.uiMsg.StringData; int ovenIndex = int.Parse(strData); tables[ovenIndex].ClearCellData(); //tables[ovenIndex].ClearElectricData(); //tables[ovenIndex].ClearVData(); //tables[ovenIndex].ClearWaterData(); return; } if (MethodCode == 15) { /// 保存电流数据 strData = e.uiMsg.StringData; string[] datas = strData.Split(';'); int ovenIndex = int.Parse(datas[0]); int cellIndex = int.Parse(datas[1]); string filePath = datas[2]; tables[ovenIndex].GetSingleCell(cellIndex).SaveElectricDataToCSV(filePath); return; } if (MethodCode == 16) { /// 添加电压图表数据 strData = e.uiMsg.StringData; string[] datas = strData.Split(';'); int ovenIndex = int.Parse(datas[0]); int cellIndex = int.Parse(datas[1]); double eData = double.Parse(datas[2]); tables[ovenIndex].GetSingleCell(cellIndex).AddVData(eData); return; } if (MethodCode == 17) { /// 保存电压数据 strData = e.uiMsg.StringData; string[] datas = strData.Split(';'); int ovenIndex = int.Parse(datas[0]); int cellIndex = int.Parse(datas[1]); string filePath = datas[2]; tables[ovenIndex].GetSingleCell(cellIndex).SaveVDataToCSV(filePath); return; } if (MethodCode == 18) { /// 保存穴位测试数据到CSV strData = e.uiMsg.StringData; string[] datas = strData.Split(';'); int ovenIndex = int.Parse(datas[0]); int cellIndex = int.Parse(datas[1]); string filePath = datas[2]; tables[ovenIndex].GetSingleCell(cellIndex).SaveInfoToCSV(filePath); return; } if (MethodCode == 19) { /// 保存穴位测试数据到Sqlite strData = e.uiMsg.StringData; string[] datas = strData.Split(';'); int ovenIndex = int.Parse(datas[0]); int cellIndex = int.Parse(datas[1]); tables[ovenIndex].GetSingleCell(cellIndex).SaveInfoToDB(); return; } if (MethodCode == 20) { /// 清空条码 strData = e.uiMsg.StringData; int ovenIndex = int.Parse(strData); tables[ovenIndex].ClearAllSN(); return; } if (MethodCode == 21) { /// 添加水流图表数据 strData = e.uiMsg.StringData; string[] datas = strData.Split(';'); int ovenIndex = int.Parse(datas[0]); int cellIndex = int.Parse(datas[1]); double waterTemp = double.Parse(datas[2]); double backWaterTemp = double.Parse(datas[3]); double waterPressure = double.Parse(datas[4]); tables[ovenIndex].GetSingleCell(cellIndex).AddWaterData(waterTemp, backWaterTemp, waterPressure); return; } if (MethodCode == 99) { strData = e.uiMsg.StringData; string[] datas = strData.Split(';'); int index = int.Parse(datas[0]); if (MsgBoxHelper2.WarnChoose(datas[1], "提示") == MessageBoxResult.OK) { SequenceContext.StationGlobals.SetValNumber($"StationState.Pipe[{index}]", 1, 1); } else { SequenceContext.StationGlobals.SetValNumber($"StationState.Pipe[{index}]", 1, 0); } return; } } catch (Exception ex) { ViewControl.Logger.Warn("TestStand Event Error.", ex); } } public void SetStartFlag(int index, bool data) { if (this.SequenceContext == null) return; string name = tables[index].title; string key = $"StationState.Start[{index}]"; this.engine.Globals.SetValBoolean(key, 1, data); //bool val = this.engine.Globals.GetValBoolean(key, 0); //this.SequenceContext.StationGlobals.SetValBoolean(key, 0, data); //bool val = this.SequenceContext.StationGlobals.GetValBoolean(key, 0); } public void ReleaseResource() { testApp.ExitApplication -= this.axApplicationMgr_ExitApplication; testApp.UIMessageEvent -= this.axApplicationMgr_UIMessageEvent; testApp.ExecutionClosed -= this.axApplicationMgr_ExecutionClosed; foreach (var table in tables) { table.RelaseResource(); } } /// /// 计数清零 /// public void ClearNumber() { foreach (var table in tables) { table.ClearNumber(); } } public void SetProductSource(List productSource) { foreach (var table in tables) { table.SetProductSource(productSource); } } public void SetCurrentProduct(string currentProduct) { for (int i = 0; i < tables.Length; i++) { var table = tables[i]; // table.SetCurrentProduct(currentProduct); string LookupStr = $"StationState.Model[{i}]"; string tableModel = engine?.Globals?.GetValString(LookupStr, 1); table.SetCurrentProduct(tableModel); } } public void SetOvenProduct(int index, string product) { string LookupStr = $"StationState.Model[{index}]"; engine?.Globals?.SetValString(LookupStr, 1, product); engine?.CommitGlobalsToDisk(promptOnSaveConflicts: false); } } }