using log4net; using Plugin.DeviceDebug.Entity; using System; using System.Collections.ObjectModel; using System.Windows; using System.Windows.Controls; namespace Plugin.DeviceDebug.Panels { /// /// IO 点位状态显示模型 /// public class IoPointStatus { public string Address { get; set; } public bool Value { get; set; } public DateTime LastUpdate { get; set; } } /// /// 互锁状态显示模型 /// public class InterlockStatus { public string Name { get; set; } public string Status { get; set; } // "满足" / "不满足" } /// /// PlcDebugPanel.xaml 的交互逻辑 /// public partial class PlcDebugPanel : UserControl { private static readonly ILog log = LogManager.GetLogger(typeof(PlcDebugPanel)); /// /// 是否为维护模式(控制输入可用性) /// public static readonly DependencyProperty IsMaintenanceModeProperty = DependencyProperty.Register(nameof(IsMaintenanceMode), typeof(bool), typeof(PlcDebugPanel), new PropertyMetadata(false)); public bool IsMaintenanceMode { get => (bool)GetValue(IsMaintenanceModeProperty); set => SetValue(IsMaintenanceModeProperty, value); } /// /// 命令执行事件 /// public event EventHandler OnCommandExecute; /// /// IO 点位状态列表 /// public ObservableCollection IoStatuses { get; } = new(); /// /// 互锁状态列表 /// public ObservableCollection Interlocks { get; } = new(); public PlcDebugPanel() { InitializeComponent(); ioStatusList.ItemsSource = IoStatuses; interlockList.ItemsSource = Interlocks; // 初始化示例数据 InitSampleData(); } /// /// 初始化示例数据(实际应从 PLC 读取) /// private void InitSampleData() { try { // 添加示例 IO 点位 IoStatuses.Add(new IoPointStatus { Address = "M0.0", Value = false, LastUpdate = DateTime.Now }); IoStatuses.Add(new IoPointStatus { Address = "M0.1", Value = true, LastUpdate = DateTime.Now }); IoStatuses.Add(new IoPointStatus { Address = "M0.2", Value = false, LastUpdate = DateTime.Now }); IoStatuses.Add(new IoPointStatus { Address = "I0.0", Value = true, LastUpdate = DateTime.Now }); IoStatuses.Add(new IoPointStatus { Address = "Q0.0", Value = false, LastUpdate = DateTime.Now }); // 添加示例互锁 Interlocks.Add(new InterlockStatus { Name = "安全门关闭", Status = "满足" }); Interlocks.Add(new InterlockStatus { Name = "急停未触发", Status = "满足" }); Interlocks.Add(new InterlockStatus { Name = "气压正常", Status = "不满足" }); Interlocks.Add(new InterlockStatus { Name = "温度正常", Status = "满足" }); } catch (Exception ex) { log.Error("初始化示例数据失败", ex); } } /// /// 更新 IO 点位状态 /// public void UpdateIoStatus(string address, bool value) { try { var existing = IoStatuses.FirstOrDefault(s => s.Address == address); if (existing != null) { existing.Value = value; existing.LastUpdate = DateTime.Now; } else { IoStatuses.Add(new IoPointStatus { Address = address, Value = value, LastUpdate = DateTime.Now }); } } catch (Exception ex) { log.Error($"更新 IO 状态失败: {address}", ex); } } /// /// 更新互锁状态 /// public void UpdateInterlock(string name, bool satisfied) { try { var existing = Interlocks.FirstOrDefault(i => i.Name == name); if (existing != null) { existing.Status = satisfied ? "满足" : "不满足"; } else { Interlocks.Add(new InterlockStatus { Name = name, Status = satisfied ? "满足" : "不满足" }); } } catch (Exception ex) { log.Error($"更新互锁状态失败: {name}", ex); } } private void WriteBtn_Click(object sender, RoutedEventArgs e) { try { if (!IsMaintenanceMode) { MessageBox.Show("当前为只读模式,无法执行写入操作", "提示", MessageBoxButton.OK, MessageBoxImage.Warning); return; } string address = addressInput.Text.Trim(); if (string.IsNullOrEmpty(address)) { MessageBox.Show("请输入 IO 地址", "错误", MessageBoxButton.OK, MessageBoxImage.Error); return; } bool value = (valueSelect.SelectedItem as ComboBoxItem)?.Content?.ToString() == "True"; // 创建命令 var command = new PlcWriteCommand { IoAddress = address, Value = value }; // 触发命令执行事件 OnCommandExecute?.Invoke(this, command); // 更新本地显示 UpdateIoStatus(address, value); log.Info($"写入 PLC IO: {address} = {value}"); } catch (Exception ex) { log.Error("写入 PLC IO 失败", ex); MessageBox.Show($"写入失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); } } } }