| | |
| | | using HMI.Core.Api; |
| | | using HMI.Core.Entity; |
| | | using HMI.Core.Manager; |
| | | using HMI.Core.Setting; |
| | | using HMI.Core.Util; |
| | | using HMI.MQUtil; |
| | | using HMI.UI; |
| | | 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.Plottables; |
| | |
| | | /// <summary> |
| | | /// UserControl1.xaml 的交互逻辑 |
| | | /// </summary> |
| | | public partial class TsExecution : PluginControl |
| | | public partial class TsExecution : PluginMaskControl |
| | | { |
| | | #region TestStand事件 |
| | | /// <summary> |
| | |
| | | set |
| | | { |
| | | Set(ref selectedProduct, value); |
| | | CurrentProductModel = value?.Name; |
| | | SetTestSeqFile(value); |
| | | } |
| | | } |
| | | |
| | | private string currentProductModel; |
| | | public string CurrentProductModel |
| | | { |
| | | get => currentProductModel; |
| | | set |
| | | { |
| | | Set(ref currentProductModel, value); |
| | | } |
| | | } |
| | | |
| | |
| | | Set(ref products, value); |
| | | } |
| | | } |
| | | |
| | | 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; |
| | |
| | | if (WriteIni("UI_CurrentWorkorder", value)) |
| | | { |
| | | Set(ref currentWorkorder, value); |
| | | engine?.Globals.SetValString("StationState.WorkOrder", 1, value); |
| | | engine?.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | | } |
| | | } |
| | | } |
| | |
| | | DataContext = this; |
| | | GCTimer = new Timer(); |
| | | InitializeComponent(); |
| | | |
| | | InitChart(); |
| | | InitTsEngine(); |
| | | //初始化TestStand引擎 |
| | |
| | | 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() |
| | |
| | | |
| | | private void PluginControl_Loaded(object sender, RoutedEventArgs e) |
| | | { |
| | | new MaskWindow((WindowX)Window.GetWindow(this), |
| | | (win) => |
| | | ShowMask(() => |
| | | { |
| | | try |
| | | { |
| | | 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}"); |
| | | } |
| | | //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}"); |
| | | } |
| | | |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | 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() |
| | |
| | | { |
| | | 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 string csvDir; |
| | |
| | | { |
| | | |
| | | value = ParameterManager.GetCommonParameterByName("UI_CurrentWorkorder"); |
| | | currentWorkorder = value.Value; |
| | | Set("CurrentWorkorder"); |
| | | CurrentWorkorder = value.Value; |
| | | } |
| | | catch |
| | | { |
| | | currentWorkorder = string.Empty; |
| | | Set("CurrentWorkorder"); |
| | | CurrentWorkorder = string.Empty; |
| | | } |
| | | |
| | | try |
| | |
| | | { |
| | | } |
| | | |
| | | try |
| | | { |
| | | |
| | | value = ParameterManager.GetCommonParameterByName("TS_DataLogPath"); |
| | | dataLogPath = value.Value; |
| | | } |
| | | catch |
| | | { |
| | | dataLogPath = Path.Combine(PathHelper.ConfigFolder, "DataBoard"); |
| | | } |
| | | dataLogPath = ParamSetting.DataLogFolder; |
| | | |
| | | try |
| | | { |
| | | |
| | | value = ParameterManager.GetCommonParameterByName("TsModelPath"); |
| | | tsModelPath = value.Value; |
| | | tsModelPath = value?.Value ?? @"C:\Users\Public\Documents\National Instruments\TestStand 2020 (64-bit)\Components\Models\ParallelModel.seq"; |
| | | } |
| | | catch |
| | | { |
| | |
| | | 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; |
| | | } |
| | |
| | | private void StartSequence() |
| | | { |
| | | if (!isLoadOK) return; |
| | | //MaskWindow mask = new MaskWindow(); |
| | | try |
| | | { |
| | | engine?.Globals.SetValString("StationState.ProductModel", 1, SelectedProduct?.Name); |
| | | 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 |
| | | { |
| | | |
| | | if (ParamSetting.EnableAutoModel) |
| | | { |
| | | try |
| | | { |
| | | 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) |
| | | { |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | log.Error("Start Sequence Failed.", ex); |
| | | MsgBoxHelper.Error(this, $"{LangUtil.Get("Ts.StartSequenceFail")}: {ex.Message}"); |
| | | }); |
| | | } |
| | | } |
| | | 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) => |
| | | { |
| | | try |
| | | { |
| | | bool stoped = StopSequence(); |
| | | if (stoped) |
| | | { |
| | | IsTesting = false; |
| | | } |
| | | } |
| | | finally |
| | | { |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | ShowMask(() => |
| | | { |
| | | bool stoped = StopSequence(); |
| | | if (stoped) |
| | | { |
| | | IsTesting = false; |
| | | } |
| | | }, null, null, LangUtil.Get("App.SequenceIsStopping")); |
| | | //new MaskWindow((WindowX)Window.GetWindow(this), |
| | | // (win) => |
| | | // { |
| | | // try |
| | | // { |
| | | // bool stoped = StopSequence(); |
| | | // if (stoped) |
| | | // { |
| | | // IsTesting = false; |
| | | // } |
| | | // } |
| | | // finally |
| | | // { |
| | | // Dispatcher.Invoke(() => |
| | | // { |
| | | |
| | | win.Close(); |
| | | }); |
| | | } |
| | | } |
| | | ).Info(LangUtil.Get("App.SequenceIsStopping")); |
| | | // win.Close(); |
| | | // }); |
| | | // } |
| | | // } |
| | | // ).Info(LangUtil.Get("App.SequenceIsStopping")); |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | |
| | | private void StartClick() |
| | | { |
| | | new MaskWindow(Window.GetWindow(this), |
| | | (win) => |
| | | { |
| | | try |
| | | { |
| | | StartSequence(); |
| | | } |
| | | finally |
| | | { |
| | | win.Dispatcher.Invoke(() => |
| | | { |
| | | win.Close(); |
| | | }); |
| | | } |
| | | }).Info(LangUtil.Get("Ts.SequenceIsStarting")); |
| | | 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> |
| | |
| | | { |
| | | 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"); |
| | | string csvPath = Path.Combine(csvDir, CurrentProductModel ?? "未知产品", time.ToString("yyyyMMdd"), status, $"{this.tsSockets[index].Barcode}-{time.ToString("HHmmss")}.csv"); |
| | | this.tsSockets[index].WriteToCSV(csvPath); |
| | | } |
| | | |
| | |
| | | var socket = this.tsSockets[index]; |
| | | var time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); |
| | | string snr = socket.Barcode; |
| | | string model = SelectedProduct?.Name; |
| | | string model = CurrentProductModel; |
| | | |
| | | List<string> sqls = new List<string>(); |
| | | foreach (var data in socket.Datasource) |
| | |
| | | this.tsSockets[index].ShowPausePanel(); |
| | | break; |
| | | case 10033: |
| | | ShowAlarm(strData); |
| | | var alarm = new AlarmText |
| | | { |
| | | VirtualId = DateTime.Now.ToString("yyyyMMddHHmmssfff"), |
| | | AlarmInfo = strData |
| | | }; |
| | | ShowAlarm(alarm); |
| | | break; |
| | | case 10034: |
| | | CurrentProductModel = strData; |
| | | break; |
| | | case 10099: |
| | | break; |
| | |
| | | } |
| | | } |
| | | |
| | | private void ShowAlarm(string info) |
| | | private void ShowAlarm(AlarmText alarm) |
| | | { |
| | | AlarmShowHelper.ShowAlarm(info); |
| | | mSMQHelper.Send("Alarm", $"ATE测试 {info}"); |
| | | AlarmShowHelper.ShowAlarm(alarm); |
| | | mSMQHelper.Send("Alarm", $"ATE测试 {alarm.AlarmInfo}"); |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | { |
| | | |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |