//using Modbus.Device;
using ModbusDemo.Model;
using ModbusDemo.Uitls;
using Prism.Commands;
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
{
public class AttachUCViewModel : BindableBase
{
private SerialPort _serialPort;
public DelegateCommand ReadOddRegisterCmm { get; set; }
//读取的结果
private string _readResult;
public string ReadResult
{
get { return _readResult; }
set
{
_readResult = value;
RaisePropertyChanged();
}
}
//显示操作的时间
private int _time;
public int Time
{
get { return _time; }
set
{
_time = value;
RaisePropertyChanged();
}
}
public AttachUCViewModel()
{
}
public AttachUCViewModel(SerialPort serialPort)
{
//ReadOddRegisterCmm = new DelegateCommand(ReadOddRegister);
_serialPort = serialPort;
}
///
/// 读1000个寄存器
///
//private void ReadOddRegister()
//{
// // 创建 Modbus RTU 主站
// IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(_serialPort);
// byte slaveId = 1;
// ushort totalRegisters = 1000;
// ushort chunkSize = 100;
// int numChunks = (int)Math.Ceiling((double)totalRegisters / chunkSize);
// ushort[] allRegisters = new ushort[totalRegisters];
// Task[] tasks = new Task[numChunks];
// DateTime startTime = DateTime.Now;
// for (int i = 0; i < numChunks; i++)
// {
// ushort startAddress = (ushort)(10300 + i * chunkSize);
// ushort currentChunkSize = 100;
// int chunkIndex = i;
// tasks[i] = Task.Run(() =>
// {
// try
// {
// ushort[] registers = master.ReadHoldingRegisters(slaveId, startAddress, currentChunkSize);
// Array.Copy(registers, 0, allRegisters, chunkIndex * chunkSize, currentChunkSize);
// }
// catch (Exception ex)
// {
// MessageBox.Show($"线程 {chunkIndex} 读取寄存器时出错: {ex.Message}");
// }
// });
// }
// // 等待所有任务完成
// Task.WaitAll(tasks);
// Time = (int)(DateTime.Now - startTime).TotalMilliseconds;
// StringBuilder result = new StringBuilder();
// int count = 0;
// for (int i = 1; i < totalRegisters; i += 2)
// {
// result.Append(allRegisters[i].ToString() + " ");
// count++;
// if (count % 50 == 0)
// {
// result.AppendLine();
// }
// }
// ReadResult = result.ToString();
//}
///
/// 自己的类
///
private void ReadOddRegister2()
{
byte slaveId = 1;
ushort totalRegisters = 1000;
ushort chunkSize = 100;
int numChunks = (int)Math.Ceiling((double)totalRegisters / chunkSize);
ushort[] allRegisters = new ushort[totalRegisters];
Task[] tasks = new Task[numChunks];
DateTime startTime = DateTime.Now;
for (int i = 0; i < numChunks; i++)
{
ushort startAddress = (ushort)(10300 + i * chunkSize);
ushort currentChunkSize = 100;
int chunkIndex = i;
ushort[] registers = ReadRegisters(slaveId, startAddress, currentChunkSize);
Array.Copy(registers, 0, allRegisters, chunkIndex * chunkSize, currentChunkSize);
}
// 等待所有任务完成
Time = (int)(DateTime.Now - startTime).TotalMilliseconds;
StringBuilder result = new StringBuilder();
int count = 0;
for (int i = 1; i < totalRegisters; i += 2)
{
result.Append(allRegisters[i].ToString() + " ");
count++;
if (count % 50 == 0)
{
result.AppendLine();
}
}
ReadResult = result.ToString();
}
public ushort[] ReadRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints)
{
ushort[] resultValue = null;
if (!_serialPort.IsOpen)
{
MessageBox.Show("串口没有链接,请先链接");
return resultValue;
}
var sendByteList = new List(8)
{
slaveAddress, // 从站地址
0x03, // 功能码:读保持寄存器
};
// 添加起始地址(高字节在前)
sendByteList.AddRange(BitConverter.GetBytes(startAddress).Reverse());
// 添加读取点数(高字节在前)
sendByteList.AddRange(BitConverter.GetBytes(numberOfPoints).Reverse());
//获取CRC校验码
byte[] getCRC = sendByteList.ToArray();
byte[] resultCRC = CRCUitl.CalculateCRC(getCRC, getCRC.Length);
sendByteList.Add(resultCRC[0]);
sendByteList.Add(resultCRC[1]);
byte[] sendByte = sendByteList.ToArray();
int maxRetries = 3; // 最大重试次数
int attempt = 0;
List responseData = new List();
byte[] response = null;
while (attempt < maxRetries)
{
// 每次重试前清空缓冲区
responseData.Clear();
// 清除输入缓冲区残留数据
_serialPort.DiscardInBuffer();
try
{
_serialPort.Write(sendByte, 0, sendByte.Length);
//使用时间去轮询查询数据
DateTime startTime = DateTime.Now;
while ((DateTime.Now - startTime).TotalMilliseconds < _serialPort.ReadTimeout)
{
int bytesToRead = _serialPort.BytesToRead;
if (bytesToRead > 0)
{
byte[] buffer = new byte[bytesToRead];
int bytesRead = _serialPort.Read(buffer, 0, bytesToRead);
responseData.AddRange(buffer.Take(bytesRead));
}
//延迟20毫秒,节约cpu资源
Thread.Sleep(20);
}
response = responseData.ToArray();
if (response.Length == 0)
{
continue;
}
resultValue = ParseRegistersresponse(sendByte, response, numberOfPoints);
return resultValue;
}
catch (Exception)
{
}
finally
{
attempt++;
}
}
return resultValue;
}
///
/// 解析读取到的操作
///
///
///
///
///
public ushort[] ParseRegistersresponse(byte[] sendByte, byte[] response, ushort numberOfPoints)
{
//判断发送回来的数据是否正确
if (CheckData.CheckResponse(response))
{
ushort[] registers = new ushort[numberOfPoints];
for (int i = 0; i < numberOfPoints; i++)
{
int pos = 3 + i * 2;
// 大端序转换 (高位在前)
registers[i] = (ushort)((response[pos] << 8) | response[pos + 1]);
}
return registers;
}
else
{
return null;
}
}
}
}