kingno
2025-04-10 655481176b286fa91ef9d171fd8cbfac2be2545a
打印机,数据库格式更新
9个文件已修改
558 ■■■■ 已修改文件
libs/PFW/Bro.Common.Model.dll 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M135.Common/ProductModel.cs 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M135.DBManager/Models/P_PRODUCT_DETAIL.cs 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M141.Process/M141Config.cs 162 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M141.Process/M141Process.cs 286 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M141.Process/M141Process_Mysql.cs 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M141.Process/UI/UIPrinter.cs 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M141_AOI1.Process/AOI1Process.cs 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M141_AOI1.Process/Bro.M141_AOI1.Process.csproj 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
libs/PFW/Bro.Common.Model.dll
Binary files differ
src/Bro.M135.Common/ProductModel.cs
@@ -194,10 +194,12 @@
                });
            });
            allSpecs.RemoveAll(u => (u.Code.ToLower() == "ngspec" || u.Code == "检测TBD"));
            head = $"时间,PID,栏具码,物料码,条码,汇总检测结果,";
            positionList = new List<string>();
            Details = Details.OrderBy(u => u.PositionName).ToList();
            Details = Details.OrderBy(u => u.STATION_CODE).ThenBy(u => u.PositionName).ToList();
            foreach (var d in Details)
            {
                positionList.Add($"{d.STATION_CODE}_{d.PositionName}");
@@ -303,6 +305,8 @@
                });
            });
            allSpecs.RemoveAll(u => u.Code.ToLower() == "ngspec" || u.Code == "检测TBD");
            head = $"时间,栏具码,PID,序号,条码,";
            foreach (var d in positionDetail)
@@ -380,22 +384,22 @@
                }
            });
            positionDetail.ForEach(detail =>
            {
                if (detail.IsDone)
                {
            //positionDetail.ForEach(detail =>
            //{
            //    if (detail.IsDone)
            //    {
                    var results = detail.ResultList;
            //        var results = detail.ResultList;
                    var list = results.Where((DetectResult u) => u.ResultState != EnumHelper.ResultState.OK).SelectMany((DetectResult u) => u.NetResults.Where((NetResult m) => !m.IsAbandoned && m.CurResult != EnumHelper.ResultState.OK).SelectMany((NetResult m) => from n in m.DetectDetails where !n.IsAbandoned && n.FinalResult != EnumHelper.ResultState.OK select n)).ToList();
            //        var list = results.Where((DetectResult u) => u.ResultState != EnumHelper.ResultState.OK).SelectMany((DetectResult u) => u.NetResults.Where((NetResult m) => !m.IsAbandoned && m.CurResult != EnumHelper.ResultState.OK).SelectMany((NetResult m) => from n in m.DetectDetails where !n.IsAbandoned && n.FinalResult != EnumHelper.ResultState.OK select n)).ToList();
                    list.ForEach(d =>
                    {
                        data += $"{(d.Rect.Height * d.PixelSize).ToString("f4")},";
                        data += $"{(d.Rect.Width * d.PixelSize).ToString("f4")},";
                    });
                }
            });
            //        list.ForEach(d =>
            //        {
            //            data += $"{(d.Rect.Height * d.PixelSize).ToString("f4")},";
            //            data += $"{(d.Rect.Width * d.PixelSize).ToString("f4")},";
            //        });
            //    }
            //});
src/Bro.M135.DBManager/Models/P_PRODUCT_DETAIL.cs
@@ -14,11 +14,11 @@
        public string FAIData { get; set; } = "";
        public bool IsDone { get; set; } = false;
        //[NotMapped]
        [NotMapped]
        public List<DetectResult> ResultList { get; set; } = new List<DetectResult>();
        //[NotMapped]
        [NotMapped]
        public List<ISpec> SpecList { get; set; } = new List<ISpec>();
        //[NotMapped]
        [NotMapped]
        public List<string> DefectList { get; set; } = new List<string>();
    }
}
src/Bro.M141.Process/M141Config.cs
@@ -6,9 +6,11 @@
using Bro.Common.Model;
using Bro.M135.Common;
using Bro.Process;
using Newtonsoft.Json;
using System.ComponentModel;
using System.Drawing.Design;
using System.Drawing.Imaging;
using System.Drawing.Printing;
using System.Reflection;
using System.Windows.Forms.Design;
@@ -16,6 +18,15 @@
{
    public class M141Config : ProcessConfigBase
    {
        [Category("打印机配置")]
        [Description("打印机配置集合")]
        [DisplayName("打印机配置集合")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<Printer>), typeof(UITypeEditor))]
        public List<Printer> Printers { get; set; } = new List<Printer>();
        [Category("产品显示界面配置")]
        [Description("字体大小")]
        [DisplayName("字体大小")]
@@ -125,10 +136,18 @@
        public bool Isreadbasketcode { get; set; } = false;
        //[Category("数据库配置")]
        //[Description("是否为终点设备")]
        //[DisplayName("是否为终点设备")]
        //public bool IsfinDevice { get; set; } = false;
        [Category("PLC配置")]
        [Description("报警配置")]
        [DisplayName("报警配置")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<PLCAlarms>), typeof(UITypeEditor))]
        public List<PLCAlarms> PLCAlarm { get; set; } = new List<PLCAlarms>();
        [Category("PLC配置")]
        [Description("心跳地址")]
        [DisplayName("心跳地址")]
        public int heartadd { get; set; } = 1505;
    }
@@ -192,6 +211,72 @@
            return $"{(IsEnabled ? "" : "禁用")} 工位 {PositionName} 交互触发值:{TriggerValue}";
        }
    }
    public class PLCAlarms : IComplexDisplay
    {
        [Category("PLC配置")]
        [DisplayName("plc名称")]
        [Description("plc名称")]
        [TypeConverter(typeof(DeviceIdSelectorConverter<PLCBase>))]
        public string plcname { get; set; } = "";
        [Category("PLC配置")]
        [DisplayName("是否启用")]
        [Description("是否启用")]
        public bool isused { get; set; } = true;
        [Category("报警配置")]
        [Description("报警详情")]
        [DisplayName("报警详情")]
        [TypeConverter(typeof(CollectionCountConvert))]
        [Editor(typeof(ComplexCollectionEditor<PLCAlarmDetails>), typeof(UITypeEditor))]
        public List<PLCAlarmDetails> AlarmDetails { get; set; } = new List<PLCAlarmDetails>();
        public string GetDisplayText()
        {
            return plcname + (isused ? "启用" : "禁用");
        }
    }
    public class PLCAlarmDetails : IComplexDisplay
    {
        [Category("配置")]
        [DisplayName("首地址")]
        [Description("首地址")]
        public int address { get; set; }
        [Category("配置")]
        [DisplayName("子地址")]
        [Description("子地址")]
        public int address2 { get; set; }
        [Category("配置")]
        [DisplayName("报警名称")]
        [Description("报警名称")]
        public string alarmname { get; set; } = "";
        [Browsable(false)]
        [JsonIgnore]
        public int value { get; set; } = -1;
        public string GetDisplayText()
        {
            return alarmname;
        }
    }
@@ -412,6 +497,43 @@
    }
    public class Printer : IComplexDisplay
    {
        [Category("打印机配置")]
        [DisplayName("名称")]
        [Description("名称")]
        [TypeConverter(typeof(DevicePrinter))]
        public string name { get; set; } = "";
        [Category("打印机配置")]
        [DisplayName("位置")]
        [Description("位置")]
        public string station { get; set; }
        [Category("PLC配置")]
        [DisplayName("plc名称")]
        [Description("plc名称")]
        [TypeConverter(typeof(DeviceIdSelectorConverter<PLCBase>))]
        public string plcname { get; set; }
        [Category("PLC配置")]
        [DisplayName("状态地址")]
        [Description("状态地址")]
        public int addstate { get; set; }
        [Category("PLC配置")]
        [DisplayName("结果地址")]
        [Description("结果地址")]
        public int addresult { get; set; }
        public string GetDisplayText()
        {
            return name;
        }
    }
@@ -585,7 +707,7 @@
                    string filePath = "";
                    if (saveFileDialog.ShowDialog() == DialogResult.OK)
                    {
                         filePath = saveFileDialog.FileName; // 获取用户选择的文件路径
                        filePath = saveFileDialog.FileName; // 获取用户选择的文件路径
                    }
                    else
                    {
@@ -612,6 +734,36 @@
        }
    }
    public class DevicePrinter : ComboBoxItemTypeConvert
    {
        public override Dictionary<string, string> GetConvertDict(ITypeDescriptorContext context)
        {
            Dictionary<string, string> table = new Dictionary<string, string>();
            table[""] = "未指定";
            PrintDocument print = new PrintDocument();
            string sDefault = print.PrinterSettings.PrinterName;//默认打印机名
            foreach (string sPrint in PrinterSettings.InstalledPrinters)//获取所有打印机名称
            {
                table[sPrint] = sPrint;
            }
            return table;
        }
    }
    [Device("ImageCheck", "图片检测操作配置", EnumHelper.DeviceAttributeType.OperationConfig)]
    public class ImageCheckOperationConfigBase : OperationConfigBase, IHalconToolPath, IImageCheckOperationConfig
    {
src/Bro.M141.Process/M141Process.cs
@@ -22,7 +22,11 @@
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using Windows.ApplicationModel.Appointments;
using ZXing;
using static Bro.Common.Helper.EnumHelper;
using static Bro.Process.ProcessControl;
using static Org.BouncyCastle.Math.EC.ECCurve;
namespace Bro.M141.Process
@@ -52,10 +56,20 @@
        M141Process_Mysql mysqlhelper = new M141Process_Mysql();
        public override void InitialProcessMethods()
        {
            base.InitialProcessMethods();
            if (ThHeartPlc == null)
            {
                ThHeartPlc = new Thread(Heartplc);
                ThHeartPlc.IsBackground = true;
                ThHeartPlc.Start();
            }
        }
        public override void ProcessRunStateChanged()
@@ -72,11 +86,16 @@
        }
        public PLCBase Plc1;
        bool devicestate = false;
        PLCBase Plc2;
        Thread ThHeartPlc;
        public Thread ThHeartPlc;
        public override void Open()
        {
            base.Open();
            devicestate = true;
            ML = DeviceCollection.FirstOrDefault(u => u is MachineLearningBase) as MachineLearningBase;
            if (ML == null)
            {
@@ -99,42 +118,117 @@
            mysqlhelper.IniDBIP(M141Config.IPforall);
            if (ThHeartPlc == null)
            {
                ThHeartPlc = new Thread(Heartplc);
                ThHeartPlc.IsBackground = true;
                ThHeartPlc.Start();
            }
        }
        public override void Close()
        {
            devicestate = false;
            base.Close();
            try
            {
                if (ThHeartPlc != null)
                {
                    ThHeartPlc.Abort();
                }
            }
            catch
            {
            }
            ThHeartPlc = null;
        }
        public void Heartplc()
        {
            while (true)
            Thread.Sleep(1000);
            string _statisticFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Statistic.json");
            if (File.Exists(_statisticFilePath))
            {
                try
                {
                    if (Plc1 != null)
                    string dataStr = "";
                    using (StreamReader reader = new StreamReader(_statisticFilePath, System.Text.Encoding.UTF8))
                    {
                        Plc1.WriteSingleAddress(1505, 0, out _);
                        dataStr = reader.ReadToEnd();
                    }
                    lock (StatisticRecordsFull)
                    {
                        var temRecords = JsonConvert.DeserializeObject<StatisticRecords_Full>(dataStr);
                        if (StatisticRecordsFull != null && temRecords != null)
                        {
                            StatisticRecordsFull.CurRecord = temRecords.CurRecord;
                            StatisticRecordsFull.HistoryRecord = temRecords.HistoryRecord;
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"产品统计信息反序列化异常");
                    StatisticRecordsFull = new StatisticRecords_Full();
                }
            }
            int numsum = 0;
            //List<int> Statelist = new List<int>();
            Dictionary<string, List<int>> StateDIC = new Dictionary<string, List<int>>();
            int numplc = 0;
            while (true)
            {
                numplc++;
                numsum++;
                if (!devicestate)
                {
                    Thread.Sleep(1000);
                    continue;
                }
                try
                {
                    if (M141Config.WorkShiftList != null && M141Config.WorkShiftList.Count > 0 && numsum >= 0)
                    {
                        for (int i = 0; i < M141Config.WorkShiftList.Count; i++)
                        {
                            if (M141Config.WorkShiftList[i].IsClearProductSummary)
                            {
                                double timeshap = (DateTime.Now - M141Config.WorkShiftList[i].ShiftTime_Start).TotalMinutes % 1440;
                                if (timeshap > 0 && timeshap < 1)
                                {
                                    StatisticRecordsFull.CurRecord.ProductSummary.RecordsList.Clear();
                                    StatisticRecordsFull.CurRecord.DefectSummary.RecordsList.Clear();
                                    numsum = -62;
                                }
                            }
                        }
                    }
                    lock (StatisticRecordsFull)
                    {
                        if (numsum > 20)
                        {
                            numsum = 0;
                            using (FileStream fileStream = new FileStream(_statisticFilePath, FileMode.OpenOrCreate, FileAccess.Write))
                            {
                                fileStream.Seek(0L, SeekOrigin.Begin);
                                string s = JsonConvert.SerializeObject(StatisticRecordsFull);
                                byte[] bytes = Encoding.UTF8.GetBytes(s);
                                fileStream.Write(bytes, 0, bytes.Length);
                                fileStream.SetLength(bytes.Length);
                                fileStream.Flush();
                                fileStream.Close();
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                }
                try
                {
                    if (numplc > 3)
                    {
                        numplc = 0;
                        if (Plc1 != null)
                        {
                            Plc1.WriteSingleAddress(M141Config.heartadd, 0, out _);
                        }
                    }
                }
                catch
@@ -142,7 +236,91 @@
                }
                Thread.Sleep(3000);
                try
                {
                    string csvhead = "时间";
                    string csvdata = DateTime.Now.ToString("yyyyMMddHHmmss") + "T";
                    if (Plc1 != null)
                    {
                        foreach (var item1 in M141Config.PLCAlarm)
                        {
                            try
                            {
                                if (!item1.isused)
                                {
                                    continue;
                                }
                                var alrams = item1.AlarmDetails;
                                var plcdev = DeviceCollection.FirstOrDefault(u => u.Id == item1.plcname) as PLCBase;
                                if (!StateDIC.ContainsKey(plcdev.Name))
                                {
                                    StateDIC[plcdev.Name] = new List<int>();
                                }
                                foreach (var item in alrams.GroupBy(u => u.address))
                                {
                                    int add = item.Key;
                                    var readres = plcdev.Read(add, 1, out _)[0];
                                    var Allbin = Convert.ToString(readres, 2).PadLeft(16, '0').Select(c => c - '0').ToArray();
                                    Allbin = Allbin.Reverse().ToArray();
                                    foreach (var item2 in item)
                                    {
                                        item2.value = Allbin[item2.address2];
                                    }
                                }
                                List<int> list = new List<int>();
                                foreach (var item in alrams)
                                {
                                    csvhead += $",{item.alarmname}";
                                    csvdata += $",{(item.value == 1 ? "1" : "")}";
                                    list.Add(item.value);
                                }
                                if (!StateDIC[plcdev.Name].SequenceEqual(list))
                                {
                                    StateDIC[plcdev.Name].Clear();
                                    StateDIC[plcdev.Name].AddRange(list);
                                    CSVRecordAsync($"PLCstate_{plcdev.Name}.csv", csvdata, csvhead);
                                    var showdata = alrams.Where(u => u.value == 1).Select(u => u.alarmname).ToList();
                                    if (showdata == null)
                                    {
                                        showdata = new List<string>();
                                    }
                                    if (showdata.Count > 0)
                                    {
                                        LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"{plcdev.Name}报警 个数:{showdata.Count}  {string.Join(',', showdata)}");
                                    }
                                    else
                                    {
                                        LogAsync(DateTime.Now, EnumHelper.LogLevel.Detail, $"{plcdev.Name}报警 个数:0");
                                    }
                                }
                            }
                            catch
                            {
                            }
                        }
                    }
                }
                catch
                {
                }
                Thread.Sleep(1000);
            }
        }
@@ -152,7 +330,6 @@
        /// <exception cref="NotImplementedException"></exception>
        private void NetWarmUp()
        {
            string warmUpImageFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "WarmUp");
            if (!Directory.Exists(warmUpImageFolder))
            {
@@ -263,19 +440,6 @@
            if (isSaveDB)
            {
                if (M141Config.Isreadbasketcode)
                {
                    p.BasketCode = M141Config.basketcode;
                }
                else
                {
                    p.BasketCode = mysqlhelper.Getbasketcode(p.SEQUENCE);
                    if ("NoRead".Equals(p.BasketCode))
                    {
                        LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"{p.PID}_{p.SEQUENCE}获取框具码失败 赋值Noread");
                    }
                }
                mysqlhelper.NewProduct(p);
            }
@@ -307,9 +471,8 @@
                    p.PID = p.PID + "_" + sequence.Split('_')[sequence.Split('_').Length - 1];
                    p.Initial(M141Config.StationCode, M141Config.WorkPositionCollection.Where(u => u.IsEnabled).Select(u => u.PositionName).ToList());
                    LogAsync(DateTime.Now, EnumHelper.LogLevel.Warning, $"未能从数据库获取产品对象,使用临时新建产品对象");
                    LogAsync(DateTime.Now, EnumHelper.LogLevel.Warning, $"未能从数据库获取产品对象,使用临时新建产品对象   {sequence}");
                }
                NewProductIntoList(p, false);
            }
@@ -373,7 +536,7 @@
                                    var errorSpec = _errorSpec.Copy();
                                    errorSpec.Code = "检测TBD";
                                    errorSpec.ActualValue = -999;
                                    DetectResult ngResult = new DetectResult() { Specs = new List<ISpec>() { errorSpec }, PID = u.Key ,Id=Guid.NewGuid().ToString()};
                                    DetectResult ngResult = new DetectResult() { Specs = new List<ISpec>() { errorSpec }, PID = u.Key, Id = Guid.NewGuid().ToString() };
                                    ngResults.Add(ngResult);
                                }
                            }
