From 409089e2caddb40d92c0344e85acd732e696e3c7 Mon Sep 17 00:00:00 2001
From: "xhm\\HP" <1173131411@qq.com>
Date: Tue, 1 Apr 2025 18:15:30 +0800
Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=97=A5=E5=BF=97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
DH.Commons/Base/CameraBase.cs | 3 +
DH.Commons/Base/DetectionConfig.cs | 19 +-
DH.Commons/Base/DeviceBase.cs | 389 ++++++++++++++++++++++++
DH.Commons/Base/PLCBase.cs | 1 +
DH.Commons/Base/VisionEngineBase.cs | 116 +------
DH.Commons/DH.Commons.csproj | 2 +-
DH.Commons/Exception/ExceptionHelper.cs | 64 ++++
DH.Commons/Helper/EnumHelper.cs | 71 +++++
DH.Commons/Helper/LoggerHelper.cs | 12 +
DH.Commons/Interface/Spec.cs | 109 +++++++
DH.Devices.Camera/Do3ThinkCamera.cs | 83 +++--
DH.Devices.PLC/XinJEPLCTcpNet.cs | 81 ++++-
DH.Devices.Vision/SimboDetection.cs | 9 +-
DH.Devices.Vision/SimboVisionDriver.cs | 370 +++++++++++++++++++++-
DHSoftware/DHSoftware.csproj | 40 ---
DHSoftware/MainWindow.Designer.cs | 158 +++++-----
DHSoftware/MainWindow.cs | 131 +++++---
DHSoftware/MainWindow.resx | 24 +-
DHSoftware/Views/FrmLog.Designer.cs | 148 +++++++++
DHSoftware/Views/FrmLog.cs | 236 ++++++++++++++
DHSoftware/Views/FrmLog.resx | 126 ++++++++
21 files changed, 1838 insertions(+), 354 deletions(-)
create mode 100644 DH.Commons/Base/DeviceBase.cs
create mode 100644 DH.Commons/Exception/ExceptionHelper.cs
create mode 100644 DH.Commons/Interface/Spec.cs
create mode 100644 DHSoftware/Views/FrmLog.Designer.cs
create mode 100644 DHSoftware/Views/FrmLog.cs
create mode 100644 DHSoftware/Views/FrmLog.resx
diff --git a/DH.Commons/Base/CameraBase.cs b/DH.Commons/Base/CameraBase.cs
index 07eee8a..2547a56 100644
--- a/DH.Commons/Base/CameraBase.cs
+++ b/DH.Commons/Base/CameraBase.cs
@@ -9,6 +9,9 @@ namespace DH.Commons.Base
{
public class CameraBase : NotifyProperty
{
+
+ // public LoggerHelper LoggerHelper { get; set; } = new LoggerHelper();
+
// 私有字段 + 带通知的属性(与DetectionLabel风格一致)
private bool _isEnabled = false;
private bool _isallPicEnabled = true;//默认全画幅
diff --git a/DH.Commons/Base/DetectionConfig.cs b/DH.Commons/Base/DetectionConfig.cs
index f5ae3e6..538c953 100644
--- a/DH.Commons/Base/DetectionConfig.cs
+++ b/DH.Commons/Base/DetectionConfig.cs
@@ -191,18 +191,14 @@ namespace DH.Commons.Base
}
public class DetectStationResult
{
-#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
- public string Pid { get; set; }
+ public string Pid { get; set; }
-
-#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
- public string TempPid { get; set; }
+ public string TempPid { get; set; }
///
/// 检测工位名称
///
-#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
public string DetectName { get; set; }
@@ -212,8 +208,11 @@ namespace DH.Commons.Base
///
public List DetectDetails = new List();
public List DetectionResultShapes = new List();
-
-
+ ///
+ /// 视觉测量结果集合
+ ///
+
+ public List realSpecs { get; set; } = new List();
///
/// 工位检测结果
///
@@ -249,9 +248,9 @@ namespace DH.Commons.Base
public int StationDetectElapsed { get; set; }
public static string NormalizeAndClean(string input)
{
-#pragma warning disable CS8603 // 可能返回 null 引用。
+
if (input == null) return null;
-#pragma warning restore CS8603 // 可能返回 null 引用。
+
// Step 1: 标准化字符编码为 Form C (规范组合)
string normalizedString = input.Normalize(NormalizationForm.FormC);
diff --git a/DH.Commons/Base/DeviceBase.cs b/DH.Commons/Base/DeviceBase.cs
new file mode 100644
index 0000000..c764613
--- /dev/null
+++ b/DH.Commons/Base/DeviceBase.cs
@@ -0,0 +1,389 @@
+
+using DH.Commons.Enums;
+using OpenCvSharp.Internal;
+using System;
+using System.ComponentModel;
+using System.IO;
+using System.Text.Json.Serialization;
+using System.Threading;
+using System.Threading.Tasks;
+using static DH.Commons.Enums.EnumHelper;
+using Timer = System.Threading.Timer;
+
+namespace DH.Commons.Base
+{
+ public abstract class DeviceBase : IDisposable
+ {
+ #region Event
+ [JsonIgnore]
+ [Browsable(false)]
+ public Action OnExceptionOccured { get; set; }
+ //public event Action OnLog;
+ public event Action OnLog;
+ // public event Action OnDeviceStateChanged;
+ public event PropertyChangedEventHandler PropertyChanged;
+ #endregion
+
+ #region field
+ int RetryTime = 3;
+ ///
+ /// 和设备暂停状态关联的信号量
+ ///
+ private readonly ManualResetEvent pauseHandle = new ManualResetEvent(true);
+ readonly Timer stateChangedTimer;
+ #endregion
+
+ #region Property
+ #region State
+ private EnumHelper.DeviceState _currentStateToBe = EnumHelper.DeviceState.DSUninit;
+ ///
+ /// 当前设备状态
+ ///
+ [JsonIgnore]
+ internal EnumHelper.DeviceState CurrentStateToBe
+ {
+ get
+ {
+ return _currentStateToBe;
+ }
+ set
+ {
+ if (value != _currentStateToBe)
+ {
+ var initialState = _currentStateToBe;
+ _currentStateToBe = value;
+
+ if (_currentStateToBe != EnumHelper.DeviceState.DSExcept)
+ {
+ // OnStateChanged(initialState);
+ }
+ else
+ {
+ stateChangedTimer.Change(Timeout.Infinite, Timeout.Infinite);
+ }
+ }
+ }
+ }
+
+ //private EnumHelper.DeviceState initialState = EnumHelper.DeviceState.DSUninit;
+ private EnumHelper.DeviceState _currentState = EnumHelper.DeviceState.DSUninit;
+ public EnumHelper.DeviceState CurrentState
+ {
+ get
+ {
+ return _currentState;
+ }
+ set
+ {
+ _currentState = value;
+
+ if (value != EnumHelper.DeviceState.TBD)
+ {
+ // OnDeviceStateChanged?.Invoke(this, _currentState);
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("CurrentState"));
+ }
+ //else
+ //{
+ // initialState = _currentState;
+ //}
+ }
+ }
+ #endregion
+
+ ///
+ /// 设备标识符 从数据库获取
+ ///
+ public string Id { get; set; }
+
+ ///
+ /// 设备名称 从数据库获取
+ ///
+ public string Name { get; set; }
+
+ //private IInitialConfig initialConfig = null;
+ /////
+ ///// 设备初始化配置 从数据库获取
+ /////
+ //public virtual IInitialConfig InitialConfig
+ //{
+ // get => initialConfig;
+ // set
+ // {
+ // initialConfig = value;
+ // Id = initialConfig.Id;
+ // Name = initialConfig.Name;
+
+ // LoggerHelper.LogPath = initialConfig.LogPath;
+ // LoggerHelper.LogPrefix = initialConfig.Name;
+ // }
+ //}
+ #endregion
+
+ #region 构造函数
+ public DeviceBase()
+ {
+ RegisterFileWriterException();
+ // stateChangedTimer = new Timer(new TimerCallback(CheckDeviceOpTimeOut), null, Timeout.Infinite, Timeout.Infinite);
+ }
+ #endregion
+
+ #region 设备抽象方法
+ protected virtual void Init()
+ {
+ LogAsync(DateTime.Now, LogLevel.Information, $"{Name}初始化完成");
+ }
+
+
+
+ protected virtual void Start()
+ {
+ LogAsync(DateTime.Now, LogLevel.Information, $"{Name}启动");
+ }
+
+ protected virtual void Stop()
+ {
+ LogAsync(DateTime.Now, LogLevel.Information, $"{Name}停止");
+ }
+
+ //public abstract void AttachToProcess(IProcess process);
+ #endregion
+
+ ///
+ /// 常用操作封装方法
+ ///
+ ///
+ ///
+ //public virtual ResponseMessage RunWrap(IOperationConfig opConfig)
+ //{
+ // ResponseMessage msg = new ResponseMessage();
+ // msg.Message = "设备基类默认操作";
+ // return msg;
+ //}
+
+ #region 状态切换
+ //[DeviceExceptionAspect]
+ //public void StateChange(EnumHelper.DeviceState stateToBe)
+ //{
+ // if (CurrentState == stateToBe)
+ // {
+ // return;
+ // }
+
+ // if (!stateToBe.CheckPreStateValid((int)CurrentStateToBe))
+ // {
+ // string currentStateStr = CurrentStateToBe.GetEnumDescription();
+ // string stateToBeStr = stateToBe.GetEnumDescription();
+ // throw new ProcessException($"{InitialConfig.Name}设备的当前状态为{currentStateStr},无法切换至{stateToBeStr}");
+ // }
+
+ // CurrentState = EnumHelper.DeviceState.TBD;
+ // CurrentStateToBe = stateToBe;
+ //}
+
+ //[DeviceExceptionAspect]
+ //private void OnStateChanged(EnumHelper.DeviceState initialState)
+ //{
+ // try
+ // {
+ // if (CurrentStateToBe != EnumHelper.DeviceState.DSExcept)
+ // {
+ // }
+ // else
+ // {
+ // if (CurrentState == EnumHelper.DeviceState.DSExcept)
+ // {
+ // return;
+ // }
+ // else
+ // {
+ // throw new ProcessException($"{InitialConfig.Name}设备操作超时");
+ // }
+ // }
+
+ // if (RetryTime >= 0)
+ // {
+ // if (initialState == CurrentStateToBe)
+ // {
+ // CurrentState = CurrentStateToBe;
+ // return;
+ // }
+
+ // #region 状态切换操作
+ // switch (CurrentStateToBe)
+ // {
+ // case EnumHelper.DeviceState.DSInit:
+ // if (initialState == EnumHelper.DeviceState.DSOpen)
+ // {
+ // return;
+ // }
+ // else
+ // {
+ // Init();
+ // }
+ // break;
+ // case EnumHelper.DeviceState.DSOpen:
+ // if (initialState == EnumHelper.DeviceState.DSInit)
+ // {
+ // Start();
+ // }
+ // else if (initialState == EnumHelper.DeviceState.DSPause)
+ // {
+ // Resume();
+ // pauseHandle.Set();
+ // }
+ // break;
+ // case EnumHelper.DeviceState.DSPause:
+ // pauseHandle.Reset();
+ // Pause();
+ // break;
+ // case EnumHelper.DeviceState.DSClose:
+ // if (initialState != DeviceState.DSUninit)
+ // {
+ // Stop();
+ // }
+ // break;
+ // default:
+ // break;
+ // }
+
+ // RetryTime = 3;
+ // CurrentState = CurrentStateToBe;
+ // #endregion
+ // }
+
+ // stateChangedTimer.Change(Timeout.Infinite, Timeout.Infinite);
+ // }
+ // catch (Exception ex)
+ // {
+ // RetryTime--;
+ // if (RetryTime > 0)
+ // {
+ // OnStateChanged(initialState);
+ // }
+ // else
+ // {
+ // if (CurrentState != EnumHelper.DeviceState.DSExcept)
+ // {
+ // RetryTime = 3;
+ // throw new ProcessException($"设备{InitialConfig.Name}的{CurrentStateToBe.GetEnumDescription()}操作重复3次失败", ex, ExceptionLevel.Warning);
+ // }
+ // }
+ // }
+ //}
+
+ //private void CheckDeviceOpTimeOut(object state)
+ //{
+ // stateChangedTimer?.Change(Timeout.Infinite, Timeout.Infinite);
+
+ // if (CurrentState != EnumHelper.DeviceState.DSExcept)
+ // {
+ // StateChange(EnumHelper.DeviceState.DSExcept);
+ // }
+ //}
+ #endregion
+
+ #region 日志处理
+ private void RegisterFileWriterException()
+ {
+ LoggerHelper.OnLogExceptionRaised -= LoggerHelper_OnLogExceptionRaised;
+ // CSVHelper.OnCSVExceptionRaised -= LoggerHelper_OnLogExceptionRaised;
+
+ LoggerHelper.OnLogExceptionRaised += LoggerHelper_OnLogExceptionRaised;
+ // CSVHelper.OnCSVExceptionRaised += LoggerHelper_OnLogExceptionRaised;
+ }
+ // public CSVHelper CSVHelper { get; set; } = new CSVHelper();
+
+ public LoggerHelper LoggerHelper { get; set; } = new LoggerHelper();
+
+ public virtual void LogAsync(LogMsg msg)
+ {
+ msg.MsgSource = Name;
+ msg.ThreadId = Thread.CurrentThread.ManagedThreadId;
+
+ //OnLog?.BeginInvoke(msg, null, null);
+ OnLog?.Invoke(msg);
+
+ //if (InitialConfig.IsEnableLog)
+ //{
+ // LoggerHelper.LogAsync(msg);
+ //}
+ }
+
+ public virtual void LogAsync(DateTime dt, LogLevel logLevel, string msg)
+ {
+ LogAsync(new LogMsg(dt, logLevel, msg));
+ }
+ private void LoggerHelper_OnLogExceptionRaised(DateTime dt, string msg)
+ {
+ OnLog?.Invoke(new LogMsg(dt, LogLevel.Error, msg));
+ }
+ ///
+ /// CSV异步数据输出
+ ///
+ /// CSV输出文件的文件全路径
+ /// CSV输出数据
+ /// CSV文件表头
+ public virtual void CSVRecordAsync(string csvFile, string csvData, string csvHead = "")
+ {
+ // CSVHelper.CSVOutputAsync(csvFile, csvData, csvHead);
+ }
+ #endregion
+
+ #region 报警记录
+ //object _alarmLock = new object();
+ //protected virtual async void SaveAlarmCSVAsync(DateTime now, string deviceName, IWarningSet ws)
+ //{
+ // await Task.Run(() =>
+ // {
+ // LogAsync(now, LogLevel.Warning, $"{ws.WarningCode}-{ws.WarningDescription} {(ws.CurrentStatus ? "发生" : "取消")}");
+
+ // if (string.IsNullOrWhiteSpace(this.InitialConfig.LogPath) || !InitialConfig.IsEnableCSV)
+ // return;
+
+ // string path = Path.Combine(InitialConfig.LogPath, $"Alarm_{Name}_{now.ToString("yyyyMMdd")}.csv");
+ // string head = "Time,Source,AlarmCode,AlarmDescription,AlarmStatus";
+ // string data = $"{now.ToString("HH:mm:ss.fff")},{deviceName},{ws.WarningCode},{ws.WarningDescription},{(ws.CurrentStatus ? "报警发生" : "报警取消")}";
+ // CSVRecordAsync(path, data, head);
+ // });
+ //}
+ #endregion
+
+ #region IDisposable Support
+ private bool disposedValue = false; // 要检测冗余调用
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposedValue)
+ {
+ if (disposing)
+ {
+ //释放托管状态(托管对象)。
+ stateChangedTimer?.Dispose();
+ pauseHandle?.Dispose();
+ }
+
+ // TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。
+ // TODO: 将大型字段设置为 null。
+
+ disposedValue = true;
+ }
+ }
+
+ // TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。
+ // ~DeviceBase()
+ // {
+ // // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
+ // Dispose(false);
+ // }
+
+ // 添加此代码以正确实现可处置模式。
+ public void Dispose()
+ {
+ // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
+ Dispose(true);
+ // TODO: 如果在以上内容中替代了终结器,则取消注释以下行。
+ // GC.SuppressFinalize(this);
+ }
+ #endregion
+ }
+}
diff --git a/DH.Commons/Base/PLCBase.cs b/DH.Commons/Base/PLCBase.cs
index dbe97a5..d6e890f 100644
--- a/DH.Commons/Base/PLCBase.cs
+++ b/DH.Commons/Base/PLCBase.cs
@@ -8,6 +8,7 @@ namespace DH.Commons.Base
{
public class PLCBase : NotifyProperty
{
+
// 私有字段
private bool _enable;
private bool _connected;
diff --git a/DH.Commons/Base/VisionEngineBase.cs b/DH.Commons/Base/VisionEngineBase.cs
index 2c8bb21..1acbebd 100644
--- a/DH.Commons/Base/VisionEngineBase.cs
+++ b/DH.Commons/Base/VisionEngineBase.cs
@@ -18,7 +18,7 @@ namespace DH.Commons.Base
/// Object Detection 目标检测:寻找图像中的物体并进行定位;
/// Instance Segmentation 实例分割:定位图中每个物体,并进行像素级标注,区分不同个体;
///
- public abstract class VisionEngineBase
+ public abstract class VisionEngineBase : DeviceBase
{
public List DetectionConfigs = new List();
#region event
@@ -66,118 +66,8 @@ namespace DH.Commons.Base
}
}
}
- public class CamModuleXY
- {
- [Category("图片行")]
- [DisplayName("行")]
- [Description("行")]
- // [TypeConverter(typeof(DeviceIdSelectorConverter))]
- //[TypeConverter(typeof(CollectionCountConvert))]
- public int PicRows { get; set; } = 1;
-
- [Category("图片列")]
- [DisplayName("列")]
- [Description("列")]
- // [TypeConverter(typeof(DeviceIdSelectorConverter))]
- //[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))]
- // //[TypeConverter(typeof(CollectionCountConvert))]
- // public string CameraSourceId { get; set; } = "";
-
-
- // //public string GetDisplayText()
- // //{
- // // using (var scope = GlobalVar.Container.BeginLifetimeScope())
- // // {
- // // List deviceList = scope.Resolve>();
- // // 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), typeof(UITypeEditor))]
- public List DetectionConfigs { get; set; } = new List();
-
- [Category("深度学习检测配置")]
- [DisplayName("标签分类")]
- [Description("标签分类,A_NG,B_TBD...")]
- // [TypeConverter(typeof(CollectionCountConvert))]
- // [Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))]
- public List RecongnitionLabelCategoryList { get; set; } = new List();
-
- [Category("深度学习检测配置")]
- [DisplayName("检测标签定义集合")]
- [Description("定义检测标签的集合,例如:Seg/Detection模式:断裂、油污、划伤...;Class模式:ok、ng、上面、下面、套环、正常...")]
- // [TypeConverter(typeof(CollectionCountConvert))]
- // [Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))]
- public List RecongnitionLabelList { get; set; } = new List();
-
- [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), typeof(UITypeEditor))]
- // public List DetectionGPUList { get; set; } = new List();
-
- // [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";
-
- }
+
+
}
diff --git a/DH.Commons/DH.Commons.csproj b/DH.Commons/DH.Commons.csproj
index 1cbfe74..41a3dcc 100644
--- a/DH.Commons/DH.Commons.csproj
+++ b/DH.Commons/DH.Commons.csproj
@@ -11,7 +11,7 @@
AnyCPU;x64
-
+
diff --git a/DH.Commons/Exception/ExceptionHelper.cs b/DH.Commons/Exception/ExceptionHelper.cs
new file mode 100644
index 0000000..9b49522
--- /dev/null
+++ b/DH.Commons/Exception/ExceptionHelper.cs
@@ -0,0 +1,64 @@
+using System;
+using static DH.Commons.Enums.EnumHelper;
+
+
+namespace DH.Commons.Helper
+{
+ public enum ExceptionLevel
+ {
+ Info = 0,
+ Warning = 1,
+ Fatal = 2,
+ }
+
+ //public delegate void OnProcessExceptionRaisedDelegate(DateTime dt, ProcessException ex);
+ //[Serializable]
+ public class ProcessException : Exception
+ {
+ public ExceptionLevel Level { get; set; } = ExceptionLevel.Warning;
+
+ public ProcessException()
+ {
+ }
+
+ public ProcessException(Exception ex, ExceptionLevel lvl = ExceptionLevel.Warning) : base(ex.Message, ex)
+ {
+ Level = lvl;
+ ExceptionNotice();
+ }
+
+ public ProcessException(string error, Exception ex = null, ExceptionLevel lvl = ExceptionLevel.Warning) : base(error, ex)
+ {
+ Level = lvl;
+ ExceptionNotice();
+ }
+
+ public void ExceptionNotice()
+ {
+ //OnProcessExceptionRaised?.Invoke(DateTime.Now, this);
+ }
+ }
+
+ public static class ExceptionHelper
+ {
+ public static LogLevel LogLevel = LogLevel.Information;
+ public static string GetExceptionMessage(this Exception ex)
+ {
+ string msg = "异常信息:" + ex.Message;
+ if (ex.InnerException != null)
+ {
+ msg += ";\t内部异常信息:" + ex.InnerException.GetExceptionMessage();
+ }
+
+ if (LogLevel <= LogLevel.Assist)
+ {
+ msg += (";\r\n\t\tStackTrace:" + ex.StackTrace);
+ }
+ return msg;
+ }
+ }
+
+ public class AuthorityException : ProcessException
+ {
+ }
+}
diff --git a/DH.Commons/Helper/EnumHelper.cs b/DH.Commons/Helper/EnumHelper.cs
index 3b0d2a6..1ff12c4 100644
--- a/DH.Commons/Helper/EnumHelper.cs
+++ b/DH.Commons/Helper/EnumHelper.cs
@@ -120,6 +120,40 @@ namespace DH.Commons.Enums
.FirstOrDefault() as DescriptionAttribute;
return attribute?.Description ?? value.ToString();
}
+
+ public static System.Drawing.Color GetEnumSelectedColor(this Enum enumObj)
+ {
+ Type t = enumObj.GetType();
+ FieldInfo f = t.GetField(enumObj.ToString());
+
+ ColorSelectAttribute attr = f.GetCustomAttribute();
+ 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();
+ if (attr != null)
+ {
+ return System.Drawing.Color.FromName(attr.SelectedColor);
+ }
+ else
+ {
+ return System.Drawing.Color.Transparent;
+ }
+ }
+
+
[Flags]
public enum DeviceAttributeType
{
@@ -303,7 +337,44 @@ namespace DH.Commons.Enums
// NG = -1,
// IGNORE = -999,
//}
+ 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
+ }
public enum PriorityDirection
{
X,
diff --git a/DH.Commons/Helper/LoggerHelper.cs b/DH.Commons/Helper/LoggerHelper.cs
index eba4c68..d8161c6 100644
--- a/DH.Commons/Helper/LoggerHelper.cs
+++ b/DH.Commons/Helper/LoggerHelper.cs
@@ -8,6 +8,18 @@ using static DH.Commons.Enums.EnumHelper;
namespace DH.Commons.Enums
{
+ public interface ILogOutput
+ {
+ event Action OnLogMsgOutput;
+ void LogDisplay(LogMsg msg);
+ }
+ public interface ILogger
+ {
+ event Action OnLog;
+ LoggerHelper LoggerHelper { get; set; }
+ //void LogAsync(DateTime dt, LogLevel loglevel, string msg);
+ void LogAsync(LogMsg msg);
+ }
public class LoggerHelper
{
public event Action OnLogExceptionRaised;
diff --git a/DH.Commons/Interface/Spec.cs b/DH.Commons/Interface/Spec.cs
new file mode 100644
index 0000000..06fe034
--- /dev/null
+++ b/DH.Commons/Interface/Spec.cs
@@ -0,0 +1,109 @@
+
+using System;
+using System.ComponentModel;
+using System.Drawing.Design;
+
+namespace DH.Commons.Enums
+{
+
+ ///
+ /// 标准配置
+ ///
+ public class Spec
+ {
+ [Category("通用配置")]
+ [Description("标准代码")]
+ public virtual string Code { get; set; }
+
+ [Category("通用配置")]
+ [Description("启用状态,true:启用;false:禁用")]
+ [DisplayName("启用状态")]
+ public bool IsEnabled { get; set; }
+
+ [Category("标准配置")]
+ [Description("标准值")]
+ [DisplayName("标准值")]
+ public double StandardValue { get; set; }
+
+ [Category("标准配置")]
+ [Description("正公差")]
+ [DisplayName("正公差")]
+ public double Tolrenance_Positive { get; set; }
+
+ [Category("标准配置")]
+ [Description("负公差")]
+ [DisplayName("负公差")]
+ public double Tolrenance_Negative { get; set; }
+
+ protected double? actualValue = null;
+ [Browsable(false)]
+
+ public virtual double? ActualValue
+ {
+ get
+ {
+ return actualValue;
+ }
+ set
+ {
+ //if (actualValue != value && value != null)
+ if (value != null)
+ {
+ if (value.Value >= (StandardValue - Tolrenance_Negative) && value.Value <= (StandardValue + Tolrenance_Positive))
+ {
+ MeasureResult = true;
+ }
+ else
+ {
+ MeasureResult = false;
+ }
+ }
+
+ actualValue = value;
+ }
+ }
+
+ [Browsable(false)]
+
+ public bool? MeasureResult { get; set; } = null;
+
+
+ public Spec Copy()
+ {
+ Spec spec = new Spec();
+
+ spec.Code = this.Code;
+ spec.IsEnabled = this.IsEnabled;
+ spec.StandardValue = this.StandardValue;
+ spec.Tolrenance_Positive = this.Tolrenance_Positive;
+ spec.Tolrenance_Negative = this.Tolrenance_Negative;
+
+ return spec;
+ }
+ }
+
+
+
+ public class IndexedSpec : Spec
+ {
+ [Category("数据源配置")]
+ [Description("数据源输出索引")]
+ [DisplayName("数据源输出索引")]
+ public int OutputIndex { get; set; }
+
+ public new IndexedSpec Copy()
+ {
+ IndexedSpec spec = new IndexedSpec();
+
+ spec.Code = this.Code;
+ spec.IsEnabled = this.IsEnabled;
+ spec.StandardValue = this.StandardValue;
+ spec.Tolrenance_Positive = this.Tolrenance_Positive;
+ spec.Tolrenance_Negative = this.Tolrenance_Negative;
+
+ spec.OutputIndex = this.OutputIndex;
+
+ return spec;
+ }
+ }
+}
diff --git a/DH.Devices.Camera/Do3ThinkCamera.cs b/DH.Devices.Camera/Do3ThinkCamera.cs
index 90d2f1c..b45f69b 100644
--- a/DH.Devices.Camera/Do3ThinkCamera.cs
+++ b/DH.Devices.Camera/Do3ThinkCamera.cs
@@ -2,16 +2,17 @@
using System.Reflection.Metadata;
using System.Xml.Linq;
using DH.Commons.Base;
+using DH.Commons.Enums;
using DVPCameraType;
using OpenCvSharp;
using static System.Net.Mime.MediaTypeNames;
-
+using LogLevel = DH.Commons.Enums.EnumHelper.LogLevel;
namespace DH.Devices.Camera
{
- public class Do3ThinkCamera : CameraBase
+ public class Do3ThinkCamera : CameraBase, ILogger
{
private dvpCameraInfo stDevInfo = new dvpCameraInfo();
@@ -24,9 +25,15 @@ namespace DH.Devices.Camera
public dvpStreamFormat dvpStreamFormat = dvpStreamFormat.S_RGB24;
public int m_CamCount = 0;
public Double m_dfDisplayCount = 0;
+
+ public LoggerHelper LoggerHelper { get; set; } = new LoggerHelper();
+ public event Action OnLog;
+
public Do3ThinkCamera()
{
-
+ LoggerHelper.LogPath = "D://";
+ LoggerHelper.LogPrefix = CameraName;
+
}
@@ -130,41 +137,43 @@ namespace DH.Devices.Camera
throw new Exception($"Start grabbing failed:{nRet:x8}");
}
//// 曝光
- //if (IIConfig.DefaultExposure != 0)
- //{
- // SetExposure(IIConfig.DefaultExposure);
- //}
+ if (Exposure != 0)
+ {
+ SetExposure(Exposure);
+ }
//// 增益
- //if (IIConfig.Gain >= 0)
- //{
- // SetGain(IIConfig.Gain);
- //}
- //SetPictureRoi(IIConfig.VelocityPara.A_Pic_X, IIConfig.VelocityPara.A_Pic_Y, IIConfig.VelocityPara.Width, IIConfig.VelocityPara.Hight);
+ if (Gain >= 0)
+ {
+ SetGain(Gain);
+ }
+ //全画幅
+ if(!IsAllPicEnabled)
+ SetPictureRoi((int)ROIX, (int)ROIY, (int)ROIW, (int)ROIH);
//// 设置 触发延迟
- //if (IIConfig.TriggerDelay > 0)
- //{
- // nRet = DVPCamera.dvpSetTriggerDelay(m_handle, IIConfig.TriggerDelay);
- // if (nRet != dvpStatus.DVP_STATUS_OK)
- // {
- // throw new Exception("Set TriggerDelay failed!");
- // }
- //}
+ if (TriggerDelay > 0)
+ {
+ nRet = DVPCamera.dvpSetTriggerDelay(m_handle, TriggerDelay);
+ if (nRet != dvpStatus.DVP_STATUS_OK)
+ {
+ throw new Exception("Set TriggerDelay failed!");
+ }
+ }
//// 信号消抖
- //if (IIConfig.LineDebouncerTime > 0)
- //{
- // nRet = DVPCamera.dvpSetTriggerJitterFilter(m_handle, IIConfig.LineDebouncerTime);
- // if (nRet != dvpStatus.DVP_STATUS_OK)
- // {
- // throw new Exception($"LineDebouncerTime set failed:{nRet}");
- // }
- //}
+ if (LineDebouncerTime > 0)
+ {
+ nRet = DVPCamera.dvpSetTriggerJitterFilter(m_handle, LineDebouncerTime);
+ if (nRet != dvpStatus.DVP_STATUS_OK)
+ {
+ throw new Exception($"LineDebouncerTime set failed:{nRet}");
+ }
+ }
//IIConfig.PropertyChanged -= IIConfig_PropertyChanged;
//IIConfig.PropertyChanged += IIConfig_PropertyChanged;
-
+
}
return true;
}
@@ -411,6 +420,22 @@ namespace DH.Devices.Camera
}
+ public void LogAsync(LogMsg msg)
+ {
+ msg.MsgSource = CameraName;
+ msg.ThreadId = Thread.CurrentThread.ManagedThreadId;
+ //OnLog?.BeginInvoke(msg, null, null);
+ OnLog?.Invoke(msg);
+
+ //if (InitialConfig.IsEnableLog)
+ {
+ LoggerHelper.LogAsync(msg);
+ }
+ }
+ public void LogAsync(DateTime dt, LogLevel logLevel, string msg)
+ {
+ LogAsync(new LogMsg(dt, logLevel, msg));
+ }
}
}
diff --git a/DH.Devices.PLC/XinJEPLCTcpNet.cs b/DH.Devices.PLC/XinJEPLCTcpNet.cs
index 1444366..6167f82 100644
--- a/DH.Devices.PLC/XinJEPLCTcpNet.cs
+++ b/DH.Devices.PLC/XinJEPLCTcpNet.cs
@@ -16,10 +16,11 @@ using HslCommunication;
using HslCommunication.Enthernet;
using HslCommunication.Profinet.XINJE;
using OpenCvSharp;
+using LogLevel = DH.Commons.Enums.EnumHelper.LogLevel;
namespace DH.Devices.PLC
{
- public class XinJEPLCTcpNet : PLCBase
+ public class XinJEPLCTcpNet : PLCBase, ILogger
{
private static XinJEPLCTcpNet _instance;
public static XinJEPLCTcpNet Instance
@@ -31,13 +32,18 @@ namespace DH.Devices.PLC
return _instance;
}
}
-
+
+ public LoggerHelper LoggerHelper { get; set; } = new LoggerHelper();
+ public event Action OnLog;
private XinJETcpNet TcpNet = new XinJETcpNet();
public override bool PLCConnect()
{
try
{
+ LoggerHelper.LogPath = "D://";
+ LoggerHelper.LogPrefix = "PLC";
+
TcpNet.IpAddress = IP;
TcpNet.Port = Port;
TcpNet.ConnectTimeOut = 5000;
@@ -63,11 +69,13 @@ namespace DH.Devices.PLC
Connected = true;
//初始化流程
InitProcess();
+ LogAsync(DateTime.Now, LogLevel.Information, $"{IP}:{Port}PLC连接成功");
return true;
}
else
{
Connected = false;
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC初始化失败");
throw new Exception($"{IP}:{Port}PLC连接失败!");
}
@@ -76,6 +84,7 @@ namespace DH.Devices.PLC
catch(Exception ex)
{
Connected = false;
+ LogAsync(DateTime.Now, LogLevel.Error, $"{IP}:{Port}PLC连接失败!失败原因:{ex.ToString()}");
throw new Exception($"{IP}:{Port}PLC连接失败!失败原因:{ex.ToString()}");
}
@@ -95,18 +104,20 @@ namespace DH.Devices.PLC
}
else
{
-
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取int16失败,地址{address}");
throw new Exception($"PLC操作读取int16失败,地址{address}");
}
}
else
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC未连接,地址{address}");
throw new Exception($"PLC未连接,地址{address}");
}
}
catch (Exception ex)
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取int16失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作读取int16失败,地址{address},失败原因:{ex.ToString()}");
}
}
@@ -125,17 +136,20 @@ namespace DH.Devices.PLC
}
else
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取int32失败,地址{address}");
throw new Exception($"PLC操作读取int32失败,地址{address}");
}
}
else
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC未连接,地址{address}");
throw new Exception($"PLC未连接,地址{address}");
}
}
catch (Exception ex)
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取int32失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作读取int32失败,地址{address},失败原因:{ex.ToString()}");
}
}
@@ -155,6 +169,7 @@ namespace DH.Devices.PLC
}
else
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取uint16失败,地址{address}");
throw new Exception($"PLC操作读取uint16失败,地址{address}");
@@ -162,12 +177,14 @@ namespace DH.Devices.PLC
}
else
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC未连接,地址{address}");
throw new Exception($"PLC未连接,地址{address}");
}
}
catch (Exception ex)
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取uint16失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作读取uint16失败,地址{address},失败原因:{ex.ToString()}");
}
}
@@ -186,17 +203,20 @@ namespace DH.Devices.PLC
}
else
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作uint32失败,地址{address}");
throw new Exception($"PLC操作uint32失败,地址{address}");
}
}
else
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC未连接,地址{address}");
throw new Exception($"PLC未连接,地址{address}");
}
}
catch (Exception ex)
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取uint32失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作读取uint32失败,地址{address},失败原因:{ex.ToString()}");
}
}
@@ -216,16 +236,19 @@ namespace DH.Devices.PLC
}
else
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取float失败,地址{address}");
throw new Exception($"PLC操作读取float失败,地址{address}");
}
}
else
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC未连接,地址{address}");
throw new Exception($"PLC未连接,地址{address}");
}
}
catch (Exception ex)
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取float失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作读取float失败,地址{address},失败原因:{ex.ToString()}");
}
}
@@ -243,16 +266,19 @@ namespace DH.Devices.PLC
}
else
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取bool失败,地址{address}");
throw new Exception($"PLC操作读取bool失败,地址{address}");
}
}
else
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC未连接,地址{address}");
throw new Exception($"PLC未连接,地址{address}");
}
}
catch (Exception ex)
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取bool失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作读取bool失败,地址{address},失败原因:{ex.ToString()}");
}
}
@@ -291,6 +317,7 @@ namespace DH.Devices.PLC
repeatTime--;
if (repeatTime <= 0)
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作写入uint32失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作写入uint32失败,地址{address},失败原因:{ex.ToString()}");
}
}
@@ -298,6 +325,8 @@ namespace DH.Devices.PLC
}
else
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC未连接,地址{address}");
+
throw new Exception($"PLC未连接,地址{address}");
}
return false;
@@ -336,6 +365,7 @@ namespace DH.Devices.PLC
repeatTime--;
if (repeatTime <= 0)
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作写入uint16失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作写入uint16失败,地址{address},失败原因:{ex.ToString()}");
}
}
@@ -343,6 +373,8 @@ namespace DH.Devices.PLC
}
else
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC未连接,地址{address}");
+
throw new Exception($"PLC未连接,地址{address}");
}
return false;
@@ -383,6 +415,7 @@ namespace DH.Devices.PLC
repeatTime--;
if (repeatTime <= 0)
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作写入int32失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作写入int32失败,地址{address},失败原因:{ex.ToString()}");
}
}
@@ -476,6 +509,7 @@ namespace DH.Devices.PLC
repeatTime--;
if (repeatTime <= 0)
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作写入float失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作写入float失败,地址{address},失败原因:{ex.ToString()}");
}
}
@@ -483,6 +517,8 @@ namespace DH.Devices.PLC
}
else
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC未连接,地址{address}");
+
throw new Exception($"PLC未连接,地址{address}");
}
return false;
@@ -519,6 +555,7 @@ namespace DH.Devices.PLC
repeatTime--;
if (repeatTime <= 0)
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作写入bool失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作写入bool失败,地址{address},失败原因:{ex.ToString()}");
}
}
@@ -528,6 +565,7 @@ namespace DH.Devices.PLC
}
else
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"PLC未连接,地址{address}");
throw new Exception($"PLC未连接,地址{address}");
}
@@ -537,12 +575,14 @@ namespace DH.Devices.PLC
public override bool PLCDisConnect()
{
+
if (Connected)
{
var res = TcpNet.ConnectClose();
if (res.IsSuccess)
{
+ LogAsync(DateTime.Now, LogLevel.Information, $"{IP}:{Port}停止");
Connected = false;
return true;
}
@@ -575,6 +615,7 @@ namespace DH.Devices.PLC
/// int,int 轴号 捕获位置
///
public event Action OnNewPieces;
+
public void NewPieces(int axisIndex, uint pieceNumber)
{
@@ -635,7 +676,7 @@ namespace DH.Devices.PLC
//LogAsync(DateTime.Now, LogLevel.Information, $"转盘{0}产品入列 {piecesCountDic[0]} size:{sum}");
if (tmpPieceNumber != piecesCount + 1)
{
- //LogAsync(DateTime.Now, LogLevel.Information, $"入列触发丢失\t{tmpPieceNumber}");
+ LogAsync(DateTime.Now, LogLevel.Information, $"入列触发丢失\t{tmpPieceNumber}");
// Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")}\t板卡{station}产品入列触发丢失,{piecesCountDic[station]}\t{tmpPieceNumber}");
}
@@ -660,20 +701,25 @@ namespace DH.Devices.PLC
{
//启用心跳
OpenHeartbeat(true);
+ // LogAsync(DateTime.Now, LogLevel.Information, $"启用心跳");
//状态复位
StatusReset();
+ //LogAsync(DateTime.Now, LogLevel.Information, $"状态复位");
//关闭定位
VisionPos(false);
-
+ // LogAsync(DateTime.Now, LogLevel.Information, $"关闭定位");
//写入流程加载点位配置
InitProcessAction();
-
+ //LogAsync(DateTime.Now, LogLevel.Information, $"写入流程加载点位配置");
//计数清零
CountToZero();
+ // LogAsync(DateTime.Now, LogLevel.Information, $"计数清零");
//停止转盘
TurnStart(false);
+ //LogAsync(DateTime.Now, LogLevel.Information, $"停止转盘");
//转盘使能
TurnEnable(true);
+ LogAsync(DateTime.Now, LogLevel.Information, $"启用心跳-状态复位-关闭定位-写入流程加载点位配置-计数清零-停止转盘-转盘使能");
//开启入料监听
MonitorPieces();
@@ -683,12 +729,16 @@ namespace DH.Devices.PLC
{
//状态复位
StatusReset();
+ // LogAsync(DateTime.Now, LogLevel.Information, $"状态复位");
//关闭定位
VisionPos(false);
+ // LogAsync(DateTime.Now, LogLevel.Information, $"关闭定位");
//写入流程启动点位配置
StartProcessAction();
+ // LogAsync(DateTime.Now, LogLevel.Information, $"写入流程加载点位配置");
//计数清零
CountToZero();
+ LogAsync(DateTime.Now, LogLevel.Information, $"状态复位-关闭定位-写入流程加载点位配置-计数清零");
//转盘启动
TurnStart(true);
}
@@ -702,6 +752,7 @@ namespace DH.Devices.PLC
TurnEnable(false);
OpenHeartbeat(false);
PLCDisConnect();
+ // LogAsync(DateTime.Now, LogLevel.Information, $"PLC断开连接");
}
public void InitProcessAction() =>
ProcessAction(ConfigModel.GlobalList?.FirstOrDefault()?.InitProcessList?.ToList() ?? new List());
@@ -974,5 +1025,23 @@ namespace DH.Devices.PLC
WriteUInt16($"D{currentRegister}", value);
}
+
+ public void LogAsync(LogMsg msg)
+ {
+ msg.MsgSource = "PLC";
+ msg.ThreadId = Thread.CurrentThread.ManagedThreadId;
+
+ //OnLog?.BeginInvoke(msg, null, null);
+ OnLog?.Invoke(msg);
+
+ //if (InitialConfig.IsEnableLog)
+ {
+ LoggerHelper.LogAsync(msg);
+ }
+ }
+ public void LogAsync(DateTime dt, LogLevel logLevel, string msg)
+ {
+ LogAsync(new LogMsg(dt, logLevel, msg));
+ }
}
}
diff --git a/DH.Devices.Vision/SimboDetection.cs b/DH.Devices.Vision/SimboDetection.cs
index 03918f0..1c3a130 100644
--- a/DH.Devices.Vision/SimboDetection.cs
+++ b/DH.Devices.Vision/SimboDetection.cs
@@ -104,18 +104,18 @@ namespace DH.Devices.Vision
// json = "{\"FastDetResult\":[{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.654843,\"rect\":[175,99,110,594]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.654589,\"rect\":[2608,19,104,661]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.654285,\"rect\":[1275,19,104,662]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.620762,\"rect\":[1510,95,107,600]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.617812,\"rect\":[2844,93,106,602]}]}";
//
Console.WriteLine("检测结果JSON:" + json);
-#pragma warning disable CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
+
HYoloResult detResult = JsonConvert.DeserializeObject(json);
-#pragma warning restore CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
+
if (detResult == null)
{
return;
}
int iNum = detResult.HYolo.Count;
-#pragma warning disable CS0219 // 变量已被赋值,但从未使用过它的值
+
int IokNum = 0;
-#pragma warning restore CS0219 // 变量已被赋值,但从未使用过它的值
+
for (int ix = 0; ix < iNum; ix++)
{
var det = detResult.HYolo[ix];
@@ -145,7 +145,6 @@ namespace DH.Devices.Vision
Mat originMat = new Mat();
Mat detectMat = new Mat();
-#pragma warning disable CS0168 // 声明了变量,但从未使用过
try
{
if (req.mImage == null)
diff --git a/DH.Devices.Vision/SimboVisionDriver.cs b/DH.Devices.Vision/SimboVisionDriver.cs
index afa5444..4512d07 100644
--- a/DH.Devices.Vision/SimboVisionDriver.cs
+++ b/DH.Devices.Vision/SimboVisionDriver.cs
@@ -1,5 +1,6 @@
using DH.Commons.Base;
using DH.Commons.Enums;
+using DH.Commons.Helper;
using DH.UI.Model.Winform;
using HalconDotNet;
using OpenCvSharp;
@@ -15,6 +16,7 @@ using System.Windows.Forms;
using System.Xml.Linq;
using XKRS.UI.Model.Winform;
using static DH.Commons.Enums.EnumHelper;
+using LogLevel = DH.Commons.Enums.EnumHelper.LogLevel;
using ResultState = DH.Commons.Base.ResultState;
@@ -70,16 +72,21 @@ namespace DH.Devices.Vision
if (detectConfig == null)
{
-
+ LogAsync(DateTime.Now, LogLevel.Exception, $"异常:未能获取检测配置");
//未能获得检测配置
return detectResult;
}
+ Stopwatch sw = new Stopwatch();
#region 1.预处理
-
+ sw.Start();
using (Mat PreTMat = originImgSet.Clone())
{
PreTreated(detectConfig, detectResult, PreTMat);
+ PreTreated2(detectConfig, detectResult, PreTMat);
}
+ sw.Stop();
+ LogAsync(DateTime.Now, LogLevel.Information, $"产品:{detectResult.Pid} {detectConfig.Name}预处理耗时:{sw.ElapsedMilliseconds}ms。SpecsResults:{string.Join(";", detectResult.realSpecs.Select(u => $"{u.Code} {u.ActualValue}"))}");
+ // 工位2尺寸测量
@@ -111,7 +118,7 @@ namespace DH.Devices.Vision
}
#region 2.深度学习推理
- //LogAsync(DateTime.Now, LogLevel.Information, $"{detectConfig.Name} 产品{detectResult.TempPid} 模型检测执行");
+ LogAsync(DateTime.Now, LogLevel.Information, $"{detectConfig.Name} 产品{detectResult.TempPid} 模型检测执行");
if (!string.IsNullOrWhiteSpace(detectConfig.ModelPath))
{
@@ -193,6 +200,8 @@ namespace DH.Devices.Vision
if (result == null || (result != null && !result.IsSuccess))
{
+ LogAsync(DateTime.Now, LogLevel.Exception, $"CoreInx:{mlSet.GPUNo} 产品:{detectResult.Pid} {detectConfig.Name} 模型检测异常,{result?.ResultMessage}");
+
detectResult.IsMLDetectDone = false;
}
if (result != null && result.IsSuccess)
@@ -200,9 +209,13 @@ namespace DH.Devices.Vision
detectResult.DetectDetails = result.ResultDetails;
if (detectResult.DetectDetails != null)
{
+ LogAsync(DateTime.Now, LogLevel.Information, $"CoreInx:{mlSet.GPUNo} 产品:{detectResult.Pid} {detectResult.DetectName} 模型检测总耗时:{mlWatch.ElapsedMilliseconds} ms {result.ResultMessage},{string.Join(";", detectResult.DetectDetails.Select(u => $"{u.LabelName} X:{u.Rect.X} Y:{u.Rect.Y} Area:{u.Area.ToString("f2")} W:{u.Rect.Width} H:{u.Rect.Height}"))}");
+
}
else
{
+ LogAsync(DateTime.Now, LogLevel.Exception, $"CoreInx:{mlSet.GPUNo} 产品:{detectResult.Pid} {detectConfig.Name} 模型检测异常返回 null");
+
detectResult.IsMLDetectDone = false;
}
}
@@ -280,6 +293,7 @@ namespace DH.Devices.Vision
#endregion
+ LogAsync(DateTime.Now, LogLevel.Information, $"{detectConfig.Name} 检测结果:{detectResult.ResultState.GetEnumDescription()}");
@@ -430,11 +444,13 @@ namespace DH.Devices.Vision
{
// throw new ProcessException("异常:模型加载异常", null);
}
- //LogAsync(DateTime.Now, LogLevel.Information, $"模型加载成功;是否GPU:{isGPU} CoreInx:{coreInx} - {dc.Name}" + $" {dc.ModelType.GetEnumDescription()}:{dc.ModelPath}");
+ LogAsync(DateTime.Now, LogLevel.Information, $"模型加载成功;是否GPU:{isGPU} CoreInx:{coreInx} - {dc.Name}" + $" {dc.ModelType.GetEnumDescription()}:{dc.ModelPath}");
}
}
catch (Exception ex)
{
+ LogAsync(DateTime.Now, LogLevel.Error, $"模型加载成功;是否GPU:{isGPU} CoreInx:{coreInx} - {dc.Name}" + $" {dc.ModelType.GetEnumDescription()}:{dc.ModelPath}");
+
//throw new ProcessException($"异常:是否GPU:{isGPU} CoreInx:{coreInx} - {dc.Name}模型加载异常:{ex.GetExceptionMessage()}");
}
return mLEngineSet;
@@ -519,7 +535,7 @@ namespace DH.Devices.Vision
if (!tool.RunProcedure(out string errorMsg, out _))
{
// detectResult.PreTreatedFlag = false;
-
+ LogAsync(DateTime.Now, LogLevel.Exception, $"{detectConfig.Name}预处理异常,{errorMsg}");
detectResult.IsPreTreatDone = false;
@@ -534,12 +550,82 @@ namespace DH.Devices.Vision
// detectResult.IsPreTreatDone = detectResult.VisionImageSet.PreTreatedFlag = preTreatRet == 1;
//detectResult.IsPreTreatDone = detectResult.VisionImageSet.PreTreatedFlag = true;
// detectResult.VisionImageSet.PreTreatedTime = DateTime.Now;
-
- for (int i = 0; i < detectConfig.OUTPreTreatParams.Count; i++)
+ switch (preTreatRet)
{
- var param = detectConfig.OUTPreTreatParams[i];
- tool.InputTupleDic[param.Name] = double.Parse(param.Value);
+ case 0: // 预处理算法无异常
+ {
+
+ for (int i = 0; i < detectConfig.OUTPreTreatParams.Count; i++)
+ {
+
+ var param = detectConfig.OUTPreTreatParams[i];
+
+ var Value = tool.GetResultTuple(param.Name);
+
+ // 显示结果
+ IndexedSpec specRCricularity = new()
+ {
+ Code = param.Name,
+ ActualValue = Value
+ };
+ detectResult.realSpecs.Add(specRCricularity);
+ }
+ detectResult.IsPreTreatNG = false;
+ detectResult.IsPreTreatDone = true;
+ }
+ break;
+ case -111: // 检测结果为NG
+ {
+ /// detectResult.VisionImageSet.DetectionResultImage =
+ // tool.GetResultObject("OUTPUT_PreTreatedImage").ConvertHImageToBitmap();
+ for (int i = 0; i < detectConfig.OUTPreTreatParams.Count; i++)
+ {
+
+ var param = detectConfig.OUTPreTreatParams[i];
+
+ var Value = tool.GetResultTuple(param.Name);
+
+ // 显示结果
+ IndexedSpec specRCricularity = new()
+ {
+ Code = param.Name,
+ ActualValue = Value
+ };
+ detectResult.realSpecs.Add(specRCricularity);
+ }
+ // 结果为NG
+ detectResult.ResultState = ResultState.DetectNG;
+ detectResult.IsPreTreatNG = true;
+ detectResult.IsPreTreatDone = true;
+ break;
+ }
+ default:
+ case -999: // 算法异常
+ {
+ // 算法异常时,结果图
+ // detectResult.VisionImageSet.DetectionResultImage =
+ // tool.GetResultObject("OUTPUT_PreTreatedImage").ConvertHImageToBitmap();
+
+ for (int i = 0; i < detectConfig.OUTPreTreatParams.Count; i++)
+ {
+
+
+ var param = detectConfig.OUTPreTreatParams[i];
+ // 显示结果
+ IndexedSpec specRCricularity = new()
+ {
+ Code = param.Name,
+ ActualValue = -1,
+ };
+ detectResult.realSpecs.Add(specRCricularity);
+ }
+
+ // 结果保持TBD
+ detectResult.IsPreTreatDone = true;
+ break;
+ }
}
+
@@ -571,7 +657,7 @@ namespace DH.Devices.Vision
}
catch (Exception ex)
{
-
+ LogAsync(DateTime.Now, LogLevel.Exception, $"{detectConfig.Name}预处理异常:{ex.GetExceptionMessage()}");
}
finally
{
@@ -582,6 +668,266 @@ namespace DH.Devices.Vision
}
}
+ public void PreTreated2(DetectionConfig detectConfig, DetectStationResult detectResult,Mat MhImage)
+ {
+ try
+ {
+
+ if (detectConfig.SizeTreatParamList != null && detectConfig.SizeTreatParamList.Count > 0)
+ {
+ foreach (var preTreat in detectConfig.SizeTreatParamList)
+ {
+ if (!string.IsNullOrWhiteSpace(preTreat.PrePath))
+ {
+ string toolKey = preTreat.PrePath;
+ if (!HalconToolDict.ContainsKey(toolKey))
+ {
+ LogAsync(DateTime.Now, LogLevel.Exception, $"{detectConfig.Name}未获取预处理{preTreat.PreName}算法");
+ return;
+ }
+ //Mean_Thre Deviation_Thre Mean_standard Deviation_standard
+ var tool = HalconToolDict[toolKey];
+
+ //tool.InputTupleDic["Mean_Thre"] = 123;
+ List PreParams = new List();
+ preoutparms(PreParams, preTreat.ResultShow);
+ for (int i = 0; i < PreParams.Count(); i++)
+ {
+ var param = PreParams[i];
+ if (param.Value.Contains(","))
+ {
+ string[] strings = param.Value.Split(",");
+ float[] array = strings.Select(s => float.Parse(s)).ToArray();
+ HTuple hTupleArray = new HTuple(array);
+
+ tool.InputTupleDic[param.Name] = hTupleArray;
+ }
+ else
+ {
+ tool.InputTupleDic[param.Name] = double.Parse(param.Value);// param.Value.ToInt();
+ }
+
+ IndexedSpec spec1 = new IndexedSpec();
+
+ switch (preTreat.PreType)
+ {
+ case SizeEnum.线线测量:
+
+ break;
+ case SizeEnum.线圆测量:
+
+ break;
+ case SizeEnum.圆形测量:
+ break;
+ case SizeEnum.高度测量:
+ spec1.Code = $"in-{param.Name}";
+ spec1.ActualValue = double.Parse(param.Value);
+ break;
+ case SizeEnum.直线测量:
+ break;
+ }
+
+
+
+ detectResult.realSpecs.Add(spec1);
+ }
+ //// 指定保存路径
+ //string filePath = @"D:\saved_image.jpg"; // 你可以根据需要更改路径和文件名
+
+ //// 使用WriteImage保存图像
+ //detectResult.VisionImageSet.HImage.WriteImage("jpeg", 0, filePath); // "jpeg" 表示图像格式,0表示不使用压缩
+ HObject obj = OpenCVHelper.MatToHImage(MhImage);
+ HImage hImage = HalconHelper.ConvertHObjectToHImage(obj);
+ tool.InputImageDic["INPUT_Image"] = hImage;
+ if (!tool.RunProcedure(out string errorMsg, out _))
+ {
+ // detectResult.VisionImageSet.PreTreatedFlag = false;
+ LogAsync(DateTime.Now, LogLevel.Exception, $"{detectConfig.Name}预处理异常,{errorMsg}");
+ detectResult.IsPreTreatDone = false;
+
+ // HandleDetectDone(detectResult, detectConfig);
+ return;
+ }
+
+ var preTreatRet = tool.GetResultTuple("OUTPUT_Flag").I;
+ //double MatchScore = 1;
+ //MatchScore = tool.GetResultTuple("MatchScore");
+
+
+ detectResult.IsPreTreatDone = preTreatRet == 1;
+ // detectResult.IsPreTreatDone = detectResult.VisionImageSet.PreTreatedFlag = true;
+ // detectResult.VisionImageSet.PreTreatedTime = DateTime.Now;
+
+
+ //IndexedSpec spec1 = new IndexedSpec();
+ //spec1.Code = "score";
+ //spec1.ActualValue = MatchScore;
+
+
+ //detectResult.realSpecs.Add(spec1);
+ ;
+
+
+ // 2023/10/16 新增预处理结果反馈,如果预处理结果为NG,直接返回
+ if (preTreatRet != 0)
+ {
+ detectResult.ResultState = ResultState.DetectNG;
+
+ detectResult.IsPreTreatNG = true;
+ // detectResult.VisionImageSet.DetectionResultImage = detectResult.VisionImageSet.MLImage.ConvertHImageToBitmap();
+
+
+ }
+ else
+ {
+
+ switch (preTreat.PreType)
+ {
+ case SizeEnum.线线测量:
+ isPreOutparams(ref detectResult, preTreat, tool, ref preTreatRet);
+ break;
+ case SizeEnum.线圆测量:
+ isPreOutparams(ref detectResult, preTreat, tool, ref preTreatRet);
+ break;
+ case SizeEnum.圆形测量:
+ break;
+ case SizeEnum.高度测量:
+ {
+
+ isPreOutparams(ref detectResult, preTreat, tool, ref preTreatRet);
+ }
+ break;
+ case SizeEnum.直线测量:
+ break;
+ }
+
+
+
+ }
+ }
+ }
+
+
+
+ }
+
+
+
+
+
+ }
+ catch (Exception ex)
+ {
+ LogAsync(DateTime.Now, LogLevel.Exception, $"{detectConfig.Name}尺寸预处理异常:{ex.GetExceptionMessage()}");
+ }
+ finally
+ {
+ //detectResult.VisionImageSet.HImage?.Dispose();
+ //detectResult.VisionImageSet.HImage = null;
+ }
+ }
+ public void isPreOutparams(ref DetectStationResult detectResult, SizeTreatParam preTreat, HDevEngineTool tool, ref int preTreatRet)
+ {
+ List PreParams = new List();
+ preoutparms(PreParams, preTreat.OutResultShow);
+
+ for (int i = 0; i < PreParams.Count; i++)
+ {
+ var param = PreParams[i];
+ double dParam = double.Parse(param.Value);
+ double heights = tool.GetResultTuple(param.Name).D;
+ switch (preTreat.PreType)
+ {
+ case SizeEnum.高度测量:
+
+
+ IndexedSpec spec2 = new IndexedSpec();
+ spec2.Code = $"out-{param.Name}";
+ spec2.ActualValue = Convert.ToDouble(param.Value);
+
+
+ detectResult.realSpecs.Add(spec2);
+
+
+ IndexedSpec spec1 = new IndexedSpec();
+ spec1.Code = $"actual-{param.Name}";
+ spec1.ActualValue = heights;
+
+
+ detectResult.realSpecs.Add(spec1);
+
+ break;
+ default: break;
+ }
+
+
+
+ if ((heights > dParam - preTreat.PrePix) && (heights < dParam + preTreat.PrePix))
+ {
+
+
+ }
+ else
+ {
+ preTreatRet = -1;
+ break;
+ }
+
+ }
+
+ if (preTreatRet != 0)
+ {
+ detectResult.ResultState = ResultState.DetectNG;
+
+ detectResult.IsPreTreatNG = true;
+ //detectResult.VisionImageSet.DetectionResultImage = detectResult.VisionImageSet.MLImage.ConvertHImageToBitmap();
+
+ }
+ else
+ {
+ // detectResult.VisionImageSet.DetectionResultImage = detectResult.VisionImageSet.MLImage.ConvertHImageToBitmap();
+
+ }
+ }
+
+
+ public void preoutparms(List preTreatParams, string defectRows)
+ {
+ // 解析 ReslutShow 字符串,构建 PreTreatParam 列表
+ if (!string.IsNullOrEmpty(defectRows))
+ {
+ var keyValuePairs = defectRows.Split(';');
+
+ foreach (var pair in keyValuePairs)
+ {
+ var parts = pair.Split(':');
+ if (parts.Length == 2)
+ {
+ PreTreatParam param;
+ if (parts[1].Trim().Contains(","))
+ {
+ param = new PreTreatParam
+ {
+ Name = parts[0].Trim(), // 去除多余的空格
+ Value = parts[1].Trim() // 转换为 double,失败则为0
+ };
+ }
+ else
+ {
+ double dvalue = double.TryParse(parts[1].Trim(), out double value) ? value : 0;
+
+ param = new PreTreatParam
+ {
+ Name = parts[0].Trim(), // 去除多余的空格
+ Value = dvalue.ToString() // 转换为 double,失败则为0
+ };
+ }
+
+ preTreatParams.Add(param);
+ }
+ }
+ }
+ }
///
/// 显示检测结果
@@ -654,8 +1000,8 @@ namespace DH.Devices.Vision
}
catch (Exception ex)
{
- // LogAsync(DateTime.Now, LogLevel.Exception,
- // $"{Name}显示{detectResult.DetectName}检测结果异常,{ex.GetExceptionMessage()}");
+ LogAsync(DateTime.Now, LogLevel.Exception,
+ $"{Name}显示{detectResult.DetectName}检测结果异常,{ex.GetExceptionMessage()}");
}
finally
{
diff --git a/DHSoftware/DHSoftware.csproj b/DHSoftware/DHSoftware.csproj
index 25a7edd..c854633 100644
--- a/DHSoftware/DHSoftware.csproj
+++ b/DHSoftware/DHSoftware.csproj
@@ -17,46 +17,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/DHSoftware/MainWindow.Designer.cs b/DHSoftware/MainWindow.Designer.cs
index 4101135..ef88309 100644
--- a/DHSoftware/MainWindow.Designer.cs
+++ b/DHSoftware/MainWindow.Designer.cs
@@ -28,14 +28,14 @@
///
private void InitializeComponent()
{
- AntdUI.Tabs.StyleLine styleLine2 = new AntdUI.Tabs.StyleLine();
- AntdUI.Tabs.StyleCard styleCard2 = new AntdUI.Tabs.StyleCard();
- AntdUI.SegmentedItem segmentedItem6 = new AntdUI.SegmentedItem();
+ AntdUI.Tabs.StyleLine styleLine1 = new AntdUI.Tabs.StyleLine();
+ AntdUI.Tabs.StyleCard styleCard1 = new AntdUI.Tabs.StyleCard();
+ AntdUI.SegmentedItem segmentedItem1 = new AntdUI.SegmentedItem();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainWindow));
- AntdUI.SegmentedItem segmentedItem7 = new AntdUI.SegmentedItem();
- AntdUI.SegmentedItem segmentedItem8 = new AntdUI.SegmentedItem();
- AntdUI.SegmentedItem segmentedItem9 = new AntdUI.SegmentedItem();
- AntdUI.SegmentedItem segmentedItem10 = new AntdUI.SegmentedItem();
+ AntdUI.SegmentedItem segmentedItem2 = new AntdUI.SegmentedItem();
+ AntdUI.SegmentedItem segmentedItem3 = new AntdUI.SegmentedItem();
+ AntdUI.SegmentedItem segmentedItem4 = new AntdUI.SegmentedItem();
+ AntdUI.SegmentedItem segmentedItem5 = new AntdUI.SegmentedItem();
titlebar = new AntdUI.PageHeader();
lbName = new AntdUI.Label();
tabsStas = new AntdUI.Tabs();
@@ -58,7 +58,7 @@
panel2 = new AntdUI.Panel();
tabImgDisplay = new AntdUI.Tabs();
panel4 = new AntdUI.Panel();
- richTextBox1 = new RichTextBox();
+ pnlLog = new AntdUI.Panel();
panel6 = new AntdUI.Panel();
lblNum2 = new Label();
label12 = new Label();
@@ -125,7 +125,7 @@
tabsStas.Name = "tabsStas";
tabsStas.Pages.Add(tabPage3);
tabsStas.Size = new Size(580, 176);
- tabsStas.Style = styleLine2;
+ tabsStas.Style = styleLine1;
tabsStas.TabIndex = 3;
tabsStas.Text = "tabs3";
//
@@ -303,13 +303,13 @@
tabImgDisplay.Location = new Point(0, 0);
tabImgDisplay.Name = "tabImgDisplay";
tabImgDisplay.Size = new Size(1024, 388);
- tabImgDisplay.Style = styleCard2;
+ tabImgDisplay.Style = styleCard1;
tabImgDisplay.TabIndex = 3;
tabImgDisplay.Text = "tabs1";
//
// panel4
//
- panel4.Controls.Add(richTextBox1);
+ panel4.Controls.Add(pnlLog);
panel4.Controls.Add(panel6);
panel4.Dock = DockStyle.Bottom;
panel4.Location = new Point(0, 456);
@@ -318,14 +318,14 @@
panel4.TabIndex = 2;
panel4.Text = "panel4";
//
- // richTextBox1
+ // pnlLog
//
- richTextBox1.Dock = DockStyle.Fill;
- richTextBox1.Location = new Point(0, 0);
- richTextBox1.Name = "richTextBox1";
- richTextBox1.Size = new Size(719, 112);
- richTextBox1.TabIndex = 1;
- richTextBox1.Text = "";
+ pnlLog.Dock = DockStyle.Fill;
+ pnlLog.Location = new Point(0, 0);
+ pnlLog.Name = "pnlLog";
+ pnlLog.Size = new Size(719, 112);
+ pnlLog.TabIndex = 2;
+ pnlLog.Text = "panel8";
//
// panel6
//
@@ -493,66 +493,66 @@
segmented1.Font = new Font("Microsoft YaHei UI", 9F);
segmented1.ForeColor = Color.White;
segmented1.Full = true;
- segmentedItem6.Badge = null;
- segmentedItem6.BadgeAlign = AntdUI.TAlignFrom.TR;
- segmentedItem6.BadgeBack = null;
- segmentedItem6.BadgeMode = false;
- segmentedItem6.BadgeOffsetX = 0;
- segmentedItem6.BadgeOffsetY = 0;
- segmentedItem6.BadgeSize = 0.6F;
- segmentedItem6.BadgeSvg = null;
- segmentedItem6.IconActiveSvg = resources.GetString("segmentedItem6.IconActiveSvg");
- segmentedItem6.IconSvg = resources.GetString("segmentedItem6.IconSvg");
- segmentedItem6.Text = "启动";
- segmentedItem7.Badge = null;
- segmentedItem7.BadgeAlign = AntdUI.TAlignFrom.TR;
- segmentedItem7.BadgeBack = null;
- segmentedItem7.BadgeMode = false;
- segmentedItem7.BadgeOffsetX = 0;
- segmentedItem7.BadgeOffsetY = 0;
- segmentedItem7.BadgeSize = 0.6F;
- segmentedItem7.BadgeSvg = null;
- segmentedItem7.IconActiveSvg = resources.GetString("segmentedItem7.IconActiveSvg");
- segmentedItem7.IconSvg = resources.GetString("segmentedItem7.IconSvg");
- segmentedItem7.Text = "停止";
- segmentedItem8.Badge = null;
- segmentedItem8.BadgeAlign = AntdUI.TAlignFrom.TR;
- segmentedItem8.BadgeBack = null;
- segmentedItem8.BadgeMode = false;
- segmentedItem8.BadgeOffsetX = 0;
- segmentedItem8.BadgeOffsetY = 0;
- segmentedItem8.BadgeSize = 0.6F;
- segmentedItem8.BadgeSvg = null;
- segmentedItem8.IconActiveSvg = resources.GetString("segmentedItem8.IconActiveSvg");
- segmentedItem8.IconSvg = resources.GetString("segmentedItem8.IconSvg");
- segmentedItem8.Text = "复位";
- segmentedItem9.Badge = null;
- segmentedItem9.BadgeAlign = AntdUI.TAlignFrom.TR;
- segmentedItem9.BadgeBack = null;
- segmentedItem9.BadgeMode = false;
- segmentedItem9.BadgeOffsetX = 0;
- segmentedItem9.BadgeOffsetY = 0;
- segmentedItem9.BadgeSize = 0.6F;
- segmentedItem9.BadgeSvg = null;
- segmentedItem9.IconActiveSvg = resources.GetString("segmentedItem9.IconActiveSvg");
- segmentedItem9.IconSvg = resources.GetString("segmentedItem9.IconSvg");
- segmentedItem9.Text = "登录";
- segmentedItem10.Badge = null;
- segmentedItem10.BadgeAlign = AntdUI.TAlignFrom.TR;
- segmentedItem10.BadgeBack = null;
- segmentedItem10.BadgeMode = false;
- segmentedItem10.BadgeOffsetX = 0;
- segmentedItem10.BadgeOffsetY = 0;
- segmentedItem10.BadgeSize = 0.6F;
- segmentedItem10.BadgeSvg = null;
- segmentedItem10.IconActiveSvg = resources.GetString("segmentedItem10.IconActiveSvg");
- segmentedItem10.IconSvg = resources.GetString("segmentedItem10.IconSvg");
- segmentedItem10.Text = "设置";
- segmented1.Items.Add(segmentedItem6);
- segmented1.Items.Add(segmentedItem7);
- segmented1.Items.Add(segmentedItem8);
- segmented1.Items.Add(segmentedItem9);
- segmented1.Items.Add(segmentedItem10);
+ segmentedItem1.Badge = null;
+ segmentedItem1.BadgeAlign = AntdUI.TAlignFrom.TR;
+ segmentedItem1.BadgeBack = null;
+ segmentedItem1.BadgeMode = false;
+ segmentedItem1.BadgeOffsetX = 0;
+ segmentedItem1.BadgeOffsetY = 0;
+ segmentedItem1.BadgeSize = 0.6F;
+ segmentedItem1.BadgeSvg = null;
+ segmentedItem1.IconActiveSvg = resources.GetString("segmentedItem1.IconActiveSvg");
+ segmentedItem1.IconSvg = resources.GetString("segmentedItem1.IconSvg");
+ segmentedItem1.Text = "启动";
+ segmentedItem2.Badge = null;
+ segmentedItem2.BadgeAlign = AntdUI.TAlignFrom.TR;
+ segmentedItem2.BadgeBack = null;
+ segmentedItem2.BadgeMode = false;
+ segmentedItem2.BadgeOffsetX = 0;
+ segmentedItem2.BadgeOffsetY = 0;
+ segmentedItem2.BadgeSize = 0.6F;
+ segmentedItem2.BadgeSvg = null;
+ segmentedItem2.IconActiveSvg = resources.GetString("segmentedItem2.IconActiveSvg");
+ segmentedItem2.IconSvg = resources.GetString("segmentedItem2.IconSvg");
+ segmentedItem2.Text = "停止";
+ segmentedItem3.Badge = null;
+ segmentedItem3.BadgeAlign = AntdUI.TAlignFrom.TR;
+ segmentedItem3.BadgeBack = null;
+ segmentedItem3.BadgeMode = false;
+ segmentedItem3.BadgeOffsetX = 0;
+ segmentedItem3.BadgeOffsetY = 0;
+ segmentedItem3.BadgeSize = 0.6F;
+ segmentedItem3.BadgeSvg = null;
+ segmentedItem3.IconActiveSvg = resources.GetString("segmentedItem3.IconActiveSvg");
+ segmentedItem3.IconSvg = resources.GetString("segmentedItem3.IconSvg");
+ segmentedItem3.Text = "复位";
+ segmentedItem4.Badge = null;
+ segmentedItem4.BadgeAlign = AntdUI.TAlignFrom.TR;
+ segmentedItem4.BadgeBack = null;
+ segmentedItem4.BadgeMode = false;
+ segmentedItem4.BadgeOffsetX = 0;
+ segmentedItem4.BadgeOffsetY = 0;
+ segmentedItem4.BadgeSize = 0.6F;
+ segmentedItem4.BadgeSvg = null;
+ segmentedItem4.IconActiveSvg = resources.GetString("segmentedItem4.IconActiveSvg");
+ segmentedItem4.IconSvg = resources.GetString("segmentedItem4.IconSvg");
+ segmentedItem4.Text = "登录";
+ segmentedItem5.Badge = null;
+ segmentedItem5.BadgeAlign = AntdUI.TAlignFrom.TR;
+ segmentedItem5.BadgeBack = null;
+ segmentedItem5.BadgeMode = false;
+ segmentedItem5.BadgeOffsetX = 0;
+ segmentedItem5.BadgeOffsetY = 0;
+ segmentedItem5.BadgeSize = 0.6F;
+ segmentedItem5.BadgeSvg = null;
+ segmentedItem5.IconActiveSvg = resources.GetString("segmentedItem5.IconActiveSvg");
+ segmentedItem5.IconSvg = resources.GetString("segmentedItem5.IconSvg");
+ segmentedItem5.Text = "设置";
+ segmented1.Items.Add(segmentedItem1);
+ segmented1.Items.Add(segmentedItem2);
+ segmented1.Items.Add(segmentedItem3);
+ segmented1.Items.Add(segmentedItem4);
+ segmented1.Items.Add(segmentedItem5);
segmented1.Location = new Point(0, 0);
segmented1.Name = "segmented1";
segmented1.Size = new Size(491, 68);
@@ -626,7 +626,6 @@
private AntdUI.Panel panel2;
private AntdUI.Panel panel4;
private AntdUI.Tabs tabImgDisplay;
- private RichTextBox richTextBox1;
private AntdUI.Panel panel6;
private Label lblUPH2;
private Label lblNum2;
@@ -635,5 +634,6 @@
private Label label10;
private Label lblstarttime2;
private Label label7;
+ private AntdUI.Panel pnlLog;
}
}
\ No newline at end of file
diff --git a/DHSoftware/MainWindow.cs b/DHSoftware/MainWindow.cs
index 8754f09..d99d65b 100644
--- a/DHSoftware/MainWindow.cs
+++ b/DHSoftware/MainWindow.cs
@@ -14,6 +14,7 @@ using DHSoftware.Utils;
using DHSoftware.Views;
using DVPCameraType;
using HalconDotNet;
+using Microsoft.VisualBasic.Logging;
using Microsoft.Win32;
using OpenCvSharp;
using SqlSugar;
@@ -33,6 +34,7 @@ using XKRS.UI.Device.Winform;
using static AntdUI.Math3D;
using static DH.Commons.Enums.EnumHelper;
using Camera = DHSoftware.Models.Camera;
+using LogLevel = DH.Commons.Enums.EnumHelper.LogLevel;
using ResultState = DH.Commons.Base.ResultState;
namespace DHSoftware
@@ -40,7 +42,7 @@ namespace DHSoftware
public partial class MainWindow : AntdUI.Window
{
private Dictionary> _cameraRelatedDetectionDict = null;
-
+ public event Action OnLog;
private string _loginName;
public string LoginName
@@ -262,12 +264,15 @@ namespace DHSoftware
var cameraBase = ConfigModel.CameraBaseList[i];
if (cameraBase.CamType == EnumCamType.度申Do3think)
{
+
Do3ThinkCamera cam = new Do3ThinkCamera();
cam.CameraName = cameraBase.CameraName;
cam.CameraIP = cameraBase.CameraIP;
cam.IsEnabled = cameraBase.IsEnabled;
Cameras.Add(cam);
+ cam.OnLog -= _visionEngine_OnLog;
+ cam.OnLog += _visionEngine_OnLog;
cam.CameraConnect();
cam.OnHImageOutput += OnCameraHImageOutput;
}
@@ -300,12 +305,14 @@ namespace DHSoftware
PLC.PLCName = plcBase.PLCName;
PLC.PLCItemList = plcBase.PLCItemList;
PLC.Port = plcBase.Port;
+ PLC.OnLog -= _visionEngine_OnLog;
+ PLC.OnLog += _visionEngine_OnLog;
PLC.PLCConnect();
}
}
}
}
-
+ FrmLog frmLog;
public void InitModel()
{
Dectection.Clear();
@@ -323,6 +330,7 @@ namespace DHSoftware
detectionConfig.ModelHeight = detection.ModelHeight;
detectionConfig.In_lable_path = detection.In_lable_path;
detectionConfig.IsEnabled = detection.IsEnabled;
+
detectionConfig.ShowLocation.X = (i + 1) % 5 + (i + 1) / 5;
// detectionConfig.ShowLocation.X = detection.ShowLocation.X;
detectionConfig.ShowLocation.Y = (i + 1) / 5 + 1;
@@ -351,22 +359,66 @@ namespace DHSoftware
});
string inferenceDevice = "CPU";
+ frmLog = new FrmLog();
+ frmLog.Dock = DockStyle.Fill;
+ pnlLog.Controls.Add(frmLog);
//
_visionEngine = new SimboVisionDriver();
_visionEngine.DetectionConfigs = DetectionConfigs;
-
+ _visionEngine.OnLog += _visionEngine_OnLog;
//初始化模型 加载模型
_visionEngine.Init();
+
CtrlVisionRunBase ctrlVisionRun = new CtrlVisionRunBase(_visionEngine);
ctrlVisionRun.Dock = DockStyle.Fill;
tabImgDisplay.Controls.Add(ctrlVisionRun);
+
}
+ private void _visionEngine_OnLog(LogMsg msg)
+ {
+ OnLog?.Invoke(msg);
+ LogDisplay(msg);
+ }
+ private void LogDisplay(LogMsg msg)
+ {
+
+ frmLog?.LogDisplay(msg);
+ }
+ public LoggerHelper LoggerHelper { get; set; } = new LoggerHelper();
+ public virtual void LogAsync(LogMsg msg)
+ {
+ //if (IConfig != null)
+ //{
+ // LoggerHelper.SetLogLevel(IConfig.DefaultLogLevel);
+ //}
+ //else
+ //{
+ // LoggerHelper.SetLogLevel(LogLevel.Assist);
+ //}
+
+ msg.ThreadId = Thread.CurrentThread.ManagedThreadId;
+
+ OnLog?.Invoke(msg);
+ //if (IConfig?.IsLogEnabled ?? true)
+ //{
+ LoggerHelper.LogAsync(msg);
+ //}
+ }
+ public virtual void LogAsync(DateTime dt, LogLevel logLevel, string msg)
+ {
+ LogAsync(new LogMsg(dt, logLevel, msg));
+
+ }
private void BindEventHandler()
{
btnAddProject.Click += BtnAddProject_Click;
btnDeleteProject.Click += BtnDeleteProject_Click;
btnLoadProject.Click += BtnLoadProject_Click;
+ LoggerHelper.LogPath = "D://";
+ LoggerHelper.LogPrefix = "Process";
+ OnLog -= LogDisplay;
+ OnLog += LogDisplay;
}
private void BtnDeleteProject_Click(object? sender, EventArgs e)
@@ -579,7 +631,9 @@ namespace DHSoftware
private void HandleStartButton()
{
+ LogAsync(DateTime.Now, LogLevel.Information, "流程启动中,请稍候...");
StartProcess();
+ LogAsync(DateTime.Now, LogLevel.Action, "流程启动完成!");
}
@@ -731,12 +785,10 @@ namespace DHSoftware
{
ProductData pData = new ProductData("", pieceNumber, ProductBaseCount);
_productLists[index][pieceNumber] = pData;
+ LogAsync(DateTime.Now, LogLevel.Action, $">> 轴{axisIndex}新产品{pieceNumber}加入队列{index}----板卡计数{PieceCount}");
+
}
- string logStr = $"时间:{DateTime.Now} 轴{axisIndex}新产品{pieceNumber}加入队列{index}----入料计数{PieceCount}\n";
- Task.Run(() =>
- {
- //this.BeginInvoke(new MethodInvoker(delegate () { richTextBox1.AppendText(logStr); }));
- });
+
DateTime dtNow = DateTime.Now;
UpdateCT(null, (float)(dtNow - _ctTime).TotalSeconds);
_ctTime = dtNow;
@@ -812,22 +864,7 @@ namespace DHSoftware
//LogAsync(DateTime.Now, LogLevel.Error, $"{camera.Name} 未找到产品,编号:{productNumber},队列{index}数量:{tmpDic.Count},列表:{pnStr}");
localImageSet.Dispose();
- this.BeginInvoke(new MethodInvoker(delegate ()
- {
- int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
-
- richTextBox1.AppendText(productNumber + "提前推出" + camera.CameraName);
-
- // 设置回原来的滚动位置
- richTextBox1.SelectionStart = richTextBox1.TextLength;
- richTextBox1.ScrollToCaret();
- }));
- //重新生成实例 销毁之前的实例
-
- using (StreamWriter sw = new StreamWriter("D://123log.txt", true, Encoding.UTF8))
- {
- sw.WriteLine(productNumber + "提前推出" + camera.CameraName);
- }
+
return;
}
@@ -836,20 +873,20 @@ namespace DHSoftware
if (!_cameraRelatedDetectionDict.ContainsKey(camera.CameraName))
{
localImageSet.Dispose();
- this.BeginInvoke(new MethodInvoker(delegate ()
- {
- int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
+ //this.BeginInvoke(new MethodInvoker(delegate ()
+ //{
+ // // int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
- richTextBox1.AppendText(productNumber + "提前推出" + camera.CameraName);
+ // // richTextBox1.AppendText(productNumber + "提前推出" + camera.CameraName);
- // 设置回原来的滚动位置
- richTextBox1.SelectionStart = richTextBox1.TextLength;
- richTextBox1.ScrollToCaret();
- }));
- //重新生成实例 销毁之前的实例
+ // // 设置回原来的滚动位置
+ // // richTextBox1.SelectionStart = richTextBox1.TextLength;
+ // // richTextBox1.ScrollToCaret();
+ //}));
+ ////重新生成实例 销毁之前的实例
- // LogAsync(DateTime.Now, LogLevel.Warning, $"{camera.Name} 找到产品{productNumber},但是没有推理1");
+ LogAsync(DateTime.Now, LogLevel.Warning, $"{camera.CameraName} 找到产品{productNumber},但是没有推理1");
return;
}
@@ -863,7 +900,7 @@ namespace DHSoftware
{
string detectionId = detectionDict[i];
- // 1. 预处理
+
using (Mat inferenceImage = localImageSet.Clone()) // 仅在此处克隆,确保推理过程中 Mat 有独立副本
{
DetectStationResult temp1 = _visionEngine.RunInference(inferenceImage, detectionId);
@@ -888,13 +925,13 @@ namespace DHSoftware
// CalculateOEE();
this.BeginInvoke(new MethodInvoker(delegate ()
{
- int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
+ //int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
- richTextBox1.AppendText($"统计结果成功,{productNumber} 吹气!\n");
+ //richTextBox1.AppendText($"统计结果成功,{productNumber} 吹气!\n");
// 设置回原来的滚动位置
- richTextBox1.SelectionStart = richTextBox1.TextLength;
- richTextBox1.ScrollToCaret();
+ // richTextBox1.SelectionStart = richTextBox1.TextLength;
+ // richTextBox1.ScrollToCaret();
}));
#region 6. 统计产品结果
@@ -935,13 +972,13 @@ namespace DHSoftware
$"当前队列产品数量:{tmpDic.Count}";
this.BeginInvoke(new MethodInvoker(delegate ()
{
- int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
+ // int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
- richTextBox1.AppendText(logStr);
+ // richTextBox1.AppendText(logStr);
// 设置回原来的滚动位置
- richTextBox1.SelectionStart = richTextBox1.TextLength;
- richTextBox1.ScrollToCaret();
+ // richTextBox1.SelectionStart = richTextBox1.TextLength;
+ //richTextBox1.ScrollToCaret();
}));
}
else
@@ -953,13 +990,13 @@ namespace DHSoftware
$"当前队列产品数量:{tmpDic.Count}";
this.BeginInvoke(new MethodInvoker(delegate ()
{
- int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
+ //int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
- richTextBox1.AppendText(logStr);
+ // richTextBox1.AppendText(logStr);
// 设置回原来的滚动位置
- richTextBox1.SelectionStart = richTextBox1.TextLength;
- richTextBox1.ScrollToCaret();
+ // richTextBox1.SelectionStart = richTextBox1.TextLength;
+ //richTextBox1.ScrollToCaret();
}));
//重新生成实例 销毁之前的实例
var saveData = temp.GetProductData();
diff --git a/DHSoftware/MainWindow.resx b/DHSoftware/MainWindow.resx
index ea83a3c..1a56e4c 100644
--- a/DHSoftware/MainWindow.resx
+++ b/DHSoftware/MainWindow.resx
@@ -1,7 +1,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+ 182, 17
+
+
\ No newline at end of file