添加 MX-PD-盘古 项目文件
将 MX-PD-盘古 - new 目录下的所有文件添加到主仓库
This commit is contained in:
@@ -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
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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 "单输出控制";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user