using MainShell.Common; using MainShell.Filewritable; using MainShell.Hardware; using MainShell.Log; using MainShell.Models; using MainShell.ParaSetting.Model; using MwFramework.Device; using MwFramework.Device.Drivers; using MwFramework.Device.Motion; using Stylet; using System; using System.Collections.ObjectModel; using System.Linq; using System.Windows; namespace MainShell.ParaSetting.ViewModel { public class AxisSoftLimitSettingViewModel : BaseScreen { private const string AxisSoftLimitSettingFileName = "AxisSoftLimitSetting.json"; private readonly HardwareManager _hardwareManager; private readonly string _axisSoftLimitSettingFilePath; private AxisSoftLimitSetting _axisSoftLimitSetting; private ObservableCollection _axisSoftLimitItems = new ObservableCollection(); public ObservableCollection AxisSoftLimitItems { get { return _axisSoftLimitItems; } set { SetAndNotify(ref _axisSoftLimitItems, value); } } private AxisSoftLimitItemViewModel _selectedAxisSoftLimitItem; public AxisSoftLimitItemViewModel SelectedAxisSoftLimitItem { get { return _selectedAxisSoftLimitItem; } set { SetAndNotify(ref _selectedAxisSoftLimitItem, value); } } private string _parameterFilePath; public string ParameterFilePath { get { return _parameterFilePath; } set { SetAndNotify(ref _parameterFilePath, value); } } public AxisSoftLimitSettingViewModel(HardwareManager hardwareManager) { _hardwareManager = hardwareManager ?? throw new ArgumentNullException(nameof(hardwareManager)); _axisSoftLimitSettingFilePath = System.IO.Path.Combine(Paths.CalibSettingPath, AxisSoftLimitSettingFileName); ParameterFilePath = _axisSoftLimitSettingFilePath; } protected override void OnViewLoaded() { base.OnViewLoaded(); LoadAxisSoftLimitItems(); } public void BtnSave() { if (!ValidateAxisSoftLimitItems()) { return; } MessageBoxResult confirmResult = LocalizedMessageBox.Show(MessageKey.AxisSoftLimitSaveConfirm, MessageKey.TitleConfirm, MessageBoxButton.OKCancel, MessageBoxImage.Question); if (confirmResult != MessageBoxResult.OK) { return; } try { System.IO.Directory.CreateDirectory(Paths.CalibSettingPath); AxisSoftLimitSetting axisSoftLimitSetting = CreateAxisSoftLimitSetting(); foreach (AxisSoftLimitItemViewModel axisSoftLimitItem in AxisSoftLimitItems) { AxisSoftLimitItem axisSoftLimitItemModel = new AxisSoftLimitItem(); axisSoftLimitItemModel.AxisName = axisSoftLimitItem.AxisName; axisSoftLimitItemModel.CardName = axisSoftLimitItem.CardName; axisSoftLimitItemModel.CardNum = axisSoftLimitItem.CardNum; axisSoftLimitItemModel.AxisNum = axisSoftLimitItem.AxisNum; axisSoftLimitItemModel.NegativeSoftLimit = axisSoftLimitItem.NegativeSoftLimit; axisSoftLimitItemModel.PositiveSoftLimit = axisSoftLimitItem.PositiveSoftLimit; axisSoftLimitSetting.AxisSoftLimitItems.Add(axisSoftLimitItemModel); UpdateAxisCheckLimit(axisSoftLimitItem); } axisSoftLimitSetting.Write(_axisSoftLimitSettingFilePath); _axisSoftLimitSetting = axisSoftLimitSetting; LocalizedMessageBox.Show(MessageKey.CommonSaveSucceeded, MessageKey.TitleInfo); } catch (Exception ex) { LogManager.LogSysError(ex); LocalizedMessageBox.ShowFormat(MessageKey.AxisSoftLimitSaveFailedWithReason, MessageKey.TitleError, MessageBoxButton.OK, MessageBoxImage.Error, ex.Message); } } public void BtnApply() { if (!ValidateAxisSoftLimitItems()) { return; } AxisSoftLimitItemViewModel axisSoftLimitItem = SelectedAxisSoftLimitItem; if (axisSoftLimitItem == null) { LocalizedMessageBox.Show(MessageKey.AxisSoftLimitSelectedAxisRequired, MessageKey.TitleError); return; } try { ApplyAxisSoftLimitToController(axisSoftLimitItem); LocalizedMessageBox.ShowFormat(MessageKey.AxisSoftLimitApplySucceeded, MessageKey.TitleInfo, MessageBoxButton.OK, MessageBoxImage.Information, axisSoftLimitItem.AxisName); } catch (Exception ex) { LogManager.LogSysError(ex); LocalizedMessageBox.ShowFormat(MessageKey.AxisSoftLimitApplyFailedWithReason, MessageKey.TitleError, MessageBoxButton.OK, MessageBoxImage.Error, axisSoftLimitItem.AxisName, ex.Message); } } public void BtnApplyAll() { if (!ValidateAxisSoftLimitItems()) { return; } if (AxisSoftLimitItems == null || AxisSoftLimitItems.Count == 0) { LocalizedMessageBox.Show(MessageKey.AxisSoftLimitNoAxisData, MessageKey.TitleError); return; } try { int appliedAxisCount = 0; foreach (AxisSoftLimitItemViewModel axisSoftLimitItem in AxisSoftLimitItems) { ApplyAxisSoftLimitToController(axisSoftLimitItem); appliedAxisCount++; } LocalizedMessageBox.ShowFormat(MessageKey.AxisSoftLimitApplyAllSucceeded, MessageKey.TitleInfo, MessageBoxButton.OK, MessageBoxImage.Information, appliedAxisCount); } catch (Exception ex) { LogManager.LogSysError(ex); LocalizedMessageBox.ShowFormat(MessageKey.AxisSoftLimitApplyAllFailedWithReason, MessageKey.TitleError, MessageBoxButton.OK, MessageBoxImage.Error, ex.Message); } } private void LoadAxisSoftLimitItems() { try { AxisSoftLimitSetting axisSoftLimitSetting = CreateAxisSoftLimitSetting(); if (System.IO.File.Exists(_axisSoftLimitSettingFilePath)) { axisSoftLimitSetting.Read(_axisSoftLimitSettingFilePath); } _axisSoftLimitSetting = axisSoftLimitSetting; AxisSoftLimitItems = BuildAxisSoftLimitItems(axisSoftLimitSetting); SelectedAxisSoftLimitItem = AxisSoftLimitItems.FirstOrDefault(); } catch (Exception ex) { LogManager.LogSysError(ex); _axisSoftLimitSetting = CreateAxisSoftLimitSetting(); AxisSoftLimitItems = BuildAxisSoftLimitItems(_axisSoftLimitSetting); SelectedAxisSoftLimitItem = AxisSoftLimitItems.FirstOrDefault(); LocalizedMessageBox.ShowFormat(MessageKey.AxisSoftLimitLoadFailedWithReason, MessageKey.TitleError, MessageBoxButton.OK, MessageBoxImage.Error, ex.Message); } } private ObservableCollection BuildAxisSoftLimitItems(AxisSoftLimitSetting axisSoftLimitSetting) { ObservableCollection items = new ObservableCollection(); System.Collections.Generic.IEnumerable> axisPairs = Enumerable.Empty>(); if (_hardwareManager.AxesDic != null) { axisPairs = _hardwareManager.AxesDic.OrderBy(item => item.Key); } foreach (System.Collections.Generic.KeyValuePair axisPair in axisPairs) { IAxis axis = axisPair.Value; if (axis == null) { continue; } AxisCardParaPO axisCardParaPo = axis.AxisPO as AxisCardParaPO; int cardNum = axisCardParaPo != null ? axisCardParaPo.AxisCardNum : -1; string cardName = axisCardParaPo != null ? axisCardParaPo.AxisCardName : string.Empty; AxisSoftLimitItem axisSoftLimitItem = FindAxisSoftLimitItem(axisSoftLimitSetting, cardNum, axis.AxisIndex); double negativeSoftLimit = axisSoftLimitItem != null ? axisSoftLimitItem.NegativeSoftLimit : 0d; double positiveSoftLimit = axisSoftLimitItem != null ? axisSoftLimitItem.PositiveSoftLimit : axisCardParaPo != null ? axisCardParaPo.MaxCheckPos : 0d; AxisSoftLimitItemViewModel item = new AxisSoftLimitItemViewModel(axis, axisPair.Key, cardName, cardNum, axis.AxisIndex, negativeSoftLimit, positiveSoftLimit); items.Add(item); } return items; } private static AxisSoftLimitItem FindAxisSoftLimitItem(AxisSoftLimitSetting axisSoftLimitSetting, int cardNum, int axisNum) { if (axisSoftLimitSetting == null || axisSoftLimitSetting.AxisSoftLimitItems == null) { return null; } return axisSoftLimitSetting.AxisSoftLimitItems.FirstOrDefault(item => item != null && item.CardNum == cardNum && item.AxisNum == axisNum); } private static void UpdateAxisCheckLimit(AxisSoftLimitItemViewModel axisSoftLimitItem) { AxisCardParaPO axisCardParaPo = axisSoftLimitItem.Axis == null ? null : axisSoftLimitItem.Axis.AxisPO as AxisCardParaPO; if (axisCardParaPo != null) { axisCardParaPo.MaxCheckPos = axisSoftLimitItem.PositiveSoftLimit; } } private static void ApplyAxisSoftLimitToController(AxisSoftLimitItemViewModel axisSoftLimitItem) { if (axisSoftLimitItem == null) { throw new ArgumentNullException(nameof(axisSoftLimitItem)); } IAxis axis = axisSoftLimitItem.Axis; if (axis == null) { throw new InvalidOperationException("当前轴对象无效,无法下发软限位设置。"); } IAxisFunc axisFunc = axis as IAxisFunc; if (axisFunc == null) { throw new InvalidOperationException($"轴 {axisSoftLimitItem.AxisName} 不支持软限位设置接口。"); } IMotionController controller = axis.Parent; if (controller == null || !controller.IsOpen) { throw new InvalidOperationException($"轴 {axisSoftLimitItem.AxisName} 所属控制器未连接或未打开。"); } EnsureMotionCommandSucceeded(axisFunc.SetSoftMel(axisSoftLimitItem.NegativeSoftLimit), axisSoftLimitItem.AxisName, "负软限位"); EnsureMotionCommandSucceeded(axisFunc.SetSoftPel(axisSoftLimitItem.PositiveSoftLimit), axisSoftLimitItem.AxisName, "正软限位"); EnsureMotionCommandSucceeded(axisFunc.IssueParam(), axisSoftLimitItem.AxisName, "参数下发"); UpdateAxisCheckLimit(axisSoftLimitItem); } private static void EnsureMotionCommandSucceeded(MotionErrorCode motionErrorCode, string axisName, string actionName) { if (motionErrorCode != MotionErrorCode.NoError) { throw new InvalidOperationException($"轴 {axisName} {actionName}失败,错误码:{motionErrorCode}"); } } private bool ValidateAxisSoftLimitItems() { foreach (AxisSoftLimitItemViewModel axisSoftLimitItem in AxisSoftLimitItems) { if (axisSoftLimitItem.PositiveSoftLimit < axisSoftLimitItem.NegativeSoftLimit) { LocalizedMessageBox.ShowFormat(MessageKey.AxisSoftLimitRangeInvalid, MessageKey.TitleError, MessageBoxButton.OK, MessageBoxImage.Error, axisSoftLimitItem.AxisName); SelectedAxisSoftLimitItem = axisSoftLimitItem; return false; } } return true; } private static AxisSoftLimitSetting CreateAxisSoftLimitSetting() { return new AxisSoftLimitSetting(); } } public class AxisSoftLimitItemViewModel : PropertyChangedBase { private double _negativeSoftLimit; private double _positiveSoftLimit; public AxisSoftLimitItemViewModel(IAxis axis, string axisName, string cardName, int cardNum, int axisNum, double negativeSoftLimit, double positiveSoftLimit) { Axis = axis; AxisName = axisName; CardName = cardName; CardNum = cardNum; AxisNum = axisNum; _negativeSoftLimit = negativeSoftLimit; _positiveSoftLimit = positiveSoftLimit; } public IAxis Axis { get; private set; } public string AxisName { get; private set; } public string CardName { get; private set; } public int CardNum { get; private set; } public int AxisNum { get; private set; } public double NegativeSoftLimit { get { return _negativeSoftLimit; } set { SetAndNotify(ref _negativeSoftLimit, value); } } public double PositiveSoftLimit { get { return _positiveSoftLimit; } set { SetAndNotify(ref _positiveSoftLimit, value); } } } }