using HMI.Base;
|
using HMI.Core.Entity;
|
using HMI.Core.Manager;
|
using HMI.Core.Util;
|
using HMI.UI;
|
using HMI.UI.Entity;
|
using HMI.UI.Util;
|
using NationalInstruments.TestStand.Interop.API;
|
using NationalInstruments.TestStand.Interop.UI.Ax;
|
using Panuon.WPF.UI;
|
using System;
|
using System.Collections.Generic;
|
using System.Collections.ObjectModel;
|
using System.IO;
|
using System.IO.Ports;
|
using System.Linq;
|
using System.Reflection;
|
using System.Windows;
|
using System.Windows.Controls;
|
|
namespace Plugin.JarUI
|
{
|
/// <summary>
|
/// UserControl1.xaml 的交互逻辑
|
/// </summary>
|
public partial class JarUI : PluginControl
|
{
|
public JarUI()
|
{
|
DataContext = this;
|
InitializeComponent();
|
InitTsEngine();
|
InitProducts();
|
}
|
|
public override void InitFinish()
|
{
|
string iniFile = Path.Combine(BaseFolder, "Config.ini");
|
if (!File.Exists(iniFile))
|
{
|
File.Create(iniFile);
|
}
|
this.iniFile = iniFile;
|
}
|
|
#region Properties
|
|
#region TestStand相关
|
private AxApplicationMgr AxApplicationMgr;
|
/// <summary>
|
/// TS 引擎
|
/// </summary>
|
private Engine engine = null;
|
|
private string testSeqFile = string.Empty;
|
/// <summary>
|
/// 测试序列
|
/// </summary>
|
private SequenceFile testSeq = null;
|
|
/// <summary>
|
/// 测试模型序列
|
/// </summary>
|
private SequenceFile modeSeq = null;
|
public SequenceContext SequenceContext { get; private set; } = null;
|
private Execution execution = null;
|
#endregion
|
|
private bool _isRunning;
|
public bool IsRunning
|
{
|
get => _isRunning;
|
set
|
{
|
Dispatcher.Invoke(() =>
|
{
|
startBtn.IsEnabled = !value;
|
stopBtn.IsEnabled = value;
|
CbProduct.IsEnabled = !value;
|
});
|
Set(ref _isRunning, value);
|
}
|
}
|
|
private ObservableCollection<ProductData> _products;
|
|
public ObservableCollection<ProductData> Products
|
{
|
get { return _products; }
|
set { Set(ref _products, value); }
|
}
|
|
private ProductData _selectedProduct;
|
|
public ProductData SelectedProduct
|
{
|
get { return _selectedProduct; }
|
set
|
{
|
Set(ref _selectedProduct, value);
|
SetTestSeqFile(value);
|
}
|
}
|
|
private bool _enableMes;
|
public bool EnableMes
|
{
|
get => _enableMes;
|
set
|
{
|
if (WriteConfig("EnableMes", value))
|
{
|
Set(ref _enableMes, value);
|
}
|
}
|
}
|
|
|
private bool isLoadOk = false;
|
private string iniFile;
|
private JarCell selectedCell;
|
|
private JarCell[] tsSockets;
|
private Dictionary<string, JarCell> socketMap = new Dictionary<string, JarCell>();
|
private SerialPort serialPort;
|
#endregion
|
|
private void RefershUI()
|
{
|
tsSockets = new JarCell[18];
|
for (int i = 0; i < 18; i++)
|
{
|
var cell = new JarCell(i);
|
cell.GotFocus += Cell_GotFocus;
|
uGrid.Children.Add(cell);
|
tsSockets[i] = cell;
|
socketMap.Add(cell.Name, cell);
|
}
|
}
|
|
private void Cell_GotFocus(object sender, RoutedEventArgs e)
|
{
|
selectedCell = sender as JarCell;
|
}
|
|
private void SetTestSeqFile(ProductData product)
|
{
|
if (product == null)
|
{
|
testSeqFile = null;
|
return;
|
}
|
string name = product.Name;
|
List<ParameterData> parameters = ProductManager.GetParametersByProductName(name);
|
testSeqFile = parameters.FirstOrDefault(p => p.Name == "TestSequence")?.Value?.ToString();
|
StartSequence();
|
}
|
|
private void InitProducts()
|
{
|
Products = ProductManager.GetProducts<ObservableCollection<ProductData>>();
|
if (Products != null && Products.Count > 0)
|
{
|
List<ParameterData> parameters =
|
ParameterManager.GetCommonParameter<List<ParameterData>>();
|
string tmpNum = parameters?.FirstOrDefault(p => p.Name == "SocketNum")?.Value?.ToString();
|
string lastModel = engine?.Globals.GetValString("StationState.ProductModel", 1);
|
|
if (!string.IsNullOrEmpty(lastModel))
|
{
|
var product = Products.FirstOrDefault(p => p.Name == lastModel);
|
if (product != null)
|
{
|
SelectedProduct = product;
|
RefershUI();
|
return;
|
}
|
}
|
SelectedProduct = Products[0];
|
RefershUI();
|
}
|
}
|
|
private bool WriteConfig(string name, bool value)
|
{
|
//IniFileHelper.WriteIniData("Config", name, value.ToString(), CountIniPath);
|
try
|
{
|
if (ParameterManager.UpdateCommonParameter(name, value, out string errMsg))
|
{
|
SequenceContext?.StationGlobals.SetValBoolean($"SystemSetting.{name}", 1, value);
|
return true;
|
}
|
else
|
{
|
throw new Exception(errMsg);
|
}
|
}
|
catch (Exception ex)
|
{
|
MsgBoxHelper2.Error(ex.Message);
|
return false;
|
}
|
}
|
|
/// <summary>
|
/// 读取配置文件里的几个属性
|
/// </summary>
|
/// <param name="pass"></param>
|
/// <param name="fail"></param>
|
private void ReadConfig()
|
{
|
ParameterData value;
|
try
|
{
|
value = ParameterManager.GetCommonParameterByName("EnableMes");
|
_enableMes = bool.Parse(value.Value);
|
Set("EnableMes");
|
}
|
catch
|
{
|
_enableMes = false;
|
Set("EnableMes");
|
}
|
|
//try
|
//{
|
// value = ParameterManager.GetCommonParameterByName("EnableNGPause");
|
// _enableNGPause = bool.Parse(value.Value);
|
// Set("EnableNGPause");
|
//}
|
//catch
|
//{
|
// _enableNGPause = false;
|
// Set("EnableNGPause");
|
//}
|
|
//try
|
//{
|
// value = ParameterManager.GetCommonParameterByName("EnableCanLog");
|
// _enableCanLog = bool.Parse(value.Value);
|
// Set("EnableCanLog");
|
//}
|
//catch
|
//{
|
// _enableCanLog = false;
|
// Set("EnableCanLog");
|
//}
|
|
//try
|
//{
|
// value = ParameterManager.GetCommonParameterByName("EnableDebugMode");
|
// _enableDebugMode = bool.Parse(value.Value);
|
// Set("EnableDebugMode");
|
//}
|
//catch
|
//{
|
// _enableDebugMode = false;
|
// Set("EnableDebugMode");
|
//}
|
|
//try
|
//{
|
// value = ParameterManager.GetCommonParameterByName("EnableSimpleMode");
|
// EnableSimpleMode = bool.Parse(value.Value);
|
//}
|
//catch
|
//{
|
// EnableSimpleMode = false;
|
//}
|
|
//try
|
//{
|
// value = ParameterManager.GetCommonParameterByName("UI_ShowInfoDock");
|
// UI_ShowInfoDock = bool.Parse(value.Value);
|
//}
|
//catch
|
//{
|
// UI_ShowInfoDock = false;
|
//}
|
|
//try
|
//{
|
|
// value = ParameterManager.GetCommonParameterByName("TestReportFolder");
|
// csvDir = value.Value;
|
// if (!Directory.Exists(csvDir))
|
// {
|
// Directory.CreateDirectory(csvDir);
|
// }
|
//}
|
//catch
|
//{
|
// csvDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TestReport");
|
//}
|
}
|
|
#region 扫码枪相关
|
/// <summary>
|
/// 设置扫码枪
|
/// </summary>
|
private void InitScanner()
|
{
|
if (serialPort != null) return;
|
ScannerConfig common = ScannerConfig.ReadFromIni(iniFile, "Config");
|
// 配置串口
|
serialPort = new SerialPort
|
{
|
PortName = common.PortName,
|
BaudRate = common.BaudRate,
|
Parity = Parity.None,
|
DataBits = common.DataBits,
|
StopBits = common.StopBits,
|
Handshake = Handshake.None,
|
DtrEnable = common.DtrEnable,
|
RtsEnable = common.RtsEnable
|
//ReadTimeout = 500,
|
//WriteTimeout = 500,
|
//ReciveBufferSize=4096
|
};
|
|
try
|
{
|
// 打开串口
|
serialPort.Open();
|
// 注册接收数据事件
|
serialPort.DataReceived += SerialPort_DataReceived;
|
}
|
catch (Exception ex)
|
{
|
log.Error("Init Scan Gun Failed.", ex);
|
Dispatcher.Invoke(() =>
|
{
|
MsgBoxHelper.Error(this, $"{this.lang("Tr.InitGunFailed")}: {ex.StackTrace}");
|
});
|
}
|
}
|
private string ReadDataFrom(SerialPort sp)
|
{
|
string barcode = "";
|
while (sp.BytesToRead > 0)
|
{
|
byte[] buffer = new byte[sp.BytesToRead];
|
sp.Read(buffer, 0, buffer.Length);
|
barcode += System.Text.Encoding.UTF8.GetString(buffer);
|
System.Threading.Thread.Sleep(50);
|
}
|
return barcode;
|
}
|
|
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
|
{
|
try
|
{
|
SerialPort sp = (SerialPort)sender;
|
string barcode = ReadDataFrom(sp);
|
if (selectedCell != null)
|
{
|
Dispatcher.Invoke(() =>
|
{
|
selectedCell.SetSn(barcode);
|
});
|
SequenceContext.StationGlobals.SetValString($"StationState.SN[{selectedCell.Index}]", 1, barcode);
|
SequenceContext.StationGlobals.SetValBoolean($"StationState.Socket_{selectedCell.Index}", 1, true);
|
}
|
}
|
catch (Exception ex)
|
{
|
log.Error("Get Scan Gun Data Failed.", ex);
|
MessageBox.Show($"{this.lang("Tr.GetGunData")}: {ex.StackTrace}");
|
}
|
}
|
#endregion
|
|
private void Button_Click(object sender, RoutedEventArgs e)
|
{
|
Button btn = sender as Button;
|
switch (btn?.Name)
|
{
|
case "startBtn":
|
StartBtnClick();
|
break;
|
case "stopBtn":
|
StopBtnClick();
|
break;
|
case "scannerSettingBtn":
|
ScannerSetting ss = new ScannerSetting
|
{
|
Owner = Window.GetWindow(this)
|
};
|
if (ss.Open(true, "Config", iniFile) == true)
|
{
|
serialPort?.Close();
|
InitScanner();
|
}
|
break;
|
default:
|
break;
|
}
|
}
|
|
private void StartBtnClick()
|
{
|
new MaskWindow(Window.GetWindow(this),
|
(win) =>
|
{
|
try
|
{
|
StartSequence();
|
}
|
finally
|
{
|
win.Dispatcher.Invoke(() =>
|
{
|
win.Close();
|
});
|
}
|
}).Info(LangUtil.Get("Ts.SequenceIsStarting"));
|
}
|
|
public void StopBtnClick()
|
{
|
new MaskWindow((WindowX)Window.GetWindow(this),
|
(win) =>
|
{
|
try
|
{
|
bool stoped = StopSequence();
|
if (stoped)
|
{
|
IsRunning = false;
|
}
|
}
|
finally
|
{
|
Dispatcher.Invoke(() =>
|
{
|
win.Close();
|
});
|
}
|
}
|
).Info(LangUtil.Get("App.SequenceIsStopping"));
|
}
|
|
private bool StopSequence()
|
{
|
try
|
{
|
SequenceContext?.StationGlobals.SetValBoolean("StationState.StopTest", 1, true);
|
if (this.execution == null) return true;
|
return this.execution.WaitForEndEx(2000, true, null, null);
|
}
|
catch (Exception ex)
|
{
|
log.Error("Stop Sequence Failed.", ex);
|
MsgBoxHelper.Error(this, $"{LangUtil.Get("Ts.StopSequenceFail")}: {ex.Message}");
|
return false;
|
}
|
}
|
|
private void PluginControl_Loaded(object sender, RoutedEventArgs e)
|
{
|
new MaskWindow((WindowX)Window.GetWindow(this),
|
(win) =>
|
{
|
try
|
{
|
InitScanner();
|
isLoadOk = true;
|
StartSequence();
|
}
|
catch (Exception ex)
|
{
|
log.Error("TsExecution Loaded Failed.", ex);
|
Dispatcher.Invoke(() =>
|
{
|
MsgBoxHelper.Error(this, $"{LangUtil.Get("Ts.UserControlLoadFailed")}: {ex.Message}");
|
});
|
}
|
Dispatcher.Invoke(() =>
|
{
|
if (isLoadOk) Loaded -= PluginControl_Loaded;
|
});
|
}
|
).Info(LangUtil.Get("App.SequenceIsStarting"));
|
}
|
|
#region teststand初始化相关
|
/// <summary>
|
/// 启动测试序列
|
/// </summary>
|
private void StartSequence()
|
{
|
try
|
{
|
if (!isLoadOk) return;
|
engine?.Globals.SetValString("StationState.ProductModel", 1, SelectedProduct?.Name);
|
engine?.CommitGlobalsToDisk(promptOnSaveConflicts: false);
|
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);
|
IsRunning = true;
|
}
|
catch (Exception ex)
|
{
|
Dispatcher.Invoke(() =>
|
{
|
log.Error("Start Sequence Failed.", ex);
|
MsgBoxHelper.Error(this, $"{LangUtil.Get("Ts.StartSequenceFail")}: {ex.Message}");
|
});
|
}
|
}
|
|
/// <summary>
|
/// 初始化TestStand引擎
|
/// </summary>
|
private void InitTsEngine()
|
{
|
try
|
{
|
AxApplicationMgr = new AxApplicationMgr();
|
AxApplicationMgr.ExitApplication += new EventHandler(this.AxApplicationMgr_ExitApplication);
|
AxApplicationMgr.UIMessageEvent +=
|
new _ApplicationMgrEvents_UIMessageEventEventHandler(this.AxApplicationMgr_UIMessageEvent);
|
AxApplicationMgr.ExecutionClosed +=
|
new _ApplicationMgrEvents_ExecutionClosedEventHandler(this.AxApplicationMgr_ExecutionClosed);
|
((System.ComponentModel.ISupportInitialize)(AxApplicationMgr)).BeginInit();
|
host.Child = AxApplicationMgr;
|
((System.ComponentModel.ISupportInitialize)(AxApplicationMgr)).EndInit();
|
|
this.engine = this.AxApplicationMgr.GetEngine();
|
this.engine.PersistBreakpoints = false;
|
this.AxApplicationMgr.IsEditor = true;
|
this.AxApplicationMgr.LoginOnStart = false;
|
this.AxApplicationMgr.Start();
|
this.modeSeq = this.engine.GetSequenceFileEx(@"C:\Program Files\National Instruments\TestStand 2020\Components\Models\TestStandModels\ParallelModel.seq");
|
}
|
catch (Exception ex)
|
{
|
log.Error("InitTsEngine Failed.", ex);
|
throw ex;
|
}
|
}
|
|
/// <summary>
|
/// 退出应用
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void AxApplicationMgr_ExitApplication(object sender, EventArgs e)
|
{
|
//Environment.ExitCode = this.AxApplicationMgr.ExitCode;
|
//this.Close();
|
}
|
|
/// <summary>
|
/// 进程结束事件
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void AxApplicationMgr_ExecutionClosed(object sender, _ApplicationMgrEvents_ExecutionClosedEvent e)
|
{
|
try
|
{
|
if (this.testSeq == null)
|
return;
|
this.engine.ReleaseSequenceFileEx(this.testSeq, 0);
|
this.engine.ReleaseSequenceFileEx(this.modeSeq, 0);
|
this.engine.UnloadAllModules();
|
this.testSeq = null;
|
this.modeSeq = null;
|
}
|
catch (Exception ex)
|
{
|
log.Error("ReleaseSequenceFileEx Failed.", ex);
|
MsgBoxHelper.Error(Window.GetWindow(this), $"{LangUtil.Get("Ts.ReleaseSequenceFileFail")}: {ex.Message}");
|
}
|
}
|
|
/// <summary>
|
/// TestStand用户交互事件
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
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 = e.uiMsg.StringData;
|
|
try
|
{
|
log.Info($"Event: {EventCase}, NumericData: {MethodCode}, StringData: {strData}");
|
}
|
catch
|
{
|
|
}
|
|
if (EventCase != 10015) return;
|
switch (MethodCode)
|
{
|
case 0:
|
/// 设置句柄
|
this.SequenceContext = (SequenceContext)e.uiMsg.ActiveXData;
|
break;
|
case 1:
|
var arr1 = strData.Split(';');
|
int index1 = int.Parse(arr1[0]);
|
this.tsSockets[index1].SetStatus(arr1[1]);
|
break;
|
case 2:
|
var arr2 = strData.Split(';');
|
int index2 = int.Parse(arr2[0]);
|
this.tsSockets[index2].SetInfo(arr2[1]);
|
break;
|
default:
|
break;
|
}
|
}
|
catch (Exception ex)
|
{
|
log.Warn("Ts Event Error.", ex);
|
}
|
}
|
#endregion
|
|
|
}
|
}
|