修改统计

This commit is contained in:
2025-04-10 14:08:55 +08:00
parent ab38ee029a
commit 4765e0e5bd
7 changed files with 910 additions and 366 deletions

View File

@ -22,9 +22,11 @@ using System;
using System.CodeDom;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
@ -36,6 +38,7 @@ using static DH.Commons.Enums.EnumHelper;
using Camera = DHSoftware.Models.Camera;
using LogLevel = DH.Commons.Enums.EnumHelper.LogLevel;
using ResultState = DH.Commons.Base.ResultState;
using Timer = System.Threading.Timer;
namespace DHSoftware
{
@ -43,6 +46,13 @@ namespace DHSoftware
{
private Dictionary<string, List<string>> _cameraRelatedDetectionDict = null;
public event Action<LogMsg> OnLog;
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;
private string _loginName;
public string LoginName
@ -173,8 +183,7 @@ namespace DHSoftware
public MainWindow()
{
InitializeComponent();
//refreshTimer.Start();
InitialCameraSumsView(); //refreshTimer.Start();
//初始化数据
InitData();
//绑定事件
@ -185,6 +194,317 @@ namespace DHSoftware
//userControlFrm.Dock = DockStyle.Fill;
//tabPage2.Controls.Add(userControlFrm);
}
//#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
/// <summary>
/// 窗体对象实例
@ -425,6 +745,43 @@ namespace DHSoftware
LoggerHelper.LogPrefix = "Process";
OnLog -= LogDisplay;
OnLog += LogDisplay;
OnUpdateCamResult -= UpdateCamResult;
OnUpdateCamResult += UpdateCamResult;
OnUpdateResult -= UpdateResult;
OnUpdateResult += UpdateResult;
}
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(() =>
{
dgvProductNums.DataSource = null;
dgvProductNums.DataSource = ProductSummaries;
if (dgvProductNums.Rows.Count > 0)
{
dgvProductNums.Height = dgvProductNums.Rows[0].Height * dgvProductNums.Rows.Count + 15;
}
else
{
dgvProductNums.Height = 15;
}
//lblOEE_Rate.Text = ProcessControl.OEE.ToString("f2") + " %";
lblUPH.Text = UPH.ToString();
}));
}
private void BtnDeleteProject_Click(object? sender, EventArgs e)
@ -647,7 +1004,7 @@ namespace DHSoftware
private void StartProcess()
{
ProcessstartTime = DateTime.Now;
lblstarttime2.Text = ProcessstartTime.ToString("yyyy-MM-dd HH:mm:ss");
lblstarttime.Text = ProcessstartTime.ToString("yyyy-MM-dd HH:mm:ss");
//计数清零
PieceCount = 0;
@ -907,7 +1264,9 @@ namespace DHSoftware
}
}
stopwatch.Stop();
if (product.ResultCollection.Count != 0)
UpdateResultoverride(dt, camera, resultStates, totalTime, _cameraRelatedDetectionDict.Keys.Count);
product.InferenceOne();
// LogAsync(DateTime.Now, LogLevel.Information, $"{camera.Name} 推理完成,产品{productNumber}");
@ -916,7 +1275,7 @@ namespace DHSoftware
{
return;
}
UpdateResult(DateTime.Now, null, product.ProductResult.GetEnumDescription());
UpdateResultPro(DateTime.Now, null, product.ProductResult.GetEnumDescription());
#region 6.
@ -1010,19 +1369,116 @@ namespace DHSoftware
}
});
}
public async Task UpdateResult(DateTime dt, object objData, string resultStr)
public virtual void AddOKProduct(string resultStr)
{
// CurrentState = RunState.Running;
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("相机名称不能为空");
}
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)
{
CurrentState = RunState.Running;
ProductNum_Total++;
//AddOKProduct(resultStr);
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;
ProductSummaries.Add(product);
}
int totalNum = ProductSummaries.Sum(p => p.ProductAmount);
ProductSummaries.ForEach(p => p.PercentStr = ((double)p.ProductAmount * 100.0 / totalNum).ToString("f2") + " %");
}
CalculateOEE();
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, "合计");
});
}
private void HandleStopButton()
@ -1035,21 +1491,33 @@ namespace DHSoftware
//sLDMotion.Stop();
}
public int UPH = 0;
public void CalculateOEE()
{
TimeSpan timeSpan = DateTime.Now - ProcessstartTime;
UPH = (int)(ProductNum_Total / timeSpan.TotalHours) + 100;
//UPM = (int)UPH / 60;
this.BeginInvoke(new MethodInvoker(delegate ()
if (TotalTime.TotalHours == 0)
{
lblNowtime2.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
lblUPH2.Text = UPH.ToString();
lblNum2.Text = ProductNum_Total.ToString();
labuph.Text = UPH.ToString();
}));
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();
//}));
}
private void HandleResetButton()