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 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;
|
using static Bro.Common.Helper.EnumHelper;
|
|
namespace Bro.M141.Process
|
{
|
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("字体大小")]
|
public int FontSize_p { get; set; } = 15;
|
|
|
[Category("产品显示界面配置")]
|
[Description("每行列数")]
|
[DisplayName("每行列数")]
|
public int LineLimit_p { get; set; } = 30;
|
|
|
[Category("工位信息")]
|
[Description("工位信息配置集合")]
|
[DisplayName("工位信息")]
|
[TypeConverter(typeof(CollectionCountConvert))]
|
[Editor(typeof(ComplexCollectionEditor<WorkPositionSet>), typeof(UITypeEditor))]
|
public List<WorkPositionSet> WorkPositionCollection { get; set; } = new List<WorkPositionSet>();
|
|
|
[Category("检测配置")]
|
[Description("检测配置集合,配置检测的工位,图片索引,相机和检测调用项关系")]
|
[DisplayName("检测配置集合")]
|
[TypeConverter(typeof(CollectionCountConvert))]
|
[Editor(typeof(ComplexCollectionEditor<MeasureBind>), typeof(UITypeEditor))]
|
public List<MeasureBind> MeasureBindCollection { get; set; } = new List<MeasureBind>();
|
|
|
|
[Category("检测超时设置")]
|
[Description("检测超时设置,获取检测结果时的允许最大等待时间,单位ms")]
|
[DisplayName("检测超时时间")]
|
public int DetectTimeout { get; set; } = 1000;
|
|
|
|
[Category("检测异常指示")]
|
[Description("选择某个Spec,其表示检测过程中异常")]
|
[DisplayName("异常指示标准")]
|
[TypeConverter(typeof(SpecCodeSelectorConverter))]
|
public string CheckErrorSpecCode { get; set; } = "";
|
|
|
[Category("位置度设置")]
|
[Description("产品测量点位集合")]
|
[DisplayName("产品测量点位集合")]
|
[TypeConverter(typeof(CollectionCountConvert))]
|
[Editor(typeof(ComplexCollectionEditor<ContourPoint>), typeof(UITypeEditor))]
|
public List<ContourPoint> MeasurePointCollection { get; set; } = new List<ContourPoint>();
|
|
|
[Category("位置度设置")]
|
[Description("检测项计算公式集合,设置包含组合点位的检测项")]
|
[DisplayName("检测项计算公式集合")]
|
[TypeConverter(typeof(CollectionCountConvert))]
|
[Editor(typeof(ComplexCollectionEditor<MeasureItemBind>), typeof(UITypeEditor))]
|
public List<MeasureItemBind> MeasureItemBinds { get; set; } = new List<MeasureItemBind>();
|
|
|
|
[Category("图片显示设置")]
|
[Description("背景图片文件路径")]
|
[DisplayName("背景图片")]
|
[Editor(typeof(FileDialogEditor), typeof(UITypeEditor))]
|
public string BackgroundImageFilePath { get; set; }
|
|
|
[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;
|
|
|
|
[Category("数据库配置")]
|
[Description("IP")]
|
[DisplayName("IP")]
|
public string IPforall { get; set; } = "192.168.44.122";
|
|
[Category("数据库配置")]
|
[Description("是否为终点设备")]
|
[DisplayName("是否为终点设备")]
|
public bool IsfinDevice { get; set; } = false;
|
|
|
|
|
[Category("栏具条码配置")]
|
[Description("当前栏具码")]
|
[DisplayName("当前栏具码")]
|
public string basketcode { get; set; } = "NoRead";
|
|
[Category("栏具条码配置")]
|
[Description("本站是否读取栏具码")]
|
[DisplayName("本站是否读取栏具码")]
|
public bool Isreadbasketcode { 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;
|
|
|
}
|
|
|
public class WorkPositionSet : IComplexDisplay
|
{
|
[Category("plc地址")]
|
[Description("是否取图即完成")]
|
[DisplayName("是否取图即完成")]
|
public bool ispiccover { get; set; } = false;
|
|
|
[Category("plc地址")]
|
[Description("完成地址")]
|
[DisplayName("完成地址")]
|
public int plcover { get; set; }
|
|
[Category("plc地址")]
|
[Description("结果地址")]
|
[DisplayName("结果地址")]
|
public int plcresult { get; set; }
|
|
[Category("plc地址")]
|
[Description("物料码地址")]
|
[DisplayName("物料码地址")]
|
public int plcnum { get; set; }
|
|
[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 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, IImportFromFileInEditor
|
{
|
[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;
|
}
|
|
|
|
public IImportFromFileInEditor GetImportObject(string data, out string msg)
|
{
|
msg = "";
|
PLCAlarmDetails ret = new PLCAlarmDetails();
|
try
|
{
|
var temchar = data.Split(',');
|
ret.alarmname = temchar[0];
|
ret.address =Convert.ToInt32(temchar[1]);
|
ret.address2 = Convert.ToInt32(temchar[2]);
|
}
|
catch (Exception ex)
|
{
|
throw ex;
|
}
|
|
return ret;
|
|
}
|
|
public bool ICSVOutput(object o)
|
{
|
try
|
{
|
if (o is List<PLCAlarmDetails> Pl)
|
{
|
SaveFileDialog saveFileDialog = new SaveFileDialog();
|
saveFileDialog.Filter = "CSV files (*.csv)|*.csv"; // 设置文件过滤器,只显示CSV文件
|
saveFileDialog.Title = "Save CSV File"; // 设置对话框标题
|
saveFileDialog.FileName = "PLCAlarms"; // 默认文件名
|
saveFileDialog.DefaultExt = "csv"; // 默认文件扩展名
|
string filePath = "";
|
if (saveFileDialog.ShowDialog() == DialogResult.OK)
|
{
|
filePath = saveFileDialog.FileName; // 获取用户选择的文件路径
|
}
|
else
|
{
|
return false;
|
}
|
|
using (StreamWriter writer = new StreamWriter(filePath))
|
{
|
// 写入标题行
|
writer.WriteLine("报警名称,首地址,子地址");
|
// 写入数据行
|
foreach (var row in Pl)
|
{
|
writer.WriteLine($"{row.alarmname},{row.address},{row.address2}");
|
}
|
}
|
}
|
}
|
catch
|
{
|
|
}
|
return true;
|
}
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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("true:该检测项是固定检测项目,必须执行 false:该检测是可变检测项目,流程中决定是否检测,默认不检测")]
|
public bool IsFixed { get; set; } = true;
|
|
[Category("取像设置")]
|
[DisplayName("相机选择")]
|
[Description("选择该检测项对应的相机")]
|
[TypeConverter(typeof(DeviceIdSelectorConverter<CameraBase>))]
|
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<int>))]
|
[Editor(typeof(SimpleCollectionEditor<int>), typeof(UITypeEditor))]
|
public List<int> ProductIndices { get; set; } = new List<int>();
|
|
[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 string ImageSaveSeq { get; set; } = "1";
|
|
public string GetDisplayText()
|
{
|
string cameraName = "";
|
string detectionName = "未指定";
|
string methodName = "未指定";
|
string combineMethodName = "未指定";
|
using (var scope = GlobalVar.Container.BeginLifetimeScope())
|
{
|
var deviceList = scope.Resolve<List<IDevice>>();
|
|
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<IProcessConfig>();
|
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<string> GetHalconToolPathList()
|
{
|
return (SnapshotOpConfig as IHalconToolPath).GetHalconToolPathList();
|
}
|
}
|
|
|
public class ContinuousNGAlarm : IComplexDisplay, IImportFromFileInEditor
|
{
|
[Category("缺陷类型")]
|
[Description("选择需要监控的缺陷类型")]
|
[DisplayName("缺陷类型")]
|
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;
|
}
|
|
public IImportFromFileInEditor GetImportObject(string data, out string msg)
|
{
|
msg = "";
|
var dataList = data.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
if (dataList.Length < 6)
|
{
|
msg = "导入文件每行至少包含6段内容:缺陷类型,连续NG数量阈值,连续NG报警类型,监控时间段,时间内NG数量阈值,时段报警类型";
|
return null;
|
}
|
|
ContinuousNGAlarm ret = new ContinuousNGAlarm();
|
ret.DefectType = dataList[0];
|
ret.ContinuousNumThreshold = int.Parse(dataList[1]);
|
ret.ContinuousAlarmType = int.Parse(dataList[2]);
|
ret.TimePeriod = int.Parse(dataList[3]);
|
ret.TimePeriodNumThresold = int.Parse(dataList[4]);
|
ret.TimePeriodAlarmType = int.Parse(dataList[5]);
|
|
return ret;
|
}
|
|
public bool ICSVOutput(object o)
|
{
|
//try
|
//{
|
// if (o is )
|
// {
|
|
// }
|
//}
|
//catch
|
//{
|
|
//}
|
return true;
|
}
|
}
|
|
|
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;
|
}
|
}
|
|
|
|
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<List<IDevice>>();
|
camera = deviceList.FirstOrDefault(u => u.Id == ssa.CameraId);
|
}
|
|
if (camera != null)
|
{
|
var curCameraTypeAttr = camera.GetType().GetCustomAttribute<DeviceAttribute>();
|
var curOpconfigTypeAttr = value.GetType().GetCustomAttribute<DeviceAttribute>();
|
|
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<string, string> GetConvertDict(ITypeDescriptorContext context)
|
{
|
Dictionary<string, string> dict = new Dictionary<string, string>();
|
|
using (var scope = GlobalVar.Container.BeginLifetimeScope())
|
{
|
var config = scope.Resolve<IProcessConfig>();
|
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<ProductModel> 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<SpecSelector> SpecCollection { get; set; }
|
|
//List<SpecSelector> SpecCollection_CombineViews { get; set; }
|
|
List<PointSelector> CheckPointList { get; set; }
|
|
|
int Outindex { get; set; }
|
IImageCheckOperationConfig Clone();
|
|
|
|
}
|
|
|
public class PointSelector : IComplexDisplay, IImportFromFileInEditor
|
{
|
[ResCategory("点位选择")]
|
[ResDisplayName("选择点位")]
|
[ResDescription("从预设置的点位中选择")]
|
[TypeConverter(typeof(MeasurePointNameSelectorConvertor))]
|
public string pointCode { get; set; }
|
|
public string GetDisplayText()
|
{
|
return pointCode == null ? "" : pointCode;
|
}
|
|
|
public IImportFromFileInEditor GetImportObject(string data, out string msg)
|
{
|
msg = "";
|
PointSelector ret = new PointSelector();
|
try
|
{
|
|
using (var scope = GlobalVar.Container.BeginLifetimeScope())
|
{
|
var config = scope.Resolve<IProcessConfig>();
|
if (config is M141Config iConfig)
|
{
|
if (iConfig.MeasurePointCollection.Any(u => u.Name == data))
|
{
|
ret.pointCode = data;
|
}
|
else
|
{
|
throw new Exception(data + "不存在于点位集合中,不可录入");
|
}
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
throw ex;
|
}
|
|
return ret;
|
|
}
|
|
public bool ICSVOutput(object o)
|
{
|
try
|
{
|
if (o is List<PointSelector> Pl)
|
{
|
SaveFileDialog saveFileDialog = new SaveFileDialog();
|
saveFileDialog.Filter = "CSV files (*.csv)|*.csv"; // 设置文件过滤器,只显示CSV文件
|
saveFileDialog.Title = "Save CSV File"; // 设置对话框标题
|
saveFileDialog.FileName = "PointSelectors"; // 默认文件名
|
saveFileDialog.DefaultExt = "csv"; // 默认文件扩展名
|
string filePath = "";
|
if (saveFileDialog.ShowDialog() == DialogResult.OK)
|
{
|
filePath = saveFileDialog.FileName; // 获取用户选择的文件路径
|
}
|
else
|
{
|
return false;
|
}
|
|
using (StreamWriter writer = new StreamWriter(filePath))
|
{
|
// 写入标题行
|
writer.WriteLine("点位");
|
// 写入数据行
|
foreach (var row in Pl)
|
{
|
writer.WriteLine(row.pointCode);
|
}
|
}
|
}
|
}
|
catch
|
{
|
|
}
|
return true;
|
}
|
}
|
|
|
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
|
{
|
[Browsable(false)]
|
public List<ProductModel> Products { get; set; } = new List<ProductModel>();
|
|
[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<SpecSelector>), typeof(UITypeEditor))]
|
public List<SpecSelector> SpecCollection { get; set; } = new List<SpecSelector>();
|
|
|
[Category("检测标准")]
|
[Description("检测点位集合")]
|
[DisplayName("检测点位集合")]
|
[TypeConverter(typeof(ComplexObjectConvert))]
|
[Editor(typeof(ComplexCollectionEditor<PointSelector>), typeof(UITypeEditor))]
|
public List<PointSelector> CheckPointList { get; set; } = new List<PointSelector>();
|
|
|
//[ResCategory("标定配置")]
|
//[ResDescription("调用设备")]
|
//[ResDisplayName("调用设备")]
|
//[TypeConverter(typeof(DeviceIdSelectorConverter<IDevice>))]
|
//public string ExecuteDevice { get; set; } = "";
|
|
|
[Category("数据输出配置")]
|
[Description("配置数据输出时,代表数据输出序号,配置二次进算法时,代表数据量")]
|
[DisplayName("数据输出序号")]
|
public int Outindex { get; set; } = 0;
|
|
|
|
public List<string> GetHalconToolPathList()
|
{
|
return new List<string>() { 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.TriggerStr = TriggerStr;
|
|
//config.AlgorithemPath_CombineViews = AlgorithemPath_CombineViews;
|
//config.SpecCollection_CombineViews = SpecCollection_CombineViews.Select(u => new SpecSelector() { SpecCode = u.SpecCode }).ToList();
|
|
config.CheckPointList = CheckPointList.Select(u => new PointSelector() { pointCode = u.pointCode }).ToList();
|
|
return config;
|
}
|
}
|
|
|
[Device("OfflineDemo", "离线测试", DeviceAttributeType.OperationConfig)]
|
public class OfflineDemoOperationConfig : OperationConfigBase
|
{
|
[Category("图片目录")]
|
[Description("图片目录")]
|
[DisplayName("图片目录")]
|
[Editor(typeof(FoldDialogEditor), typeof(UITypeEditor))]
|
public string ImageFolder { get; set; }
|
|
[Category("启动配置")]
|
[Description("true:启动离线测试 false:停止离线测试")]
|
[DisplayName("测试开关")]
|
public bool IsStart { get; set; } = true;
|
}
|
|
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;
|
}
|
}
|
}
|