添加 MX-PD-盘古 项目文件

将 MX-PD-盘古 - new 目录下的所有文件添加到主仓库
This commit is contained in:
Shi.Ji
2026-05-18 11:43:09 +08:00
parent 03632a379d
commit e31d3560bb
739 changed files with 99783 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
using MainShell.DeviceMaintance.Model;
using MainShell.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MainShell.DeviceMaintance.ViewModel
{
public class CameraAccuracyCalibrationViewModel: DeviceMaintanceBaseViewModel
{
}
}

View File

@@ -0,0 +1,305 @@
using MainShell.DeviceMaintance.Model;
using MainShell.DeviceMaintance.ViewModel.State;
using MainShell.Hardware;
using MainShell.Manual.ViewModel.State;
using MaxwellFramework.Core.Interfaces;
using Stylet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MainShell.DeviceMaintance.ViewModel
{
public class CylinderViewModel : Screen, IPage
{
private readonly IDeviceIoMonitorService _ioMonitorService;
private readonly IDeviceCylinderService _cylinderService;
private readonly Dictionary<string, List<CylinderSignalState>> _signalMap = new Dictionary<string, List<CylinderSignalState>>(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<string, DeviceIoPointDefinition> _ioDefinitionsByName;
private CylinderPageState _pageState;
public CylinderPageState PageState
{
get { return _pageState; }
set { SetAndNotify(ref _pageState, value); }
}
public CylinderViewModel(IDeviceIoMonitorService ioMonitorService, IDeviceCylinderService cylinderService)
{
_ioMonitorService = ioMonitorService;
_cylinderService = cylinderService;
_ioDefinitionsByName = _ioMonitorService.Definitions.ToDictionary(x => x.Name, x => x, StringComparer.OrdinalIgnoreCase);
PageState = BuildState();
_ioMonitorService.IoChanged += OnIoChanged;
_ioMonitorService.Start();
}
protected override void OnViewLoaded()
{
base.OnViewLoaded();
ApplyIoPoints(_ioMonitorService.LatestPoints.Values);
InitializePointsAsync();
}
protected override void OnDeactivate()
{
_ioMonitorService.IoChanged -= OnIoChanged;
base.OnDeactivate();
}
private CylinderPageState BuildState()
{
var state = new CylinderPageState();
_signalMap.Clear();
foreach (var definition in _cylinderService.Definitions)
{
var item = new CylinderItemState
{
Name = definition.Name,
Description = definition.Description,
Module = definition.Module,
ControlTypeText = GetControlTypeText(definition.ControlType)
};
item.ExtendCommand = new ActionCommand(() => ExecuteCylinderAction(definition, item, true), () => !item.IsBusy);
item.RetractCommand = new ActionCommand(() => ExecuteCylinderAction(definition, item, false), () => !item.IsBusy);
for (var i = 0; i < definition.ExtendOutputPoints.Count; i++)
{
AddOutputSignal(item, definition.ExtendOutputPoints[i], definition.ExtendOutputPoints.Count > 1 ? string.Format("{0}-伸出输出{1}", definition.Name, i + 1) : definition.Name + "-伸出输出");
}
for (var i = 0; i < definition.RetractOutputPoints.Count; i++)
{
AddOutputSignal(item, definition.RetractOutputPoints[i], definition.RetractOutputPoints.Count > 1 ? string.Format("{0}-缩回输出{1}", definition.Name, i + 1) : definition.Name + "-缩回输出");
}
foreach (var pointReference in definition.ExtendedFeedbackPoints)
{
AddFeedbackSignal(item, pointReference, definition.Name + "-伸出到位");
}
foreach (var pointReference in definition.RetractedFeedbackPoints)
{
AddFeedbackSignal(item, pointReference, definition.Name + "-缩回到位");
}
state.Cylinders.Add(item);
}
return state;
}
private void AddOutputSignal(CylinderItemState item, string pointReference, string fallbackName)
{
var definition = ResolveDefinition(pointReference);
var signal = new CylinderSignalState
{
PointReference = pointReference,
PointKey = definition?.PointKey,
Name = definition != null ? definition.Name : fallbackName,
LineNo = definition != null ? definition.LineNo : string.Empty,
IsOutput = true
};
item.OutputSignals.Add(signal);
MapSignal(signal, pointReference);
}
private void AddFeedbackSignal(CylinderItemState item, string pointReference, string fallbackName)
{
var definition = ResolveDefinition(pointReference);
var signal = new CylinderSignalState
{
PointReference = pointReference,
PointKey = definition?.PointKey,
Name = definition != null ? definition.Name : fallbackName,
LineNo = definition != null ? definition.LineNo : string.Empty,
IsOutput = false
};
item.FeedbackSignals.Add(signal);
MapSignal(signal, pointReference);
}
private DeviceIoPointDefinition ResolveDefinition(string pointReference)
{
if (string.IsNullOrWhiteSpace(pointReference))
{
return null;
}
DeviceIoPointDefinition definition;
if (_ioDefinitionsByName.TryGetValue(pointReference, out definition))
{
return definition;
}
int id;
if (!int.TryParse(pointReference, out id))
{
return null;
}
var matches = _ioMonitorService.Definitions.Where(x => x.Id == id).Take(2).ToList();
return matches.Count == 1 ? matches[0] : null;
}
private void MapSignal(CylinderSignalState signal, string pointReference)
{
var key = !string.IsNullOrWhiteSpace(signal.PointKey) ? signal.PointKey : pointReference;
if (string.IsNullOrWhiteSpace(key))
{
return;
}
List<CylinderSignalState> signals;
if (!_signalMap.TryGetValue(key, out signals))
{
signals = new List<CylinderSignalState>();
_signalMap[key] = signals;
}
signals.Add(signal);
}
private void OnIoChanged(object sender, EventArgs e)
{
var args = e as MainShell.EventArgsFolder.DeviceIoChangedEventArgs;
if (args == null)
{
return;
}
ApplyIoPoints(args.ChangedPoints);
}
private async void InitializePointsAsync()
{
_ioMonitorService.RequestRefresh();
await Task.Delay(150);
ApplyIoPoints(_ioMonitorService.LatestPoints.Values);
}
private void ApplyIoPoints(IEnumerable<DeviceIoPointState> points)
{
if (points == null)
{
return;
}
foreach (var point in points)
{
if (point == null)
{
continue;
}
List<CylinderSignalState> signals;
if (!_signalMap.TryGetValue(point.PointKey, out signals))
{
continue;
}
foreach (var signal in signals)
{
signal.IsOn = point.Value;
}
}
}
private void ExecuteCylinderAction(CylinderDefinition definition, CylinderItemState item, bool extend)
{
item.IsBusy = true;
RaiseCommands(item);
string failureReason;
var result = extend ? _cylinderService.TryExtend(definition.Name, out failureReason) : _cylinderService.TryRetract(definition.Name, out failureReason);
if (result)
{
SimulateCylinderFeedback(definition, extend);
PageState.LastActionMessage = definition.Name + (extend ? " 执行伸出成功。" : " 执行缩回成功。");
}
else
{
PageState.LastActionMessage = string.IsNullOrWhiteSpace(failureReason)
? definition.Name + (extend ? " 伸出失败。" : " 缩回失败。")
: failureReason;
}
PageState.LastActionTime = DateTime.Now;
item.IsBusy = false;
RaiseCommands(item);
}
private void SimulateCylinderFeedback(CylinderDefinition definition, bool extend)
{
foreach (var output in definition.ExtendOutputPoints.SelectMany(GetSignals))
{
output.IsOn = extend;
}
foreach (var output in definition.RetractOutputPoints.SelectMany(GetSignals))
{
output.IsOn = !extend;
}
foreach (var feedback in definition.ExtendedFeedbackPoints.SelectMany(GetSignals))
{
feedback.IsOn = extend;
}
foreach (var feedback in definition.RetractedFeedbackPoints.SelectMany(GetSignals))
{
feedback.IsOn = !extend;
}
}
private IEnumerable<CylinderSignalState> GetSignals(string pointReference)
{
var definition = ResolveDefinition(pointReference);
var key = definition != null ? definition.PointKey : pointReference;
if (string.IsNullOrWhiteSpace(key))
{
return Enumerable.Empty<CylinderSignalState>();
}
List<CylinderSignalState> signals;
if (_signalMap.TryGetValue(key, out signals))
{
return signals;
}
return Enumerable.Empty<CylinderSignalState>();
}
private static void RaiseCommands(CylinderItemState item)
{
var extend = item.ExtendCommand as ActionCommand;
if (extend != null)
{
extend.RaiseCanExecuteChanged();
}
var retract = item.RetractCommand as ActionCommand;
if (retract != null)
{
retract.RaiseCanExecuteChanged();
}
}
private static string GetControlTypeText(CylinderControlType controlType)
{
switch (controlType)
{
case CylinderControlType.DualOutput:
return "双输出控制";
case CylinderControlType.MultiOutput:
return "多输出单控";
default:
return "单输出控制";
}
}
}
}

View File

@@ -0,0 +1,194 @@
using MainShell.EventArgsFolder;
using MainShell.Hardware;
using MainShell.Manual.Model;
using MainShell.DeviceMaintance.ViewModel.State;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MainShell.DeviceMaintance.ViewModel
{
public class DeviceIoViewModel : OperateViewModelBase
{
private readonly IDeviceIoMonitorService _ioMonitorService;
private readonly Dictionary<string, DeviceIoPointItemState> _pointStateMap = new Dictionary<string, DeviceIoPointItemState>(StringComparer.OrdinalIgnoreCase);
private DeviceIoPageState _pageState;
public DeviceIoPageState PageState
{
get { return _pageState; }
set { SetAndNotify(ref _pageState, value); }
}
public DeviceIoViewModel(IDeviceIoMonitorService ioMonitorService)
{
_ioMonitorService = ioMonitorService;
PageState = BuildState();
_ioMonitorService.IoChanged += OnIoChanged;
_ioMonitorService.Start();
}
protected override void OnViewLoaded()
{
base.OnViewLoaded();
RefreshFromCurrentPoints();
InitializeLatestPointsAsync();
}
protected override void OnDeactivate()
{
_ioMonitorService.IoChanged -= OnIoChanged;
base.OnDeactivate();
}
private DeviceIoPageState BuildState()
{
var state = new DeviceIoPageState();
_pointStateMap.Clear();
foreach (var moduleGroup in _ioMonitorService.Definitions.GroupBy(x => string.IsNullOrWhiteSpace(x.Module) ? "Default" : x.Module))
{
var moduleState = new DeviceIoModuleState
{
Name = moduleGroup.Key
};
foreach (var definition in moduleGroup.OrderBy(x => x.StationNo).ThenBy(x => x.Id).ThenBy(x => x.LineNo))
{
var item = new DeviceIoPointItemState
{
Id = definition.Id,
PointKey = definition.PointKey,
Module = definition.Module,
Name = definition.Name,
StationNo = definition.StationNo,
LineNo = definition.LineNo,
Description = definition.Description,
IsOutput = definition.Type == IoPointType.Output,
IsOn = definition.DefaultValue,
IsInverse = definition.IsInverse,
CanWrite = definition.Type == IoPointType.Output && definition.Enabled,
};
if (item.IsOutput)
{
var command = new ActionCommand(() => ToggleOutput(item), () => item.CanWrite);
item.ToggleCommand = command;
}
_pointStateMap[item.PointKey] = item;
if (item.IsOutput)
{
moduleState.OutputPoints.Add(item);
}
else
{
moduleState.InputPoints.Add(item);
}
}
state.Modules.Add(moduleState);
}
state.IsOnline = _ioMonitorService.IsOnline;
return state;
}
private async void InitializeLatestPointsAsync()
{
_ioMonitorService.RequestRefresh();
await Task.Delay(150);
RefreshFromCurrentPoints();
}
private void RefreshFromCurrentPoints()
{
var points = _ioMonitorService.LatestPoints.Values.ToList();
ApplyPoints(points);
}
private void OnIoChanged(object sender, EventArgs e)
{
var args = e as DeviceIoChangedEventArgs;
if (args == null)
{
return;
}
ApplyPoints(args.ChangedPoints);
PageState.LastRefreshTime = DateTime.Now;
}
private void ApplyPoints(IEnumerable<DeviceIoPointState> points)
{
if (points == null)
{
return;
}
var hasPoint = false;
foreach (var point in points)
{
if (point == null)
{
continue;
}
hasPoint = true;
DeviceIoPointItemState item;
if (!_pointStateMap.TryGetValue(point.PointKey, out item))
{
continue;
}
item.IsOn = point.Value;
var outputPoint = point as DeviceOutputPointState;
item.CanWrite = outputPoint != null && outputPoint.CanWrite;
var command = item.ToggleCommand as ActionCommand;
if (command != null)
{
command.RaiseCanExecuteChanged();
}
}
if (hasPoint)
{
PageState.LastRefreshTime = DateTime.Now;
}
PageState.IsOnline = hasPoint && _ioMonitorService.IsOnline;
}
private void ToggleOutput(DeviceIoPointItemState item)
{
DeviceIoPointState point;
if (!_ioMonitorService.TryGetPoint(item.PointKey, out point))
{
UpdateWriteResult(item.Name + " 写入失败:未找到输出点。", false);
return;
}
var outputPoint = point as DeviceOutputPointState;
if (outputPoint == null || !outputPoint.CanWrite)
{
UpdateWriteResult(item.Name + " 写入失败:输出点不可写。", false);
return;
}
var targetState = !item.IsOn;
var result = outputPoint.TrySetOutput(targetState);
UpdateWriteResult(item.Name + (result ? (targetState ? " 已切换为 ON。" : " 已切换为 OFF。") : " 写入失败。"), result);
}
private void UpdateWriteResult(string message, bool success)
{
PageState.LastWriteMessage = message;
PageState.IsWriteSuccess = success;
PageState.LastWriteTime = DateTime.Now;
}
}
}

View File

@@ -0,0 +1,114 @@
using MainShell.HeightMeasure.ViewModel;
using MainShell.Models;
using MaxwellFramework.Core.Interfaces;
using Stylet;
using StyletIoC;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace MainShell.DeviceMaintance.ViewModel
{
public class DeviceMaintanceViewModel : BaseScreen, IPage
{
public string Name => "MenuDeviceMaint";
private const string NEEDLEBASE = "刺晶头维护";
private const string IOMONITOR = "IO监控";
private const string HARDWARETEST = "硬件维护";
private const string LASERCOMPENSATION = "激光补偿";
private readonly Dictionary<string, Screen> _viewModelDict = new Dictionary<string, Screen>();
public ObservableCollection<MenuItemWrap> MenuItemWraps { get; private set; }
private MenuItemWrap _selectedMenuItem;
public MenuItemWrap SelectedMenuItem
{
get { return _selectedMenuItem; }
set
{
if (SetAndNotify(ref _selectedMenuItem, value))
{
CurrentScreen = _viewModelDict[value.Header];
}
}
}
private Screen _currentScreen;
public Screen CurrentScreen
{
get { return _currentScreen; }
set { SetAndNotify(ref _currentScreen, value); }
}
private NeedleBaseViewModel _needleBaseViewModel;
[Inject]
public NeedleBaseViewModel NeedleBaseViewModel
{
get { return _needleBaseViewModel; }
set { _needleBaseViewModel = value; }
}
private IOMaintanceViewModel _ioMaintanceViewModel;
[Inject]
public IOMaintanceViewModel IOMaintanceViewModel
{
get { return _ioMaintanceViewModel; }
set { _ioMaintanceViewModel = value; }
}
private HardwareTestViewModel _hardwareTestViewModel;
[Inject]
public HardwareTestViewModel HardwareTestViewModel
{
get { return _hardwareTestViewModel; }
set { _hardwareTestViewModel = value; }
}
private LaserCompensationViewModel _laserCompensationViewModel;
[Inject]
public LaserCompensationViewModel LaserCompensationViewModel
{
get { return _laserCompensationViewModel; }
set { _laserCompensationViewModel = value; }
}
public DeviceMaintanceViewModel()
{
InitMenuItems();
}
protected override void OnViewLoaded()
{
base.OnViewLoaded();
if (_viewModelDict.Count == 0)
{
InitViewModelDict();
}
if (SelectedMenuItem == null)
{
SelectedMenuItem = MenuItemWraps[0];
}
}
private void InitMenuItems()
{
MenuItemWraps = new ObservableCollection<MenuItemWrap>
{
new MenuItemWrap() { Header = NEEDLEBASE, Tag = NEEDLEBASE },
new MenuItemWrap() { Header = IOMONITOR, Tag = IOMONITOR },
new MenuItemWrap() { Header = HARDWARETEST, Tag = HARDWARETEST },
new MenuItemWrap() { Header = LASERCOMPENSATION, Tag = LASERCOMPENSATION },
};
}
private void InitViewModelDict()
{
_viewModelDict.Clear();
_viewModelDict.Add(NEEDLEBASE, NeedleBaseViewModel);
_viewModelDict.Add(IOMONITOR, IOMaintanceViewModel);
_viewModelDict.Add(HARDWARETEST, HardwareTestViewModel);
_viewModelDict.Add(LASERCOMPENSATION, LaserCompensationViewModel);
}
}
}

View File

@@ -0,0 +1,164 @@
using MainShell.Hardware;
using MainShell.Log;
using MainShell.Models;
using MwFramework.Device;
using MwFramework.Device.DeviceInterface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MainShell.DeviceMaintance.ViewModel
{
public class HardwareTestViewModel:BaseScreen
{
private readonly HardwareManager _device;
private IFFUItem _ffuItem1;
private string _message = "XXXX";
public string Message
{
get
{
return _message;
}
set { SetAndNotify(ref _message, value); }
}
private string _waferBarcode = string.Empty;
/// <summary>
/// 方片扫码枪读取结果
/// </summary>
public string WaferBarcode
{
get { return _waferBarcode; }
set { SetAndNotify(ref _waferBarcode, value); }
}
private string _glassBarcode = string.Empty;
/// <summary>
/// <summary>
/// 基板扫码枪读取结果
/// </summary>
public string GlassBarcode
{
get { return _glassBarcode; }
set { SetAndNotify(ref _glassBarcode, value); }
}
private int _fFURotateSpeed ;
/// <summary>
/// <summary>
/// 基板扫码枪读取结果
/// </summary>
public int FFURotateSpeed
{
get { return _fFURotateSpeed; }
set { SetAndNotify(ref _fFURotateSpeed, value); }
}
public HardwareTestViewModel(HardwareManager hardwareManager)
{
_device = hardwareManager;
_ffuItem1 = _device.FFU?.Count > 0 ? _device.FFU[0] : null;
}
public void btnZeroClick()
{
try
{
_device.Diastimeter.ZeroReset();
}
catch (Exception ex)
{
LogManager.LogSysError(ex, true);
}
}
public void GetDarkReference()
{
IDeviceParamExtend p = _device.Diastimeter as IDeviceParamExtend;
if (p[(CommandStr)"GetDarkReference"].Execute())
{
}
else
{
}
}
public void btnGetCurrentValueClick()
{
try
{
_device.Diastimeter.GetLastSample(out double Distance);
Message = Convert.ToString(Distance);
}
catch (Exception ex)
{
LogManager.LogSysError(ex, true);
}
}
public void FFURotateSpeedChanged()
{
if (_ffuItem1 != null)
{
if (!_ffuItem1.CurrentOnOff) _ffuItem1.OnOff = true;
//_deviceDefaltSetting.Write();
_ffuItem1.SettingVelocity = FFURotateSpeed;
}
}
public void BtnOpenFFU()
{
if (_ffuItem1 != null)
{
if (!_ffuItem1.CurrentOnOff) _ffuItem1.OnOff = true;
}
}
public void BtnCloseFFU()
{
if (_ffuItem1 != null)
{
if (_ffuItem1.CurrentOnOff) _ffuItem1.OnOff = false;
}
}
public void btnScanWaferBarcodeClick()
{
try
{
//this.WaferBarcode = string.Empty;
//_device.WaferBarcodeScanner.TryScan(out string barcode, 1000);
//this.WaferBarcode = string.IsNullOrEmpty(barcode) ? "NA" : barcode;
}
catch (Exception ex)
{
LogManager.LogSysError(ex, true);
}
}
public async void btnScanGlassBarcodeClick()
{
try
{
await Task.Run(() =>
{
//this.GlassBarcode = string.Empty;
//_device.GlassBarcodeScanner.TryScan(out string barcode, 1000 * 5);
//this.GlassBarcode = string.IsNullOrEmpty(barcode) ? "NA" : barcode;
});
}
catch (Exception ex)
{
LogManager.LogSysError(ex, true);
}
}
}
}

View File

@@ -0,0 +1,38 @@
using MainShell.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Stylet;
using StyletIoC;
namespace MainShell.DeviceMaintance.ViewModel
{
public class IOMaintanceViewModel : BaseScreen
{
private IOMonitorViewModel _iOMonitorViewModel;
[Inject]
public IOMonitorViewModel IOMonitorViewModel
{
get { return _iOMonitorViewModel; }
set { _iOMonitorViewModel = value; }
}
private CylinderViewModel _cylinderViewModel;
[Inject]
public CylinderViewModel CylinderViewModel
{
get { return _cylinderViewModel; }
set { _cylinderViewModel = value; }
}
private IoTestViewModel _ioTestViewModel;
[Inject]
public IoTestViewModel IoTestViewModel
{
get { return _ioTestViewModel; }
set { _ioTestViewModel = value; }
}
}
}

View File

@@ -0,0 +1,41 @@
using Stylet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MaxwellFramework.Core.Interfaces;
using MwFramework.Device;
using MwFramework.ManagerService;
using StyletIoC;
namespace MainShell.DeviceMaintance.ViewModel
{
public class IOMonitorViewModel:Screen,IPage
{
private DeviceIoViewModel _deviceIoViewModel;
[Inject]
public DeviceIoViewModel DeviceIoViewModel
{
get { return _deviceIoViewModel; }
set { _deviceIoViewModel = value; }
}
//private IDIO ioprop;
//public IDIO IOProp
//{
// get { return ioprop; }
// set
// {
// ioprop = value;
// OnPropertyChanged("IOProp");
// }
//}
//public IOMonitorViewModel(IDeviceManager manager)
//{
// IDeviceList dlist = (IDeviceList)manager;
// IOProp = dlist.GetDevice<IDIO>("PLCIO");
//}
}
}

View File

@@ -0,0 +1,533 @@
using MainShell.Hardware;
using MainShell.Log;
using MainShell.Models;
using MwFramework.Device.Delta;
using Stylet;
using System;
using System.Globalization;
namespace MainShell.DeviceMaintance.ViewModel
{
public class IoTestViewModel : BaseScreen
{
public class DeltaBitTestState : PropertyChangedBase
{
private int _cardNo;
public int CardNo
{
get { return _cardNo; }
set { SetAndNotify(ref _cardNo, value); }
}
private int _node;
public int Node
{
get { return _node; }
set { SetAndNotify(ref _node, value); }
}
private int _slot;
public int Slot
{
get { return _slot; }
set { SetAndNotify(ref _slot, value); }
}
private int _index;
public int Index
{
get { return _index; }
set { SetAndNotify(ref _index, value); }
}
private int _subIndex;
public int SubIndex
{
get { return _subIndex; }
set { SetAndNotify(ref _subIndex, value); }
}
private int _bitNo;
public int BitNo
{
get { return _bitNo; }
set { SetAndNotify(ref _bitNo, value); }
}
private int _ioType = 1;
public int IoType
{
get { return _ioType; }
set { SetAndNotify(ref _ioType, value); }
}
private int _readIoType = 1;
public int ReadIoType
{
get { return _readIoType; }
set { SetAndNotify(ref _readIoType, value); }
}
private bool _writeValue;
public bool WriteValue
{
get { return _writeValue; }
set { SetAndNotify(ref _writeValue, value); }
}
private bool _readValue;
public bool ReadValue
{
get { return _readValue; }
set { SetAndNotify(ref _readValue, value); }
}
private ushort _returnCode;
public ushort ReturnCode
{
get { return _returnCode; }
set { SetAndNotify(ref _returnCode, value); }
}
private string _resultMessage = string.Empty;
public string ResultMessage
{
get { return _resultMessage; }
set { SetAndNotify(ref _resultMessage, value); }
}
}
public class DeltaDaTestState : PropertyChangedBase
{
private int _cardNo;
public int CardNo
{
get { return _cardNo; }
set { SetAndNotify(ref _cardNo, value); }
}
private int _node;
public int Node
{
get { return _node; }
set { SetAndNotify(ref _node, value); }
}
private int _slot;
public int Slot
{
get { return _slot; }
set { SetAndNotify(ref _slot, value); }
}
private int _index;
public int Index
{
get { return _index; }
set { SetAndNotify(ref _index, value); }
}
private int _subIndex;
public int SubIndex
{
get { return _subIndex; }
set { SetAndNotify(ref _subIndex, value); }
}
private int _byteSize = 2;
public int ByteSize
{
get { return _byteSize; }
set { SetAndNotify(ref _byteSize, value); }
}
private bool _signed = true;
public bool Signed
{
get { return _signed; }
set { SetAndNotify(ref _signed, value); }
}
private int _ioType = 1;
public int IoType
{
get { return _ioType; }
set { SetAndNotify(ref _ioType, value); }
}
private int _writeRawValue;
public int WriteRawValue
{
get { return _writeRawValue; }
set { SetAndNotify(ref _writeRawValue, value); }
}
private int _readRawValue;
public int ReadRawValue
{
get { return _readRawValue; }
set { SetAndNotify(ref _readRawValue, value); }
}
private ushort _returnCode;
public ushort ReturnCode
{
get { return _returnCode; }
set { SetAndNotify(ref _returnCode, value); }
}
private string _resultMessage = string.Empty;
public string ResultMessage
{
get { return _resultMessage; }
set { SetAndNotify(ref _resultMessage, value); }
}
}
private readonly HardwareManager _hardwareManager;
private string _cardStatusText;
public string CardStatusText
{
get { return _cardStatusText; }
set { SetAndNotify(ref _cardStatusText, value); }
}
public DeltaBitTestState BitState { get; private set; }
public DeltaDaTestState DaState { get; private set; }
public IoTestViewModel(HardwareManager hardwareManager)
{
if (hardwareManager == null)
{
throw new ArgumentNullException(nameof(hardwareManager));
}
_hardwareManager = hardwareManager;
BitState = BuildBitState();
DaState = BuildDaState();
RefreshCardStatus();
}
protected override void OnViewLoaded()
{
base.OnViewLoaded();
RefreshCardStatus();
}
public void RefreshCardStatus()
{
IDeltaIoExtend deltaIoExtend;
bool available = _hardwareManager.TryGetDeltaIoExtend(out deltaIoExtend);
CardStatusText = available ? $"Delta卡已连接{_hardwareManager.TdCard.GetType().FullName}" : "Delta卡未初始化或未实现 IDeltaIoExtend";
}
public void ReadBit()
{
try
{
IDeltaIoExtend deltaIoExtend;
if (!TryGetDeltaIoExtend(out deltaIoExtend))
{
return;
}
ushort cardNo;
ushort node;
ushort slot;
ushort index;
ushort subIndex;
byte bitNo;
ushort ioType;
if (!TryGetBitReadParameters(out cardNo, out node, out slot, out index, out subIndex, out bitNo, out ioType))
{
return;
}
bool value;
ushort result = deltaIoExtend.ReadBit(cardNo, node, slot, index, subIndex, bitNo, out value, ioType);
BitState.ReadValue = value;
BitState.ReturnCode = result;
BitState.ResultMessage = $"ReadBit 返回码:{result},结果:{value}";
}
catch (Exception ex)
{
HandleException(ex, BitState, "ReadBit 执行异常");
}
}
public void WriteBit()
{
try
{
IDeltaIoExtend deltaIoExtend;
if (!TryGetDeltaIoExtend(out deltaIoExtend))
{
return;
}
ushort cardNo;
ushort node;
ushort slot;
ushort index;
ushort subIndex;
byte bitNo;
ushort readIoType;
if (!TryGetBitWriteParameters(out cardNo, out node, out slot, out index, out subIndex, out bitNo, out readIoType))
{
return;
}
ushort result = deltaIoExtend.WriteBit(cardNo, node, slot, index, subIndex, bitNo, BitState.WriteValue, readIoType);
BitState.ReturnCode = result;
BitState.ResultMessage = $"WriteBit 返回码:{result},写入值:{BitState.WriteValue}";
}
catch (Exception ex)
{
HandleException(ex, BitState, "WriteBit 执行异常");
}
}
public void ReadDa()
{
try
{
IDeltaIoExtend deltaIoExtend;
if (!TryGetDeltaIoExtend(out deltaIoExtend))
{
return;
}
ushort cardNo;
ushort node;
ushort slot;
ushort index;
ushort subIndex;
ushort byteSize;
ushort ioType;
if (!TryGetDaReadParameters(out cardNo, out node, out slot, out index, out subIndex, out byteSize, out ioType))
{
return;
}
int rawValue;
ushort result = deltaIoExtend.ReadDA(cardNo, node, slot, index, subIndex, out rawValue, byteSize, DaState.Signed, ioType);
DaState.ReadRawValue = rawValue;
DaState.ReturnCode = result;
DaState.ResultMessage = $"ReadDA 返回码:{result},结果:{rawValue}";
}
catch (Exception ex)
{
HandleException(ex, DaState, "ReadDA 执行异常");
}
}
public void WriteDa()
{
try
{
IDeltaIoExtend deltaIoExtend;
if (!TryGetDeltaIoExtend(out deltaIoExtend))
{
return;
}
ushort cardNo;
ushort node;
ushort slot;
ushort index;
ushort subIndex;
ushort byteSize;
if (!TryGetDaWriteParameters(out cardNo, out node, out slot, out index, out subIndex, out byteSize))
{
return;
}
ushort result = deltaIoExtend.WriteDA(cardNo, node, slot, index, subIndex, DaState.WriteRawValue, byteSize);
DaState.ReturnCode = result;
DaState.ResultMessage = $"WriteDA 返回码:{result},写入值:{DaState.WriteRawValue}";
}
catch (Exception ex)
{
HandleException(ex, DaState, "WriteDA 执行异常");
}
}
private DeltaBitTestState BuildBitState()
{
DeltaBitTestState state = new DeltaBitTestState();
state.CardNo = 0;
state.Node = 0;
state.Slot = 0;
state.Index = 0;
state.SubIndex = 0;
state.BitNo = 0;
state.IoType = 1;
state.ReadIoType = 1;
return state;
}
private DeltaDaTestState BuildDaState()
{
DeltaDaTestState state = new DeltaDaTestState();
state.CardNo = 0;
state.Node = 0;
state.Slot = 0;
state.Index = 0;
state.SubIndex = 0;
state.ByteSize = 2;
state.IoType = 1;
return state;
}
private bool TryGetDeltaIoExtend(out IDeltaIoExtend deltaIoExtend)
{
RefreshCardStatus();
if (_hardwareManager.TryGetDeltaIoExtend(out deltaIoExtend))
{
return true;
}
BitState.ResultMessage = "Delta卡未初始化或未实现 IDeltaIoExtend";
DaState.ResultMessage = BitState.ResultMessage;
return false;
}
private bool TryGetBitReadParameters(out ushort cardNo, out ushort node, out ushort slot, out ushort index, out ushort subIndex, out byte bitNo, out ushort ioType)
{
cardNo = 0;
node = 0;
slot = 0;
index = 0;
subIndex = 0;
bitNo = 0;
ioType = 0;
bool isValid = TryGetUInt16(BitState.CardNo, "CardNo", out cardNo) &&
TryGetUInt16(BitState.Node, "Node", out node) &&
TryGetUInt16(BitState.Slot, "Slot", out slot) &&
TryGetHexUInt16(BitState.Index, "Index", out index) &&
TryGetHexUInt16(BitState.SubIndex, "SubIndex", out subIndex) &&
TryGetByte(BitState.BitNo, "BitNo", out bitNo) &&
TryGetUInt16(BitState.IoType, "IoType", out ioType);
return isValid;
}
private bool TryGetBitWriteParameters(out ushort cardNo, out ushort node, out ushort slot, out ushort index, out ushort subIndex, out byte bitNo, out ushort readIoType)
{
cardNo = 0;
node = 0;
slot = 0;
index = 0;
subIndex = 0;
bitNo = 0;
readIoType = 0;
bool isValid = TryGetUInt16(BitState.CardNo, "CardNo", out cardNo) &&
TryGetUInt16(BitState.Node, "Node", out node) &&
TryGetUInt16(BitState.Slot, "Slot", out slot) &&
TryGetHexUInt16(BitState.Index, "Index", out index) &&
TryGetHexUInt16(BitState.SubIndex, "SubIndex", out subIndex) &&
TryGetByte(BitState.BitNo, "BitNo", out bitNo) &&
TryGetUInt16(BitState.ReadIoType, "ReadIoType", out readIoType);
return isValid;
}
private bool TryGetDaReadParameters(out ushort cardNo, out ushort node, out ushort slot, out ushort index, out ushort subIndex, out ushort byteSize, out ushort ioType)
{
cardNo = 0;
node = 0;
slot = 0;
index = 0;
subIndex = 0;
byteSize = 0;
ioType = 0;
bool isValid = TryGetUInt16(DaState.CardNo, "CardNo", out cardNo) &&
TryGetUInt16(DaState.Node, "Node", out node) &&
TryGetUInt16(DaState.Slot, "Slot", out slot) &&
TryGetHexUInt16(DaState.Index, "Index", out index) &&
TryGetHexUInt16(DaState.SubIndex, "SubIndex", out subIndex) &&
TryGetUInt16(DaState.ByteSize, "ByteSize", out byteSize) &&
TryGetUInt16(DaState.IoType, "IoType", out ioType);
return isValid;
}
private bool TryGetDaWriteParameters(out ushort cardNo, out ushort node, out ushort slot, out ushort index, out ushort subIndex, out ushort byteSize)
{
cardNo = 0;
node = 0;
slot = 0;
index = 0;
subIndex = 0;
byteSize = 0;
bool isValid = TryGetUInt16(DaState.CardNo, "CardNo", out cardNo) &&
TryGetUInt16(DaState.Node, "Node", out node) &&
TryGetUInt16(DaState.Slot, "Slot", out slot) &&
TryGetHexUInt16(DaState.Index, "Index", out index) &&
TryGetHexUInt16(DaState.SubIndex, "SubIndex", out subIndex) &&
TryGetUInt16(DaState.ByteSize, "ByteSize", out byteSize);
return isValid;
}
private bool TryGetHexUInt16(int sourceValue, string parameterName, out ushort value)
{
string hexText = sourceValue.ToString(CultureInfo.InvariantCulture);
return ushort.TryParse(hexText, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out value)
? true
: SetHexUInt16Error(parameterName, out value);
}
private bool SetHexUInt16Error(string parameterName, out ushort value)
{
value = 0;
string message = $"参数 {parameterName} 超出十六进制 ushort 范围。";
BitState.ResultMessage = message;
DaState.ResultMessage = message;
return false;
}
private bool TryGetUInt16(int sourceValue, string parameterName, out ushort value)
{
if (sourceValue < ushort.MinValue || sourceValue > ushort.MaxValue)
{
value = 0;
string message = $"参数 {parameterName} 超出 ushort 范围。";
BitState.ResultMessage = message;
DaState.ResultMessage = message;
return false;
}
value = (ushort)sourceValue;
return true;
}
private bool TryGetByte(int sourceValue, string parameterName, out byte value)
{
if (sourceValue < byte.MinValue || sourceValue > byte.MaxValue)
{
value = 0;
string message = $"参数 {parameterName} 超出 byte 范围。";
BitState.ResultMessage = message;
return false;
}
value = (byte)sourceValue;
return true;
}
private void HandleException(Exception ex, DeltaBitTestState state, string operationName)
{
state.ResultMessage = operationName;
LogManager.LogSysError(ex, true);
}
private void HandleException(Exception ex, DeltaDaTestState state, string operationName)
{
state.ResultMessage = operationName;
LogManager.LogSysError(ex, true);
}
}
}

View File

@@ -0,0 +1,446 @@
using MainShell.Common;
using MainShell.Hardware;
using MainShell.DeviceMaintance.Model;
using MainShell.Log;
using MainShell.Motion;
using MaxwellFramework.Core.Interfaces;
using Stylet;
using StyletIoC;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MwFramework.Device;
namespace MainShell.DeviceMaintance.ViewModel
{
public class LaserCompensationViewModel : DeviceMaintanceBaseViewModel, IPage
{
private const string ProjectPageName = "激光补偿";
private const int MinimumMoveTimeoutMilliseconds = 15000;
private const double MoveTimeoutScaleFactor = 3d;
private const int MoveTimeoutExtraMilliseconds = 2000;
private readonly SafeAxisMotion _safeAxisMotion;
private readonly AxisSpeedManager _axisSpeedManager;
private readonly HardwareManager _hardwareManager;
private CancellationTokenSource _cancellationTokenSource;
private bool _uiEnable = true;
private bool _isRunning;
private string _statusMessage;
private int _currentLoopIndex;
private int _currentPointIndex;
private double _currentTargetPosition;
private string _selectedAxisName;
public LaserCompensationViewModel(SafeAxisMotion safeAxisMotion, AxisSpeedManager axisSpeedManager, HardwareManager hardwareManager)
{
_safeAxisMotion = safeAxisMotion;
_axisSpeedManager = axisSpeedManager;
_hardwareManager = hardwareManager;
Setting = new LaserCompensationSetting();
Setting.LoadFromFile();
AxisNames = new System.Collections.ObjectModel.ObservableCollection<string>(BuildAxisNames());
if (!string.IsNullOrWhiteSpace(Setting.AxisName) && AxisNames.Contains(Setting.AxisName))
{
SelectedAxisName = Setting.AxisName;
}
else
{
SelectedAxisName = AxisNames.FirstOrDefault();
}
StatusMessage = "待机";
}
public string Name => "LaserCompensationMaint";
public LaserCompensationSetting Setting { get; }
public System.Collections.ObjectModel.ObservableCollection<string> AxisNames { get; }
public string SelectedAxisName
{
get { return _selectedAxisName; }
set
{
if (SetAndNotify(ref _selectedAxisName, value))
{
Setting.AxisName = value;
}
}
}
public bool UiEnable
{
get { return _uiEnable; }
set
{
if (SetAndNotify(ref _uiEnable, value))
{
OnUiStateChanged(value);
}
}
}
public bool IsRunning
{
get { return _isRunning; }
set { SetAndNotify(ref _isRunning, value); }
}
public string StatusMessage
{
get { return _statusMessage; }
set { SetAndNotify(ref _statusMessage, value); }
}
public int CurrentLoopIndex
{
get { return _currentLoopIndex; }
set { SetAndNotify(ref _currentLoopIndex, value); }
}
public int CurrentPointIndex
{
get { return _currentPointIndex; }
set { SetAndNotify(ref _currentPointIndex, value); }
}
public double CurrentTargetPosition
{
get { return _currentTargetPosition; }
set { SetAndNotify(ref _currentTargetPosition, value); }
}
public async Task StartAsync()
{
if (IsRunning)
{
return;
}
string validationMessage = ValidateSetting();
if (!string.IsNullOrWhiteSpace(validationMessage))
{
StatusMessage = validationMessage;
LocalizedMessageBox.Show(MessageKey.ParamInvalid, MessageKey.TitleError, System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
return;
}
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = new CancellationTokenSource();
UiEnable = false;
IsRunning = true;
CurrentLoopIndex = 0;
CurrentPointIndex = 0;
CurrentTargetPosition = 0d;
Setting.AxisName = SelectedAxisName;
StatusMessage = "激光补偿运行中";
IoC.Get<IProjectManager>().EnablePageAndDisableOther(ProjectPageName);
BuildStartLogMessage().LogInfo();
try
{
CancellationToken cancellationToken = _cancellationTokenSource.Token;
await ExecuteCompensationAsync(cancellationToken).ConfigureAwait(true);
StatusMessage = "激光补偿执行完成";
BuildFinishLogMessage("完成").LogInfo();
}
catch (OperationCanceledException)
{
StatusMessage = "激光补偿已停止";
BuildFinishLogMessage("已停止").LogInfo();
}
catch (Exception ex)
{
StatusMessage = $"激光补偿异常:{ex.Message}";
LogManager.LogSysError(ex, true);
}
finally
{
IsRunning = false;
UiEnable = true;
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = null;
IoC.Get<IProjectManager>().SwitchState();
}
}
public void Stop()
{
if (!IsRunning)
{
return;
}
StatusMessage = "正在停止激光补偿";
"激光补偿收到停止请求".LogInfo();
_cancellationTokenSource?.Cancel();
}
public void Save()
{
try
{
Setting.SaveToFile();
StatusMessage = "参数已保存";
"激光补偿参数已保存".LogInfo();
LocalizedMessageBox.Show(MessageKey.CommonSaveSucceeded, MessageKey.TitleInfo, System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information);
}
catch (Exception ex)
{
StatusMessage = $"参数保存失败:{ex.Message}";
LogManager.LogSysError(ex, true);
}
}
private async Task ExecuteCompensationAsync(CancellationToken cancellationToken)
{
IReadOnlyList<double> trajectory = BuildTrajectory();
ApplyAxisSpeedIfPossible();
for (int workIndex = 0; workIndex < Setting.WorkCount; workIndex++)
{
cancellationToken.ThrowIfCancellationRequested();
CurrentLoopIndex = workIndex + 1;
$"激光补偿开始第{CurrentLoopIndex}次循环,总点数={trajectory.Count}".LogInfo();
for (int pointIndex = 0; pointIndex < trajectory.Count; pointIndex++)
{
cancellationToken.ThrowIfCancellationRequested();
double targetPosition = trajectory[pointIndex];
CurrentPointIndex = pointIndex + 1;
CurrentTargetPosition = targetPosition;
StatusMessage = $"循环 {CurrentLoopIndex}/{Setting.WorkCount},点位 {CurrentPointIndex}/{trajectory.Count}";
int timeoutMilliseconds = CalculateMoveTimeoutMilliseconds(targetPosition, trajectory, pointIndex);
$"激光补偿移动开始:轴={Setting.AxisName},循环={CurrentLoopIndex},点位={CurrentPointIndex},目标={targetPosition:F4},超时={timeoutMilliseconds}ms".LogInfo();
MotionResult motionResult = await _safeAxisMotion.MoveAbsAsync(
Setting.AxisName,
targetPosition,
timeoutMilliseconds,
cancellationToken,
alarmId: null).ConfigureAwait(false);
motionResult.EnsureSuccess();
$"激光补偿移动完成:轴={Setting.AxisName},循环={CurrentLoopIndex},点位={CurrentPointIndex},目标={targetPosition:F4},到位={motionResult.EndPosition:F4}".LogInfo();
if (Setting.DwellTime > 0d)
{
int dwellMilliseconds = (int)Math.Ceiling(Setting.DwellTime * 1000d);
$"激光补偿延时采样:{dwellMilliseconds}ms".LogInfo();
await Task.Delay(dwellMilliseconds, cancellationToken).ConfigureAwait(false);
}
}
}
}
private void ApplyAxisSpeedIfPossible()
{
try
{
if (!string.IsNullOrWhiteSpace(Setting.AxisName) && Setting.Speed > 0d)
{
_axisSpeedManager.SetAxisSpeed(Setting.AxisName, Setting.Speed);
$"激光补偿轴速度已设置:轴={Setting.AxisName}Speed={Setting.Speed:F4}".LogInfo();
}
}
catch (Exception ex)
{
$"激光补偿轴速度设置失败:{ex}".LogSysError();
throw;
}
}
private IReadOnlyList<double> BuildTrajectory()
{
List<double> measurePoints = Enumerable.Range(0, Setting.StepsCount)
.Select(index => Setting.StartPos + index * Setting.Steps)
.ToList();
double readyPosition = Setting.StartPos - Setting.JumpPos;
double overshootPosition = measurePoints[measurePoints.Count - 1] + Setting.JumpPos;
List<double> trajectory = new List<double>(measurePoints.Count * 2 + 3)
{
readyPosition
};
trajectory.AddRange(measurePoints);
trajectory.Add(overshootPosition);
trajectory.AddRange(measurePoints.AsEnumerable().Reverse());
trajectory.Add(readyPosition);
return trajectory;
}
private int CalculateMoveTimeoutMilliseconds(double targetPosition, IReadOnlyList<double> trajectory, int pointIndex)
{
IAxis axis = _hardwareManager.GetAxisByName(Setting.AxisName);
double startPosition = GetMoveStartPosition(axis, trajectory, pointIndex, targetPosition);
double distance = Math.Abs(targetPosition - startPosition);
double speed = ResolvePositiveMotionParameter(axis != null ? axis.Param.Velocity : 0d, Math.Abs(Setting.Speed));
if (speed <= 0d)
{
return MinimumMoveTimeoutMilliseconds;
}
double acceleration = ResolvePositiveMotionParameter(axis != null ? axis.Param.Accelerate : 0d, 0d);
double deceleration = ResolvePositiveMotionParameter(axis != null ? axis.Param.Decelerate : 0d, acceleration);
double expectedMilliseconds = CalculateExpectedMoveMilliseconds(distance, speed, acceleration, deceleration);
return Math.Max(MinimumMoveTimeoutMilliseconds, (int)Math.Ceiling(expectedMilliseconds * MoveTimeoutScaleFactor + MoveTimeoutExtraMilliseconds));
}
private static double GetMoveStartPosition(IAxis axis, IReadOnlyList<double> trajectory, int pointIndex, double targetPosition)
{
if (pointIndex > 0)
{
return trajectory[pointIndex - 1];
}
if (axis != null)
{
return axis.State != null ? axis.State.ActualPos : axis.GetPositionImmediate();
}
return targetPosition;
}
private static double ResolvePositiveMotionParameter(double primaryValue, double fallbackValue)
{
if (!double.IsNaN(primaryValue) && !double.IsInfinity(primaryValue) && primaryValue > 0d)
{
return primaryValue;
}
if (!double.IsNaN(fallbackValue) && !double.IsInfinity(fallbackValue) && fallbackValue > 0d)
{
return fallbackValue;
}
return 0d;
}
private static double CalculateExpectedMoveMilliseconds(double distance, double speed, double acceleration, double deceleration)
{
if (distance <= 0d)
{
return 0d;
}
if (speed <= 0d)
{
return 0d;
}
if (acceleration <= 0d || deceleration <= 0d)
{
return distance / speed * 1000d;
}
double accelerateDistance = speed * speed / (2d * acceleration);
double decelerateDistance = speed * speed / (2d * deceleration);
double criticalDistance = accelerateDistance + decelerateDistance;
double expectedSeconds;
if (distance >= criticalDistance)
{
expectedSeconds = speed / acceleration + speed / deceleration + (distance - criticalDistance) / speed;
}
else
{
double peakSpeed = Math.Sqrt(2d * distance * acceleration * deceleration / (acceleration + deceleration));
expectedSeconds = peakSpeed / acceleration + peakSpeed / deceleration;
}
return expectedSeconds * 1000d;
}
private string ValidateSetting()
{
if (string.IsNullOrWhiteSpace(Setting.AxisName))
{
return "轴名称不能为空";
}
if (!AxisNames.Contains(Setting.AxisName))
{
return "请选择有效的轴名称";
}
if (Setting.StepsCount <= 0)
{
return "步距次数必须大于0";
}
if (Setting.WorkCount <= 0)
{
return "循环次数必须大于0";
}
if (Math.Abs(Setting.Steps) <= 0d)
{
return "步距必须非0";
}
if (Setting.JumpPos < 0d)
{
return "跃程不能小于0";
}
if (Setting.Speed <= 0d)
{
return "速度必须大于0";
}
if (Setting.DwellTime < 0d)
{
return "延时时间不能小于0";
}
return null;
}
private string BuildStartLogMessage()
{
return $"激光补偿启动:轴={Setting.AxisName}StartPos={Setting.StartPos:F4}Steps={Setting.Steps:F4}StepsCount={Setting.StepsCount}JumpPos={Setting.JumpPos:F4}WorkCount={Setting.WorkCount}Speed={Setting.Speed:F4}DwellTime={Setting.DwellTime:F3}s";
}
private string BuildFinishLogMessage(string state)
{
return $"激光补偿结束:状态={state},轴={Setting.AxisName},已执行循环={CurrentLoopIndex},最后点位={CurrentPointIndex},最后目标={CurrentTargetPosition:F4}";
}
private IEnumerable<string> BuildAxisNames()
{
return new[]
{
GetAxisName(_hardwareManager?.Axis_PHS_X1, MainShell.Hardware.AxisName.Axis_PHS_X1),
GetAxisName(_hardwareManager?.Axis_PHS_X2, MainShell.Hardware.AxisName.Axis_PHS_X2),
GetAxisName(_hardwareManager?.Axis_PHS_Y1, MainShell.Hardware.AxisName.Axis_PHS_Y1),
GetAxisName(_hardwareManager?.Axis_WS_X3, MainShell.Hardware.AxisName.Axis_WS_X3),
GetAxisName(_hardwareManager?.Axis_Stage_Y3, MainShell.Hardware.AxisName.Axis_Stage_Y3),
GetAxisName(_hardwareManager?.Axis_WS_R, MainShell.Hardware.AxisName.Axis_WS_R),
}.Where(x => !string.IsNullOrWhiteSpace(x)).Distinct().ToArray();
}
private static string GetAxisName(IAxis axis, string fallbackName)
{
if (axis == null || string.IsNullOrWhiteSpace(axis.Name))
{
return fallbackName;
}
return axis.Name;
}
}
}

View File

@@ -0,0 +1,119 @@
using MainShell.Hardware;
using MainShell.Models;
using MainShell.Recipe.Models;
using MaxwellFramework.Core.Common;
using MaxwellFramework.Core.Interfaces;
using MwFramework.ManagerService;
using MXJM.Parameter.Maintance;
using Stylet;
using StyletIoC;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MainShell.DeviceMaintance.ViewModel
{
public class NeedleBaseViewModel : CameraBaseViewModel, IPage
{
private readonly Dictionary<string, Screen> _screenDics = new Dictionary<string, Screen>();
private const string NEEDLE_CAMERA_CALIB = "针尖相机校准";
private const string CAMERA_ACCURACY_CALIB = "针印检测";
private const string NEEDLECALIB = "针尖对刀检查";
private Screen _currentScreen;
public Screen CurrentScreen
{
get => _currentScreen;
set { SetAndNotify(ref _currentScreen, value); }
}
private ObservableCollection<string> _navigationItems = new ObservableCollection<string>();
public ObservableCollection<string> NavigationItems
{
get => _navigationItems;
set
{
_navigationItems = value;
OnPropertyChanged(nameof(NavigationItems));
}
}
private string _selectedItem;
public string SelectedItem
{
get => _selectedItem;
set
{
_selectedItem = value;
OnPropertyChanged(nameof(SelectedItem));
// 当选择项改变时更新当前ViewModel
if (_selectedItem != null)
{
CurrentScreen = _screenDics[value];
}
}
}
private NeedleCaliViewModel _needleCaliViewModel;
[Inject]
public NeedleCaliViewModel NeedleCaliViewModel
{
get { return _needleCaliViewModel; }
set { _needleCaliViewModel = value; }
}
private NeedleCameraPrintViewModel _needleCameraPrintViewModel;
[Inject]
public NeedleCameraPrintViewModel NeedleCameraPrintViewModel
{
get { return _needleCameraPrintViewModel; }
set { _needleCameraPrintViewModel = value; }
}
private CameraAccuracyCalibrationViewModel _cameraAccuracyCalibrationViewModel;
[Inject]
public CameraAccuracyCalibrationViewModel CameraAccuracyCalibrationViewModel
{
get { return _cameraAccuracyCalibrationViewModel; }
set { _cameraAccuracyCalibrationViewModel = value; }
}
private HardwareManager _hardwareManager;
public NeedleBaseViewModel(HardwareManager hardwareManager)
{
_hardwareManager = hardwareManager ?? throw new ArgumentNullException(nameof(hardwareManager));
_cameraAxisViewModel = IoC.Get<Common.Display.ViewModel.CameraAxisViewModel>();
_cameraAxisViewModel.CameraAxisDevices.HardwareDeviceList = hardwareManager.CameraAxisManager.TopCameraAxisDevices;
InitNavigationItems();
}
protected override void OnViewLoaded()
{
base.OnViewLoaded();
if (_screenDics.Count == 0)
{
InitScreenDics();
}
if (SelectedItem == null)
SelectedItem = NavigationItems[0];
}
public void InitNavigationItems()
{
NavigationItems.Add(NEEDLE_CAMERA_CALIB);
NavigationItems.Add(CAMERA_ACCURACY_CALIB);
NavigationItems.Add(NEEDLECALIB);
}
public void InitScreenDics()
{
_screenDics.Add(NEEDLE_CAMERA_CALIB, NeedleCameraPrintViewModel);
_screenDics.Add(NEEDLECALIB, NeedleCaliViewModel);
_screenDics.Add(CAMERA_ACCURACY_CALIB, CameraAccuracyCalibrationViewModel);
}
}
}

View File

@@ -0,0 +1,454 @@
using MainShell.Common;
using MainShell.DeviceMaintance.Model;
using MainShell.EventArgsFolder;
using MainShell.Hardware;
using MainShell.Models;
using MainShell.Motion;
using MainShell.Parameter;
using MainShell.Process;
using MainShell.Recipe.Models;
using MaxwellControl.Tools;
using MaxwellFramework.Core.Interfaces;
using MW.WorkFlow;
using MwFramework.Device;
using MwFramework.ManagerService;
using MXJM.Parameter.Maintance;
using Stylet;
using StyletIoC;
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
namespace MainShell.DeviceMaintance.ViewModel
{
public class NeedleCaliViewModel : DeviceMaintanceBaseViewModel, IPage, IHandle<NeedleZCalibrationResultEventArgs>
{
private const string CalibrationWorkflowName = "NeedleZCalibration";
private readonly IParameterManager _parameterManager;
private readonly IParamList _paramList;
private readonly SafeAxisMotion _safeAxisMotion;
private readonly StagePlatformMotionService _stagePlatformMotionService;
private readonly HardwareManager _hardwareManager;
private readonly IDeviceIoMonitorService _deviceIoMonitorService;
private readonly IEventAggregator _eventAggregator;
private readonly WorkflowRunner _workflowRunner;
private readonly NeedleZCalibrationService _needleZCalibrationService;
private ParameterHelper _parameterHelper = new ParameterHelper();
private NeedleCalibrationSetting _needleCalibrationSetting;
private NeedleZCalibrationItem _needleZCalibrationItem;
private CancellationTokenSource _cancellationTokenSource;
private bool _uiEnable = true;
private bool _autoRaiseZ1 = true;
private bool _isEnabledNeedleCalibrationControl = true;
private NeedleTouchRecord _selectedRecord;
public NeedleCaliViewModel(IParameterManager parameterManager, SafeAxisMotion safeAxisMotion,
StagePlatformMotionService stagePlatformMotionService, HardwareManager hardwareManager,
IDeviceIoMonitorService deviceIoMonitorService, IEventAggregator eventAggregator,
WorkflowRunner workflowRunner, NeedleZCalibrationService needleZCalibrationService)
{
_parameterManager = parameterManager;
_paramList = parameterManager as IParamList;
_safeAxisMotion = safeAxisMotion;
_stagePlatformMotionService = stagePlatformMotionService;
_hardwareManager = hardwareManager;
_deviceIoMonitorService = deviceIoMonitorService;
_eventAggregator = eventAggregator;
_workflowRunner = workflowRunner;
_needleZCalibrationService = needleZCalibrationService;
_eventAggregator?.Subscribe(this);
}
public string Name { get; set; } = "NeedleCaliMaint";
public ParameterHelper ParameterHelper
{
get => _parameterHelper;
set => SetAndNotify(ref _parameterHelper, value);
}
public NeedleCalibrationSetting NeedleCalibrationSetting
{
get => _needleCalibrationSetting;
set => SetAndNotify(ref _needleCalibrationSetting, value);
}
public NeedleZCalibrationItem NeedleZCalibrationItem
{
get => _needleZCalibrationItem;
set => SetAndNotify(ref _needleZCalibrationItem, value);
}
public bool UiEnable
{
get => _uiEnable;
set
{
if (SetAndNotify(ref _uiEnable, value))
{
OnUiStateChanged(value);
}
}
}
public bool AutoRaiseZ1
{
get => _autoRaiseZ1;
set => SetAndNotify(ref _autoRaiseZ1, value);
}
public bool IsEnabledNeedleCalibrationControl
{
get => _isEnabledNeedleCalibrationControl;
set => SetAndNotify(ref _isEnabledNeedleCalibrationControl, value);
}
public NeedleTouchRecord SelectedRecord
{
get => _selectedRecord;
set => SetAndNotify(ref _selectedRecord, value);
}
protected override void OnViewLoaded()
{
base.OnViewLoaded();
LoadParameters();
}
protected override void OnClose()
{
_eventAggregator?.Unsubscribe(this);
base.OnClose();
}
public void Handle(NeedleZCalibrationResultEventArgs message)
{
if (message == null || NeedleZCalibrationItem == null)
{
return;
}
CommonUti.RunOnUi(() =>
{
EnsureRecordCollection();
int index = NeedleZCalibrationItem.NeedleTouchRecords.Count + 1;
NeedleZCalibrationItem.NeedleTouchHeight = message.Result;
NeedleZCalibrationItem.NeedleTouchRecords.Add(new NeedleTouchRecord
{
CurrentCount = index,
Height = message.Result,
});
SelectedRecord = NeedleZCalibrationItem.NeedleTouchRecords.LastOrDefault();
RefreshStatistics();
});
}
public void MoveCzCurrentLocation()
{
ExecuteMotion(() =>
{
if (NeedleZCalibrationItem == null)
{
return;
}
_safeAxisMotion.MoveAbs(_hardwareManager.Axis_SZ, NeedleZCalibrationItem.CZHeight);
_stagePlatformMotionService.MoveFlat(NeedleZCalibrationItem.StageHeight);
});
}
public void ReadGantry2CurrentLocation()
{
CommonUti.RunOnUi(() =>
{
if (NeedleZCalibrationItem == null)
{
return;
}
NeedleZCalibrationItem.Gantry2AvoidPositionX = GetAxisPosition(_hardwareManager.Axis_X2);
NeedleZCalibrationItem.Gantry2AvoidPositionY = GetAxisPosition(_hardwareManager.Axis_Y2);
});
}
public void MoveGantry2ToCurrentLocation()
{
ExecuteMotion(() =>
{
if (NeedleZCalibrationItem == null)
{
return;
}
_safeAxisMotion.MoveAbs(_hardwareManager.Axis_X2, NeedleZCalibrationItem.Gantry2AvoidPositionX);
_safeAxisMotion.MoveAbs(_hardwareManager.Axis_Y2, NeedleZCalibrationItem.Gantry2AvoidPositionY);
});
}
public void ReadSupportPinCurrentLocation()
{
CommonUti.RunOnUi(() =>
{
if (NeedleZCalibrationItem == null)
{
return;
}
NeedleZCalibrationItem.SupportPinPositionX = GetAxisPosition(_hardwareManager.Axis_X1);
NeedleZCalibrationItem.SupportPinPositionY = GetAxisPosition(_hardwareManager.Axis_Y1);
});
}
public void MoveSupportPinToCurrentLocation()
{
ExecuteMotion(() =>
{
if (NeedleZCalibrationItem == null)
{
return;
}
_safeAxisMotion.MoveAbs(_hardwareManager.Axis_X1, NeedleZCalibrationItem.SupportPinPositionX);
_safeAxisMotion.MoveAbs(_hardwareManager.Axis_Y1, NeedleZCalibrationItem.SupportPinPositionY);
});
}
public void SetBaseHeight()
{
CommonUti.RunOnUi(() =>
{
if (NeedleZCalibrationItem == null)
{
return;
}
NeedleZCalibrationItem.NeedleTouchHeightBase = NeedleZCalibrationItem.CurrentNeedleTouchHeight;
RefreshStatistics();
});
}
public async void StartSingleZ1CalibrationAsync()
{
await ExecuteCalibrationAsync(1, false);
}
public void UseCurrentZ1Height()
{
CommonUti.RunOnUi(() =>
{
if (NeedleZCalibrationItem == null)
{
return;
}
NeedleZCalibrationItem.CurrentNeedleTouchHeight = NeedleZCalibrationItem.NeedleTouchHeightAve + NeedleZCalibrationItem.KnifeOffset;
RefreshStatistics();
SaveParameterInternal(true);
});
}
public async void StartCalibrationAsync()
{
await ExecuteCalibrationAsync(Math.Max(1, NeedleZCalibrationItem != null ? NeedleZCalibrationItem.NeedleTouchCount : 1), true);
}
public async void StopCalibrationAsync()
{
_cancellationTokenSource?.Cancel();
if (_workflowRunner != null && _workflowRunner.IsRunning)
{
await _workflowRunner.StopAsync();
}
_safeAxisMotion.Stop(
_hardwareManager.Axis_X1,
_hardwareManager.Axis_X2,
_hardwareManager.Axis_Y1,
_hardwareManager.Axis_Y2,
_hardwareManager.Axis_Z1,
_hardwareManager.Axis_SZ,
_hardwareManager.Axis_Stage_Z7,
_hardwareManager.Axis_Stage_Z8,
_hardwareManager.Axis_Stage_Z9);
UiEnable = true;
}
public void SaveCalibration()
{
CommonUti.RunOnUi(() => SaveParameterInternal(true));
}
private async Task ExecuteCalibrationAsync(int touchCount, bool clearRecords)
{
if (NeedleZCalibrationItem == null)
{
LoadParameters();
}
if (NeedleZCalibrationItem == null)
{
LocalizedMessageBox.Show(MessageKey.NeedleCalibrationLoadFailed, MessageKey.TitleError);
return;
}
if (touchCount <= 0)
{
LocalizedMessageBox.Show(MessageKey.NeedleCalibrationTouchCountMustGreaterThanZero, MessageKey.TitleWarning);
return;
}
InitCancelToken();
if (clearRecords)
{
CommonUti.RunOnUi(() =>
{
EnsureRecordCollection();
NeedleZCalibrationItem.NeedleTouchRecords.Clear();
NeedleZCalibrationItem.NeedleTouchHeight = 0;
NeedleZCalibrationItem.NeedleTouchHeightAve = 0;
NeedleZCalibrationItem.CurrentNeedleTouchHeight = 0;
NeedleZCalibrationItem.NeedleTouchOffset = 0;
});
}
UiEnable = false;
try
{
WorkflowContext context = new WorkflowContext();
NeedleZCalibrationWorkflowData workflowData = new NeedleZCalibrationWorkflowData(
CalibrationWorkflowName,
touchCount,
AutoRaiseZ1,
_cancellationTokenSource.Token,
_eventAggregator,
_hardwareManager,
_safeAxisMotion,
_parameterManager,
_deviceIoMonitorService);
context.SetData(WorkflowContextKeys.WorkflowName, workflowData.WorkflowName);
context.SetData(WorkflowContextKeys.NeedleZCalibrationWorkflowData, workflowData);
NeedleZCalibrationActivity activity = new NeedleZCalibrationActivity(_needleZCalibrationService);
WorkflowRunCompletedEventArgs result = await _workflowRunner.RunActivityWithResultAsync(activity, context);
switch (result != null ? result.FinalState : WorkflowState.Faulted)
{
case WorkflowState.Completed:
RefreshStatistics();
LocalizedMessageBox.Show(MessageKey.NeedleCalibrationCompleted, MessageKey.TitleInfo);
break;
case WorkflowState.Canceled:
LocalizedMessageBox.Show(MessageKey.NeedleCalibrationStopped, MessageKey.TitleWarning);
break;
case WorkflowState.Faulted:
string failureMessage = string.IsNullOrWhiteSpace(result != null ? result.FailureMessage : null)
? (result != null ? result.Error : null)
: result.FailureMessage;
if (string.IsNullOrWhiteSpace(failureMessage))
{
LocalizedMessageBox.Show(MessageKey.ProcessFailed, MessageKey.TitleError);
}
else
{
LocalizedMessageBox.ShowFormat(MessageKey.ProcessFailedWithReason, MessageKey.TitleError, MessageBoxButton.OK, MessageBoxImage.Error, failureMessage);
}
break;
}
}
catch (OperationCanceledException)
{
LocalizedMessageBox.Show(MessageKey.NeedleCalibrationCanceled, MessageKey.TitleWarning);
}
catch (Exception ex)
{
LocalizedMessageBox.ShowFormat(MessageKey.ProcessFailedWithReason, MessageKey.TitleError, MessageBoxButton.OK, MessageBoxImage.Error, ex.Message);
}
finally
{
UiEnable = true;
}
}
private void RefreshStatistics()
{
if (NeedleZCalibrationItem == null)
{
return;
}
ObservableCollection<NeedleTouchRecord> records = NeedleZCalibrationItem.NeedleTouchRecords;
if (records == null || records.Count == 0)
{
NeedleZCalibrationItem.NeedleTouchHeightAve = 0;
NeedleZCalibrationItem.CurrentNeedleTouchHeight = 0;
NeedleZCalibrationItem.NeedleTouchOffset = 0;
return;
}
NeedleZCalibrationItem.NeedleTouchHeightAve = records.Average(x => x.Height);
NeedleZCalibrationItem.CurrentNeedleTouchHeight = NeedleZCalibrationItem.NeedleTouchHeightAve + NeedleZCalibrationItem.KnifeOffset;
NeedleZCalibrationItem.NeedleTouchOffset = NeedleZCalibrationItem.CurrentNeedleTouchHeight - NeedleZCalibrationItem.NeedleTouchHeightBase;
}
private void SaveParameterInternal(bool showSuccessMessage)
{
NeedleCalibrationSetting?.Write();
ParameterHelper?.RaiseValueAccept();
if (showSuccessMessage)
{
LocalizedMessageBox.Show(MessageKey.CommonSaveSucceeded, MessageKey.TitleInfo);
}
}
private void LoadParameters()
{
NeedleCalibrationSetting = _paramList?.GetParameter<NeedleCalibrationSetting>();
NeedleZCalibrationItem = NeedleCalibrationSetting != null ? NeedleCalibrationSetting.NeedleZCalibrationItem : null;
EnsureRecordCollection();
}
private void EnsureRecordCollection()
{
if (NeedleZCalibrationItem != null && NeedleZCalibrationItem.NeedleTouchRecords == null)
{
NeedleZCalibrationItem.NeedleTouchRecords = new ObservableCollection<NeedleTouchRecord>();
}
}
private void InitCancelToken()
{
_cancellationTokenSource?.Cancel();
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = new CancellationTokenSource();
}
private double GetAxisPosition(IAxis axis)
{
if (axis == null)
{
return 0;
}
return axis.State != null ? axis.State.ActualPos : axis.GetPositionImmediate();
}
private void ExecuteMotion(Action action)
{
CommonUti.RunOnUi(() =>
{
try
{
action?.Invoke();
}
catch (Exception ex)
{
LocalizedMessageBox.ShowFormat(MessageKey.ProcessFailedWithReason, MessageKey.TitleError, MessageBoxButton.OK, MessageBoxImage.Error, ex.Message);
}
});
}
}
}

View File

@@ -0,0 +1,536 @@
using MainShell.Common;
using MainShell.DeviceMaintance.Model;
using MainShell.Hardware;
using MainShell.Log;
using MainShell.Models;
using MainShell.Motion;
using MainShell.Parameter;
using MaxwellControl.Tools;
using MaxwellFramework.Core.Interfaces;
using MwFramework.ManagerService;
using Stylet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace MainShell.DeviceMaintance.ViewModel
{
public class NeedleCameraPrintViewModel : DeviceMaintanceBaseViewModel
{
private NeedlePrintCalibrateSetting _needlePrintCalibrateSetting;
private readonly IParamList _paramList;
private readonly HardwareManager _device;
private readonly SafeAxisMotion _safeMotion;
private readonly GlobalParameterContext _globalParam;
private CancellationTokenSource _cancellationTokenSource;
private List<Point> _workPos;
private readonly double _z1Speed = 70;
private MaintanceRecord maintanceRecord;
private ParameterHelper _parameterHelper = new ParameterHelper();
public ParameterHelper ParameterHelper
{
get
{
return _parameterHelper;
}
set
{
_parameterHelper = value;
OnPropertyChanged(nameof(ParameterHelper));
}
}
private MPoint _cameraPoint;
public MPoint CameraPoint
{
get { return _cameraPoint; }
set { SetAndNotify(ref _cameraPoint, value); }
}
private MPoint _currentNeedlePoint;
public MPoint CurrentNeedlePoint
{
get { return _currentNeedlePoint; }
set { SetAndNotify(ref _currentNeedlePoint, value); }
}
private MPoint _currentNeedleOffsetPoint;
public MPoint CurrentNeedleOffsetPoint
{
get { return _currentNeedleOffsetPoint; }
set { SetAndNotify(ref _currentNeedleOffsetPoint, value); }
}
private NeedlePrintCalibrateParameter _needlePrintCalibrateParameter;
public NeedlePrintCalibrateParameter NeedlePrintCalibrateParameter
{
get { return _needlePrintCalibrateParameter; }
set { SetAndNotify(ref _needlePrintCalibrateParameter, value); }
}
private bool _uiEnable = true;
public bool UiEnable
{
get { return _uiEnable; }
set
{
if (SetAndNotify(ref _uiEnable, value))
{
OnUiStateChanged(value);
}
}
}
/*
public NeedleCameraPrintViewModel(IParameterManager parameterManager, GlobalParam globalParam, HardwareManager hardwareManager, SafeAxisMotion safeAxisMotion)
{
_currentNeedleOffsetPoint = new MPoint();
CurrentNeedlePoint = new MPoint();
_cameraPoint = new MPoint();
_workPos = new List<Point>();
_device = hardwareManager;
_safeMotion = safeAxisMotion;
_globalParam = globalParam;
_paramList = parameterManager as IParamList;
_needlePrintCalibrateSetting = _globalParam.NeedlePrintCalibrateSetting;
_needlePrintCalibrateParameter = _needlePrintCalibrateSetting.NeedlePrintCalibrateParameter;
SetSpeed(50);
CalculteWorkPos();
maintanceRecord = new MaintanceRecord()
{
DeviceId = LogManager.MachineID,
MaintanceType = MaintanceType.针印验证,
};
}
protected override void OnViewLoaded()
{
base.OnViewLoaded();
NeedlePrintCalibrateParameter = _needlePrintCalibrateSetting.NeedlePrintCalibrateParameter;
var needleCalibrationSetting = _globalParam.NeedleCalibrationSetting;
CurrentNeedleOffsetPoint.X = needleCalibrationSetting.NeedleXYCalibrationItem.OffsetX;
CurrentNeedleOffsetPoint.Y = needleCalibrationSetting.NeedleXYCalibrationItem.OffsetY;
}
public void SpeedChanged(object sender, EventArgs eventArgs)
{
if (sender is RadioButton radioButton)
{
if (radioButton.Tag != null)
{
var speed = Convert.ToInt32(radioButton.Tag);
SetSpeed(speed);
}
}
}
private void SetSpeed(double speed)
{
_safeMotion.SetAxisSpeed(_device.Axis_X1, speed);
_safeMotion.SetAxisSpeed(_device.Axis_Y1, speed);
_safeMotion.SetAxisSpeed(_device.Axis_X2, speed);
_safeMotion.SetAxisSpeed(_device.Axis_Y2, speed);
_safeMotion.SetAxisSpeed(_device.Axis_Z1, _z1Speed);
}
public void MoveToOrginPos()
{
CommonUti.RunOnUi(() =>
{
MoveOrgin();
});
}
public void TeachWSPos()
{
CommonUti.RunOnUi(() =>
{
NeedlePrintCalibrateParameter.AvoidancePoint.X = _device.Axis_X2.GetPositionImmediate();
NeedlePrintCalibrateParameter.AvoidancePoint.Y = _device.Axis_Y2.GetPositionImmediate();
});
}
public void MoveToWsPos()
{
CommonUti.RunOnUi(() =>
{
MoveAvoidancePos();
});
}
public void TeachZ1Pos()
{
CommonUti.RunOnUi(() =>
{
NeedlePrintCalibrateParameter.Z1WorkHeight = _device.Axis_Z1.GetPositionImmediate();
});
}
public void MoveToZ1Pos()
{
CommonUti.RunOnUi(() =>
{
MoveZ1Pos();
});
}
public void TeachZ2Pos()
{
CommonUti.RunOnUi(() =>
{
NeedlePrintCalibrateParameter.Z2WorkHeight = _device.Axis_Z2.GetPositionImmediate();
});
}
public void MoveToZ2Pos()
{
CommonUti.RunOnUi(() =>
{
MoveZ2Pos();
});
}
public void TeachStartPos()
{
CommonUti.RunOnUi(() =>
{
NeedlePrintCalibrateParameter.StartPoint.X = _device.Axis_X1.GetPositionImmediate();
NeedlePrintCalibrateParameter.StartPoint.Y = _device.Axis_Y1.GetPositionImmediate();
});
}
public void MoveToStartPos()
{
CommonUti.RunOnUi(() =>
{
_safeMotion.MoveAxis(new AxisPos
{
Axis = _device.Axis_X11,
Pos = NeedlePrintCalibrateParameter.StartPoint.PointX
}, new AxisPos
{
Axis = _device.Axis_Y11,
Pos = NeedlePrintCalibrateParameter.StartPoint.PointY
});
});
}
public void TeachEndPos()
{
CommonUti.RunOnUi(() =>
{
NeedlePrintCalibrateParameter.EndPoint.X = _device.Axis_X1.GetPositionImmediate();
NeedlePrintCalibrateParameter.EndPoint.Y = _device.Axis_Y1.GetPositionImmediate();
});
}
public void MoveToEndPos()
{
CommonUti.RunOnUi(() =>
{
_safeMotion.SafeMove(new MotionData
{
Name = "X1",
TargetPosition = NeedlePrintCalibrateParameter.EndPoint.X
}, new MotionData
{
Name = "y1",
TargetPosition = NeedlePrintCalibrateParameter.EndPoint.Y
});
});
}
private void MoveOrgin()
{
_safeMotion.SafeMoveAxis(new AxisPos
{
Axis = _device.Axis_CY,
Pos = 0
}, new AxisPos
{
Axis = _device.Axis_CZ,
Pos = 0
});
}
private void MoveAvoidancePos()
{
_safeMotion.MoveAxis(new AxisPos
{
Axis = _device.Axis_X21,
Pos = NeedlePrintCalibrateParameter.AvoidancePoint.PointX
}, new AxisPos
{
Axis = _device.Axis_Y21,
Pos = NeedlePrintCalibrateParameter.AvoidancePoint.PointY
});
}
private void MoveZ1Pos()
{
_safeMotion.MoveAxis(new AxisPos
{
Axis = _device.Axis_Z1,
Pos = NeedlePrintCalibrateParameter.Z1WorkHeight
});
}
private void MoveZ2Pos()
{
_safeMotion.MoveAxis(new AxisPos
{
Axis = _device.Axis_Z2,
Pos = NeedlePrintCalibrateParameter.Z2WorkHeight
});
}
private void MoveAvoidanceAndWorkPos(Point workP)
{
_safeMotion.MoveAxis(new AxisPos
{
Axis = _device.Axis_X21,
Pos = NeedlePrintCalibrateParameter.AvoidancePoint.PointX
}, new AxisPos
{
Axis = _device.Axis_Y21,
Pos = NeedlePrintCalibrateParameter.AvoidancePoint.PointY
}, new AxisPos
{
Axis = _device.Axis_X11,
Pos = workP.X
}, new AxisPos
{
Axis = _device.Axis_Y11,
Pos = workP.Y
});
}
public void StartVerify()
{
CommonUti.RunOnUi(() =>
{
InitCancelToken();
if (_workPos.Count == 0)
{
MaxwellControl.Controls.MessageBox.Show("无法计算有效的下扎点,请检查铜箔示教的起始点坐标");
return;
}
if (_workPos.Count <= NeedlePrintCalibrateParameter.UsedNum)
{
MaxwellControl.Controls.MessageBox.Show("当前铜箔已用完,请确认是否需要更换");
}
IoC.Get<IProjectManager>().EnablePageAndDisableOther("刺晶头校正");
VisionParData visionParData = new VisionParData
{
LightSourceBack = 0,
LightSourceRingBlue = 255,
LightSourcePointBlue = 255,
LightSourcePointRed = 255,
LightSourceRingRed = 255,
};
_safeMotion.MoveZToEscape();
visionParData.SetLightData();
CheckCancel();
var workPoint = _workPos[NeedlePrintCalibrateParameter.UsedNum];
CurrentNeedlePoint.PointX = workPoint.X;
CurrentNeedlePoint.PointY = workPoint.Y;
MoveOrgin();
MoveAvoidanceAndWorkPos(workPoint);
MoveZ1Pos();
CheckCancel();
Thread.Sleep(NeedlePrintCalibrateParameter.SleepTime);
_safeMotion.Z1MoveToEscape();
CheckCancel();
var cameraPoint = IoC.Get<VisionOperation>().GetCameraRulerPointByRulerNeedle(new Point(_device.Axis_X11.GetPositionImmediate(), _device.Axis_Y11.GetPositionImmediate()));
_safeMotion.SafeMoveAxis(new AxisPos
{
Axis = _device.Axis_X11,
Pos = cameraPoint.X
}, new AxisPos
{
Axis = _device.Axis_Y11,
Pos = cameraPoint.Y
});
MoveZ2Pos();
NeedlePrintCalibrateParameter.UsedNum++;
_needlePrintCalibrateSetting.Write();
}, exceptionHandler: ex =>
{
_safeMotion.MoveZToEscape();
CommonUti.ShowMessageBox(ex);
}, begainAction: () =>
{
UiEnable = false;
}, afterAction: () =>
{
UiEnable = true;
IoC.Get<IProjectManager>().SwitchState();
});
}
private void InitCancelToken()
{
if (_cancellationTokenSource != null)
{
_cancellationTokenSource.Cancel();
_cancellationTokenSource.Dispose();
}
_cancellationTokenSource = new CancellationTokenSource();
}
private void CheckCancel()
{
_cancellationTokenSource.Token.ThrowIfCancellationRequested();
}
public void StopVerify()
{
_cancellationTokenSource?.Cancel();
IoC.Get<CancelSourceManager>().CancelMotionAndCheck();
IoC.Get<GlobalDeviceService>().StopMainAxis();
}
public void void NeedleAlignment()
{
CommonUti.RunOnUi(() =>
{
var needlePoint = IoC.Get<VisionOperation>().GetNeedleRulerPointByRulerCamera(new Point(_device.Axis_X11.GetPositionImmediate(), _device.Axis_Y11.GetPositionImmediate()));
_safeMotion.SafeMoveAxis(new AxisPos
{
Axis = _device.Axis_X11,
Pos = needlePoint.X
}, new AxisPos
{
Axis = _device.Axis_Y11,
Pos = needlePoint.Y
});
});
}
public void void CameraAlignment()
{
CommonUti.RunOnUi(() =>
{
var cameraPoint = IoC.Get<VisionOperation>().GetCameraRulerPointByRulerNeedle(new Point(_device.Axis_X11.GetPositionImmediate(), _device.Axis_Y11.GetPositionImmediate()));
_safeMotion.SafeMoveAxis(new AxisPos
{
Axis = _device.Axis_X11,
Pos = cameraPoint.X
}, new AxisPos
{
Axis = _device.Axis_Y11,
Pos = cameraPoint.Y
});
});
}
public void SaveParam()
{
CommonUti.RunOnUi(() =>
{
CalculteWorkPos();
if (_workPos.Count == 0)
{
MaxwellControl.Controls.MessageBox.Show("无法计算有效的下扎点,请检查铜箔示教的起始点坐标");
return;
}
_needlePrintCalibrateSetting.Write();
Application.Current.Dispatcher.Invoke(() =>
{
ParameterHelper.RaiseValueAccept();
});
MaxwellControl.Controls.MessageBox.Show("操作成功");
});
}
public void ResetRecord()
{
NeedlePrintCalibrateParameter.UsedNum = 0;
SaveParam();
}
public void TeachCameraPos()
{
CameraPoint.PointX = _device.Axis_X11.GetPositionImmediate();
CameraPoint.PointY = _device.Axis_Y11.GetPositionImmediate();
}
public void CalculateOffset()
{
CommonUti.RunOnUi(() =>
{
if (CameraPoint.PointX == 0 || CameraPoint.PointY == 0 || CurrentNeedlePoint.PointX == 0 || CurrentNeedlePoint.PointY == 0)
{
MaxwellControl.Controls.MessageBox.Show("请先示教相机位置和针尖位置");
return;
}
List<Point> cameraRealPointList = new List<Point>();
List<Point> needleRealPointList = new List<Point>();
VisionOperation visionOperation = IoC.Get<VisionOperation>();
Point cameraPointReal = visionOperation.GetRealByRuler(_device.Camera_Extend.Id, new Point(CameraPoint.PointX, CameraPoint.PointY));
Point needlePointReal = visionOperation.GetRealByRuler(_device.Camera_Extend.Id, new Point(CurrentNeedlePoint.PointX, CurrentNeedlePoint.PointY));
var needleCalibrationSetting = _paramList.GetParameter<NeedleCalibrationSetting>();
needleCalibrationSetting.NeedleXYCalibrationItem.InitialOffsetX = needlePointReal.X - cameraPointReal.X;
needleCalibrationSetting.NeedleXYCalibrationItem.InitialOffsetY = needlePointReal.Y - cameraPointReal.Y;
var offsetX = needleCalibrationSetting.NeedleXYCalibrationItem.OffsetX - needleCalibrationSetting.NeedleXYCalibrationItem.InitialOffsetX;
var offsetY = needleCalibrationSetting.NeedleXYCalibrationItem.OffsetY - needleCalibrationSetting.NeedleXYCalibrationItem.InitialOffsetY;
if (Math.Abs(offsetY) >= 2 || Math.Abs(offsetX) > 2.5)
{
MaxwellControl.Controls.MessageBox.Show("当前相机与针尖偏差过大,请重新校准!");
return;
}
needleCalibrationSetting.NeedleXYCalibrationItem.OffsetX = needleCalibrationSetting.NeedleXYCalibrationItem.CompensateX + needleCalibrationSetting.NeedleXYCalibrationItem.InitialOffsetX;
needleCalibrationSetting.NeedleXYCalibrationItem.OffsetY = needleCalibrationSetting.NeedleXYCalibrationItem.CompensateY + needleCalibrationSetting.NeedleXYCalibrationItem.InitialOffsetY;
CurrentNeedleOffsetPoint.PointX = needleCalibrationSetting.NeedleXYCalibrationItem.OffsetX;
CurrentNeedleOffsetPoint.PointY = needleCalibrationSetting.NeedleXYCalibrationItem.OffsetY;
EquipmentParaSysSetting equipmentParaSysSetting = _paramList.GetParameter<EquipmentParaSysSetting>();
equipmentParaSysSetting.SafeParaSysItem.NeedleCameraOffsetX = needleCalibrationSetting.NeedleXYCalibrationItem.OffsetX;
equipmentParaSysSetting.SafeParaSysItem.NeedleCameraOffsetY = needleCalibrationSetting.NeedleXYCalibrationItem.OffsetY;
equipmentParaSysSetting.Write();
needleCalibrationSetting.Write();
maintanceRecord.WriteToFile($"当前相机与针尖与上次偏差 X{offsetX} Y:{offsetY}");
MaxwellControl.Controls.MessageBox.Show("操作成功");
});
}
private void CalculteWorkPos()
{
_workPos.Clear();
var startPoint = new Point(NeedlePrintCalibrateParameter.StartPoint.X, NeedlePrintCalibrateParameter.StartPoint.PointY);
var width = NeedlePrintCalibrateParameter.EndPoint.X - NeedlePrintCalibrateParameter.StartPoint.X;
var height = NeedlePrintCalibrateParameter.EndPoint.Y - NeedlePrintCalibrateParameter.StartPoint.Y;
var xscale = width > 0 ? 1 : -1;
var yscale = height > 0 ? 1 : -1;
var xcount = Math.Floor(Math.Abs(width) / NeedlePrintCalibrateParameter.Xpitch);
var ycount = Math.Floor(Math.Abs(height) / NeedlePrintCalibrateParameter.Ypitch);
for (int i = 0; i < ycount; i++)
{
for (int j = 0; j < xcount; j++)
{
var cameraPoint = new Point
{
X = startPoint.X + xscale * i * NeedlePrintCalibrateParameter.Xpitch,
Y = startPoint.Y + yscale * j * NeedlePrintCalibrateParameter.Ypitch,
};
var needlePoint = IoC.Get<VisionOperation>().GetNeedleRulerPointByRulerCamera(cameraPoint);
_workPos.Add(needlePoint);
}
}
}
*/
private bool CheckPointInRange(Point point)
{
return IsPointInRange(NeedlePrintCalibrateParameter.StartPoint, NeedlePrintCalibrateParameter.EndPoint, point);
}
bool IsPointInRange(MPoint p1, MPoint p2, Point current)
{
// 计算最小和最大 X 和 Y 值
double minX = Math.Min(p1.X, p2.X);
double maxX = Math.Max(p1.X, p2.X);
double minY = Math.Min(p1.Y, p2.Y);
double maxY = Math.Max(p1.Y, p2.Y);
// 检查待判断的点是否在范围内
return (current.X >= minX && current.X <= maxX) && (current.Y >= minY && current.Y <= maxY);
}
}
}

View File

@@ -0,0 +1,83 @@
using MainShell.Manual.ViewModel.State;
using Stylet;
using System;
using System.Collections.ObjectModel;
using System.Windows.Input;
namespace MainShell.DeviceMaintance.ViewModel.State
{
public class CylinderPageState : PropertyChangedBase
{
private DateTime _lastActionTime = DateTime.MinValue;
private string _lastActionMessage = "等待气缸控制操作";
public DateTime LastActionTime
{
get { return _lastActionTime; }
set { SetAndNotify(ref _lastActionTime, value); }
}
public string LastActionMessage
{
get { return _lastActionMessage; }
set { SetAndNotify(ref _lastActionMessage, value); }
}
public ObservableCollection<CylinderItemState> Cylinders { get; } = new ObservableCollection<CylinderItemState>();
}
public class CylinderItemState : PropertyChangedBase
{
private bool _isBusy;
public string Name { get; set; }
public string Description { get; set; }
public string Module { get; set; }
public string ControlTypeText { get; set; }
public bool IsBusy
{
get { return _isBusy; }
set { SetAndNotify(ref _isBusy, value); }
}
public ObservableCollection<CylinderSignalState> OutputSignals { get; } = new ObservableCollection<CylinderSignalState>();
public ObservableCollection<CylinderSignalState> FeedbackSignals { get; } = new ObservableCollection<CylinderSignalState>();
public ICommand ExtendCommand { get; set; }
public ICommand RetractCommand { get; set; }
}
public class CylinderSignalState : PropertyChangedBase
{
private bool _isOn;
public string PointReference { get; set; }
public string PointKey { get; set; }
public string Name { get; set; }
public string LineNo { get; set; }
public bool IsOutput { get; set; }
public string IoNameText
{
get { return string.IsNullOrWhiteSpace(PointReference) ? string.Empty : "IO Name" + PointReference; }
}
public bool IsOn
{
get { return _isOn; }
set
{
if (SetAndNotify(ref _isOn, value))
{
OnPropertyChanged(nameof(StateText));
}
}
}
public string StateText
{
get { return IsOn ? "ON" : "OFF"; }
}
}
}

View File

@@ -0,0 +1,163 @@
using Stylet;
using System;
using System.Collections.ObjectModel;
using System.Windows.Input;
namespace MainShell.DeviceMaintance.ViewModel.State
{
public class DeviceIoPageState : PropertyChangedBase
{
private DateTime _lastRefreshTime = DateTime.MinValue;
private DateTime _lastWriteTime = DateTime.MinValue;
private bool _isOnline;
private bool _isWriteSuccess;
private string _lastWriteMessage = "等待写入操作";
public DateTime LastRefreshTime
{
get { return _lastRefreshTime; }
set { SetAndNotify(ref _lastRefreshTime, value); }
}
public DateTime LastWriteTime
{
get { return _lastWriteTime; }
set { SetAndNotify(ref _lastWriteTime, value); }
}
public bool IsOnline
{
get { return _isOnline; }
set
{
if (SetAndNotify(ref _isOnline, value))
{
OnPropertyChanged(nameof(OnlineText));
}
}
}
public bool IsWriteSuccess
{
get { return _isWriteSuccess; }
set { SetAndNotify(ref _isWriteSuccess, value); }
}
public string LastWriteMessage
{
get { return _lastWriteMessage; }
set { SetAndNotify(ref _lastWriteMessage, value); }
}
public string OnlineText
{
get { return IsOnline ? "在线" : "离线/模拟"; }
}
public ObservableCollection<DeviceIoModuleState> Modules { get; } = new ObservableCollection<DeviceIoModuleState>();
}
public class DeviceIoModuleState : PropertyChangedBase
{
private string _name;
public string Name
{
get { return _name; }
set { SetAndNotify(ref _name, value); }
}
public ObservableCollection<DeviceIoPointItemState> InputPoints { get; } = new ObservableCollection<DeviceIoPointItemState>();
public ObservableCollection<DeviceIoPointItemState> OutputPoints { get; } = new ObservableCollection<DeviceIoPointItemState>();
public bool HasInputs
{
get { return InputPoints.Count > 0; }
}
public bool HasOutputs
{
get { return OutputPoints.Count > 0; }
}
}
public class DeviceIoPointItemState : PropertyChangedBase
{
private bool _isOn;
private bool _canWrite;
public int Id { get; set; }
public string PointKey { get; set; }
public string Module { get; set; }
public string Name { get; set; }
public int StationNo { get; set; }
public string LineNo { get; set; }
public string Description { get; set; }
public bool IsOutput { get; set; }
public bool IsInverse { get; set; }
public bool IsOn
{
get { return _isOn; }
set
{
if (SetAndNotify(ref _isOn, value))
{
OnPropertyChanged(nameof(StateText));
OnPropertyChanged(nameof(ToggleText));
}
}
}
public bool CanWrite
{
get { return _canWrite; }
set { SetAndNotify(ref _canWrite, value); }
}
public string StateText
{
get { return IsOn ? "ON" : "OFF"; }
}
public string ToggleText
{
get { return IsOn ? "ON" : "OFF"; }
}
public ICommand ToggleCommand { get; set; }
}
public class ActionCommand : ICommand
{
private readonly Action _execute;
private readonly Func<bool> _canExecute;
public ActionCommand(Action execute, Func<bool> canExecute = null)
{
_execute = execute;
_canExecute = canExecute;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute();
}
public void Execute(object parameter)
{
_execute();
}
public void RaiseCanExecuteChanged()
{
var handler = CanExecuteChanged;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
}