using Aurora; using Aurora.Api.Devices; using Aurora.Api.Manager; using Aurora.View; using System; using System.Collections.Generic; using System.Windows; using System.Windows.Input; using System.Windows.Threading; namespace WeldingCommon.Views { internal class UCSingleAxisStatusViewModel : NotifyPropertyChangedBase { private readonly IDeviceManager DeviceManager; private readonly DispatcherTimer MonitorTimer; #region Binding Properties private List _MotorIDList; public List MotorIDList { get => _MotorIDList; set => SetProperty(ref _MotorIDList, value); } private string _SelectedMotorID; public string SelectedMotorID { get => _SelectedMotorID; set => SetProperty(ref _SelectedMotorID, value); } // TODO: 아래 strMotorServoOnOffStatus 와 하나로 합치자. 이 부분은 background 색상 변경에 사용됨 private bool _bMotorServoOnOffStatus; public bool bMotorServoOnOffStatus { get => _bMotorServoOnOffStatus; set => SetProperty(ref _bMotorServoOnOffStatus, value); } private string _strMotorServoOnOffStatus; public string strMotorServoOnOffStatus { get => _strMotorServoOnOffStatus; set => SetProperty(ref _strMotorServoOnOffStatus, value); } private bool _MotorAlarmStatus; public bool MotorAlarmStatus { get => _MotorAlarmStatus; set => SetProperty(ref _MotorAlarmStatus, value); } private bool _MotorInMotion; public bool MotorInMotion { get => _MotorInMotion; set => SetProperty(ref _MotorInMotion, value); } private bool _MotorInPosition; public bool MotorInPosition { get => _MotorInPosition; set => SetProperty(ref _MotorInPosition, value); } private bool _MotorHomeStatus; public bool MotorHomeStatus { get => _MotorHomeStatus; set => SetProperty(ref _MotorHomeStatus, value); } private bool _MotorPlusLimitStatus; public bool MotorPlusLimitStatus { get => _MotorPlusLimitStatus; set => SetProperty(ref _MotorPlusLimitStatus, value); } private bool _MotorMinusLimitStatus; public bool MotorMinusLimitStatus { get => _MotorMinusLimitStatus; set => SetProperty(ref _MotorMinusLimitStatus, value); } private bool _MotorEmergencyStop; public bool MotorEmergencyStop { get => _MotorEmergencyStop; set => SetProperty(ref _MotorEmergencyStop, value); } private string _AlarmCode; public string AlarmCode { get => _AlarmCode; set => SetProperty(ref _AlarmCode, value); } private double _TargetPos; public double TargetPos { get => _TargetPos; set => SetProperty(ref _TargetPos, value); } private double _ActualPos; public double ActualPos { get => _ActualPos; set => SetProperty(ref _ActualPos, value); } private double _PosError; public double PosError { get => _PosError; set => SetProperty(ref _PosError, value); } private double _Velocity; public double Velocity { get => _Velocity; set => SetProperty(ref _Velocity, value); } #endregion #region EventCommands public ICommand CMD_VisibleChanged { get; } public ICommand CMD_INCCOMBOMOTORID { get; } public ICommand CMD_DECCOMBOMOTORID { get; } public ICommand CMD_ServoOnOff { get; } public ICommand CMD_ResetAlarm { get; } #endregion public UCSingleAxisStatusViewModel(IAuroraEnvironment aurora) { DeviceManager = aurora.DeviceManager; #region Initialize Binding Properties // Motor ID 를 List 에 넣기. devicemanager 에서 motor ID 를 받아오자. // motor 가 define 되지 않았으니 테스트를 위해 임시로 몇개 넣어둔다. MotorIDList = new List { "Welding Y1", "Welding Z" }; SelectedMotorID = MotorIDList[0]; strMotorServoOnOffStatus = "Servo Off"; #endregion #region DelegateCommands CMD_VisibleChanged = new DelegateCommand(VisibleChanged); CMD_INCCOMBOMOTORID = new DelegateCommand(IncreaseComboMotorID); CMD_DECCOMBOMOTORID = new DelegateCommand(DecreaseComboMotorID); CMD_ServoOnOff = new DelegateCommand(MotorServoOnOff); CMD_ResetAlarm = new DelegateCommand(MotorResetAlarm); #endregion MonitorTimer = new DispatcherTimer(); MonitorTimer.Tick += OnMonitoring; MonitorTimer.Interval = TimeSpan.FromMilliseconds(100); } private void OnMonitoring(object sender, EventArgs e) { try { var motor = GetComboSelectedBaseMotor(); if (motor != null) { if (motor.IsServoOn()) { bMotorServoOnOffStatus = true; strMotorServoOnOffStatus = "Servo Off"; } else { bMotorServoOnOffStatus = false; strMotorServoOnOffStatus = "Servo On"; } if (motor.IsAlarm()) { MotorAlarmStatus = true; AlarmCode = motor.GetLastAlarm().ToString(); } else { MotorAlarmStatus = false; AlarmCode = "No Alarm"; } if (motor.IsMoving()) MotorInMotion = true; else MotorInMotion = false; // inposition bit 를 받아오는 함수가 없다. current 와 target 을 비교하는 것으로 하기에는 위험성이 있다. 일단 만들어는 두자. // motor position 정보를 받아오는 함수를 따로 만드는게 맞지만, 이 view 에서 쓰는 코드를 재활용할일이 없으므로 IsMotorInPositiong 함수안에서 다한다. if (IsMotorInPosition(motor)) MotorInPosition = true; else MotorInPosition = false; if (motor.IsHomeCompleted()) MotorHomeStatus = true; else MotorHomeStatus = false; // plus limit 함수없음. ACS 모터는 IsHPLimit() 함수가 있음. // minus limit 함수없음. ACS 모터는 IsHNLimit() 함수가 있음. // EMG 함수 없음 MotorPlusLimitStatus = false; MotorMinusLimitStatus = false; MotorEmergencyStop = false; Velocity = motor.GetVelocity(); } AlarmCode = "No Alarm"; } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void IncreaseComboMotorID(object obj) { try { int nIndex = MotorIDList.IndexOf(SelectedMotorID); if (nIndex >= MotorIDList.Count - 1) nIndex = MotorIDList.Count; else nIndex++; SelectedMotorID = MotorIDList[nIndex]; } catch { } } private void DecreaseComboMotorID(object obj) { try { int nIndex = MotorIDList.IndexOf(SelectedMotorID); if (nIndex < 1) nIndex = 0; else nIndex--; SelectedMotorID = MotorIDList[nIndex]; } catch { } } private void MotorServoOnOff(object obj) { try { var motor = GetComboSelectedBaseMotor(); if (motor != null) { if (motor.IsServoOn()) motor.ServoOn(false); else motor.ServoOn(true); } } catch { } } private void MotorResetAlarm(object obj) { try { var motor = GetComboSelectedBaseMotor(); if (motor != null) { if (motor.IsAlarm()) motor.ClearAlarm(); } } catch { } } private void VisibleChanged(object obj) { bool visible = (bool)obj; if (visible) { MonitorTimer.Start(); } else { MonitorTimer.Stop(); } } private BaseMotor GetComboSelectedBaseMotor() { return DeviceManager[SelectedMotorID] as BaseMotor; } private bool IsMotorInPosition(string MotorID) { var motor = DeviceManager[MotorID] as BaseMotor; return IsMotorInPosition(motor); } private bool IsMotorInPosition(BaseMotor motor) { if (motor == null) return false; double dbInPositionRange = 0.001; ActualPos = motor.GetCurrentPosition(); TargetPos = motor.GetTargetPosition(); PosError = TargetPos - ActualPos; if (!motor.IsMoving() && (Math.Abs(PosError) < dbInPositionRange)) return true; return false; } } }