@@ -725,7 +888,7 @@
                            imgSetDicts[b] = CollectHImage(camera, b.SnapshotOpConfig);
                            if (positionSet.ispiccover)
                            {
                                Plc1.WriteSingleAddress(positionSet.plcover,1,out _);
                                Plc1.WriteSingleAddress(positionSet.plcover, 1, out _);
                            }
                        }
                        catch (Exception ea)
@@ -827,6 +990,20 @@
                    p.SEQUENCE = $"{tempSequence}_{i}";
                    p.PID = $"{pidstr}T_{i}";
                    if (M141Config.Isreadbasketcode)
                    {
                        p.BasketCode = M141Config.basketcode;
                    }
                    else
                    {
                        p.BasketCode = mysqlhelper.Getbasketcode(p.SEQUENCE, out string sntem);
                        p.SN = sntem;
                        if ("NoRead".Equals(p.BasketCode))
                        {
                            LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"{p.PID}_{p.SEQUENCE}获取框具码失败 赋值Noread");
                        }
                    }
                    if (positionSet.IsLastPosition)
                    {
                        p.Initial(M141Config.StationCode, new List<string>() { positionSet.PositionName });
@@ -839,9 +1016,9 @@
                });
            });
            Thread.Sleep(50);
            int de = 0;
            measureBinds.Where(b => (b.CheckIndex == de || b.CheckIndex == 1) && b.ImageIndex == 0).AsParallel().ForAll(b =>
            {
                List<int> temint = new List<int>();
@@ -943,14 +1120,14 @@
                        List<string> specHeads = new List<string>();
                        string head = p.GetCSVHead(ref specHeads, positionName);
                        _positionSpecHeads[positionName] = specHeads;
                        //_positionSpecHeads[positionName] = specHeads;
                        string data = p.GetCSVData(_positionSpecHeads[positionName], positionName);
                        string data = p.GetCSVData(specHeads, positionName);
                        CSVRecordAsync($"{positionName}_Record_{DateTime.Now.ToString("yyyyMMdd")}.csv", data, head);
                        //UpdatePositionResultToDB(detail);
                        //var seqData = p.SEQUENCE.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                        ReplyPlcData(positionSet, plcresult);
                        mysqlhelper.UpdateProduct(p);
                        if (positionSet.IsLastPosition)
                        {
@@ -962,7 +1139,7 @@
                            }
                        }
                    });
                    ReplyPlcData(positionSet, plcresult);
                    //ReplyPlcData(positionSet, plcresult);
                    if (positionSet.IsLastPosition)
                    {
                        if (_ct != null)
@@ -1008,25 +1185,20 @@
        }
        public void SummaryAllprodata(ProductModel p)
        {
            _taskFactory.StartNew(() =>
            {
                try
                {
                    ProductModel newp = new ProductModel();
                    newp.SEQUENCE = p.SEQUENCE;
                    newp.PID = p.PID;
                    newp.BasketCode = p.BasketCode;
                    newp.Result = p.Result;
                    newp.SN = p.SN;
                    newp.Details.AddRange(p.Details);
                    var plist = mysqlhelper.GetProductList(p.SEQUENCE);
                    if (plist != null)
                    {
@@ -1036,21 +1208,21 @@
                        }
                    }
                    //newp.Details.AddRange(p.Details);
                    List<string> specHeadListforall = new List<string>();
                    List<string> positionListforall = new List<string>();
                    string csvHeadforall = p.GetCSVHead(ref specHeadListforall, ref positionListforall);
                    CSVRecordAsync($"AllDeviceProductRecord.csv", p.GetCSVData(specHeadListforall, positionListforall), csvHeadforall);
                    string csvHeadforall = newp.GetCSVHead(ref specHeadListforall, ref positionListforall);
                    CSVRecordAsync($"AllDeviceProductRecord.csv", newp.GetCSVData(specHeadListforall, positionListforall), csvHeadforall);
                }
                catch(Exception exx)
                catch (Exception exx)
                {
                    LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, "AllDeviceProductRecord数据汇总异常  " + exx.ToString());
                }
            });
        }
