alielie
2026-03-02 12e606635c42ea20f4b7c2bdda5204237a4b4c96
Plugin.TestResult/SingleCell.xaml.cs
@@ -1,7 +1,11 @@
using HMI.Core.Manager;
using CSVHelper;
using HMI.Core.Entity;
using HMI.Core.Manager;
using HMI.Core.Setting;
using HMI.Core.Util;
using HMI.UI.Util;
using HMI.Util;
using PLCHelper;
using Plugin.TestResult.Util;
using Plugin.TestResult_WPF.Constant;
using Plugin.TestResult_WPF.Model;
using System;
@@ -38,40 +42,12 @@
        }
        #endregion
        private static readonly HashSet<string> IgnoreTestItem = new HashSet<string> {
            "产品条码","checkin","预检电流","precheckresult","checkout",
        };
        private InfoWindow window;
        private int maxSize;
        private static string dataLogPath;
        private static int ProbeWarn;
        static SingleCell()
        {
            try
            {
                var value = ParameterManager.GetCommonParameterByName("TS_DataLogPath");
                dataLogPath = value?.Value ?? Path.Combine(PathHelper.ConfigFolder, "DataBoard");
            }
            catch
            {
                dataLogPath = Path.Combine(PathHelper.ConfigFolder, "DataBoard");
            }
            try
            {
                var value = ParameterManager.GetCommonParameterByName("ProbeWarn");
                ProbeWarn = value != null ? int.Parse(value.Value) : 1000;
            }
            catch
            {
                ProbeWarn = 1000;
            }
        }
        public SingleCell()
        {
            DataContext = this;
            InitializeComponent();
        }
        private DataTable table;
@@ -82,10 +58,79 @@
            this.index = index;
            this.maxSize = maxSize;
            this.countIniPath = iniFile;
            this.probeWarn = ProbeWarn;
            DataContext = this;
            InitializeComponent();
            LoadProbeCount();
            RefreshProbe();
        }
        public void RefreshProbe()
        {
            try
            {
                string key = string.Empty;
                ParameterData value;
                if (ParamSetting.ProbeByModel)
                {
                    string model = table.CbProduct?.SelectedItem?.ToString();
                    key = $"{title}_{model}";
                    value = ProductManager.GetParameterByProductAndName(model, "ProbeWarn");
                    if (value == null)
                    {
                        value = ParameterManager.GetCommonParameterByName("ProbeWarn");
                    }
                    ProbeWarn = value != null ? int.Parse(value.Value) : 1000;
                }
                else
                {
                    key = $"{title}";
                    value = ParameterManager.GetCommonParameterByName("ProbeWarn");
                    ProbeWarn = value != null ? int.Parse(value.Value) : 1000;
                }
                string temp = IniFileHelper.ReadIniData(key, "ProbeCount", "0", countIniPath);
                int count = Convert.ToInt32(temp);
                ProbeCount = count;
            }
            catch
            {
                ProbeWarn = 1000;
            }
            if (window != null) window.UpdateProbeCount(ProbeCount, ProbeWarn);
        }
        public void RefreshCharts()
        {
            charts = new LiveChart[3];
            try
            {
                ParameterData value;
                string model = table.CbProduct?.SelectedItem?.ToString();
                for (int i = 0; i < charts.Length; i++)
                {
                    value = ProductManager.GetParameterByProductAndName(model, $"ChartConfig_{i}");
                    if (value == null)
                    {
                        value = ParameterManager.GetCommonParameterByName($"ChartConfig_{i}");
                    }
                    var config = value != null ? value.Value : null;
                    if (string.IsNullOrEmpty(config))
                    {
                        charts[i] = null;
                    }
                    else
                    {
                        charts[i] = new LiveChart(config) //new string[] { "温度(℃)", "流量(L/m)" }
                        {
                            MinHeight = 120
                        };
                    }
                }
            }
            catch
            {
                charts = new LiveChart[0];
            }
        }
        private string _sn;
