领胜LDS 键盘AOI检测项目
src/Bro.M071.Process/M071Models.cs
@@ -3,6 +3,8 @@
using Bro.Common.Helper;
using Bro.Common.Interface;
using Bro.Common.Model;
using HalconDotNet;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@@ -10,10 +12,33 @@
using System.Drawing.Design;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Bro.M071.Process
{
    public class KeyLocation : IComplexDisplay
    {
        [Category("键名配置")]
        [Description("单键键名")]
        [TypeConverter(typeof(KeyNameDictConverter))]
        public string Key { get; set; }
        [Category("位置配置")]
        [Description("单键在键盘平面图上的位置显示")]
        public Rectangle KeyRect { get; set; } = new Rectangle();
        [Category("位置配置")]
        [Description("单键之后间隙位置")]
        public Rectangle IntervalRect { get; set; } = new Rectangle();
        public string GetDisplayText()
        {
            return $"{Key}:{KeyRect.X},{KeyRect.Y},{KeyRect.Width},{KeyRect.Height}";
        }
    }
    public class KeyAlgorithem : IComplexDisplay
    {
        [Browsable(false)]
@@ -32,6 +57,19 @@
        {
            return $"{Name} -- {AlgorithemPath}";
        }
    }
    public class MeasureType : Spec
    {
        [Category("检测类型")]
        [Description("检测类型")]
        [DisplayName("检测类型")]
        public override string Code { get; set; }
        [Category("检测算法")]
        [Description("检测算法路径")]
        [Editor(typeof(FileDialogEditor), typeof(UITypeEditor))]
        public string AlgorithemPath { get; set; }
    }
    public class KeyResult : IComplexDisplay
@@ -59,7 +97,7 @@
    {
        public string GetDisplayText()
        {
            return Name + " " + string.Join(" ", Destination.Select(u => u.GetDisplayText())) + " " + CameraOp.GetDisplayText();
            return (IsEnabled ? "" : "禁用 ") + Name + " " + MotionOp.GetDisplayText() + " " + CameraOp.GetDisplayText();
        }
        public List<string> GetHalconToolPathList()
@@ -81,16 +119,26 @@
        [Description("拍照点名称")]
        public string Name { get; set; }
        [Category("设备配置")]
        [Description("运动设备")]
        [TypeConverter(typeof(DeviceSelectorConverter<IMotion>))]
        public string MotionDevice { get; set; }
        [Category("启用设置")]
        [Description("true:启用 false:禁用")]
        public bool IsEnabled { get; set; } = true;
        [Category("运动点位")]
        [Description("运动点位")]
        //[Category("设备配置")]
        //[Description("运动设备")]
        //[TypeConverter(typeof(DeviceSelectorConverter<IMotion>))]
        //public string MotionDevice { get; set; }
        //[Category("运动点位")]
        //[Description("运动点位")]
        //[TypeConverter(typeof(ComplexObjectConvert))]
        //[Editor(typeof(ComplexCollectionEditor<AxisInfo>), typeof(UITypeEditor))]
        //public List<AxisInfo> Destination { get; set; } = new List<AxisInfo>();
        [Category("运动机构配置")]
        [Description("运动机构配置")]
        [TypeConverter(typeof(ComplexObjectConvert))]
        [Editor(typeof(ComplexCollectionEditor<AxisInfo>), typeof(UITypeEditor))]
        public List<AxisInfo> Destination { get; set; } = new List<AxisInfo>();
        [Editor(typeof(IOperationConfigByDeviceEditor), typeof(UITypeEditor))]
        public DeviceOpBind MotionOp { get; set; } = new DeviceOpBind();
        [Category("相机和操作配置")]
        [Description("相机和操作配置")]
@@ -101,6 +149,7 @@
    public class KeyUnit : IComplexDisplay, IHalconToolPath
    {
        #region 配置
        private string key = "";
        [Category("键名配置")]
        [Description("单键检测键名")]
@@ -110,49 +159,136 @@
            get => key;
            set
            {
                AlignName = key = value;
                AliasName = key = value;
            }
        }
        [Category("键名配置")]
        [Description("别名")]
        public string AlignName { get; set; }
        public string AliasName { get; set; }
        [Category("启用设置")]
        [Description("true:启用 false:禁用")]
        public bool IsEnabled { get; set; } = true;
        [Category("图像来源")]
        [Description("拍照点位")]
        [TypeConverter(typeof(SnapshotPointConverter))]
        public string SnapshotPoint { get; set; }
        public string SnapshotPointId { get; set; }
        [Category("图像来源")]
        [Description("拍照点位获取的图片索引")]
        public int ImageIndex { get; set; } = 0;
        [Description("拍照点位获取的图片序号,从1开始")]
        public int ImageSeq { get; set; } = 1;
        [Category("算法配置")]
        [Description("单键检测配置算法类型")]
        [TypeConverter(typeof(KeyAlgorithemConverter))]
        public string KeyAlgorithem { get; set; }
        public string KeyAlgorithemId { get; set; }
        [Category("算法配置")]
        [Description("单键检测配置结果类型")]
        [TypeConverter(typeof(KeyResultConverter))]
        public string KeyResult { get; set; }
        public string KeyResultId { get; set; }
        #endregion
        #region 检测相关字段
        public Dictionary<string, double> KeyValues = null;
        //public SnapshotPoint SnapshotPoint = null;
        public string KeyAlgorithemPath = "";
        public List<string> KeyResultList = null;
        #endregion
        public string GetDisplayText()
        {
            return $"{AlignName}";
            string snapShot = "未指定";
            using (var scope = GlobalVar.Container.BeginLifetimeScope())
            {
                var config = scope.Resolve<IProcessConfig>();
                if (config != null)
                {
                    var snapshotPoint = (config as M071Config).SnapshotPointCollection.FirstOrDefault(u => u.Id == SnapshotPointId);
                    if (snapshotPoint != null)
                    {
                        snapShot = snapshotPoint.Name;
                    }
                }
            }
            return $"{AliasName}-{snapShot}-{ImageSeq}";
        }
        public List<string> GetHalconToolPathList()
        {
            return null;
            using (var scope = GlobalVar.Container.BeginLifetimeScope())
            {
                IProcessConfig iConfig = scope.Resolve<IProcessConfig>();
                if (iConfig is M071Config config)
                {
                    var algo = config.KeyAlgorithemCollection.FirstOrDefault(u => u.Id == KeyAlgorithemId);
                    if (algo != null)
                    {
                        return new List<string>() { algo.AlgorithemPath };
                    }
                }
            }
            return new List<string>();
        }
    }
    public class MeasurementUint : IComplexDisplay
    public class ProductionMeasurement : INotifyPropertyChanged, IDisposable
    {
        public string Barcode;
        public string PResult;
        public List<MeasurementUnit> Measurements = new List<MeasurementUnit>();
        public List<IShapeElement> ElementList = new List<IShapeElement>();
        public DateTime? StartTime = null;
        public DateTime? EndTime = null;
        public event PropertyChangedEventHandler PropertyChanged;
        public void Dispose()
        {
            Measurements?.ForEach(m => m?.Dispose());
            Measurements = null;
            ElementList = null;
            Barcode = null;
            GC.Collect();
        }
        public void InitialMeasurementsPropertyChanged()
        {
            Measurements.ForEach(m => m.PropertyChanged += M_PropertyChanged);
        }
        private object pChangedLock = new object();
        private void M_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            lock (pChangedLock)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Measurements"));
            }
        }
    }
    public class MeasurementUnit : IComplexDisplay, INotifyPropertyChanged, IDisposable
    {
        public string Id = Guid.NewGuid().ToString();
        #region 配置
        [Category("名称")]
        [Description("名称")]
        public string Name { get; set; } = "";
        [Category("启用设置")]
        [Description("true:启用 false:禁用")]
        public bool IsEnabled { get; set; } = true;
        [Category("算法配置")]
        [Description("检测和标准类型")]
@@ -164,24 +300,84 @@
        [TypeConverter(typeof(ComplexObjectConvert))]
        [Editor(typeof(ComplexCollectionEditor<KeyUnitBind>), typeof(UITypeEditor))]
        public List<KeyUnitBind> KeyUnitCollection { get; set; } = new List<KeyUnitBind>();
        #endregion
        #region 显示
        [Browsable(false)]
        public RectangleF DisplayLocation { get; set; } = new RectangleF();
        public Rectangle DisplayLocation { get; set; } = new Rectangle(10, 10, 100, 100);
        #endregion
        #region 检测结果
        [Browsable(false)]
        public MeasureType Spec { get; set; } = null;
        #endregion
        public bool IsUpdated = false;
        public event PropertyChangedEventHandler PropertyChanged;
        public void Dispose()
        {
            KeyUnitCollection?.ForEach(k => k?.Dispose());
            KeyUnitCollection = null;
        }
        public string GetDisplayText()
        {
            if (string.IsNullOrWhiteSpace(Name))
            {
                return string.Join("-", KeyUnitCollection.Select(u => u.GetDisplayText())) + "-" + MeasureType.ToString();
                return (IsEnabled ? "" : "禁用 ") + string.Join("-", KeyUnitCollection.Select(u => u.GetDisplayText())) + "-" + MeasureType?.ToString();
            }
            else
            {
                return Name;
                return (IsEnabled ? "" : "禁用 ") + Name;
            }
        }
        public void InitialKeyUnitMeasureChanged()
        {
            KeyUnitCollection.ForEach(k => k.PropertyChanged += K_PropertyChanged);
        }
        private void K_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("KeyUnitCollection"));
        }
        public MeasurementUnit Copy()
        {
            MeasurementUnit mUnit = new MeasurementUnit();
            mUnit.Id = this.Id;
            mUnit.Name = this.Name;
            mUnit.IsEnabled = this.IsEnabled;
            mUnit.MeasureType = this.MeasureType;
            mUnit.DisplayLocation = new Rectangle(this.DisplayLocation.Location, this.DisplayLocation.Size);
            if (this.Spec == null)
            {
                mUnit.Spec = null;
            }
            else
            {
                mUnit.Spec = new MeasureType();
                mUnit.Spec.Code = this.Spec.Code;
                mUnit.Spec.AlgorithemPath = this.Spec.AlgorithemPath;
                mUnit.Spec.StandardValue = this.Spec.StandardValue;
                mUnit.Spec.Tolrenance_Positive = this.Spec.Tolrenance_Positive;
                mUnit.Spec.Tolrenance_Negative = this.Spec.Tolrenance_Negative;
            }
            this.KeyUnitCollection.ForEach(k =>
            {
                mUnit.KeyUnitCollection.Add(k.Copy());
            });
            return mUnit;
        }
    }
    public class KeyUnitBind : IComplexDisplay
    public class KeyUnitBind : IComplexDisplay, INotifyPropertyChanged, IDisposable
    {
        [Category("单键配置")]
        [Description("单键配置")]
@@ -191,15 +387,116 @@
        [Category("单键配置")]
        [Description("单键结果配置")]
        [TypeConverter(typeof(KeyUnitResultConverter))]
        public string KeyResult { get; set; } = "";
        public string KeyResultId { get; set; } = "";
        public List<HImage> KeyImages = new List<HImage>();
        public volatile int ImageSaveStatus = 0;
        //[Browsable(false)]
        //public NoticedDictionary<string, double?> MeasureValueDict { get; set; } = new NoticedDictionary<string, double?>();
        [Browsable(false)]
        public Dictionary<string, double?> MeasureValueDict { get; set; } = new Dictionary<string, double?>();
        public event PropertyChangedEventHandler PropertyChanged;
        //public void InitialMeasureValueDictPropertyChanged()
        //{
        //    MeasureValueDict.PropertyChanged += MeasureValueDict_PropertyChanged;
        //}
        //private void MeasureValueDict_PropertyChanged(object sender, PropertyChangedEventArgs e)
        //{
        //    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("MeasureValueDict"));
        //}
        public bool? IsDone = null;
        public string GetDisplayText()
        {
            string msg = Key;
            msg += string.IsNullOrWhiteSpace(KeyResult) ? "" : $"-{KeyResult}";
            msg += string.IsNullOrWhiteSpace(KeyResultId) ? "" : $"-{KeyResultId}";
            return msg;
        }
        public void Dispose()
        {
            while (ImageSaveStatus != 0)
            {
                Thread.Sleep(10);
            }
            KeyImages?.ForEach(i =>
            {
                i?.Dispose();
                i = null;
            });
            KeyImages = null;
            MeasureValueDict = null;
        }
        object valueDictLock = new object();
        public void FillKeyValues(Dictionary<string, double> valuePairs)
        {
            lock (valueDictLock)
            {
                if (valuePairs == null || valuePairs.Count == 0)
                {
                    IsDone = false;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsDone"));
                    return;
                }
                foreach (KeyValuePair<string, double> pair in valuePairs)
                {
                    if (MeasureValueDict.ContainsKey(pair.Key))
                    {
                        MeasureValueDict[pair.Key] = pair.Value;
                    }
                }
                if (MeasureValueDict.Values.All(u => u != null))
                {
                    IsDone = true;
                }
                if (IsDone != null)
                {
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsDone"));
                }
            }
        }
        public KeyUnitBind Copy()
        {
            KeyUnitBind clone = new KeyUnitBind();
            clone.Key = this.Key;
            clone.KeyResultId = this.KeyResultId;
            this.MeasureValueDict.Keys.ToList().ForEach(k =>
            {
                clone.MeasureValueDict[k] = null;
            });
            return clone;
        }
    }
    //public class NoticedDictionary<T1, T2> : Dictionary<T1, T2>, INotifyPropertyChanged
    //{
    //    public event PropertyChangedEventHandler PropertyChanged;
    //    public new T2 this[T1 index]
    //    {
    //        get => base[index];
    //        set
    //        {
    //            base[index] = value;
    //            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Index"));
    //        }
    //    }
    //}
}