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

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

View File

@@ -0,0 +1,49 @@
using System.Collections.Generic;
namespace MainShell.DeviceMaintance.Model
{
public enum CylinderControlType
{
SingleOutput = 0,
DualOutput = 1,
MultiOutput = 2
}
public enum CylinderConditionType
{
PointOn = 0,
PointOff = 1
}
public class CylinderActionConditionDefinition
{
public CylinderConditionType ConditionType { get; set; }
public string PointReference { get; set; }
public string Message { get; set; }
public bool ExpectedState => ConditionType == CylinderConditionType.PointOn;
}
public class CylinderDefinition
{
public string Name { get; set; }
public string Description { get; set; }
public string Module { get; set; }
public CylinderControlType ControlType { get; set; }
public List<string> ExtendOutputPoints { get; set; } = new List<string>();
public List<string> RetractOutputPoints { get; set; } = new List<string>();
public List<string> ExtendedFeedbackPoints { get; set; } = new List<string>();
public List<string> RetractedFeedbackPoints { get; set; } = new List<string>();
public List<CylinderActionConditionDefinition> ExtendConditions { get; set; } = new List<CylinderActionConditionDefinition>();
public List<CylinderActionConditionDefinition> RetractConditions { get; set; } = new List<CylinderActionConditionDefinition>();
public bool HasRetractOutputs => RetractOutputPoints != null && RetractOutputPoints.Count > 0;
}
public class CylinderExecutionResult
{
public bool Success { get; set; }
public string FailureReason { get; set; }
public IReadOnlyList<string> FailurePointReferences { get; set; } = new List<string>();
}
}

View File

@@ -0,0 +1,209 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace MainShell.DeviceMaintance.Model
{
public static class CylinderDefinitionLoader
{
private const string CylinderConfigFileName = "CylinderDefinitions.csv";
public static IReadOnlyList<CylinderDefinition> LoadDefinitions()
{
var definitions = new List<CylinderDefinition>();
var path = ResolveConfigPath();
if (string.IsNullOrWhiteSpace(path) || !File.Exists(path))
{
return definitions;
}
var lines = File.ReadAllLines(path, Encoding.UTF8);
foreach (var raw in lines)
{
if (string.IsNullOrWhiteSpace(raw))
{
continue;
}
var line = raw.Trim();
if (line.StartsWith("#") || line.StartsWith("Name", StringComparison.OrdinalIgnoreCase))
{
continue;
}
var cols = line.Split(',');
if (cols.Length < 7)
{
continue;
}
var extendOutputPoints = ParsePointReferences(cols[3]);
if (extendOutputPoints.Count == 0)
{
continue;
}
var retractOutputPoints = ParsePointReferences(cols[4]);
var hasConditionColumns = cols.Length >= 10;
var extendConditionIndex = hasConditionColumns ? 7 : -1;
var retractConditionIndex = hasConditionColumns ? 8 : -1;
var descriptionIndex = hasConditionColumns ? 9 : 7;
definitions.Add(new CylinderDefinition
{
Name = cols[0].Trim(),
Module = cols[1].Trim(),
ControlType = ParseControlType(cols[2]),
ExtendOutputPoints = extendOutputPoints,
RetractOutputPoints = retractOutputPoints,
ExtendedFeedbackPoints = ParsePointReferences(cols[5]),
RetractedFeedbackPoints = ParsePointReferences(cols[6]),
ExtendConditions = extendConditionIndex >= 0 ? ParseConditions(cols[extendConditionIndex]) : new List<CylinderActionConditionDefinition>(),
RetractConditions = retractConditionIndex >= 0 ? ParseConditions(cols[retractConditionIndex]) : new List<CylinderActionConditionDefinition>(),
Description = cols.Length > descriptionIndex ? string.Join(",", cols.Skip(descriptionIndex)).Trim() : string.Empty
});
}
return definitions;
}
private static CylinderControlType ParseControlType(string raw)
{
if (string.Equals(raw, "DualOutput", StringComparison.OrdinalIgnoreCase) ||
string.Equals(raw, "Dual", StringComparison.OrdinalIgnoreCase))
{
return CylinderControlType.DualOutput;
}
if (string.Equals(raw, "MultiOutput", StringComparison.OrdinalIgnoreCase) ||
string.Equals(raw, "Multi", StringComparison.OrdinalIgnoreCase))
{
return CylinderControlType.MultiOutput;
}
return CylinderControlType.SingleOutput;
}
private static List<string> ParsePointReferences(string raw)
{
return (raw ?? string.Empty)
.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.Trim())
.Where(x => !string.IsNullOrWhiteSpace(x))
.ToList();
}
private static List<CylinderActionConditionDefinition> ParseConditions(string raw)
{
return (raw ?? string.Empty)
.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
.Select(ParseCondition)
.Where(x => x != null)
.ToList();
}
private static CylinderActionConditionDefinition ParseCondition(string raw)
{
if (string.IsNullOrWhiteSpace(raw))
{
return null;
}
var parts = raw.Split(new[] { ':' }, 3);
if (parts.Length < 2)
{
return null;
}
var pointReference = parts[1].Trim();
if (string.IsNullOrWhiteSpace(pointReference))
{
return null;
}
CylinderConditionType conditionType;
switch ((parts[0] ?? string.Empty).Trim().ToUpperInvariant())
{
case "POINTON":
case "ON":
conditionType = CylinderConditionType.PointOn;
break;
case "POINTOFF":
case "OFF":
conditionType = CylinderConditionType.PointOff;
break;
default:
return null;
}
return new CylinderActionConditionDefinition
{
ConditionType = conditionType,
PointReference = pointReference,
Message = parts.Length > 2 ? parts[2].Trim() : string.Empty
};
}
private static string ResolveConfigPath()
{
var baseDir = AppDomain.CurrentDomain.BaseDirectory;
var localPath = Path.Combine(baseDir, "Configuration", CylinderConfigFileName);
var sourcePath = ResolveRootConfigPath(baseDir);
if (TrySyncConfigToLocal(sourcePath, localPath))
{
return localPath;
}
return File.Exists(localPath) ? localPath : sourcePath;
}
private static string ResolveRootConfigPath(string baseDir)
{
var current = new DirectoryInfo(baseDir);
while (current != null)
{
var rootConfigDir = Path.Combine(current.FullName, "Configuration");
if (Directory.Exists(rootConfigDir) && Directory.Exists(Path.Combine(current.FullName, "MainShell")))
{
var path = Path.Combine(rootConfigDir, CylinderConfigFileName);
if (File.Exists(path))
{
return path;
}
}
current = current.Parent;
}
return null;
}
private static bool TrySyncConfigToLocal(string sourcePath, string localPath)
{
if (string.IsNullOrWhiteSpace(sourcePath) || !File.Exists(sourcePath))
{
return false;
}
if (!string.Equals(Path.GetFullPath(sourcePath), Path.GetFullPath(localPath), StringComparison.OrdinalIgnoreCase))
{
var localDir = Path.GetDirectoryName(localPath);
if (!string.IsNullOrWhiteSpace(localDir))
{
Directory.CreateDirectory(localDir);
}
if (!File.Exists(localPath) || File.GetLastWriteTimeUtc(localPath) < File.GetLastWriteTimeUtc(sourcePath))
{
File.Copy(sourcePath, localPath, true);
}
}
return true;
}
}
}

View File

@@ -0,0 +1,19 @@
using Stylet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MainShell.DeviceMaintance.Model
{
public class DeviceMaintanceBaseViewModel : Screen
{
public event Action<bool> UiStateChangedEvent = null;
protected void OnUiStateChanged(bool uiStateChanged)
{
UiStateChangedEvent?.Invoke(uiStateChanged);
}
}
}

View File

@@ -0,0 +1,97 @@
using MainShell.Filewritable;
using Newtonsoft.Json;
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace MainShell.DeviceMaintance.Model
{
public class LaserCompensationSetting : MXJM.FileWritable.JsonFileWritableBase, INotifyPropertyChanged
{
private string _axisName = "Axis_Stage_Y3";
public string AxisName
{
get { return _axisName; }
set { SetAndNotify(ref _axisName, value); }
}
private double _startPos;
public double StartPos
{
get { return _startPos; }
set { SetAndNotify(ref _startPos, value); }
}
private double _steps = 1.0d;
public double Steps
{
get { return _steps; }
set { SetAndNotify(ref _steps, value); }
}
private int _stepsCount = 5;
public int StepsCount
{
get { return _stepsCount; }
set { SetAndNotify(ref _stepsCount, value); }
}
private double _jumpPos = 1.0d;
public double JumpPos
{
get { return _jumpPos; }
set { SetAndNotify(ref _jumpPos, value); }
}
private int _workCount = 1;
public int WorkCount
{
get { return _workCount; }
set { SetAndNotify(ref _workCount, value); }
}
private double _speed = 5.0d;
public double Speed
{
get { return _speed; }
set { SetAndNotify(ref _speed, value); }
}
private double _dwellTime = 0.5d;
public double DwellTime
{
get { return _dwellTime; }
set { SetAndNotify(ref _dwellTime, value); }
}
[JsonIgnore]
public override string Dir => Paths.CalibSettingPath;
[JsonIgnore]
public override string FileName => "LaserCompensationSetting.json";
public event PropertyChangedEventHandler PropertyChanged;
public void LoadFromFile()
{
Read();
}
public void SaveToFile()
{
Write();
}
protected bool SetAndNotify<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (Equals(field, value))
{
return false;
}
field = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
return true;
}
}
}

View File

@@ -0,0 +1,64 @@
using MainShell.Common;
using MainShell.Filewritable;
using MaxwellControl.Controls;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MainShell.DeviceMaintance.Model
{
public enum MaintanceType
{
= 1,
= 2,
= 3,
}
public class MaintanceRecord
{
/// <summary>
/// 设备编号
/// </summary>
public string DeviceId { get; set; }
/// <summary>
/// 设备名称
/// </summary>
public string DeviceName { get; set; }
/// <summary>
/// 维护时间
/// </summary>
public DateTime MaintanceTime { get; set; }
/// <summary>
/// 维护内容
/// </summary>
public MaintanceType MaintanceType { get; set; }
public void WriteToFile(string info)
{
try
{
if (!Directory.Exists(Paths.MaintanceRecordDir))
{
Directory.CreateDirectory(Paths.MaintanceRecordDir);
}
string filePath = Path.Combine(Paths.MaintanceRecordDir, $"{MaintanceType}_MaintanceRecord.txt");
using (var writer = new System.IO.StreamWriter(filePath, true))
{
if (!File.Exists(filePath))
{
writer.WriteLine("设备ID,日期,信息");
}
writer.WriteLine($"{DeviceId},{DateTime.Now}: {info}");
writer.Flush();
}
}
catch (Exception ex)
{
MessageBox.Show($"写入文件失败: {ex.Message}");
}
}
}
}

View File

