using System; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using TeamAAS.Global.Devices; namespace TeamAAS.Motion { /// /// 运动/IO 通用调试页面:轴状态表 + 定位/回零/使能/停止 + IO 输出点翻转。 /// 所有运动卡与 IO 卡(仿真/雷赛/固高/IMC60G/GR20T…)共用此页面(设备内核·统一调试页要求); /// 品牌特有调试能力可通过 IDeviceDebugPageFactory 提供专用页面替换本页。 /// public partial class MotionDebugView : UserControl { private IMotionCard _motion; private IIOCard _io; private readonly System.Windows.Threading.DispatcherTimer _refreshTimer; public MotionDebugView() { InitializeComponent(); _refreshTimer = new System.Windows.Threading.DispatcherTimer { Interval = TimeSpan.FromMilliseconds(300) }; _refreshTimer.Tick += (s, e) => RefreshStatus(); } /// 绑定设备(运动卡或 IO 卡,二选一或同时实现)。 public void Bind(object device) { _motion = device as IMotionCard; _io = device as IIOCard; TxtTitle.Text = (_motion as TeamAAS.Global.Devices.INamedDevice)?.Name ?? (_io as TeamAAS.Global.Devices.INamedDevice)?.Name ?? "运动/IO 调试"; if (_motion != null) { AxisGrid.ItemsSource = _motion.GetAllAxisStatus(); } else { AxisGrid.Visibility = Visibility.Collapsed; } BuildIoPanel(); _refreshTimer.Start(); RefreshStatus(); } private IMotionCard Motion => _motion; private IIOCard Io => _io; private void BuildIoPanel() { IoPanel.Children.Clear(); if (_io == null) { IoPanel.Visibility = Visibility.Collapsed; return; } IoPanel.Visibility = Visibility.Visible; for (int i = 0; i < _io.OutputCount; i++) { int index = i; var btn = new ToggleButton { Content = $"Y{index}", Width = 44, Margin = new Thickness(2), }; btn.Checked += (s, e) => _io.WriteOutput(index, true); btn.Unchecked += (s, e) => _io.WriteOutput(index, false); IoPanel.Children.Add(btn); } } private void RefreshStatus() { try { if (_motion != null && _motion.IsConnected) AxisGrid.ItemsSource = _motion.GetAllAxisStatus(); if (_io != null && _io.IsConnected) { var outs = _io.ReadAllOutputs(); var ins = _io.ReadAllInputs(); for (int i = 0; i < IoPanel.Children.Count && i < outs.Length; i++) { if (IoPanel.Children[i] is ToggleButton tb && tb.IsChecked != outs[i]) { _suppressIo = true; tb.IsChecked = outs[i]; _suppressIo = false; } } TxtStatus.Text = $"已连接 · 输入:{ToMask(ins)} 输出:{ToMask(outs)}"; } else { TxtStatus.Text = _motion != null && _motion.IsConnected ? "已连接" : "未连接"; } } catch { } } private bool _suppressIo; private static string ToMask(bool[] bits) => bits == null ? "" : new string(bits.Select(b => b ? '1' : '0').ToArray()); private bool TryGetAxis(out int axis, out double vel, out double pos) { axis = 0; vel = 100; pos = 0; if (_motion == null) return false; return int.TryParse(TxtAxis.Text, out axis) && double.TryParse(TxtVel.Text, out vel) && double.TryParse(TxtPos.Text, out pos); } private void BtnOpen_Click(object sender, RoutedEventArgs e) { try { bool ok = (_motion as IConnectableDevice)?.Open() ?? (_io as IConnectableDevice)?.Open() ?? false; TxtStatus.Text = ok ? "已连接" : "连接失败"; } catch (Exception ex) { TxtStatus.Text = "连接失败: " + ex.Message; } } private void BtnClose_Click(object sender, RoutedEventArgs e) { try { (_motion as IConnectableDevice)?.Close(); (_io as IConnectableDevice)?.Close(); } catch { } TxtStatus.Text = "未连接"; } private void BtnMoveAbs_Click(object sender, RoutedEventArgs e) { if (TryGetAxis(out var axis, out var vel, out var pos)) _motion?.MoveAbsolute(axis, pos, vel); } private void BtnEnable_Click(object sender, RoutedEventArgs e) { if (int.TryParse(TxtAxis.Text, out var axis)) _motion?.SetEnable(axis, true); } private void BtnHome_Click(object sender, RoutedEventArgs e) { if (int.TryParse(TxtAxis.Text, out var axis)) _motion?.Home(axis); } private void BtnStop_Click(object sender, RoutedEventArgs e) { _motion?.Stop(-1); } private void BtnRefresh_Click(object sender, RoutedEventArgs e) => RefreshStatus(); } /// /// 运动/IO 设备通用调试页工厂:注册到设备调试页体系后,所有运动卡/IO 卡自动获得调试页面。 /// public class MotionDebugPageFactory : TeamAAS.Global.Devices.IDeviceDebugPageFactory { public string DeviceCategory => "运动卡"; public object CreatePage(object device) { var view = new MotionDebugView(); view.Bind(device); return view; } } }