src/Bro.M141.Process/M141Process_Mysql.cs
@@ -12,6 +12,7 @@
using System.Text;
using System.Threading.Tasks;
using Windows.Globalization.PhoneNumberFormatting;
using Windows.Media.Ocr;
using static Org.BouncyCastle.Math.EC.ECCurve;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ListView;
@@ -22,7 +23,6 @@
        string connStrAll = "server=localhost;port=3306;user id=root;password=123456;database=BroDB;charset=utf8";
        string connStrLocal = "server=localhost;port=3306;user id=root;password=123456;database=BroDB;charset=utf8";
        #region 基础操作
@@ -145,33 +145,18 @@
        {
            try
            {
                if (pro.Details!=null)
                Thread.Sleep(200);
                if (pro.Details != null)
                {
                    foreach (var item in pro.Details)
                    {
                        if (item.ResultList!=null)
                        if (item != null)
                        {
                            item.ResultList.ForEach(u =>
                            {
                                if (u.NetResults != null)
                                {
                                    u.NetResults.ForEach(x =>
                                    {
                                        if (x.DetectDetails != null)
                                        {
                                            var distinctItems = x.DetectDetails.GroupBy(i => new { i.ClassName, i.FinalResult }) // 根据Id和Name去重
                             .Select(g => g.First()) // 选择每个组的第一个元素
                             .ToList();
                                            x.DetectDetails = distinctItems;
                                        }
                                    });
                                }
                            });
                            var defects = item.ResultList.GetDefectDescList();
                            item.DefectList.AddRange(defects);
                        }
                    }
                }
                JsonSerializerSettings settings = new JsonSerializerSettings
                {
@@ -206,7 +191,6 @@
            {
                try
                {
                    //保留数据库最新的1000条数据
                    //string destr = "delete from forall where id not in (select id from (select id from forall order BY id desc limit 1000) as subquery)";
                    //Operatoremysql(destr, connStrAll);
@@ -218,7 +202,6 @@
                        string str2 = $"delete from forall where id < ({index}-1000)";
                        Operatoremysql(str2, connStrAll);
                    }
                    string mysqlstr = $"insert into forall (basketcode,device,plcnum,sn,data,time) values('{pro.BasketCode}','{devicestr}','{pro.SEQUENCE}','{pro.SN}','{JsonConvert.SerializeObject(pro, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All })}','{DateTime.Now.ToString("yyyyMMddHHmmss")}')";
@@ -263,20 +246,26 @@
            return null;
        }
        public string Getbasketcode(string plcnum)
        public string Getbasketcode(string plcnum, out string sn)
        {
            sn = "Noread";
            try
            {
                string mysqlstr = $"select basketcode from forall where plcnum='{plcnum}' && device='S2' order by id desc limit 1";
                string str = selectmysql(mysqlstr, connStrAll);
                if (!string.IsNullOrEmpty(str))
                string mysqlstr = $"select basketcode,sn from forall where plcnum='{plcnum}' && device='S2' order by id desc limit 1";
                var dt = selectdt(mysqlstr, connStrAll);
                if (dt == null || dt.Rows.Count == 0)
                {
                    return str;
                    return "Noread";
                }
                else
                {
                    sn = dt.Rows[0][1].ToString();
                    return dt.Rows[0][0].ToString();
                }
            }
            catch (Exception e)
            {
                //CommonLogger.LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"数据库forlocal获取异常 {e.ToString()}");
            }
            return "NoRead";
        }
@@ -286,7 +275,7 @@
        {
            try
            {
                string mysqlstr = $"select data from forall where plcnum='{plcnum}'";
                string mysqlstr = $"select data from forall where plcnum='{plcnum}' order by device";
                var dt = selectdt(mysqlstr, connStrAll);
                if (dt == null)
                {
src/Bro.M141.Process/UI/UIPrinter.cs
@@ -78,10 +78,8 @@
            int statuscode = GetPrinterStatusCodeInt();
            string status = GetPrinterStatusMessage(statuscode);
            //   Config141
            //Config141
            Process141.PlcwritePrinter(1520, 0);
            Process141.PlcwritePrinter(1510, 1);
        }
src/Bro.M141_AOI1.Process/AOI1Process.cs
@@ -6,12 +6,14 @@
using Bro.M141.Process;
using Bro.UI.Model.Winform;
using HalconDotNet;
using Newtonsoft.Json;
using NPOI.POIFS.Crypt.Dsig;
using NPOI.SS.Formula.Functions;
using NPOI.XSSF.Streaming.Values;
using System.Collections.Concurrent;
using System.Net.Sockets;
using System.Text.RegularExpressions;
using static Bro.Common.Helper.EnumHelper;
using static NPOI.HSSF.Util.HSSFColor;
using static Org.BouncyCastle.Crypto.Engines.SM2Engine;
using static Org.BouncyCastle.Math.EC.ECCurve;
@@ -29,10 +31,20 @@
        AOI1Config ConfigAOI1 => Config as AOI1Config;
        public override void Open()
        {
            //string configPath = @"C:\Users\30263\Desktop\666.txt";
            //string _configBackupStr = "";
            //using (StreamReader reader = new StreamReader(configPath, System.Text.Encoding.UTF8))
            //{
            //    _configBackupStr = reader.ReadToEnd();
            //}
            //ProductModel p = JsonConvert.DeserializeObject<ProductModel>(_configBackupStr, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All });
            base.Open();
        }
src/Bro.M141_AOI1.Process/Bro.M141_AOI1.Process.csproj
@@ -39,6 +39,9 @@
    <Reference Include="halcondotnet">
      <HintPath>..\..\libs\halcon12\halcondotnet.dll</HintPath>
    </Reference>
    <Reference Include="Newtonsoft.Json">
      <HintPath>..\..\libs\Nuget\Newtonsoft.Json.dll</HintPath>
    </Reference>
  </ItemGroup>
</Project>