@@ -0,0 +1,757 @@
using MwFramework.Controls.UIControl;
using MwFramework.ManagerService;
using Stylet;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MainShell.DeviceMaintance.Model
{
[Export(typeof(IParameter))]
public class NeedleCalibrationSetting : ParameterBase
{
public NeedleZCalibrationItem NeedleZCalibrationItem { get; set; } = new NeedleZCalibrationItem();
public NeedleXYCalibrationItem NeedleXYCalibrationItem { get; set; } = new NeedleXYCalibrationItem();
public NeedleXYCalibrationItemNew NeedleXYCalibrationItemNew { get; set; } = new NeedleXYCalibrationItemNew();
public override void Copy(IParameter source)
{
NeedleCalibrationSetting setting = source as NeedleCalibrationSetting;
if (setting != null)
{
ReflectionExtension.Copy<NeedleZCalibrationItem>(NeedleZCalibrationItem, setting.NeedleZCalibrationItem);
ReflectionExtension.Copy<NeedleXYCalibrationItem>(NeedleXYCalibrationItem, setting.NeedleXYCalibrationItem);
ReflectionExtension.Copy<NeedleXYCalibrationItemNew>(NeedleXYCalibrationItemNew, setting.NeedleXYCalibrationItemNew);
}
}
}
public class NeedleZCalibrationItem : PropertyChangedBase, IParameterItem
{
private double _supportPinPositionX;
[WatchValue("针尖对准对刀仪X1位置")]
public double SupportPinPositionX
{
get { return _supportPinPositionX; }
set { if (_supportPinPositionX != value) { _supportPinPositionX = value; OnPropertyChanged(nameof(SupportPinPositionX)); } }
}
private double _supportPinPositionY;
[WatchValue("针尖对准对刀仪Y1位置")]
public double SupportPinPositionY
{
get { return _supportPinPositionY; }
set { if (_supportPinPositionY != value) { _supportPinPositionY = value; OnPropertyChanged(nameof(SupportPinPositionY)); } }
}
private double _knifeOffset;
[WatchValue("对刀仪偏差")]
/// <summary>
/// 对刀仪偏差
/// </summary>
public double KnifeOffset
{
get { return _knifeOffset; }
set { if (_knifeOffset != value) { _knifeOffset = value; OnPropertyChanged(nameof(KnifeOffset)); } }
}
private double _cZHeight = -0.725;
[WatchValue("SZ高度")]
public double CZHeight
{
get { return _cZHeight; }
set { if (_cZHeight != value) { _cZHeight = value; OnPropertyChanged(nameof(CZHeight)); } }
}
private double _stageHeight;
[WatchValue("载台高度")]
public double StageHeight
{
get { return _stageHeight; }
set { if (_stageHeight != value) { _stageHeight = value; OnPropertyChanged(nameof(StageHeight)); } }
}
private double _gantry2AvoidPositionX = 10;
[WatchValue("对刀时龙门X2的避让位置")]
public double Gantry2AvoidPositionX
{
get { return _gantry2AvoidPositionX; }
set { if (_gantry2AvoidPositionX != value) { _gantry2AvoidPositionX = value; OnPropertyChanged(nameof(Gantry2AvoidPositionX)); } }
}
private double _gantry2AvoidPositionY = 200;
[WatchValue("对刀时龙门Y2的避让位置")]
public double Gantry2AvoidPositionY
{
get { return _gantry2AvoidPositionY; }
set { if (_gantry2AvoidPositionY != value) { _gantry2AvoidPositionY = value; OnPropertyChanged(nameof(Gantry2AvoidPositionY)); } }
}
private double _z1StartPosition;
[WatchValue("Z1开始位置")]
public double Z1StartPosition
{
get { return _z1StartPosition; }
set { if (_z1StartPosition != value) { _z1StartPosition = value; OnPropertyChanged(nameof(Z1StartPosition)); } }
}
private double _z1Speed;
[WatchValue("Z1速度")]
public double Z1Speed
{
get { return _z1Speed; }
set { if (_z1Speed != value) { _z1Speed = value; OnPropertyChanged(nameof(Z1Speed)); } }
}
private double _z1DropMaxPosition;
[WatchValue("Z1下降距离")]
public double Z1DropMaxPosition
{
get { return _z1DropMaxPosition; }
set { if (_z1DropMaxPosition != value) { _z1DropMaxPosition = value; OnPropertyChanged(nameof(Z1DropMaxPosition)); } }
}
private int _needleTouchCount = 1;
[WatchValue("对刀次数")]
public int NeedleTouchCount
{
get { return _needleTouchCount; }
set { if (_needleTouchCount != value) { _needleTouchCount = value; OnPropertyChanged(nameof(NeedleTouchCount)); } }
}
private double _needleTouchHeight = 14;
/// <summary>
/// Z1接触对刀仪高度
/// </summary>
[WatchValue("Z1接触对刀仪高度")]
public double NeedleTouchHeight
{
get { return _needleTouchHeight; }
set { if (_needleTouchHeight != value) { _needleTouchHeight = value; OnPropertyChanged(nameof(NeedleTouchHeight)); } }
}
private double _needleTouchHeightBase;
/// <summary>
/// 基准值
/// </summary>
[WatchValue("基准值")]
public double NeedleTouchHeightBase
{
get { return _needleTouchHeightBase; }
set { if (_needleTouchHeightBase != value) { _needleTouchHeightBase = value; OnPropertyChanged(nameof(NeedleTouchHeightBase)); } }
}
private double _currentNeedleTouchHeight;
[WatchValue("当前使用对刀高度")]
/// <summary>
/// 当前使用对刀高度
/// </summary>
public double CurrentNeedleTouchHeight
{
get { return _currentNeedleTouchHeight; }
set { if (_currentNeedleTouchHeight != value) { _currentNeedleTouchHeight = value; OnPropertyChanged(nameof(CurrentNeedleTouchHeight)); } }
}
private double _needleTouchOffset;
[WatchValue("对刀与基准偏差")]
/// <summary>
/// 对刀与基准偏差
/// </summary>
public double NeedleTouchOffset
{
get { return _needleTouchOffset; }
set { if (_needleTouchOffset != value) { _needleTouchOffset = value; OnPropertyChanged(nameof(NeedleTouchOffset)); } }
}
private double _needleTouchHeightAve;
[WatchValue("Z1对刀平均高度")]
/// <summary>
/// Z1对刀平均高度
/// </summary>
public double NeedleTouchHeightAve
{
get { return _needleTouchHeightAve; }
set { if (_needleTouchHeightAve != value) { _needleTouchHeightAve = value; OnPropertyChanged(nameof(NeedleTouchHeightAve)); } }
}
private ObservableCollection<NeedleTouchRecord> _needleTouchRecords = new ObservableCollection<NeedleTouchRecord>();
public ObservableCollection<NeedleTouchRecord> NeedleTouchRecords
{
get { return _needleTouchRecords; }
set
{
_needleTouchRecords = value;
OnPropertyChanged(nameof(NeedleTouchRecords));
}
}
private double _laserToNeedleOffset = 0;
public double LaserToNeedleOffset
{
get { return _laserToNeedleOffset; }
set { if (_laserToNeedleOffset != value) { _laserToNeedleOffset = value; OnPropertyChanged(nameof(LaserToNeedleOffset)); } }
}
private double _needleCameraHeightOffset;
public double NeedleCameraHeightOffset
{
get { return _needleCameraHeightOffset; }
set { if (_needleCameraHeightOffset != value) { _needleCameraHeightOffset = value; OnPropertyChanged(nameof(NeedleCameraHeightOffset)); } }
}
public IParameterItem Clone()
{
NeedleZCalibrationItem clone = new NeedleZCalibrationItem();
clone.CurrentNeedleTouchHeight = _needleCameraHeightOffset;
clone.CZHeight = CZHeight;
clone.Gantry2AvoidPositionX = Gantry2AvoidPositionX;
clone.Gantry2AvoidPositionY = Gantry2AvoidPositionY;
clone.LaserToNeedleOffset = LaserToNeedleOffset;
clone.NeedleCameraHeightOffset = NeedleCameraHeightOffset;
clone.NeedleTouchCount = NeedleTouchCount;
clone.NeedleTouchHeight = NeedleTouchHeight;
clone.NeedleTouchHeightAve = NeedleTouchHeightAve;
clone.NeedleTouchHeightBase = NeedleTouchHeightBase;
clone.NeedleTouchOffset = NeedleTouchOffset;
clone.StageHeight = StageHeight;
clone.SupportPinPositionX = SupportPinPositionX;
clone.SupportPinPositionY = SupportPinPositionY;
clone.Z1DropMaxPosition = Z1DropMaxPosition;
clone.Z1Speed = Z1Speed;
clone.Z1StartPosition = Z1StartPosition;
if (this.NeedleTouchRecords != null)
{
foreach (var item in this.NeedleTouchRecords)
{
clone.NeedleTouchRecords.Add(item.Clone() as NeedleTouchRecord);
}
}
return clone;
}
}
public class NeedleXYCalibrationItem : PropertyChangedBase, IParameterItem
{
private double _needleX;
[WatchValue("设置—刺晶头X")]
public double NeedleX
{
get { return _needleX; }
set { if (_needleX != value) { _needleX = value; OnPropertyChanged(nameof(NeedleX)); } }
}
private double _needleY;
[WatchValue("设置—刺晶头Y")]
public double NeedleY
{
get { return _needleY; }
set { if (_needleY != value) { _needleY = value; OnPropertyChanged(nameof(NeedleY)); } }
}
private double _cameraX;
[WatchValue("设置—相机X")]
public double CameraX
{
get { return _cameraX; }
set { if (_cameraX != value) { _cameraX = value; OnPropertyChanged(nameof(CameraX)); } }
}
private double _cameraY;
[WatchValue("设置—相机Y")]
public double CameraY
{
get { return _cameraY; }
set { if (_cameraY != value) { _cameraY = value; OnPropertyChanged(nameof(CameraY)); } }
}
private double _needleZ1 = 0.0;
[WatchValue("设置—刺晶头Z1")]
public double NeedleZ1
{
get { return _needleZ1; }
set { if (_needleZ1 != value) { _needleZ1 = value; OnPropertyChanged(nameof(NeedleZ1)); } }
}
private double _offsetX;
[WatchValue("X方向偏差")]
public double OffsetX
{
get { return _offsetX; }
set { if (_offsetX != value) { _offsetX = value; OnPropertyChanged(nameof(OffsetX)); } }
}
private double _offsetY;
[WatchValue("Y方向偏差")]
public double OffsetY
{
get { return _offsetY; }
set { if (_offsetY != value) { _offsetY = value; OnPropertyChanged(nameof(OffsetY)); } }
}
private double _initialOffsetX;
/// <summary>
/// 针和相机之间的X初始偏差不加补偿
/// </summary>
[WatchValue("X方向初始偏差")]
public double InitialOffsetX
{
get { return _initialOffsetX; }
set { if (_initialOffsetX != value) { _initialOffsetX = value; OnPropertyChanged(nameof(InitialOffsetX)); } }
}
private double _initialOffsetY;
/// <summary>
/// 针和相机之间的Y初始偏差不加补偿
/// </summary>
[WatchValue("Y方向初始偏差")]
public double InitialOffsetY
{
get { return _initialOffsetY; }
set { if (_initialOffsetY != value) { _initialOffsetY = value; OnPropertyChanged(nameof(InitialOffsetY)); } }
}
private double _compensateX;
/// <summary>
/// 针和相机之间的X方向偏差补偿
/// </summary>
[WatchValue("X方向补偿")]
public double CompensateX
{
get { return _compensateX; }
set { if (_compensateX != value) { _compensateX = value; OnPropertyChanged(nameof(CompensateX)); } }
}
private double _compensateY;
/// <summary>
/// 针和相机之间的Y方向偏差补偿
/// </summary>
[WatchValue("Y方向补偿")]
public double CompensateY
{
get { return _compensateY; }
set { if (_compensateY != value) { _compensateY = value; OnPropertyChanged(nameof(CompensateY)); } }
}
private double _offsetXMax;
[WatchValue("偏差限制—X偏差最大值")]
public double OffsetXMax
{
get { return _offsetXMax; }
set { if (_offsetXMax != value) { _offsetXMax = value; OnPropertyChanged(nameof(OffsetXMax)); } }
}
private double _offsetXMin;
[WatchValue("偏差限制—X偏差最小值")]
public double OffsetXMin
{
get { return _offsetXMin; }
set { if (_offsetXMin != value) { _offsetXMin = value; OnPropertyChanged(nameof(OffsetXMin)); } }
}
private double _offsetYMax;
[WatchValue("偏差限制—Y偏差最大值")]
public double OffsetYMax
{
get { return _offsetYMax; }
set { if (_offsetYMax != value) { _offsetYMax = value; OnPropertyChanged(nameof(OffsetYMax)); } }
}
private double _offsetYMin;
[WatchValue("偏差限制—Y偏差最小值")]
public double OffsetYMin
{
get { return _offsetYMin; }
set { if (_offsetYMin != value) { _offsetYMin = value; OnPropertyChanged(nameof(OffsetYMin)); } }
}
/// <summary>
/// 扎铜箔时龙门X2避让位置
/// </summary>
private double _x2AvoidPosition;
[WatchValue("扎铜箔时龙门X2避让位置")]
public double X2AvoidPosition
{
get { return _x2AvoidPosition; }
set { if (_x2AvoidPosition != value) { _x2AvoidPosition = value; OnPropertyChanged(nameof(X2AvoidPosition)); } }
}
/// <summary>
/// 扎铜箔时龙门Y2避让位置
/// </summary>
private double _y2AvoidPosition;
[WatchValue("扎铜箔时龙门Y2避让位置")]
public double Y2AvoidPosition
{
get { return _y2AvoidPosition; }
set { if (_y2AvoidPosition != value) { _y2AvoidPosition = value; OnPropertyChanged(nameof(Y2AvoidPosition)); } }
}
/// <summary>
/// 扎铜箔时Stage的位置
/// </summary>
private double _stagePosition;
[WatchValue("扎铜箔时Stage的位置")]
public double StagePosition
{
get { return _stagePosition; }
set { if (_stagePosition != value) { _stagePosition = value; OnPropertyChanged(nameof(StagePosition)); } }
}
public IParameterItem Clone()
{
NeedleXYCalibrationItem clone = new NeedleXYCalibrationItem();
clone.NeedleX = this.NeedleX;
clone.NeedleY = this.NeedleY;
clone.CameraX = this.CameraY;
clone.CameraY = this.CameraY;
clone.OffsetX = this.OffsetX;
clone.OffsetY = this.OffsetY;
clone.OffsetXMax = this.OffsetXMax;
clone.OffsetXMin = this.OffsetXMin;
clone.OffsetYMax = this.OffsetYMax;
clone.OffsetYMin = this.OffsetYMin;
return this.MemberwiseClone() as IParameterItem;
}
}
public class NeedleXYCalibrationItemNew : PropertyChangedBase, IParameterItem
{
//private VisionParData _needleVisionParData;
//public VisionParData NeedleVisionParData
//{
// get { return _needleVisionParData ?? new VisionParData() { Exposure = 2000 }; }
// set { SetAndNotify(ref _needleVisionParData, value); }
//}
private double _x1Calib;
/// <summary>
/// 相机标定位X1
/// </summary>
[WatchValue("相机标定位X1")]
public double X1Calib
{
get { return _x1Calib; }
set { if (_x1Calib != value) { _x1Calib = value; OnPropertyChanged(nameof(X1Calib)); } }
}
private double _x1MechanicalOffset = 0.0;
/// <summary>
/// 机械X1Offset
/// </summary>
[WatchValue("机械X1Offset")]
public double X1MechanicalOffset
{
get { return _x1MechanicalOffset; }
set { if (_x1MechanicalOffset != value) { _x1MechanicalOffset = value; OnPropertyChanged(nameof(X1MechanicalOffset)); } }
}
private double _wSCalibX2;
/// <summary>
/// 方片标定位X2
/// </summary>
[WatchValue("方片标定位X2")]
public double WSCalibX2
{
get { return _wSCalibX2; }
set { if (_wSCalibX2 != value) { _wSCalibX2 = value; OnPropertyChanged(nameof(WSCalibX2)); } }
}
private double _wSCalibY2;
/// <summary>
/// 方片标定位Y2
/// </summary>
[WatchValue("方片标定位Y2")]
public double WSCalibY2
{
get { return _wSCalibY2; }
set { if (_wSCalibY2 != value) { _wSCalibY2 = value; OnPropertyChanged(nameof(WSCalibY2)); } }
}
private double _needleX1;
[WatchValue("刺晶头X1")]
public double NeedleX1
{
get { return _needleX1; }
set { if (_needleX1 != value) { _needleX1 = value; OnPropertyChanged(nameof(NeedleX1)); } }
}
private double _needleZ1 = 0.0;
[WatchValue("刺晶头Z1")]
public double NeedleZ1
{
get { return _needleZ1; }
set { if (_needleZ1 != value) { _needleZ1 = value; OnPropertyChanged(nameof(NeedleZ1)); } }
}
private int _z1WorkTime = 0;
/// <summary>
/// Z1保持下扎时长
/// </summary>
[WatchValue("Z1保持下扎时长")]
public int Z1WorkTime
{
get { return _z1WorkTime; }
set { if (_z1WorkTime != value) { _z1WorkTime = value; OnPropertyChanged(nameof(Z1WorkTime)); } }
}
private double _offsetX;
/// <summary>
/// 针和相机之间的X初始偏差不加补偿
/// </summary>
[WatchValue("X方向偏差")]
public double OffsetX
{
get { return _offsetX; }
set { if (_offsetX != value) { _offsetX = value; OnPropertyChanged(nameof(OffsetX)); } }
}
private double _offsetY;
/// <summary>
/// 针和相机之间的Y初始偏差不加补偿
/// </summary>
[WatchValue("Y方向偏差")]
public double OffsetY
{
get { return _offsetY; }
set { if (_offsetY != value) { _offsetY = value; OnPropertyChanged(nameof(OffsetY)); } }
}
private double _compensateX;
/// <summary>
/// 针和相机之间的X方向偏差补偿
/// </summary>
[WatchValue("X方向补偿")]
public double CompensateX
{
get { return _compensateX; }
set { if (_compensateX != value) { _compensateX = value; OnPropertyChanged(nameof(CompensateX)); } }
}
private double _compensateY;
/// <summary>
/// 针和相机之间的Y方向偏差补偿
/// </summary>
[WatchValue("Y方向补偿")]
public double CompensateY
{
get { return _compensateY; }
set { if (_compensateY != value) { _compensateY = value; OnPropertyChanged(nameof(CompensateY)); } }
}
private double _offsetXMax;
[WatchValue("偏差限制—X偏差最大值")]
public double OffsetXMax
{
get { return _offsetXMax; }
set { if (_offsetXMax != value) { _offsetXMax = value; OnPropertyChanged(nameof(OffsetXMax)); } }
}
private double _offsetXMin;
[WatchValue("偏差限制—X偏差最小值")]
public double OffsetXMin
{
get { return _offsetXMin; }
set { if (_offsetXMin != value) { _offsetXMin = value; OnPropertyChanged(nameof(OffsetXMin)); } }
}
private double _offsetYMax;
[WatchValue("偏差限制—Y偏差最大值")]
public double OffsetYMax
{
get { return _offsetYMax; }
set { if (_offsetYMax != value) { _offsetYMax = value; OnPropertyChanged(nameof(OffsetYMax)); } }
}
private double _offsetYMin;
[WatchValue("偏差限制—Y偏差最小值")]
public double OffsetYMin
{
get { return _offsetYMin; }
set { if (_offsetYMin != value) { _offsetYMin = value; OnPropertyChanged(nameof(OffsetYMin)); } }
}
private double _wSApproachX2;
/// <summary>
/// 方片逼近位X2
/// </summary>
[WatchValue("方片逼近位X2")]
public double WSApproachX2
{
get { return _wSApproachX2; }
set { if (_wSApproachX2 != value) { _wSApproachX2 = value; OnPropertyChanged(nameof(WSApproachX2)); } }
}
private double _wSApproachY2;
/// <summary>
/// 方片逼近位Y2
/// </summary>
[WatchValue("方片逼近位Y2")]
public double WSApproachY2
{
get { return _wSApproachY2; }
set { if (_wSApproachY2 != value) { _wSApproachY2 = value; OnPropertyChanged(nameof(WSApproachY2)); } }
}
private double _stampThreRadius;
/// <summary>
/// 针印理论半径
/// </summary>
[WatchValue("针印理论半径")]
public double StampThreRadius
{
get { return _stampThreRadius; }
set { if (_stampThreRadius != value) { _stampThreRadius = value; OnPropertyChanged(nameof(StampThreRadius)); } }
}
private double _stampThreErrorRange;
/// <summary>
/// 针印误差范围
/// </summary>
[WatchValue("针印误差范围")]
public double StampThreErrorRange
{
get { return _stampThreErrorRange; }
set { if (_stampThreErrorRange != value) { _stampThreErrorRange = value; OnPropertyChanged(nameof(StampThreErrorRange)); } }
}
private double _stampMinCircularity;
/// <summary>
/// 针印最小圆度
/// </summary>
[WatchValue("针印最小圆度")]
public double StampMinCircularity
{
get { return _stampMinCircularity; }
set { if (_stampMinCircularity != value) { _stampMinCircularity = value; OnPropertyChanged(nameof(StampMinCircularity)); } }
}
private double _stampPolarity;
/// <summary>
/// 针印颜色,0黑1白
/// </summary>
[WatchValue("针印理论半径")]
public double StampPolarity
{
get { return _stampPolarity; }
set { if (_stampPolarity != value) { _stampPolarity = value; OnPropertyChanged(nameof(StampPolarity)); } }
}
private bool _isBlack = false;
public bool IsBlack
{
get
{
return _isBlack;
}
set
{
_isBlack = value;
StampPolarityUpdate();
OnPropertyChanged(nameof(IsBlack));
}
}
public void StampPolarityUpdate()
{
if (IsBlack)
{
StampPolarity = 0;
}
else
{
StampPolarity = 1;
}
}
public IParameterItem Clone()
{
NeedleXYCalibrationItemNew clone = new NeedleXYCalibrationItemNew();
clone.NeedleX1 = this.NeedleX1;
clone.NeedleZ1 = this.NeedleZ1;
clone.WSApproachX2 = this.WSApproachX2;
clone.WSApproachY2 = this.WSApproachY2;
clone.Z1WorkTime = Z1WorkTime;
clone.X1MechanicalOffset = X1MechanicalOffset;
clone.X1Calib = X1Calib;
clone.WSCalibX2 = WSCalibX2;
clone.WSCalibY2 = WSCalibY2;
clone.CompensateX = CompensateX;
clone.CompensateY = CompensateY;
clone.OffsetX = this.OffsetX;
clone.OffsetY = this.OffsetY;
clone.OffsetXMax = this.OffsetXMax;
clone.OffsetXMin = this.OffsetXMin;
clone.OffsetYMax = this.OffsetYMax;
clone.OffsetYMin = this.OffsetYMin;
clone.IsBlack = this.IsBlack;
clone.StampMinCircularity = this.StampMinCircularity;
clone.StampPolarity = this.StampPolarity;
clone.StampThreErrorRange = this.StampThreErrorRange;
clone.StampThreRadius = this.StampThreRadius;
//clone.NeedleVisionParData.Exposure = this.NeedleVisionParData.Exposure;
//clone.NeedleVisionParData.Gain = this.NeedleVisionParData.Gain;
//clone.NeedleVisionParData.LightSourceBack = this.NeedleVisionParData.LightSourceBack;
//clone.NeedleVisionParData.LightSourcePointBlue = this.NeedleVisionParData.LightSourcePointBlue;
//clone.NeedleVisionParData.LightSourcePointRed = this.NeedleVisionParData.LightSourcePointRed;
//clone.NeedleVisionParData.LightSourceRingBlue = this.NeedleVisionParData.LightSourceRingBlue;
//clone.NeedleVisionParData.LightSourceRingRed = this.NeedleVisionParData.LightSourceRingRed;
//clone.NeedleVisionParData.Z2 = this.NeedleVisionParData.Z2;
return this.MemberwiseClone() as IParameterItem;
}
}
public class NeedleTouchRecord : PropertyChangedBase, IParameterItem
{
private int _CurrentCount;
/// <summary>
/// 当前次数
/// </summary>
public int CurrentCount
{
get { return _CurrentCount; }
set
{ SetAndNotify(ref _CurrentCount, value); }
}
private double _Height;
/// <summary>
/// 高度
/// </summary>
public double Height
{
get { return _Height; }
set
{ SetAndNotify(ref _Height, value); }
}
public NeedleTouchRecord()
{
}
public NeedleTouchRecord(int count, double height)
{
CurrentCount = count;
Height = height;
}
public IParameterItem Clone()
{
return this.MemberwiseClone() as IParameterItem;
}
}
}

