This commit is contained in:
2025-03-21 08:51:20 +08:00
parent 0dedff36fd
commit 9a5d3be528
70 changed files with 4542 additions and 2207 deletions

View File

@ -0,0 +1,300 @@
using System;
using System.ComponentModel;
using System.Drawing.Imaging;
using AntdUI;
using OpenCvSharp;
namespace DH.Commons.Base
{
public class CameraBase : NotifyProperty
{
// 私有字段 + 带通知的属性与DetectionLabel风格一致
private bool _isEnabled = false;
private bool _isContinueMode = false;
private bool _isSavePicEnabled = false;
private string _imageSaveDirectory;
private ImageFormat _imageFormat = ImageFormat.Jpeg;
private bool _isHardwareTrigger = false;
private string _serialNumber = string.Empty;
private string _cameraName = string.Empty;
private string _cameraIP = string.Empty;
private string _computerIP = string.Empty;
private bool _isDirectHardwareTrigger = false;
private float _gain = -1;
private float _rotateImage = 0;
private float _exposure = 200;
private float _triggerDelay = 0;
private decimal _roiX = 0;
private decimal _roiY = 0;
private decimal _roiW = 0;
private decimal _roiH = 0;
private int _lineDebouncerTime = 0;
public volatile int SnapshotCount = 0;
[Category("采图模式")]
[DisplayName("连续模式")]
[Description("是否连续模式。true连续模式采图false触发模式采图")]
public bool IsContinueMode
{
get => _isContinueMode;
set
{
if (_isContinueMode == value) return;
_isContinueMode = value;
OnPropertyChanged(nameof(IsContinueMode));
}
}
public virtual bool IsEnabled
{
get => _isEnabled;
set
{
if (_isEnabled == value) return;
_isEnabled = value;
OnPropertyChanged(nameof(IsEnabled));
}
}
public virtual bool IsSavePicEnabled
{
get => _isSavePicEnabled;
set
{
if (_isSavePicEnabled == value) return;
_isSavePicEnabled = value;
OnPropertyChanged(nameof(IsSavePicEnabled));
}
}
[Category("图片保存")]
[DisplayName("图片保存文件夹")]
[Description("图片保存文件夹")]
public virtual string ImageSaveDirectory
{
get => _imageSaveDirectory;
set
{
if (_imageSaveDirectory == value) return;
_imageSaveDirectory = value;
OnPropertyChanged(nameof(ImageSaveDirectory));
}
}
[Category("图片保存")]
[DisplayName("图片保存格式")]
[Description("图片保存格式")]
public ImageFormat ImageFormat
{
get => _imageFormat;
set
{
if (_imageFormat == value) return;
_imageFormat = value;
OnPropertyChanged(nameof(ImageFormat));
}
}
[Category("采图模式")]
[DisplayName("硬触发")]
[Description("是否硬触发模式。true硬触发false软触发")]
public bool IsHardwareTrigger
{
get => _isHardwareTrigger;
set
{
if (_isHardwareTrigger == value) return;
_isHardwareTrigger = value;
OnPropertyChanged(nameof(IsHardwareTrigger));
}
}
public string SerialNumber
{
get => _serialNumber;
set
{
if (_serialNumber == value) return;
_serialNumber = value;
OnPropertyChanged(nameof(SerialNumber));
}
}
public string CameraName
{
get => _cameraName;
set
{
if (_cameraName == value) return;
_cameraName = value;
OnPropertyChanged(nameof(CameraName));
}
}
public string CameraIP
{
get => _cameraIP;
set
{
if (_cameraIP == value) return;
_cameraIP = value;
OnPropertyChanged(nameof(CameraIP));
}
}
public string ComputerIP
{
get => _computerIP;
set
{
if (_computerIP == value) return;
_computerIP = value;
OnPropertyChanged(nameof(ComputerIP));
}
}
[Category("采图模式")]
[DisplayName("是否传感器直接硬触发")]
[Description("是否传感器直接硬触发。true传感器硬触发不通过软件触发false通过软件触发IO 的硬触发模式")]
public bool IsDirectHardwareTrigger
{
get => _isDirectHardwareTrigger;
set
{
if (_isDirectHardwareTrigger == value) return;
_isDirectHardwareTrigger = value;
OnPropertyChanged(nameof(IsDirectHardwareTrigger));
}
}
[Category("相机设置")]
[DisplayName("增益")]
[Description("Gain增益,-1:不设置不同型号相机的增益请参考mvs")]
public float Gain
{
get => _gain;
set
{
if (_gain.Equals(value)) return;
_gain = value;
OnPropertyChanged(nameof(Gain));
}
}
[Category("图像旋转")]
[DisplayName("默认旋转")]
[Description("默认旋转,相机开启后默认不旋转")]
public virtual float RotateImage
{
get => _rotateImage;
set
{
if (_rotateImage.Equals(value)) return;
_rotateImage = value;
OnPropertyChanged(nameof(RotateImage));
}
}
[Category("取像配置")]
[DisplayName("曝光")]
[Description("曝光")]
public virtual float Exposure
{
get => _exposure;
set
{
if (_exposure.Equals(value)) return;
_exposure = value;
OnPropertyChanged(nameof(Exposure));
}
}
[Category("相机设置")]
[DisplayName("硬触发后的延迟")]
[Description("TriggerDelay:硬触发后的延迟,单位us 微秒")]
public float TriggerDelay
{
get => _triggerDelay;
set
{
if (_triggerDelay.Equals(value)) return;
_triggerDelay = value;
OnPropertyChanged(nameof(TriggerDelay));
}
}
public decimal ROIX
{
get => _roiX;
set
{
if (_roiX == value) return;
_roiX = value;
OnPropertyChanged(nameof(ROIX));
}
}
public decimal ROIY
{
get => _roiY;
set
{
if (_roiY == value) return;
_roiY = value;
OnPropertyChanged(nameof(ROIY));
}
}
public decimal ROIW
{
get => _roiW;
set
{
if (_roiW == value) return;
_roiW = value;
OnPropertyChanged(nameof(ROIW));
}
}
public decimal ROIH
{
get => _roiH;
set
{
if (_roiH == value) return;
_roiH = value;
OnPropertyChanged(nameof(ROIH));
}
}
[Category("相机设置")]
[DisplayName("滤波时间")]
[Description("LineDebouncerTimeI/O去抖时间 单位us")]
public int LineDebouncerTime
{
get => _lineDebouncerTime;
set
{
if (_lineDebouncerTime == value) return;
_lineDebouncerTime = value;
OnPropertyChanged(nameof(LineDebouncerTime));
}
}
// 其他方法保持原有逻辑
public Action<DateTime, CameraBase, Mat> OnHImageOutput { get; set; }
public virtual bool CameraConnect() { return false; }
public virtual bool CameraDisConnect() { return false; }
public virtual void SetExposure(int exposureTime, string cameraName) { }
public virtual void SetGain(int gain, string cameraName) { }
internal virtual void SetAcquisitionMode(int mode) { }
internal virtual void SetAcqRegion(int offsetV, int offsetH, int imageH, int imageW, string cameraName) { }
}
}

View File

