2026-06-05 13:44:39 +09:00

219 lines
8.8 KiB
C#

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<string> _MotorIDList;
public List<string> 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<string> { "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;
}
}
}