View File

@@ -0,0 +1,104 @@
using MainShell.Models;
using MwFramework.ManagerService;
using Stylet;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MainShell.DeviceMaintance.Model
{
[Export(typeof(IParameter))]
public class NeedlePrintCalibrateSetting : ParameterBase
{
public NeedlePrintCalibrateParameter NeedlePrintCalibrateParameter { get; set; } = new NeedlePrintCalibrateParameter();
public NeedlePrintCalibrateSetting() { }
public override void Copy(IParameter source)
{
if (source is NeedlePrintCalibrateSetting setting)
{
ReflectionExtension.Copy(NeedlePrintCalibrateParameter, setting.NeedlePrintCalibrateParameter);
}
}
}
public class NeedlePrintCalibrateParameter : PropertyChangedBase, IParameterItem
{
private MPoint _startPoint = new MPoint();
public MPoint StartPoint
{
get { return _startPoint; }
set { SetAndNotify(ref _startPoint, value); }
}
private MPoint _endPoint = new MPoint();
public MPoint EndPoint
{
get { return _endPoint; }
set { SetAndNotify(ref _endPoint, value); }
}
private MPoint _avoidancePoint = new MPoint();
public MPoint AvoidancePoint
{
get { return _avoidancePoint; }
set { SetAndNotify(ref _avoidancePoint, value); }
}
private double _z1WorkHeight;
public double Z1WorkHeight
{
get { return _z1WorkHeight; }
set { SetAndNotify(ref _z1WorkHeight, value); }
}
private double _z2WorkHeight;
public double Z2WorkHeight
{
get { return _z2WorkHeight; }
set { SetAndNotify(ref _z2WorkHeight, value); }
}
private double _xPitch;
public double Xpitch
{
get { return _xPitch; }
set { SetAndNotify(ref _xPitch, value); }
}
private double _yPitch;
public double Ypitch
{
get { return _yPitch; }
set { SetAndNotify(ref _yPitch, value); }
}
private int _usedNum;
public int UsedNum
{
get { return _usedNum; }
set { SetAndNotify(ref _usedNum, value); }
}
private int _sleepTime = 1000;
public int SleepTime
{
get { return _sleepTime; }
set { SetAndNotify(ref _sleepTime, value); }
}
public IParameterItem Clone()
{
return MemberwiseClone() as NeedlePrintCalibrateParameter;
}
}
}

View File