@ -7,26 +7,13 @@ using System.Text;
using System.Drawing.Design;
using AntdUI;
using static DH.Commons.Enums.EnumHelper;
using System.Text.Json.Serialization;
using DH.Commons.Enums;
namespace DH.Commons.Enums
namespace DH.Commons.Base
{
public enum MLModelType
{
[Description("图像分类")]
ImageClassification = 1,
[Description("目标检测")]
ObjectDetection = 2,
//[Description("图像分割")]
//ImageSegmentation = 3
[Description("语义分割")]
SemanticSegmentation = 3,
[Description("实例分割")]
InstanceSegmentation = 4,
[Description("目标检测GPU")]
ObjectGPUDetection = 5
}
public class ModelLabel
public class ModelLabel
{
public string LabelId { get; set; }
@ -42,7 +29,7 @@ namespace DH.Commons.Enums
[Description("模型识别的标签名称")]
public string LabelName { get; set; }
//[Category("模型配置")]
@ -71,28 +58,28 @@ namespace DH.Commons.Enums
//public int ImageResizeCount;
public bool IsCLDetection;
public int ProCount;
public string in_node_name;
public string in_node_name;
public string out_node_name;
public string out_node_name;
public string in_lable_path;
public string in_lable_path;
public int ResizeImageSize;
public int segmentWidth;
public int ImageWidth;
// public List<labelStringBase> OkClassTxtList;
// public List<labelStringBase> OkClassTxtList;
public List<ModelLabel> LabelNames;
public List<ModelLabel> LabelNames;
}
public enum ResultState
{
[Description("检测NG")]
DetectNG = -3,
@ -202,7 +189,7 @@ namespace DH.Commons.Enums
}
}
public class DetectStationResult
public class DetectStationResult
{
#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public string Pid { get; set; }
@ -219,7 +206,7 @@ namespace DH.Commons.Enums
public string DetectName { get; set; }
/// <summary>
/// 深度学习 检测结果
/// </summary>
@ -280,7 +267,7 @@ namespace DH.Commons.Enums
return cleanedString;
}
}
public class RelatedCamera : NotifyProperty
{
@ -402,7 +389,7 @@ namespace DH.Commons.Enums
public static double GetDistance(CustomizedPoint p1, CustomizedPoint p2)
{
return Math.Sqrt(Math.Pow((p1.X - p2.X), 2) + Math.Pow((p1.Y - p2.Y), 2));
return Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2));
}
public override string ToString()
@ -443,13 +430,13 @@ namespace DH.Commons.Enums
public int CompareTo(CustomizedPoint other)
{
return (X == other.X && Y == other.Y) ? 0 : 1;
return X == other.X && Y == other.Y ? 0 : 1;
}
public override int GetHashCode()
{
//return (int)(X * 10 + Y);
return (new Tuple<double, double>(X, Y)).GetHashCode();
return new Tuple<double, double>(X, Y).GetHashCode();
}
public static CustomizedPoint operator -(CustomizedPoint p1, CustomizedPoint p2)
@ -462,193 +449,421 @@ namespace DH.Commons.Enums
return new CustomizedPoint(p1.X + p2.X, p1.Y + p2.Y);
}
}
// public class PreTreatParam
// {
// public class PreTreatParam
// {
// /// <summary>
// /// 参数名称
// /// </summary>
// ///
// [Category("预处理参数")]
// [DisplayName("参数名称")]
// [Description("参数名称")]
//#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
// public string Name { get; set; }
// /// <summary>
// /// 参数名称
// /// </summary>
// ///
// [Category("预处理参数")]
// [DisplayName("参数名称")]
// [Description("参数名称")]
//#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
// public string Name { get; set; }
// /// <summary>
// /// 参数值
// /// </summary>
// ///
// [Category("预处理参数")]
// [DisplayName("参数值")]
// [Description("参数值")]
//#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
// public string Value { get; set; }
// /// <summary>
// /// 参数值
// /// </summary>
// ///
// [Category("预处理参数")]
// [DisplayName("参数值")]
// [Description("参数值")]
//#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
// public string Value { get; set; }
// }
public class DetectionConfig
// }
public class DetectionConfig : NotifyProperty
{
[ReadOnly(true)]
public string Id { get; set; } = Guid.NewGuid().ToString();
#region
private string _id = Guid.NewGuid().ToString();
private string _name;
private string _cameraSourceId = "";
private List<RelatedCamera> _cameraCollects = new List<RelatedCamera>();
private bool _isEnableGPU;
private bool _isMixModel;
private bool _isPreEnabled;
private bool _isEnabled;
private bool _isAddStation = true;
private string _halconAlgorithemPath_Pre;
private AntList<PreTreatParam> _preTreatParams = new AntList<PreTreatParam>();
private AntList<PreTreatParam> _outPreTreatParams = new AntList<PreTreatParam>();
private ModelType _modelType = ModelType.;
private string _modelPath;
private int _modelWidth = 640;
private int _modelHeight = 640;
private string _modeloutNodeName = "output0";
private float _modelconfThreshold = 0.5f;
private string _in_lable_path;
private AntList<DetectionLable> _detectionLableList = new AntList<DetectionLable>();
private AntList<SizeTreatParam> _sizeTreatParamList = new AntList<SizeTreatParam>();
private CustomizedPoint _showLocation = new CustomizedPoint();
private bool _saveOKOriginal = false;
private bool _saveNGOriginal = false;
private bool _saveOKDetect = false;
private bool _saveNGDetect = false;
#endregion
#region
[ReadOnly(true)]
public string Id
{
get => _id;
set
{
if (_id == value) return;
_id = value;
OnPropertyChanged(nameof(Id));
}
}
[Category("检测配置")]
[DisplayName("检测配置名称")]
[Description("检测配置名称")]
public string Name { get; set; }
[Category("关联相机")]
[DisplayName("关联相机")]
[Description("关联相机描述")]
public string CameraSourceId { get; set; } = "";
public string Name
{
get => _name;
set
{
if (_name == value) return;
_name = value;
OnPropertyChanged(nameof(Name));
}
}
[Category("关联相机集合")]
[DisplayName("关联相机集合")]
[Description("关联相机描述")]
//[TypeConverter(typeof(DeviceIdSelectorConverter<CameraBase>))]
public List<RelatedCamera> CameraCollects { get; set; } = new List<RelatedCamera>();
public List<RelatedCamera> CameraCollects
{
get => _cameraCollects;
set
{
if (_cameraCollects == value) return;
_cameraCollects = value;
OnPropertyChanged(nameof(CameraCollects));
}
}
[Category("启用配置")]
[DisplayName("是否启用GPU检测")]
[Description("是否启用GPU检测")]
public bool IsEnableGPU { get; set; } = false;
public bool IsEnableGPU
{
get => _isEnableGPU;
set
{
if (_isEnableGPU == value) return;
_isEnableGPU = value;
OnPropertyChanged(nameof(IsEnableGPU));
}
}
[Category("启用配置")]
[DisplayName("是否混料模型")]
[Description("是否混料模型")]
public bool IsMixModel { get; set; } = false;
public bool IsMixModel
{
get => _isMixModel;
set
{
if (_isMixModel == value) return;
_isMixModel = value;
OnPropertyChanged(nameof(IsMixModel));
}
}
[Category("启用配置")]
[DisplayName("是否启用预处理")]
[Description("是否启用预处理")]
public bool IsPreEnabled
{
get => _isPreEnabled;
set
{
if (_isPreEnabled == value) return;
_isPreEnabled = value;
OnPropertyChanged(nameof(IsPreEnabled));
}
}
[Category("启用配置")]
[DisplayName("是否启用该检测")]
[Description("是否启用该检测")]
public bool IsEnabled { get; set; }
public bool IsEnabled
{
get => _isEnabled;
set
{
if (_isEnabled == value) return;
_isEnabled = value;
OnPropertyChanged(nameof(IsEnabled));
}
}
[Category("启用配置")]
[DisplayName("是否加入检测工位")]
[Description("是否加入检测工位")]
public bool IsAddStation { get; set; } = true;
public bool IsAddStation
{
get => _isAddStation;
set
{
if (_isAddStation == value) return;
_isAddStation = value;
OnPropertyChanged(nameof(IsAddStation));
}
}
[Category("1.预处理(视觉算子)")]
[DisplayName("预处理-算法文件路径")]
// [Description("预处理算法文件路径配置")][Editor(typeof(FileDialogEditor), typeof(UITypeEditor))]
public string HalconAlgorithemPath_Pre { get; set; }
// [Category("1.预处理(视觉算子)")]
//[DisplayName("预处理-输出结果的SPEC标准")]
//[Description("预处理输出结果的SPEC标准配置")]
// public List<IndexedSpec> OutputSpec_Pre { get; set; } = new List<IndexedSpec>();
public string HalconAlgorithemPath_Pre
{
get => _halconAlgorithemPath_Pre;
set
{
if (_halconAlgorithemPath_Pre == value) return;
_halconAlgorithemPath_Pre = value;
OnPropertyChanged(nameof(HalconAlgorithemPath_Pre));
}
}
[Category("1.预处理(视觉算子)")]
[DisplayName("预处理-参数列表")]
[Description("预处理-参数列表")]
public List<PreTreatParam> PreTreatParams { get; set; } = new List<PreTreatParam>();
public AntList<PreTreatParam> PreTreatParams
{
get => _preTreatParams;
set
{
if (_preTreatParams == value) return;
_preTreatParams = value;
OnPropertyChanged(nameof(PreTreatParams));
}
}
[Category("1.预处理(视觉算子)")]
[DisplayName("预处理-输出参数列表")]
[Description("预处理-输出参数列表")]
public List<PreTreatParam> OUTPreTreatParams { get; set; } = new List<PreTreatParam>();
public AntList<PreTreatParam> OUTPreTreatParams
{
get => _outPreTreatParams;
set
{
if (_outPreTreatParams == value) return;
_outPreTreatParams = value;
OnPropertyChanged(nameof(OUTPreTreatParams));
}
}
[Category("2.中检测(深度学习)")]
[DisplayName("中检测-模型类型")]
[Description("模型类型ImageClassification-图片分类ObjectDetection目标检测Segmentation-图像分割")]
//[TypeConverter(typeof(EnumDescriptionConverter<MLModelType>))]
public MLModelType ModelType { get; set; } = MLModelType.ObjectDetection;
//[Category("2.中检测(深度学习)")]
//[DisplayName("中检测-GPU索引")]
//[Description("GPU索引")]
//public int GPUIndex { get; set; } = 0;
public ModelType ModelType
{
get => _modelType;
set
{
if (_modelType == value) return;
_modelType = value;
OnPropertyChanged(nameof(ModelType));
}
}
[Category("2.中检测(深度学习)")]
[DisplayName("中检测-模型文件路径")]
[Description("中处理 深度学习模型文件路径,路径中不可含有中文字符,一般情况可以只配置中检测模型,当需要先用预检测过滤一次时,请先配置好与预检测相关配置")]
public string ModelPath { get; set; }
[Description("中处理 深度学习模型文件路径")]
public string ModelPath
{
get => _modelPath;
set
{
if (_modelPath == value) return;
_modelPath = value;
OnPropertyChanged(nameof(ModelPath));
}
}
[Category("2.中检测(深度学习)")]
[DisplayName("中检测-模型宽度")]
[Description("中处理-模型宽度")]
public int ModelWidth { get; set; } = 640;
public int ModelWidth
{
get => _modelWidth;
set
{
if (_modelWidth == value) return;
_modelWidth = value;
OnPropertyChanged(nameof(ModelWidth));
}
}
[Category("2.中检测(深度学习)")]
[DisplayName("中检测-模型高度")]
[Description("中处理-模型高度")]
public int ModelHeight { get; set; } = 640;
public int ModelHeight
{
get => _modelHeight;
set
{
if (_modelHeight == value) return;
_modelHeight = value;
OnPropertyChanged(nameof(ModelHeight));
}
}
[Category("2.中检测(深度学习)")]
[DisplayName("中检测-模型节点名称")]
[Description("中处理-模型节点名称")]
public string ModeloutNodeName { get; set; } = "output0";
public string ModeloutNodeName
{
get => _modeloutNodeName;
set
{
if (_modeloutNodeName == value) return;
_modeloutNodeName = value;
OnPropertyChanged(nameof(ModeloutNodeName));
}
}
[Category("2.中检测(深度学习)")]
[DisplayName("中检测-模型置信度")]
[Description("中处理-模型置信度")]
public float ModelconfThreshold { get; set; } = 0.5f;
public float ModelconfThreshold
{
get => _modelconfThreshold;
set
{
if (_modelconfThreshold == value) return;
_modelconfThreshold = value;
OnPropertyChanged(nameof(ModelconfThreshold));
}
}
[Category("2.中检测(深度学习)")]
[DisplayName("中检测-模型标签路径")]
[Description("中处理-模型标签路径")]
public string in_lable_path { get; set; }
[Category("4.最终过滤(逻辑过滤)")]
[DisplayName("过滤器集合")]
[Description("最后的逻辑过滤:可根据 识别出对象的 宽度、高度、面积、得分来设置最终检测结果,同一识别目标同一判定,多项过滤器之间为“或”关系")]
public List<DetectionFilter> DetectionFilterList { get; set; } = new List<DetectionFilter>();
/// <summary>
/// 标签集合
/// </summary>
public List<DetectionLable> DetectionLableList { get; set; } = new List<DetectionLable>();
//[Category("深度学习配置")]
//[DisplayName("检测配置标签")]
//[Description("检测配置标签关联")]
//public List<DetectConfigLabel> DetectConfigLabelList { get; set; } = new List<DetectConfigLabel>();
[Category("显示配置")]
[DisplayName("显示位置")]
[Description("检测信息显示位置。左上角为11向右向下为正方向")]
// [TypeConverter(typeof(ComplexObjectConvert))]
// [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))]
public CustomizedPoint ShowLocation { get; set; } = new CustomizedPoint();
public DetectionConfig()
public string In_lable_path
{
get => _in_lable_path;
set
{
if (_in_lable_path == value) return;
_in_lable_path = value;
OnPropertyChanged(nameof(In_lable_path));
}
}
public DetectionConfig(string name, MLModelType modelType, string modelPath, bool isEnableGPU,string sCameraSourceId)
{
[Category("显示配置")]
[DisplayName("显示位置")]
[Description("检测信息显示位置")]
public CustomizedPoint ShowLocation
{
get => _showLocation;
set
{
if (_showLocation == value) return;
_showLocation = value;
OnPropertyChanged(nameof(ShowLocation));
}
}
/// <summary>
/// 标签集合需确保DetectionLable也实现INotifyPropertyChanged
/// </summary>
public AntList<DetectionLable> DetectionLableList
{
get => _detectionLableList;
set
{
if (_detectionLableList == value) return;
_detectionLableList = value;
OnPropertyChanged(nameof(DetectionLableList));
}
}
public AntList<SizeTreatParam> SizeTreatParamList
{
get => _sizeTreatParamList;
set
{
if (_sizeTreatParamList == value) return;
_sizeTreatParamList = value;
OnPropertyChanged(nameof(SizeTreatParamList));
}
}
public bool SaveOKOriginal
{
get => _saveOKOriginal;
set
{
if (_saveOKOriginal == value) return;
_saveOKOriginal = value;
OnPropertyChanged(nameof(SaveOKOriginal));
}
}
public bool SaveNGOriginal
{
get => _saveNGOriginal;
set
{
if (_saveNGOriginal == value) return;
_saveNGOriginal = value;
OnPropertyChanged(nameof(SaveNGOriginal));
}
}
public bool SaveOKDetect
{
get => _saveOKDetect;
set
{
if (_saveOKDetect == value) return;
_saveOKDetect = value;
OnPropertyChanged(nameof(SaveOKDetect));
}
}
public bool SaveNGDetect
{
get => _saveNGDetect;
set
{
if (_saveNGDetect == value) return;
_saveNGDetect = value;
OnPropertyChanged(nameof(SaveNGDetect));
}
}
#endregion
#region
public DetectionConfig() { }
public DetectionConfig(
string name,
ModelType modelType,
string modelPath,
bool isEnableGPU,
string sCameraSourceId)
{
// 通过属性赋值触发通知
ModelPath = modelPath ?? string.Empty;
Name = name;
ModelType = modelType;
IsEnableGPU = isEnableGPU;
Id = Guid.NewGuid().ToString();
CameraSourceId = sCameraSourceId;
}
#endregion
}
//大改预处理类
@ -696,6 +911,7 @@ namespace DH.Commons.Enums
}
private CellLink[] cellLinks;
[JsonIgnore]
public CellLink[] CellLinks
{
get { return cellLinks; }
@ -724,7 +940,7 @@ namespace DH.Commons.Enums
public bool Selected
{
get { return _selected; }
@ -816,6 +1032,7 @@ namespace DH.Commons.Enums
}
private CellLink[] cellLinks;
[JsonIgnore]
public CellLink[] CellLinks
{
get { return cellLinks; }
@ -909,7 +1126,7 @@ namespace DH.Commons.Enums
_resultShow = value;
OnPropertyChanged(nameof(ResultShow));
}
}
public string OutResultShow
@ -933,9 +1150,10 @@ namespace DH.Commons.Enums
OnPropertyChanged(nameof(PrePath));
}
}
private CellLink[] cellLinks;
[JsonIgnore]
public CellLink[] CellLinks
{
get { return cellLinks; }
@ -973,9 +1191,9 @@ namespace DH.Commons.Enums
//[TypeConverter(typeof(LabelCategoryConverter))]
public string LabelCategory { get; set; } = "";
}
/// <summary>
@ -1036,8 +1254,8 @@ namespace DH.Commons.Enums
//public string GetLabelName()
//{
// var name = "";
// var mlBase = iConfig.DeviceConfigs.FirstOrDefault(c => c is VisionEngineInitialConfigBase) as VisionEngineInitialConfigBase;
// if (mlBase != null)
// {
@ -1048,7 +1266,7 @@ namespace DH.Commons.Enums
// }
// }
// return name;
//}
}
@ -1109,11 +1327,11 @@ namespace DH.Commons.Enums
[DisplayName("过滤条件集合")]
[Description("过滤条件集合,集合之间为“且”关系")]
//[TypeConverter(typeof(CollectionCountConvert))]
// [Editor(typeof(ComplexCollectionEditor<FilterConditions>), typeof(UITypeEditor))]
// [Editor(typeof(ComplexCollectionEditor<FilterConditions>), typeof(UITypeEditor))]
public List<FilterConditions> FilterConditionsCollection { get; set; } = new List<FilterConditions>();
public bool FilterOperation(DetectionResultDetail recongnitionResult)
{
return FilterConditionsCollection.All(u =>

408
DH.Commons/Base/PLCBase.cs Normal file
View File

@ -0,0 +1,408 @@
using System.ComponentModel;
using System.IO.Ports;
using System.Text.Json.Serialization;
using AntdUI;
using DH.Commons.Enums; // 请确保此命名空间包含EnumPLCType
namespace DH.Commons.Base
{
public class PLCBase : NotifyProperty
{
// 私有字段
private bool _enable;
private bool _connected;
private string _plcName;
private EnumPLCType _plcType;
private string _com = "COM1";
private int _baudRate = 9600;
private int _dataBit = 8;
private StopBits _stopBit = StopBits.One;
private Parity _parity = Parity.None;
private string _ip = "192.168.6.6";
private int _port = 502;
private AntList<PLCItem> _PLCItemList = new AntList<PLCItem>();
[Category("设备配置")]
[DisplayName("是否启用")]
[Description("是否启用")]
public bool Enable
{
get => _enable;
set
{
if (_enable == value) return;
_enable = value;
OnPropertyChanged(nameof(Enable));
}
}
[Category("状态监控")]
[DisplayName("连接状态")]
[Description("PLC连接状态")]
public bool Connected
{
get => _connected;
set
{
if (_connected == value) return;
_connected = value;
OnPropertyChanged(nameof(Connected));
}
}
[Category("设备配置")]
[DisplayName("PLC名称")]
[Description("PLC设备名称")]
public string PLCName
{
get => _plcName;
set
{
if (_plcName == value) return;
_plcName = value;
OnPropertyChanged(nameof(PLCName));
}
}
[Category("设备配置")]
[DisplayName("PLC类型")]
[Description("PLC通信协议类型")]
public EnumPLCType PLCType
{
get => _plcType;
set
{
if (_plcType == value) return;
_plcType = value;
OnPropertyChanged(nameof(PLCType));
}
}
[Category("串口配置")]
[DisplayName("COM端口")]
[Description("串口号如COM1")]
public string COM
{
get => _com;
set
{
if (_com == value) return;
_com = value;
OnPropertyChanged(nameof(COM));
}
}
[Category("串口配置")]
[DisplayName("波特率")]
[Description("串口通信波特率")]
public int BaudRate
{
get => _baudRate;
set
{
if (_baudRate == value) return;
_baudRate = value;
OnPropertyChanged(nameof(BaudRate));
}
}
[Category("串口配置")]
[DisplayName("数据位")]
[Description("数据位长度(5/6/7/8)")]
public int DataBit
{
get => _dataBit;
set
{
if (_dataBit == value) return;
_dataBit = value;
OnPropertyChanged(nameof(DataBit));
}
}
[Category("串口配置")]
[DisplayName("停止位")]
[Description("停止位设置")]
public StopBits StopBit
{
get => _stopBit;
set
{
if (_stopBit == value) return;
_stopBit = value;
OnPropertyChanged(nameof(StopBit));
}
}
[Category("串口配置")]
[DisplayName("校验位")]
[Description("奇偶校验方式")]
public Parity Parity
{
get => _parity;
set
{
if (_parity == value) return;
_parity = value;
OnPropertyChanged(nameof(Parity));
}
}
[Category("网络配置")]
[DisplayName("IP地址")]
[Description("PLC网络地址")]
public string IP
{
get => _ip;
set
{
if (_ip == value) return;
_ip = value;
OnPropertyChanged(nameof(IP));
}
}
[Category("网络配置")]
[DisplayName("端口号")]
[Description("网络通信端口")]
public int Port
{
get => _port;
set
{
if (_port == value) return;
_port = value;
OnPropertyChanged(nameof(Port));
}
}
[Category("点位配置")]
[DisplayName("点位配置")]
[Description("点位配置")]
public AntList<PLCItem> PLCItemList
{
get => _PLCItemList;
set
{
if (_PLCItemList == value) return;
_PLCItemList = value;
OnPropertyChanged(nameof(PLCItemList));
}
}
public virtual bool PLCConnect()
{
Connected = true;
return true;
}
public virtual bool PLCDisConnect()
{
Connected = false;
return true;
}
public virtual ushort ReadShort(string address) { return 0; }
public virtual int ReadInt(string address) { return 0; }
public virtual float ReadFloat(string address) { return 0; }
public virtual bool ReadBool(string address) { return false; }
public virtual bool WriteShort(string address, short value, bool waitForReply = true) { return false; }
public virtual bool WriteInt(string address, int value, bool waitForReply = true) { return false; }
public virtual bool WriteDInt(string address, int value, bool waitForReply = true) { return false; }
public virtual bool WriteFloat(string address, float value, bool waitForReply = true) { return false; }
public virtual bool WriteBool(string address, bool value, bool waitForReply = true) { return false; }
}
public class PLCItem : NotifyProperty
{
private bool _selected;
private string _name = string.Empty;
private string _type = string.Empty;
private string _value = string.Empty;
private bool _startexecute;
private bool _endexecute;
private int _startindex;
private int _endindex;
private string _numtype;
private string _address;
/// <summary>
/// 是否选中
/// </summary>
public bool Selected
{
get => _selected;
set
{
if (_selected != value)
{
_selected = value;
OnPropertyChanged(nameof(Selected));
}
}
}
/// <summary>
/// 参数名称
/// </summary>
public string Name
{
get => _name;
set
{
if (_name != value)
{
_name = value;
OnPropertyChanged(nameof(Name));
}
}
}
public string Type
{
get => _type;
set
{
if (_type != value)
{
_type = value;
OnPropertyChanged(nameof(Type));
}
}
}
/// <summary>
/// 参数类型
/// </summary>
public string Address
{
get => _address;
set
{
if (_address != value)
{
_address = value;
OnPropertyChanged(nameof(Address));
}
}
}
public string NumTpye
{
get => _numtype;
set
{
if (_numtype != value)
{
_numtype = value;
OnPropertyChanged(nameof(NumTpye));
}
}
}
/// <summary>
/// 参数值
/// </summary>
public string Value
{
get => _value;
set
{
if (_value != value)
{
_value = value;
OnPropertyChanged(nameof(Value));
}
}
}
/// <summary>
/// 流程开启执行状态
/// </summary>
public bool StartExecute
{
get => _startexecute;
set
{
if (_startexecute != value)
{
_startexecute = value;
OnPropertyChanged(nameof(StartExecute));
}
}
}
/// <summary>
/// 流程结束执行状态
/// </summary>
public bool EndExecute
{
get => _endexecute;
set
{
if (_endexecute != value)
{
_endexecute = value;
OnPropertyChanged(nameof(EndExecute));
}
}
}
/// <summary>
/// 流程开启顺序
/// </summary>
public int StartIndex
{
get => _startindex;
set
{
if (_startindex != value)
{
_startindex = value;
OnPropertyChanged(nameof(StartIndex));
}
}
}
/// <summary>
/// 流程结束顺序
/// </summary>
public int EndIndex
{
get => _endindex;
set
{
if (_endindex != value)
{
_endindex = value;
OnPropertyChanged(nameof(EndIndex));
}
}
}
private CellLink[] cellLinks;
[JsonIgnore]
public CellLink[] CellLinks
{
get { return cellLinks; }
set
{
if (cellLinks == value) return;
cellLinks = value;
OnPropertyChanged(nameof(CellLinks));
}
}
private CellTag[] cellTags;
[JsonIgnore]
public CellTag[] CellTags
{
get { return cellTags; }
set
{
if (cellTags == value) return;
cellTags = value;
OnPropertyChanged(nameof(CellTags));
}
}
}
}

View File

@ -0,0 +1,186 @@
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using DH.Commons.Enums;
using HalconDotNet;
using OpenCvSharp;
namespace DH.Commons.Base
{
/// <summary>
/// 视觉处理引擎1.传统视觉 2.深度学习
/// CV深度学习 四大领域
/// Image Classification 图像分类:判别图中物体是什么,比如是猫还是狗;
/// Semantic Segmentation 语义分割:对图像进行像素级分类,预测每个像素属于的类别,不区分个体;
/// Object Detection 目标检测:寻找图像中的物体并进行定位;
/// Instance Segmentation 实例分割:定位图中每个物体,并进行像素级标注,区分不同个体;
/// </summary>
public abstract class VisionEngineBase
{
public List<DetectionConfig> DetectionConfigs = new List<DetectionConfig>();
#region event
public event Action<string, List<double>> OnCropParamsOutput;
public event Action<string, Bitmap, List<IShapeElement>> OnDetectionDone;
public event Action<string> OnDetectionWarningStop;//有无检测 需要报警停机
#endregion
//public VisionEngineInitialConfigBase IConfig
//{
// get => InitialConfig as VisionEngineInitialConfigBase;
//}
// public ImageSaveHelper ImageSaveHelper { get; set; } = new ImageSaveHelper();
public string BatchNO { get; set; }
public HTuple hv_ModelID;
public abstract DetectStationResult RunInference(Mat originImgSet, string detectionId = null);
//public abstract void SaveDetectResultAsync(DetectStationResult detectResult);
public virtual void DetectionDone(string detectionId, Bitmap image, List<IShapeElement> detectionResults)
{
OnDetectionDone?.Invoke(detectionId, image, detectionResults);
}
public virtual void DetectionWarningStop(string detectionDes)
{
OnDetectionWarningStop?.Invoke(detectionDes);
}
public virtual void SaveImageAsync(string fullname, Bitmap saveMap, ImageFormat imageFormat)
{
if (saveMap != null)
{
//ImageSaveSet imageSaveSet = new ImageSaveSet()
//{
// FullName = fullname,
// SaveImage = saveMap.CopyBitmap(),
// ImageFormat = imageFormat.DeepSerializeClone()
//};
//ImageSaveHelper.ImageSaveAsync(imageSaveSet);
}
}
}
public class CamModuleXY
{
[Category("图片行")]
[DisplayName("行")]
[Description("行")]
// [TypeConverter(typeof(DeviceIdSelectorConverter<CameraBase>))]
//[TypeConverter(typeof(CollectionCountConvert))]
public int PicRows { get; set; } = 1;
[Category("图片列")]
[DisplayName("列")]
[Description("列")]
// [TypeConverter(typeof(DeviceIdSelectorConverter<CameraBase>))]
//[TypeConverter(typeof(CollectionCountConvert))]
public int PicCols { get; set; } = 1;
public string GetDisplayText()
{
return "行:" + PicRows.ToString() + "列:" + PicCols.ToString();
}
}
//public class RelatedCamera
//{
// [Category("关联相机")]
// [DisplayName("关联相机")]
// [Description("关联相机描述")]
// //[TypeConverter(typeof(DeviceIdSelectorConverter<CameraBase>))]
// //[TypeConverter(typeof(CollectionCountConvert))]
// public string CameraSourceId { get; set; } = "";
// //public string GetDisplayText()
// //{
// // using (var scope = GlobalVar.Container.BeginLifetimeScope())
// // {
// // List<IDevice> deviceList = scope.Resolve<List<IDevice>>();
// // IDevice CameraDevice = deviceList.FirstOrDefault(dev => dev.Id.Equals(CameraSourceId));
// // if (CameraDevice != null && CameraDevice is CameraBase)
// // {
// // return CameraDevice.Name;
// // }
// // }
// // return CameraSourceId;
// //}
//}
public class VisionEngineInitialConfigBase //: InitialConfigBase
{
[Category("深度学习检测配置")]
[DisplayName("检测配置集合")]
[Description("检测配置集合")]
//[TypeConverter(typeof(CollectionCountConvert))]
//[Editor(typeof(ComplexCollectionEditor<DetectionConfig>), typeof(UITypeEditor))]
public List<DetectionConfig> DetectionConfigs { get; set; } = new List<DetectionConfig>();
[Category("深度学习检测配置")]
[DisplayName("标签分类")]
[Description("标签分类,A_NG,B_TBD...")]
// [TypeConverter(typeof(CollectionCountConvert))]
// [Editor(typeof(ComplexCollectionEditor<RecongnitionLabelCategory>), typeof(UITypeEditor))]
public List<RecongnitionLabelCategory> RecongnitionLabelCategoryList { get; set; } = new List<RecongnitionLabelCategory>();
[Category("深度学习检测配置")]
[DisplayName("检测标签定义集合")]
[Description("定义检测标签的集合例如Seg/Detection模式断裂、油污、划伤...Class模式ok、ng、上面、下面、套环、正常...")]
// [TypeConverter(typeof(CollectionCountConvert))]
// [Editor(typeof(ComplexCollectionEditor<RecongnitionLabel>), typeof(UITypeEditor))]
public List<RecongnitionLabel> RecongnitionLabelList { get; set; } = new List<RecongnitionLabel>();
[Category("深度学习检测配置")]
[DisplayName("标签置信度")]
[Description("标签置信度,过滤小于改置信度的标签,大于该设置的标签才能识别")]
public float Score { get; set; } = 0.5f;
[Category("深度学习检测配置")]
[DisplayName("CPU线程数量")]
[Description("用于深度学习的CPU线程数量不要设置太大会单独占用线程影响其他程序运行")]
public int CPUNums { get; set; } = 1;
//[Category("深度学习检测配置")]
//[DisplayName("检测项GPU指定")]
//[Description("将检测项指定到GPU")]
// [TypeConverter(typeof(CollectionCountConvert))]
// [Editor(typeof(ComplexCollectionEditor<DetectionGPUConfig>), typeof(UITypeEditor))]
// public List<DetectionGPUConfig> DetectionGPUList { get; set; } = new List<DetectionGPUConfig>();
// [Category("数据保存配置")]
//[DisplayName("是否保存检测明细CSV")]
//[Description("是否保存 检测明细CSV")]
//public override bool IsEnableCSV { get; set; } = true;
//[Category("数据保存配置")]
//[DisplayName("是否保存检测图片")]
//[Description("是否保存 检测图片,总开关")]
//public bool IsSaveImage { get; set; } = true;
//[Category("数据保存配置")]
//[Description("检测图片 保存文件夹")]
//[DisplayName("检测图片保存文件夹")]
//[Editor(typeof(FoldDialogEditor), typeof(UITypeEditor))]
//public string ImageSaveDirectory { get; set; } = "D:\\PROJECTS\\X017\\Images";
//[Category("数据保存配置")]
//[Description("检测明细CSV文件夹")]
//[DisplayName("检测明细CSV文件夹")]
//[Editor(typeof(FoldDialogEditor), typeof(UITypeEditor))]
//public string CSVDataPath { get; set; } = "D:\\PROJECTS\\X017\\Images";
}
}

View File

@ -13,12 +13,19 @@
<ItemGroup>
<PackageReference Include="AntdUI" Version="1.8.9" />
<PackageReference Include="OpenCvSharp4" Version="4.10.0.20241108" />
<PackageReference Include="OpenCvSharp4.Extensions" Version="4.10.0.20241108" />
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.10.0.20241108" />
<PackageReference Include="System.IO.Ports" Version="9.0.3" />
</ItemGroup>
<ItemGroup>

View File

@ -1,16 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DH.Commons.Enums
{
public class CameraInfo
{
public string CamName { get; set; }
public string Serinum { get; set; }
public string IP { get; set; }
}
}

View File

@ -7,12 +7,48 @@ using System.Threading.Tasks;
namespace DH.Commons.Enums
{
public enum ModelType
{
= 1,
= 2,
= 3,
= 4,
GPU = 5
}
public enum SelectPicType
{
[Description("训练图片")]
train = 0,
[Description("测试图片")]
test
}
public enum NetModel
{
[Description("目标检测")]
training = 0,
[Description("语义分割")]
train_seg,
[Description("模型导出")]
emport,
[Description("推理预测")]
infernce
}
public enum EnumPLCType
{
XC_串口,
XC_网口,
XD_串口,
XD_网口
[Description("信捷XC串口")]
XC串口 = 0,
[Description("信捷XC网口")]
XC网口 = 1,
[Description("信捷XD串口")]
XD串口 = 2,
[Description("信捷XD网口")]
XD网口 = 3
}
@ -43,20 +79,39 @@ namespace DH.Commons.Enums
3=13,
4=14,
5=15,
OK料盒=16,
NG料盒=17,
OK吹气时间=18,
NG吹气时间=19,
=20,
=21,
=22,
=23,
=24,
=25
6 = 16,
7 = 17,
8 = 18,
9 = 19,
10 = 20,
OK料盒 =21,
NG料盒=22,
OK吹气时间=23,
NG吹气时间=24,
=25,
=26,
=27,
=28,
=29,
=30
}
public enum EnumPLCDataType
{
HD,
D,
M
}
public enum EnumPLCINTType
{
16,
32,
16,
32
}
public enum StreamFormat
{
[Description("8位图像")]

View File

@ -0,0 +1,227 @@
using System;
using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;
using DH.Commons.Base;
using DH.Commons.Models;
namespace DH.Commons.Helper
{
public static class ConfigHelper
{
private static readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions
{
WriteIndented = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
IgnoreNullValues = true
};
/// <summary>
/// 配置存储根目录
/// </summary>
private static string ConfigsRoot => Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
"configs");
/// <summary>
/// 获取当前方案的主配置文件路径
/// </summary>
private static string CurrentConfigPath
{
get
{
ValidateCurrentScheme();
return Path.Combine(
ConfigsRoot,
$"config_{SystemModel.CurrentScheme}.json");
}
}
/// <summary>
/// 获取当前方案的备份目录路径
/// </summary>
private static string CurrentBackupDir
{
get
{
ValidateCurrentScheme();
return Path.Combine(
ConfigsRoot,
$"bak_{SystemModel.CurrentScheme}");
}
}
/// <summary>
/// 初始化新方案(创建空文件)
/// </summary>
public static void InitializeScheme(string scheme)
{
SystemModel.CurrentScheme = scheme;
// 创建空配置文件
if (!File.Exists(CurrentConfigPath))
{
Directory.CreateDirectory(ConfigsRoot);
File.WriteAllText(CurrentConfigPath, "{}");
}
// 创建备份目录
Directory.CreateDirectory(CurrentBackupDir);
}
/// <summary>
/// 保存当前配置(自动备份)
/// </summary>
public static void SaveConfig()
{
ValidateCurrentScheme();
// 确保配置目录存在
Directory.CreateDirectory(ConfigsRoot);
// 备份现有配置
if (File.Exists(CurrentConfigPath))
{
var backupName = $"config_{SystemModel.CurrentScheme}_{DateTime.Now:yyyyMMddHHmmss}.json";
var backupPath = Path.Combine(CurrentBackupDir, backupName);
Directory.CreateDirectory(CurrentBackupDir);
File.Copy(CurrentConfigPath, backupPath);
}
// 序列化当前配置
var json = JsonSerializer.Serialize(new
{
ConfigModel.CameraBaseList,
ConfigModel.PLCBaseList,
ConfigModel.DetectionList
}, _jsonOptions);
// 写入新配置
File.WriteAllText(CurrentConfigPath, json);
}
/// <summary>
/// 加载当前方案配置
/// </summary>
public static void LoadConfig()
{
ValidateCurrentScheme();
if (!File.Exists(CurrentConfigPath))
{
InitializeScheme(SystemModel.CurrentScheme);
return;
}
var json = File.ReadAllText(CurrentConfigPath);
var data = JsonSerializer.Deserialize<ConfigData>(json, _jsonOptions);
ConfigModel.CameraBaseList = data?.Cameras ?? new List<CameraBase>();
ConfigModel.PLCBaseList = data?.PLCs ?? new List<PLCBase>();
ConfigModel.DetectionList = data?.Detections ?? new List<DetectionConfig>();
}
/// <summary>
/// 验证当前方案有效性
/// </summary>
private static void ValidateCurrentScheme()
{
if (string.IsNullOrWhiteSpace(SystemModel.CurrentScheme))
throw new InvalidOperationException("当前方案未设置");
}
/// <summary>
/// 派生新方案(基于当前方案创建副本)
/// </summary>
/// <param name="newSchemeName">新方案名称</param>
public static void DeriveScheme(string newSchemeName)
{
// 验证输入
if (string.IsNullOrWhiteSpace(newSchemeName))
{
throw new ArgumentException("新方案名称不能为空");
}
// 验证当前方案是否有效
ValidateCurrentScheme();
// 检查新方案是否已存在
var newConfigPath = Path.Combine(ConfigsRoot, $"config_{newSchemeName}.json");
if (File.Exists(newConfigPath))
{
throw new InvalidOperationException($"方案 {newSchemeName} 已存在");
}
// 保存当前配置确保最新
SaveConfig();
try
{
// 复制配置文件
File.Copy(CurrentConfigPath, newConfigPath);
// 创建备份目录
var newBackupDir = Path.Combine(ConfigsRoot, $"bak_{newSchemeName}");
Directory.CreateDirectory(newBackupDir);
// 可选:自动切换新方案
// SystemModel.CurrentScheme = newSchemeName;
}
catch (IOException ex)
{
throw new InvalidOperationException($"方案派生失败: {ex.Message}", ex);
}
}
/// <summary>
/// 删除指定方案的配置文件及备份目录
/// </summary>
/// <param name="schemeName">要删除的方案名称</param>
/// <exception cref="ArgumentException">当方案名称为空时抛出</exception>
/// <exception cref="IOException">文件操作失败时抛出</exception>
public static void DeleteSchemeConfig(string schemeName)
{
if (string.IsNullOrWhiteSpace(schemeName))
throw new ArgumentException("方案名称无效");
// 构造路径
var configPath = Path.Combine(ConfigsRoot, $"config_{schemeName}.json");
var backupDir = Path.Combine(ConfigsRoot, $"bak_{schemeName}");
try
{
// 删除配置文件
if (File.Exists(configPath))
{
File.Delete(configPath);
}
// 删除备份目录(递归删除)
if (Directory.Exists(backupDir))
{
Directory.Delete(backupDir, true);
}
}
catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException)
{
throw new IOException($"删除方案 {schemeName} 的配置文件失败: {ex.Message}", ex);
}
}
/// <summary>
/// 配置数据模型(内部类)
/// </summary>
private class ConfigData
{
[JsonPropertyName("cameraBaseList")]
public List<CameraBase> Cameras { get; set; } = new List<CameraBase>();
[JsonPropertyName("plcBaseList")]
public List<PLCBase> PLCs { get; set; } = new List<PLCBase>();
[JsonPropertyName("detectionList")]
public List<DetectionConfig> Detections { get; set; } = new List<DetectionConfig>();
}
}
}

View File

@ -76,160 +76,50 @@ namespace DH.Commons.Enums
}
}
//public static System.Windows.Media.Color GetEnumSelectedMediaColor(this Enum enumObj)
//{
// Type t = enumObj.GetType();
// FieldInfo f = t.GetField(enumObj.ToString());
// ColorSelectAttribute attr = f.GetCustomAttribute<ColorSelectAttribute>();
// if (attr != null)
// {
// var prop = typeof(System.Windows.Media.Colors).GetProperties().FirstOrDefault(p => p.Name == attr.SelectedColor);
// if (prop != null)
// {
// return (System.Windows.Media.Color)prop.GetValue(null);
// }
// }
// return System.Windows.Media.Colors.Transparent;
//}
//public static System.Drawing.Color GetEnumSelectedColor(this Enum enumObj)
//{
// Type t = enumObj.GetType();
// FieldInfo f = t.GetField(enumObj.ToString());
// ColorSelectAttribute attr = f.GetCustomAttribute<ColorSelectAttribute>();
// if (attr != null)
// {
// return System.Drawing.Color.FromName(attr.SelectedColor);
// }
// else
// {
// return System.Drawing.Color.Transparent;
// }
//}
//public static System.Drawing.Color GetEnumSelectedFontColor(this Enum enumObj)
//{
// Type t = enumObj.GetType();
// FieldInfo f = t.GetField(enumObj.ToString());
// var attr = f.GetCustomAttribute<FontColorSelectAttribute>();
// if (attr != null)
// {
// return System.Drawing.Color.FromName(attr.SelectedColor);
// }
// else
// {
// return System.Drawing.Color.Transparent;
// }
//}
//public static string GetEnumSelectedColorString(this Enum enumObj)
//{
// Type t = enumObj.GetType();
// FieldInfo f = t.GetField(enumObj.ToString());
// ColorSelectAttribute attr = f.GetCustomAttribute<ColorSelectAttribute>();
// if (attr != null)
// {
// return attr.SelectedColor;
// }
// else
// {
// return "Transparent";
// }
//}
// 根据描述获取枚举值(泛型方法)
public static T GetEnumFromDescription<T>(string description) where T : Enum
{
Type enumType = typeof(T);
foreach (T value in Enum.GetValues(enumType))
{
string desc = GetEnumDescription(value);
if (desc == description)
{
return value;
}
}
throw new ArgumentException($"在枚举 {enumType.Name} 中未找到描述为 '{description}' 的值");
}
/// <summary>
/// 当枚举牵涉到状态变换,检查现状态是否满足待转换的状态的前置状态要求
/// 获取枚举类型的所有描述文本
/// </summary>
/// <param name="stateToBe"></param>
/// <param name="currentState"></param>
/// <returns></returns>
//public static bool CheckPreStateValid(this Enum stateToBe, int currentState)
//{
// Type t = stateToBe.GetType();
// FieldInfo f = t.GetField(stateToBe.ToString());
/// <param name="enumType">枚举类型</param>
/// <returns>描述文本列表</returns>
public static List<string> GetEnumDescriptions(Type enumType)
{
// 验证类型是否为枚举
if (!enumType.IsEnum)
throw new ArgumentException("传入的类型必须是枚举类型", nameof(enumType));
// PreStateAttribute attr = f.GetCustomAttribute<PreStateAttribute>();
// if (attr == null)
// {
// return true;
// }
// else
// {
// return attr.CheckPreStateValid(currentState);
// }
//}
var descriptions = new List<string>();
/// <summary>
/// 设备状态定义
/// 未初始化和异常状态无前置状态要求
/// 初始化操作前置状态必须是未初始化、关闭状态和异常状态
/// 打开前置必须是初始化和暂停
/// 关闭前置必须是打开和暂停和异常
/// 暂停前置必须是打开
/// </summary>
//public enum DeviceState
//{
// TBD = -1,
// [ColorSelect("Gray")]
// [FontColorSelect("Black")]
// [Description("未初始化")]
// DSUninit = 1,
// [ColorSelect("Gold")]
// [FontColorSelect("White")]
// [PreState(1 + 2 + 4 + 8 + 32)]
// [Description("初始化")]
// DSInit = 2,
// [ColorSelect("Lime")]
// [FontColorSelect("Black")]
// [PreState(2 + 4 + 16)]
// [Description("运行中")]
// DSOpen = 4,
// [ColorSelect("Gray")]
// [FontColorSelect("White")]
// [PreState(1 + 4 + 8 + 16 + 32)]
// [Description("关闭")]
// DSClose = 8,
// [ColorSelect("Gold")]
// [FontColorSelect("White")]
// [PreState(4 + 16)]
// [Description("暂停")]
// DSPause = 16,
// [ColorSelect("Red")]
// [FontColorSelect("White")]
// [Description("异常")]
// DSExcept = 32
//}
///// <summary>
///// 工序状态
///// </summary>
//public enum RunState
//{
// [ColorSelect("Gold")]
// [Description("空闲")]
// Idle = 1,
// [ColorSelect("Lime")]
// [Description("运行中")]
// Running = 2,
// [ColorSelect("Gray")]
// [Description("停止")]
// Stop = 3,
// [ColorSelect("Red")]
// [Description("宕机")]
// Down = 99,
//}
foreach (var value in Enum.GetValues(enumType))
{
var fieldInfo = enumType.GetField(value.ToString());
var attribute = fieldInfo.GetCustomAttribute<DescriptionAttribute>();
descriptions.Add(attribute?.Description ?? value.ToString());
}
return descriptions;
}
public static string GetEnumDescription1(Enum value)
{
var field = value.GetType().GetField(value.ToString());
var attribute = field.GetCustomAttributes(typeof(DescriptionAttribute), false)
.FirstOrDefault() as DescriptionAttribute;
return attribute?.Description ?? value.ToString();
}
[Flags]
public enum DeviceAttributeType
{

View File

@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DH.Commons.Helper
{
public static class SchemeHelper
{
private const string SchemesKey = "Schemes";
private const string CurrentSchemeKey = "CurrentScheme";
private const char Separator = '|';
/// <summary>
/// 初始化配置(首次运行时调用)
/// </summary>
public static void Initialize()
{
// 如果Schemes不存在创建空键
if (!SystemConfigHelper.KeyExists(SchemesKey))
{
SystemConfigHelper.SetValue(SchemesKey, "");
}
// 如果CurrentScheme不存在创建空键
if (!SystemConfigHelper.KeyExists(CurrentSchemeKey))
{
SystemConfigHelper.SetValue(CurrentSchemeKey, "");
}
}
/// <summary>
/// 获取所有方案(自动处理空值)
/// </summary>
public static List<string> GetAllSchemes()
{
var schemeString = SystemConfigHelper.GetValue(SchemesKey, "");
return string.IsNullOrEmpty(schemeString)
? new List<string>()
: new List<string>(schemeString.Split(Separator));
}
/// <summary>
/// 添加新方案(自动初始化处理)
/// </summary>
public static void AddScheme(string schemeName)
{
if (string.IsNullOrWhiteSpace(schemeName))
throw new ArgumentException("方案名称无效");
var schemes = GetAllSchemes();
if (schemes.Contains(schemeName))
throw new InvalidOperationException($"方案 {schemeName} 已存在");
schemes.Add(schemeName);
SaveSchemes(schemes);
}
/// <summary>
/// 设置当前方案(空值安全处理)
/// </summary>
public static void SetCurrentScheme(string schemeName)
{
var schemes = GetAllSchemes();
if (!schemes.Contains(schemeName))
throw new KeyNotFoundException($"方案 {schemeName} 不存在");
SystemConfigHelper.SetValue(CurrentSchemeKey, schemeName);
}
/// <summary>
/// 获取当前方案(默认值处理)
/// </summary>
public static string GetCurrentScheme()
{
var current = SystemConfigHelper.GetValue(CurrentSchemeKey, "");
return !string.IsNullOrEmpty(current) ? current : "默认方案";
}
private static void SaveSchemes(List<string> schemes)
{
var schemeString = schemes.Count > 0
? string.Join(Separator.ToString(), schemes)
: "";
SystemConfigHelper.SetValue(SchemesKey, schemeString);
}
/// <summary>
/// 删除指定方案(自动同步当前方案状态)
/// </summary>
/// <param name="schemeName">要删除的方案名称</param>
/// <exception cref="ArgumentException">当方案名称为空时抛出</exception>
/// <exception cref="KeyNotFoundException">当方案不存在时抛出</exception>
public static void DeleteScheme(string schemeName)
{
if (string.IsNullOrWhiteSpace(schemeName))
throw new ArgumentException("方案名称无效");
var schemes = GetAllSchemes();
if (!schemes.Contains(schemeName))
throw new KeyNotFoundException($"方案 {schemeName} 不存在");
// 删除前检查是否是当前方案
bool isCurrent = GetCurrentScheme() == schemeName;
// 执行删除操作
schemes.Remove(schemeName);
SaveSchemes(schemes);
}
}
}

View File

@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace DH.Commons.Helper
{
/// <summary>
/// 配置文件操作工具类(自动定位主程序配置)
/// </summary>
public static class SystemConfigHelper
{
private static Configuration _mainConfig;
private static readonly object _lock = new object();
/// <summary>
/// 获取主程序配置对象
/// </summary>
private static Configuration MainConfiguration
{
get
{
if (_mainConfig == null)
{
lock (_lock)
{
if (_mainConfig == null)
{
// 获取主程序路径
string exePath = Assembly.GetEntryAssembly().Location;
var configFile = exePath + ".config";
// 加载主程序配置
var fileMap = new ExeConfigurationFileMap
{
ExeConfigFilename = configFile
};
_mainConfig = ConfigurationManager.OpenMappedExeConfiguration(
fileMap,
ConfigurationUserLevel.None
);
}
}
}
return _mainConfig;
}
}
/// <summary>
/// 检查配置项是否存在
/// </summary>
public static bool KeyExists(string key)
{
return MainConfiguration.AppSettings.Settings[key] != null;
}
/// <summary>
/// 读取配置项(带类型自动转换)
/// </summary>
public static T GetValue<T>(string key, T defaultValue = default)
{
try
{
var setting = MainConfiguration.AppSettings.Settings[key];
if (setting == null) return defaultValue;
return (T)Convert.ChangeType(setting.Value, typeof(T));
}
catch
{
return defaultValue;
}
}
/// <summary>
/// 写入配置项(自动保存)
/// </summary>
public static void SetValue(string key, object value)
{
var settings = MainConfiguration.AppSettings.Settings;
var stringValue = value?.ToString() ?? string.Empty;
if (settings[key] == null)
{
settings.Add(key, stringValue);
}
else
{
settings[key].Value = stringValue;
}
SaveChanges();
}
/// <summary>
/// 删除指定配置项
/// </summary>
public static void RemoveKey(string key)
{
if (KeyExists(key))
{
MainConfiguration.AppSettings.Settings.Remove(key);
SaveChanges();
}
}
/// <summary>
/// 保存配置修改
/// </summary>
private static void SaveChanges()
{
MainConfiguration.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
}
}
}

View File

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DH.Commons.Base;
namespace DH.Commons.Models
{
public static class SystemModel
{
/// <summary>
/// 当前方案
/// </summary>
public static string CurrentScheme=string.Empty;
}
/// <summary>
/// 配置集合
/// </summary>
public static class ConfigModel
{
public static List<CameraBase> CameraBaseList = new List<CameraBase>();
public static List<PLCBase> PLCBaseList = new List<PLCBase>();
public static List<DetectionConfig> DetectionList = new List<DetectionConfig>();
}
}