using System;
using System.ComponentModel;
using System.Threading.Tasks;
using Prism.Commands;
using Prism.Mvvm;
using TeamAAS_VP.Interfaces;
using TeamAAS_VP.Models;
namespace TeamAAS_VP.Core.Robots
{
///
/// Axis view-model for binding to View: provides Axis + / - commands, axis name and current position.
///
public class AxisViewModel : BindableBase, IDisposable
{
private readonly IRobot _robot;
private readonly string _axisName;
private double _currentPosition;
private double _step;
public DelegateCommand AxisPlusCommand { get; private set; }
public DelegateCommand AxisMinusCommand { get; private set; }
///
/// 轴名称(X/Y/Z/U)
///
public string AxisName => _axisName;
///
/// 当前轴位置(从 Robot 读取或命令后更新)
///
public double CurrentPosition
{
get => _currentPosition;
private set => SetProperty(ref _currentPosition, value);
}
///
/// 每次 jog 的步长(可设置)
///
public double Step
{
get => _step;
set
{
if (SetProperty(ref _step, value))
{
RaiseCanExecuteChanged();
}
}
}
public AxisViewModel(string axisName, IRobot robot, double step = 1.0)
{
if (string.IsNullOrWhiteSpace(axisName)) throw new ArgumentNullException(nameof(axisName));
_axisName = axisName.ToUpper();
_robot = robot ?? throw new ArgumentNullException(nameof(robot));
_step = step;
AxisPlusCommand = DelegateCommand.FromAsyncHandler(ExecutePlusAsync, CanExecuteCommands);
AxisMinusCommand = DelegateCommand.FromAsyncHandler(ExecuteMinusAsync, CanExecuteCommands);
// 尝试初始化当前位置(异步,不阻塞构造)
Task.Run(async () => await UpdatePositionFromRobotAsync());
// 订阅机器人属性变化以刷新命令可用性
if (_robot is INotifyPropertyChanged npc)
{
npc.PropertyChanged += Robot_PropertyChanged;
}
}
private void Robot_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
// 监听 CanExecute 或 IsConnected 等关键属性名(Robots 中使用 CanExecute 字段)
if (string.Equals(e.PropertyName, nameof(XYZU_Robot.CanExecute), StringComparison.OrdinalIgnoreCase) ||
string.Equals(e.PropertyName, nameof(IRobot.CanExecute), StringComparison.OrdinalIgnoreCase) ||
string.Equals(e.PropertyName, nameof(IRobot.IsConnected), StringComparison.OrdinalIgnoreCase))
{
RaiseCanExecuteChanged();
}
}
private bool CanExecuteCommands()
{
try
{
if (_robot == null) return false;
// 优先使用机器人公开的 CanExecute 属性(若存在),否则回退到 IsConnected
var canExecuteProp = _robot.GetType().GetProperty("CanExecute");
if (canExecuteProp != null && canExecuteProp.PropertyType == typeof(bool))
{
return (bool)canExecuteProp.GetValue(_robot);
}
return _robot.IsConnected;
}
catch
{
return false;
}
}
private void RaiseCanExecuteChanged()
{
AxisPlusCommand.RaiseCanExecuteChanged();
AxisMinusCommand.RaiseCanExecuteChanged();
}
private async Task ExecutePlusAsync()
{
if (!CanExecuteCommands()) return;
try
{
await _robot.JogAsync(_axisName, Step);
}
catch
{
// 忽略错误,视需求可扩展日志或通知
}
await UpdatePositionFromRobotAsync();
}
private async Task ExecuteMinusAsync()
{
if (!CanExecuteCommands()) return;
try
{
await _robot.JogAsync(_axisName, -Step);
}
catch
{
// 忽略错误
}
await UpdatePositionFromRobotAsync();
}
///
/// 从 Robot 读取完整位置并更新当前轴的 CurrentPosition
///
public async Task UpdatePositionFromRobotAsync()
{
try
{
var pos = await _robot.GetRobotPosAsync();
if (pos == null) return;
switch (_axisName)
{
case "X":
CurrentPosition = pos.X;
break;
case "Y":
CurrentPosition = pos.Y;
break;
case "Z":
CurrentPosition = pos.Z;
break;
case "U":
CurrentPosition = pos.U;
break;
default:
// 未知轴,保持不变
break;
}
}
catch
{
// 忽略读取错误
}
}
public void Dispose()
{
if (_robot is INotifyPropertyChanged npc)
{
npc.PropertyChanged -= Robot_PropertyChanged;
}
}
}
}