@@ -0,0 +1,109 @@
<UserControl x:Class="MainShell.DeviceMaintance.View.CameraAccuracyCalibrationView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MainShell.DeviceMaintance.View"
xmlns:mwControls="http://www.maxwell-gp.com/"
xmlns:customControl="clr-namespace:MainShell.Resources.CustomControl"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="700">
<UserControl.Resources>
<Style TargetType="GroupBox" BasedOn="{StaticResource GroupStepControl}"/>
<Style TargetType="Label" BasedOn="{StaticResource {x:Type Label}}">
<Setter Property="HorizontalContentAlignment" Value="Right"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Right"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Height" Value="35"/>
</Style>
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}" >
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="Margin" Value="3"/>
<Setter Property="Height" Value="35"/>
<Setter Property="Width" Value="90"/>
</Style>
</UserControl.Resources>
<Grid mwControls:ParameterAttach.DelayAcceptValue ="{Binding ParameterHelper}">
<StackPanel>
<GroupBox IsEnabled="{Binding UiEnable}" Header="【第一步】针尖高度设置">
<customControl:AxisMoveControl LableContent1="Z1(mm)"
Value1="{Binding QuickNeedlePrintParameter.Z1InkHeight}"
IsAllShow="False"
ReadCommand="{mwControls:Action TeachZ1Pos}"
IsReadOnly="False"
MoveCommand="{mwControls:Action MoveToZ1Pos}"/>
</GroupBox>
<GroupBox IsEnabled="{Binding UiEnable}" Header="【第二步】WS避让位">
<GroupBox.Content>
<customControl:AxisMoveControl LableContent1="X2(mm)"
Value1="{Binding QuickNeedlePrintParameter.AvoidancePoint.PointX}"
LableContent2="Y2(mm)"
Value2="{Binding QuickNeedlePrintParameter.AvoidancePoint.PointY}"
ReadCommand="{mwControls:Action TeachWSPos}"
MoveCommand="{mwControls:Action MoveToWsPos}"
IsReadOnly="True"/>
<!--<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Label VerticalAlignment="Center" Content="X2:"/>
<mwControls:NumberBox Value="{Binding QuickNeedlePrintParameter.AvoidancePoint.PointX}" IsReadOnly="True" Width="80" Margin="4,0" />
<Label VerticalAlignment="Center" Content="Y2:"/>
<mwControls:NumberBox Value="{Binding QuickNeedlePrintParameter.AvoidancePoint.PointY}" IsReadOnly="True" Width="80" Margin="4,0" />
<Button Margin="2,0" Click="{mwControls:Action TeachWSPos}" Content="示教"/>
<Button Margin="2,0" Click="{mwControls:Action MoveToWsPos}" Content="移动"/>
</StackPanel>-->
</GroupBox.Content>
</GroupBox>
<GroupBox IsEnabled="{Binding UiEnable}" Margin="2" Header="【第三步】墨水位置">
<GroupBox.Content>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<customControl:AxisMoveControl LableContent1="X2(mm)"
Value1="{Binding QuickNeedlePrintParameter.InkPos.PointX}"
LableContent2="Y2(mm)"
Value2="{Binding QuickNeedlePrintParameter.InkPos.PointY}"
ReadCommand="{mwControls:Action TeachInkPos}"
MoveCommand="{mwControls:Action MoveToInkPos}"
IsReadOnly="True"/>
<Button Margin="2,0" HorizontalAlignment="Right" Click="{mwControls:Action InkSmearing}" Content="涂墨"/>
</Grid>
</GroupBox.Content>
</GroupBox>
<GroupBox Header="【第四步】快打针印参数设置">
<StackPanel>
<StackPanel Orientation="Horizontal">
<Label VerticalAlignment="Center" HorizontalAlignment="Left" Content="打件颗数:"/>
<mwControls:IntNumberBox Value="{Binding BondingNumber}" IsReadOnly="True" Width="75" Margin="4,0" />
<Button IsEnabled="{Binding UiEnable}" Margin="2,0" Click="{mwControls:Action PositiveBonding}" Content="快打正向"/>
<Button IsEnabled="{Binding UiEnable}" Margin="2,0" Click="{mwControls:Action NegativeBonding}" Content="快打反向"/>
<Button IsEnabled="{Binding UiEnable}" Margin="2,0" Click="{mwControls:Action SlowBonding}" Content="补打"/>
<Button Margin="2,0" Content="停止打件" Click="{mwControls:Action StopBonding}"/>
</StackPanel>
<Label Content="正向针印查看:" HorizontalAlignment="Left"/>
<StackPanel IsEnabled="{Binding UiEnable}" HorizontalAlignment="Left" Orientation="Horizontal">
<Button Margin="2,0" IsEnabled="{Binding CanLastPositiveIndex}" Click="{mwControls:Action LastPositiveIndex}" Content="上一个"/>
<Button Margin="2,0" IsEnabled="{Binding CanNextPositiveIndex}" Click="{mwControls:Action NextPositiveIndex}" Content="下一个"/>
</StackPanel>
<Label Content="反向针印查看:" HorizontalAlignment="Left"/>
<StackPanel IsEnabled="{Binding UiEnable}" HorizontalAlignment="Left" Orientation="Horizontal">
<Button Margin="2,0" IsEnabled="{Binding CanLastNegativeIndex}" Click="{mwControls:Action LastNegativeIndex}" Content="上一个"/>
<Button Margin="2,0" IsEnabled="{Binding CanNextNegativeIndex}" Click="{mwControls:Action NextNegativeIndex}" Content="下一个"/>
</StackPanel>
<Label Content="补打针印查看:" HorizontalAlignment="Left"/>
<StackPanel IsEnabled="{Binding UiEnable}" HorizontalAlignment="Left" Orientation="Horizontal">
<Button Margin="2,0" IsEnabled="{Binding CanLastSlowIndex}" Click="{mwControls:Action LastSlowIndex}" Content="上一个"/>
<Button Margin="2,0" IsEnabled="{Binding CanNextSlowIndex}" Click="{mwControls:Action NextSlowIndex}" Content="下一个"/>
</StackPanel>
<Button IsEnabled="{Binding UiEnable}" HorizontalAlignment="Right" Click="{mwControls:Action SaveParameter}" Margin="10,2" Content="保存"/>
</StackPanel>
</GroupBox>
</StackPanel>
</Grid>
</UserControl>

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace MainShell.DeviceMaintance.View
{
/// <summary>
/// CameraAccuracyCalibrationView.xaml 的交互逻辑
/// </summary>
public partial class CameraAccuracyCalibrationView : UserControl
{
public CameraAccuracyCalibrationView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,176 @@
<UserControl x:Class="MainShell.DeviceMaintance.View.CylinderView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MainShell.DeviceMaintance.View"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<Style x:Key="CylinderCardStyle" TargetType="Border">
<Setter Property="Background" Value="#F8FAFD"/>
<Setter Property="BorderBrush" Value="#D4DCE8"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="8"/>
<Setter Property="Padding" Value="14"/>
<Setter Property="Margin" Value="0,0,0,12"/>
</Style>
<Style x:Key="CylinderDotStyle" TargetType="Ellipse">
<Setter Property="Width" Value="10"/>
<Setter Property="Height" Value="10"/>
<Setter Property="Fill" Value="#CBD5E1"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsOn}" Value="True">
<Setter Property="Fill" Value="#22C55E"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="CylinderActionButtonStyle" TargetType="Button">
<Setter Property="Foreground" Value="White"/>
<Setter Property="Padding" Value="12,6"/>
<Setter Property="MinWidth" Value="90"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Margin" Value="0,0,8,0"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"
CornerRadius="18"
Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid Background="#EDF1F7">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Margin="12,12,12,8">
<TextBlock Text="CYLINDER CONTROL / 气缸控制" FontSize="20" FontWeight="Bold" Foreground="#0F3B7A"/>
<Border Background="#EFF6FF" BorderBrush="#BFDBFE" BorderThickness="1" CornerRadius="6" Padding="10" Margin="0,8,0,0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="最近操作:" Foreground="#475569" Margin="0,0,8,0"/>
<TextBlock Text="{Binding PageState.LastActionTime, StringFormat={}{0:HH:mm:ss}}" Foreground="#0F172A" FontWeight="Bold" Margin="0,0,12,0"/>
<TextBlock Text="{Binding PageState.LastActionMessage}" Foreground="#1D4ED8" FontWeight="SemiBold" TextWrapping="Wrap"/>
</StackPanel>
</Border>
</StackPanel>
<ScrollViewer Grid.Row="1" Margin="12,0,12,12" VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding PageState.Cylinders}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Style="{StaticResource CylinderCardStyle}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel>
<TextBlock Text="{Binding Name}" FontSize="18" FontWeight="Bold" Foreground="#0F3B7A"/>
<TextBlock Text="{Binding Description}" Foreground="#64748B" Margin="0,4,0,0"/>
</StackPanel>
<Border Grid.Column="1" Background="#FEF3C7" CornerRadius="12" Padding="10,4" VerticalAlignment="Center">
<TextBlock Text="{Binding ControlTypeText}" Foreground="#92400E" FontWeight="Bold"/>
</Border>
</Grid>
<Grid Grid.Row="1" Margin="0,12,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Margin="0,0,16,0">
<TextBlock Text="控制" Foreground="#1D4ED8" FontWeight="Bold" Margin="0,0,0,8"/>
<StackPanel Orientation="Horizontal">
<Button Content="伸出"
Command="{Binding ExtendCommand}"
Background="#2563EB"
BorderBrush="#2563EB"
Style="{StaticResource CylinderActionButtonStyle}"/>
<Button Content="缩回"
Command="{Binding RetractCommand}"
Background="#F97316"
BorderBrush="#F97316"
Style="{StaticResource CylinderActionButtonStyle}"/>
</StackPanel>
</StackPanel>
<StackPanel Grid.Column="1" Margin="0,0,16,0">
<TextBlock Text="输出信号" Foreground="#C2410C" FontWeight="Bold" Margin="0,0,0,8"/>
<ItemsControl ItemsSource="{Binding OutputSignals}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="#FFF7ED" BorderBrush="#FED7AA" BorderThickness="1" CornerRadius="4" Padding="8,6" Margin="0,0,0,6">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Ellipse Style="{StaticResource CylinderDotStyle}" VerticalAlignment="Center" Margin="0,0,8,0"/>
<StackPanel Grid.Column="1">
<TextBlock Text="{Binding Name}" Foreground="#9A3412" FontWeight="SemiBold"/>
<TextBlock Text="{Binding IoNameText}" Foreground="#7C2D12" FontSize="11" TextWrapping="Wrap"/>
<TextBlock Text="{Binding LineNo, StringFormat=线标:{0}}" Foreground="#C2410C" FontSize="11"/>
</StackPanel>
<TextBlock Grid.Column="2" Text="{Binding StateText}" Foreground="#C2410C" FontWeight="Bold"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Text="反馈信号" Foreground="#166534" FontWeight="Bold" Margin="0,0,0,8"/>
<ItemsControl ItemsSource="{Binding FeedbackSignals}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="#F0FDF4" BorderBrush="#BBF7D0" BorderThickness="1" CornerRadius="4" Padding="8,6" Margin="0,0,0,6">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Ellipse Style="{StaticResource CylinderDotStyle}" VerticalAlignment="Center" Margin="0,0,8,0"/>
<StackPanel Grid.Column="1">
<TextBlock Text="{Binding Name}" Foreground="#166534" FontWeight="SemiBold"/>
<TextBlock Text="{Binding IoNameText}" Foreground="#15803D" FontSize="11" TextWrapping="Wrap"/>
<TextBlock Text="{Binding LineNo, StringFormat=线标:{0}}" Foreground="#15803D" FontSize="11"/>
</StackPanel>
<TextBlock Grid.Column="2" Text="{Binding StateText}" Foreground="#166534" FontWeight="Bold"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</UserControl>

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace MainShell.DeviceMaintance.View
{
/// <summary>
/// CylinderView.xaml 的交互逻辑
/// </summary>
public partial class CylinderView : UserControl
{
public CylinderView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,310 @@
<UserControl x:Class="MainShell.DeviceMaintance.View.DeviceIoView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="900">
<UserControl.Resources>
<Style x:Key="IoCardStyle" TargetType="Border">
<Setter Property="Background" Value="#F8FAFD"/>
<Setter Property="BorderBrush" Value="#D4DCE8"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="8"/>
<Setter Property="Margin" Value="0,0,0,12"/>
<Setter Property="Padding" Value="14"/>
</Style>
<Style x:Key="StatusBadgeBorderStyle" TargetType="Border">
<Setter Property="CornerRadius" Value="12"/>
<Setter Property="Padding" Value="10,4"/>
<Setter Property="Margin" Value="0,0,8,0"/>
<Setter Property="Background" Value="#E2E8F0"/>
</Style>
<Style x:Key="InputStatusDotStyle" TargetType="Ellipse">
<Setter Property="Width" Value="10"/>
<Setter Property="Height" Value="10"/>
<Setter Property="Fill" Value="#93C5FD"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsOn}" Value="True">
<Setter Property="Fill" Value="#2563EB"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="OutputStatusDotStyle" TargetType="Ellipse">
<Setter Property="Width" Value="10"/>
<Setter Property="Height" Value="10"/>
<Setter Property="Fill" Value="#FCD34D"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsOn}" Value="True">
<Setter Property="Fill" Value="#F97316"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="InputItemBorderStyle" TargetType="Border">
<Setter Property="Background" Value="#EFF6FF"/>
<Setter Property="BorderBrush" Value="#DBEAFE"/>
<Setter Property="BorderThickness" Value="0,0,0,1"/>
<Setter Property="Padding" Value="8,6"/>
<Setter Property="Margin" Value="0,0,0,4"/>
<Setter Property="CornerRadius" Value="4"/>
</Style>
<Style x:Key="OutputItemBorderStyle" TargetType="Border">
<Setter Property="Background" Value="#FFF7ED"/>
<Setter Property="BorderBrush" Value="#FED7AA"/>
<Setter Property="BorderThickness" Value="0,0,0,1"/>
<Setter Property="Padding" Value="8,6"/>
<Setter Property="Margin" Value="0,0,0,4"/>
<Setter Property="CornerRadius" Value="4"/>
</Style>
<Style x:Key="IoSectionBorderStyle" TargetType="Border">
<Setter Property="CornerRadius" Value="6"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="10"/>
</Style>
<Style x:Key="IoOutputToggleButtonStyle" TargetType="ToggleButton">
<Setter Property="Width" Value="90"/>
<Setter Property="Height" Value="30"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border x:Name="Root" Background="#CBD5E1" BorderBrush="#94A3B8" BorderThickness="1" CornerRadius="15">
<Grid Margin="2">
<Border x:Name="Knob" Width="24" Height="24" Background="White" CornerRadius="12" HorizontalAlignment="Left"/>
<TextBlock x:Name="ToggleLabel" Text="OFF" Foreground="#334155" FontWeight="Bold" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,10,0"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Root" Property="Background" Value="#16A34A"/>
<Setter TargetName="Root" Property="BorderBrush" Value="#16A34A"/>
<Setter TargetName="Knob" Property="HorizontalAlignment" Value="Right"/>
<Setter TargetName="ToggleLabel" Property="Text" Value="ON"/>
<Setter TargetName="ToggleLabel" Property="Foreground" Value="White"/>
<Setter TargetName="ToggleLabel" Property="HorizontalAlignment" Value="Left"/>
<Setter TargetName="ToggleLabel" Property="Margin" Value="10,0,0,0"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Root" Property="Opacity" Value="0.45"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid Background="#EDF1F7">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Margin="10,10,10,8">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="DEVICE IO MONITOR / 设备IO监控" FontSize="20" FontWeight="Bold" Foreground="#0F3B7A"/>
<StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center">
<Border Style="{StaticResource StatusBadgeBorderStyle}">
<TextBlock Text="{Binding PageState.LastRefreshTime, StringFormat=刷新:{0:HH:mm:ss}}" Foreground="#475569"/>
</Border>
<Border>
<Border.Style>
<Style TargetType="Border" BasedOn="{StaticResource StatusBadgeBorderStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding PageState.IsOnline}" Value="True">
<Setter Property="Background" Value="#DCFCE7"/>
</DataTrigger>
<DataTrigger Binding="{Binding PageState.IsOnline}" Value="False">
<Setter Property="Background" Value="#FEE2E2"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBlock Text="{Binding PageState.OnlineText}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="#B91C1C"/>
<Style.Triggers>
<DataTrigger Binding="{Binding PageState.IsOnline}" Value="True">
<Setter Property="Foreground" Value="#166534"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Border>
</StackPanel>
</Grid>
<Border Margin="0,8,0,0" Padding="12,6">
<Border.Style>
<Style TargetType="Border" BasedOn="{StaticResource StatusBadgeBorderStyle}">
<Setter Property="Background" Value="#EFF6FF"/>
<Style.Triggers>
<DataTrigger Binding="{Binding PageState.IsWriteSuccess}" Value="True">
<Setter Property="Background" Value="#DCFCE7"/>
</DataTrigger>
<DataTrigger Binding="{Binding PageState.IsWriteSuccess}" Value="False">
<Setter Property="Background" Value="#FEF3C7"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding PageState.LastWriteTime, StringFormat=写入时间:{0:HH:mm:ss}}" Foreground="#475569" Margin="0,0,14,0"/>
<TextBlock Text="{Binding PageState.LastWriteMessage}" FontWeight="SemiBold" TextWrapping="Wrap"/>
</StackPanel>
</Border>
</StackPanel>
<ScrollViewer Grid.Row="1" Margin="10,0,10,10" VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding PageState.Modules}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Style="{StaticResource IoCardStyle}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Name}" FontSize="18" FontWeight="Bold" Foreground="#0F3B7A"/>
<Grid Grid.Row="1" Margin="0,10,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition>
<ColumnDefinition.Style>
<Style TargetType="ColumnDefinition">
<Setter Property="Width" Value="*"/>
<Style.Triggers>
<DataTrigger Binding="{Binding HasInputs}" Value="False">
<Setter Property="Width" Value="0"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ColumnDefinition.Style>
</ColumnDefinition>
<ColumnDefinition>
<ColumnDefinition.Style>
<Style TargetType="ColumnDefinition">
<Setter Property="Width" Value="*"/>
<Style.Triggers>
<DataTrigger Binding="{Binding HasOutputs}" Value="False">
<Setter Property="Width" Value="0"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ColumnDefinition.Style>
</ColumnDefinition>
</Grid.ColumnDefinitions>
<Border BorderBrush="#BFDBFE" Background="#F8FBFF">
<Border.Style>
<Style TargetType="Border" BasedOn="{StaticResource IoSectionBorderStyle}">
<Setter Property="Margin" Value="0,0,6,0"/>
<Style.Triggers>
<DataTrigger Binding="{Binding HasInputs}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
<DataTrigger Binding="{Binding HasOutputs}" Value="False">
<Setter Property="Margin" Value="0"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<StackPanel>
<TextBlock Text="输入 IO" Foreground="#1D4ED8" FontWeight="Bold" Margin="0,0,0,8"/>
<ItemsControl ItemsSource="{Binding InputPoints}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Style="{StaticResource InputItemBorderStyle}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Ellipse Style="{StaticResource InputStatusDotStyle}" VerticalAlignment="Center" Margin="0,0,8,0"/>
<StackPanel Grid.Column="1">
<TextBlock Text="{Binding Description}" Foreground="#1E3A8A" FontWeight="SemiBold"/>
<TextBlock Text="{Binding StationNo, StringFormat=站号:{0}}" Foreground="#1D4ED8" FontSize="11"/>
<TextBlock Text="{Binding LineNo, StringFormat=线标:{0}}" Foreground="#1D4ED8" FontSize="11"/>
<TextBlock Text="{Binding Name}" Foreground="#64748B" FontSize="11" TextWrapping="Wrap"/>
</StackPanel>
<TextBlock Grid.Column="2" Text="{Binding StateText}" VerticalAlignment="Center" Foreground="#1E40AF" FontWeight="Bold"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
<Border Grid.Column="1" BorderBrush="#FDBA74" Background="#FFF9F2">
<Border.Style>
<Style TargetType="Border" BasedOn="{StaticResource IoSectionBorderStyle}">
<Setter Property="Margin" Value="6,0,0,0"/>
<Style.Triggers>
<DataTrigger Binding="{Binding HasOutputs}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
<DataTrigger Binding="{Binding HasInputs}" Value="False">
<Setter Property="Margin" Value="0"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<StackPanel>
<TextBlock Text="输出 IO" Foreground="#C2410C" FontWeight="Bold" Margin="0,0,0,8"/>
<ItemsControl ItemsSource="{Binding OutputPoints}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Style="{StaticResource OutputItemBorderStyle}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Ellipse Style="{StaticResource OutputStatusDotStyle}" VerticalAlignment="Center" Margin="0,0,8,0"/>
<StackPanel Grid.Column="1">
<TextBlock Text="{Binding Description}" Foreground="#9A3412" FontWeight="SemiBold"/>
<TextBlock Text="{Binding StationNo, StringFormat=站号:{0}}" Foreground="#C2410C" FontSize="11"/>
<TextBlock Text="{Binding LineNo, StringFormat=线标:{0}}" Foreground="#C2410C" FontSize="11"/>
<TextBlock Text="{Binding Name}" Foreground="#7C2D12" FontSize="11" TextWrapping="Wrap"/>
</StackPanel>
<TextBlock Grid.Column="2" Text="{Binding StateText}" Margin="0,0,10,0" VerticalAlignment="Center" Foreground="#C2410C" FontWeight="Bold"/>
<ToggleButton Grid.Column="3"
Style="{StaticResource IoOutputToggleButtonStyle}"
IsChecked="{Binding IsOn, Mode=OneWay}"
Command="{Binding ToggleCommand}"
IsEnabled="{Binding CanWrite}"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
</Grid>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</UserControl>

