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.Runtime.InteropServices;
|
using System.Windows;
|
using System.Windows.Controls;
|
|
namespace Plugin.TestResult_WPF
|
{
|
/// <summary>
|
/// TestResultView.xaml 的交互逻辑
|
/// </summary>
|
public partial class TestResultView : UserControl
|
{
|
private int rowCount;
|
private int colCount;
|
private int cellCount;
|
|
public static DataTable[] tables { get; private set; }
|
public static Dictionary<string, DataTable> nameTables { get; private set; } = new Dictionary<string, DataTable>();
|
private readonly BaseConfig config;
|
|
|
|
public string testModelFile;
|
public string testSeqFile;
|
public bool inManualDebugMode = false;
|
|
#region TS相关
|
//public AxApplicationMgr testApp;
|
///// <summary>
|
///// 测试序列
|
///// </summary>
|
//private SequenceFile testSeq = null;
|
//public Engine engine;
|
//private Execution execution = null;
|
///// <summary>
|
///// 测试序列操作句柄
|
///// </summary>
|
//public SequenceContext SequenceContext { get; private set; } = null;
|
///// <summary>
|
///// 测试模型序列
|
///// </summary>
|
//private SequenceFile modeSeq;
|
|
public ITestExecutionWrapper executionWrapper;
|
#endregion
|
|
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();
|
|
executionWrapper = new TsExecutionWrapper(); //new TsExecutionWrapper();
|
if (executionWrapper is TsExecutionWrapper tsWrapper)
|
{
|
tsWrapper.AxApplicationMgr.ExitApplication += this.axApplicationMgr_ExitApplication;
|
tsWrapper.AxApplicationMgr.UIMessageEvent += this.axApplicationMgr_UIMessageEvent;
|
tsWrapper.AxApplicationMgr.ExecutionClosed += this.axApplicationMgr_ExecutionClosed;
|
((System.ComponentModel.ISupportInitialize)(tsWrapper.AxApplicationMgr)).BeginInit();//myClient为第三方控件名
|
host.Child = tsWrapper.AxApplicationMgr;
|
((System.ComponentModel.ISupportInitialize)(tsWrapper.AxApplicationMgr)).EndInit();
|
}
|
|
|
|
//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();
|
}
|
|
private void Refresh()
|
{
|
}
|
|
/// <summary>
|
/// 探针计数配置路径
|
/// </summary>
|
private string CountIniPath;
|
public void SetCountIniPath(string countIniPath)
|
{
|
CountIniPath = countIniPath;
|
}
|
|
public void InitMainGrid()
|
{
|
nameTables = new Dictionary<string, DataTable>();
|
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;
|
}
|
|
/// <summary>
|
/// 启动测试序列
|
/// </summary>
|
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);
|
executionWrapper.Init();
|
}
|
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;
|
executionWrapper?.StartSequence(this.testSeqFile,
|
@"C:\Program Files\National Instruments\TestStand 2020\Components\Models\TestStandModels\ParallelModel.seq");
|
|
executionWrapper.SetStationGlobalValue<bool>("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
|
{
|
executionWrapper?.SetStationGlobalValue<bool>("StationState.StopTest", 0, true, true);
|
|
try
|
{
|
executionWrapper?.WaitForExit();
|
executionWrapper?.ReleaseSeqFile();
|
}
|
catch (Exception ex)
|
{
|
ViewControl.Logger.Error("Wait For Exit error.", ex);
|
//if (ex is NullReferenceException ne)
|
//{
|
|
//}
|
//else
|
//{
|
// throw ex;
|
//}
|
}
|
}
|
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;
|
if (executionWrapper is TsExecutionWrapper tsWrapper)
|
{
|
tsWrapper.context = (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();
|
//GC.Collect();
|
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 == 180)
|
{
|
/// 保存穴位测试数据到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).NormalCSV(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)
|
{
|
executionWrapper.SetStationGlobalValue<int>($"StationState.Pipe[{index}]", 1, 1);
|
//SequenceContext.StationGlobals.SetValNumber($"StationState.Pipe[{index}]", 1, 1);
|
}
|
else
|
{
|
executionWrapper.SetStationGlobalValue<int>($"StationState.Pipe[{index}]", 1, 0);
|
//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)
|
{
|
string name = tables[index].title;
|
ViewControl.Logger?.Info($"将老化炉[{name}] 的Start变量设置为 {data};");
|
string key = $"StationState.Start[{index}]";
|
|
executionWrapper?.SetStationGlobalValue<bool>(key, 1, data);
|
|
if (data == false)
|
{
|
key = $"StationState.Scanner[{index}]";
|
executionWrapper?.SetStationGlobalValue<bool>(key, 1, false);
|
}
|
}
|
|
public bool? GetStartFlag(int index)
|
{
|
string key = $"StationState.Start[{index}]";
|
return executionWrapper.GetStationGlobalValue<bool>(key, 0);
|
}
|
|
public void ReleaseResource()
|
{
|
if (executionWrapper is TsExecutionWrapper tsWrapper)
|
{
|
tsWrapper.AxApplicationMgr.ExitApplication -= this.axApplicationMgr_ExitApplication;
|
tsWrapper.AxApplicationMgr.UIMessageEvent -= this.axApplicationMgr_UIMessageEvent;
|
tsWrapper.AxApplicationMgr.ExecutionClosed -= this.axApplicationMgr_ExecutionClosed;
|
}
|
|
foreach (var table in tables)
|
{
|
table.RelaseResource();
|
}
|
}
|
|
/// <summary>
|
/// 计数清零
|
/// </summary>
|
public void ClearNumber()
|
{
|
foreach (var table in tables)
|
{
|
table.ClearNumber();
|
}
|
}
|
|
public void SetProductSource(List<string> 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];
|
string LookupStr = $"StationState.Model[{i}]";
|
|
string tableModel = executionWrapper?.GetStationGlobalValue<string>(LookupStr, 1);
|
//engine?.Globals?.GetValString(LookupStr, 1);
|
table.SetCurrentProduct(tableModel);
|
}
|
}
|
|
public void SetOvenProduct(int index, string product)
|
{
|
string LookupStr = $"StationState.Model[{index}]";
|
executionWrapper?.SetStationGlobalValue<string>(LookupStr, 1, product);
|
executionWrapper?.CommitToDisk(false);
|
}
|
|
public void RefreshProducts()
|
{
|
}
|
}
|
}
|