alielie
2026-06-15 f08871fe7d148d667f2f11f80f64de71a0d9504c
Plugin.TestResult/ViewControl.xaml.cs
@@ -1,19 +1,22 @@
using HMI.Base;
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.LogUtil;
using HMI.StdControl;
using HMI.UI.Util;
using log4net;
using NationalInstruments.TestStand.Interop.API;
using NationalInstruments.TestStand.Interop.UI.Ax;
using Plugin.TestResult_WPF.Model;
using Plugin.TestResult_WPF.Util;
using PLCHelper;
using Plugin.TestResult.Util;
using Plugin.TsSupport;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
@@ -22,22 +25,10 @@
    /// <summary>
    /// ViewControl.xaml 的交互逻辑
    /// </summary>
    public partial class ViewControl : PluginControl
    public partial class ViewControl : PluginMaskControl, IAlarmHandler
    {
        private CommonCodeParser codeParser = new CommonCodeParser();
        private double TestTemperature = 60;
        private int TestTime = 3600;
        private double SaftyTemperature = 40;
        private double TestVoltage = 12;
        private double Time_Heating_Low = 300;
        private double Time_Heating_High = 2400;
        private string testSeqFile;
        private Scanner scannerWindow1;
        private Scanner scannerWindow2;
        /// <summary>
        /// 测试序列操作句柄
        /// </summary>
        private SequenceContext SequenceContext = null;
        private System.Timers.Timer timer;
        public static ILog Logger { get; private set; }
@@ -58,58 +49,100 @@
            set => Set(ref _produceStatus, value);
        }
        private string _fileName;
        public string FileName
        {
            get => _fileName;
            set => Set(ref _fileName, value);
        }
        private bool enableManualDebug;
        public bool EnableManualDebug
        {
            get => enableManualDebug;
            set
            {
                if (IsRunning)
                {
                    MsgBoxHelper2.Warn("请先结束自动测试");
                    return;
                }
                testResultView.inManualDebugMode = value;
                Set(ref enableManualDebug, value);
            }
        }
        public override void SetLogger(ILog logger)
        {
            base.SetLogger(logger);
            Logger = logger;
        }
        private bool isRunning = false;
        public bool IsRunning
        {
            get => isRunning;
            set
            {
                Set(ref isRunning, value);
                testResultView.IsRunning = value;
                this.modelSelect.IsEnabled = !value;
                this.btnStop.IsEnabled = value;
                stdEnableMes.CbEnabled = !value;
            }
        }
        private bool AutoExecuteSeq = true;
        #region TS相关
        /// <summary>
        /// 测试序列操作句柄
        /// </summary>
        private SequenceContext SequenceContext = null;
        #endregion
        public ViewControl()
        {
            S7Context.Init(SystemSetting.Instance.PlcIp, SystemSetting.Instance.PlcPort);
            DataContext = this;
            timer = new System.Timers.Timer();
            timer.Interval = 1000;
            timer.Elapsed += Timer_Elapsed;
            InitializeComponent();
            testResultView.testApp.ExitApplication += new EventHandler(this.axApplicationMgr_ExitApplication);
            testResultView.testApp.UIMessageEvent += new _ApplicationMgrEvents_UIMessageEventEventHandler(this.axApplicationMgr_UIMessageEvent);
            testResultView.testApp.ExecutionClosed += new _ApplicationMgrEvents_ExecutionClosedEventHandler(this.axApplicationMgr_ExecutionClosed);
            //testResultView.testApp.ExitApplication += new EventHandler(this.axApplicationMgr_ExitApplication);
            //testResultView.testApp.UIMessageEvent += new _ApplicationMgrEvents_UIMessageEventEventHandler(this.axApplicationMgr_UIMessageEvent);
            //testResultView.testApp.ExecutionClosed += new _ApplicationMgrEvents_ExecutionClosedEventHandler(this.axApplicationMgr_ExecutionClosed);
        }
        public override void InitFinish()
        {
            base.InitFinish();
            string path = Path.Combine(BaseFolder, "Count.ini");
            testResultView.SetCountIniPath(path);
            testResultView.InitMainGrid();
            LoadProduct();
            testResultView.InitTestStandEngine();
        }
        public override void DoClose(object sender, EventArgs e)
        {
            testResultView.ReleaseResource();
        }
        private void axApplicationMgr_ExitApplication(object sender, EventArgs e)
        {
        }
        private void axApplicationMgr_ExecutionClosed(object sender, _ApplicationMgrEvents_ExecutionClosedEvent e)
        {
        }
        private void axApplicationMgr_UIMessageEvent(object sender, _ApplicationMgrEvents_UIMessageEventEvent e)
        private void HandleUIMessage(int EventCase, int MethodCode, string strData, object xData)
        {
            try
            {
                int EventCase = Convert.ToInt32(e.uiMsg.Event);
                int MethodCode = Convert.ToInt16(e.uiMsg.NumericData);
                string strData;
                try
                {
                    log.Debug($"EventCase: {EventCase}, MethodCode: {MethodCode}, StrData: {strData}");
                }
                catch
                {
                }
                if (EventCase == 8)
                {
                    IsRunning = false;
                    return;
                }
                if (EventCase != 10014) return;
                if (MethodCode == 0)
                {
                    /// 设置句柄
                    this.SequenceContext = (SequenceContext)e.uiMsg.ActiveXData;
                    this.SequenceContext = (SequenceContext)xData;
                    return;
                }
@@ -117,7 +150,6 @@
                if (MethodCode == 8)
                {
                    /// 更新MES状态
                    strData = e.uiMsg.StringData;
                    mesStatus = strData == "1";
                    return;
                }
@@ -125,7 +157,6 @@
                if (MethodCode == 9)
                {
                    /// 更新生产状态
                    strData = e.uiMsg.StringData;
                    produceStatus = strData;
                    return;
                }
@@ -134,55 +165,162 @@
            { }
        }
        private void ExecutionWrapper_UIMessageEvent(object sender, UIMessageEvent e)
        {
            HandleUIMessage(e.EventCode, Convert.ToInt16(e.NumberData), e.StrData, e.Data);
        }
        private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            testResultView.RefreshCooler();
        }
        public TestResultView View
        {
            get => testResultView;
        }
        public static string SannerIniFile { get; private set; }
        public override void InitFinish()
        {
            base.InitFinish();
            string path = Path.Combine(BaseFolder, "Count.ini");
            testResultView.SetCountIniPath(path);
            testResultView.InitMainGrid();
            path = Path.Combine(BaseFolder, "Scanner.ini");
            if (!File.Exists(path))
            {
                File.Create(path).Close();
            }
            SannerIniFile = path;
            LoadProduct();
            var api = S7Context.Get(RunTimeVariablePool.DEFAULT_PLC_NAME);
            log.Debug($"PLC {api.IpAddress}:{api.Port}");
            try
            {
                var value = ParameterManager.GetCommonParameterByName("AutoExecuteSeq");
                AutoExecuteSeq = bool.Parse(value.Value);
            }
            catch
            {
                AutoExecuteSeq = true;
            }
            try
            {
                var value = ParameterManager.GetCommonParameterByName("BurnInMainSeq");
                testResultView.testSeqFile = value.Value;
                FileName = Path.GetFileName(value.Value);
            }
            catch
            {
                testResultView.testSeqFile = string.Empty;
                FileName = string.Empty;
            }
            string type = Path.GetExtension(FileName);
            bool isTap = string.Equals(".tapplan", type, StringComparison.OrdinalIgnoreCase);
            testResultView.InitTestStandEngine(isTap);
            testResultView.executionWrapper.UIMessageEvent += ExecutionWrapper_UIMessageEvent;
            RefreshUIConfig();
        }
        /// <summary>
        /// 刷新UI配置
        /// </summary>
        private void RefreshUIConfig()
        {
            try
            {
                /// 运行中就不管
                if (IsRunning)
                {
                    return;
                }
                bool enableManualDebug = ParameterManager.GetCommonParameterByName("EnableManualDebug", false);
                if (enableManualDebug)
                {
                    FgEnableManualDebug.Visibility = Visibility.Visible;
                }
                else
                {
                    FgEnableManualDebug.Visibility = Visibility.Collapsed;
                    EnableManualDebug = false;
                }
            }
            catch (Exception ex)
            {
                log.Error("RefreshUIConfig Error.", ex);
            }
        }
        private bool isLoaded;
        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            new MaskWindow(Window.GetWindow(this),
                (win) =>
            AlarmShowHelper.AddHandler(this);
            if (AutoExecuteSeq)
            {
                ShowMask(() =>
                {
                    Dispatcher.Invoke(() =>
                    Dispatcher.BeginInvoke(new Action(() =>
                    {
                        try
                        {
                            Start_Click(null, null);
                            Loaded -= UserControl_Loaded;
                        }
                        finally
                        {
                            win.Close();
                        }
                    });
                }).Info(LangUtil.Get("Ts.SequenceIsStarting"));
                        Start_Click(null, null);
                    }), System.Windows.Threading.DispatcherPriority.Background);
                }, (ex) =>
                {
                    ToastHelper.Error("Loaded Failed.");
                    log.Error("Loaded Failed.", ex);
                }, "请稍后", LangUtil.Get("Ts.SequenceIsStarting"));
            }
            else
            {
                IsRunning = false;
            }
            Loaded -= UserControl_Loaded;
        }
        public void LoadProduct()
        {
            List<ProductData> products = ParameterManager.GetProducts<List<ProductData>>()
            List<ProductData> products = ProductManager.GetProducts<List<ProductData>>()
                ?? new List<ProductData>();
            this.modelSelect.Items.Clear();
            List<string> productSource = new List<string>();
            foreach (var prd in products)
            {
                this.modelSelect.Items.Add(prd.Name);
                productSource.Add(prd.Name);
            }
            if (products.Count > 0)
            {
                this.modelSelect.SelectedIndex = 0;
            }
            testResultView.SetProductSource(productSource);
            testResultView.SetCurrentProduct(null);
            //string model = testResultView.executionWrapper.GetStationGlobalValue<string>("ProductModel", 1);
            ////testResultView.engine.Globals.GetValString("ProductModel", 1);
            //if (!string.IsNullOrEmpty(model))
            //{
            //    this.modelSelect.SelectedItem = model;
            //    testResultView.SetCurrentProduct(model);
            //}
            //else if (products.Count > 0)
            //{
            //    this.modelSelect.SelectedIndex = 0;
            //    testResultView.SetCurrentProduct(products[0].Name);
            //}
        }
        private void modelSelect_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            try
            {
                List<ParameterData> parameters = ParameterManager.GetParametersByProductName(this.modelSelect.SelectedItem.ToString());
                //MessageBox.Show("ParaFile:" + ParaFile + "ParaCount:" + this.parameterManager.Parameters.Count.ToString());
                //this.TestTemperature = Convert.ToDouble(this.parameterManager.Find("TestTemperature").ParmValue);
                //this.TestTime = Convert.ToInt32(this.parameterManager.Find("TestTime").ParmValue);
                //this.TestVoltage = Convert.ToDouble(this.parameterManager.Find("TestVoltage").ParmValue);
                //this.SaftyTemperature = Convert.ToDouble(this.parameterManager.Find("SaftyTemperature").ParmValue);
                //this.Time_Heating_Low = Convert.ToDouble(this.parameterManager.Find("Time_Heat_Low").ParmValue);
                //this.Time_Heating_High = Convert.ToDouble(this.parameterManager.Find("Time_Heat_High").ParmValue);
                testResultView.testSeqFile = parameters.FirstOrDefault(p => p.Name == "TestSequence")?.Value;
                string currentModel = this.modelSelect.SelectedItem.ToString();
                List<ParameterData> parameters = ProductManager.GetParametersByProductName(currentModel);
                testResultView.executionWrapper.SetStationGlobalValue<string>("ProductModel", 0, currentModel);
                testResultView.executionWrapper.CommitToDisk(false);
                //testResultView.engine.Globals.SetValString("ProductModel", 0, currentModel);
                //testResultView.engine.CommitGlobalsToDisk(promptOnSaveConflicts: false);
            }
            catch (Exception ex)
            {
@@ -194,10 +332,29 @@
        {
            try
            {
                testResultView.StartTestSequence();
                this.modelSelect.IsEnabled = false;
                this.btnStart.IsEnabled = false;
                this.btnStop.IsEnabled = true;
                if (string.IsNullOrEmpty(testResultView.testSeqFile))
                {
                    MsgBoxHelper2.Warn("请先设置BurnInMainSeq属性!");
                    IsRunning = false;
                    return;
                }
                LogHelper.Info("UI", "总启动按钮按下", out _);
                log.Info("总启动按钮按下");
                ShowMask(() =>
                {
                    testResultView.StartTestSequence();
                    Dispatcher.Invoke(() =>
                    {
                        IsRunning = true;
                    });
                }, (ex) =>
                {
                    log.Error("StartTestSequence Error.", ex);
                    Dispatcher.Invoke(() =>
                    {
                        MsgBoxHelper.Error(Window.GetWindow(this), $"{this.lang("Ts.StartTestSequenceFailed")}: {ex.Message}");
                    });
                }, null, "请稍后...");
            }
            catch (Exception ex)
            {
@@ -211,10 +368,31 @@
        {
            try
            {
                bool breakStop = false;
                foreach (var oven in TestResultView.tables)
                {
                    if (oven.IsTesting)
                    {
                        breakStop = true;
                        break;
                    }
                }
                if (breakStop)
                {
                    MsgBoxHelper2.Warn(this.lang("Tr.OvenIsTesting"));
                    return;
                }
                if (MsgBoxHelper2.WarnChoose(this.lang("Tr.MakeSureStopAllTest")) != MessageBoxResult.OK)
                {
                    return;
                }
                LogHelper.Info("UI", "总停止按钮按下", out _);
                log.Info("总停止按钮按下");
                testResultView.StopTest();
                this.modelSelect.IsEnabled = true;
                this.btnStart.IsEnabled = true;
                this.btnStop.IsEnabled = false;
                /// 已经加了WaitForExit,这里可以改为false
                IsRunning = false;
            }
            catch (Exception ex)
            {
@@ -222,80 +400,6 @@
                MsgBoxHelper.Error(Window.GetWindow(this),
                    $"{this.lang("Ts.StopTestSequenceFailed")}: {ex.Message}");
            }
        }
        private void Scan_Click_1(object sender, RoutedEventArgs e)
        {
            if (scannerWindow1 == null)
            {
                scannerWindow1 = new Scanner(this.lang("Tr.Zone1Scan"))
                {
                    Tag = "Zone1"
                };
                scannerWindow1.FinishBarcode += ScannerWindow_FinishBarcode;
                //scannerWindow1.Owner = Window.GetWindow(this);
                scannerWindow1.Closed += ScannerWindow1_Closed;
                scannerWindow1.Show();
            }
            else
            {
                scannerWindow1.Activate();
            }
        }
        private void Scan_Click_2(object sender, RoutedEventArgs e)
        {
            if (scannerWindow2 == null)
            {
                scannerWindow2 = new Scanner(this.lang("Tr.Zone2Scan"))
                {
                    Tag = "Zone2"
                };
                scannerWindow2.FinishBarcode += ScannerWindow_FinishBarcode;
                scannerWindow2.Owner = Window.GetWindow(this);
                scannerWindow2.Closed += ScannerWindow2_Closed;
                scannerWindow2.Show();
            }
            else
            {
                scannerWindow2.Activate();
            }
        }
        /// <summary>
        /// 扫码完成逻辑
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ScannerWindow_FinishBarcode(object sender, BarcodeEventArg e)
        {
            if (this.SequenceContext == null) return;
            CellInfo cellInfo = codeParser.GetCellInfoByCode(e.positionCode);
            string paramName = e.name == "Zone1" ? "StationState.StartScanner_A" : "StationState.StartScanner_B";
            testResultView.engine.Globals.SetValBoolean(paramName, 0, true);
            string positionCode = e.positionCode, snrCode = e.snrCode;
            //需要增加条码校验功能
            //将读到的条码写入到SN中
            int dutNo = Convert.ToInt16(positionCode.Split('-')[2]) - 1;
            string LookupStr = e.name == "Zone1" ? $"StationState.SN[{dutNo}]" : $"StationState.SN[{(dutNo + 54)}]";
            //this.SequenceContext.StationGlobals.SetValString(LookupStr, 0, snrCode);
            //string code = this.SequenceContext.StationGlobals.GetValString(LookupStr, 0);
            testResultView.engine.Globals.SetValString(LookupStr, 0, snrCode);
            string code = testResultView.engine.Globals.GetValString(LookupStr, 0);
            testResultView.nameTables[cellInfo.OvenName].GetSingleCell(cellInfo.Index).SetStatus("hadCode");
        }
        private void ScannerWindow1_Closed(object sender, EventArgs e)
        {
            scannerWindow1 = null;
        }
        private void ScannerWindow2_Closed(object sender, EventArgs e)
        {
            scannerWindow2 = null;
        }
        private void testResultView_Loaded(object sender, RoutedEventArgs e)
@@ -312,6 +416,80 @@
            testResultView.ClearNumber();
        }
        private void ScannerSetting_Click(object sender, RoutedEventArgs e)
        {
            Plugin.TestResult.ScannerSetting setting = new Plugin.TestResult.ScannerSetting()
            {
                Owner = Window.GetWindow(this)
            };
            setting.Open(false, "Config");
        }
        private void StdEnableMes_ValueChanged(object sender, StdUIEventArg e)
        {
            testResultView.executionWrapper.SetStationGlobalValue<bool>($"SystemSetting.{e.StringValue}", 1, e.BoolValue);
            //testResultView.SequenceContext?.StationGlobals.SetValBoolean($"SystemSetting.{e.StringValue}", 1, e.BoolValue);
        }
        public void HandleAlarm(AlarmText alarm)
        {
            if (alarm.Level >= 4 && TestResultView.tables != null)
            {
                log.Info($"4级报警触发: [{alarm.AlarmInfo}],将停止所有炉体测试");
                foreach (var oven in TestResultView.tables)
                {
                    testResultView.SetStartFlag(oven.index, false);
                }
                return;
            }
            DataTable targetOven = null;
            foreach (var oven in TestResultView.tables)
            {
                if (alarm.AlarmInfo?.StartsWith(oven.title) == true)
                {
                    targetOven = oven;
                    break;
                }
            }
            if (targetOven == null)
            {
                return;
            }
            if (alarm.Level >= 3)
            {
                /// 3级以上的报警会停止测试
                log.Info($"3级报警触发: [{alarm.AlarmInfo}],将停止老化炉[{targetOven.title}]测试");
                testResultView.SetStartFlag(targetOven.index, false);
            }
        }
        public override void Active()
        {
            base.Active();
            LoadProduct();
            RefreshUIConfig();
        }
        public override void OnClose(object sender, CancelEventArgs e)
        {
            if (IsRunning)
            {
                MsgBoxHelper2.Warn("请先停止老化测试!");
                e.Cancel = true;
            }
        }
        public override void DoClose(object sender, EventArgs e)
        {
            try
            {
                timer?.Stop();
                testResultView.ReleaseResource();
            }
            catch
            {
            }
        }
    }
}