using ModbusDemo.Device; using ModbusDemo.Event; using ModbusDemo.Model; using Prism.Commands; using Prism.Events; using Prism.Mvvm; using System; using System.Collections.Generic; using System.IO.Ports; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; namespace ModbusDemo.VIewModel { /// /// 这是CoilUC的VM用来支持数据绑定 /// public class CoilUCViewModel : BindableBase { //事件聚合器 private readonly IEventAggregator _eventAggregator; //定义数据库操作 private ModbusDbContext _modbusDbContext; //获取读线圈的类 private IModbusRTU _modbusRTU; //定义读线圈的命令 public DelegateCommand ReadCoilCmm { get; set; } //定义写线圈操作 public DelegateCommand WriteCoilCmm { get; set; } //获取当前使用的串口 private SerialPort _serialPort; //显示当前链接串口的信息 //按钮是否可以点击 private bool _isEnable; public bool IsEnable { get { return _isEnable; } set { _isEnable = value; RaisePropertyChanged(); } } public string SerialPortInfo { get { return "当前为读写线圈:" + "串口号:" + _serialPort.PortName + ",波特率:" + _serialPort.BaudRate + ",数据位:" + _serialPort.DataBits + ",校验位:" + _serialPort.Parity + ",停止位:" + _serialPort.StopBits; } } #region 读取定义 //读取的从站id private string _slaveAddress; public string SlaveAddress { get { return _slaveAddress; } set { _slaveAddress = value; RaisePropertyChanged(); } } //读取的起始地址 private string _startAddress; public string StartAddress { get { return _startAddress; } set { _startAddress = value; RaisePropertyChanged(); } } //读取的位数 private string _numberOfPoints; public string NumberOfPoints { get { return _numberOfPoints; } set { _numberOfPoints = value; RaisePropertyChanged(); } } private string _readResult; //读取的结果 public string ReadResult { get { return _readResult; } set { _readResult = value; RaisePropertyChanged(); } } #endregion #region 写入定义 //写入的从站id private string _writeslaveAddress; public string WriteSlaveAddress { get { return _writeslaveAddress; } set { _writeslaveAddress = value; RaisePropertyChanged(); } } //写入的起始地址 private string _writestartAddress; public string WriteStartAddress { get { return _writestartAddress; } set { _writestartAddress = value; RaisePropertyChanged(); } } //写入的数据 private string _writeData; public string WriteData { get { return _writeData; } set { _writeData = value; } } #endregion private List _modbusLogList; public List ModbusLogList { get { return _modbusLogList; } set { _modbusLogList = value; RaisePropertyChanged(); } } public CoilUCViewModel() { } public CoilUCViewModel(SerialPort serialPort, ModbusRTU modbusRTU, ModbusDbContext modbusDbContext, IEventAggregator eventAggregator) { _serialPort = serialPort; ReadCoilCmm = new DelegateCommand(ReadCoil); _modbusRTU = modbusRTU; WriteCoilCmm = new DelegateCommand(WriteCoil); _modbusDbContext = modbusDbContext; _eventAggregator = eventAggregator; // 订阅事件(使用弱引用,避免内存泄漏) _eventAggregator.GetEvent().Subscribe( OnSerialPortSettingsChanged, ThreadOption.UIThread, // 在UI线程执行回调 false);// 不使用强引用 //初始化查询操作 ModbusLogList = GetOperateCoil(); IsEnable = true; } // 事件回调方法:当串口设置变更时触发 private void OnSerialPortSettingsChanged() { // 强制刷新SerialPortInfo属性,触发UI更新 RaisePropertyChanged(nameof(SerialPortInfo)); } /// /// 线圈读取操作 /// private void ReadCoil() { //将按钮设置为不可点击状态,并解析用户输入的信息 IsEnable = false; if (!byte.TryParse(SlaveAddress, out byte slaveAddressValue)) { MessageBox.Show("SlaveAddress 格式无效", "warning", MessageBoxButton.OK, MessageBoxImage.Warning); IsEnable = true; return; } if (!ushort.TryParse(StartAddress, out ushort startAddressValue)) { MessageBox.Show("StartAddress 格式无效", "warning", MessageBoxButton.OK, MessageBoxImage.Warning); IsEnable = true; return; } if (!ushort.TryParse(NumberOfPoints, out ushort numberOfPointsValue)) { MessageBox.Show("NumberOfPoints 格式无效", "warning", MessageBoxButton.OK, MessageBoxImage.Warning); IsEnable = true; return; } //使用子线程,防止ui线程卡顿 Task.Run(() => { bool[] result = _modbusRTU.ReadCoil(slaveAddressValue, startAddressValue, numberOfPointsValue); if (result == null) { MessageBox.Show("读取失败", "error", MessageBoxButton.OK, MessageBoxImage.Error); ModbusLogList = GetOperateCoil(); IsEnable = true; return; } string temp = ""; int count = 0; foreach (var item in result) { count++; temp += item; temp += " "; if(count %25 == 0) { temp += "\n"; } } ReadResult = temp; MessageBox.Show("读取成功"); IsEnable = true; ModbusLogList = GetOperateCoil(); }); } private void WriteCoil() { //将按钮设置为不可点击状态,并解析用户输入的信息 IsEnable = false; if (!byte.TryParse(WriteSlaveAddress, out byte writeSlaveAddressValue)) { MessageBox.Show("WriteSlaveAddress 格式无效", "warning", MessageBoxButton.OK, MessageBoxImage.Warning); IsEnable = true; return; } if (!ushort.TryParse(WriteStartAddress, out ushort WriteStartAddressValue)) { MessageBox.Show("WriteStartAddress 格式无效", "warning", MessageBoxButton.OK, MessageBoxImage.Warning); IsEnable = true; return; } if (string.IsNullOrEmpty(WriteData)) { MessageBox.Show("WriteData 格式无效", "warning", MessageBoxButton.OK, MessageBoxImage.Warning); IsEnable = true; return; } //去除字符串中的空格 WriteData = WriteData.Replace(" ", ""); //转换为布尔数组 bool[] data = WriteData.Select(m => m == '1').ToArray(); //使用子线程执行,避免ui线程卡顿 Task.Run(() => { _modbusRTU.WriteCoil(writeSlaveAddressValue, WriteStartAddressValue, data); ModbusLogList = GetOperateCoil(); ModbusLog modbusLog = ModbusLogList.FirstOrDefault(); if (modbusLog != null && modbusLog.ResponseData != string.Empty && modbusLog.ResponseData[3] !='8') { MessageBox.Show("写入成功"); IsEnable = true; } else { MessageBox.Show("写入失败", "error", MessageBoxButton.OK, MessageBoxImage.Error); IsEnable = true; } }); } /// /// 获取展示数据 /// /// private List GetOperateCoil() { return _modbusDbContext.ModbusLog .Where(log => log.OperationType == "读线圈" || log.OperationType == "写线圈") .OrderByDescending(log => log.Time) // 按时间倒序,最新的在前 .Take(20) // 只取前20条记录 .ToList(); // 执行查询 } } }