| | |
| | | using HMI.Base; |
| | | using HMI.Core; |
| | | using HMI.Core.Api; |
| | | using HMI.Core.Entity; |
| | | using HMI.Core.Manager; |
| | | using HMI.Core.Setting; |
| | | using HMI.Core.Util; |
| | | using HMI.ParameterManage.Entity; |
| | | using HMI.ParameterManage.Util; |
| | | using HMI.UI; |
| | | using HMI.MQUtil; |
| | | using HMI.UI.Util; |
| | | using HMI.Util; |
| | | using log4net; |
| | | using NationalInstruments.TestStand.Interop.API; |
| | | using NationalInstruments.TestStand.Interop.UI.Ax; |
| | | using Panuon.WPF.UI; |
| | | using Plugin.TsSupport; |
| | | using ScottPlot; |
| | | using ScottPlot.AxisLimitManagers; |
| | | using ScottPlot.Plottables; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Collections.ObjectModel; |
| | | using System.ComponentModel; |
| | | using System.Drawing; |
| | | using System.IO; |
| | | using System.Linq; |
| | | using System.Runtime.InteropServices; |
| | | using System.Timers; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | |
| | | /// <summary> |
| | | /// UserControl1.xaml 的交互逻辑 |
| | | /// </summary> |
| | | public partial class TsExecution : PluginControl |
| | | public partial class TsExecution : PluginMaskControl |
| | | { |
| | | //private OpcInterface.OpcInterface OpcHandle = new OpcInterface.OpcInterface(); |
| | | #region TestStand事件 |
| | | /// <summary> |
| | | /// TS 引擎 |
| | |
| | | public AxApplicationMgr AxApplicationMgr; |
| | | private Execution execution = null; |
| | | |
| | | private SequenceContext sequenceContext = null; |
| | | |
| | | private Chart chart; |
| | | #endregion |
| | | |
| | | public static ILog logger { get; private set; } |
| | | private List<SingleControl> tsSockets = new List<SingleControl>(); |
| | | /// <summary> |
| | | /// 样件模式状态 |
| | |
| | | } |
| | | } |
| | | |
| | | private string _currentUserCode; |
| | | |
| | | public string CurrentUserCode |
| | | { |
| | | get { return _currentUserCode; } |
| | | set { Set(ref _currentUserCode, value); } |
| | | } |
| | | |
| | | |
| | | private bool isLoadOK = false; |
| | | private Timer GCTimer; |
| | | |
| | |
| | | |
| | | private ProductData selectedProduct; |
| | | |
| | | private MSMQHelper mSMQHelper = new MSMQHelper("HMI_Alarm"); |
| | | |
| | | public ProductData SelectedProduct |
| | | { |
| | | get { return selectedProduct; } |
| | | set |
| | | { |
| | | Set(ref selectedProduct, value); |
| | | CurrentProductModel = value?.Name; |
| | | if (tsSockets != null) |
| | | { |
| | | foreach (SingleControl socket in tsSockets) |
| | | { |
| | | socket.RefreshProduct(value); |
| | | } |
| | | } |
| | | SetTestSeqFile(value); |
| | | } |
| | | } |
| | | |
| | | private string currentProductModel; |
| | | public string CurrentProductModel |
| | | { |
| | | get => currentProductModel; |
| | | set |
| | | { |
| | | Set(ref currentProductModel, value); |
| | | } |
| | | } |
| | | |
| | | public override void SetLogger(ILog logger) |
| | | { |
| | | base.SetLogger(logger); |
| | | TsExecution.logger = logger; |
| | | } |
| | | |
| | | private ObservableCollection<ProductData> products; |
| | |
| | | } |
| | | } |
| | | |
| | | public List<double> FontSizeSource { get; set; } = new List<double> { |
| | | 10,11,12,13,14,15,16,17,18,19,20 |
| | | }; |
| | | |
| | | private Pie pie; |
| | | private string CountIniPath; |
| | | private bool IsOptRequirePassword; |
| | | |
| | | private bool alarmVisiable; |
| | | public bool AlarmVisiable |
| | |
| | | } |
| | | } |
| | | |
| | | private bool _enableMes; |
| | | public bool EnableMes |
| | | { |
| | | get => _enableMes; |
| | | set |
| | | { |
| | | if (RequirePassword() == true) |
| | | { |
| | | if (WriteConfig("EnableMes", value)) |
| | | { |
| | | Set(ref _enableMes, value); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | private bool _enableCanLog; |
| | | public bool EnableCanLog |
| | | { |
| | | get => _enableCanLog; |
| | | set |
| | | { |
| | | if (WriteConfig("EnableCanLog", value)) |
| | | { |
| | | Set(ref _enableCanLog, value); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private bool _enableDebugMode; |
| | | public bool EnableDebugMode |
| | | { |
| | | get => _enableDebugMode; |
| | | set |
| | | { |
| | | if (RequirePassword() == true) |
| | | { |
| | | if (WriteConfig("EnableDebugMode", value)) |
| | | { |
| | | Set(ref _enableDebugMode, value); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | private bool _enableNGPause; |
| | | public bool EnableNGPause |
| | | { |
| | | get => _enableNGPause; |
| | | set |
| | | { |
| | | if (RequirePassword() == true) |
| | | { |
| | | if (WriteConfig("EnableNGPause", value)) |
| | | { |
| | | Set(ref _enableNGPause, value); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | private bool _enableSimpleMode; |
| | | public bool EnableSimpleMode |
| | | { |
| | | get => _enableSimpleMode; |
| | | set |
| | | { |
| | | if (WriteConfig("EnableSimpleMode", value)) |
| | | { |
| | | Set(ref _enableSimpleMode, value); |
| | | foreach (var cell in tsSockets) cell.SetSimpleUI(value); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private bool _ui_showInfoDock; |
| | | public bool UI_ShowInfoDock |
| | | { |
| | | get => _ui_showInfoDock; |
| | | set |
| | | { |
| | | if (WriteConfig("UI_ShowInfoDock", value)) |
| | | { |
| | | Set(ref _ui_showInfoDock, value); |
| | | detailPanel.Visibility = value ? Visibility.Visible : Visibility.Collapsed; |
| | | } |
| | | } |
| | | } |
| | | |
| | | private bool autoExecuteSeq; |
| | | public bool AutoExecuteSeq |
| | | { |
| | | get => autoExecuteSeq; |
| | | set |
| | | { |
| | | Set(ref autoExecuteSeq, value); |
| | | } |
| | | } |
| | | |
| | | private string currentWorkorder; |
| | | public string CurrentWorkorder |
| | | { |
| | | get => currentWorkorder; |
| | | set |
| | | { |
| | | if (WriteIni("UI_CurrentWorkorder", value)) |
| | | { |
| | | Set(ref currentWorkorder, value); |
| | | engine?.Globals.SetValString("StationState.WorkOrder", 1, value); |
| | | engine?.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private bool _DisableScanner; |
| | | public bool DisableScanner |
| | | { |
| | | get => _DisableScanner; |
| | | set |
| | | { |
| | | if (WriteConfig("DisableScanner", value)) |
| | | { |
| | | Set(ref _DisableScanner, value); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private string tsModelPath; |
| | | private string dataLogPath; |
| | | private SqliteHelper sqliteHelper; |
| | | |
| | | private MQConnector mqConnector; |
| | | private int probeWarn; |
| | | |
| | | public TsExecution() |
| | | { |
| | | DataContext = this; |
| | | GCTimer = new Timer(); |
| | | InitializeComponent(); |
| | | |
| | | InitChart(); |
| | | InitTsEngine(); |
| | | //初始化TestStand引擎 |
| | | this.InitTestStandEngine(); |
| | | |
| | | } |
| | | |
| | | public override void SetBaseFolder(string folder) |
| | |
| | | base.SetBaseFolder(folder); |
| | | } |
| | | |
| | | private void CheckSqlHelper() |
| | | { |
| | | string today = DateTime.Now.ToString("yyyyMMdd"); |
| | | string dbPath = Path.Combine(dataLogPath, $"Data_{today}.db"); |
| | | if (!File.Exists(dbPath)) |
| | | { |
| | | SqliteHelper.CreateDatabase(dbPath); |
| | | } |
| | | if (sqliteHelper == null || sqliteHelper.DataBaseFile != dbPath) |
| | | { |
| | | sqliteHelper?.Dispose(); |
| | | sqliteHelper = new SqliteHelper(dbPath); |
| | | sqliteHelper.ExecuteSql(@"CREATE TABLE IF NOT EXISTS serialData ( |
| | | id INTEGER PRIMARY KEY AUTOINCREMENT, |
| | | sn TEXT NOT NULL, |
| | | model TEXT, |
| | | station TEXT NOT NULL, |
| | | step TEXT NOT NULL, |
| | | position TEXT, |
| | | limitDown TEXT, |
| | | limitUp TEXT, |
| | | unit TEXT, |
| | | offset TEXT, |
| | | value TEXT, |
| | | status TEXT, |
| | | finalStatus TEXT, |
| | | consumeTime TEXT, |
| | | totalConsumeTime TEXT, |
| | | time DATETIME NOT NULL);"); |
| | | sqliteHelper.ExecuteSql(@"CREATE TABLE IF NOT EXISTS testResult ( |
| | | id INTEGER PRIMARY KEY AUTOINCREMENT, |
| | | sn TEXT NOT NULL, |
| | | model TEXT, |
| | | station TEXT NOT NULL, |
| | | position TEXT, |
| | | status TEXT, |
| | | result TEXT NOT NULL, |
| | | time DATETIME NOT NULL);"); |
| | | } |
| | | } |
| | | |
| | | public override void InitFinish() |
| | | { |
| | | this.ReadCount(out int pass, out int fail); |
| | | this.DisplayCount(pass, fail); |
| | | UpdateChart(pass, fail); |
| | | ReadConfig(); |
| | | InitProducts(); |
| | | CheckSqlHelper(); |
| | | base.InitFinish(); |
| | | |
| | | if (ParamSetting.EnableAutoModel) |
| | | { |
| | | selectModelPanel.Visibility = Visibility.Collapsed; |
| | | autoModelPanel.Visibility = Visibility.Visible; |
| | | CurrentProductModel = string.Empty; |
| | | } |
| | | |
| | | try |
| | | { |
| | | UserInfo user = UserInfo.User; |
| | | CurrentUserCode = user?.Code; |
| | | engine?.Globals.SetValString("StationState.OPID", 1, CurrentUserCode); |
| | | engine?.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Warn("Get Login User Failed.", ex); |
| | | } |
| | | } |
| | | |
| | | private void InitMQ() |
| | | { |
| | | mqConnector = new MQConnector("UI"); |
| | | mqConnector.BeginReceive(HandleMQUI); |
| | | } |
| | | |
| | | void HandleMQUI(string msg) |
| | | { |
| | | string[] arr = msg.Split('|'); |
| | | int eventCode = int.Parse(arr[0]); |
| | | int index = int.Parse(arr[1]); |
| | | string strData = arr[2]; |
| | | Dispatcher.BeginInvoke(new Action(() => |
| | | { |
| | | HandleUIMessage(eventCode, index, strData); |
| | | })); |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | { |
| | | pieChart.Plot.Axes.Frameless(); |
| | | pieChart.Plot.HideGrid(); |
| | | pieChart.Plot.DataBackground.Color = Colors.Transparent; |
| | | pieChart.Plot.DataBackground.Color = ScottPlot.Colors.Transparent; |
| | | |
| | | var legend = pieChart.Plot.ShowLegend(Alignment.UpperRight); |
| | | legend.Alignment = Alignment.UpperRight; |
| | | legend.Padding = new PixelPadding(0); |
| | | legend.FontSize = (float)CustomFontSizeConverter.CountFontSize(20, 300, 300); |
| | | legend.FontSize = (float)WidthSizeConverter.CountFontSize(20, 300, 300); |
| | | pieChart.UserInputProcessor.Disable(); |
| | | pieChart.Plot.Font.Automatic(); |
| | | |
| | | List<PieSlice> slices = new List<PieSlice> { |
| | | new PieSlice() { Value = 5, FillColor = Colors.Green, |
| | | LabelFontSize = (float)CustomFontSizeConverter.CountFontSize(20,300,300), |
| | | new PieSlice() { Value = 5, FillColor = ScottPlot.Colors.Green, |
| | | LabelFontSize = (float)WidthSizeConverter.CountFontSize(20,300,300), |
| | | Label = "Pass",LegendText="Pass" }, |
| | | new PieSlice() { Value = 2, FillColor = Colors.Red, |
| | | LabelFontSize = (float)CustomFontSizeConverter.CountFontSize(20,300,300), |
| | | new PieSlice() { Value = 2, FillColor = ScottPlot.Colors.Red, |
| | | LabelFontSize = (float)WidthSizeConverter.CountFontSize(20,300,300), |
| | | Label = "Fail",LegendText="Fail" } }; |
| | | |
| | | |
| | | pie = pieChart.Plot.Add.Pie(slices); |
| | | } |
| | | |
| | | private bool? RequirePassword() |
| | | { |
| | | if (!IsOptRequirePassword) return true; |
| | | var win = new RequirePasswordWindow |
| | | { |
| | | Owner = Window.GetWindow(this) |
| | | }; |
| | | return win.ShowDialog(); |
| | | } |
| | | |
| | | private void InitProducts() |
| | | { |
| | | Products = ParameterManager.GetProducts<ObservableCollection<ProductData>>(); |
| | | 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(); |
| | | if (!string.IsNullOrEmpty(tmpNum)) |
| | | string lastModel = engine?.Globals.GetValString("StationState.ProductModel", 1); |
| | | var tempProduct = Products[0]; |
| | | if (!string.IsNullOrEmpty(lastModel)) |
| | | { |
| | | this.socketNum = Convert.ToInt32(tmpNum); |
| | | var product = Products.FirstOrDefault(p => p.Name == lastModel); |
| | | if (product != null) |
| | | { |
| | | tempProduct = product; |
| | | } |
| | | } |
| | | SelectedProduct = Products[0]; |
| | | RefershUI(); |
| | | SelectedProduct = tempProduct; |
| | | } |
| | | RefershUI(); |
| | | if (tsSockets != null) |
| | | { |
| | | foreach (SingleControl socket in tsSockets) |
| | | { |
| | | socket.RefreshProduct(SelectedProduct); |
| | | } |
| | | } |
| | | SampleStatus = false; |
| | | } |
| | | |
| | | private bool _isTesting = false; |
| | | public bool IsTesting |
| | | { |
| | | get { return _isTesting; } |
| | | set |
| | | { |
| | | Set(ref _isTesting, value); |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | BtnStartSeq.IsEnabled = !value; |
| | | BtnStopSeq.IsEnabled = value; |
| | | CbProduct.IsEnabled = !value; |
| | | }); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | /// </summary> |
| | | private void InitTsEngine() |
| | | { |
| | | 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); |
| | | AxApplicationMgr = TestAppManager.GetAxApplicationMgr(); |
| | | |
| | | |
| | | //AxApplicationMgr. += AxApplicationMgr_EndExecution; |
| | | AxApplicationMgr.EndExecution += AxApplicationMgr_EndExecution; |
| | | |
| | | AxApplicationMgr.ExitApplication += this.AxApplicationMgr_ExitApplication; |
| | | AxApplicationMgr.UIMessageEvent += this.AxApplicationMgr_UIMessageEvent; |
| | | AxApplicationMgr.ExecutionClosed += this.AxApplicationMgr_ExecutionClosed; |
| | | |
| | | ((System.ComponentModel.ISupportInitialize)(AxApplicationMgr)).BeginInit(); |
| | | host.Child = AxApplicationMgr; |
| | | ((System.ComponentModel.ISupportInitialize)(AxApplicationMgr)).EndInit(); |
| | | } |
| | | |
| | | private volatile bool canSwitchModel = false; |
| | | private volatile Action switchAction = null; |
| | | |
| | | private void AxApplicationMgr_EndExecution(object sender, _ApplicationMgrEvents_EndExecutionEvent e) |
| | | { |
| | | log.Info("AxApplicationMgr_EndExecution"); |
| | | if (ReleaseSequenceFile()) |
| | | { |
| | | IsTesting = false; |
| | | log.Info("Release SeqFile Success!"); |
| | | if (canSwitchModel) switchAction?.Invoke(); |
| | | } |
| | | else |
| | | { |
| | | log.Warn("Release SeqFile Fail!"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 进程结束事件 |
| | | /// </summary> |
| | | /// <param name="sender"></param> |
| | | /// <param name="e"></param> |
| | | private void AxApplicationMgr_ExecutionClosed(object sender, _ApplicationMgrEvents_ExecutionClosedEvent e) |
| | | { |
| | | //ReleaseSequenceFile(); |
| | | } |
| | | |
| | | private void PluginControl_Loaded(object sender, RoutedEventArgs e) |
| | | { |
| | | new MaskWindow((WindowX)Window.GetWindow(this), |
| | | (win) => |
| | | ShowMask(() => |
| | | { |
| | | try |
| | | { |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | try |
| | | { |
| | | //连接OPChandle |
| | | //this.OpcHandle.Connect2("127.0.0.1", 6543, 18081, out string ErrMsg, null); |
| | | //启动测试进程 |
| | | StartSequence(); |
| | | isLoadOK = true; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Error("TsExecution Loaded Failed.", ex); |
| | | MsgBoxHelper.Error(this, $"{LangUtil.Get("Ts.UserControlLoadFailed")}: {ex.Message}"); |
| | | } |
| | | //Dispatcher.Invoke(() => |
| | | //{ |
| | | |
| | | try |
| | | { |
| | | if (Environment.Version.ToString() != this.AxApplicationMgr.GetEngine().DotNetCLRVersion) |
| | | this.GCTimer.Enabled = true; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Error("TsExecution GCTimer Start Failed", ex); |
| | | MsgBoxHelper.Error(this, $"{LangUtil.Get("Ts.LoadFailed")}: {ex.Message}"); |
| | | } |
| | | finally |
| | | { |
| | | win.Close(); |
| | | } |
| | | if (isLoadOK) Loaded -= PluginControl_Loaded; |
| | | }); |
| | | //}); |
| | | isLoadOK = true; |
| | | if (AutoExecuteSeq) StartSequence(); |
| | | } |
| | | ).Info(LangUtil.Get("App.UsercontrolIsLoading")); |
| | | catch (Exception ex) |
| | | { |
| | | log.Error("TsExecution Loaded Failed.", ex); |
| | | MsgBoxHelper.Error(this, $"{LangUtil.Get("Ts.UserControlLoadFailed")}: {ex.Message}"); |
| | | } |
| | | |
| | | try |
| | | { |
| | | if (Environment.Version.ToString() != this.AxApplicationMgr.GetEngine().DotNetCLRVersion) |
| | | this.GCTimer.Enabled = true; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Error("TsExecution GCTimer Start Failed", ex); |
| | | MsgBoxHelper.Error(this, $"{LangUtil.Get("Ts.LoadFailed")}: {ex.Message}"); |
| | | } |
| | | |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | if (isLoadOK) Loaded -= PluginControl_Loaded; |
| | | }); |
| | | }, (ex) => |
| | | { |
| | | ToastHelper.Error("Loaded Failed."); |
| | | log.Error("Loaded Error.", ex); |
| | | }, null, LangUtil.Get("App.UsercontrolIsLoading")); |
| | | |
| | | //new MaskWindow((WindowX)Window.GetWindow(this), |
| | | // (win) => |
| | | // { |
| | | // try |
| | | // { |
| | | // Dispatcher.Invoke(() => |
| | | // { |
| | | // try |
| | | // { |
| | | // UserInfo user = UserInfo.User; |
| | | // CurrentUserCode = user?.Code; |
| | | // } |
| | | // catch (Exception ex) |
| | | // { |
| | | // log.Warn("Get Login User Failed.", ex); |
| | | // } |
| | | // }); |
| | | // isLoadOK = true; |
| | | // if (AutoExecuteSeq) StartSequence(); |
| | | // } |
| | | // catch (Exception ex) |
| | | // { |
| | | // log.Error("TsExecution Loaded Failed.", ex); |
| | | // MsgBoxHelper.Error(this, $"{LangUtil.Get("Ts.UserControlLoadFailed")}: {ex.Message}"); |
| | | // } |
| | | |
| | | // try |
| | | // { |
| | | // if (Environment.Version.ToString() != this.AxApplicationMgr.GetEngine().DotNetCLRVersion) |
| | | // this.GCTimer.Enabled = true; |
| | | // } |
| | | // catch (Exception ex) |
| | | // { |
| | | // log.Error("TsExecution GCTimer Start Failed", ex); |
| | | // MsgBoxHelper.Error(this, $"{LangUtil.Get("Ts.LoadFailed")}: {ex.Message}"); |
| | | // } |
| | | |
| | | // Dispatcher.Invoke(() => |
| | | // { |
| | | // if (isLoadOK) Loaded -= PluginControl_Loaded; |
| | | // }); |
| | | // } |
| | | // ).Info(LangUtil.Get("App.UsercontrolIsLoading")); |
| | | } |
| | | |
| | | private void RefershUI() |
| | | { |
| | | panel.Children.Clear(); |
| | | string[] names = ParamSetting.SocketNames.Split(','); |
| | | |
| | | //重新生成子面板 |
| | | for (int i = 0; i < this.socketNum; i++) |
| | | { |
| | | SingleControl control = new SingleControl(i, CountIniPath); |
| | | string name = string.Empty; |
| | | if (i < names.Length) |
| | | { |
| | | name = names[i]; |
| | | } |
| | | |
| | | SingleControl control = new SingleControl(i, CountIniPath, this.probeWarn) |
| | | { |
| | | SocketName = name |
| | | }; |
| | | panel.Children.Add(control); |
| | | tsSockets.Add(control); |
| | | |
| | | //createChildInNewThread(i, CountIniPath, ProbeWarn); |
| | | } |
| | | if (tsSockets.Count == 1) |
| | | { |
| | | panel.Columns = 1; |
| | | } |
| | | else if (tsSockets.Count > 0 && (tsSockets.Count % 3) == 0) |
| | | { |
| | | panel.Columns = 3; |
| | | } |
| | | else |
| | | { |
| | |
| | | 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"); |
| | | //this.modeSeq = this.engine.GetSequenceFileEx(@"C:\Program Files\National Instruments\TestStand 2020\Components\Models\TestStandModels\ParallelModel.seq"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | |
| | | /// <param name="fail">不合格数</param> |
| | | private void ReadCount(out int pass, out int fail) |
| | | { |
| | | pass = Convert.ToInt32(IniFileHelper.ReadIniData("Count", "Pass", "", CountIniPath)); |
| | | fail = Convert.ToInt32(IniFileHelper.ReadIniData("Count", "Fail", "", CountIniPath)); |
| | | pass = Convert.ToInt32(IniFileHelper.ReadIniData("Count", "Pass", "0", CountIniPath)); |
| | | fail = Convert.ToInt32(IniFileHelper.ReadIniData("Count", "Fail", "0", CountIniPath)); |
| | | var fontSize = Convert.ToDouble(IniFileHelper.ReadIniData("Config", "TableFontSize", "12", CountIniPath)); |
| | | this.Resources["tableFontSize"] = 20d; |
| | | //CbFontSize.SelectedItem = fontSize; |
| | | } |
| | | |
| | | private void WriteCount(int pass, int fail) |
| | | private string csvDir; |
| | | |
| | | /// <summary> |
| | | /// 读取配置文件里的几个属性 |
| | | /// </summary> |
| | | /// <param name="pass"></param> |
| | | /// <param name="fail"></param> |
| | | private void ReadConfig() |
| | | { |
| | | ParameterData value; |
| | | |
| | | |
| | | bool flag = false; |
| | | try |
| | | { |
| | | value = ParameterManager.GetCommonParameterByName("DefaultEnableMes"); |
| | | if (value != null) |
| | | { |
| | | flag = bool.Parse(value.Value); |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | flag = false; |
| | | } |
| | | |
| | | try |
| | | { |
| | | value = ParameterManager.GetCommonParameterByName("SocketNum"); |
| | | if (value != null) |
| | | { |
| | | this.socketNum = int.Parse(value.Value); |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | this.socketNum = 2; |
| | | } |
| | | |
| | | if (flag) |
| | | { |
| | | EnableMes = true; |
| | | } |
| | | else |
| | | { |
| | | try |
| | | { |
| | | value = ParameterManager.GetCommonParameterByName("EnableMes"); |
| | | if (value == null) |
| | | { |
| | | CbEnableMes.Visibility = Visibility.Collapsed; |
| | | } |
| | | else |
| | | { |
| | | _enableMes = bool.Parse(value.Value); |
| | | Set("EnableMes"); |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | _enableMes = false; |
| | | Set("EnableMes"); |
| | | } |
| | | } |
| | | |
| | | |
| | | try |
| | | { |
| | | value = ParameterManager.GetCommonParameterByName("EnableNGPause"); |
| | | if (value == null) |
| | | { |
| | | CbEnableNGPause.Visibility = Visibility.Collapsed; |
| | | } |
| | | else |
| | | { |
| | | _enableNGPause = bool.Parse(value.Value); |
| | | Set("EnableNGPause"); |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | _enableNGPause = false; |
| | | Set("EnableNGPause"); |
| | | } |
| | | |
| | | try |
| | | { |
| | | value = ParameterManager.GetCommonParameterByName("EnableDebugMode"); |
| | | if (value == null) |
| | | { |
| | | CbEnableDebugMode.Visibility = Visibility.Collapsed; |
| | | } |
| | | else |
| | | { |
| | | _enableDebugMode = bool.Parse(value.Value); |
| | | Set("EnableDebugMode"); |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | _enableDebugMode = false; |
| | | Set("EnableDebugMode"); |
| | | } |
| | | |
| | | try |
| | | { |
| | | value = ParameterManager.GetCommonParameterByName("DisableScanner"); |
| | | if (value == null) |
| | | { |
| | | CbDisableScanner.Visibility = Visibility.Collapsed; |
| | | } |
| | | else |
| | | { |
| | | _DisableScanner = bool.Parse(value.Value); |
| | | Set("DisableScanner"); |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | _DisableScanner = false; |
| | | Set("DisableScanner"); |
| | | } |
| | | |
| | | try |
| | | { |
| | | value = ParameterManager.GetCommonParameterByName("EnableCanLog"); |
| | | _enableCanLog = bool.Parse(value.Value); |
| | | Set("EnableCanLog"); |
| | | } |
| | | catch |
| | | { |
| | | _enableCanLog = false; |
| | | Set("EnableCanLog"); |
| | | } |
| | | |
| | | |
| | | try |
| | | { |
| | | value = ParameterManager.GetCommonParameterByName("EnableSimpleMode"); |
| | | if (value == null) |
| | | { |
| | | CbEnableSimpleMode.Visibility = Visibility.Collapsed; |
| | | } |
| | | else |
| | | { |
| | | EnableSimpleMode = bool.Parse(value.Value); |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | EnableSimpleMode = false; |
| | | } |
| | | |
| | | try |
| | | { |
| | | value = ParameterManager.GetCommonParameterByName("UI_ShowInfoDock"); |
| | | if (value == null) |
| | | { |
| | | CbUI_ShowInfoDock.Visibility = Visibility.Collapsed; |
| | | } |
| | | else |
| | | { |
| | | UI_ShowInfoDock = bool.Parse(value.Value); |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | UI_ShowInfoDock = false; |
| | | } |
| | | |
| | | try |
| | | { |
| | | value = ParameterManager.GetCommonParameterByName("AutoExecuteSeq"); |
| | | AutoExecuteSeq = bool.Parse(value.Value); |
| | | } |
| | | catch |
| | | { |
| | | AutoExecuteSeq = true; |
| | | } |
| | | |
| | | try |
| | | { |
| | | |
| | | value = ParameterManager.GetCommonParameterByName("TestReportFolder"); |
| | | csvDir = value.Value; |
| | | if (!Directory.Exists(csvDir)) |
| | | { |
| | | Directory.CreateDirectory(csvDir); |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | csvDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TestReport"); |
| | | } |
| | | |
| | | try |
| | | { |
| | | |
| | | value = ParameterManager.GetCommonParameterByName("IsOptRequirePassword"); |
| | | IsOptRequirePassword = bool.Parse(value.Value); |
| | | } |
| | | catch |
| | | { |
| | | IsOptRequirePassword = false; |
| | | } |
| | | |
| | | try |
| | | { |
| | | |
| | | value = ParameterManager.GetCommonParameterByName("UI_CurrentWorkorder"); |
| | | CurrentWorkorder = value.Value; |
| | | } |
| | | catch |
| | | { |
| | | CurrentWorkorder = string.Empty; |
| | | } |
| | | |
| | | try |
| | | { |
| | | |
| | | value = ParameterManager.GetCommonParameterByName("TS_ShowTitleWorkorder"); |
| | | var boo = bool.Parse(value.Value); |
| | | if (boo) |
| | | { |
| | | workorderPanel.Visibility = Visibility.Visible; |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | } |
| | | |
| | | dataLogPath = ParamSetting.DataLogFolder; |
| | | |
| | | try |
| | | { |
| | | |
| | | value = ParameterManager.GetCommonParameterByName("TsModelPath"); |
| | | tsModelPath = 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" |
| | | tsModelPath = @"C:\Users\Public\Documents\National Instruments\TestStand 2020 (64-bit)\Components\Models\ParallelModel.seq"; |
| | | } |
| | | |
| | | try |
| | | { |
| | | |
| | | value = ParameterManager.GetCommonParameterByName("ProbeWarn"); |
| | | probeWarn = int.Parse(value?.Value); |
| | | } |
| | | catch |
| | | { |
| | | probeWarn = 0; |
| | | } |
| | | //Convert.ToBoolean(IniFileHelper.ReadIniData("Config", "EnableMes", "true", CountIniPath)); |
| | | //EnableCanLog = Convert.ToBoolean(IniFileHelper.ReadIniData("Config", "EnableCanLog", "true", CountIniPath)); |
| | | //EnableDebugMode = Convert.ToBoolean(IniFileHelper.ReadIniData("Config", "EnableDebugMode", "true", CountIniPath)); |
| | | } |
| | | |
| | | private bool WriteConfig(string name, bool value) |
| | | { |
| | | try |
| | | { |
| | | if (ParameterManager.UpdateCommonParameter(name, value, out string errMsg)) |
| | | { |
| | | foreach (var ts in tsSockets) |
| | | { |
| | | ts?.SequenceFileContext?.StationGlobals.SetValBoolean($"SystemSetting.{name}", 1, value); |
| | | if (ts?.SequenceFileContext?.Sequence != null) |
| | | { |
| | | ts.SequenceFileContext.Sequence.FailureAction = |
| | | value ? FailureActions.FailureAction_None : FailureActions.FailureAction_GotoCleanup; |
| | | } |
| | | } |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | throw new Exception(errMsg); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | MsgBoxHelper2.Error(ex.Message); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | private bool WriteIni(string name, object value) |
| | | { |
| | | //IniFileHelper.WriteIniData("Config", name, value.ToString(), CountIniPath); |
| | | try |
| | | { |
| | | if (ParameterManager.UpdateCommonParameter(name, value, out string errMsg)) |
| | | { |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | throw new Exception(errMsg); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | MsgBoxHelper2.Error(ex.Message); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | private void WriteCount(double pass, double fail) |
| | | { |
| | | IniFileHelper.WriteIniData("Count", "Pass", pass.ToString(), CountIniPath); |
| | | IniFileHelper.WriteIniData("Count", "Fail", fail.ToString(), CountIniPath); |
| | |
| | | /// </summary> |
| | | /// <param name="pass">合格数</param> |
| | | /// <param name="fail">不合格数</param> |
| | | private void DisplayCount(int pass, int fail) |
| | | private void DisplayCount(double pass, double fail) |
| | | { |
| | | int total = pass + fail; |
| | | double total = pass + fail; |
| | | double passRate; |
| | | if (total == 0) |
| | | { |
| | |
| | | this.TbFail.Text = fail.ToString(); |
| | | this.TbTotal.Text = total.ToString(); |
| | | this.TbPassRate.Text = string.Format("{0:0.00}", passRate) + "%"; |
| | | |
| | | pie.Slices[0].Value = pass; |
| | | pie.Slices[1].Value = fail; |
| | | pieChart.Refresh(); |
| | | |
| | | WriteCount(pass, fail); |
| | | } |
| | | |
| | |
| | | /// </summary> |
| | | private void StartSequence() |
| | | { |
| | | //MaskWindow mask = new MaskWindow(); |
| | | try |
| | | if (!isLoadOK) return; |
| | | engine?.Globals.SetValBoolean("StationState.StopTest", 0, false); |
| | | if (ParamSetting.EnableAutoModel) |
| | | { |
| | | 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); |
| | | |
| | | Dispatcher.Invoke(() => |
| | | try |
| | | { |
| | | this.CbProduct.IsEnabled = false; |
| | | this.BtnStartSeq.IsEnabled = false; |
| | | this.BtnStopSeq.IsEnabled = true; |
| | | }); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Dispatcher.Invoke(() => |
| | | var path = ParameterManager.GetCommonParameterByName<string>("CommonMainSeq", ""); |
| | | if (string.IsNullOrEmpty(path)) |
| | | { |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | MsgBoxHelper.Error(this, $"请先设置CommonMainSeq参数"); |
| | | }); |
| | | return; |
| | | } |
| | | this.testSeqFile = path; |
| | | this.modeSeq = this.engine.GetSequenceFileEx(tsModelPath); |
| | | this.testSeq = this.engine.GetSequenceFileEx(this.testSeqFile, 2, TypeConflictHandlerTypes.ConflictHandler_UseGlobalType); |
| | | this.execution = this.engine.NewExecution(this.testSeq, "Test UUTs", this.modeSeq, false, 0, null, null, null); |
| | | IsTesting = true; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Error("Start Sequence Failed.", ex); |
| | | MsgBoxHelper.Error(this, $"{LangUtil.Get("Ts.StartSequenceFail")}: {ex.Message}"); |
| | | }); |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | log.Error("Start Sequence Failed.", ex); |
| | | MsgBoxHelper.Error(this, $"{LangUtil.Get("Ts.StartSequenceFail")}: {ex.Message}"); |
| | | }); |
| | | } |
| | | } |
| | | finally |
| | | else |
| | | { |
| | | //MaskWindow mask = new MaskWindow(); |
| | | try |
| | | { |
| | | engine?.Globals.SetValString("StationState.ProductModel", 1, CurrentProductModel); |
| | | engine?.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | | this.modeSeq = this.engine.GetSequenceFileEx(tsModelPath); |
| | | this.testSeq = this.engine.GetSequenceFileEx(this.testSeqFile, 2, TypeConflictHandlerTypes.ConflictHandler_UseGlobalType); |
| | | this.execution = this.engine.NewExecution(this.testSeq, "Test UUTs", this.modeSeq, false, 0, null, null, null); |
| | | IsTesting = true; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | log.Error("Start Sequence Failed.", ex); |
| | | MsgBoxHelper.Error(this, $"{LangUtil.Get("Ts.StartSequenceFail")}: {ex.Message}"); |
| | | }); |
| | | } |
| | | finally |
| | | { |
| | | |
| | | } |
| | | } |
| | | } |
| | | |
| | | public void StopSequenceClick() |
| | | { |
| | | new MaskWindow((WindowX)Window.GetWindow(this), |
| | | (win) => |
| | | { |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | try |
| | | { |
| | | StopSequence(); |
| | | } |
| | | finally |
| | | { |
| | | win.Close(); |
| | | } |
| | | }); |
| | | } |
| | | ).Info(LangUtil.Get("App.SequenceIsStopping")); |
| | | canSwitchModel = false; |
| | | switchAction = null; |
| | | ShowMask(() => |
| | | { |
| | | bool stoped = StopSequence(); |
| | | }, null, null, LangUtil.Get("App.SequenceIsStopping")); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 停止测试序列 |
| | | /// </summary> |
| | | private void StopSequence() |
| | | private bool StopSequence() |
| | | { |
| | | try |
| | | { |
| | | if (this.tsSockets.Count > 0 && this.tsSockets[0]?.SequenceFileContext != null) |
| | | if (this.tsSockets.Count > 0) |
| | | { |
| | | bool val = this.tsSockets[0].SequenceFileContext.StationGlobals.Exists("StationState.StopTest", 0); |
| | | if (val) |
| | | for (int i = 0; i < tsSockets.Count; i++) |
| | | { |
| | | tsSockets[0].SequenceFileContext.StationGlobals.SetValBoolean("StationState.StopTest", 0, true); |
| | | bool isStop = this.execution.WaitForEndEx(2000, true, null, null); |
| | | var context = this.tsSockets[i].SequenceFileContext; |
| | | context?.StationGlobals.SetValBoolean("StationState.StopTest", 1, true); |
| | | } |
| | | } |
| | | this.CbProduct.IsEnabled = true; |
| | | this.BtnStartSeq.IsEnabled = true; |
| | | this.BtnStopSeq.IsEnabled = false; |
| | | if (this.execution == null) return true; |
| | | |
| | | //bool res = this.execution.WaitForEndEx(-1, true, null, null); |
| | | bool res = this.execution?.WaitForEndEx(-1, true, Type.Missing, null) == true; |
| | | Marshal.ReleaseComObject(this.execution); |
| | | this.execution = null; |
| | | return res; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Error("Stop Sequence Failed.", ex); |
| | | MsgBoxHelper.Error(this, $"{LangUtil.Get("Ts.StopSequenceFail")}: {ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | private void StartClick() |
| | | { |
| | | new MaskWindow(Window.GetWindow(this), |
| | | (win) => |
| | | { |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | try |
| | | { |
| | | StartSequence(); |
| | | } |
| | | finally |
| | | { |
| | | win.Close(); |
| | | } |
| | | }); |
| | | }).Info(LangUtil.Get("Ts.SequenceIsStarting")); |
| | | canSwitchModel = true; |
| | | ShowMask(() => |
| | | { |
| | | StartSequence(); |
| | | }, null, null, LangUtil.Get("Ts.SequenceIsStarting")); |
| | | //new MaskWindow(Window.GetWindow(this), |
| | | // (win) => |
| | | // { |
| | | // try |
| | | // { |
| | | // StartSequence(); |
| | | // } |
| | | // catch (Exception ex) { |
| | | |
| | | // } |
| | | // finally |
| | | // { |
| | | // win.Dispatcher.Invoke(() => |
| | | // { |
| | | // win.Close(); |
| | | // }); |
| | | // } |
| | | // }).Info(LangUtil.Get("Ts.SequenceIsStarting")); |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | //this.Close(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 进程结束事件 |
| | | /// </summary> |
| | | /// <param name="sender"></param> |
| | | /// <param name="e"></param> |
| | | private void AxApplicationMgr_ExecutionClosed(object sender, NationalInstruments.TestStand.Interop.UI.Ax._ApplicationMgrEvents_ExecutionClosedEvent e) |
| | | public void UpdatePositionStatus(int index, string status) |
| | | { |
| | | try |
| | | this.tsSockets[index].UpdateStatus(status); |
| | | this.UpdateTestCounter(); |
| | | } |
| | | |
| | | public void UpdatePositionProcessValue(int index, int value) |
| | | { |
| | | this.tsSockets[index].SetTestProcess(value); |
| | | } |
| | | |
| | | public void PausePosition(int index) |
| | | { |
| | | this.tsSockets[index].ShowPausePanel(); |
| | | } |
| | | |
| | | public void AddTestData(int index, string data) |
| | | { |
| | | string[] TestItems = data.Split(','); |
| | | tsSockets[index].AddTestData(TestItems[0], TestItems[1], TestItems[2], TestItems[3], |
| | | TestItems[4], TestItems[5], TestItems[6]); |
| | | } |
| | | |
| | | public void SetPositionBarcode(int index, string strData) |
| | | { |
| | | if (strData.Contains(";")) |
| | | { |
| | | if (this.testSeq == null) |
| | | var strs = strData.Split(';'); |
| | | this.tsSockets[index].Barcode = strs[0]; |
| | | this.tsSockets[index].Model = strs[1]; |
| | | } |
| | | else |
| | | { |
| | | this.tsSockets[index].Barcode = strData; |
| | | } |
| | | } |
| | | |
| | | public void SavePositionCSV(int index, string csvPath) |
| | | { |
| | | //var time = DateTime.Now; |
| | | //string status = this.tsSockets[index].Status == "Passed" ? "PASS" : "FAIL"; |
| | | //string csvPath = Path.Combine(csvDir, SelectedProduct?.Name ?? "未知产品", time.ToString("yyyyMMdd"), status, |
| | | // $"{this.tsSockets[index].Barcode}-{time.ToString("HHmmss")}.csv"); |
| | | this.tsSockets[index].WriteToCSV(csvPath); |
| | | } |
| | | |
| | | public void SaveTemplateCSV(int index) |
| | | { |
| | | var time = DateTime.Now; |
| | | string status = this.tsSockets[index].Status == "Passed" ? "PASS" : "FAIL"; |
| | | string csvPath = Path.Combine(csvDir, CurrentProductModel ?? "未知产品", time.ToString("yyyyMMdd"), status, $"{this.tsSockets[index].Barcode}-{time.ToString("HHmmss")}.csv"); |
| | | this.tsSockets[index].WriteToCSV(csvPath); |
| | | } |
| | | |
| | | public void SavePositionDB(int index, string status) |
| | | { |
| | | CheckSqlHelper(); |
| | | var socket = this.tsSockets[index]; |
| | | var time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); |
| | | string snr = socket.Barcode; |
| | | string model = CurrentProductModel; |
| | | |
| | | List<string> sqls = new List<string>(); |
| | | foreach (var data in socket.Datasource) |
| | | { |
| | | sqls.Add($@"INSERT INTO serialData (sn,model,station,step,position,limitDown,limitUp,unit,value,status,finalStatus,consumeTime,totalConsumeTime,time) VALUES |
| | | ('{snr}','{model}','','{data.Name}','{index}','{data.LimitDown}','{data.LimitUp}','{data.Unit}','{data.Value}','{data.Result}','{socket.Status}','{data.ConsumeTime}','{socket.ElapseTime}','{time}')"); |
| | | } |
| | | sqls.Add($@"INSERT INTO testResult (sn,model,station,result,time,position,status) VALUES |
| | | ('{snr}','{model}','','{socket.Status}','{time}','{index}','{status}')"); |
| | | sqliteHelper.ExecuteBatchSql(sqls); |
| | | } |
| | | |
| | | private void HandleUIMessage(int eventCode, int index, string strData) |
| | | { |
| | | switch (eventCode) |
| | | { |
| | | case 10002://更新测试状态 |
| | | string status = strData; |
| | | UpdatePositionStatus(index, status); |
| | | break; |
| | | |
| | | case 10003://发送测试数据 |
| | | AddTestData(index, strData); |
| | | break; |
| | | |
| | | case 10004://发送测试过程信息 |
| | | this.tsSockets[index].CurrentStep = strData; |
| | | break; |
| | | |
| | | case 10005://初始化测试数据,清空测试数据 |
| | | this.tsSockets[index].IniTestData(); |
| | | break; |
| | | |
| | | case 10006://发送产品条码 |
| | | SetPositionBarcode(index, strData); |
| | | break; |
| | | |
| | | case 10007://开始测试计时 |
| | | tsSockets[index].ElapseTime = "Start Timing"; |
| | | BtnStopSeq.IsEnabled = false; |
| | | break; |
| | | |
| | | case 10008://停止测试计时 |
| | | tsSockets[index].ElapseTime = "Stop Timing"; |
| | | BtnStopSeq.IsEnabled = true; |
| | | break; |
| | | |
| | | case 10009: |
| | | // |
| | | break; |
| | | |
| | | case 10010: |
| | | |
| | | //PropertyObj.SetValBoolean("Locals.MD5_Used", 0, true); |
| | | //PropertyObj.SetValVariant("FileGlobals.MD5_Value", 0, MD5_DATA); |
| | | //PropertyObj.SetValVariant("StationGlobals.MD5", 0, MD5_DATA); |
| | | break; |
| | | |
| | | case 10011: |
| | | // write model |
| | | |
| | | break; |
| | | |
| | | case 10012: |
| | | // read model |
| | | |
| | | break; |
| | | |
| | | case 10013: |
| | | // read continue |
| | | |
| | | |
| | | break; |
| | | |
| | | case 10014: |
| | | |
| | | break; |
| | | |
| | | case 10015: |
| | | |
| | | break; |
| | | case 10016://显示3D拼接图片 |
| | | |
| | | break; |
| | | case 10017://更新测试计时,针对部分计时有PLC完成的项目 |
| | | this.tsSockets[index].ElapseTime = strData; |
| | | break; |
| | | case (int)UIMessageCodes.UIMsg_EndExecution://执行结束 |
| | | //IsTesting = false; |
| | | //this.ReleaseSequenceFile(); |
| | | break; |
| | | case 10030://显示测试进度 |
| | | int ProcessVal = Convert.ToInt32(strData); |
| | | this.tsSockets[index].SetTestProcess(ProcessVal); |
| | | break; |
| | | case 10031://导出CSV |
| | | if (string.IsNullOrEmpty(strData)) |
| | | { |
| | | SaveTemplateCSV(index); |
| | | return; |
| | | } |
| | | try |
| | | { |
| | | string[] datas = strData.Split(';'); |
| | | SavePositionCSV(index, datas[0]); |
| | | if (datas.Length >= 2) |
| | | { |
| | | SavePositionDB(index, datas[1]); |
| | | } |
| | | else |
| | | { |
| | | var sss = this.tsSockets[index].Status; |
| | | SavePositionDB(index, sss); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Warn("10031 Error.", ex); |
| | | SaveTemplateCSV(index); |
| | | } |
| | | break; |
| | | case 10032://按下标暂停测试 |
| | | this.tsSockets[index].ShowPausePanel(); |
| | | break; |
| | | case 10033: |
| | | var alarm = new AlarmText |
| | | { |
| | | VirtualId = DateTime.Now.ToString("yyyyMMddHHmmssfff"), |
| | | AlarmInfo = strData |
| | | }; |
| | | ShowAlarm(alarm); |
| | | break; |
| | | case 10034: |
| | | CurrentProductModel = strData; |
| | | break; |
| | | case 10035: |
| | | string[] arr_10035 = strData.Split(';'); |
| | | |
| | | int[][] points = new int[arr_10035.Length - 1][]; |
| | | |
| | | for (int i = 1; i < arr_10035.Length; i++) |
| | | { |
| | | string[] strs = arr_10035[i].Split(','); |
| | | points[i - 1] = new int[2] { int.Parse(strs[0]), int.Parse(strs[1]) }; |
| | | } |
| | | this.tsSockets[index].DrawScreenPoints(int.Parse(arr_10035[0]), points); |
| | | break; |
| | | case 10036: |
| | | this.tsSockets[index].ClearScreenPoint(int.Parse(strData)); |
| | | break; |
| | | case 10099: |
| | | string[] arr = strData.Split(','); |
| | | if (canSwitchModel) SwitchSequenceByModel(index, arr[0], arr[1]); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | |
| | | private void SwitchSequenceByModel(int index, string model, string snr) |
| | | { |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | var target = Products.FirstOrDefault(e => e.Name == model); |
| | | |
| | | ShowMask(() => |
| | | { |
| | | bool stoped = StopSequence(); |
| | | //if (stoped) |
| | | //{ |
| | | // IsTesting = false; |
| | | //} |
| | | }, null, null, "换型中,请稍后..."); |
| | | |
| | | if (target == null) |
| | | { |
| | | MsgBoxHelper2.Warn($"请先在产品管理页面配置型号 [{model}] 的产品信息!"); |
| | | 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}"); |
| | | } |
| | | } |
| | | |
| | | switchAction = () => |
| | | { |
| | | switchAction = null; |
| | | log?.Info($"尝试自动换型: {switchAction}"); |
| | | if (canSwitchModel) |
| | | { |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | try |
| | | { |
| | | log?.Info("开始自动换型"); |
| | | SelectedProduct = target; |
| | | engine?.Globals.SetValString($"CacheSNR[{index}]", 1, snr); |
| | | engine?.CommitGlobalsToDisk(false); |
| | | StartClick(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log?.Error("自动换型失败", ex); |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | }); |
| | | } |
| | | |
| | | private void ShowAlarm(AlarmText alarm) |
| | | { |
| | | AlarmShowHelper.ShowAlarm(alarm); |
| | | mSMQHelper.Send("Alarm", $"ATE测试 {alarm.AlarmInfo}"); |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | { |
| | | try |
| | | { |
| | | int EventCase = Convert.ToInt32(e.uiMsg.Event); |
| | | int Index = Convert.ToInt16(e.uiMsg.NumericData);//SocketIndex |
| | | switch (EventCase) |
| | | int eventCode = Convert.ToInt32(e.uiMsg.Event); |
| | | int index = Convert.ToInt16(e.uiMsg.NumericData);//SocketIndex |
| | | string strData = e.uiMsg.StringData; |
| | | |
| | | try |
| | | { |
| | | case 10001://传递SocketContext |
| | | tsSockets[Index].SequenceFileContext = (SequenceContext)e.uiMsg.ActiveXData; |
| | | break; |
| | | |
| | | case 10002://更新测试状态 |
| | | string status = e.uiMsg.StringData; |
| | | this.tsSockets[Index].UpdateStatus(status); |
| | | this.UpdateTestCounter(); |
| | | break; |
| | | |
| | | case 10003://发送测试数据 |
| | | string[] TestItems = e.uiMsg.StringData.Split('\t'); |
| | | tsSockets[Index].AddTestData(TestItems[0], TestItems[4], TestItems[1], TestItems[2], TestItems[3], TestItems[5]); |
| | | |
| | | break; |
| | | |
| | | case 10004://发送测试过程信息 |
| | | this.tsSockets[Index].CurrentStep = e.uiMsg.StringData; |
| | | break; |
| | | |
| | | case 10005://初始化测试数据,清空测试数据 |
| | | this.tsSockets[Index].IniTestData(); |
| | | break; |
| | | |
| | | case 10006://发送产品条码 |
| | | this.tsSockets[Index].Barcode = e.uiMsg.StringData; |
| | | break; |
| | | |
| | | case 10007://开始测试计时 |
| | | tsSockets[Index].ElapseTime = "Start Timing"; |
| | | BtnStopSeq.IsEnabled = false; |
| | | break; |
| | | |
| | | case 10008://停止测试计时 |
| | | tsSockets[Index].ElapseTime = "Stop Timing"; |
| | | BtnStopSeq.IsEnabled = true; |
| | | break; |
| | | |
| | | case 10009: |
| | | // |
| | | break; |
| | | |
| | | case 10010: |
| | | |
| | | //PropertyObj.SetValBoolean("Locals.MD5_Used", 0, true); |
| | | //PropertyObj.SetValVariant("FileGlobals.MD5_Value", 0, MD5_DATA); |
| | | //PropertyObj.SetValVariant("StationGlobals.MD5", 0, MD5_DATA); |
| | | break; |
| | | |
| | | case 10011: |
| | | // write model |
| | | |
| | | break; |
| | | |
| | | case 10012: |
| | | // read model |
| | | |
| | | break; |
| | | |
| | | case 10013: |
| | | // read continue |
| | | |
| | | |
| | | break; |
| | | |
| | | case 10014: |
| | | |
| | | break; |
| | | |
| | | case 10015: |
| | | |
| | | break; |
| | | case 10016://显示3D拼接图片 |
| | | |
| | | break; |
| | | case 10017://更新测试计时,针对部分计时有PLC完成的项目 |
| | | this.tsSockets[Index].ElapseTime = e.uiMsg.StringData; |
| | | break; |
| | | case (int)UIMessageCodes.UIMsg_EndExecution://执行结束 |
| | | this.BtnStartSeq.IsEnabled = true; |
| | | this.BtnStopSeq.IsEnabled = true; |
| | | // this.ReleaseSequenceFile(); |
| | | break; |
| | | case 10030://显示测试进度 |
| | | int ProcessVal = Convert.ToInt32(e.uiMsg.StringData); |
| | | this.tsSockets[Index].SetTestProcess(ProcessVal); |
| | | break; |
| | | default: |
| | | break; |
| | | log.Debug($"Event: {eventCode}, NumericData: {index}, StringData: {strData}"); |
| | | } |
| | | catch |
| | | { |
| | | |
| | | } |
| | | if (eventCode == 10001) |
| | | { |
| | | sequenceContext = (SequenceContext)e.uiMsg.ActiveXData; |
| | | |
| | | tsSockets[index].SequenceFileContext = (SequenceContext)e.uiMsg.ActiveXData; |
| | | return; |
| | | } |
| | | HandleUIMessage(eventCode, index, strData); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | |
| | | |
| | | private void UpdateTestCounter() |
| | | { |
| | | int PassNum = 0; |
| | | int FailNum = 0; |
| | | double PassNum = 0; |
| | | double FailNum = 0; |
| | | foreach (SingleControl socket in this.tsSockets) |
| | | { |
| | | PassNum += socket.PassNum; |
| | | FailNum += socket.FailNum; |
| | | } |
| | | this.DisplayCount(PassNum, FailNum); |
| | | UpdateChart(PassNum, FailNum); |
| | | } |
| | | |
| | | private void UpdateChart(int pass, int fail) |
| | | { |
| | | pie.Slices[0].Value = pass; |
| | | pie.Slices[1].Value = fail; |
| | | pieChart.Refresh(); |
| | | } |
| | | |
| | | private void SetTestSeqFile(ProductData product) |
| | | { |
| | | if (product == null) |
| | | { |
| | | testSeqFile = null; |
| | | return; |
| | | } |
| | | string name = product.Name; |
| | | List<ParameterData> parameters = ParameterManager.GetParametersByProductName(name); |
| | | List<ParameterData> parameters = ProductManager.GetParametersByProductName(name); |
| | | testSeqFile = parameters.FirstOrDefault(p => p.Name == "TestSequence")?.Value?.ToString(); |
| | | if (AutoExecuteSeq) |
| | | { |
| | | StartSequence(); |
| | | } |
| | | } |
| | | |
| | | private void ClearNum() |
| | |
| | | { |
| | | PassAmount = 0; |
| | | FailAmount = 0; |
| | | DisplayCount(PassAmount, FailAmount); |
| | | UpdateChart(PassAmount, FailAmount); |
| | | //this.OpcHandle.DoFctWriteSingle("Count_Clear", "1", out string ErrMsg); |
| | | foreach (SingleControl socket in tsSockets) |
| | | { |
| | | socket.ResetCounter(); |
| | | } |
| | | DisplayCount(PassAmount, FailAmount); |
| | | } |
| | | } |
| | | |
| | | public override void OnClose(object sender, CancelEventArgs e) |
| | | { |
| | | StopSequence(); |
| | | this.engine?.ReleaseSequenceFileEx(this.testSeq, 0); |
| | | this.engine?.ReleaseSequenceFileEx(this.modeSeq, 0); |
| | | this.engine?.UnloadAllModules(); |
| | | this.testSeq = null; |
| | | this.modeSeq = null; |
| | | base.OnClose(sender, e); |
| | | try |
| | | { |
| | | StopSequence(); |
| | | base.OnClose(sender, e); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Error("OnClose Error.", ex); |
| | | } |
| | | } |
| | | |
| | | public override void DoClose(object sender, EventArgs e) |
| | | { |
| | | base.DoClose(sender, e); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 释放所有的序列文件 |
| | | /// </summary> |
| | | private bool ReleaseSequenceFile() |
| | | { |
| | | try |
| | | { |
| | | lock (this) |
| | | { |
| | | if (this.testSeq == null) |
| | | { |
| | | return true; |
| | | } |
| | | //execution.Abort(); |
| | | int count = 10; |
| | | while (count > 0) |
| | | { |
| | | try |
| | | { |
| | | if (this.testSeq == null) |
| | | return true; |
| | | |
| | | if (this.engine?.ReleaseSequenceFileEx(this.testSeq, 4) == true) |
| | | { |
| | | Marshal.ReleaseComObject(this.testSeq); |
| | | this.testSeq = null; |
| | | // GC.Collect(); |
| | | } |
| | | if (this.engine?.ReleaseSequenceFileEx(this.modeSeq, 4) == true) |
| | | { |
| | | Marshal.ReleaseComObject(this.modeSeq); |
| | | this.modeSeq = null; |
| | | } |
| | | this.engine?.UnloadAllModules(); |
| | | return this.testSeq == null && this.modeSeq == null; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Warn($"ReleaseSequenceFile In {count} Times Fail.", ex); |
| | | count--; |
| | | System.Threading.Thread.Sleep(1000); |
| | | } |
| | | } |
| | | log.Warn($"ReleaseSequenceFile Failed."); |
| | | return false; |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Warn("ReleaseSequenceFile Error.", ex); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | private void PluginControl_SizeChanged(object sender, SizeChangedEventArgs e) |
| | | { |
| | | |
| | | } |
| | | |
| | | private void CbFontSize_SelectionChanged(object sender, SelectionChangedEventArgs e) |
| | | { |
| | | try |
| | | { |
| | | if (e.AddedItems != null && e.AddedItems.Count > 0) |
| | | { |
| | | var fontSize = (double)e.AddedItems[0]; |
| | | this.Resources["tableFontSize"] = fontSize; |
| | | IniFileHelper.WriteIniData("Config", "TableFontSize", fontSize.ToString(), CountIniPath); |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | } |
| | | } |
| | | |
| | | private void Label_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e) |
| | | { |
| | | //workOrderEditor.Focus(); |
| | | //workOrderEditor.IsEditing = true; |
| | | if (RequirePassword() == true) |
| | | { |
| | | var win = new WorkOrderWin |
| | | { |
| | | WorkOrder = CurrentWorkorder, |
| | | Owner = Window.GetWindow(this) |
| | | }; |
| | | if (win.ShowDialog() == true) |
| | | { |
| | | CurrentWorkorder = win.WorkOrder; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |