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.Windows;
using System.Windows.Controls;
namespace Plugin.JarUI
{
///
/// UserControl1.xaml 的交互逻辑
///
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;
///
/// TS 引擎
///
private Engine engine = null;
private string testSeqFile = string.Empty;
///
/// 测试序列
///
private SequenceFile testSeq = null;
///
/// 测试模型序列
///
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 _products;
public ObservableCollection 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 socketMap = new Dictionary();
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 parameters = ProductManager.GetParametersByProductName(name);
testSeqFile = parameters.FirstOrDefault(p => p.Name == "TestSequence")?.Value?.ToString();
StartSequence();
}
private void InitProducts()
{
Products = ProductManager.GetProducts>();
if (Products != null && Products.Count > 0)
{
List parameters =
ParameterManager.GetCommonParameter>();
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;
}
}
///
/// 读取配置文件里的几个属性
///
///
///
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 扫码枪相关
///
/// 设置扫码枪
///
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初始化相关
///
/// 启动测试序列
///
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}");
});
}
}
///
/// 初始化TestStand引擎
///
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;
}
}
///
/// 退出应用
///
///
///
private void AxApplicationMgr_ExitApplication(object sender, EventArgs e)
{
//Environment.ExitCode = this.AxApplicationMgr.ExitCode;
//this.Close();
}
///
/// 进程结束事件
///
///
///
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}");
}
}
///
/// TestStand用户交互事件
///
///
///
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
}
}