添加 MX-PD-盘古 项目文件
将 MX-PD-盘古 - new 目录下的所有文件添加到主仓库
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
using MainShell.Process;
|
||||
using System;
|
||||
|
||||
namespace MainShell.ProcessResult
|
||||
{
|
||||
public class AutoProductionResumeValidator
|
||||
{
|
||||
public bool IsStateConsistentForResume(
|
||||
string resumeStepId,
|
||||
PreparationAreaProcessState preparationState,
|
||||
CurrentChipProcessState currentChipState)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(resumeStepId))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (preparationState != null && preparationState.Status == ChipPreparationStatus.Faulted)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CurrentChipLifecycleState chipState = currentChipState == null
|
||||
? CurrentChipLifecycleState.Empty
|
||||
: currentChipState.State;
|
||||
|
||||
if (string.Equals(resumeStepId, WorkflowStepIds.AutoProduction.SubstrateLoadEntry, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(resumeStepId, WorkflowStepIds.AutoProduction.PreparationSignalEntry, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return preparationState == null || preparationState.Status != ChipPreparationStatus.Faulted;
|
||||
}
|
||||
|
||||
if (string.Equals(resumeStepId, WorkflowStepIds.AutoProduction.ChipPreparationSyncEntry, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return chipState == CurrentChipLifecycleState.Loading ||
|
||||
chipState == CurrentChipLifecycleState.LoadedPendingTransfer ||
|
||||
chipState == CurrentChipLifecycleState.InUse ||
|
||||
(preparationState != null && preparationState.Status == ChipPreparationStatus.Loaded);
|
||||
}
|
||||
|
||||
if (string.Equals(resumeStepId, WorkflowStepIds.AutoProduction.PreTransferValidationEntry, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(resumeStepId, WorkflowStepIds.AutoProduction.ChipStraighteningEntry, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(resumeStepId, WorkflowStepIds.AutoProduction.DiePositionEntry, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(resumeStepId, WorkflowStepIds.AutoProduction.DieTransferEntry, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(resumeStepId, WorkflowStepIds.AutoProduction.DieRecheckEntry, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return chipState == CurrentChipLifecycleState.LoadedPendingTransfer ||
|
||||
chipState == CurrentChipLifecycleState.InUse ||
|
||||
(preparationState != null && preparationState.Status == ChipPreparationStatus.Loaded);
|
||||
}
|
||||
|
||||
if (string.Equals(resumeStepId, WorkflowStepIds.AutoProduction.ChipUnloadEntry, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return chipState == CurrentChipLifecycleState.PendingUnload ||
|
||||
chipState == CurrentChipLifecycleState.Unloading ||
|
||||
chipState == CurrentChipLifecycleState.InUse;
|
||||
}
|
||||
|
||||
if (string.Equals(resumeStepId, WorkflowStepIds.AutoProduction.SubstrateUnloadEntry, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public string BuildResumeValidationError(
|
||||
string resumeStepId,
|
||||
PreparationAreaProcessState preparationState,
|
||||
CurrentChipProcessState currentChipState)
|
||||
{
|
||||
if (IsStateConsistentForResume(resumeStepId, preparationState, currentChipState))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (preparationState != null && preparationState.Status == ChipPreparationStatus.Faulted)
|
||||
{
|
||||
return "<22>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>ָ̻<CCBB>ʧ<EFBFBD>ܣ<EFBFBD><EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD>ڹ<EFBFBD><DAB9><EFBFBD>״̬<D7B4><CCAC>";
|
||||
}
|
||||
|
||||
if (string.Equals(resumeStepId, WorkflowStepIds.AutoProduction.DieTransferEntry, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(resumeStepId, WorkflowStepIds.AutoProduction.DieRecheckEntry, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(resumeStepId, WorkflowStepIds.AutoProduction.DiePositionEntry, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(resumeStepId, WorkflowStepIds.AutoProduction.ChipStraighteningEntry, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(resumeStepId, WorkflowStepIds.AutoProduction.PreTransferValidationEntry, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return "<22>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>ָ̻<CCBB>ʧ<EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD>ǰоƬ״̬<D7B4><CCAC><EFBFBD><EFBFBD>װǰ<D7B0><C7B0><EFBFBD><EFBFBD>״̬<D7B4><CCAC>һ<EFBFBD>¡<EFBFBD>";
|
||||
}
|
||||
|
||||
if (string.Equals(resumeStepId, WorkflowStepIds.AutoProduction.ChipPreparationSyncEntry, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return "<22>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>ָ̻<CCBB>ʧ<EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD>ǰоƬ<D0BE><C6AC><EFBFBD><EFBFBD>״̬<D7B4><CCAC>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD>״̬<D7B4><CCAC>һ<EFBFBD>¡<EFBFBD>";
|
||||
}
|
||||
|
||||
if (string.Equals(resumeStepId, WorkflowStepIds.AutoProduction.ChipUnloadEntry, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return "<22>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>ָ̻<CCBB>ʧ<EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD>ǰоƬ״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>оƬ<D0BE><C6AC><EFBFBD>ϻָ<CFBB><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>";
|
||||
}
|
||||
|
||||
return "<22>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>ָ̻<CCBB>ʧ<EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD>ǰ<EFBFBD><C7B0>Դ״̬<D7B4><CCAC><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD>ڲ<EFBFBD>һ<EFBFBD>¡<EFBFBD>";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
|
||||
namespace MainShell.ProcessResult
|
||||
{
|
||||
public class AutoProductionRuntimeState : ProcessResultBase
|
||||
{
|
||||
public int CurrentSubstratePendingCount { get; set; }
|
||||
|
||||
public int CurrentSubstrateProcessedCount { get; set; }
|
||||
|
||||
public int CurrentChipRemainingCount { get; set; }
|
||||
|
||||
public bool TransferNeedsRecheck { get; set; }
|
||||
|
||||
public bool TransferChipExhausted { get; set; }
|
||||
|
||||
public DateTime LastUpdatedTime { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MainShell.ProcessResult
|
||||
{
|
||||
public class ClipPositionResult : ProcessResultBase
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using MainShell.Filewritable;
|
||||
using MainShell.Process;
|
||||
using MXJM.FileWritable;
|
||||
using System;
|
||||
|
||||
namespace MainShell.ProcessResult
|
||||
{
|
||||
public class CurrentChipProcessState : ProcessResultBase
|
||||
{
|
||||
public CurrentChipLifecycleState State { get; set; } = CurrentChipLifecycleState.Empty;
|
||||
|
||||
public DateTime LastUpdatedTime { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using MainShell.Common;
|
||||
using MainShell.Models.Wafer;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
|
||||
namespace MainShell.ProcessResult
|
||||
{
|
||||
public class DiePositionProcessResult : ProcessResultBase
|
||||
{
|
||||
public bool IsSuccess { get; set; }
|
||||
|
||||
public string RecipeName { get; set; }
|
||||
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
public MessageKey ErrorMessageKey { get; set; } = MessageKey.None;
|
||||
|
||||
public string[] ErrorMessageArguments { get; set; } = Array.Empty<string>();
|
||||
|
||||
public int RowCount { get; set; }
|
||||
|
||||
public int ColumnCount { get; set; }
|
||||
|
||||
public int TheoryDieCount { get; set; }
|
||||
|
||||
public int ScanPointCount { get; set; }
|
||||
|
||||
public int RecognizedDieCount { get; set; }
|
||||
|
||||
public int NgDieCount { get; set; }
|
||||
|
||||
public double AverageSpacingX { get; set; }
|
||||
|
||||
public double AverageSpacingY { get; set; }
|
||||
|
||||
public List<Point> ScanPoints { get; set; } = new List<Point>();
|
||||
|
||||
public List<Die> RecognizedDies { get; set; } = new List<Die>();
|
||||
|
||||
public Die[,] MapDies { get; set; } = new Die[0, 0];
|
||||
|
||||
public List<Die> PatchDies { get; set; } = new List<Die>();
|
||||
|
||||
public List<Die> ExceptDies { get; set; } = new List<Die>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MainShell.ProcessResult
|
||||
{
|
||||
public class DieRecheckPointResult
|
||||
{
|
||||
public int StepIndex { get; set; }
|
||||
|
||||
public int PadRow { get; set; }
|
||||
|
||||
public int PadColumn { get; set; }
|
||||
|
||||
public int DieRow { get; set; }
|
||||
|
||||
public int DieColumn { get; set; }
|
||||
|
||||
public double PadX { get; set; }
|
||||
|
||||
public double PadY { get; set; }
|
||||
|
||||
public double DieX { get; set; }
|
||||
|
||||
public double DieY { get; set; }
|
||||
|
||||
public string TransPathType { get; set; }
|
||||
|
||||
public bool IsMissingBond { get; set; }
|
||||
|
||||
public double XError { get; set; }
|
||||
|
||||
public double YError { get; set; }
|
||||
}
|
||||
|
||||
public class DieRecheckProcessResult : ProcessResultBase
|
||||
{
|
||||
public bool IsSuccess { get; set; }
|
||||
|
||||
public List<DieRecheckPointResult> PointResults { get; set; } = new List<DieRecheckPointResult>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using MainShell.Process;
|
||||
using System;
|
||||
|
||||
namespace MainShell.ProcessResult
|
||||
{
|
||||
public class PreparationAreaProcessState : ProcessResultBase
|
||||
{
|
||||
public ChipPreparationStatus Status { get; set; } = ChipPreparationStatus.Idle;
|
||||
|
||||
public string ActiveRequestId { get; set; }
|
||||
|
||||
public string RecipeName { get; set; }
|
||||
|
||||
public string SourceStepId { get; set; }
|
||||
|
||||
public string CurrentStage { get; set; }
|
||||
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
public DateTime LastUpdatedTime { get; set; }
|
||||
|
||||
public ChipPreparationAction CurrentAction { get; set; } = ChipPreparationAction.None;
|
||||
|
||||
public bool HasPreparedChip { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using MainShell.Filewritable;
|
||||
using MXJM.FileWritable;
|
||||
using System;
|
||||
|
||||
namespace MainShell.ProcessResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 记录当前流程的执行状态,用于断点恢复
|
||||
/// </summary>
|
||||
public class ProcessFlowState : JsonFileWritableBase
|
||||
{
|
||||
public override string Dir => Paths.ProcessResultDir;
|
||||
|
||||
/// <summary>
|
||||
/// 顶层工作流名称 (例如 "AutoProduction")
|
||||
/// </summary>
|
||||
public string WorkflowName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// [新增] 父级活动/子流程名称 (例如 "SubstratePositionFlow")
|
||||
/// </summary>
|
||||
public string ParentActivityName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前最底层的步骤名称 (例如 "MoveToMark1")
|
||||
/// </summary>
|
||||
public string CurrentActivityName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前正在执行的步骤ID。
|
||||
/// </summary>
|
||||
public string CurrentStepId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下次恢复时优先执行的步骤ID。
|
||||
/// </summary>
|
||||
public string NextStepId { get; set; }
|
||||
|
||||
public string Status { get; set; }
|
||||
public string ErrorMessage { get; set; }
|
||||
public DateTime LastUpdateTime { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using MainShell.Filewritable;
|
||||
using MainShell.Manual.ViewModel;
|
||||
using MXJM.FileWritable;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MainShell.ProcessResult
|
||||
{
|
||||
public class ProcessResultBase : JsonFileWritableBase
|
||||
{
|
||||
public override string Dir => Paths.ProcessResultDir;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,298 @@
|
||||
using MainShell.Common;
|
||||
using MainShell.EventArgsFolder;
|
||||
using MainShell.Process;
|
||||
using Stylet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MW.WorkFlow;
|
||||
|
||||
namespace MainShell.ProcessResult
|
||||
{
|
||||
public class ProcessResultManager
|
||||
{
|
||||
private readonly MachineState _machineState;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
|
||||
/// <summary>
|
||||
/// 流程运行状态记录(仅在自动模式下持久化)
|
||||
/// </summary>
|
||||
public ProcessFlowState FlowState { get; } = new ProcessFlowState();
|
||||
|
||||
/// <summary>
|
||||
/// 基板定位的业务结果数据(始终持久化)
|
||||
/// </summary>
|
||||
public SubstratePositionProcessResult SubstratePositionResult { get; } = new SubstratePositionProcessResult();
|
||||
|
||||
/// <summary>
|
||||
/// 芯片定位的业务结果数据(始终持久化)
|
||||
/// </summary>
|
||||
public DiePositionProcessResult DiePositionResult { get; } = new DiePositionProcessResult();
|
||||
|
||||
/// <summary>
|
||||
/// 基板测高的业务结果数据(始终持久化)
|
||||
/// </summary>
|
||||
public SubstrateHeightMeasureProcessResult SubstrateHeightMeasureResult { get; } = new SubstrateHeightMeasureProcessResult();
|
||||
|
||||
/// <summary>
|
||||
/// 精度复检的业务结果数据(始终持久化)
|
||||
/// </summary>
|
||||
public DieRecheckProcessResult DieRecheckResult { get; } = new DieRecheckProcessResult();
|
||||
|
||||
/// <summary>
|
||||
/// 首页统计与条码展示状态(始终持久化)
|
||||
/// </summary>
|
||||
public ProductionDashboardState DashboardState { get; } = new ProductionDashboardState();
|
||||
|
||||
/// <summary>
|
||||
/// 准备区状态(用于恢复前一致性校验)
|
||||
/// </summary>
|
||||
public PreparationAreaProcessState PreparationAreaState { get; } = new PreparationAreaProcessState();
|
||||
|
||||
private readonly AutoProductionResumeValidator _resumeValidator = new AutoProductionResumeValidator();
|
||||
|
||||
/// <summary>
|
||||
/// 当前芯片使用位状态
|
||||
/// </summary>
|
||||
public CurrentChipProcessState CurrentChipState { get; } = new CurrentChipProcessState();
|
||||
|
||||
/// <summary>
|
||||
/// 自动流程运行态
|
||||
/// </summary>
|
||||
public AutoProductionRuntimeState AutoProductionRuntimeState { get; } = new AutoProductionRuntimeState();
|
||||
|
||||
public ProcessResultManager(MachineState machineState, IEventAggregator eventAggregator)
|
||||
{
|
||||
_machineState = machineState ?? throw new ArgumentNullException(nameof(machineState));
|
||||
_eventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(eventAggregator));
|
||||
// 构造时读取一次
|
||||
ReloadAll();
|
||||
}
|
||||
|
||||
public void UpdateFlowState(string workflowName, string parentActivityName, string activityName, ProcessExecutionStatus status, string errorMessage = null)
|
||||
{
|
||||
FlowState.WorkflowName = workflowName;
|
||||
FlowState.ParentActivityName = parentActivityName;
|
||||
FlowState.CurrentActivityName = activityName;
|
||||
FlowState.Status = status.ToString();
|
||||
FlowState.ErrorMessage = errorMessage;
|
||||
FlowState.LastUpdateTime = DateTime.Now;
|
||||
|
||||
if (ShouldPersistFlowState(workflowName))
|
||||
{
|
||||
FlowState.Write();
|
||||
}
|
||||
|
||||
_eventAggregator.Publish(new ProcessFlowStateChangedEventArgs
|
||||
{
|
||||
WorkflowName = workflowName,
|
||||
ParentActivityName = parentActivityName,
|
||||
CurrentActivityName = activityName,
|
||||
Status = status,
|
||||
ErrorMessage = errorMessage
|
||||
});
|
||||
}
|
||||
|
||||
public void UpdateFlowState(string workflowName, string parentActivityName, string activityName, string status, string errorMessage = null)
|
||||
{
|
||||
ProcessExecutionStatus parsed;
|
||||
if (!Enum.TryParse(status, true, out parsed))
|
||||
{
|
||||
parsed = ProcessExecutionStatus.Unknown;
|
||||
}
|
||||
|
||||
UpdateFlowState(workflowName, parentActivityName, activityName, parsed, errorMessage);
|
||||
}
|
||||
|
||||
public void UpdateExecutionPointer(WorkflowExecutionPointer executionPointer)
|
||||
{
|
||||
if (executionPointer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FlowState.WorkflowName = executionPointer.WorkflowName;
|
||||
FlowState.ParentActivityName = executionPointer.FlowName;
|
||||
FlowState.CurrentActivityName = executionPointer.ActivityName;
|
||||
FlowState.CurrentStepId = executionPointer.CurrentStepId;
|
||||
FlowState.NextStepId = executionPointer.NextStepId;
|
||||
FlowState.LastUpdateTime = executionPointer.UpdatedAt == default(DateTime) ? DateTime.Now : executionPointer.UpdatedAt;
|
||||
|
||||
if (ShouldPersistFlowState(executionPointer.WorkflowName))
|
||||
{
|
||||
FlowState.Write();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void ReportWorkflowFault(WorkflowFaultInfo faultInfo)
|
||||
{
|
||||
if (faultInfo == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FlowState.WorkflowName = faultInfo.WorkflowName;
|
||||
FlowState.ParentActivityName = faultInfo.FlowName;
|
||||
FlowState.CurrentActivityName = faultInfo.ActivityName;
|
||||
FlowState.CurrentStepId = faultInfo.CurrentStepId;
|
||||
FlowState.NextStepId = faultInfo.CurrentStepId;
|
||||
FlowState.Status = ProcessExecutionStatus.Faulted.ToString();
|
||||
FlowState.ErrorMessage = faultInfo.ErrorMessage;
|
||||
FlowState.LastUpdateTime = faultInfo.OccurredAt == default(DateTime) ? DateTime.Now : faultInfo.OccurredAt;
|
||||
|
||||
if (ShouldPersistFlowState(faultInfo.WorkflowName))
|
||||
{
|
||||
FlowState.Write();
|
||||
}
|
||||
_eventAggregator.Publish(new ProcessFlowStateChangedEventArgs
|
||||
{
|
||||
WorkflowName = faultInfo.WorkflowName,
|
||||
ParentActivityName = faultInfo.FlowName,
|
||||
CurrentActivityName = faultInfo.ActivityName,
|
||||
Status = ProcessExecutionStatus.Faulted,
|
||||
ErrorMessage = faultInfo.ErrorMessage
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public bool TryGetResumeStepId(string workflowName, out string resumeStepId)
|
||||
{
|
||||
resumeStepId = null;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(workflowName) ||
|
||||
!string.Equals(FlowState.WorkflowName, workflowName, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.IsNullOrWhiteSpace(FlowState.NextStepId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.Equals(FlowState.Status, ProcessExecutionStatus.Completed.ToString(), StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(FlowState.Status, ProcessExecutionStatus.Canceled.ToString(), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_resumeValidator.IsStateConsistentForResume(FlowState.NextStepId, PreparationAreaState, CurrentChipState))
|
||||
{
|
||||
FlowState.ErrorMessage = _resumeValidator.BuildResumeValidationError(FlowState.NextStepId, PreparationAreaState, CurrentChipState);
|
||||
FlowState.LastUpdateTime = DateTime.Now;
|
||||
if (ShouldPersistFlowState(workflowName))
|
||||
{
|
||||
FlowState.Write();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
resumeStepId = FlowState.NextStepId;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SaveSubstratePositionResult()
|
||||
{
|
||||
SubstratePositionResult.Write();
|
||||
}
|
||||
|
||||
public void SaveDiePositionResult()
|
||||
{
|
||||
DiePositionResult.Write();
|
||||
}
|
||||
|
||||
public void SaveSubstrateHeightMeasureResult()
|
||||
{
|
||||
SubstrateHeightMeasureResult.Write();
|
||||
}
|
||||
|
||||
public void SaveDieRecheckResult()
|
||||
{
|
||||
DieRecheckResult.Write();
|
||||
}
|
||||
|
||||
public void SaveDashboardState()
|
||||
{
|
||||
DashboardState.Write();
|
||||
}
|
||||
|
||||
public void SavePreparationAreaState(ChipPreparationStateSnapshot snapshot)
|
||||
{
|
||||
if (snapshot == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PreparationAreaState.Status = snapshot.Status;
|
||||
PreparationAreaState.ActiveRequestId = snapshot.ActiveRequestId;
|
||||
PreparationAreaState.RecipeName = snapshot.RecipeName;
|
||||
PreparationAreaState.SourceStepId = snapshot.SourceStepId;
|
||||
PreparationAreaState.CurrentStage = snapshot.CurrentStage;
|
||||
PreparationAreaState.ErrorMessage = snapshot.ErrorMessage;
|
||||
PreparationAreaState.LastUpdatedTime = snapshot.LastUpdatedTime;
|
||||
PreparationAreaState.CurrentAction = snapshot.CurrentAction;
|
||||
PreparationAreaState.HasPreparedChip = snapshot.IsChipLoaded;
|
||||
PreparationAreaState.Write();
|
||||
}
|
||||
|
||||
public void SaveCurrentChipState(CurrentChipLifecycleState chipState)
|
||||
{
|
||||
CurrentChipState.State = chipState;
|
||||
CurrentChipState.LastUpdatedTime = DateTime.Now;
|
||||
CurrentChipState.Write();
|
||||
}
|
||||
|
||||
public void SaveAutoProductionRuntimeState(AutoProductionRuntimeState runtimeState)
|
||||
{
|
||||
if (runtimeState == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AutoProductionRuntimeState.CurrentSubstratePendingCount = runtimeState.CurrentSubstratePendingCount;
|
||||
AutoProductionRuntimeState.CurrentSubstrateProcessedCount = runtimeState.CurrentSubstrateProcessedCount;
|
||||
AutoProductionRuntimeState.CurrentChipRemainingCount = runtimeState.CurrentChipRemainingCount;
|
||||
AutoProductionRuntimeState.TransferNeedsRecheck = runtimeState.TransferNeedsRecheck;
|
||||
AutoProductionRuntimeState.TransferChipExhausted = runtimeState.TransferChipExhausted;
|
||||
AutoProductionRuntimeState.LastUpdatedTime = runtimeState.LastUpdatedTime;
|
||||
AutoProductionRuntimeState.Write();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 强制从磁盘重新加载所有状态和结果数据
|
||||
/// <para>在启动或恢复自动流程前调用,确保获取到最新的(可能是手动操作产生的)结果数据</para>
|
||||
/// </summary>
|
||||
public void ReloadAll()
|
||||
{
|
||||
// 1. 读取断点状态(决定从哪一步开始)
|
||||
FlowState.Read();
|
||||
|
||||
// 2. 读取业务结果(决定流程所需的数据上下文)
|
||||
// 无论之前是手动还是自动写入的,这里统一读取最新值
|
||||
SubstratePositionResult.Read();
|
||||
DiePositionResult.Read();
|
||||
SubstrateHeightMeasureResult.Read();
|
||||
DieRecheckResult.Read();
|
||||
|
||||
// 3. 首页运行数据
|
||||
DashboardState.Read();
|
||||
|
||||
// 4. 准备区状态
|
||||
PreparationAreaState.Read();
|
||||
|
||||
// 5. 当前芯片使用位状态
|
||||
CurrentChipState.Read();
|
||||
|
||||
// 6. 自动流程运行态
|
||||
AutoProductionRuntimeState.Read();
|
||||
|
||||
// 后续如果有其他结果类(如 WaferMapResult),也在这里读取
|
||||
// WaferMapResult.Read();
|
||||
}
|
||||
|
||||
private bool ShouldPersistFlowState(string workflowName)
|
||||
{
|
||||
return _machineState.CurrentMode == MachineMode.Auto ||
|
||||
string.Equals(workflowName, ProcessFlowName.AutoProduction, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace MainShell.ProcessResult
|
||||
{
|
||||
public class ProductionDashboardState : ProcessResultBase, INotifyPropertyChanged
|
||||
{
|
||||
private string _productId = string.Empty;
|
||||
private string _chipId = string.Empty;
|
||||
private int _processedSubstrateTotal;
|
||||
private int _pendingCount;
|
||||
private int _processedCount;
|
||||
private int _realTimeUph;
|
||||
private int _yieldUph;
|
||||
private double _mappingProgress;
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public string ProductId
|
||||
{
|
||||
get => _productId;
|
||||
set => SetField(ref _productId, value);
|
||||
}
|
||||
|
||||
public string ChipId
|
||||
{
|
||||
get => _chipId;
|
||||
set => SetField(ref _chipId, value);
|
||||
}
|
||||
|
||||
public int ProcessedSubstrateTotal
|
||||
{
|
||||
get => _processedSubstrateTotal;
|
||||
set => SetField(ref _processedSubstrateTotal, value);
|
||||
}
|
||||
|
||||
public int PendingCount
|
||||
{
|
||||
get => _pendingCount;
|
||||
set => SetField(ref _pendingCount, value);
|
||||
}
|
||||
|
||||
public int ProcessedCount
|
||||
{
|
||||
get => _processedCount;
|
||||
set => SetField(ref _processedCount, value);
|
||||
}
|
||||
|
||||
public int RealTimeUph
|
||||
{
|
||||
get => _realTimeUph;
|
||||
set => SetField(ref _realTimeUph, value);
|
||||
}
|
||||
|
||||
public int YieldUph
|
||||
{
|
||||
get => _yieldUph;
|
||||
set => SetField(ref _yieldUph, value);
|
||||
}
|
||||
|
||||
public double MappingProgress
|
||||
{
|
||||
get => _mappingProgress;
|
||||
set => SetField(ref _mappingProgress, value);
|
||||
}
|
||||
|
||||
private void SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
|
||||
{
|
||||
if (EqualityComparer<T>.Default.Equals(field, value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
field = value;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using MainShell.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MainShell.ProcessResult
|
||||
{
|
||||
public class SubstrateHeightMeasurePointResult
|
||||
{
|
||||
public string PointName { get; set; }
|
||||
|
||||
public int RowIndex { get; set; }
|
||||
|
||||
public int ColumnIndex { get; set; }
|
||||
|
||||
public double PositionX { get; set; }
|
||||
|
||||
public double PositionY { get; set; }
|
||||
|
||||
public double? HeightValue { get; set; }
|
||||
}
|
||||
|
||||
public class SubstrateHeightMeasureProcessResult : ProcessResultBase
|
||||
{
|
||||
public bool IsSuccess { get; set; }
|
||||
|
||||
public string RecipeName { get; set; }
|
||||
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
public MessageKey ErrorMessageKey { get; set; } = MessageKey.None;
|
||||
|
||||
public string[] ErrorMessageArguments { get; set; } = Array.Empty<string>();
|
||||
|
||||
public List<SubstrateHeightMeasurePointResult> PointResults { get; set; } = new List<SubstrateHeightMeasurePointResult>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using MainShell.Common;
|
||||
using MainShell.Filewritable;
|
||||
using MXJM.FileWritable;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace MainShell.ProcessResult
|
||||
{
|
||||
public class SubstratePositionProcessResult : ProcessResultBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 流程是否成功
|
||||
/// </summary>
|
||||
public bool IsSuccess { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误信息
|
||||
/// </summary>
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误消息键
|
||||
/// </summary>
|
||||
public MessageKey ErrorMessageKey { get; set; } = MessageKey.None;
|
||||
|
||||
/// <summary>
|
||||
/// 错误消息参数
|
||||
/// </summary>
|
||||
public string[] ErrorMessageArguments { get; set; } = Array.Empty<string>();
|
||||
|
||||
/// <summary>
|
||||
/// 配方中可用Mark点数量
|
||||
/// </summary>
|
||||
public int AvailableMarkCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 成功识别的Mark点数量
|
||||
/// </summary>
|
||||
public int RecognizedMarkCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Mark点结果集合
|
||||
/// </summary>
|
||||
public List<Point> MarkResults { get; set; } = new List<Point>();
|
||||
|
||||
/// <summary>
|
||||
/// 基板角度
|
||||
/// </summary>
|
||||
public double SubstrateAngle { get; set; } = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MainShell.ProcessResult
|
||||
{
|
||||
public class WaferAngleAdjustmentResult : ProcessResultBase
|
||||
{
|
||||
public double AdjustedWaferAngle { get; set; } = 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user