View File

@@ -0,0 +1,12 @@
using System.Windows.Controls;
namespace MainShell.DeviceMaintance.View
{
public partial class DeviceIoView : UserControl
{
public DeviceIoView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,38 @@
<UserControl x:Class="MainShell.DeviceMaintance.View.DeviceMaintanceView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MainShell.DeviceMaintance.View"
xmlns:mw="http://www.maxwell-gp.com/"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Margin="-40,0,0,0" Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<mw:SideMenu ItemsSource="{Binding MenuItemWraps}"
SelectedItem="{Binding SelectedMenuItem, Mode=TwoWay}"
Grid.Row ="0" Width="180"
ExpandMode="Accordion"
AutoSelect="True"
>
<mw:SideMenu.ItemContainerStyle>
<Style TargetType="{x:Type mw:SideMenuItem}" BasedOn="{StaticResource SideMenuItemHeaderAccordionBaseStyle}">
<Setter Property="Header" Value="{Binding Header}" />
<Setter Property="Tag" Value="{Binding Tag}" />
</Style>
</mw:SideMenu.ItemContainerStyle>
</mw:SideMenu>
</Grid>
<ContentControl Margin="5,0" Grid.Column="1" mw:View.Model="{Binding CurrentScreen}"/>
</Grid>
</UserControl>

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace MainShell.DeviceMaintance.View
{
/// <summary>
/// DeviceMaintanceView.xaml 的交互逻辑
/// </summary>
public partial class DeviceMaintanceView : UserControl
{
public DeviceMaintanceView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,102 @@
<UserControl x:Class="MainShell.DeviceMaintance.View.HardwareTestView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mw="http://www.maxwell-gp.com/"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<ResourceDictionary>
<Style x:Key="HardwareTestLabelStyle" TargetType="Label" BasedOn="{StaticResource ProcessLabelStyle}">
<Setter Property="Width" Value="126"/>
</Style>
<Style x:Key="HardwareTestValueBorderStyle" TargetType="Border">
<Setter Property="Background" Value="#F8FAFC"/>
<Setter Property="BorderBrush" Value="{StaticResource ProcessCardBorderBrush}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="4"/>
<Setter Property="Padding" Value="12,6"/>
<Setter Property="Margin" Value="8,0,18,0"/>
<Setter Property="MinWidth" Value="150"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style x:Key="HardwareTestValueTextStyle" TargetType="TextBlock">
<Setter Property="FontSize" Value="14"/>
<Setter Property="Foreground" Value="{StaticResource ProcessBodyForegroundBrush}"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
<Style x:Key="HardwareTestIntNumberBoxStyle" TargetType="{x:Type mw:IntNumberBox}" BasedOn="{StaticResource ProcessLargeIntNumberBoxStyle}">
<Setter Property="Margin" Value="8,0,18,0"/>
</Style>
<Style x:Key="HardwareTestButtonStyle" TargetType="Button" BasedOn="{StaticResource TestButtonStyle}">
<Setter Property="Width" Value="110"/>
<Setter Property="Height" Value="32"/>
<Setter Property="Margin" Value="8,0,0,0"/>
</Style>
<Style x:Key="HardwareTestStartButtonStyle" TargetType="Button" BasedOn="{StaticResource StartButtonStyle}">
<Setter Property="Width" Value="110"/>
<Setter Property="Height" Value="32"/>
<Setter Property="Margin" Value="8,0,0,0"/>
</Style>
<Style x:Key="HardwareTestStopButtonStyle" TargetType="Button" BasedOn="{StaticResource CloseButtonStyle}">
<Setter Property="Width" Value="110"/>
<Setter Property="Height" Value="32"/>
<Setter Property="Margin" Value="8,0,0,0"/>
</Style>
</ResourceDictionary>
</UserControl.Resources>
<Grid Background="{StaticResource ProcessPageBackgroundBrush}">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" Margin="4" Padding="0,0,4,0">
<StackPanel Margin="0,0,0,4">
<GroupBox Header="{DynamicResource Diastimeter}" Style="{StaticResource ProcessWideCardGroupBoxStyle}">
<WrapPanel>
<Label Style="{StaticResource HardwareTestLabelStyle}" Content="{DynamicResource DiastimeterValue}"/>
<Border Style="{StaticResource HardwareTestValueBorderStyle}">
<TextBlock Style="{StaticResource HardwareTestValueTextStyle}" Text="{Binding Message}"/>
</Border>
<Button Style="{StaticResource HardwareTestButtonStyle}" Click="{mw:Action btnZeroClick}" Content="{DynamicResource SetZero}"/>
<Button Style="{StaticResource HardwareTestButtonStyle}" Click="{mw:Action btnGetCurrentValueClick}" Content="{DynamicResource GetCurrentValue}"/>
</WrapPanel>
</GroupBox>
<GroupBox Header="FFU" Style="{StaticResource ProcessWideCardGroupBoxStyle}">
<WrapPanel>
<Label Style="{StaticResource HardwareTestLabelStyle}" Content="{DynamicResource FFURotateSpeed}"/>
<mw:IntNumberBox Style="{StaticResource HardwareTestIntNumberBoxStyle}" Value="{Binding FFURotateSpeed}" ValueChanged="{mw:Action FFURotateSpeedChanged}"/>
<Button Style="{StaticResource HardwareTestStartButtonStyle}" Content="{DynamicResource Open}" Click="{mw:Action BtnOpenFFU}"/>
<Button Style="{StaticResource HardwareTestStopButtonStyle}" Content="{DynamicResource Close}" Click="{mw:Action BtnCloseFFU}"/>
</WrapPanel>
</GroupBox>
<WrapPanel>
<GroupBox Header="{DynamicResource WaferScaner}" Style="{StaticResource ProcessCardGroupBoxStyle}" Width="430" Margin="0,0,18,18">
<WrapPanel>
<Button Style="{StaticResource HardwareTestButtonStyle}" Click="{mw:Action btnScanWaferBarcodeClick}" Content="{DynamicResource GetCurrentValue}"/>
<Border Style="{StaticResource HardwareTestValueBorderStyle}" MinWidth="180" Margin="8,0,0,0">
<TextBlock Style="{StaticResource HardwareTestValueTextStyle}" Text="{Binding WaferBarcode}"/>
</Border>
</WrapPanel>
</GroupBox>
<GroupBox Header="{DynamicResource GlassScaner}" Style="{StaticResource ProcessCardGroupBoxStyle}" Width="430" Margin="0,0,0,18">
<WrapPanel>
<Button Style="{StaticResource HardwareTestButtonStyle}" Click="{mw:Action btnScanGlassBarcodeClick}" Content="{DynamicResource GetCurrentValue}"/>
<Border Style="{StaticResource HardwareTestValueBorderStyle}" MinWidth="180" Margin="8,0,0,0">
<TextBlock Style="{StaticResource HardwareTestValueTextStyle}" Text="{Binding GlassBarcode}"/>
</Border>
</WrapPanel>
</GroupBox>
</WrapPanel>
</StackPanel>
</ScrollViewer>
</Grid>
</UserControl>

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace MainShell.DeviceMaintance.View
{
/// <summary>
/// HardwareTestView.xaml 的交互逻辑
/// </summary>
public partial class HardwareTestView : UserControl
{
public HardwareTestView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,23 @@
<UserControl x:Class="MainShell.DeviceMaintance.View.IOMaintanceView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MainShell.DeviceMaintance.View"
xmlns:mw="http://www.maxwell-gp.com/"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Border Background="{StaticResource BackgroundBrush}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="2,2,2,2">
<TabControl mw:TabControlAttach.FontSize="14">
<TabItem Header="IO监控" >
<ContentControl mw:View.Model="{Binding IOMonitorViewModel}" Margin="15"/>
</TabItem>
<TabItem Header="气缸控制" >
<ContentControl mw:View.Model="{Binding CylinderViewModel}" Margin="15"/>
</TabItem>
<TabItem Header="IO测试" >
<ContentControl mw:View.Model="{Binding IoTestViewModel}" Margin="15"/>
</TabItem>
</TabControl>
</Border>
</UserControl>

View File

@@ -0,0 +1,13 @@
<UserControl x:Class="MainShell.DeviceMaintance.View.IOMonitorView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MainShell.DeviceMaintance.View"
xmlns:mw="http://www.maxwell-gp.com/"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<ContentControl mw:View.Model="{Binding DeviceIoViewModel}"/>
</Grid>
</UserControl>

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace MainShell.DeviceMaintance.View
{
/// <summary>
/// IOMonitorView.xaml 的交互逻辑
/// </summary>
public partial class IOMonitorView : UserControl
{
public IOMonitorView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,143 @@
<UserControl x:Class="MainShell.DeviceMaintance.View.IoTestView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mw="http://www.maxwell-gp.com/"
mc:Ignorable="d"
d:DesignHeight="560" d:DesignWidth="980">
<UserControl.Resources>
<Style x:Key="IoTestGroupBoxStyle" TargetType="GroupBox" BasedOn="{StaticResource ProcessWideCardGroupBoxStyle}">
<Setter Property="Margin" Value="0,0,0,16"/>
</Style>
<Style x:Key="IoTestLabelStyle" TargetType="Label" BasedOn="{StaticResource ProcessLabelStyle}">
<Setter Property="Width" Value="95"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
</Style>
<Style x:Key="IoTestNumberBoxStyle" TargetType="{x:Type mw:IntNumberBox}" BasedOn="{StaticResource ProcessLargeIntNumberBoxStyle}">
<Setter Property="Width" Value="110"/>
<Setter Property="Margin" Value="0,0,12,8"/>
</Style>
<Style x:Key="IoTestButtonStyle" TargetType="Button" BasedOn="{StaticResource TestButtonStyle}">
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="32"/>
<Setter Property="Margin" Value="0,0,12,0"/>
</Style>
<Style x:Key="IoTestResultBorderStyle" TargetType="Border">
<Setter Property="Background" Value="#F8FAFC"/>
<Setter Property="BorderBrush" Value="{StaticResource ProcessCardBorderBrush}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="4"/>
<Setter Property="Padding" Value="12,8"/>
<Setter Property="Margin" Value="0,4,0,0"/>
</Style>
<Style x:Key="IoTestCheckBoxStyle" TargetType="CheckBox">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="0,0,18,8"/>
</Style>
</UserControl.Resources>
<Grid Background="{StaticResource ProcessPageBackgroundBrush}">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" Margin="4" Padding="0,0,4,0">
<StackPanel Margin="0,0,0,4">
<GroupBox Header="Delta IO状态" Style="{StaticResource IoTestGroupBoxStyle}">
<StackPanel>
<WrapPanel>
<Label Style="{StaticResource IoTestLabelStyle}" Content="控制卡状态"/>
<TextBlock VerticalAlignment="Center" Text="{Binding CardStatusText}" TextWrapping="Wrap" Width="620"/>
<Button Style="{StaticResource IoTestButtonStyle}" Content="刷新状态" Click="{mw:Action RefreshCardStatus}"/>
</WrapPanel>
</StackPanel>
</GroupBox>
<GroupBox Header="数字量 Bit 测试" Style="{StaticResource IoTestGroupBoxStyle}">
<StackPanel>
<WrapPanel>
<Label Style="{StaticResource IoTestLabelStyle}" Content="CardNo"/>
<mw:IntNumberBox Style="{StaticResource IoTestNumberBoxStyle}" Value="{Binding BitState.CardNo}"/>
<Label Style="{StaticResource IoTestLabelStyle}" Content="Node"/>
<mw:IntNumberBox Style="{StaticResource IoTestNumberBoxStyle}" Value="{Binding BitState.Node}"/>
<Label Style="{StaticResource IoTestLabelStyle}" Content="Slot"/>
<mw:IntNumberBox Style="{StaticResource IoTestNumberBoxStyle}" Value="{Binding BitState.Slot}"/>
</WrapPanel>
<WrapPanel>
<Label Style="{StaticResource IoTestLabelStyle}" Content="Index"/>
<mw:IntNumberBox Style="{StaticResource IoTestNumberBoxStyle}" Value="{Binding BitState.Index}"/>
<Label Style="{StaticResource IoTestLabelStyle}" Content="SubIndex"/>
<mw:IntNumberBox Style="{StaticResource IoTestNumberBoxStyle}" Value="{Binding BitState.SubIndex}"/>
<Label Style="{StaticResource IoTestLabelStyle}" Content="BitNo"/>
<mw:IntNumberBox Style="{StaticResource IoTestNumberBoxStyle}" Value="{Binding BitState.BitNo}"/>
</WrapPanel>
<WrapPanel>
<Label Style="{StaticResource IoTestLabelStyle}" Content="IoType"/>
<mw:IntNumberBox Style="{StaticResource IoTestNumberBoxStyle}" Value="{Binding BitState.IoType}"/>
<Label Style="{StaticResource IoTestLabelStyle}" Content="ReadIoType"/>
<mw:IntNumberBox Style="{StaticResource IoTestNumberBoxStyle}" Value="{Binding BitState.ReadIoType}"/>
<CheckBox Style="{StaticResource IoTestCheckBoxStyle}" Content="写入值" IsChecked="{Binding BitState.WriteValue}"/>
<CheckBox Style="{StaticResource IoTestCheckBoxStyle}" Content="读取结果" IsChecked="{Binding BitState.ReadValue}" IsEnabled="False"/>
</WrapPanel>
<WrapPanel Margin="0,4,0,0">
<Button Style="{StaticResource IoTestButtonStyle}" Content="读取 Bit" Click="{mw:Action ReadBit}"/>
<Button Style="{StaticResource IoTestButtonStyle}" Content="写入 Bit" Click="{mw:Action WriteBit}"/>
<TextBlock VerticalAlignment="Center" Text="{Binding BitState.ReturnCode, StringFormat=返回码:{0}}"/>
</WrapPanel>
<Border Style="{StaticResource IoTestResultBorderStyle}">
<TextBlock Text="{Binding BitState.ResultMessage}" TextWrapping="Wrap"/>
</Border>
</StackPanel>
</GroupBox>
<GroupBox Header="模拟量 DA 测试" Style="{StaticResource IoTestGroupBoxStyle}">
<StackPanel>
<WrapPanel>
<Label Style="{StaticResource IoTestLabelStyle}" Content="CardNo"/>
<mw:IntNumberBox Style="{StaticResource IoTestNumberBoxStyle}" Value="{Binding DaState.CardNo}"/>
<Label Style="{StaticResource IoTestLabelStyle}" Content="Node"/>
<mw:IntNumberBox Style="{StaticResource IoTestNumberBoxStyle}" Value="{Binding DaState.Node}"/>
<Label Style="{StaticResource IoTestLabelStyle}" Content="Slot"/>
<mw:IntNumberBox Style="{StaticResource IoTestNumberBoxStyle}" Value="{Binding DaState.Slot}"/>
</WrapPanel>
<WrapPanel>
<Label Style="{StaticResource IoTestLabelStyle}" Content="Index"/>
<mw:IntNumberBox Style="{StaticResource IoTestNumberBoxStyle}" Value="{Binding DaState.Index}"/>
<Label Style="{StaticResource IoTestLabelStyle}" Content="SubIndex"/>
<mw:IntNumberBox Style="{StaticResource IoTestNumberBoxStyle}" Value="{Binding DaState.SubIndex}"/>
<Label Style="{StaticResource IoTestLabelStyle}" Content="ByteSize"/>
<mw:IntNumberBox Style="{StaticResource IoTestNumberBoxStyle}" Value="{Binding DaState.ByteSize}"/>
</WrapPanel>
<WrapPanel>
<Label Style="{StaticResource IoTestLabelStyle}" Content="IoType"/>
<mw:IntNumberBox Style="{StaticResource IoTestNumberBoxStyle}" Value="{Binding DaState.IoType}"/>
<Label Style="{StaticResource IoTestLabelStyle}" Content="写入值"/>
<mw:IntNumberBox Style="{StaticResource IoTestNumberBoxStyle}" Value="{Binding DaState.WriteRawValue}"/>
<Label Style="{StaticResource IoTestLabelStyle}" Content="读取值"/>
<mw:IntNumberBox Style="{StaticResource IoTestNumberBoxStyle}" Value="{Binding DaState.ReadRawValue}" IsEnabled="False"/>
</WrapPanel>
<WrapPanel>
<CheckBox Style="{StaticResource IoTestCheckBoxStyle}" Content="有符号" IsChecked="{Binding DaState.Signed}"/>
<Button Style="{StaticResource IoTestButtonStyle}" Content="读取 DA" Click="{mw:Action ReadDa}"/>
<Button Style="{StaticResource IoTestButtonStyle}" Content="写入 DA" Click="{mw:Action WriteDa}"/>
<TextBlock VerticalAlignment="Center" Text="{Binding DaState.ReturnCode, StringFormat=返回码:{0}}"/>
</WrapPanel>
<Border Style="{StaticResource IoTestResultBorderStyle}">
<TextBlock Text="{Binding DaState.ResultMessage}" TextWrapping="Wrap"/>
</Border>
</StackPanel>
</GroupBox>
</StackPanel>
</ScrollViewer>
</Grid>
</UserControl>

View File

@@ -0,0 +1,15 @@
using System.Windows.Controls;
namespace MainShell.DeviceMaintance.View
{
/// <summary>
/// IoTestView.xaml 的交互逻辑
/// </summary>
public partial class IoTestView : UserControl
{
public IoTestView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,178 @@
<UserControl x:Class="MainShell.DeviceMaintance.View.LaserCompensationView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mw="http://www.maxwell-gp.com/"
mc:Ignorable="d"
d:DesignHeight="560"
d:DesignWidth="900">
<UserControl.Resources>
<ResourceDictionary>
<Style TargetType="Label" BasedOn="{StaticResource {x:Type Label}}">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Right"/>
<Setter Property="Margin" Value="8,0,8,0"/>
<Setter Property="Foreground" Value="{StaticResource ProcessBodyForegroundBrush}"/>
<Setter Property="FontWeight" Value="SemiBold"/>
</Style>
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}">
<Setter Property="Foreground" Value="{StaticResource ProcessBodyForegroundBrush}"/>
</Style>
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Width" Value="110"/>
<Setter Property="Height" Value="32"/>
<Setter Property="Margin" Value="8,0,0,0"/>
</Style>
</ResourceDictionary>
</UserControl.Resources>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
<Grid Background="{StaticResource ProcessPageBackgroundBrush}" Margin="8">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<GroupBox Grid.Row="0" Header="{DynamicResource LaserCompensationParameters}" Style="{StaticResource ProcessWideCardGroupBoxStyle}">
<Grid Margin="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="280"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="280"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="280"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="{DynamicResource AxisName}"/>
<ComboBox Grid.Row="0" Grid.Column="1"
Style="{StaticResource ProcessLargeComboBoxStyle}"
ItemsSource="{Binding AxisNames}"
SelectedItem="{Binding SelectedAxisName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<Label Grid.Row="0" Grid.Column="2" Content="{DynamicResource LaserCompensationStartPosition}"/>
<mw:NumberBox Grid.Row="0" Grid.Column="3"
Style="{StaticResource ProcessLargeNumberBoxStyle}"
Value="{Binding Setting.StartPos, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DecimalPlaces="4"
mw:NumericKeypadAttach.IsEnabled="True"
ShowUpDownButton="True"/>
<Label Grid.Row="0" Grid.Column="4" Content="{DynamicResource LaserCompensationStepDistance}"/>
<mw:NumberBox Grid.Row="0" Grid.Column="5"
Style="{StaticResource ProcessLargeNumberBoxStyle}"
Value="{Binding Setting.Steps, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DecimalPlaces="4"
mw:NumericKeypadAttach.IsEnabled="True"
ShowUpDownButton="True"/>
<Label Grid.Row="1" Grid.Column="0" Content="{DynamicResource LaserCompensationStepCount}"/>
<mw:IntNumberBox Grid.Row="1" Grid.Column="1"
Style="{StaticResource ProcessLargeIntNumberBoxStyle}"
Value="{Binding Setting.StepsCount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
mw:NumericKeypadAttach.IsEnabled="True"
ShowUpDownButton="True"/>
<Label Grid.Row="1" Grid.Column="2" Content="{DynamicResource LaserCompensationJumpPosition}"/>
<mw:NumberBox Grid.Row="1" Grid.Column="3"
Style="{StaticResource ProcessLargeNumberBoxStyle}"
Value="{Binding Setting.JumpPos, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DecimalPlaces="4"
mw:NumericKeypadAttach.IsEnabled="True"
ShowUpDownButton="True"/>
<Label Grid.Row="1" Grid.Column="4" Content="{DynamicResource LaserCompensationCycleCount}"/>
<mw:IntNumberBox Grid.Row="1" Grid.Column="5"
Style="{StaticResource ProcessLargeIntNumberBoxStyle}"
Value="{Binding Setting.WorkCount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
mw:NumericKeypadAttach.IsEnabled="True"
ShowUpDownButton="True"/>
<Label Grid.Row="2" Grid.Column="0" Content="{DynamicResource Speed}"/>
<mw:NumberBox Grid.Row="2" Grid.Column="1"
Style="{StaticResource ProcessLargeNumberBoxStyle}"
Value="{Binding Setting.Speed, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DecimalPlaces="4"
mw:NumericKeypadAttach.IsEnabled="True"
ShowUpDownButton="True"/>
<Label Grid.Row="2" Grid.Column="2" Content="{DynamicResource LaserCompensationDelaySeconds}"/>
<mw:NumberBox Grid.Row="2" Grid.Column="3"
Style="{StaticResource ProcessLargeNumberBoxStyle}"
Value="{Binding Setting.DwellTime, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DecimalPlaces="3"
mw:NumericKeypadAttach.IsEnabled="True"
ShowUpDownButton="True"/>
<Button Grid.Row="2" Grid.Column="5" Content="{DynamicResource Save}" Click="{mw:Action Save}" HorizontalAlignment="Left"/>
</Grid>
</GroupBox>
<GroupBox Grid.Row="1" Header="{DynamicResource LaserCompensationExecutionControl}" Style="{StaticResource ProcessWideCardGroupBoxStyle}" Margin="0,12,0,0">
<Grid Margin="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Content="{DynamicResource Start}" IsEnabled="{Binding UiEnable}" Click="{mw:Action StartAsync}"/>
<Button Grid.Column="1" Content="{DynamicResource Stop}" IsEnabled="{Binding IsRunning}" Click="{mw:Action Stop}"/>
<TextBlock Grid.Column="2"
VerticalAlignment="Center"
Text="{DynamicResource LaserCompensationTrajectoryOrder}"
Margin="18,0,0,0"/>
</Grid>
</GroupBox>
<GroupBox Grid.Row="2" Header="{DynamicResource LaserCompensationExecutionStatus}" Style="{StaticResource ProcessWideCardGroupBoxStyle}" Margin="0,12,0,0">
<Grid Margin="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="160"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="{DynamicResource LaserCompensationCurrentCycle}"/>
<TextBlock Grid.Column="1" VerticalAlignment="Center" Text="{Binding CurrentLoopIndex}"/>
<Label Grid.Column="2" Content="{DynamicResource LaserCompensationCurrentPoint}"/>
<TextBlock Grid.Column="3" VerticalAlignment="Center" Text="{Binding CurrentPointIndex}"/>
<Label Grid.Column="4" Content="{DynamicResource LaserCompensationCurrentTarget}"/>
<TextBlock Grid.Column="5" VerticalAlignment="Center" Text="{Binding CurrentTargetPosition, StringFormat=F4}"/>
</Grid>
</GroupBox>
<GroupBox Grid.Row="3" Header="{DynamicResource Description}" Style="{StaticResource ProcessWideCardGroupBoxStyle}" Margin="0,12,0,0">
<StackPanel Margin="4">
<TextBlock TextWrapping="Wrap"
Text="{DynamicResource LaserCompensationDescriptionPrimary}"/>
<TextBlock Margin="0,8,0,0"
TextWrapping="Wrap"
Text="{DynamicResource LaserCompensationDescriptionSecondary}"/>
</StackPanel>
</GroupBox>
</Grid>
</ScrollViewer>
</UserControl>

View File

@@ -0,0 +1,12 @@
using System.Windows.Controls;
namespace MainShell.DeviceMaintance.View
{
public partial class LaserCompensationView : UserControl
{
public LaserCompensationView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,48 @@
<UserControl x:Class="MainShell.DeviceMaintance.View.NeedleBaseView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MainShell.DeviceMaintance.View"
xmlns:mw="http://www.maxwell-gp.com/"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ListBox Grid.Row="0" Background="#D7DDE4"
Style="{StaticResource NavigationListBoxStyle}"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ItemsSource="{Binding NavigationItems}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate >
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"
FontWeight="Bold"
Foreground="#505050"
FontSize="14" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ContentControl Margin="2" Content="{Binding CameraAxisViewModel}"/>
<Border BorderBrush="Gray" BorderThickness="1" Margin="5,2" Grid.Column="1">
<ContentControl Margin="2"
mw:View.Model="{Binding CurrentScreen}"/>
</Border>
</Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace MainShell.DeviceMaintance.View
{
/// <summary>
/// NeedleBaseView.xaml 的交互逻辑
/// </summary>
public partial class NeedleBaseView : UserControl
{
public NeedleBaseView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,142 @@
<UserControl x:Class="MainShell.DeviceMaintance.View.NeedleCaliView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MainShell.DeviceMaintance.View"
xmlns:mwControls="http://www.maxwell-gp.com/"
xmlns:Att="clr-namespace:MainShell.Common.ControlAttribute"
xmlns:customControl="clr-namespace:MainShell.Resources.CustomControl"
mc:Ignorable="d"
d:DesignHeight="850" d:DesignWidth="800">
<UserControl.Resources>
<Style TargetType="GroupBox" BasedOn="{StaticResource GroupStepControl}"/>
<Style TargetType="Label" BasedOn="{StaticResource {x:Type Label}}">
<Setter Property="HorizontalContentAlignment" Value="Right"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Right"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Height" Value="35"/>
<Setter Property="Width" Value="80"/>
</Style>
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="Margin" Value="3"/>
<Setter Property="Height" Value="35"/>
<Setter Property="Width" Value="90"/>
</Style>
</UserControl.Resources>
<Grid mwControls:ParameterAttach.DelayAcceptValue="{Binding ParameterHelper}">
<ScrollViewer VerticalScrollBarVisibility="Visible" Margin="5" ClipToBounds="True">
<StackPanel>
<GroupBox Header="【第一步】对刀仪偏差设置" IsEnabled="{Binding UiEnable}">
<StackPanel Margin="5" HorizontalAlignment="Center" Orientation="Horizontal">
<Label Content="对刀时偏差:" />
<mwControls:NumberBox Value="{Binding NeedleZCalibrationItem.KnifeOffset}" mwControls:NumericKeypadAttach.IsEnabled="True" Minimum="-1000" Maximum="1000" HorizontalAlignment="Left" Margin="2" Width="80" Height="35" />
</StackPanel>
</GroupBox>
<GroupBox Header="【第二步】SZ / StagePlatform设置" IsEnabled="{Binding UiEnable}">
<customControl:AxisMoveControl LableContent1="SZ(mm)"
Value1="{Binding NeedleZCalibrationItem.CZHeight}"
LableContent2="StagePlatform高度"
Value2="{Binding NeedleZCalibrationItem.StageHeight}"
IsAllShow="{Binding HasStagePlatform}"
MoveCommand="{mwControls:Action MoveCzCurrentLocation}"/>
</GroupBox>
<GroupBox Header="【第三步】龙门2的避让位置" IsEnabled="{Binding UiEnable}">
<customControl:AxisMoveControl LableContent1="X2(mm)"
Value1="{Binding NeedleZCalibrationItem.Gantry2AvoidPositionX}"
LableContent2="Y2(mm)"
Value2="{Binding NeedleZCalibrationItem.Gantry2AvoidPositionY}"
ReadCommand="{mwControls:Action ReadGantry2CurrentLocation}"
MoveCommand="{mwControls:Action MoveGantry2ToCurrentLocation}"/>
</GroupBox>
<GroupBox Header="【第四步】针尖对准对刀仪位置" IsEnabled="{Binding UiEnable}">
<customControl:AxisMoveControl LableContent1="X1(mm)"
Value1="{Binding NeedleZCalibrationItem.SupportPinPositionX}"
LableContent2="Y1(mm)"
Value2="{Binding NeedleZCalibrationItem.SupportPinPositionY}"
ReadCommand="{mwControls:Action ReadSupportPinCurrentLocation}"
MoveCommand="{mwControls:Action MoveSupportPinToCurrentLocation}"/>
</GroupBox>
<GroupBox Header="【第五步】Z1设置" IsEnabled="{Binding UiEnable}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<UniformGrid Columns="4" Rows="1">
<Label Content="开始位置(mm)" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Right" />
<mwControls:NumberBox Value="{Binding NeedleZCalibrationItem.Z1StartPosition}" mwControls:NumericKeypadAttach.IsEnabled="True" Minimum="-1000" Maximum="1000" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Left" Margin="2" Width="80" Height="35" />
<Label Content="速度(mm/s)" Grid.Row="0" Grid.Column="2" HorizontalAlignment="Right" />
<mwControls:NumberBox Value="{Binding NeedleZCalibrationItem.Z1Speed}" mwControls:NumericKeypadAttach.IsEnabled="True" Minimum="-1000" Maximum="1000" Grid.Row="0" Grid.Column="3" HorizontalAlignment="Left" Margin="2" Width="80" Height="35" />
</UniformGrid>
<UniformGrid Columns="2" Rows="1" Grid.Column="1">
<Label Content="下降距离(mm)" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Right" />
<mwControls:NumberBox Value="{Binding NeedleZCalibrationItem.Z1DropMaxPosition}" mwControls:NumericKeypadAttach.IsEnabled="True" Minimum="-1000" Maximum="1000" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" Margin="2" Width="80" Height="35" />
</UniformGrid>
</Grid>
</GroupBox>
<GroupBox Header="【第六步】刺针触碰到对刀仪" IsEnabled="{Binding UiEnable}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="100"/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Visibility="Visible" Content="基准值(mm)" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Right" />
<mwControls:NumberBox Visibility="Visible" IsReadOnly="True" Value="{Binding NeedleZCalibrationItem.NeedleTouchHeightBase}" mwControls:NumericKeypadAttach.IsEnabled="True" Minimum="-1000" Maximum="1000" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Left" Margin="5" Width="80" Height="35" />
<Label Content="Z1平均高度(mm)" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Right" />
<mwControls:NumberBox IsReadOnly="True" Value="{Binding NeedleZCalibrationItem.NeedleTouchHeightAve}" mwControls:NumericKeypadAttach.IsEnabled="True" Minimum="-1000" Maximum="1000" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" Margin="5" Width="80" Height="35" />
<Label Content="对刀次数:" Grid.Row="2" Grid.Column="0" HorizontalAlignment="Right" />
<mwControls:NumberBox Value="{Binding NeedleZCalibrationItem.NeedleTouchCount}" mwControls:NumericKeypadAttach.IsEnabled="True" Minimum="1" Maximum="100" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Left" Margin="5" Width="80" Height="35" />
<Label Content="当前使用对刀高度(mm)" Grid.Row="3" Grid.Column="0" HorizontalAlignment="Right" Width="140"/>
<mwControls:NumberBox IsEnabled="False" Grid.Row="3" Value="{Binding NeedleZCalibrationItem.CurrentNeedleTouchHeight}" mwControls:NumericKeypadAttach.IsEnabled="True" Minimum="-1000" Maximum="1000" Grid.Column="1" HorizontalAlignment="Left" Margin="5" Width="80" Height="35" />
<Label Content="对刀与基准偏差(mm)" Grid.Row="4" Grid.Column="0" HorizontalAlignment="Right" />
<mwControls:NumberBox IsReadOnly="True" Grid.Row="4" Value="{Binding NeedleZCalibrationItem.NeedleTouchOffset}" mwControls:NumericKeypadAttach.IsEnabled="True" Minimum="-1000" Maximum="1000" Grid.Column="1" HorizontalAlignment="Left" Margin="5" Width="80" Height="35" />
<Grid Grid.Column="2" Grid.ColumnSpan="2" Grid.RowSpan="5">
<ListView ItemsSource="{Binding NeedleZCalibrationItem.NeedleTouchRecords}" SelectedItem="{Binding SelectedRecord}">
<ListView.View>
<GridView>
<GridViewColumn Header="当前次数" DisplayMemberBinding="{Binding CurrentCount}" Width="100"/>
<GridViewColumn Header="Z1高度(mm)" DisplayMemberBinding="{Binding Height}" Width="210"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
</Grid>
</GroupBox>
<GroupBox Header="【第七步】对刀控制" IsEnabled="{Binding IsEnabledNeedleCalibrationControl}">
<StackPanel>
<StackPanel Margin="4" IsEnabled="{Binding UiEnable}" Orientation="Horizontal" HorizontalAlignment="Left">
<CheckBox Content="自动抬高" Margin="6,0" IsChecked="{Binding AutoRaiseZ1}"/>
<Button Visibility="Collapsed" Content="设置当前基准值" Tag="设置当前基准值" Click="{mwControls:Action SetBaseHeight}" Margin="6,0" />
<Button Content="Z1对刀" Tag="Z1对刀" Margin="6,0" Click="{mwControls:Action StartSingleZ1CalibrationAsync}"/>
<Button Content="使用当前对刀高度" Width="120" Tag="使用当前对刀高度" Click="{mwControls:Action UseCurrentZ1Height}" Margin="6,0" />
</StackPanel>
<StackPanel Margin="4" Orientation="Horizontal">
<Button Content="开始" Tag="开始" Click="{mwControls:Action StartCalibrationAsync}" Margin="6,0" IsEnabled="{Binding UiEnable}"/>
<Button Content="停止" Tag="停止" Click="{mwControls:Action StopCalibrationAsync}" Margin="6,0" IsEnabled="{Binding UiEnable, Converter={StaticResource boolToInversionConverter}}"/>
<Button Content="保存" Tag="保存" Click="{mwControls:Action SaveCalibration}" Margin="6,0" IsEnabled="{Binding UiEnable}"/>
</StackPanel>
</StackPanel>
</GroupBox>
</StackPanel>
</ScrollViewer>
</Grid>
</UserControl>

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace MainShell.DeviceMaintance.View
{
/// <summary>
/// NeedleCaliView.xaml 的交互逻辑
/// </summary>
public partial class NeedleCaliView : UserControl
{
public NeedleCaliView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,189 @@
<UserControl x:Class="MainShell.DeviceMaintance.View.NeedleCameraPrintView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MainShell.DeviceMaintance.View"
xmlns:mwControls="http://www.maxwell-gp.com/"
xmlns:customControl="clr-namespace:MainShell.Resources.CustomControl"
mc:Ignorable="d"
d:DesignHeight="750" d:DesignWidth="800">
<UserControl.Resources>
<Style TargetType="GroupBox" BasedOn="{StaticResource GroupStepControl}"/>
<Style TargetType="Label" BasedOn="{StaticResource {x:Type Label}}">
<Setter Property="HorizontalContentAlignment" Value="Right"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Height" Value="35"/>
<Setter Property="Width" Value="80"/>
</Style>
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}" >
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="Margin" Value="3"/>
<Setter Property="Height" Value="35"/>
<Setter Property="Width" Value="90"/>
</Style>
</UserControl.Resources>
<Grid mwControls:ParameterAttach.DelayAcceptValue ="{Binding ParameterHelper}">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<StackPanel>
<GroupBox IsEnabled="{Binding UiEnable}" Margin="2" Header="【第一步】基础设置">
<GroupBox.Content>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Button Click="{mwControls:Action MoveToOrginPos}" Content="SXSZ至初始位" Width="100"/>
<GroupBox Header="速度设置" Style="{x:Null}">
<StackPanel Orientation="Horizontal">
<RadioButton GroupName="speed" Click="{mwControls:Action SpeedChanged}" Tag="10" Margin="5,0" Content="10"/>
<RadioButton GroupName="speed" IsChecked="True" Click="{mwControls:Action SpeedChanged}" Tag="50" Margin="5,0" Content="50"/>
<RadioButton GroupName="speed" Click="{mwControls:Action SpeedChanged}" Tag="100" Margin="5,0" Content="100"/>
</StackPanel>
</GroupBox>
</StackPanel>
</GroupBox.Content>
</GroupBox>
<GroupBox IsEnabled="{Binding UiEnable}" Margin="2" Header="【第二步】WS避让位">
<GroupBox.Content>
<customControl:AxisMoveControl LableContent1="X2(mm)"
Value1="{Binding NeedlePrintCalibrateParameter.AvoidancePoint.PointX}"
LableContent2="Y2(mm)"
Value2="{Binding NeedlePrintCalibrateParameter.AvoidancePoint.PointY}"
ReadCommand="{mwControls:Action TeachWSPos}"
MoveCommand="{mwControls:Action MoveToWsPos}"/>
<!--<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Label VerticalAlignment="Center" Content="X2:"/>
<mwControls:NumberBox Value="{Binding NeedlePrintCalibrateParameter.AvoidancePoint.PointX}" IsReadOnly="True" Width="80" Margin="4,0" />
<Label VerticalAlignment="Center" Content="Y2:"/>
<mwControls:NumberBox Value="{Binding NeedlePrintCalibrateParameter.AvoidancePoint.PointY}" IsReadOnly="True" Width="80" Margin="4,0" />
<Button Margin="2,0" Click="{mwControls:Action TeachWSPos}" Content="示教"/>
<Button Margin="2,0" Click="{mwControls:Action MoveToWsPos}" Content="移动"/>
</StackPanel>-->
</GroupBox.Content>
</GroupBox>
<GroupBox IsEnabled="{Binding UiEnable}" Margin="2" Header="【第三步】Z1位置设置">
<GroupBox.Content>
<customControl:AxisMoveControl LableContent1="Z1(mm)"
Value1="{Binding NeedlePrintCalibrateParameter.Z1WorkHeight}"
IsAllShow="False"
ReadCommand="{mwControls:Action TeachZ1Pos}"
MoveCommand="{mwControls:Action MoveToZ1Pos}"/>
<!--<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Label VerticalAlignment="Center" Content="Z1:"/>
<mwControls:NumberBox mwControls:NumericKeypadAttach.IsEnabled="True" Value="{Binding NeedlePrintCalibrateParameter.Z1WorkHeight, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="False" Width="80" Margin="4,0" />
<Button Margin="2,0" Click="{mwControls:Action TeachZ1Pos}" Content="示教"/>
<Button Margin="2,0" Click="{mwControls:Action MoveToZ1Pos}" Content="移动"/>
</StackPanel>-->
</GroupBox.Content>
</GroupBox>
<GroupBox IsEnabled="{Binding UiEnable}" Margin="2" Header="【第四步】Z2位置设置">
<GroupBox.Content>
<customControl:AxisMoveControl LableContent1="Z2(mm)"
Value1="{Binding NeedlePrintCalibrateParameter.Z2WorkHeight}"
IsAllShow="False"
ReadCommand="{mwControls:Action TeachZ2Pos}"
MoveCommand="{mwControls:Action MoveToZ2Pos}"/>
<!--<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Label VerticalAlignment="Center" Content="Z2:"/>
<mwControls:NumberBox mwControls:NumericKeypadAttach.IsEnabled="True" Value="{Binding NeedlePrintCalibrateParameter.Z2WorkHeight, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="False" Width="80" Margin="4,0" />
<Button Margin="2,0" Click="{mwControls:Action TeachZ2Pos}" Content="示教"/>
<Button Margin="2,0" Click="{mwControls:Action MoveToZ2Pos}" Content="移动"/>
</StackPanel>-->
</GroupBox.Content>
</GroupBox>
<GroupBox IsEnabled="{Binding UiEnable}" Margin="2" Header="【第五步】铜箔区域设置">
<GroupBox.Content>
<StackPanel>
<Label Content="起点设置:"/>
<customControl:AxisMoveControl LableContent1="X1(mm)"
Value1="{Binding NeedlePrintCalibrateParameter.StartPoint.PointX}"
LableContent2="Y1(mm)"
Value2="{Binding NeedlePrintCalibrateParameter.StartPoint.PointY}"
ReadCommand="{mwControls:Action TeachStartPos}"
MoveCommand="{mwControls:Action MoveToStartPos}"
IsReadOnly="True"/>
<!--<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Label VerticalAlignment="Center" Content="X1:"/>
<mwControls:NumberBox Value="{Binding NeedlePrintCalibrateParameter.StartPoint.PointX}" IsReadOnly="True" Width="80" Margin="4,0" />
<Label VerticalAlignment="Center" Content="Y1:"/>
<mwControls:NumberBox Value="{Binding NeedlePrintCalibrateParameter.StartPoint.PointY}" IsReadOnly="True" Width="80" Margin="4,0" />
<Button Margin="2,0" Click="{mwControls:Action TeachStartPos}" Content="示教"/>
<Button Margin="2,0" Click="{mwControls:Action MoveToStartPos}" Content="移动"/>
</StackPanel>-->
<Label Content="尾点设置:"/>
<customControl:AxisMoveControl LableContent1="X2(mm)"
Value1="{Binding NeedlePrintCalibrateParameter.EndPoint.PointX}"
LableContent2="Y2(mm)"
Value2="{Binding NeedlePrintCalibrateParameter.EndPoint.PointY}"
ReadCommand="{mwControls:Action TeachEndPos}"
MoveCommand="{mwControls:Action MoveToEndPos}"
IsReadOnly="True"/>
<!--<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Label VerticalAlignment="Center" Content="X1:"/>
<mwControls:NumberBox Value="{Binding NeedlePrintCalibrateParameter.EndPoint.PointX}" IsReadOnly="True" Width="80" Margin="4,0" />
<Label VerticalAlignment="Center" Content="Y1:"/>
<mwControls:NumberBox Value="{Binding NeedlePrintCalibrateParameter.EndPoint.PointY}" IsReadOnly="True" Width="80" Margin="4,0" />
<Button Margin="2,0" Click="{mwControls:Action TeachEndPos}" Content="示教"/>
<Button Margin="2,0" Click="{mwControls:Action MoveToEndPos}" Content="移动"/>
</StackPanel>-->
<Label Content="间距设置:"/>
<StackPanel Orientation="Horizontal">
<Label VerticalAlignment="Center" Content="Xpitch:"/>
<mwControls:NumberBox mwControls:NumericKeypadAttach.IsEnabled="True" Value="{Binding NeedlePrintCalibrateParameter.Xpitch}" IsReadOnly="False" Width="80" Margin="4,0" />
<Label VerticalAlignment="Center" Content="Ypitch:"/>
<mwControls:NumberBox mwControls:NumericKeypadAttach.IsEnabled="True" Value="{Binding NeedlePrintCalibrateParameter.Ypitch}" IsReadOnly="False" Width="80" Margin="4,0" />
</StackPanel>
</StackPanel>
</GroupBox.Content>
</GroupBox>
<GroupBox Margin="2" Header="【第六步】针印检验">
<GroupBox.Content>
<StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button IsEnabled="{Binding UiEnable}" Click="{mwControls:Action StartVerify}" Content="开始校验"/>
<Button IsEnabled="{Binding UiEnable,Converter={StaticResource boolToInversionConverter}}" Click="{mwControls:Action StopVerify}" Content="停止校验"/>
<Button IsEnabled="{Binding UiEnable}" Click="{mwControls:Action SaveParam}" Content="保存"/>
<Button IsEnabled="{Binding UiEnable}" Click="{mwControls:Action ResetRecord}" Content="重置记录"/>
</StackPanel>
<StackPanel IsEnabled="{Binding UiEnable}" Margin="0,2" Orientation="Horizontal" HorizontalAlignment="Center">
<Button Click="{mwControls:Action NeedleAlignment}" Content="针尖对准"/>
<Button Click="{mwControls:Action CameraAlignment}" Content="相机对准"/>
</StackPanel>
</StackPanel>
</GroupBox.Content>
</GroupBox>
<GroupBox IsEnabled="{Binding UiEnable}" Margin="2" Header="【第七步】偏差补偿">
<GroupBox.Content>
<StackPanel>
<Label Content="当前针尖补偿:" Width="90"/>
<StackPanel Orientation="Horizontal">
<Label VerticalAlignment="Center" Content="XOffset:"/>
<mwControls:NumberBox Value="{Binding CurrentNeedleOffsetPoint.PointX}" IsReadOnly="True" Width="80" Margin="4,0" />
<Label VerticalAlignment="Center" Content="YOffsetY:"/>
<mwControls:NumberBox Value="{Binding CurrentNeedleOffsetPoint.PointY}" IsReadOnly="True" Width="80" Margin="4,0" />
</StackPanel>
<Label Content="针尖点位:"/>
<StackPanel Orientation="Horizontal">
<Label VerticalAlignment="Center" Content="X1:"/>
<mwControls:NumberBox Value="{Binding CurrentNeedlePoint.PointX}" IsReadOnly="True" Width="80" Margin="4,0" />
<Label VerticalAlignment="Center" Content="Y1:"/>
<mwControls:NumberBox Value="{Binding CurrentNeedlePoint.PointY}" IsReadOnly="True" Width="80" Margin="4,0" />
</StackPanel>
<Label Content="相机点位:"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Label VerticalAlignment="Center" Content="X1:"/>
<mwControls:NumberBox Value="{Binding CameraPoint.PointX}" IsReadOnly="True" Width="80" Margin="4,0" />
<Label VerticalAlignment="Center" Content="Y1:"/>
<mwControls:NumberBox Value="{Binding CameraPoint.PointY}" IsReadOnly="True" Width="80" Margin="4,0" />
<Button Margin="2,0" Click="{mwControls:Action TeachCameraPos}" Content="示教"/>
<Button Margin="2,0" Content="补偿偏差" Click="{mwControls:Action CalculateOffset}"/>
</StackPanel>
</StackPanel>
</GroupBox.Content>
</GroupBox>
</StackPanel>
</ScrollViewer>
</Grid>
</UserControl>

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace MainShell.DeviceMaintance.View
{
/// <summary>
/// NeedleCameraPrintView.xaml 的交互逻辑
/// </summary>
public partial class NeedleCameraPrintView : UserControl
{
public NeedleCameraPrintView()
{
InitializeComponent();
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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