DHDHSoftware/DHSoftware/MainWindow.cs

1590 lines
55 KiB
C#
Raw Normal View History

2025-03-07 09:06:46 +08:00
using AntdUI;
using AntdUI.Svg;
2025-03-21 08:51:20 +08:00
using DH.Commons.Base;
2025-03-12 09:21:06 +08:00
using DH.Commons.Enums;
2025-03-21 08:51:20 +08:00
using DH.Commons.Helper;
using DH.Commons.Models;
2025-03-07 09:06:46 +08:00
using DH.Devices.Camera;
2025-03-12 09:21:06 +08:00
using DH.Devices.Motion;
2025-03-07 09:06:46 +08:00
using DH.Devices.PLC;
using DH.Devices.Vision;
using DHSoftware.Languages;
using DHSoftware.Models;
using DHSoftware.Utils;
2025-03-13 18:54:05 +08:00
using DHSoftware.Views;
2025-03-07 09:06:46 +08:00
using DVPCameraType;
2025-03-12 09:21:06 +08:00
using HalconDotNet;
2025-04-01 18:15:30 +08:00
using Microsoft.VisualBasic.Logging;
2025-03-07 09:06:46 +08:00
using Microsoft.Win32;
using OpenCvSharp;
2025-03-27 15:30:52 +08:00
using SqlSugar;
2025-03-07 09:06:46 +08:00
using System;
using System.CodeDom;
using System.Collections.Concurrent;
using System.Collections.Generic;
2025-04-10 14:08:55 +08:00
using System.ComponentModel;
2025-03-07 16:29:38 +08:00
using System.Diagnostics;
2025-03-07 09:06:46 +08:00
using System.Drawing;
using System.Linq;
2025-04-10 14:08:55 +08:00
using System.Runtime.CompilerServices;
2025-03-07 09:06:46 +08:00
using System.Runtime.InteropServices;
2025-03-10 17:18:45 +08:00
using System.Text;
using System.Threading;
2025-03-07 09:06:46 +08:00
using System.Threading.Tasks;
using System.Windows.Forms;
2025-03-16 13:11:08 +08:00
using XKRS.UI.Device.Winform;
2025-03-07 09:06:46 +08:00
using static AntdUI.Math3D;
2025-03-24 15:21:16 +08:00
using static DH.Commons.Enums.EnumHelper;
2025-03-07 09:06:46 +08:00
using Camera = DHSoftware.Models.Camera;
2025-04-01 18:15:30 +08:00
using LogLevel = DH.Commons.Enums.EnumHelper.LogLevel;
2025-03-24 15:21:16 +08:00
using ResultState = DH.Commons.Base.ResultState;
2025-04-10 14:08:55 +08:00
using Timer = System.Threading.Timer;
2025-03-07 09:06:46 +08:00
namespace DHSoftware
{
public partial class MainWindow : AntdUI.Window
{
2025-03-24 19:24:16 +08:00
private Dictionary<string, List<string>> _cameraRelatedDetectionDict = null;
2025-04-01 18:15:30 +08:00
public event Action<LogMsg> OnLog;
2025-04-10 14:08:55 +08:00
public List<CameraSummary> CameraSummaries { get; set; } = new List<CameraSummary>();
public List<ProductSummary> ProductSummaries = new List<ProductSummary>();
static object _productSummaryLock = new object();
public event Action<DateTime, object, string> OnUpdateResult;
public event Action<DateTime, object, string> OnUpdateCamResult;
2025-03-24 15:20:33 +08:00
private string _loginName;
2025-03-24 19:24:16 +08:00
2025-03-24 15:20:33 +08:00
public string LoginName
{
get { return _loginName; }
set
{
_loginName = value;
UpdateLabel();
}
}
2025-03-24 19:24:16 +08:00
2025-03-24 15:20:33 +08:00
private bool _ShowConfig;
2025-03-24 19:24:16 +08:00
2025-03-24 15:20:33 +08:00
public bool ShowConfig
{
get { return _ShowConfig; }
set
{
_ShowConfig = value;
UpdateConfig();
}
}
2025-03-24 19:24:16 +08:00
private bool _addscheme;
2025-03-24 15:20:33 +08:00
2025-03-24 19:24:16 +08:00
public bool Addscheme
{
get { return _addscheme; }
set
{
_addscheme = value;
UpdateScheme();
2025-03-24 15:20:33 +08:00
}
2025-03-24 19:24:16 +08:00
}
private bool _deletescheme;
public bool Deleteschememe
{
get { return _deletescheme; }
set
2025-03-24 15:20:33 +08:00
{
2025-03-24 19:24:16 +08:00
_deletescheme = value;
2025-03-24 15:20:33 +08:00
UpdateScheme();
}
2025-03-24 19:24:16 +08:00
}
private bool _loadscheme;
public bool Loadscheme
{
get { return _loadscheme; }
set
2025-03-24 15:20:33 +08:00
{
2025-03-24 19:24:16 +08:00
_loadscheme = value;
2025-03-24 15:20:33 +08:00
UpdateScheme();
}
2025-03-24 19:24:16 +08:00
}
2025-03-24 15:20:33 +08:00
private void UpdateScheme()
{
if (this.InvokeRequired)
{
this.Invoke(new Action(UpdateScheme));
return;
}
2025-03-24 19:24:16 +08:00
if (Loadscheme)
2025-03-24 15:20:33 +08:00
{
btnDeleteProject.Visible = true;
}
else
{
btnDeleteProject.Visible = false;
}
if (Addscheme)
{
btnAddProject.Visible = true;
}
else
{
btnAddProject.Visible = false;
}
if (Deleteschememe)
{
btnLoadProject.Visible = true;
}
else
{
btnLoadProject.Visible = false;
}
}
private void UpdateLabel()
{
if (lbName.InvokeRequired)
{
lbName.Invoke(new Action(UpdateLabel));
return;
}
lbName.Text = _loginName;
}
2025-03-24 19:24:16 +08:00
2025-03-24 15:20:33 +08:00
private void UpdateConfig()
{
if (ShowConfig)
{
if (segmented1.InvokeRequired)
{
segmented1.Invoke(new Action(UpdateConfig));
return;
}
// 恢复显示时
segmented1.Items.Insert(4, itemToHide);
}
else
{
if (segmented1.InvokeRequired)
{
segmented1.Invoke(new Action(UpdateConfig));
return;
}
segmented1.Items.Remove(itemToHide);
}
}
2025-03-24 19:24:16 +08:00
2025-03-07 09:06:46 +08:00
public MainWindow()
{
InitializeComponent();
2025-04-11 10:42:40 +08:00
//refreshTimer.Start();
2025-03-07 09:06:46 +08:00
//初始化数据
InitData();
//绑定事件
BindEventHandler();
2025-03-25 13:56:48 +08:00
//UserConfigFrm userControlFrm = new UserConfigFrm();
2025-03-24 19:24:16 +08:00
2025-03-25 13:56:48 +08:00
//userControlFrm.Window = this;
//userControlFrm.Dock = DockStyle.Fill;
//tabPage2.Controls.Add(userControlFrm);
2025-03-07 09:06:46 +08:00
}
2025-04-10 14:08:55 +08:00
//#region OEE
// public event Action<RunState> OnProcessRunStateChanged;
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public virtual void Set<T>(ref T field, T newValue, [CallerMemberName] string propName = null)
{
if (!field.Equals(newValue))
{
field = newValue;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
}
#endregion
#region Properties
private int uph = 0;
private int upm = 0;
private DateTime? startTime = null;
private TimeSpan runTime = new TimeSpan();
private TimeSpan idleTime = new TimeSpan();
private TimeSpan downTime = new TimeSpan();
private TimeSpan totalTime = new TimeSpan();
private int qty_OEE = 0;
private int qty_OEE_OK = 0;
private float oee = 0;
public int UPH
{
get => uph;
set => Set(ref uph, value);
}
public int UPM
{
get => upm;
set => Set(ref upm, value);
}
public DateTime? StartTime
{
get => startTime;
set => Set(ref startTime, value);
}
/// <summary>
/// 有效运行时间
/// </summary>
public TimeSpan RunTime
{
get => runTime;
set => Set(ref runTime, value);
}
/// <summary>
/// 空闲待机时间
/// </summary>
public TimeSpan IdleTime
{
get => idleTime;
set => Set(ref idleTime, value);
}
/// <summary>
/// 故障宕机时间
/// </summary>
public TimeSpan DownTime
{
get => downTime;
set => Set(ref downTime, value);
}
/// <summary>
/// 总开机时间
/// </summary>
public TimeSpan TotalTime
{
get => totalTime;
set => Set(ref totalTime, value);
}
public float OEE
{
get => oee;
set => Set(ref oee, value);
}
#endregion
#region Timer
System.Threading.Timer _runTimer = null;
System.Threading.Timer _idleTimer = null;
System.Threading.Timer _downTimer = null;
System.Threading.Timer _checkIdleTimer = null;
//System.Threading.Timer _calculateTimer = null;
private RunState? currentState = null;
public RunState? CurrentState
{
get => currentState;
set
{
if (value != null)
{
if (value.Value == RunState.Running)
{
_checkIdleTimer?.Change(10 * 1000, -1);
}
if (currentState != value.Value)
{
switch (currentState)
{
case RunState.Idle:
//AddRunEventInBuffer(DateTime.Now, RunEvent_EventType.Idle, false);
break;
case RunState.Down:
//AddRunEventInBuffer(DateTime.Now, RunEvent_EventType.Down, false);
break;
}
switch (value.Value)
{
case RunState.Stop:
_runTimer?.Change(-1, -1);
_idleTimer?.Change(-1, -1);
_downTimer?.Change(-1, -1);
break;
case RunState.Running:
_idleTimer?.Change(-1, -1);
_downTimer?.Change(-1, -1);
_runTimer?.Change(0, 1000);
break;
case RunState.Idle:
_runTimer?.Change(-1, -1);
_downTimer?.Change(-1, -1);
_idleTimer?.Change(0, 1000);
//AddRunEventInBuffer(DateTime.Now, RunEvent_EventType.Idle, true);
break;
case RunState.Down:
_idleTimer?.Change(-1, -1);
_runTimer?.Change(-1, -1);
_downTimer?.Change(0, 1000);
//AddRunEventInBuffer(DateTime.Now, RunEvent_EventType.Down, true);
break;
}
currentState = value;
}
}
}
}
private void CheckIdleTimeStart(object state)
{
if (CurrentState == RunState.Running)
{
RunTime = RunTime.Add(new TimeSpan(0, 0, 0 - 10));
IdleTime = IdleTime.Add(new TimeSpan(0, 0, 10));
CurrentState = RunState.Idle;
}
}
public void InitialOEEStatistic()
{
InitialStatisticTimers();
ResetOEETimeDistribute();
ResetProductSummaries();
}
public void ResetProductSummaries()
{
ProductSummaries = new List<ProductSummary>();
}
private void InitialStatisticTimers()
{
if (_checkIdleTimer == null)
{
_checkIdleTimer = new Timer(new TimerCallback(CheckIdleTimeStart), null, -1, -1);
}
if (_runTimer == null)
{
_runTimer = new System.Threading.Timer(RunTimerCallBack, null, -1, -1);
}
if (_idleTimer == null)
{
_idleTimer = new System.Threading.Timer(IdleTimerCallBack, null, -1, -1);
}
if (_downTimer == null)
{
_downTimer = new System.Threading.Timer(DownTimerCallBack, null, -1, -1);
}
StartTime = DateTime.Now;
DownTime = IdleTime = RunTime = new TimeSpan(0, 0, 0);
CurrentState = RunState.Running;
}
private void DownTimerCallBack(object state)
{
DownTime = DownTime.Add(new TimeSpan(0, 0, 1));
GetTotalTime();
}
private void IdleTimerCallBack(object state)
{
IdleTime = IdleTime.Add(new TimeSpan(0, 0, 1));
GetTotalTime();
}
private void RunTimerCallBack(object state)
{
RunTime = RunTime.Add(new TimeSpan(0, 0, 1));
GetTotalTime();
}
private void GetTotalTime()
{
TotalTime = RunTime + IdleTime + DownTime;
}
public void ResetOEETimeDistribute()
{
StartTime = DateTime.Now;
DownTime = IdleTime = RunTime = new TimeSpan(0, 0, 0);
ProductNum_Total = ProductNum_OK = 0;
}
public void CloseStatisticTimers()
{
CloseTimer(ref _checkIdleTimer);
CloseTimer(ref _runTimer);
CloseTimer(ref _idleTimer);
CloseTimer(ref _downTimer);
CurrentState = RunState.Stop;
}
private void CloseTimer(ref System.Threading.Timer timer)
{
timer?.Change(-1, -1);
timer?.Dispose();
timer = null;
}
#endregion
#region CameraSum
private void InitialCameraSumsView()
{
dgvProductNums.AutoGenerateColumns = false;
dgvProductNums.DefaultCellStyle.Font = new Font("Tahoma", 12, FontStyle.Regular, GraphicsUnit.World);
dgvProductNums.DataSource = null;
dgvProductNums.DataSource = ProductSummaries;
dgvCamreaNums.AutoGenerateColumns = false;
dgvCamreaNums.DefaultCellStyle.Font = new Font("Tahoma", 12, FontStyle.Regular, GraphicsUnit.World);
dgvCamreaNums.DataSource = null;
dgvCamreaNums.Columns.Clear();
// 添加 CCD 列
dgvCamreaNums.Columns.Add(new DataGridViewTextBoxColumn
{
HeaderText = "CCD",
DataPropertyName = "CameraName"
});
// 添加 合格 列
var okColumn = new DataGridViewTextBoxColumn
{
HeaderText = "合格",
DataPropertyName = "OKCount"
};
okColumn.DefaultCellStyle.ForeColor = Color.LightGreen; // 设置背景为绿色
dgvCamreaNums.Columns.Add(okColumn);
// 添加 不合格 列
var ngColumn = new DataGridViewTextBoxColumn
{
HeaderText = "不合格",
DataPropertyName = "NGCount"
};
ngColumn.DefaultCellStyle.ForeColor = Color.LightCoral; // 设置背景为红色
dgvCamreaNums.Columns.Add(ngColumn);
// 添加 总数 列
dgvCamreaNums.Columns.Add(new DataGridViewTextBoxColumn
{
HeaderText = "总数",
DataPropertyName = "TotalCount"
});
// 添加 良率 列
dgvCamreaNums.Columns.Add(new DataGridViewTextBoxColumn
{
HeaderText = "良率",
DataPropertyName = "YieldStr"
});
dgvCamreaNums.DataSource = new BindingList<CameraSummary>(CameraSummaries);
}
#endregion
2025-03-07 09:06:46 +08:00
/// <summary>
/// 窗体对象实例
/// </summary>
private static MainWindow _instance;
2025-03-24 19:24:16 +08:00
internal static MainWindow Instance
{
get
{
if (_instance == null)
_instance = new MainWindow();
return _instance;
}
}
2025-03-24 19:24:16 +08:00
private SegmentedItem itemToHide;
2025-03-21 08:51:20 +08:00
private void InitData()
2025-03-07 09:06:46 +08:00
{
2025-03-24 15:20:33 +08:00
itemToHide = segmented1.Items[4];
segmented1.Items.Remove(itemToHide);
2025-03-07 09:06:46 +08:00
}
public void LoadScheme()
2025-03-07 09:06:46 +08:00
{
2025-03-21 08:51:20 +08:00
try
{
//方案配置初始化
SchemeHelper.Initialize();
//读取方案列表
List<string> list = SchemeHelper.GetAllSchemes();
string CurrentScheme = "默认方案";
//如果是空,新增默认数据
if (list == null || list.Count <= 0)
{
2025-03-24 19:24:16 +08:00
list = new() { CurrentScheme };
2025-03-21 08:51:20 +08:00
//显示到方案列表
sltProjects.Items.Clear();
sltProjects.Items.Add(CurrentScheme);
//保存到方案配置
SchemeHelper.AddScheme(CurrentScheme);
SchemeHelper.SetCurrentScheme(CurrentScheme);
//新构建配置文件
ConfigHelper.InitializeScheme(CurrentScheme);
sltProjects.SelectedIndex = 0;
}
else
{
foreach (string s in list)
{
sltProjects.Items.Add(s);
}
CurrentScheme = SchemeHelper.GetCurrentScheme();
sltProjects.SelectedValue = CurrentScheme;
}
SystemModel.CurrentScheme = CurrentScheme;
//加载当前方案配置
ConfigHelper.LoadConfig();
}
2025-03-24 19:24:16 +08:00
catch (Exception ex)
2025-03-21 08:51:20 +08:00
{
AntdUI.Message.error(this, ex.Message, autoClose: 3);
}
2025-03-07 09:06:46 +08:00
}
public void ConnectCamera()
{
Cameras.Clear();
HKCameras.Clear();
if (ConfigModel.CameraBaseList.Count > 0)
{
for (int i = 0; i < ConfigModel.CameraBaseList.Count; i++)
{
var cameraBase = ConfigModel.CameraBaseList[i];
if (cameraBase.CamType == EnumCamType.Do3think)
{
2025-04-02 18:26:34 +08:00
Do3ThinkCamera cam =new Do3ThinkCamera();
cam.IsSavePicEnabled = cameraBase.IsSavePicEnabled;
cam.CameraName = cameraBase.CameraName;
cam.CameraIP = cameraBase.CameraIP;
cam.IsEnabled = cameraBase.IsEnabled;
2025-04-11 10:42:40 +08:00
cam.ImageSaveDirectory = Path.Combine("D://Projects", cameraBase.CameraName);
Cameras.Add(cam);
2025-04-02 18:26:34 +08:00
if(cameraBase.IsEnabled)
{
cam.OnLog -= _visionEngine_OnLog;
cam.OnLog += _visionEngine_OnLog;
cam.CameraConnect();
cam.OnHImageOutput += OnCameraHImageOutput;
}
}
else if (cameraBase.CamType == EnumCamType.hik)
{
HikVisionCamera cam = new HikVisionCamera();
cam.CameraName = cameraBase.CameraName;
cam.CameraIP = cameraBase.CameraIP;
cam.IsEnabled = cameraBase.IsEnabled;
HKCameras.Add(cam);
// cam.CameraConnect();
//cam.OnHImageOutput += OnCameraHImageOutput;
}
}
}
}
public void ConnectPLC()
{
if (ConfigModel.PLCBaseList.Count > 0)
{
for (int i = 0; i < ConfigModel.PLCBaseList.Count; i++)
{
var plcBase = ConfigModel.PLCBaseList[i];
2025-03-27 11:37:48 +08:00
if (plcBase.PLCType == EnumPLCType.XC网口 || plcBase.PLCType == EnumPLCType.XD网口)
{
PLC.IP = plcBase.IP;
2025-03-25 13:56:48 +08:00
PLC.PLCType = plcBase.PLCType;
PLC.Enable = plcBase.Enable;
PLC.PLCName = plcBase.PLCName;
PLC.PLCItemList = plcBase.PLCItemList;
PLC.Port = plcBase.Port;
2025-04-01 18:15:30 +08:00
PLC.OnLog -= _visionEngine_OnLog;
PLC.OnLog += _visionEngine_OnLog;
PLC.PLCConnect();
}
}
}
}
2025-04-01 18:15:30 +08:00
FrmLog frmLog;
public void InitModel()
{
Dectection.Clear();
_cameraRelatedDetectionDict = new();
if (ConfigModel.DetectionList.Count > 0)
{
for (int i = 0; i < ConfigModel.DetectionList.Count; i++)
{
DetectionConfig detectionConfig = ConfigModel.DetectionList[i];
var detection = ConfigModel.DetectionList[i];
detectionConfig.CameraCollects = detection.CameraCollects;
detectionConfig.ModelconfThreshold = detection.ModelconfThreshold;
detectionConfig.ModelWidth = detection.ModelWidth;
detectionConfig.ModelHeight = detection.ModelHeight;
detectionConfig.In_lable_path = detection.In_lable_path;
detectionConfig.IsEnabled = detection.IsEnabled;
2025-04-01 18:15:30 +08:00
2025-03-27 15:11:48 +08:00
detectionConfig.ShowLocation.X = (i + 1) % 5 + (i + 1) / 5;
// detectionConfig.ShowLocation.X = detection.ShowLocation.X;
detectionConfig.ShowLocation.Y = (i + 1) / 5 + 1;
// detectionConfig.ShowLocation.Y = detection.ShowLocation.Y;
DetectionConfigs.Add(detectionConfig);
}
}
DetectionConfigs.ForEach(detection =>
{
detection.CameraCollects.ForEach(cam =>
{
List<string> Dets = new List<string>
{
detection.Id
};
if (!_cameraRelatedDetectionDict.ContainsKey(cam.CameraSourceId))
{
_cameraRelatedDetectionDict.Add(cam.CameraSourceId, Dets);
}
else
{
_cameraRelatedDetectionDict[cam.CameraSourceId].Add(detection.Id);
}
}
);
});
string inferenceDevice = "CPU";
2025-04-01 18:15:30 +08:00
frmLog = new FrmLog();
frmLog.Dock = DockStyle.Fill;
pnlLog.Controls.Add(frmLog);
//
_visionEngine = new SimboVisionDriver();
_visionEngine.DetectionConfigs = DetectionConfigs;
2025-04-11 10:42:40 +08:00
_visionEngine.LoggerHelper .LogPath = "D://PROJECTS//Logs//";
_visionEngine.LoggerHelper.LogPrefix = "Vision";
2025-04-01 18:15:30 +08:00
_visionEngine.OnLog += _visionEngine_OnLog;
//初始化模型 加载模型
_visionEngine.Init();
2025-04-01 18:15:30 +08:00
CtrlVisionRunBase ctrlVisionRun = new CtrlVisionRunBase(_visionEngine);
2025-03-25 13:56:48 +08:00
ctrlVisionRun.Dock = DockStyle.Fill;
tabImgDisplay.Controls.Add(ctrlVisionRun);
2025-04-01 18:15:30 +08:00
}
private void _visionEngine_OnLog(LogMsg msg)
{
2025-04-11 10:42:40 +08:00
//OnLog?.Invoke(msg);
2025-04-01 18:15:30 +08:00
LogDisplay(msg);
}
private void LogDisplay(LogMsg msg)
{
frmLog?.LogDisplay(msg);
}
2025-04-01 18:15:30 +08:00
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);
//}
2025-03-24 19:24:16 +08:00
2025-04-01 18:15:30 +08:00
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));
}
2025-04-11 10:42:40 +08:00
System.Windows.Forms.Timer _refreshUITimer = new System.Windows.Forms.Timer();
2025-03-07 09:06:46 +08:00
private void BindEventHandler()
{
2025-03-21 08:51:20 +08:00
btnAddProject.Click += BtnAddProject_Click;
btnDeleteProject.Click += BtnDeleteProject_Click;
2025-03-24 15:20:33 +08:00
btnLoadProject.Click += BtnLoadProject_Click;
2025-04-11 10:42:40 +08:00
LoggerHelper.LogPath = "D://PROJECTS//Logs//";
2025-04-01 18:15:30 +08:00
LoggerHelper.LogPrefix = "Process";
OnLog -= LogDisplay;
OnLog += LogDisplay;
2025-04-10 14:08:55 +08:00
OnUpdateCamResult -= UpdateCamResult;
OnUpdateCamResult += UpdateCamResult;
OnUpdateResult -= UpdateResult;
OnUpdateResult += UpdateResult;
2025-04-11 10:42:40 +08:00
Load += (s, e) =>
{
_refreshUITimer.Interval = 1000;
_refreshUITimer.Tick += _refreshUITimer_Tick;
_refreshUITimer.Enabled = true;
};
}
private void _refreshUITimer_Tick(object sender, EventArgs e)
{
_refreshUITimer.Enabled = false;
if (this != null)
{
lblStartTime.Text = StartTime == null ? "" : StartTime.Value.ToString("yyyy/MM/dd HH:mm:ss");
lblTotalTime.Text = TotalTime.ToString(); // 运行时间
// lblRunTime.Text = RunTime.ToString(); // 有效时间
// lblIdleTime.Text = ProcessControl.IdleTime.ToString(); // 空闲时间
// lblDownTime.Text = ProcessControl.DownTime.ToString(); // 宕机时间
lblOEE_Total.Text = ProductNum_Total.ToString();
// lblOEE_OK.Text = ProcessControl.ProductNum_OK.ToString();
}
_refreshUITimer.Enabled = true;
2025-04-10 14:08:55 +08:00
}
private void UpdateCamResult(DateTime updateTime, object objData, string customMessage)
{
this.Invoke(new Action(() =>
{
BindingList<CameraSummary> cameraSummaries = new BindingList<CameraSummary>(CameraSummaries);
dgvCamreaNums.DataSource = cameraSummaries;
}));
}
private void UpdateResult(DateTime updateTime, object objData, string result)
{
this.Invoke(new Action(() =>
{
2025-04-11 10:42:40 +08:00
dgvProductNums.DataSource = new BindingList<ProductSummary>(ProductSummaries);
//if (dgvProductNums.Rows.Count > 0)
//{
// dgvProductNums.Height = dgvProductNums.Rows[0].Height * dgvProductNums.Rows.Count + 15;
//}
//else
//{
// dgvProductNums.Height = 35;
//}
2025-04-10 14:08:55 +08:00
//lblOEE_Rate.Text = ProcessControl.OEE.ToString("f2") + " %";
lblUPH.Text = UPH.ToString();
}));
2025-03-07 09:06:46 +08:00
}
2025-03-21 08:51:20 +08:00
private void BtnDeleteProject_Click(object? sender, EventArgs e)
{
try
{
if (sltProjects.Items.Count == 0 || sltProjects.SelectedIndex == -1) return;
2025-03-07 09:06:46 +08:00
2025-03-21 08:51:20 +08:00
var result = AntdUI.Modal.open(this, "删除警告!", "确认要删除该方案吗?", TType.Warn);
if (result == DialogResult.OK)
{
int selectedIndex = sltProjects.SelectedIndex;
// 删除当前选中项
SchemeHelper.DeleteScheme(sltProjects.Text);
ConfigHelper.DeleteSchemeConfig(sltProjects.Text);
AntdUI.Message.success(this, $"删除方案{sltProjects.Text}成功!", autoClose: 3);
sltProjects.Items.RemoveAt(selectedIndex);
// 自动选择下一个(如果存在)
if (sltProjects.Items.Count > 0)
{
// 如果删除的不是最后一项,则选中原位置的新项,否则选中最后一项
sltProjects.SelectedIndex = selectedIndex < sltProjects.Items.Count
? selectedIndex
: sltProjects.Items.Count - 1;
2025-03-07 09:06:46 +08:00
2025-03-21 08:51:20 +08:00
SystemModel.CurrentScheme = sltProjects.Text;
SchemeHelper.SetCurrentScheme(SystemModel.CurrentScheme);
//加载当前方案配置
ConfigHelper.LoadConfig();
}
else
{
sltProjects.SelectedIndex = -1; // 清空选择
AntdUI.Modal.open(this, "空方案警告!", "当前方案全部删除,需重启程序!", TType.Warn);
}
}
}
2025-03-24 19:24:16 +08:00
catch (Exception ex)
2025-03-07 09:06:46 +08:00
{
2025-03-21 08:51:20 +08:00
AntdUI.Message.error(this, ex.Message, autoClose: 3);
2025-03-07 09:06:46 +08:00
}
}
2025-03-21 08:51:20 +08:00
private void BtnLoadProject_Click(object? sender, EventArgs e)
2025-03-07 09:06:46 +08:00
{
2025-03-21 08:51:20 +08:00
try
{
if (sltProjects.Items.Count == 0 || sltProjects.SelectedIndex == -1) return;
if (SystemModel.CurrentScheme == sltProjects.Text)
{
AntdUI.Message.warn(this, "当前已是该方案,无需重复载入!", autoClose: 3);
return;
}
//修改当前软件当前方案
SystemModel.CurrentScheme = sltProjects.Text;
//修改配置当前方案
SchemeHelper.SetCurrentScheme(SystemModel.CurrentScheme);
//将配置文件替换为当前方案
ConfigHelper.LoadConfig();
AntdUI.Message.success(this, $"载入方案{SystemModel.CurrentScheme}成功!", autoClose: 3);
}
2025-03-24 19:24:16 +08:00
catch (Exception ex)
{
2025-03-21 08:51:20 +08:00
AntdUI.Message.error(this, ex.Message, autoClose: 3);
}
2025-03-07 09:06:46 +08:00
}
2025-03-21 08:51:20 +08:00
private void BtnAddProject_Click(object? sender, EventArgs e)
2025-03-07 09:06:46 +08:00
{
2025-03-21 08:51:20 +08:00
try
{
var form = new AddSchemeControl(this, "新增方案操作") { Size = new System.Drawing.Size(400, 300) };
AntdUI.Modal.open(new AntdUI.Modal.Config(this, "", form, TType.None)
{
BtnHeight = 0,
});
if (form.submit)
{
string SchemeName = form.SchemeName;
//保存到方案配置
SchemeHelper.AddScheme(SchemeName);
if (form.NullScheme)
{
//新构建配置文件
ConfigHelper.InitializeScheme(SchemeName);
}
else
{
//派生当前方案
ConfigHelper.DeriveScheme(SchemeName);
}
//刷新方案列表
sltProjects.Items.Clear();
List<string> list = SchemeHelper.GetAllSchemes();
foreach (string s in list)
{
sltProjects.Items.Add(s);
}
string CurrentScheme = SchemeHelper.GetCurrentScheme();
sltProjects.SelectedValue = CurrentScheme;
AntdUI.Message.success(this, $"新增方案{SchemeName}成功!", autoClose: 3);
}
}
catch (Exception ex)
{
AntdUI.Message.error(this, ex.Message, autoClose: 3);
}
2025-03-24 19:24:16 +08:00
}
2025-03-07 09:06:46 +08:00
2025-03-24 15:21:16 +08:00
public List<HikVisionCamera> HKCameras { get; } = new List<HikVisionCamera>();
2025-03-07 09:06:46 +08:00
public List<Do3ThinkCamera> Cameras { get; } = new List<Do3ThinkCamera>();
public Dictionary<string, SimboObjectDetection> Dectection { get; } = new Dictionary<string, SimboObjectDetection>();
2025-03-24 15:21:16 +08:00
public XinJEPLCTcpNet PLC { get; } = XinJEPLCTcpNet.Instance;
2025-03-24 19:24:16 +08:00
private SLDMotion sLDMotion = new SLDMotion();
2025-03-07 09:06:46 +08:00
private void MainWindow_Load(object sender, EventArgs e)
{
}
2025-03-24 19:24:16 +08:00
private bool _isClosing = false; // 状态标志
2025-03-24 19:24:16 +08:00
private void MainWindow_FormClosing(object sender, FormClosingEventArgs e)
2025-03-07 09:06:46 +08:00
{
if (_isClosing) return;
_isClosing = true;
// 取消默认关闭行为
e.Cancel = true;
// 立即隐藏主窗口
this.Hide();
// 显示关闭界面
2025-03-24 19:24:16 +08:00
CloseWindow.Instance.Show();
Thread.Sleep(200);
try
2025-03-24 19:24:16 +08:00
{
// 执行关闭操作
foreach (var camera in Cameras)
{
2025-03-24 19:24:16 +08:00
camera.CameraDisConnect();
}
foreach (var camera in HKCameras)
{
2025-03-24 19:24:16 +08:00
camera.CameraDisConnect();
}
2025-03-26 11:37:23 +08:00
if (PLC != null)
2025-03-27 15:11:48 +08:00
{
PLC.CloseProcess();
}
2025-03-27 18:03:07 +08:00
_visionEngine.Stop();//释放模型
2025-03-24 19:24:16 +08:00
CloseWindow.Instance.Close();// 关闭提示窗口
//Application.Exit();
System.Environment.Exit(0);
2025-03-10 17:18:45 +08:00
}
2025-03-24 19:24:16 +08:00
catch (Exception ex)
{
CloseWindow.Instance.Close();
2025-03-24 19:24:16 +08:00
System.Environment.Exit(0);
}
2025-03-07 09:06:46 +08:00
}
private void segmented1_SelectIndexChanged(object sender, EventArgs e)
{
// Get the index of the selected item
int selectedIndex = segmented1.SelectIndex;
// Handle each button based on its index
switch (selectedIndex)
{
case 0: // "启动" (Start)
HandleStartButton();
break;
2025-03-24 19:24:16 +08:00
2025-03-07 09:06:46 +08:00
case 1: // "停止" (Stop)
HandleStopButton();
break;
2025-03-24 19:24:16 +08:00
2025-03-07 09:06:46 +08:00
case 2: // "复位" (Reset)
HandleResetButton();
break;
2025-03-24 19:24:16 +08:00
2025-03-07 09:06:46 +08:00
case 3: // "设置" (Settings)
2025-03-24 15:20:33 +08:00
HandleLoginButton();
2025-03-07 09:06:46 +08:00
break;
2025-03-24 19:24:16 +08:00
2025-03-07 09:06:46 +08:00
case 4: // "登录" (Login)
2025-03-24 15:20:33 +08:00
HandleSettingsButton();
2025-03-07 09:06:46 +08:00
break;
2025-03-24 19:24:16 +08:00
2025-03-07 09:06:46 +08:00
default:
break;
}
2025-03-21 08:51:20 +08:00
segmented1.SelectIndex = -1;
2025-03-07 09:06:46 +08:00
}
2025-03-24 19:24:16 +08:00
2025-03-07 09:06:46 +08:00
public bool CurrentMachine = false;
public volatile int ProductNum_Total = 0;
public volatile int ProductNum_OK = 0;
private readonly object _cameraSummaryLock = new object();
2025-03-16 13:11:08 +08:00
public SimboVisionDriver? _visionEngine = null;
2025-03-24 19:24:16 +08:00
2025-03-24 15:21:16 +08:00
public PLCBase? _PLCConfig = null;
2025-03-24 19:24:16 +08:00
private List<DetectionConfig> DetectionConfigs = new List<DetectionConfig>();
private List<SimboStationMLEngineSet> SimboStationMLEngineList = new List<SimboStationMLEngineSet>();
private Dictionary<string, HDevEngineTool> HalconToolDict = new Dictionary<string, HDevEngineTool>();
2025-03-07 16:29:38 +08:00
public List<RecongnitionLabel> RecongnitionLabelList { get; set; } = new List<RecongnitionLabel>();
2025-03-26 11:37:23 +08:00
public DateTime ProcessstartTime;
2025-03-24 19:24:16 +08:00
2025-03-07 09:06:46 +08:00
private void HandleStartButton()
{
2025-04-11 10:42:40 +08:00
InitialCameraSumsView();
2025-04-01 18:15:30 +08:00
LogAsync(DateTime.Now, LogLevel.Information, "流程启动中,请稍候...");
StartProcess();
2025-04-01 18:15:30 +08:00
LogAsync(DateTime.Now, LogLevel.Action, "流程启动完成!");
2025-03-24 15:21:16 +08:00
}
2025-03-24 19:24:16 +08:00
2025-03-27 11:37:48 +08:00
2025-03-24 19:24:16 +08:00
2025-03-24 15:21:16 +08:00
private void StartProcess()
{
2025-03-27 15:11:48 +08:00
ProcessstartTime = DateTime.Now;
2025-04-11 10:42:40 +08:00
lblStartTime.Text = ProcessstartTime.ToString("yyyy-MM-dd HH:mm:ss");
2025-03-24 15:21:16 +08:00
//计数清零
PieceCount = 0;
2025-03-27 11:37:48 +08:00
2025-03-27 15:11:48 +08:00
2025-03-25 13:56:48 +08:00
if (PLC?.Enable == true)
2025-03-24 15:21:16 +08:00
{
2025-03-25 13:56:48 +08:00
PLC.OnNewPieces -= MainMotion_NewPieces;
PLC.OnNewPieces += MainMotion_NewPieces;
2025-03-24 15:21:16 +08:00
}
2025-04-02 18:26:34 +08:00
Cameras.ForEach(d =>
2025-03-24 15:21:16 +08:00
{
if (d is CameraBase cam)
{
cam.SnapshotCount = 0;
}
});
//PrepareBatchNO();
2025-03-24 19:24:16 +08:00
// isInPositionChecking = false;
2025-03-24 15:21:16 +08:00
//isFullTrayChecking = false;
//队列清空
2025-03-24 19:24:16 +08:00
// var temp = new List<ITriggerSet>();
// temp.AddRange(XKRSPLCConfig.TriggerConfigCollection);
// temp.AddRange(XKRSPLCConfig.SnapshotTriggerConfigCollection);
2025-03-24 15:21:16 +08:00
//temp.ForEach(t =>
//{
// var diskInfo = XKRSPLCConfig.DiskInfoList.FirstOrDefault(u => u.DiskName == t.DiskName);
// if (diskInfo != null)
// {
// t.AxisNum = diskInfo.DiskAxisNum;
// }
// else
// {
// t.AxisNum = -1;
// }
//});
//if (temp.Any(u => u.AxisNum < 0))
//{
// LogAsync(DateTime.Now, LogLevel.Error, "触发信号归属转盘未确认");
// return new ProcessResponse(false);
//}
2025-03-24 19:24:16 +08:00
// _diskInfoListInOrder = XKRSPLCConfig.DiskInfoList.OrderBy(u => u.DiskSequence).ToList();
// var axisNumList = _diskInfoListInOrder.Select(u => u.DiskAxisNum).ToList();
2025-03-24 15:21:16 +08:00
2025-03-24 19:24:16 +08:00
/// PrepareMLEngine();
2025-03-24 15:21:16 +08:00
2025-03-24 19:24:16 +08:00
// if (_PLCConfig?.Enable == true)
//挡料电机操作
// _PLC.FeedingMotor(_PLCConfig.CunToZeroSpeed, _PLCConfig.CunPos, _PLCConfig.CunSpeed, _PLCConfig.CunDirection);
2025-03-24 15:21:16 +08:00
//流程开启操作配置
2025-03-24 19:24:16 +08:00
// ProcessInitialAction();
// if (_PLC?Enabled == true)
//皮带
// _PLC.Belt(true);
2025-03-24 15:21:16 +08:00
//DeviceCollection.ForEach(d =>
//{
// if (d is CameraBase c)
// {
// c.OnHImageOutput -= OnCameraHImageOutput;
// c.OnHImageOutput += OnCameraHImageOutput;
// c.SnapshotCount = 0;
// }
//});
_productLists.Clear();
2025-03-24 19:24:16 +08:00
#region
2025-03-24 15:21:16 +08:00
//mOfflineImageTimer = new System.Timers.Timer();
//mOfflineImageTimer.Elapsed += OnEmitSerialPortAsync;
//mOfflineImageTimer.Interval = 1000;
//mOfflineImageTimer.Start();
2025-03-24 19:24:16 +08:00
#endregion
var settings = _visionEngine.DetectionConfigs.Where(u => u.IsEnabled && u.IsAddStation).ToList();
2025-03-24 15:21:16 +08:00
if (settings != null)
{
settings = settings.Where(s => s.IsEnabled).ToList();
ProductBaseCount = settings.Count;
for (int i = 0; i < ProductBaseCount * ProductListMulti; i++)
{
ConcurrentDictionary<uint, ProductData> products = new ConcurrentDictionary<uint, ProductData>();
_productLists.Add(products);
}
}
// _MGSCameraList = DeviceCollection
//.OfType<MGSCameraDriver>() // 直接筛选出 MGSCameraDriver 类型的元素
//.Where(camera => camera.IConfig != null && camera.IConfig.IsEnabled) // 进一步筛选 IConfig 不为 null 且 IsEnabled 为 true
//.ToList();
// ProductBaseCount = _MGSCameraList.Count;
2025-03-27 17:51:07 +08:00
2025-03-24 15:21:16 +08:00
2025-03-25 18:55:59 +08:00
//流程执行时PLC
2025-03-27 11:37:48 +08:00
PLC.StartProcess();
2025-04-11 10:42:40 +08:00
InitialOEEStatistic();
2025-03-24 15:21:16 +08:00
2025-03-27 15:11:48 +08:00
2025-03-24 15:21:16 +08:00
}
2025-03-27 15:11:48 +08:00
2025-03-07 09:06:46 +08:00
private uint PieceCount = 0;
private List<ConcurrentDictionary<uint, ProductData>> _productLists = new List<ConcurrentDictionary<uint, ProductData>>();
2025-03-27 17:51:07 +08:00
private int ProductListMulti = 1;
2025-03-07 09:06:46 +08:00
private int ProductBaseCount = 0;
2025-03-24 19:24:16 +08:00
2025-03-07 09:06:46 +08:00
private int PieceNumberToIndex(uint pn)
{
// 物料编号,取余 集合数量
2025-03-12 17:18:39 +08:00
2025-03-07 09:06:46 +08:00
int ret = (int)(pn % (ProductBaseCount * ProductListMulti));
return ret;
}
2025-03-24 19:24:16 +08:00
private DateTime _ctTime = DateTime.Now;
2025-03-07 09:06:46 +08:00
public async void MainMotion_NewPieces(int axisIndex, uint pieceNumber)
{
//if (MachineState != MachineState.Running && MachineState != MachineState.Warning)
//{
// return;
//}
PieceCount++;
int index = PieceNumberToIndex(pieceNumber);
// productDatas.Add(pData);
//转盘2 的物料是不是重新覆盖之前的pDta
if (axisIndex == 1)
{
ProductData pData = new ProductData("", pieceNumber, ProductBaseCount);
_productLists[index][pieceNumber] = pData;
2025-04-01 18:15:30 +08:00
LogAsync(DateTime.Now, LogLevel.Action, $">> 轴{axisIndex}新产品{pieceNumber}加入队列{index}----板卡计数{PieceCount}");
2025-03-07 09:06:46 +08:00
}
2025-04-01 18:15:30 +08:00
2025-03-07 09:06:46 +08:00
DateTime dtNow = DateTime.Now;
UpdateCT(null, (float)(dtNow - _ctTime).TotalSeconds);
_ctTime = dtNow;
}
2025-03-24 19:24:16 +08:00
2025-03-07 09:06:46 +08:00
public async Task UpdateCT(object objData, float ctTime)
{
await Task.Run(() =>
{
2025-03-12 17:18:39 +08:00
//OnUpdateCT?.Invoke(objData, ctTime);
2025-03-07 09:06:46 +08:00
});
}
2025-03-24 19:24:16 +08:00
2025-03-12 09:21:06 +08:00
/// <summary>
2025-03-16 13:11:08 +08:00
/// 相机回调
2025-03-12 09:21:06 +08:00
/// </summary>
2025-03-16 13:11:08 +08:00
/// <param name="dt"></param>
/// <param name="camera"></param>
/// <param name="imageSet"></param>
private void OnCameraHImageOutput(DateTime dt, CameraBase camera, MatSet imageSet)
2025-03-12 09:21:06 +08:00
{
2025-03-16 13:11:08 +08:00
//if (camera.CameraName.Equals("cam1", StringComparison.OrdinalIgnoreCase))
//{
// Console.WriteLine();
//}
//if (camera.CameraName.Equals("cam2", StringComparison.OrdinalIgnoreCase))
//{
// Console.WriteLine();
//}
2025-03-12 09:21:06 +08:00
2025-03-16 13:11:08 +08:00
// 获取该相机的拍照计数
uint productNumber = (uint)camera.SnapshotCount;
2025-03-12 17:18:39 +08:00
2025-03-16 13:11:08 +08:00
Task.Run(async () =>
2025-03-12 09:21:06 +08:00
{
//using (Mat localImageSet = imageSet._mat.Clone()) // 复制 Mat 避免并发问题
2025-03-12 09:21:06 +08:00
{
2025-03-16 13:11:08 +08:00
// imageSet?.Dispose();
// 拍照计数与物件编号一致,查找对应的产品
ProductData product = null;
//内外壁模组多个相机的处理方法
//计算队列的方法不变
int index = PieceNumberToIndex(productNumber);
// 找到产品存放在哪个队列里
ConcurrentDictionary<uint, ProductData> tmpDic = _productLists[index];
try
2025-03-12 09:21:06 +08:00
{
2025-03-16 13:11:08 +08:00
int retryTimes = 100;
while (product == null && retryTimes > 0)
2025-03-12 09:21:06 +08:00
{
2025-03-16 13:11:08 +08:00
if (tmpDic.ContainsKey(productNumber))
{
product = tmpDic[productNumber];
}
else
{
2025-03-27 17:51:07 +08:00
Thread.Sleep(20);
//await Task.Delay(20);
2025-03-16 13:11:08 +08:00
}
retryTimes--;
}
// 如果产品为空,则销毁图片,提示错误
if (null == product)
{
List<uint> pnList = tmpDic.Keys.ToList();
string pnStr = "";
if (pnList != null && pnList.Count > 0)
{
pnStr = string.Join(",", pnList);
}
//LogAsync(DateTime.Now, LogLevel.Error, $"{camera.Name} 未找到产品,编号:{productNumber},队列{index}数量:{tmpDic.Count},列表:{pnStr}");
imageSet.Dispose();
2025-04-01 18:15:30 +08:00
2025-03-16 13:11:08 +08:00
return;
2025-03-12 09:21:06 +08:00
}
2025-04-11 10:42:40 +08:00
LogAsync(DateTime.Now, LogLevel.Information, $"{camera.CameraName} 找到产品{productNumber},队列{index}数量:{tmpDic.Count}");
2025-03-12 09:21:06 +08:00
2025-03-16 13:11:08 +08:00
if (!_cameraRelatedDetectionDict.ContainsKey(camera.CameraName))
{
imageSet.Dispose();
2025-04-02 18:26:34 +08:00
2025-03-12 09:21:06 +08:00
2025-03-27 17:51:07 +08:00
2025-04-01 18:15:30 +08:00
LogAsync(DateTime.Now, LogLevel.Warning, $"{camera.CameraName} 找到产品{productNumber}但是没有推理1");
2025-03-10 17:18:45 +08:00
2025-03-16 13:11:08 +08:00
return;
}
2025-03-10 17:18:45 +08:00
2025-03-16 13:11:08 +08:00
double totalTime = 0.0;
List<ResultState> resultStates = new List<ResultState>();
List<string>? detectionDict = _cameraRelatedDetectionDict[camera.CameraName];
2025-03-27 17:51:07 +08:00
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
2025-03-16 13:11:08 +08:00
for (int i = 0; i < detectionDict.Count; i++)
{
string detectionId = detectionDict[i];
var tmpImgSet = camera.CopyImageSet(imageSet as MatSet);
//imageSet
// using (Mat inferenceImage = localImageSet.Clone()) // 仅在此处克隆,确保推理过程中 Mat 有独立副本
2025-03-16 13:11:08 +08:00
{
DetectStationResult temp1 = _visionEngine.RunInference(tmpImgSet, detectionId);
2025-03-10 13:41:12 +08:00
2025-03-16 13:11:08 +08:00
resultStates.Add(temp1.ResultState);
2025-03-10 17:18:45 +08:00
2025-03-16 13:11:08 +08:00
product.ResultCollection.Add(temp1);
}
}
2025-03-27 17:51:07 +08:00
stopwatch.Stop();
2025-04-10 14:08:55 +08:00
if (product.ResultCollection.Count != 0)
UpdateResultoverride(dt, camera, resultStates, totalTime, _cameraRelatedDetectionDict.Keys.Count);
2025-03-16 13:11:08 +08:00
product.InferenceOne();
2025-03-10 13:41:12 +08:00
2025-03-16 13:11:08 +08:00
// LogAsync(DateTime.Now, LogLevel.Information, $"{camera.Name} 推理完成,产品{productNumber}");
2025-03-07 16:29:38 +08:00
2025-03-16 13:11:08 +08:00
if (!product.InferenceFinished())
{
return;
}
2025-04-11 10:42:40 +08:00
2025-03-16 13:11:08 +08:00
#region 6.
2025-03-24 19:24:16 +08:00
2025-03-16 13:11:08 +08:00
product.ProductResult = product.ResultCollection.Any(u => u.ResultState != ResultState.OK)
? ResultState.B_NG
: ResultState.OK;
product.ProductLabelCategory = product.ProductResult.GetEnumDescription();
product.ProductLabel = product.ProductResult.GetEnumDescription();
2025-04-11 10:42:40 +08:00
UpdateResultPro(DateTime.Now, null, product.ProductResult.GetEnumDescription());
LogAsync(DateTime.Now, LogLevel.Information, $"产品{product.PieceNumber}获取结果:{product.ProductResult} {(product.IsA2B ? "IsA2B" : "")}");
if (product.ProductResult == ResultState.OK)
{
PLC.Blowing(productNumber, 1);
LogAsync(DateTime.Now, LogLevel.Action, $"产品{product.PieceNumber}PLC,OK吹气");
}
else
{
PLC.Blowing(productNumber, 2);
LogAsync(DateTime.Now, LogLevel.Action, $"产品{product.PieceNumber}PLC,NG吹气");
}
2025-03-10 17:18:45 +08:00
2025-03-24 19:24:16 +08:00
#endregion 6.
2025-03-12 09:21:06 +08:00
2025-03-24 19:24:16 +08:00
// 出列
2025-03-16 13:11:08 +08:00
ProductData temp = null;
2025-03-12 09:21:06 +08:00
2025-03-16 13:11:08 +08:00
int tryTimes = 10;
while (temp == null && tryTimes > 0)
{
if (tmpDic.TryRemove(productNumber, out temp))
{
break;
}
2025-03-12 09:21:06 +08:00
2025-03-16 13:11:08 +08:00
tryTimes--;
Thread.Sleep(5);
}
if (temp == null)
{
string logStr = $"{DateTime.Now}产品{productNumber}出列失败true" +
$"当前队列产品数量:{tmpDic.Count}";
this.BeginInvoke(new MethodInvoker(delegate ()
{
2025-04-01 18:15:30 +08:00
// int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
2025-03-12 17:18:39 +08:00
2025-04-01 18:15:30 +08:00
// richTextBox1.AppendText(logStr);
2025-03-12 17:18:39 +08:00
2025-03-16 13:11:08 +08:00
// 设置回原来的滚动位置
2025-04-01 18:15:30 +08:00
// richTextBox1.SelectionStart = richTextBox1.TextLength;
//richTextBox1.ScrollToCaret();
2025-03-16 13:11:08 +08:00
}));
}
else
{
try
{
string logStr = $"{DateTime.Now}产品{productNumber}出列成功true" +
$"产品结果:{temp.ProductResult.GetEnumDescription()}" +
$"当前队列产品数量:{tmpDic.Count}";
this.BeginInvoke(new MethodInvoker(delegate ()
{
2025-04-01 18:15:30 +08:00
//int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
2025-03-16 13:11:08 +08:00
2025-04-01 18:15:30 +08:00
// richTextBox1.AppendText(logStr);
2025-03-16 13:11:08 +08:00
// 设置回原来的滚动位置
2025-04-01 18:15:30 +08:00
// richTextBox1.SelectionStart = richTextBox1.TextLength;
//richTextBox1.ScrollToCaret();
2025-03-16 13:11:08 +08:00
}));
//重新生成实例 销毁之前的实例
var saveData = temp.GetProductData();
2025-04-11 10:42:40 +08:00
2025-03-16 13:11:08 +08:00
}
catch (Exception) { }
finally
{
// temp.Dispose();
temp = null;
}
}
2025-03-12 17:18:39 +08:00
2025-03-16 13:11:08 +08:00
// UpdateCT((float)(dtNow - _ctTime).TotalSeconds);
2025-03-24 19:24:16 +08:00
//_ctTime = dtNow;
2025-03-16 13:11:08 +08:00
// });
}
catch (Exception ex)
{
//LogAsync(DateTime.Now, LogLevel.Error, $"流程检测未捕获的异常:{ex.GetExceptionMessage()}");
product?.Dispose();
}
}
});
}
2025-04-10 14:08:55 +08:00
public virtual void AddOKProduct(string resultStr)
{
if (resultStr.ToLower() == "ok")
{
ProductNum_OK++;
}
}
public async Task UpdateResultoverride(DateTime dt, CameraBase objData, List<ResultState> resultStr, double total, int _cameraDictCount)
{
// CurrentState = RunState.Running;
// 根据相机名称找到对应的信息(假设有一个字典或其他集合保存相机相关信息)
var cameraName = objData?.CameraName; // 假设 CameraBase 有 Name 属性
if (string.IsNullOrEmpty(cameraName))
{
throw new ArgumentException("相机名称不能为空");
}
2025-03-10 13:41:12 +08:00
2025-04-10 14:08:55 +08:00
lock (_cameraSummaryLock)
{
// 查找或添加相机统计项
var summary = CameraSummaries.FirstOrDefault(c => c.CameraName == cameraName)
?? new CameraSummary { CameraName = cameraName };
if (!CameraSummaries.Contains(summary))
{
CameraSummaries.Add(summary);
}
if (resultStr.Any(u => u.ToString().ToLower() == "ok"))
{
summary.OKCount++;
}
else /*if (resultStr.Equals("TBD", StringComparison.OrdinalIgnoreCase))*/
{
summary.NGCount++;
}
}
await Task.Run(() =>
{
OnUpdateCamResult?.Invoke(dt, objData, "");
});
}
public async Task UpdateResultPro(DateTime dt, object objData, string resultStr)
2025-03-07 16:29:38 +08:00
{
2025-04-10 14:08:55 +08:00
CurrentState = RunState.Running;
2025-03-07 16:29:38 +08:00
2025-03-27 15:30:52 +08:00
ProductNum_Total++;
2025-04-10 14:08:55 +08:00
AddOKProduct(resultStr);
lock (_productSummaryLock)
{
var product = ProductSummaries.FirstOrDefault(u => u.ResultDesc == resultStr);
if (product != null)
{
product.ProductAmount++;
}
else
{
product = new ProductSummary();
product.ResultDesc = resultStr;
product.ProductAmount = 1;
2025-03-27 15:30:52 +08:00
2025-04-10 14:08:55 +08:00
ProductSummaries.Add(product);
}
int totalNum = ProductSummaries.Sum(p => p.ProductAmount);
ProductSummaries.ForEach(p => p.PercentStr = ((double)p.ProductAmount * 100.0 / totalNum).ToString("f2") + " %");
}
2025-03-27 15:30:52 +08:00
CalculateOEE();
2025-04-10 14:08:55 +08:00
await Task.Run(() =>
{
OnUpdateResult?.Invoke(dt, objData, resultStr);
});
lock (_cameraSummaryLock)
{
// 查找或添加相机统计项
var summary = CameraSummaries.FirstOrDefault(c => c.CameraName == "合计")
?? new CameraSummary { CameraName = "合计" };
summary.OKCount = ProductNum_OK;
summary.NGCount = ProductNum_Total - ProductNum_OK;
if (!CameraSummaries.Contains(summary))
{
CameraSummaries.Add(summary);
}
}
await Task.Run(() =>
{
OnUpdateCamResult?.Invoke(dt, objData, "合计");
});
2025-03-07 16:29:38 +08:00
}
2025-03-24 19:24:16 +08:00
2025-03-07 09:06:46 +08:00
private void HandleStopButton()
{
2025-03-27 15:31:36 +08:00
// Cameras.Clear();
// Dectection.Clear();
2025-03-07 09:06:46 +08:00
// Add the code for the "停止" button click here
2025-03-27 11:37:48 +08:00
PLC.TurnStart(false);
2025-03-07 09:06:46 +08:00
CurrentMachine = true;
2025-03-27 11:37:48 +08:00
//sLDMotion.Stop();
2025-03-07 09:06:46 +08:00
}
2025-03-24 19:24:16 +08:00
2025-04-10 14:08:55 +08:00
2025-03-24 19:24:16 +08:00
2025-03-07 09:06:46 +08:00
public void CalculateOEE()
{
2025-04-10 14:08:55 +08:00
if (TotalTime.TotalHours == 0)
2025-03-12 17:18:39 +08:00
{
2025-04-10 14:08:55 +08:00
UPH = 0;
UPM = 0;
}
else
{
UPH = (int)(ProductNum_Total / RunTime.TotalHours) + 100;
UPM = (int)UPH / 60;
}
//TimeSpan timeSpan = DateTime.Now - ProcessstartTime;
//UPH = (int)(ProductNum_Total / timeSpan.TotalHours) + 100;
////UPM = (int)UPH / 60;
//this.BeginInvoke(new MethodInvoker(delegate ()
//{
// lblNowtime.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
// lblUPH.Text = UPH.ToString();
// lblNum.Text = ProductNum_Total.ToString();
//}));
2025-03-07 09:06:46 +08:00
}
2025-03-24 19:24:16 +08:00
2025-03-07 09:06:46 +08:00
private void HandleResetButton()
{
// Add the code for the "复位" button click here
MessageBox.Show("复位按钮按下");
}
private void HandleSettingsButton()
{
// Add the code for the "设置" button click here
2025-03-13 18:54:05 +08:00
SettingWindow.Instance.Show();
2025-03-07 09:06:46 +08:00
}
private void HandleLoginButton()
{
// Add the code for the "登录" button click here
2025-03-24 19:24:16 +08:00
LoginWindow.Instance.Owner = this;
LoginWindow.Instance.Show();
2025-03-07 09:06:46 +08:00
}
2025-03-13 18:54:05 +08:00
private void splitter1_SplitterMoved(object sender, SplitterEventArgs e)
{
}
2025-03-26 11:37:23 +08:00
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
}
2025-03-27 15:11:48 +08:00
private void splitContainer2_Panel1_Paint(object sender, PaintEventArgs e)
{
}
2025-03-07 09:06:46 +08:00
}
2025-03-24 19:24:16 +08:00
}