@@ -133,7 +178,7 @@
        }
        private int _probeWarn;
        public int probeWarn
        public int ProbeWarn
        {
            get => _probeWarn;
            set
@@ -193,7 +238,7 @@
            set
            {
                RaiseAndSetIfchanged(ref probeCount, value);
                probeAlarm = value >= probeWarn;
                probeAlarm = value >= ProbeWarn;
            }
        }
@@ -207,28 +252,24 @@
            }
        }
        public void LoadProbeCount()
        {
            string temp = IniFileHelper.ReadIniData($"{title}", "ProbeCount", "", countIniPath);
            if (!string.IsNullOrEmpty(temp))
            {
                int count = Convert.ToInt32(temp);
                ProbeCount = count;
            }
        }
        private void UpdateProbeCount(int count)
        {
            ProbeCount = count;
            IniFileHelper.WriteIniData($"{title}", "ProbeCount", ProbeCount.ToString(), countIniPath);
            if (window != null) window.UpdateProbeCount(ProbeCount);
            string key = $"{title}";
            if (ParamSetting.ProbeByModel)
            {
                string model = table?.CbProduct?.SelectedItem?.ToString();
                key = $"{title}_{model}";
            }
            IniFileHelper.WriteIniData(key, "ProbeCount", ProbeCount.ToString(), countIniPath);
            if (window != null) window.UpdateProbeCount(ProbeCount, ProbeWarn);
        }
        private void UserControl_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (window == null)
            {
                window = new InfoWindow(title, infos, electricChart, vChart, ProbeCount);
                window = new InfoWindow(title, infos, charts, ProbeCount, ProbeWarn);
                window.Closed += Window_Closed;
                window.ClearProbeCountEvent += Window_ClearProbeCountEvent;
                window.Owner = Window.GetWindow(this);
@@ -250,6 +291,9 @@
            this.window = null;
        }
        private string visualTestId;
        private Sqlite3Helper helper;
        public void SetStatus(string status)
        {
            var oldStatus = this.status;
@@ -257,12 +301,83 @@
            if (oldStatus != "testing" && status == "testing")
            {
                UpdateProbeCount(ProbeCount + 1);
                var now = DateTime.Now;
                string dateStr = now.ToString("yyyyMMdd");
                visualTestId = $"{title}_{now.ToString("yyyyMMddHHmmssfff")}";
                helper = CheckSqlHelper(dateStr);
            }
            if (oldStatus != "ok" && status == "ok")
            {
                SaveInfoToDB();
            }
            if (oldStatus != "ng" && status == "ng")
            {
                SaveInfoToDB();
            }
        }
        public void WriteCSV(Info info)
        {
            try
            {
                if (ParamSetting.CustomerCode != "LIXUN")
                {
                    return;
                }
                string fileName = this.sn?.Replace("/", "#")?.Replace("\\", "#") + ".csv";
                string dir = Path.Combine(ParamSetting.DataLogFolder, "csv", this.title);
                string title = $"{this.lang("Test.Name")},{this.lang("Test.Value")},{this.lang("Test.LimitDown")},{this.lang("Test.LimitUp")},{this.lang("Test.Unit")},{this.lang("Test.Result")},{this.lang("Test.TestTime")}";
                string line = $"{info.step},{info.value},{info.limitDown},{info.limitUp},{info.unit},{info.result},{info.updateTime}";
                CSVPrinter.Print(dir, fileName, title, line);
                // ReverseCSV(Path.Combine(dir, fileName));
            }
            catch (Exception ex)
            {
            }
        }
        public void SendToChart(Info info)
        {
            try
            {
                foreach (var chart in charts)
                {
                    if (chart?.CanHandle(info.step) == true)
                    {
                        chart.AddData(info.step, DateTime.Parse(info.updateTime), double.Parse(info.value));
                    }
                }
                //if (electricChart.CanHandle(info.step))
                //{
                //    electricChart.AddData(info.step, DateTime.Parse(info.updateTime), double.Parse(info.value));
                //}
                //if (vChart.CanHandle(info.step))
                //{
                //    vChart.AddData(info.step, DateTime.Parse(info.updateTime), double.Parse(info.value));
                //}
                //if (waterChart?.CanHandle(info.step) == true)
                //{
                //    waterChart?.AddData(info.step, DateTime.Parse(info.updateTime), double.Parse(info.value));
                //}
            }
            catch (Exception ex)
            {
            }
        }
        public void SetInfos(Info info)
        {
            string sql = string.Empty;
            try
            {
            allInfos.Add(info);
                SendToChart(info);
                WriteCSV(info);
            if (queue.Count >= maxSize)
            {
                queue.TryDequeue(out var first);
@@ -287,7 +402,37 @@
                        this.infos.Add(info);
                    });
                }
                return;
                }
                Dispatcher.Invoke(() =>
                {
                    string dateStr = string.Empty;
                    try
                    {
                        dateStr = DateTime.Parse(info.updateTime).ToString("yyyy-MM-dd HH:mm:ss");
                    }
                    catch
                    {
                        dateStr = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    }
                    try
                    {
                        string model = table?.CbProduct?.SelectedItem?.ToString();
                        sql = $@"INSERT INTO serialData (sn,model,station,position,step,limitDown,limitUp,unit,value,status,finalStatus,time,resultId)
VALUES ('{sn}','{model}','','{this.title}','{info.step}','{info.limitDown}','{info.limitUp}','{info.unit}','{info.value}','{info.result}',
NULL,'{dateStr}','{visualTestId}');";
                        helper.Execute(sql);
                    }
                    catch (Exception ex)
                    {
                        ViewControl.Logger.Error($"Save DB Test Data Error. {sql}", ex);
                    }
                });
            }
            catch (Exception ex)
            {
                ViewControl.Logger.Error($"Add Test Data Error. {sql}", ex);
            }
        }
