添加 MX-PD-盘古 项目文件
将 MX-PD-盘古 - new 目录下的所有文件添加到主仓库
This commit is contained in:
@@ -0,0 +1,581 @@
|
||||
using MainShell.Common;
|
||||
using MainShell.Hardware;
|
||||
using MainShell.Log;
|
||||
using MainShell.Manual.Model;
|
||||
using MainShell.Models;
|
||||
using MainShell.Motion;
|
||||
using MainShell.Process;
|
||||
using MainShell.ProcessResult;
|
||||
using MainShell.Recipe.Models;
|
||||
using MainShell.Resources.CustomControl;
|
||||
using MwFramework.ManagerService;
|
||||
using Stylet;
|
||||
using StyletIoC;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using MW.WorkFlow;
|
||||
|
||||
namespace MainShell.Manual.ViewModel
|
||||
{
|
||||
public class DieRecheckDisplayItem : PropertyChangedBase
|
||||
{
|
||||
private int _stepIndex;
|
||||
public int StepIndex
|
||||
{
|
||||
get { return _stepIndex; }
|
||||
set { SetAndNotify(ref _stepIndex, value); }
|
||||
}
|
||||
|
||||
private int _padRow;
|
||||
public int PadRow
|
||||
{
|
||||
get { return _padRow; }
|
||||
set { SetAndNotify(ref _padRow, value); }
|
||||
}
|
||||
|
||||
private int _padColumn;
|
||||
public int PadColumn
|
||||
{
|
||||
get { return _padColumn; }
|
||||
set { SetAndNotify(ref _padColumn, value); }
|
||||
}
|
||||
|
||||
private int _dieRow;
|
||||
public int DieRow
|
||||
{
|
||||
get { return _dieRow; }
|
||||
set { SetAndNotify(ref _dieRow, value); }
|
||||
}
|
||||
|
||||
private int _dieColumn;
|
||||
public int DieColumn
|
||||
{
|
||||
get { return _dieColumn; }
|
||||
set { SetAndNotify(ref _dieColumn, value); }
|
||||
}
|
||||
|
||||
private double _padX;
|
||||
public double PadX
|
||||
{
|
||||
get { return _padX; }
|
||||
set { SetAndNotify(ref _padX, value); }
|
||||
}
|
||||
|
||||
private double _padY;
|
||||
public double PadY
|
||||
{
|
||||
get { return _padY; }
|
||||
set { SetAndNotify(ref _padY, value); }
|
||||
}
|
||||
|
||||
private double _dieX;
|
||||
public double DieX
|
||||
{
|
||||
get { return _dieX; }
|
||||
set { SetAndNotify(ref _dieX, value); }
|
||||
}
|
||||
|
||||
private double _dieY;
|
||||
public double DieY
|
||||
{
|
||||
get { return _dieY; }
|
||||
set { SetAndNotify(ref _dieY, value); }
|
||||
}
|
||||
|
||||
private string _transPathType;
|
||||
public string TransPathType
|
||||
{
|
||||
get { return _transPathType; }
|
||||
set { SetAndNotify(ref _transPathType, value); }
|
||||
}
|
||||
|
||||
private bool _isMissingBond;
|
||||
public bool IsMissingBond
|
||||
{
|
||||
get { return _isMissingBond; }
|
||||
set { SetAndNotify(ref _isMissingBond, value); }
|
||||
}
|
||||
|
||||
private double _xError;
|
||||
public double XError
|
||||
{
|
||||
get { return _xError; }
|
||||
set { SetAndNotify(ref _xError, value); }
|
||||
}
|
||||
|
||||
private double _yError;
|
||||
public double YError
|
||||
{
|
||||
get { return _yError; }
|
||||
set { SetAndNotify(ref _yError, value); }
|
||||
}
|
||||
|
||||
private bool _isXThresholdExceeded;
|
||||
public bool IsXThresholdExceeded
|
||||
{
|
||||
get { return _isXThresholdExceeded; }
|
||||
set { SetAndNotify(ref _isXThresholdExceeded, value); }
|
||||
}
|
||||
|
||||
private bool _isYThresholdExceeded;
|
||||
public bool IsYThresholdExceeded
|
||||
{
|
||||
get { return _isYThresholdExceeded; }
|
||||
set { SetAndNotify(ref _isYThresholdExceeded, value); }
|
||||
}
|
||||
|
||||
private string _statusSummary;
|
||||
public string StatusSummary
|
||||
{
|
||||
get { return _statusSummary; }
|
||||
set { SetAndNotify(ref _statusSummary, value); }
|
||||
}
|
||||
}
|
||||
|
||||
public class DieRecheckFilterState : PropertyChangedBase
|
||||
{
|
||||
private enum DieRecheckFilterRule
|
||||
{
|
||||
None = 0,
|
||||
MissingBondOnly,
|
||||
XThresholdExceededOnly,
|
||||
YThresholdExceededOnly,
|
||||
XYThresholdExceededOnly
|
||||
}
|
||||
|
||||
private DieRecheckFilterRule _selectedRule;
|
||||
private bool _isUpdatingSelection;
|
||||
|
||||
public bool IsMissingBondRuleSelected
|
||||
{
|
||||
get { return _selectedRule == DieRecheckFilterRule.MissingBondOnly; }
|
||||
set { SetSelectedRule(value, DieRecheckFilterRule.MissingBondOnly, nameof(IsMissingBondRuleSelected)); }
|
||||
}
|
||||
|
||||
public bool IsXThresholdRuleSelected
|
||||
{
|
||||
get { return _selectedRule == DieRecheckFilterRule.XThresholdExceededOnly; }
|
||||
set { SetSelectedRule(value, DieRecheckFilterRule.XThresholdExceededOnly, nameof(IsXThresholdRuleSelected)); }
|
||||
}
|
||||
|
||||
public bool IsYThresholdRuleSelected
|
||||
{
|
||||
get { return _selectedRule == DieRecheckFilterRule.YThresholdExceededOnly; }
|
||||
set { SetSelectedRule(value, DieRecheckFilterRule.YThresholdExceededOnly, nameof(IsYThresholdRuleSelected)); }
|
||||
}
|
||||
|
||||
public bool IsXYThresholdRuleSelected
|
||||
{
|
||||
get { return _selectedRule == DieRecheckFilterRule.XYThresholdExceededOnly; }
|
||||
set { SetSelectedRule(value, DieRecheckFilterRule.XYThresholdExceededOnly, nameof(IsXYThresholdRuleSelected)); }
|
||||
}
|
||||
|
||||
private double _xThreshold = 0.01d;
|
||||
public double XThreshold
|
||||
{
|
||||
get { return _xThreshold; }
|
||||
set { SetAndNotify(ref _xThreshold, value); }
|
||||
}
|
||||
|
||||
private double _yThreshold = 0.01d;
|
||||
public double YThreshold
|
||||
{
|
||||
get { return _yThreshold; }
|
||||
set { SetAndNotify(ref _yThreshold, value); }
|
||||
}
|
||||
|
||||
public void ClearSelectedRule()
|
||||
{
|
||||
UpdateSelectedRule(DieRecheckFilterRule.None, null);
|
||||
}
|
||||
|
||||
private void SetSelectedRule(bool isSelected, DieRecheckFilterRule targetRule, string propertyName)
|
||||
{
|
||||
if (_isUpdatingSelection)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DieRecheckFilterRule newRule = isSelected ? targetRule : DieRecheckFilterRule.None;
|
||||
UpdateSelectedRule(newRule, propertyName);
|
||||
}
|
||||
|
||||
private void UpdateSelectedRule(DieRecheckFilterRule newRule, string propertyName)
|
||||
{
|
||||
if (_selectedRule == newRule)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(propertyName))
|
||||
{
|
||||
OnPropertyChanged(propertyName);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_selectedRule = newRule;
|
||||
_isUpdatingSelection = true;
|
||||
try
|
||||
{
|
||||
OnPropertyChanged(nameof(IsMissingBondRuleSelected));
|
||||
OnPropertyChanged(nameof(IsXThresholdRuleSelected));
|
||||
OnPropertyChanged(nameof(IsYThresholdRuleSelected));
|
||||
OnPropertyChanged(nameof(IsXYThresholdRuleSelected));
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isUpdatingSelection = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DieRecheckViewModel : OperateViewModelBase
|
||||
{
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly RecipeManager _recipeManager;
|
||||
private readonly ProcessResultManager _processResultManager;
|
||||
private readonly DieRecheckService _dieRecheckService;
|
||||
private readonly SafeAxisMotion _safeAxisMotion;
|
||||
|
||||
private ObservableCollection<DieRecheckDisplayItem> _allPointResults = new ObservableCollection<DieRecheckDisplayItem>();
|
||||
private List<DieRecheckDisplayItem> _filteredPointResults = new List<DieRecheckDisplayItem>();
|
||||
|
||||
private ObservableCollection<DieRecheckDisplayItem> _pointResults = new ObservableCollection<DieRecheckDisplayItem>();
|
||||
public ObservableCollection<DieRecheckDisplayItem> PointResults
|
||||
{
|
||||
get { return _pointResults; }
|
||||
set { SetAndNotify(ref _pointResults, value); }
|
||||
}
|
||||
|
||||
public PaginationViewModel Pagination { get; } = new PaginationViewModel();
|
||||
|
||||
private RegionModel _recheckRegion = new RegionModel();
|
||||
public RegionModel RecheckRegion
|
||||
{
|
||||
get { return _recheckRegion; }
|
||||
set { SetAndNotify(ref _recheckRegion, value); }
|
||||
}
|
||||
|
||||
private DieRecheckFilterState _filterState = new DieRecheckFilterState();
|
||||
public DieRecheckFilterState FilterState
|
||||
{
|
||||
get { return _filterState; }
|
||||
set { SetAndNotify(ref _filterState, value); }
|
||||
}
|
||||
|
||||
private int _pointCount;
|
||||
public int PointCount
|
||||
{
|
||||
get { return _pointCount; }
|
||||
set { SetAndNotify(ref _pointCount, value); }
|
||||
}
|
||||
|
||||
private int _filteredPointCount;
|
||||
public int FilteredPointCount
|
||||
{
|
||||
get { return _filteredPointCount; }
|
||||
set { SetAndNotify(ref _filteredPointCount, value); }
|
||||
}
|
||||
|
||||
private DieRecheckDisplayItem _selectedPointResult;
|
||||
public DieRecheckDisplayItem SelectedPointResult
|
||||
{
|
||||
get { return _selectedPointResult; }
|
||||
set { SetAndNotify(ref _selectedPointResult, value); }
|
||||
}
|
||||
|
||||
public DieRecheckViewModel(
|
||||
IEventAggregator eventAggregator,
|
||||
RecipeManager recipeManager,
|
||||
ProcessResultManager processResultManager,
|
||||
HardwareManager hardwareManager,
|
||||
DieRecheckService dieRecheckService,
|
||||
SafeAxisMotion safeAxisMotion)
|
||||
{
|
||||
_eventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(eventAggregator));
|
||||
_recipeManager = recipeManager ?? throw new ArgumentNullException(nameof(recipeManager));
|
||||
_processResultManager = processResultManager ?? throw new ArgumentNullException(nameof(processResultManager));
|
||||
if (hardwareManager == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hardwareManager));
|
||||
}
|
||||
_dieRecheckService = dieRecheckService ?? throw new ArgumentNullException(nameof(dieRecheckService));
|
||||
_safeAxisMotion = safeAxisMotion ?? throw new ArgumentNullException(nameof(safeAxisMotion));
|
||||
|
||||
_cameraAxisViewModel = IoC.Get<Common.Display.ViewModel.CameraAxisViewModel>();
|
||||
_cameraAxisViewModel.CameraAxisDevices.HardwareDeviceList = hardwareManager.CameraAxisManager.TopCameraAxisDevices;
|
||||
|
||||
FilterState.PropertyChanged += FilterState_PropertyChanged;
|
||||
RecheckRegion.PropertyChanged += RecheckRegion_PropertyChanged;
|
||||
Pagination.PageChanged += Pagination_PageChanged;
|
||||
|
||||
LoadCurrentPoints();
|
||||
}
|
||||
|
||||
protected override void OnViewLoaded()
|
||||
{
|
||||
base.OnViewLoaded();
|
||||
LoadCurrentPoints();
|
||||
}
|
||||
|
||||
public async Task StartProcess()
|
||||
{
|
||||
WorkflowContext context = new WorkflowContext();
|
||||
context[WorkflowContextKeys.EventAggregator] = _eventAggregator;
|
||||
context[WorkflowContextKeys.RecipeManager] = _recipeManager;
|
||||
context[WorkflowContextKeys.ProcessResultManager] = _processResultManager;
|
||||
context[WorkflowContextKeys.WorkflowName] = ProcessFlowName.DieRecheckFlow;
|
||||
|
||||
WorkflowRunCompletedEventArgs result = await RunManualActivityAsync(
|
||||
new DieRecheckActivity(ProcessFlowName.DieRecheckFlow, _dieRecheckService),
|
||||
context,
|
||||
false);
|
||||
|
||||
if (!IsWorkflowCompleted(result))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LoadCurrentPoints();
|
||||
}
|
||||
|
||||
public async Task MoveToSelectedPoint()
|
||||
{
|
||||
if (SelectedPointResult == null)
|
||||
{
|
||||
LocalizedMessageBox.Show(MessageKey.DieRecheckSelectedPointRequired, MessageKey.TitleWarning, MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
HardwareDevice selectedDevice = _cameraAxisViewModel.CameraAxisDevices != null
|
||||
? _cameraAxisViewModel.CameraAxisDevices.SelectedHardwareDevice
|
||||
: null;
|
||||
if (selectedDevice == null || selectedDevice.AxisX == null || selectedDevice.AxisY == null)
|
||||
{
|
||||
LocalizedMessageBox.Show(MessageKey.DieRecheckMoveDeviceUnavailable, MessageKey.TitleWarning, MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
string moveMessage = $"DieRecheck move to point. StepIndex={SelectedPointResult.StepIndex}, PadX={SelectedPointResult.PadX:F4}, PadY={SelectedPointResult.PadY:F4}";
|
||||
moveMessage.LogProcessInfo();
|
||||
|
||||
await Task.Run(() =>
|
||||
_safeAxisMotion.SafeMove(
|
||||
MotionMoveRequest.ForAxis(selectedDevice.AxisX, SelectedPointResult.PadX, source: nameof(DieRecheckViewModel), tags: new[] { "DieRecheck", "MoveToPoint", "AxisX" }),
|
||||
MotionMoveRequest.ForAxis(selectedDevice.AxisY, SelectedPointResult.PadY, source: nameof(DieRecheckViewModel), tags: new[] { "DieRecheck", "MoveToPoint", "AxisY" })));
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
LogManager.LogSysError(exception);
|
||||
MwMessageBox.Show(exception.Message, LanguageResourceHelper.GetString(MessageKey.TitleError), MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetFilters()
|
||||
{
|
||||
FilterState.ClearSelectedRule();
|
||||
FilterState.XThreshold = 0.01d;
|
||||
FilterState.YThreshold = 0.01d;
|
||||
ApplyFilters();
|
||||
}
|
||||
|
||||
private void FilterState_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
UpdateThresholdFlags();
|
||||
Pagination.CurrentPage = 1;
|
||||
ApplyFilters();
|
||||
}
|
||||
|
||||
private void RecheckRegion_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
Pagination.CurrentPage = 1;
|
||||
ApplyFilters();
|
||||
}
|
||||
|
||||
private void Pagination_PageChanged(object sender, EventArgs e)
|
||||
{
|
||||
LoadPagedData();
|
||||
}
|
||||
|
||||
private void LoadCurrentPoints()
|
||||
{
|
||||
_allPointResults.Clear();
|
||||
_filteredPointResults.Clear();
|
||||
PointResults.Clear();
|
||||
|
||||
DieRecheckProcessResult processResult = _processResultManager.DieRecheckResult;
|
||||
if (processResult == null || processResult.PointResults == null)
|
||||
{
|
||||
PointCount = 0;
|
||||
FilteredPointCount = 0;
|
||||
Pagination.TotalItems = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (DieRecheckPointResult pointResult in processResult.PointResults)
|
||||
{
|
||||
_allPointResults.Add(new DieRecheckDisplayItem
|
||||
{
|
||||
StepIndex = pointResult.StepIndex,
|
||||
PadRow = pointResult.PadRow,
|
||||
PadColumn = pointResult.PadColumn,
|
||||
DieRow = pointResult.DieRow,
|
||||
DieColumn = pointResult.DieColumn,
|
||||
PadX = pointResult.PadX,
|
||||
PadY = pointResult.PadY,
|
||||
DieX = pointResult.DieX,
|
||||
DieY = pointResult.DieY,
|
||||
TransPathType = pointResult.TransPathType,
|
||||
IsMissingBond = pointResult.IsMissingBond,
|
||||
XError = pointResult.XError,
|
||||
YError = pointResult.YError
|
||||
});
|
||||
}
|
||||
|
||||
PointCount = _allPointResults.Count;
|
||||
InitializeRegion();
|
||||
UpdateThresholdFlags();
|
||||
Pagination.CurrentPage = 1;
|
||||
ApplyFilters();
|
||||
}
|
||||
|
||||
private void InitializeRegion()
|
||||
{
|
||||
if (_allPointResults.Count == 0)
|
||||
{
|
||||
RecheckRegion.StartRow = 1;
|
||||
RecheckRegion.StartCol = 1;
|
||||
RecheckRegion.EndRow = 1;
|
||||
RecheckRegion.EndCol = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
RecheckRegion.StartRow = _allPointResults.Min(item => item.PadRow);
|
||||
RecheckRegion.StartCol = _allPointResults.Min(item => item.PadColumn);
|
||||
RecheckRegion.EndRow = Math.Max(RecheckRegion.StartRow, _allPointResults.Max(item => item.PadRow));
|
||||
RecheckRegion.EndCol = Math.Max(RecheckRegion.StartCol, _allPointResults.Max(item => item.PadColumn));
|
||||
}
|
||||
|
||||
private void UpdateThresholdFlags()
|
||||
{
|
||||
foreach (DieRecheckDisplayItem item in _allPointResults)
|
||||
{
|
||||
item.IsXThresholdExceeded = Math.Abs(item.XError) >= FilterState.XThreshold;
|
||||
item.IsYThresholdExceeded = Math.Abs(item.YError) >= FilterState.YThreshold;
|
||||
item.StatusSummary = BuildStatusSummary(item);
|
||||
}
|
||||
}
|
||||
|
||||
private string BuildStatusSummary(DieRecheckDisplayItem item)
|
||||
{
|
||||
Collection<string> tags = new Collection<string>();
|
||||
if (item.IsMissingBond)
|
||||
{
|
||||
tags.Add(LanguageResourceHelper.GetString(MessageKey.DieRecheckStatusMissingBond));
|
||||
}
|
||||
|
||||
if (item.IsXThresholdExceeded)
|
||||
{
|
||||
tags.Add(LanguageResourceHelper.Format(MessageKey.DieRecheckStatusXExceeded, item.XError));
|
||||
}
|
||||
|
||||
if (item.IsYThresholdExceeded)
|
||||
{
|
||||
tags.Add(LanguageResourceHelper.Format(MessageKey.DieRecheckStatusYExceeded, item.YError));
|
||||
}
|
||||
|
||||
if (tags.Count == 0)
|
||||
{
|
||||
tags.Add(LanguageResourceHelper.GetString(MessageKey.DieRecheckStatusOk));
|
||||
}
|
||||
|
||||
return string.Join(" / ", tags);
|
||||
}
|
||||
|
||||
private void ApplyFilters()
|
||||
{
|
||||
_filteredPointResults = _allPointResults.Where(MatchesFilters).ToList();
|
||||
FilteredPointCount = _filteredPointResults.Count;
|
||||
Pagination.TotalItems = FilteredPointCount;
|
||||
|
||||
if (Pagination.TotalItems == 0)
|
||||
{
|
||||
SelectedPointResult = null;
|
||||
PointResults = new ObservableCollection<DieRecheckDisplayItem>();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Pagination.CurrentPage > Pagination.TotalPages)
|
||||
{
|
||||
Pagination.CurrentPage = Pagination.TotalPages;
|
||||
return;
|
||||
}
|
||||
|
||||
LoadPagedData();
|
||||
}
|
||||
|
||||
private void LoadPagedData()
|
||||
{
|
||||
if (_filteredPointResults == null || _filteredPointResults.Count == 0)
|
||||
{
|
||||
PointResults = new ObservableCollection<DieRecheckDisplayItem>();
|
||||
SelectedPointResult = null;
|
||||
return;
|
||||
}
|
||||
|
||||
int safePage = Math.Max(1, Math.Min(Pagination.CurrentPage, Pagination.TotalPages));
|
||||
int offset = (safePage - 1) * Pagination.PageSize;
|
||||
int limit = Pagination.PageSize;
|
||||
|
||||
PointResults = new ObservableCollection<DieRecheckDisplayItem>(_filteredPointResults.Skip(offset).Take(limit));
|
||||
if (SelectedPointResult != null && !PointResults.Contains(SelectedPointResult))
|
||||
{
|
||||
SelectedPointResult = null;
|
||||
}
|
||||
}
|
||||
|
||||
private bool MatchesFilters(DieRecheckDisplayItem item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isInRegion = item.PadRow >= RecheckRegion.StartRow
|
||||
&& item.PadRow <= RecheckRegion.EndRow
|
||||
&& item.PadColumn >= RecheckRegion.StartCol
|
||||
&& item.PadColumn <= RecheckRegion.EndCol;
|
||||
if (!isInRegion)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FilterState.IsMissingBondRuleSelected && !item.IsMissingBond)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FilterState.IsXYThresholdRuleSelected && !(item.IsXThresholdExceeded && item.IsYThresholdExceeded))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FilterState.IsXThresholdRuleSelected && !item.IsXThresholdExceeded)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FilterState.IsYThresholdRuleSelected && !item.IsYThresholdExceeded)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user