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);
}
}
}
}