@@ -300,41 +445,80 @@
            if (window != null) window.UpdateSource(this.infos);
        }
        private Chart electricChart = new Chart("电流曲线(A)", false, 20)
        //private Chart waterChart = null;
        //private Chart electricChart = new Chart(LangUtil.Get("Tr.CurrentChart"), false, 20)
        //{
        //    Height = 120
        //};
        //private Chart vChart = new Chart(LangUtil.Get("Tr.VoltChart"), false, 20)
        //{
        //    Height = 120
        //};
        private LiveChart[] charts = new LiveChart[0];
        //private LiveChart waterChart = null;
        //private LiveChart electricChart = new LiveChart("子板电流,电流(A);母板电流,电流(A)") //new string[] { "子板电流", "模板电流" }
        //{
        //    MinHeight = 120
        //};
        //private LiveChart vChart = new LiveChart("子板电压,电压(V);母板电压,电压(V)") //new string[] { "子板电压", "模板电压" }
        //{
        //    MinHeight = 120
        //};
        public void AddWaterData(double temp, double backTemp, double pressure)
        {
            Height = 150
        };
            //waterChart?.AddData(0, "水箱温度", temp);
            //waterChart?.AddData(0, "回水温度", backTemp);
            //waterChart?.AddData(1, "流量", pressure);
            //waterChart?.AddData("水箱温度", temp);
            //waterChart?.AddData("回水温度", backTemp);
            //waterChart?.AddData("流量", pressure);
        }
        public void AddElectricData(double data)
        {
            electricChart.AddData(data);
            //electricChart.AddData("", data);
        }
        public void ClearElectricData()
        {
            electricChart.Clear();
        }
        private Chart vChart = new Chart("电压曲线(V)", false, 20)
        {
            Height = 150
        };
        public void AddVData(double data)
        {
            vChart.AddData(data);
            //vChart.AddData("", data);
        }
        public void ClearVData()
        public void ClearChart()
        {
            vChart.Clear();
            foreach (var chart in charts)
            {
                chart?.Clear();
        }
        }
        //public void ClearWaterData()
        //{
        //    waterChart?.Clear();
        //}
        //public void ClearElectricData()
        //{
        //    electricChart.Clear();
        //}
        //public void ClearVData()
        //{
        //    vChart.Clear();
        //}
        public void SaveElectricDataToCSV(string filePath)
        {
            try
            {
                List<double> datas = electricChart?.GetSingleData();
                List<double> datas = charts[1]?.GetSingleData("");
                FileInfo fi = new FileInfo(filePath);
                if (!fi.Directory.Exists)
@@ -345,7 +529,7 @@
                using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
                using (StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.UTF8))
                {
                    string title = "电流数据(A)";
                    string title = this.lang("Tr.CurrentChart");
                    sw.WriteLine(title);
                    if (datas != null)
                    {
@@ -366,7 +550,7 @@
        {
            try
            {
                List<double> datas = vChart?.GetSingleData();
                List<double> datas = charts[2]?.GetSingleData("");
                FileInfo fi = new FileInfo(filePath);
                if (!fi.Directory.Exists)
@@ -377,7 +561,7 @@
                using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
                using (StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.UTF8))
                {
                    string title = "电压数据(V)";
                    string title = this.lang("Tr.VoltChart");
                    sw.WriteLine(title);
                    if (datas != null)
                    {
@@ -394,11 +578,7 @@
            }
        }
        /// <summary>
        /// 保存测试数据到CSV
        /// </summary>
        /// <param name="filePath"></param>
        public void SaveInfoToCSV(string filePath)
        private void NormalCSV(string filePath)
        {
            try
            {
@@ -411,7 +591,7 @@
                using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
                using (StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.UTF8))
                {
                    string title = "测试项,测试值,下限,上限,单位,结果,测试时间";
                    string title = $"{this.lang("Test.Name")},{this.lang("Test.Value")},{this.lang("Test.LimitDown")},{this.lang("Test.LimitUp")},{this.lang("Test.Unit")},{this.lang("Test.Result")},{this.lang("Test.TestTime")}";
                    sw.WriteLine(title);
                    foreach (var info in allInfos)
                    {
@@ -426,16 +606,165 @@
            }
        }
        private SqliteHelper CheckSqlHelper()
        private void ReverseCSV(string filePath)
        {
            string today = DateTime.Now.ToString("yyyyMMdd");
            string dbPath = Path.Combine(dataLogPath, $"Data_{today}.db");
            try
            {
                if (allInfos == null || allInfos.Count < 4) return;
                Dictionary<string, int> columnMap = new Dictionary<string, int>();
                int colPoint = 0;
                List<string> titleRow = new List<string>();
                List<string[]> datas = new List<string[]>();
                void AddTitle(string title)
                {
                    if (titleRow.IndexOf(title) < 0)
                    {
                        titleRow.Add(title);
                    }
                }
                // 先设置表头
                for (int row = 0; row < allInfos.Count; row++)
                {
                    var info = allInfos[row];
                    if (IgnoreTestItem.Contains(info.step.ToLower()))
                    {
                        continue;
                    }
                    string title = $"{info.step}{(string.IsNullOrEmpty(info.unit) ? "" : $"({info.unit})")}";
                    AddTitle("测试时间");
                    AddTitle(title);
                    if (!string.IsNullOrEmpty(info.limitDown))
                    {
                        string key2 = $"{info.step}下限";
                        AddTitle(key2);
                    }
                    if (!string.IsNullOrEmpty(info.limitUp))
                    {
                        string key2 = $"{info.step}上限";
                        AddTitle(key2);
                    }
                    if (!string.IsNullOrEmpty(info.limitUp))
                    {
                        string key2 = $"{info.step}测试结果";
                        AddTitle(key2);
                    }
                    //if (!string.IsNullOrEmpty(info.updateTime))
                    //{
                    //    string key2 = $"{info.step}测试时间";
                    //    AddTitle(key2);
                    //}
                }
                int rowPoint = -1;
                for (int row = 0; row < allInfos.Count; row++)
                {
                    var info = allInfos[row];
                    if (IgnoreTestItem.Contains(info.step.ToLower()))
                    {
                        continue;
                    }
                    string title = $"{info.step}{(string.IsNullOrEmpty(info.unit) ? "" : $"({info.unit})")}";
                    int col = titleRow.IndexOf(title);
                    if (col == 1)
                    {
                        rowPoint++;
                    }
                    if (datas.Count <= rowPoint)
                    {
                        datas.Add(new string[titleRow.Count]);
                    }
                    var arr = datas[rowPoint];
                    arr[col] = info.value;
                    if (!string.IsNullOrEmpty(info.limitDown))
                    {
                        string key2 = $"{info.step}下限";
                        int col2 = titleRow.IndexOf(key2);
                        arr[col2] = info.limitDown;
                    }
                    if (!string.IsNullOrEmpty(info.limitUp))
                    {
                        string key2 = $"{info.step}上限";
                        int col2 = titleRow.IndexOf(key2);
                        arr[col2] = info.limitUp;
                    }
                    if (!string.IsNullOrEmpty(info.limitUp))
                    {
                        string key2 = $"{info.step}测试结果";
                        int col2 = titleRow.IndexOf(key2);
                        arr[col2] = info.result;
                    }
                    if (!string.IsNullOrEmpty(info.updateTime))
                    {
                        string key2 = "测试时间";// $"{info.step}测试时间";
                        int col2 = titleRow.IndexOf(key2);
                        arr[col2] = info.updateTime;
                    }
                }
                FileInfo fi = new FileInfo(filePath);
                if (!fi.Directory.Exists)
                {
                    fi.Directory.Create();  //文件不存在,创建文件
                }
                using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
                using (StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.UTF8))
                {
                    string title = string.Join(",", titleRow);
                    sw.WriteLine(title);
                    foreach (var info in datas)
                    {
                        string row = string.Join(",", info);
                        sw.WriteLine(row);
                    }
                }
            }
            catch (Exception ex)
            {
                ViewControl.Logger.Error($"Cell[{title}] SaveInfoToCSV Error.", ex);
            }
        }
        /// <summary>
        /// 保存测试数据到CSV
        /// </summary>
        /// <param name="filePath"></param>
        public void SaveInfoToCSV(string filePath)
        {
            if (ParamSetting.ReverseCSV)
            {
                ReverseCSV(filePath);
            }
            else
            {
                NormalCSV(filePath);
            }
        }
        private Sqlite3Helper CheckSqlHelper(string dateStr = null)
        {
            dateStr = string.IsNullOrEmpty(dateStr) ? DateTime.Now.ToString("yyyyMMdd") : dateStr;
            string dbPath = Path.Combine(ParamSetting.DataLogFolder, $"Data_{dateStr}.db");
            if (!File.Exists(dbPath))
            {
                SqliteHelper.CreateDatabase(dbPath);
                Sqlite3Helper.CreateDatabase(dbPath);
            }
            var sqliteHelper = new SqliteHelper(dbPath);
            sqliteHelper.ExecuteSql(@"CREATE TABLE IF NOT EXISTS serialData (
            var sqliteHelper = new Sqlite3Helper(dbPath);
            sqliteHelper.Execute(@"CREATE TABLE IF NOT EXISTS serialData (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    sn TEXT NOT NULL,
                    model TEXT,
@@ -451,8 +780,9 @@
                    finalStatus TEXT,
                    consumeTime TEXT, 
                    totalConsumeTime TEXT, 
                    resultId TEXT,
                    time DATETIME NOT NULL);");
            sqliteHelper.ExecuteSql(@"CREATE TABLE IF NOT EXISTS testResult (
            sqliteHelper.Execute(@"CREATE TABLE IF NOT EXISTS testResult (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    sn TEXT NOT NULL,
                    model TEXT,
@@ -460,7 +790,16 @@
                    position TEXT,
                    status TEXT,
                    result TEXT NOT NULL, 
                    resultId TEXT,
                    time DATETIME NOT NULL);");
            if (!sqliteHelper.HasData("SELECT 1 FROM pragma_table_info('serialData') WHERE name = 'resultId';"))
            {
                sqliteHelper.Execute("ALTER TABLE serialData ADD resultId TEXT;");
            }
            if (!sqliteHelper.HasData("SELECT 1 FROM pragma_table_info('testResult') WHERE name = 'resultId';"))
            {
                sqliteHelper.Execute("ALTER TABLE testResult ADD resultId TEXT;");
            }
            return sqliteHelper;
        }
@@ -470,26 +809,34 @@
        /// <param name="filePath"></param>
        public void SaveInfoToDB()
        {
            Dispatcher.BeginInvoke(new Action(() =>
            {
            try
            {
                using (var helper = CheckSqlHelper())
                {
                    List<string> sqls = new List<string>();
                    var timestr = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    foreach (var info in allInfos)
                    {
                        string sql = $@"INSERT INTO serialData (sn,station,step,limitDown,limitUp,unit,value,status,finalStatus,time)
VALUES ('{sn}','','{info.step}','{info.limitDown}','{info.limitUp}','{info.unit}','{info.value}','{info.result}','{this.status}','{timestr}');";
                        sqls.Add(sql);
                    }
                    sqls.Add($"INSERT INTO testResult (sn,station,position,result,time) VALUES ('{sn}','','{title}','{this.status}','{timestr}');");
                    helper.ExecuteBatchSql(sqls);
                }
                    var sql = $"INSERT INTO testResult (sn,station,position,result,time,resultId) VALUES ('{sn}','','{title}','{this.status}','{timestr}','{visualTestId}');";
                    helper.Execute(sql);
                    helper.Dispose();
                    helper = null;
                    //                using (var helper = CheckSqlHelper())
                    //                {
                    //                    List<string> sqls = new List<string>();
                    //                    var timestr = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    //                    foreach (var info in allInfos)
                    //                    {
                    //                        string sql = $@"INSERT INTO serialData (sn,station,step,limitDown,limitUp,unit,value,status,finalStatus,time)
                    //VALUES ('{sn}','','{info.step}','{info.limitDown}','{info.limitUp}','{info.unit}','{info.value}','{info.result}','{this.status}','{timestr}');";
                    //                        sqls.Add(sql);
                    //                    }
                    //                    sqls.Add($"INSERT INTO testResult (sn,station,position,result,time) VALUES ('{sn}','','{title}','{this.status}','{timestr}');");
                    //                    helper.ExecuteBatchSql(sqls);
                    //                }
            }
            catch (Exception ex)
            {
                ViewControl.Logger.Error($"Cell[{title}] SaveToDB Error.", ex);
            }
            }));
        }
        private void MenuItem_Click(object sender, RoutedEventArgs e)
@@ -500,9 +847,43 @@
                case "clearSNRItem":
                    table.TryClearCellSN(this.index);
                    break;
                case "exportCSVItem":
                    TryExportCSV();
                    break;
                default:
                    break;
            }
        }
        private void TryExportCSV()
        {
            System.Windows.Forms.SaveFileDialog sfd = new System.Windows.Forms.SaveFileDialog
            {
                Filter = "CSV (*.csv)|*.csv"
            };
            if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.SaveInfoToCSV(sfd.FileName);
            }
        }
        public void ClearSN()
        {
            sn = string.Empty;
            LightGreen(false, out _);
            LightRed(false, out _);
        }
        public bool LightGreen(bool on, out string msg)
        {
            return S7Context.WriteData(RunTimeVariablePool.DEFAULT_PLC_NAME,
                $"Oven{table.index + 1}_Cell{index + 1}_Light_OK", on, out msg);
        }
        public bool LightRed(bool on, out string msg)
        {
            return S7Context.WriteData(RunTimeVariablePool.DEFAULT_PLC_NAME,
                $"Oven{table.index + 1}_Cell{index + 1}_Light_NG", on, out msg);
        }
    }
}