alielie
2026-06-15 f08871fe7d148d667f2f11f80f64de71a0d9504c
Plugin.TestResult/TestResultView.xaml.cs
@@ -1,10 +1,10 @@
using HMI.Core.Util;
using HMI.Core.Entity;
using HMI.Core.Manager;
using HMI.Core.Util;
using HMI.UI.Util;
using NationalInstruments.TestStand.Interop.API;
using NationalInstruments.TestStand.Interop.UI.Ax;
using NationalInstruments.TestStand.Utility;
using Plugin.TestResult_WPF.Constant;
using Plugin.TestResult_WPF.Model;
using Plugin.TsSupport;
using System;
using System.Collections.Generic;
using System.Windows;
@@ -20,34 +20,111 @@
        private int rowCount;
        private int colCount;
        private int cellCount;
        private DataTable[] tables;
        public Dictionary<string, DataTable> nameTables { get; private set; }
        public static DataTable[] tables { get; private set; }
        public static Dictionary<string, DataTable> nameTables { get; private set; } = new Dictionary<string, DataTable>();
        private readonly BaseConfig config;
        public AxApplicationMgr testApp;
        public string testModelFile;
        public string testSeqFile;
        /// <summary>
        /// 测试序列
        /// </summary>
        private SequenceFile testSeq = null;
        public Engine engine;
        private Execution execution = null;
        /// <summary>
        /// 测试序列操作句柄
        /// </summary>
        public SequenceContext SequenceContext { get; private set; } = null;
        /// <summary>
        /// 测试模型序列
        /// </summary>
        private SequenceFile modeSeq;
        public bool inManualDebugMode = false;
        #region TS相关
        //public AxApplicationMgr testApp;
        ///// <summary>
        ///// 测试序列
        ///// </summary>
        //private SequenceFile testSeq = null;
        //public Engine engine;
        //private Execution execution = null;
        ///// <summary>
        ///// 测试序列操作句柄
        ///// </summary>
        //public SequenceContext SequenceContext { get; private set; } = null;
        ///// <summary>
        ///// 测试模型序列
        ///// </summary>
        //private SequenceFile modeSeq;
        public ITestExecutionWrapper executionWrapper;
        #endregion
        public TestResultView() : this(new BaseConfig { testing = false })
        {
        }
        public bool IsRunning { get; set; } = false;
        public void RefreshCooler()
        {
        }
        private void RefreshNumberConfig(BaseConfig config)
        {
            ParameterData value = null;
            try
            {
                value = ParameterManager.GetCommonParameterByName("BurnInOvenCount");
                string[] datas = value.Value.Trim().Split(',');
                config.Row = int.Parse(datas[0]);
                config.Column = int.Parse(datas[1]);
            }
            catch (Exception ex)
            {
            }
            try
            {
                value = ParameterManager.GetCommonParameterByName("BurnInOvenName");
                config.NameStr = value.Value;
            }
            catch (Exception ex)
            {
            }
            try
            {
                value = ParameterManager.GetCommonParameterByName("BurnInOvenPort");
                config.PortStart = int.Parse(value.Value);
            }
            catch (Exception ex)
            {
            }
            try
            {
                value = ParameterManager.GetCommonParameterByName("BurnInCellCount");
                string[] datas = value.Value.Trim().Split(',');
                config.PositionColumn = int.Parse(datas[0]);
                config.PositionCount = int.Parse(datas[1]);
            }
            catch (Exception ex)
            {
            }
        }
        public TestResultView(BaseConfig config)
        {
            try
            {
                var value = ParameterManager.GetCommonParameterByName("TsModelPath");
                testModelFile = 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"
                testModelFile = @"C:\Users\Public\Documents\National Instruments\TestStand 2020 (64-bit)\Components\Models\ParallelModel.seq";
            }
            RefreshNumberConfig(config);
            this.rowCount = config.Row;
            this.colCount = config.Column;
            this.config = config;
@@ -63,60 +140,29 @@
            InitializeComponent();
            testApp = new AxApplicationMgr();
            testApp.ExitApplication += new EventHandler(this.axApplicationMgr_ExitApplication);
            testApp.UIMessageEvent += new _ApplicationMgrEvents_UIMessageEventEventHandler(this.axApplicationMgr_UIMessageEvent);
            testApp.ExecutionClosed += new _ApplicationMgrEvents_ExecutionClosedEventHandler(this.axApplicationMgr_ExecutionClosed);
        }
            ((System.ComponentModel.ISupportInitialize)(this.testApp)).BeginInit();//myClient为第三方控件名
            host.Child = testApp;
            ((System.ComponentModel.ISupportInitialize)(this.testApp)).EndInit();
        private void ExecutionWrapper_UIMessageEvent(object sender, UIMessageEvent e)
        {
            try
            {
                HandleUIMessage(e.EventCode, Convert.ToInt16(e.NumberData), e.StrData, e.Data);
            }
            catch (Exception ex)
            {
            //InitTestStandEngine();
            //StartTestSequence();
            }
        }
        private void Refresh()
        {
            for (int i = 0; i < tables.Length; i++)
            {
                var sb = new System.Timers.Timer()
                {
                    Interval = 1000,
                    AutoReset = true,
                };
                var table = tables[i];
                Random random = new Random(i * 13);
                sb.Elapsed += (s, e) =>
                {
                    table.RefreshCount(1, 0);
                    table.SetTemperature(random.Next(100));
                    for (int j = 0; j < 3; j++)
                    {
                        table.SetTemperature(j + "89", random.Next(100));
                    }
                    //table.SetOkCount(random.Next(100));
                    //table.SetNgCount(random.Next(100));
                    table.SetStatus(CommonStatus.GetRandomStatus());
                    table.SetStartTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                    table.SetEndTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                    table.SetConsumeTime(random.Next(10000));
                    tables[0].GetSingleCell(0).AddElectricData(random.Next(100));
                    var cell = tables[0].GetSingleCell(0);//table.GetSingleCell(random.Next(table.GetSize()));
                    cell.SetStatus(CommonStatus.GetRandomStatus());
                    cell.SetInfos(new Info
                    {
                        step = random.Next(1000) + "",
                        value = random.Next(1000) + ""
                    });
                    table.SetStatusText(DateTime.Now + "");
                };
                sb.Start();
            }
        }
        /// <summary>
        /// 探针计数配置路径
        /// </summary>
        private string CountIniPath;
        public void SetCountIniPath(string countIniPath)
        {
@@ -162,17 +208,33 @@
        /// <summary>
        /// 启动测试序列
        /// </summary>
        public void InitTestStandEngine()
        public void InitTestStandEngine(bool isTap)
        {
            try
            {
                this.engine = this.testApp.GetEngine();
                this.engine.PersistBreakpoints = false;
                this.testApp.IsEditor = true;
                this.testApp.LoginOnStart = false;
                this.testApp.Start();
                this.modeSeq = this.engine.GetSequenceFileEx(@"C:\Program Files\National Instruments\TestStand 2020\Components\Models\TestStandModels\ParallelModel.seq");
                if (isTap)
                {
                    executionWrapper = new TapWrapper();
                }
                else
                {
                    executionWrapper = new TsExecutionWrapper();
                }
                executionWrapper.UIMessageEvent += ExecutionWrapper_UIMessageEvent;
                if (executionWrapper is TsExecutionWrapper tsWrapper)
                {
                    ((System.ComponentModel.ISupportInitialize)(tsWrapper.AxApplicationMgr)).BeginInit();
                    host.Child = tsWrapper.AxApplicationMgr;
                    ((System.ComponentModel.ISupportInitialize)(tsWrapper.AxApplicationMgr)).EndInit();
                }
                //this.engine = this.testApp.GetEngine();
                //this.engine.PersistBreakpoints = false;
                //this.testApp.IsEditor = true;
                //this.testApp.LoginOnStart = false;
                //this.testApp.Start();
                //this.modeSeq = this.engine.GetSequenceFileEx(testModelFile);
                executionWrapper.Init();
            }
            catch (Exception ex)
            {
@@ -185,10 +247,11 @@
        {
            try
            {
                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);
                this.engine.Globals.SetValBoolean("StationState.StopTest", 0, false);
                if (string.IsNullOrEmpty(testSeqFile)) return;
                executionWrapper?.StartSequence(this.testSeqFile,
                    @"C:\Program Files\National Instruments\TestStand 2020\Components\Models\TestStandModels\ParallelModel.seq");
                executionWrapper.SetStationGlobalValue<bool>("StationState.StopTest", 0, false);
            }
            catch (Exception ex)
            {
@@ -201,13 +264,24 @@
        {
            try
            {
                if (this.SequenceContext == null)
                    return;
                bool val = this.SequenceContext.StationGlobals.Exists("StationState.StopTest", 0);
                if (val)
                executionWrapper?.SetStationGlobalValue<bool>("StationState.StopTest", 0, true, true);
                try
                {
                    this.SequenceContext.StationGlobals.SetValBoolean("StationState.StopTest", 0, true);
                    bool isStop = this.execution.WaitForEndEx(2000, true, null, null);
                    executionWrapper?.WaitForExit();
                    executionWrapper?.ReleaseSeqFile();
                }
                catch (Exception ex)
                {
                    ViewControl.Logger.Error("Wait For Exit error.", ex);
                    //if (ex is NullReferenceException ne)
                    //{
                    //}
                    //else
                    //{
                    //    throw ex;
                    //}
                }
            }
            catch (Exception ex)
@@ -217,12 +291,14 @@
            }
        }
        [Obsolete]
        private void axApplicationMgr_ExitApplication(object sender, EventArgs e)
        {
            Environment.ExitCode = testApp.ExitCode;
            TSHelper.DoSynchronousGCForCOMObjectDestruction();
            //Environment.ExitCode = testApp.ExitCode;
            //TSHelper.DoSynchronousGCForCOMObjectDestruction();
        }
        [Obsolete]
        private void axApplicationMgr_ExecutionClosed(object sender, _ApplicationMgrEvents_ExecutionClosedEvent e)
        {
            try
@@ -236,27 +312,23 @@
            }
        }
        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;
                if (EventCase != 10014) return;
                if (MethodCode == 0)
                {
                    /// 设置句柄
                    this.SequenceContext = (SequenceContext)e.uiMsg.ActiveXData;
                    executionWrapper.SetContext(xData);
                    return;
                }
                if (MethodCode == 1)
                {
                    /// 更新炉子状态
                    strData = e.uiMsg.StringData;
                    string[] datas_10014 = strData.Split(';');
                    int ovenIndex = int.Parse(datas_10014[0]);
@@ -267,7 +339,6 @@
                if (MethodCode == 2)
                {
                    /// 更新炉子数量信息
                    strData = e.uiMsg.StringData;
                    string[] datas_10014 = strData.Split(';');
                    int ovenIndex = int.Parse(datas_10014[0]);
@@ -280,22 +351,26 @@
                if (MethodCode == 3)
                {
                    /// 更新炉子时间信息
                    strData = e.uiMsg.StringData;
                    string[] datas_10014 = strData.Split(';');
                    int ovenIndex = int.Parse(datas_10014[0]);
                    string startTime = datas_10014[1];
                    string consumeTime = datas_10014[2];
                    string planEndTime = datas_10014[3];
                    tables[ovenIndex].SetStartTime(startTime);
                    tables[ovenIndex].SetConsumeTime(double.Parse(consumeTime));
                    tables[ovenIndex].SetEndTime(planEndTime);
                    double? leftTime = null;
                    /// 为了兼容旧版本,如果有剩余时间就传,没有就传null
                    if (datas_10014.Length >= 5)
                    {
                        leftTime = double.Parse(datas_10014[4]);
                    }
                    tables[ovenIndex].UpdateConsumeTime(double.Parse(consumeTime), leftTime);
                    return;
                }
                if (MethodCode == 4)
                {
                    /// 更新老化炉底部状态栏
                    strData = e.uiMsg.StringData;
                    string[] datas_10014 = strData.Split(';');
                    int ovenIndex = int.Parse(datas_10014[0]);
@@ -306,7 +381,6 @@
                if (MethodCode == 5)
                {
                    /// 采集炉温度
                    strData = e.uiMsg.StringData;
                    string[] datas_10016 = strData.Split(';');
                    int ovenIndex = int.Parse(datas_10016[0]);
@@ -322,29 +396,28 @@
                }
                if (MethodCode == 6)
                {
                    /// 更新穴位状态
                    strData = e.uiMsg.StringData;
                    string[] datas_10015 = strData.Split(';');
                    int ovenIndex = int.Parse(datas_10015[0]);
                    int cellIndex = int.Parse(datas_10015[1]);
                    string status_10015 = datas_10015[2];
                    tables[ovenIndex].GetSingleCell(cellIndex).SetStatus(status_10015);
                    Dispatcher.Invoke(() =>
                    {/// 更新穴位状态
                        string[] datas_10015 = strData.Split(';');
                        int ovenIndex = int.Parse(datas_10015[0]);
                        int cellIndex = int.Parse(datas_10015[1]);
                        string status_10015 = datas_10015[2];
                        tables[ovenIndex].GetSingleCell(cellIndex).SetStatus(status_10015);
                    if (status_10015 == "OK" || status_10015 == "ok")
                    {
                        tables[ovenIndex].RefreshCount(1, 0);
                    }
                    else if (status_10015 == "ng" || status_10015 == "NG")
                    {
                        tables[ovenIndex].RefreshCount(0, 1);
                    }
                        if (status_10015 == "OK" || status_10015 == "ok")
                        {
                            tables[ovenIndex].RefreshCount(1, 0);
                        }
                        else if (status_10015 == "ng" || status_10015 == "NG")
                        {
                            tables[ovenIndex].RefreshCount(0, 1);
                        }
                    });
                    return;
                }
                if (MethodCode == 7)
                {
                    /// 更新穴位参数
                    strData = e.uiMsg.StringData;
                    string[] datas_10015 = strData.Split(';');
                    int ovenIndex = int.Parse(datas_10015[0]);
                    int cellIndex = int.Parse(datas_10015[1]);
@@ -358,17 +431,17 @@
                    {
                        step = values[0],
                        value = values[1],
                        result = values[2],
                        range = values[3],
                        condition = values[4],
                        updateTime = values[5]
                        limitUp = values[2],
                        limitDown = values[3],
                        unit = values[4],
                        result = values[5],
                        updateTime = values[6]
                    });
                    return;
                }
                if (MethodCode == 10)
                {
                    /// 清空炉子的温度图表
                    strData = e.uiMsg.StringData;
                    int ovenIndex = int.Parse(strData);
                    tables[ovenIndex].ClearChartData();
                    return;
@@ -376,18 +449,16 @@
                if (MethodCode == 11)
                {
                    /// 清除穴位参数
                    strData = e.uiMsg.StringData;
                    string[] datas_10015 = strData.Split(';');
                    int ovenIndex = int.Parse(datas_10015[0]);
                    int cellIndex = int.Parse(datas_10015[1]);
                    tables[ovenIndex].GetSingleCell(cellIndex).ClearInfo();
                    //GC.Collect();
                    return;
                }
                if (MethodCode == 12)
                {
                    /// 保存温度文件
                    ///
                    strData = e.uiMsg.StringData;
                    /// 保存炉体温度文件
                    string[] datas = strData.Split(';');
                    int ovenIndex = int.Parse(datas[0]);
                    string folder = datas[1];
@@ -397,7 +468,6 @@
                if (MethodCode == 13)
                {
                    /// 添加电流数据
                    strData = e.uiMsg.StringData;
                    string[] datas = strData.Split(';');
                    int ovenIndex = int.Parse(datas[0]);
                    int cellIndex = int.Parse(datas[1]);
@@ -405,23 +475,117 @@
                    tables[ovenIndex].GetSingleCell(cellIndex).AddElectricData(eData);
                    return;
                }
                if (MethodCode == 14)
                {
                    /// 清空电流数据
                    strData = e.uiMsg.StringData;
                    /// 清空电流和电压数据
                    int ovenIndex = int.Parse(strData);
                    tables[ovenIndex].ClearElectricData();
                    tables[ovenIndex].ClearCellData();
                    //tables[ovenIndex].ClearElectricData();
                    //tables[ovenIndex].ClearVData();
                    //tables[ovenIndex].ClearWaterData();
                    return;
                }
                if (MethodCode == 15)
                {
                    /// 清空电流数据
                    strData = e.uiMsg.StringData;
                    /// 保存电流数据
                    string[] datas = strData.Split(';');
                    int ovenIndex = int.Parse(datas[0]);
                    int cellIndex = int.Parse(datas[1]);
                    string filePath = datas[2];
                    tables[ovenIndex].GetSingleCell(cellIndex).SaveElectricDataToCSV(filePath);
                    return;
                }
                if (MethodCode == 16)
                {
                    /// 添加电压图表数据
                    string[] datas = strData.Split(';');
                    int ovenIndex = int.Parse(datas[0]);
                    int cellIndex = int.Parse(datas[1]);
                    double eData = double.Parse(datas[2]);
                    tables[ovenIndex].GetSingleCell(cellIndex).AddVData(eData);
                    return;
                }
                if (MethodCode == 17)
                {
                    /// 保存电压数据
                    string[] datas = strData.Split(';');
                    int ovenIndex = int.Parse(datas[0]);
                    int cellIndex = int.Parse(datas[1]);
                    string filePath = datas[2];
                    tables[ovenIndex].GetSingleCell(cellIndex).SaveVDataToCSV(filePath);
                    return;
                }
                if (MethodCode == 18)
                {
                    /// 保存穴位测试数据到CSV
                    string[] datas = strData.Split(';');
                    int ovenIndex = int.Parse(datas[0]);
                    int cellIndex = int.Parse(datas[1]);
                    string filePath = datas[2];
                    tables[ovenIndex].GetSingleCell(cellIndex).SaveInfoToCSV(filePath);
                    return;
                }
                if (MethodCode == 180)
                {
                    /// 保存穴位测试数据到CSV
                    string[] datas = strData.Split(';');
                    int ovenIndex = int.Parse(datas[0]);
                    int cellIndex = int.Parse(datas[1]);
                    string filePath = datas[2];
                    tables[ovenIndex].GetSingleCell(cellIndex).NormalCSV(filePath);
                    return;
                }
                if (MethodCode == 19)
                {
                    /// 保存穴位测试数据到Sqlite
                    string[] datas = strData.Split(';');
                    int ovenIndex = int.Parse(datas[0]);
                    int cellIndex = int.Parse(datas[1]);
                    tables[ovenIndex].GetSingleCell(cellIndex).SaveInfoToDB();
                    return;
                }
                if (MethodCode == 20)
                {
                    /// 清空条码
                    int ovenIndex = int.Parse(strData);
                    tables[ovenIndex].ClearAllSN();
                    return;
                }
                if (MethodCode == 21)
                {
                    /// 添加水流图表数据
                    string[] datas = strData.Split(';');
                    int ovenIndex = int.Parse(datas[0]);
                    int cellIndex = int.Parse(datas[1]);
                    double waterTemp = double.Parse(datas[2]);
                    double backWaterTemp = double.Parse(datas[3]);
                    double waterPressure = double.Parse(datas[4]);
                    tables[ovenIndex].GetSingleCell(cellIndex).AddWaterData(waterTemp, backWaterTemp, waterPressure);
                    return;
                }
                if (MethodCode == 99)
                {
                    string[] datas = strData.Split(';');
                    int index = int.Parse(datas[0]);
                    if (MsgBoxHelper2.WarnChoose(datas[1], "提示") == MessageBoxResult.OK)
                    {
                        executionWrapper.SetStationGlobalValue<int>($"StationState.Pipe[{index}]", 1, 1);
                        //SequenceContext.StationGlobals.SetValNumber($"StationState.Pipe[{index}]", 1, 1);
                    }
                    else
                    {
                        executionWrapper.SetStationGlobalValue<int>($"StationState.Pipe[{index}]", 1, 0);
                        //SequenceContext.StationGlobals.SetValNumber($"StationState.Pipe[{index}]", 1, 0);
                    }
                    return;
                }
            }
@@ -431,19 +595,27 @@
            }
        }
        private void axApplicationMgr_UIMessageEvent(object sender, _ApplicationMgrEvents_UIMessageEventEvent e)
        {
            int EventCase = Convert.ToInt32(e.uiMsg.Event);
            int MethodCode = Convert.ToInt16(e.uiMsg.NumericData);
            string strData = e.uiMsg.StringData;
            HandleUIMessage(EventCase, MethodCode, strData, e.uiMsg.ActiveXData);
        }
        public void SetStartFlag(int index, bool data)
        {
            if (this.SequenceContext == null) return;
            string name = tables[index].title;
            string key = $"StationState.Start_{name}";
            this.engine.Globals.SetValBoolean(key, 0, data);
            bool val = this.engine.Globals.GetValBoolean(key, 0);
            //this.SequenceContext.StationGlobals.SetValBoolean(key, 0, data);
            //bool val = this.SequenceContext.StationGlobals.GetValBoolean(key, 0);
            ViewControl.Logger?.Info($"将老化炉[{name}] 的Start变量设置为 {data};");
            string key = $"StationState.Start[{index}]";
            executionWrapper?.SetStationGlobalValue<bool>(key, 1, data);
        }
        public void ReleaseResource()
        {
            executionWrapper.UIMessageEvent -= ExecutionWrapper_UIMessageEvent;
            foreach (var table in tables)
            {
                table.RelaseResource();
@@ -471,16 +643,26 @@
        public void SetCurrentProduct(string currentProduct)
        {
            foreach (var table in tables)
            for (int i = 0; i < tables.Length; i++)
            {
                table.SetCurrentProduct(currentProduct);
                var table = tables[i];
                string LookupStr = $"StationState.Model[{i}]";
                string tableModel = executionWrapper?.GetStationGlobalValue<string>(LookupStr, 1);
                //engine?.Globals?.GetValString(LookupStr, 1);
                table.SetCurrentProduct(tableModel);
            }
        }
        public void SetOvenProduct(int index, string product)
        {
            string LookupStr = $"StationState.ProductModel_{tables[index].title}";
            engine?.Globals?.SetValString(LookupStr, 1, product);
            string LookupStr = $"StationState.Model[{index}]";
            executionWrapper?.SetStationGlobalValue<string>(LookupStr, 1, product);
            executionWrapper?.CommitToDisk(false);
        }
        public void RefreshProducts()
        {
        }
    }
}