using Autofac; using Bro.Common.Base; using Bro.Common.Factory; using Bro.Common.Helper; using Bro.Common.Interface; using Bro.Common.Model; using Bro.M135.Common; using Bro.Process; using System.ComponentModel; using System.Drawing.Design; using System.Drawing.Imaging; using System.Reflection; using System.Windows.Forms.Design; namespace Bro.M141.Process { public class M141Config : ProcessConfigBase { [Category("连续NG报警设置")] [Description("连续NG报警总开关。true:开启连续NG报警 false:关闭连续NG报警机制")] [DisplayName("连续NG报警总开关")] public bool IsEnableContinuousNGAlarm { get; set; } = true; [Category("连续NG报警设置")] [Description("连续NG报警设置集合。设置连续NG报警的开关,类型,数量和时间阈值。添加或删除监控需要软件重启生效。")] [DisplayName("连续NG报警设置集合")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))] public List ContinuousNGAlarmColletion { get; set; } = new List(); [Category("点检配置")] [Description("点检开关")] [DisplayName("点检开关")] public bool PointState { get; set; } = false; [Category("读码数据")] [Description("读码数据")] [DisplayName("读码数据")] public string TmpPath { get; set; } [Category("读码数据")] [Description("读码数据")] [DisplayName("读码数据")] [TypeConverter(typeof(SimpleCollectionConvert))] [Editor(typeof(SimpleCollectionEditor), typeof(UITypeEditor))] [EditorBrowsable] public List BarcodeDataList { get; set; } = new List(); [Category("工位信息")] [Description("工位信息配置集合")] [DisplayName("工位信息")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))] public List WorkPositionCollection { get; set; } = new List(); [Category("检测配置")] [Description("检测配置集合,配置检测的工位,图片索引,相机和检测调用项关系")] [DisplayName("检测配置集合")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))] public List MeasureBindCollection { get; set; } = new List(); [Category("检测配置")] [Description("标定集合,配置检测的工位,图片索引,相机和检测调用项关系")] [DisplayName("标定集合")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))] public List BDCollection { get; set; } = new List(); [Category("检测超时设置")] [Description("检测超时设置,获取检测结果时的允许最大等待时间,单位ms")] [DisplayName("检测超时时间")] public int DetectTimeout { get; set; } = 1000; [Category("数据库设置")] [Description("数据库数据保存天数,超过该天数的数据会被自动删除。设置为0时不执行删除操作")] [DisplayName("数据保存天数")] public int DBDataTimeLimit { get; set; } = 3; [Category("数据库设置")] [Description("初始化数据库时的缓存队列数量")] [DisplayName("初始缓存数量")] public int DBBufferListCount { get; set; } = 10; [Category("检测异常指示")] [Description("选择某个Spec,其表示检测过程中异常")] [DisplayName("异常指示标准")] [TypeConverter(typeof(SpecCodeSelectorConverter))] public string CheckErrorSpecCode { get; set; } = ""; //[Category("调试使用设置")] //[Description("是否允许临时产品启用,使用于不完整流程中临时接收检测数据")] //[DisplayName("临时产品开关")] //public bool IsAllowTempProduct { get; set; } = false; [Category("位置度/轮廓度设置")] [Description("产品测量点位集合")] [DisplayName("产品测量点位集合")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))] public List MeasurePointCollection { get; set; } = new List(); [Category("位置度/轮廓度设置")] [Description("检测项配置集合,设置包含组合点位的检测项")] [DisplayName("检测项配置集合")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))] public List MeasureItemBinds { get; set; } = new List(); [Category("位置度/轮廓度设置")] [DisplayName("轮廓点计算偏移")] [Description("计算轮廓点位置时的点位偏移大小,单位mm")] public float CountLineShift { get; set; } = 0.5f; [Category("位置度/轮廓度设置")] [DisplayName("测量点补偿值设置")] [Description("针对各工位对应产品的各检测项点,做单点补偿处理")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))] public List Product_PointsOffsetList { get; set; } = new List(); [Category("MES配置")] [Description("MES上传URL地址")] [DisplayName("MES上传URL地址")] public string MESUploadURL { get; set; } [Category("MES配置")] [Description("true:启用MES上传 false:未启用MES上传")] [DisplayName("MES上传开关")] public bool IsEnabelMESUpload { get; set; } = false; [Category("MES配置")] [Description("MES上传项目代码,代表Project")] [DisplayName("MES站点代码")] public string MESProjectCode { get; set; } = ""; [Category("MES配置")] [Description("MES上传机器号,代表MachineNumber")] [DisplayName("MES机器号")] public string MESMachineNum { get; set; } = ""; [Category("MES配置")] [Description("MES上传代码和检测项代码的映射关系")] [DisplayName("MES上传代码映射关系")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))] public List MESCodeMappingCollection { get; set; } = new List(); [Category("MES配置-OEE上传")] [Description("OEE数据上传URL地址")] [DisplayName("OEE URL")] public string OEEDataUploadURL { get; set; } = ""; [Category("MES配置-OEE上传")] [Description("true: 启用OEE数据上传 false:禁用OEE数据上传")] [DisplayName("OEE数据上传启用标记")] public bool IsEnableOEEDataUpload { get; set; } = false; [Category("MES配置-OEE上传")] [Description("OEE配置WorkPlace信息")] [DisplayName("OEE_WorkPlace")] public string OEEConfig_WorkPlace { get; set; } = ""; [Category("图片显示设置")] [Description("背景图片文件路径")] [DisplayName("背景图片")] [Editor(typeof(FileDialogEditor), typeof(UITypeEditor))] public string BackgroundImageFilePath { get; set; } [Category("图片显示设置")] [DisplayName("检测缺陷显示布局")] [Description("检测界面缺陷显示布局")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(DefectRectangleIndicatorEditor), typeof(UITypeEditor))] public List DefectIndicatorCollection { get; set; } = new List(); [Category("表格显示设置")] [Description("表格显示产品数据的方式,按行或列显示一个产品的所有数据")] [DisplayName("表格显示")] public RefreshMode RefreshModeSelect { get; set; } = RefreshMode.行; [Category("表格显示设置")] [Description("表格显示产品数据数量")] [DisplayName("表格显示产品数据数量")] public int DataViewCount { get; set; } = 100; [Category("表格显示设置")] [Description("表格产品数据刷新的频率,单位us")] [DisplayName("表格产品数据刷新频率")] public int DataViewRefreshTime { get; set; } = 1000; [Category("NG和OK图片保存配置")] [Description("图片保存目录")] [DisplayName("图片保存目录")] [Editor(typeof(FoldDialogEditor), typeof(UITypeEditor))] public string NGImageFolder { get; set; } = ""; [ResCategory("NG和OK图片保存配置")] [ResDescription("NG图片保存格式")] [ResDisplayName("NG图片保存格式")] public ImageFormat ImageFormatNG { get; set; } = ImageFormat.Png; [ResCategory("NG和OK图片保存配置")] [ResDescription("OK图片保存格式")] [ResDisplayName("OK图片保存格式")] public ImageFormat ImageFormatOK { get; set; } = ImageFormat.Png; [ResCategory("压缩图片保存配置")] [ResDescription("图片保存格式")] [ResDisplayName("图片保存格式")] public ImageFormat ImageFormatZip { get; set; } = ImageFormat.Jpeg; [ResCategory("压缩图片保存配置")] [ResDescription("图片保存开关")] [ResDisplayName("图片保存开关")] public bool SaveStateZip { get; set; } = false; [ResCategory("压缩图片保存配置")] [ResDescription("图片保存开关")] [ResDisplayName("保存图片工位集合")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))] public List PositionZip { get; set; } = new List(); [ResCategory("压缩图片保存配置")] [ResDescription("图片保存路径")] [ResDisplayName("图片保存路径")] [Editor(typeof(FoldDialogEditor), typeof(UITypeEditor))] public string SavePathZip { get; set; } [ResCategory("压缩图片保存配置")] [ResDescription("图片保存路径2")] [ResDisplayName("图片保存路径2")] [Editor(typeof(FoldDialogEditor), typeof(UITypeEditor))] public string SavePathZip2 { get; set; } [Browsable(false)] public string CurrPathZip { get; set; } [ResCategory("压缩图片保存配置")] [ResDescription("图片保存双路径开关")] [ResDisplayName("图片保存双路径开关")] public bool SaveTwoPathZip { get; set; } = false; [ResCategory("压缩图片保存配置")] [ResDescription("双路径保存图片,首路径磁盘剩余空间小于设置值时,改用路径2存图,路径2磁盘满同理")] [ResDisplayName("磁盘最小剩余内存%")] public int SaveMinPercentZip { get; set; } = 5; [ResCategory("压缩图片保存配置")] [ResDescription("图片压缩率")] [ResDisplayName("图片压缩率")] [TypeConverter(typeof(EnumDescriptionConverter))] public zipZip SavezipZip { get; set; } = zipZip.zip; [Category("实时数据回传设置")] [Description("选择回传实时数据的本地socket服务端")] [DisplayName("回传服务端")] [TypeConverter(typeof(DeviceIdSelectorConverter))] public string RealTimeDataServer { get; set; } [Category("实时数据回传设置")] [Description("回传数据的格式和内容设置")] [DisplayName("回传数据设置集合")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))] public List RealTimeDataModels { get; set; } = new List(); [Category("产品设置")] [DisplayName("产品展示数量上限")] [Description("产品展示数量上限,超过该数量的检测记录自动移除")] public int MaxProductListAmount { get; set; } = 20; [Category("心跳配置")] [DisplayName("心跳返回值")] [Description("心跳返回值")] public string Heartstr { get; set; } = ""; [Category("算法预热设置")] [DisplayName("开关")] [Description("是否启动算法预热,true启用,false不启用")] public bool WarmUp { get; set; } = false; [Category("算法预热设置")] [DisplayName("算法预热集合")] [Description("算法预热集合")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))] public List WarmUpList { get; set; } = new List(); //[Category("检测相关")] //[Description("流程及设备检测标准集合")] //[DisplayName("检测标准集合2")] //[TypeConverter(typeof(GlobalSpecCollectionCountConverter))] //[Editor(typeof(GlobalSpecCollectionEditor), typeof(UITypeEditor))] //public List sss { get; set; } = new List(); [Category("统计汇总配置")] [Description("汇总界面产品列表最大数量")] [DisplayName("产品列表最大数量")] public int MaxProductNumForStatistic { get; set; } = 200; } public enum zipZip { [ResDescription("1")] zip = 10, [ResDescription("0.1")] zip1 = 1, [ResDescription("0.2")] zip2 = 2, [ResDescription("0.3")] zip3 = 3, [ResDescription("0.4")] zip4 = 4, [ResDescription("0.5")] zip5 = 5, [ResDescription("0.6")] zip6 = 6, [ResDescription("0.7")] zip7 = 7, [ResDescription("0.8")] zip8 = 8, [ResDescription("0.9")] zip9 = 9, } public class PostionnameZip : IComplexDisplay { [Category("工位设置")] [DisplayName("工位名称")] [Description("工位设置")] [TypeConverter(typeof(WorkPositionNameConverter))] public string WorkPosition { get; set; } public string GetDisplayText() { return $"{WorkPosition}"; } } public class WarmUpOne : IComplexDisplay { [Category("预热设置")] [Description("预热算法文件路径")] [DisplayName("预热算法")] [Editor(typeof(FileDialogEditor), typeof(UITypeEditor))] public string HalconFilePath { get; set; } [Category("预热设置")] [Description("预热图片文件路径")] [DisplayName("预热图片")] [Editor(typeof(FileDialogEditor), typeof(UITypeEditor))] public string PicFilePath { get; set; } public string GetDisplayText() { return $"{HalconFilePath}"; } } public class MESCodeMapping : IComplexDisplay { [Category("本地检测代码")] [Description("本地使用的检测代码")] [DisplayName("本地检测代码")] [TypeConverter(typeof(SpecCodeSelectorConverter))] public string SpcCode { get; set; } = ""; [Category("MES上传代码")] [Description("MES上传代码")] [DisplayName("MES上传代码")] public string MESCode { get; set; } = ""; public string GetDisplayText() { return $"本地检测代码:{SpcCode} MES上传代码:{MESCode}"; } } public enum RefreshMode { 行, 列, } public class WorkPositionSet : IComplexDisplay { [Category("交互触发值")] [Description("交互触发信息,该交互信息表示当前该工位触发")] [DisplayName("交互触发信息")] public string TriggerValue { get; set; } [Category("工位名称")] [Description("工位名称")] [DisplayName("工位名称")] public string PositionName { get; set; } [Category("启用标志")] [Description("启用标志 true:该工位启用 false:该工位未启用")] [DisplayName("启用标志")] public bool IsEnabled { get; set; } = true; [Category("顺序设置")] [Description("是否是最后工位,最后工位完成时汇总产品数据结果")] [DisplayName("是否末工位")] public bool IsLastPosition { get; set; } = false; [Category("反馈清理设置")] [Description("true: 发送相机清理信号 false: 不发送相机清理信号")] [DisplayName("发送清理信号开关")] public bool IsSendClearSingal { get; set; } = false; [Category("反馈清理设置")] [Description("反馈相机清理时发送的文本信息")] [DisplayName("反馈清理信息")] public string ClearStr { get; set; } = "$,ClearOK"; public string GetDisplayText() { return $"{(IsEnabled ? "" : "禁用")} 工位 {PositionName} 交互触发值:{TriggerValue}"; } } public class Product_CheckPointsOffsetList : IComplexDisplay { [Category("测量点补偿值设置")] [DisplayName("输入产品索引")] [Description("输入产品索引")] public int ProductIndex { get; set; } = 1; [Category("测量点补偿值设置")] [DisplayName("补偿值设置")] [Description("补偿值设置")] [TypeConverter(typeof(CollectionCountConvert))] [Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))] public List CheckPointsOffsetList { get; set; } = new List(); public string GetDisplayText() { return $"产品索引:{ProductIndex},选择的补偿点位:{string.Join("、", CheckPointsOffsetList.Select(u => u.ReadyToOffsetMeasurePointName))}"; } } public class CheckPointsOffset : IComplexDisplay { [Category("补偿值设置")] [DisplayName("选择待补偿的测量点位")] [Description("选择待补偿的测量点位")] [TypeConverter(typeof(MeasurePointNameSelectorConvertor))] public string ReadyToOffsetMeasurePointName { get; set; } [Category("补偿值设置")] [DisplayName("补偿值开关")] [Description("补偿值开关")] public bool IsOffsetCalculate { get; set; } = false; [Category("补偿值设置")] [DisplayName("补偿值-X")] [Description("写入坐标值X的补偿值,正数为加运算,负数为减运算")] public double OffsetX { get; set; } = 0; [Category("补偿值设置")] [DisplayName("补偿值-Y")] [Description("写入坐标值Y的补偿值,正数为加运算,负数为减运算")] public double OffsetY { get; set; } = 0; public string GetDisplayText() { return $"补偿点位:{ReadyToOffsetMeasurePointName},{IsOffsetCalculate.ToString()},X:{OffsetX.ToString()},Y:{OffsetY.ToString()}"; } } public class MeasureBind : IComplexDisplay, IHalconToolPath { [Category("索引配置")] [DisplayName("工位设置")] [Description("设置该检测项对应的工位,一般和触发方法对应的工位匹配")] [TypeConverter(typeof(WorkPositionNameConverter))] public string WorkPosition { get; set; } [Category("索引配置")] [DisplayName("检测索引")] [Description("设置该检测项对应的检测索引,一般指该工位的第几次检测")] public int CheckIndex { get; set; } [Category("索引配置")] [DisplayName("图像索引")] [Description("应对单次检测项需要多次拍照时,记录图片的索引号,从0开始")] public int ImageIndex { get; set; } = 0; [Category("取像设置")] [DisplayName("相机选择")] [Description("选择该检测项对应的相机")] [TypeConverter(typeof(DeviceIdSelectorConverter))] public string CameraId { get; set; } [Category("取像设置")] [Description("检测取像时的取像配置")] [DisplayName("取像配置")] [TypeConverter(typeof(ComplexObjectConvert))] [Editor(typeof(OperationConfigByCameraEditor), typeof(UITypeEditor))] public IOperationConfig SnapshotOpConfig { get; set; } = new CameraOperationConfigBase(); [Category("产品配置")] [DisplayName("产品索引")] [Description("一次取像可能对应单个产品或多个产品,配置对应的产品索引序号,从1开始")] [TypeConverter(typeof(SimpleCollectionConvert))] [Editor(typeof(SimpleCollectionEditor), typeof(UITypeEditor))] public List ProductIndices { get; set; } = new List(); [Category("产品配置")] [DisplayName("是否首工位")] [Description("如果是首工位,需要新建产品,否则从数据源中查找产品信息")] public bool IsFirstPosition { get; set; } = false; [Category("产品配置")] [DisplayName("支持队列缓存")] [Description("true: 寻找产品信息时可以从缓存队列中获取产品信息 false:不可以从缓存队列中获取产品信息,只能从数据库获取产品信息或者新建产品信息")] public bool IsEnabelQueryFromQueue { get; set; } = true; [Category("检测配置")] [Description("选择ML设备检测配置")] [DisplayName("检测配置")] [TypeConverter(typeof(DetectionConverter))] public string DetectionId { get; set; } [Category("检测配置")] [Description("从程序自定义检测方法中获取当前检测项")] [DisplayName("自定义检测方法")] [TypeConverter(typeof(MonitorSetSelectorConverter))] public string CustomizedMonitorId { get; set; } [Category("检测配置")] [Description("从程序自定义检测方法中获取当前检测项,该检测项用于多图组合运算时")] [DisplayName("自定义组合检测方法")] [TypeConverter(typeof(MonitorSetSelectorConverter))] public string CustomizedCombineMethodId { get; set; } [Category("图片保存配置")] [Description("NG图片保存开关,true:保存NG图片,false:不保存NG图片")] [DisplayName("NG图片保存开关")] public bool NGImageSwitch { get; set; } = false; [Category("图片保存配置")] [Description("OK图片保存开关,true:保存OK图片,false:不保存OK图片")] [DisplayName("OK图片保存开关")] public bool OKImageSwitch { get; set; } = false; [Category("标定配置")] [Description("标定开关")] [DisplayName("标定开关")] public bool Calibration { get; set; } = false; [Category("标定配置")] [Description("标定索引")] [DisplayName("标定索引")] public int CalibrationIndex { get; set; } = 0; public string GetDisplayText() { string cameraName = ""; string detectionName = "未指定"; string methodName = "未指定"; string combineMethodName = "未指定"; using (var scope = GlobalVar.Container.BeginLifetimeScope()) { var deviceList = scope.Resolve>(); cameraName = deviceList.FirstOrDefault(u => u.Id == CameraId)?.Name ?? "未指定"; var detection = deviceList.Select(u => u.InitialConfig).Where(u => u is MLInitialConfigBase).SelectMany(u => ((MLInitialConfigBase)u).DetectionConfigs).FirstOrDefault(u => u.Id == DetectionId); if (detection != null) { detectionName = detection.Name; } if (!string.IsNullOrWhiteSpace(CustomizedMonitorId)) { var config = scope.Resolve(); var curMethod = config.GetAllMonitorSet().FirstOrDefault(u => u.Id == CustomizedMonitorId); if (curMethod != null) { methodName = String.IsNullOrWhiteSpace(curMethod.Name) ? curMethod.MethodDesc : curMethod.Name; } curMethod = config.GetAllMonitorSet().FirstOrDefault(u => u.Id == CustomizedCombineMethodId); if (curMethod != null) { combineMethodName = String.IsNullOrWhiteSpace(curMethod.Name) ? curMethod.MethodDesc : curMethod.Name; } } } return $"工位{WorkPosition}第{CheckIndex}次检测产品{string.Join(",", ProductIndices.Select(u => u))},ML检测:{detectionName},自定义检测:{methodName},组合检测:{combineMethodName}"; } public List GetHalconToolPathList() { return (SnapshotOpConfig as IHalconToolPath).GetHalconToolPathList(); } } public class BDMeasureBind : IComplexDisplay, IHalconToolPath { [Category("索引配置")] [DisplayName("检测索引")] [Description("检测索引,例:0,1,2,3...")] public int CheckIndex { get; set; } [Category("取像设置")] [DisplayName("相机选择")] [Description("选择该检测项对应的相机")] [TypeConverter(typeof(DeviceIdSelectorConverter))] public string CameraId { get; set; } [Category("取像设置")] [Description("检测取像时的取像配置")] [DisplayName("取像配置")] [TypeConverter(typeof(ComplexObjectConvert))] [Editor(typeof(OperationConfigByCameraEditor), typeof(UITypeEditor))] public IOperationConfig SnapshotOpConfig { get; set; } = new CameraOperationConfigBase(); [Category("标定矩阵")] [DisplayName("标定矩阵")] [Description("标定矩阵具体数据")] [TypeConverter(typeof(CollectionCountConvert))] public List BDList { get; set; } = new List(); public string GetDisplayText() { return $"索引{CheckIndex.ToString()},相机{CameraId}"; } public List GetHalconToolPathList() { return (SnapshotOpConfig as IHalconToolPath).GetHalconToolPathList(); } } public class ContinuousNGAlarm : IComplexDisplay { [Category("缺陷类型")] [Description("选择需要监控的缺陷类型")] [DisplayName("缺陷类型")] [TypeConverter(typeof(GlobalDefectNameConverter))] public string DefectType { get; set; } [Category("连续NG报警")] [Description("连续NG数量阈值。该缺陷连续NG数量达到或超过该阈值时,发出报警")] [DisplayName("连续NG数量阈值")] public int ContinuousNumThreshold { get; set; } [Category("连续NG报警")] [Description("连续NG报警类型")] [DisplayName("连续NG报警类型")] public int ContinuousAlarmType { get; set; } = 1; [Category("时段报警")] [Description("监控时间段。监控该时间段内的缺陷数量,单位:min")] [DisplayName("监控时间段")] public int TimePeriod { get; set; } [Category("时段报警")] [Description("监控时间段内NG数量阈值。监控时间段内,该缺陷NG数量达到或超过该阈值时,发出报警")] [DisplayName("时间内NG数量阈值")] public int TimePeriodNumThresold { get; set; } [Category("时段报警")] [Description("时段报警类型")] [DisplayName("时段报警类型")] public int TimePeriodAlarmType { get; set; } = 2; [Category("启用设置")] [Description("true:启用该缺陷监控报警 false: 不启用该缺陷监控报警")] [DisplayName("启用监控")] public bool IsEnabled { get; set; } = true; public string GetDisplayText() { string display = $"{(IsEnabled ? "" : "已禁用")} 监控{DefectType} "; if (ContinuousNumThreshold > 0) { display += $"连续NG{ContinuousNumThreshold}个 "; } if (TimePeriodNumThresold > 0) { display += $"{TimePeriod}分钟内NG{TimePeriodNumThresold}个 "; } return display; } private class GlobalDefectNameConverter : StringConverter { public override bool GetStandardValuesExclusive(ITypeDescriptorContext? context) { return false; } public override bool GetStandardValuesSupported(ITypeDescriptorContext? context) { return true; } public override StandardValuesCollection? GetStandardValues(ITypeDescriptorContext? context) { using (var scope = GlobalVar.Container.BeginLifetimeScope()) { var config = scope.Resolve(); return new StandardValuesCollection((config as IDefectSwitcher).DefectSwitchCollection.Select(u => u.DefectName).ToList()); } } } } public class OperationConfigByCameraEditor : UITypeEditor { public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context) { return UITypeEditorEditStyle.Modal; } public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) { IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService)); if (edSvc != null) { Form form = new Form { FormBorderStyle = FormBorderStyle.SizableToolWindow, StartPosition = FormStartPosition.CenterParent, Text = context.PropertyDescriptor.DisplayName + "--" + context.PropertyDescriptor.Description }; if (context.Instance is MeasureBind ssa) { IDevice camera = null; using (var scope = GlobalVar.Container.BeginLifetimeScope()) { var deviceList = scope.Resolve>(); camera = deviceList.FirstOrDefault(u => u.Id == ssa.CameraId); } if (camera != null) { var curCameraTypeAttr = camera.GetType().GetCustomAttribute(); var curOpconfigTypeAttr = value.GetType().GetCustomAttribute(); if (curCameraTypeAttr.TypeCode != (curOpconfigTypeAttr?.TypeCode ?? "")) { value = ConfigFactory.GetOperationConfig(curCameraTypeAttr.TypeCode); } } } PropertyGrid pg = new PropertyGrid { Dock = DockStyle.Fill, ToolbarVisible = false, SelectedObject = value }; form.Controls.Add(pg); form.ShowDialog(); value = pg.SelectedObject; return value; } return base.EditValue(context, provider, value); } } public class WorkPositionNameConverter : ComboBoxItemTypeConvert { public override Dictionary GetConvertDict(ITypeDescriptorContext context) { Dictionary dict = new Dictionary(); using (var scope = GlobalVar.Container.BeginLifetimeScope()) { var config = scope.Resolve(); if (config is M141Config iConfig) { dict = iConfig.WorkPositionCollection.Where(u => u.IsEnabled).ToDictionary(u => u.PositionName, u => u.PositionName); } } return dict; } } public interface IImageCheckOperationConfig : IOperationConfig { List Products { get; set; } IImageSet ImageSet { get; set; } string TriggerText { get; set; } string TriggerSource { get; set; } //CheckPoint CheckPoint { get; set; } string AlgorithemPath { get; set; } //string AlgorithemPath_CombineViews { get; set; } List SpecCollection { get; set; } //List SpecCollection_CombineViews { get; set; } //List CheckPointList { get; set; } bool BDstate { get; set; } int BDindex { get; set; } string ExecuteDevice { get; set; } int Outindex { get; set; } IImageCheckOperationConfig Clone(); } [Device("ImageCheck", "图片检测操作配置", EnumHelper.DeviceAttributeType.OperationConfig)] public class ImageCheckOperationConfigBase : OperationConfigBase, IHalconToolPath, IImageCheckOperationConfig { [Browsable(false)] public List Products { get; set; } = new List(); [Browsable(false)] public IImageSet ImageSet { get; set; } = null; [Browsable(false)] public string TriggerText { get; set; } = ""; [Browsable(false)] public string TriggerSource { get; set; } = ""; [Category("算法脚本")] [Description("当前单张图片算法脚本文件路径")] [DisplayName("单图算法脚本")] [Editor(typeof(FileDialogEditor), typeof(UITypeEditor))] public string AlgorithemPath { get; set; } [Category("检测标准")] [Description("计算检测标准集合")] [DisplayName("检测标准集合")] [TypeConverter(typeof(ComplexObjectConvert))] [Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))] public List SpecCollection { get; set; } = new List(); [Category("标定配置")] [Description("标定开关")] [DisplayName("标定开关")] public bool BDstate { get; set; } = false; [Category("标定配置")] [Description("标定序号,例如0,1,2,3...")] [DisplayName("标定序号")] public int BDindex { get; set; } = 0; [ResCategory("标定配置")] [ResDescription("调用设备")] [ResDisplayName("调用设备")] [TypeConverter(typeof(DeviceIdSelectorConverter))] public string ExecuteDevice { get; set; } = ""; [Category("数据输出配置")] [Description("配置数据输出时,代表数据输出序号,配置二次进算法时,代表数据量")] [DisplayName("数据输出序号")] public int Outindex { get; set; } = 0; public List GetHalconToolPathList() { return new List() { AlgorithemPath }; } public virtual IImageCheckOperationConfig Clone() { ImageCheckOperationConfigBase config = new ImageCheckOperationConfigBase(); config.AlgorithemPath = AlgorithemPath; config.SpecCollection = SpecCollection.Select(u => new SpecSelector() { SpecCode = u.SpecCode }).ToList(); config.Outindex = Outindex; config.BDindex = BDindex; config.BDstate = BDstate; config.ExecuteDevice = ExecuteDevice; //config.AlgorithemPath_CombineViews = AlgorithemPath_CombineViews; //config.SpecCollection_CombineViews = SpecCollection_CombineViews.Select(u => new SpecSelector() { SpecCode = u.SpecCode }).ToList(); //config.CheckPointList = CheckPointList.Select(u => new CheckPointSelector() { PointId = u.PointId }).ToList(); return config; } } public class RealTimeAdjustDataModel : IComplexDisplay { [Category("回传信息")] [Description("回传信息的数据头,包含了数据发送指向")] [DisplayName("回传信息数据头")] public string DataHead { get; set; } = ""; [Category("回传信息")] [Description("true: 启用该回传 false:禁用该回传")] [DisplayName("启用标志")] public bool IsEnabled { get; set; } = true; [Category("回传信息")] [Description("回传信息具体内容,指定哪些点位的哪些坐标数据需要回传")] [DisplayName("回传信息数据内容")] [TypeConverter(typeof(ComplexObjectConvert))] [Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))] public List DataDetails { get; set; } = new List(); public string GetDisplayText() { return $"{(IsEnabled ? "" : "已禁用 ")}{DataHead} {string.Join(",", DataDetails.Select(u => u.GetDisplayText()))}"; } } public class RealTimeAdjustDataDetail : IComplexDisplay { [Category("点位设置")] [Description("选择需要回传的数据点位")] [DisplayName("选择点位")] [TypeConverter(typeof(MeasurePointNameSelectorConvertor))] public string PointName { get; set; } [Category("点位设置")] [Description("选择数据点位的X坐标或者Y坐标")] [DisplayName("选择坐标")] public ContourEdge EdgeSelect { get; set; } = ContourEdge.X; [Category("检测项设置")] [Description("选择需要回传的SPC检测项数据")] [DisplayName("选择检测项")] [TypeConverter(typeof(SpecCodeSelectorConverter))] public string SpecCode { get; set; } [Category("检测项设置")] [Description("设置需要回传的SPC检测项数据的后缀,方便识别区分")] [DisplayName("检测项后缀")] public string SpecAfter { get; set; } = ""; [Category("数据范围")] [Description("数据最小值,小于该数值认为数据非法,不做回传,避免误导")] [DisplayName("数据最小值")] public double ValidRangeMin { get; set; } = -999; [Category("数据范围")] [Description("数据最大值,大于该数值认为数据非法,不做回传,避免误导")] [DisplayName("数据最大值")] public double ValidRangeMax { get; set; } = 999; public string GetDisplayText() { string desc = "未指定"; if (string.IsNullOrWhiteSpace(PointName)) { if (!string.IsNullOrWhiteSpace(SpecCode)) { desc = $"{SpecCode}{SpecAfter}"; } } else { desc = $"{PointName}-{EdgeSelect.ToString()}"; } return desc; } } }