@@ -77,12 +77,7 @@ namespace ModbusDemo | |||||
//private SerialPort CreateSerialPort() | |||||
//{ | |||||
// SerialPort serialPort = new SerialPort(); | |||||
// return serialPort; | |||||
//} | |||||
} | } | ||||
} | } |
@@ -1,4 +1,5 @@ | |||||
using ModbusDemo.Model; | |||||
using DryIoc; | |||||
using ModbusDemo.Model; | |||||
using ModbusDemo.Uitls; | using ModbusDemo.Uitls; | ||||
using System; | using System; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
@@ -19,7 +20,7 @@ namespace ModbusDemo.Device | |||||
private ModbusDbContext _modbusDbContext; | private ModbusDbContext _modbusDbContext; | ||||
//TODO,修改 | //TODO,修改 | ||||
private SerialPortAdapter _portAdapter; | private SerialPortAdapter _portAdapter; | ||||
public ModbusRTU(SerialPort serialPort, ModbusDbContext modbusDbContext) | public ModbusRTU(SerialPort serialPort, ModbusDbContext modbusDbContext) | ||||
{ | { | ||||
_serialPort = serialPort; | _serialPort = serialPort; | ||||
@@ -42,17 +43,16 @@ namespace ModbusDemo.Device | |||||
MessageBox.Show("串口没有链接,请先链接"); | MessageBox.Show("串口没有链接,请先链接"); | ||||
return resultValue; | return resultValue; | ||||
} | } | ||||
List<byte> sendByteList = new List<byte>(); | |||||
//设置从站地址 | |||||
sendByteList.Add(slaveAddress); | |||||
//设置功能码 | |||||
sendByteList.Add(0x01); | |||||
List<byte> sendByteList = new List<byte> | |||||
{ | |||||
slaveAddress, // 从站地址 | |||||
0x01, // 功能码:读线圈 | |||||
}; | |||||
//设置起始地址的高位和低位 | //设置起始地址的高位和低位 | ||||
sendByteList.Add(BitConverter.GetBytes(startAddress)[1]); | |||||
sendByteList.Add(BitConverter.GetBytes(startAddress)[0]); | |||||
sendByteList.AddRange(BitConverter.GetBytes(startAddress).Reverse()); | |||||
//设置读取几个线圈的高位和低位 | //设置读取几个线圈的高位和低位 | ||||
sendByteList.Add(BitConverter.GetBytes(numberOfPoints)[1]); | |||||
sendByteList.Add(BitConverter.GetBytes(numberOfPoints)[0]); | |||||
sendByteList.AddRange(BitConverter.GetBytes(numberOfPoints).Reverse()); | |||||
//获取CRC校验码 | //获取CRC校验码 | ||||
byte[] getCRC = sendByteList.ToArray(); | byte[] getCRC = sendByteList.ToArray(); | ||||
byte[] resultCRC = CRCUitl.CalculateCRC(getCRC, getCRC.Length); | byte[] resultCRC = CRCUitl.CalculateCRC(getCRC, getCRC.Length); | ||||
@@ -114,7 +114,7 @@ namespace ModbusDemo.Device | |||||
MessageBox.Show("0x15:数据库插入错误"); | MessageBox.Show("0x15:数据库插入错误"); | ||||
} | } | ||||
return resultValue; | return resultValue; | ||||
} | } | ||||
@@ -144,42 +144,30 @@ namespace ModbusDemo.Device | |||||
MessageBox.Show("0x15:数据库插入错误"); | MessageBox.Show("0x15:数据库插入错误"); | ||||
} | } | ||||
//判断发送回来的数据是否正确 | //判断发送回来的数据是否正确 | ||||
if (CheckData.CheckResponse(response)) | if (CheckData.CheckResponse(response)) | ||||
{ | { | ||||
List<byte> responseList = new List<byte>(response); | |||||
//移除前两位 | |||||
responseList.RemoveRange(0, 3); | |||||
//移除后两位校验码 | |||||
responseList.RemoveRange(responseList.Count - 2, 2); | |||||
responseList.Reverse(); | |||||
//数组反转之后,转为二进制字符 | |||||
List<string> StringList = responseList.Select(m => Convert.ToString(m, 2)).ToList(); | |||||
var result = ""; | |||||
foreach (var item in StringList) | |||||
{ | |||||
result += item.PadLeft(8, '0'); | |||||
} | |||||
//先将字符串转为数组,再反转,再转为字节数组 | |||||
char[] chars = result.ToArray().Reverse<char>().ToArray(); | |||||
bool[] ultimately = new bool[numberOfPoints]; | |||||
for (int i = 0; i < numberOfPoints; i++) | |||||
{ | |||||
if (chars[i] == '1') | |||||
{ | |||||
ultimately[i] = true; | |||||
} | |||||
else | |||||
{ | |||||
ultimately[i] = false; | |||||
} | |||||
} | |||||
return ultimately; | |||||
// 移除前3个字节和后2个校验码字节,并反转数组 | |||||
var processedBytes = response | |||||
.Skip(3) // 移除前3个字节 | |||||
.Take(response.Count() - 5) // 保留中间部分 (总长度-5) | |||||
.Reverse() // 反转字节顺序 | |||||
.ToList(); | |||||
// 将每个字节转换为8位二进制字符串,不足8位时左边补0 | |||||
string binaryString = string.Concat( | |||||
processedBytes.Select(b => Convert.ToString(b, 2).PadLeft(8, '0')) | |||||
); | |||||
// 反转二进制字符串中的所有位,并转换为布尔数组 | |||||
return binaryString | |||||
.Reverse() // 反转所有位的顺序 | |||||
.Take(numberOfPoints) // 取指定数量的位 | |||||
.Select(c => c == '1') // 将字符'1'转换为true,其他转换为false | |||||
.ToArray(); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
@@ -202,35 +190,25 @@ namespace ModbusDemo.Device | |||||
MessageBox.Show("串口没有链接,请先链接"); | MessageBox.Show("串口没有链接,请先链接"); | ||||
return; | return; | ||||
} | } | ||||
List<byte> sendByteList = new List<byte>(); | |||||
//设置从站地址 | |||||
sendByteList.Add(slaveAddress); | |||||
//设置功能码 | |||||
sendByteList.Add(0x0F); | |||||
//设置起始地址的高位和低位 | |||||
sendByteList.Add(BitConverter.GetBytes(startAddress)[1]); | |||||
sendByteList.Add(BitConverter.GetBytes(startAddress)[0]); | |||||
//设置写入几个线圈 | |||||
sendByteList.Add(BitConverter.GetBytes(data.Length)[1]); | |||||
sendByteList.Add(BitConverter.GetBytes(data.Length)[0]); | |||||
List<byte> sendByteList = new List<byte> | |||||
{ | |||||
slaveAddress, // 从站地址 | |||||
0x0F, // 功能码:写多个线圈 | |||||
}; | |||||
// 计算字节数 | |||||
int byteCount = (data.Length + 7) / 8; | |||||
sendByteList.Add((byte)byteCount); | |||||
// 添加起始地址(高字节在前,低字节在后) | |||||
sendByteList.AddRange(BitConverter.GetBytes(startAddress).Reverse()); | |||||
// 初始化字节数组 | |||||
byte[] coilBytes = new byte[byteCount]; | |||||
// 添加线圈数量(高字节在前,低字节在后) | |||||
ushort coilCount = (ushort)data.Length; | |||||
sendByteList.AddRange(BitConverter.GetBytes(coilCount).Reverse()); | |||||
// 把bool数组转换为字节 | |||||
for (int i = 0; i < data.Length; i++) | |||||
{ | |||||
int byteIndex = i / 8; | |||||
int bitIndex = i % 8; | |||||
if (data[i]) | |||||
{ | |||||
coilBytes[byteIndex] |= (byte)(1 << bitIndex); | |||||
} | |||||
} | |||||
// 计算所需字节数(每8个线圈占1字节) | |||||
int byteCount = (coilCount + 7) / 8; | |||||
sendByteList.Add((byte)byteCount); | |||||
// 将布尔数组转换为字节数组(每个位表示一个线圈状态) | |||||
byte[] coilBytes = ConvertBoolsToBytes(data); | |||||
sendByteList.AddRange(coilBytes); | sendByteList.AddRange(coilBytes); | ||||
//获取CRC校验码 | //获取CRC校验码 | ||||
@@ -294,12 +272,30 @@ namespace ModbusDemo.Device | |||||
MessageBox.Show("0x15:数据库插入错误"); | MessageBox.Show("0x15:数据库插入错误"); | ||||
} | } | ||||
//判断发送回来的数据是否正确 | //判断发送回来的数据是否正确 | ||||
CheckData.CheckResponse(response); | CheckData.CheckResponse(response); | ||||
} | |||||
/// <summary> | |||||
/// 将布尔数组转换为字节数组(每个位表示一个线圈状态) | |||||
/// </summary> | |||||
/// <param name="data"></param> | |||||
/// <returns></returns> | |||||
private static byte[] ConvertBoolsToBytes(bool[] data) | |||||
{ | |||||
int byteCount = (data.Length + 7) / 8; | |||||
byte[] result = new byte[byteCount]; | |||||
for (int i = 0; i < data.Length; i++) | |||||
{ | |||||
if (data[i]) | |||||
{ | |||||
int byteIndex = i / 8; | |||||
int bitIndex = i % 8; | |||||
result[byteIndex] |= (byte)(1 << bitIndex); | |||||
} | |||||
} | |||||
return result; | |||||
} | } | ||||
/// <summary> | /// <summary> | ||||
/// 读寄存器操作 | /// 读寄存器操作 | ||||
@@ -316,17 +312,17 @@ namespace ModbusDemo.Device | |||||
MessageBox.Show("串口没有链接,请先链接"); | MessageBox.Show("串口没有链接,请先链接"); | ||||
return resultValue; | return resultValue; | ||||
} | } | ||||
List<byte> sendByteList = new List<byte>(); | |||||
//设置从站地址 | |||||
sendByteList.Add(slaveAddress); | |||||
//设置功能码 | |||||
sendByteList.Add(0x03); | |||||
//设置起始地址的高位和低位 | |||||
sendByteList.Add(BitConverter.GetBytes(startAddress)[1]); | |||||
sendByteList.Add(BitConverter.GetBytes(startAddress)[0]); | |||||
//设置读取几个线圈的高位和低位 | |||||
sendByteList.Add(BitConverter.GetBytes(numberOfPoints)[1]); | |||||
sendByteList.Add(BitConverter.GetBytes(numberOfPoints)[0]); | |||||
var sendByteList = new List<byte>(8) | |||||
{ | |||||
slaveAddress, // 从站地址 | |||||
0x03, // 功能码:读保持寄存器 | |||||
}; | |||||
// 添加起始地址(高字节在前) | |||||
sendByteList.AddRange(BitConverter.GetBytes(startAddress).Reverse()); | |||||
// 添加读取点数(高字节在前) | |||||
sendByteList.AddRange(BitConverter.GetBytes(numberOfPoints).Reverse()); | |||||
//获取CRC校验码 | //获取CRC校验码 | ||||
byte[] getCRC = sendByteList.ToArray(); | byte[] getCRC = sendByteList.ToArray(); | ||||
byte[] resultCRC = CRCUitl.CalculateCRC(getCRC, getCRC.Length); | byte[] resultCRC = CRCUitl.CalculateCRC(getCRC, getCRC.Length); | ||||
@@ -390,7 +386,7 @@ namespace ModbusDemo.Device | |||||
MessageBox.Show("0x15:数据库插入错误"); | MessageBox.Show("0x15:数据库插入错误"); | ||||
} | } | ||||
return resultValue; | return resultValue; | ||||
@@ -422,7 +418,7 @@ namespace ModbusDemo.Device | |||||
MessageBox.Show("0x15:数据库插入错误"); | MessageBox.Show("0x15:数据库插入错误"); | ||||
} | } | ||||
//判断发送回来的数据是否正确 | //判断发送回来的数据是否正确 | ||||
if (CheckData.CheckResponse(response)) | if (CheckData.CheckResponse(response)) | ||||
@@ -459,28 +455,29 @@ namespace ModbusDemo.Device | |||||
MessageBox.Show("串口没有链接,请先链接"); | MessageBox.Show("串口没有链接,请先链接"); | ||||
return; | return; | ||||
} | } | ||||
List<byte> sendByteList = new List<byte>(); | |||||
//设置从站地址 | |||||
sendByteList.Add(slaveAddress); | |||||
//设置功能码 | |||||
sendByteList.Add(0x10); | |||||
//设置起始地址的高位和低位 | |||||
sendByteList.Add(BitConverter.GetBytes(startAddress)[1]); | |||||
sendByteList.Add(BitConverter.GetBytes(startAddress)[0]); | |||||
//设置写入几个线圈 | |||||
sendByteList.Add(BitConverter.GetBytes(data.Length)[1]); | |||||
sendByteList.Add(BitConverter.GetBytes(data.Length)[0]); | |||||
// 计算字节数 (每个寄存器占2字节) | |||||
int byteCount = (data.Length) * 2; | |||||
// 计算字节数 | |||||
int byteCount = (data.Length + 7) / 8; | |||||
// 预分配列表容量,避免多次扩容 | |||||
var sendByteList = new List<byte>(9 + byteCount) | |||||
{ | |||||
slaveAddress, // 从站地址 | |||||
0x10, // 功能码:写多个保持寄存器 | |||||
}; | |||||
// 添加起始地址(高字节在前) | |||||
sendByteList.AddRange(BitConverter.GetBytes(startAddress).Reverse()); | |||||
// 添加寄存器数量(高字节在前) | |||||
sendByteList.AddRange(BitConverter.GetBytes((ushort)data.Length).Reverse()); | |||||
// 添加字节数 | |||||
sendByteList.Add((byte)byteCount); | sendByteList.Add((byte)byteCount); | ||||
// 添加寄存器数据(每个寄存器2字节,高字节在前) | |||||
foreach (ushort value in data) | foreach (ushort value in data) | ||||
{ | { | ||||
byte[] valueBytes = BitConverter.GetBytes(value); | |||||
// 大端序:高字节在前,低字节在后 | |||||
sendByteList.Add(valueBytes[1]); | |||||
sendByteList.Add(valueBytes[0]); | |||||
sendByteList.AddRange(BitConverter.GetBytes(value).Reverse()); | |||||
} | } | ||||
//获取CRC校验码 | //获取CRC校验码 | ||||
@@ -544,7 +541,7 @@ namespace ModbusDemo.Device | |||||
MessageBox.Show("0x15:数据库插入错误"); | MessageBox.Show("0x15:数据库插入错误"); | ||||
} | } | ||||
//判断发送回来的数据是否正确 | //判断发送回来的数据是否正确 | ||||
CheckData.CheckResponse(response); | CheckData.CheckResponse(response); | ||||
@@ -0,0 +1,14 @@ | |||||
using Prism.Events; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace ModbusDemo.Event | |||||
{ | |||||
public class SerialPortSettingsChangedEvent: PubSubEvent | |||||
{ | |||||
} | |||||
} |
@@ -12,9 +12,7 @@ namespace ModbusDemo.Model | |||||
/// </summary> | /// </summary> | ||||
public class ModbusDbContext:DbContext | public class ModbusDbContext:DbContext | ||||
{ | { | ||||
protected ModbusDbContext() | |||||
{ | |||||
} | |||||
public ModbusDbContext(DbContextOptions<ModbusDbContext> options) :base(options) | public ModbusDbContext(DbContextOptions<ModbusDbContext> options) :base(options) | ||||
{ | { | ||||
@@ -16,7 +16,7 @@ namespace ModbusDemo.Uitls | |||||
/// <returns></returns> | /// <returns></returns> | ||||
public static bool CheckResponse(byte[] response) | public static bool CheckResponse(byte[] response) | ||||
{ | { | ||||
if (response.Length == 0) | |||||
if (response == null || response.Length == 0) | |||||
{ | { | ||||
MessageBox.Show("返回数据为空", "error", MessageBoxButton.OK, MessageBoxImage.Error); | MessageBox.Show("返回数据为空", "error", MessageBoxButton.OK, MessageBoxImage.Error); | ||||
return false; | return false; | ||||
@@ -57,6 +57,7 @@ | |||||
<RowDefinition Height="60"> | <RowDefinition Height="60"> | ||||
</RowDefinition> | </RowDefinition> | ||||
</Grid.RowDefinitions> | </Grid.RowDefinitions> | ||||
<!-- 线圈的读取 --> | |||||
<StackPanel HorizontalAlignment="Center" Orientation="Vertical"> | <StackPanel HorizontalAlignment="Center" Orientation="Vertical"> | ||||
<TextBlock Margin="20" Text="从站地址"> | <TextBlock Margin="20" Text="从站地址"> | ||||
</TextBlock> | </TextBlock> | ||||
@@ -109,6 +110,7 @@ | |||||
<ColumnDefinition> | <ColumnDefinition> | ||||
</ColumnDefinition> | </ColumnDefinition> | ||||
</Grid.ColumnDefinitions> | </Grid.ColumnDefinitions> | ||||
<!-- 线圈的写入 --> | |||||
<StackPanel HorizontalAlignment="Center" Orientation="Vertical"> | <StackPanel HorizontalAlignment="Center" Orientation="Vertical"> | ||||
<TextBlock Margin="20" Text="从站地址"> | <TextBlock Margin="20" Text="从站地址"> | ||||
</TextBlock> | </TextBlock> | ||||
@@ -149,7 +151,7 @@ | |||||
Style="{StaticResource MaterialDesignRaisedDarkButton}"> | Style="{StaticResource MaterialDesignRaisedDarkButton}"> | ||||
</Button> | </Button> | ||||
</Grid> | </Grid> | ||||
<!-- 展示历史读取数据 --> | |||||
<Grid Grid.Row="3"> | <Grid Grid.Row="3"> | ||||
<DataGrid ItemsSource="{Binding ModbusLogList}" AutoGenerateColumns="False" IsReadOnly="True" ColumnWidth="*"> | <DataGrid ItemsSource="{Binding ModbusLogList}" AutoGenerateColumns="False" IsReadOnly="True" ColumnWidth="*"> | ||||
<DataGrid.Columns> | <DataGrid.Columns> | ||||
@@ -57,6 +57,7 @@ | |||||
<RowDefinition Height="60"> | <RowDefinition Height="60"> | ||||
</RowDefinition> | </RowDefinition> | ||||
</Grid.RowDefinitions> | </Grid.RowDefinitions> | ||||
<!--读寄存器--> | |||||
<StackPanel HorizontalAlignment="Center" Orientation="Vertical"> | <StackPanel HorizontalAlignment="Center" Orientation="Vertical"> | ||||
<TextBlock Margin="20" Text="从站地址"> | <TextBlock Margin="20" Text="从站地址"> | ||||
</TextBlock> | </TextBlock> | ||||
@@ -109,6 +110,7 @@ | |||||
<ColumnDefinition> | <ColumnDefinition> | ||||
</ColumnDefinition> | </ColumnDefinition> | ||||
</Grid.ColumnDefinitions> | </Grid.ColumnDefinitions> | ||||
<!--写寄存器--> | |||||
<StackPanel HorizontalAlignment="Center" Orientation="Vertical"> | <StackPanel HorizontalAlignment="Center" Orientation="Vertical"> | ||||
<TextBlock Margin="20" Text="从站地址"> | <TextBlock Margin="20" Text="从站地址"> | ||||
</TextBlock> | </TextBlock> | ||||
@@ -150,6 +152,7 @@ | |||||
</Button> | </Button> | ||||
</Grid> | </Grid> | ||||
<Grid Grid.Row="3"> | <Grid Grid.Row="3"> | ||||
<!--数据展示--> | |||||
<DataGrid ItemsSource="{Binding ModbusLogList}" AutoGenerateColumns="False" IsReadOnly="True" ColumnWidth="*"> | <DataGrid ItemsSource="{Binding ModbusLogList}" AutoGenerateColumns="False" IsReadOnly="True" ColumnWidth="*"> | ||||
<DataGrid.Columns> | <DataGrid.Columns> | ||||
<!-- 操作类型列 --> | <!-- 操作类型列 --> | ||||
@@ -61,6 +61,8 @@ | |||||
<ComboBoxItem Content="COM2" /> | <ComboBoxItem Content="COM2" /> | ||||
<ComboBoxItem Content="COM3" /> | <ComboBoxItem Content="COM3" /> | ||||
<ComboBoxItem Content="COM4" /> | <ComboBoxItem Content="COM4" /> | ||||
<ComboBoxItem Content="COM5" /> | |||||
<ComboBoxItem Content="COM6" /> | |||||
</ComboBox> | </ComboBox> | ||||
</StackPanel> | </StackPanel> | ||||
<!-- 设置波特率 --> | <!-- 设置波特率 --> | ||||
@@ -95,7 +95,7 @@ namespace ModbusDemo.VIewModel | |||||
int count = 0; | int count = 0; | ||||
for (int i = 1; i < totalRegisters; i += 2) | for (int i = 1; i < totalRegisters; i += 2) | ||||
{ | { | ||||
result.Append(allRegisters[i].ToString()+" "); | |||||
result.Append(allRegisters[i].ToString() + " "); | |||||
count++; | count++; | ||||
if (count % 50 == 0) | if (count % 50 == 0) | ||||
{ | { | ||||
@@ -105,7 +105,9 @@ namespace ModbusDemo.VIewModel | |||||
ReadResult = result.ToString(); | ReadResult = result.ToString(); | ||||
} | } | ||||
/// <summary> | |||||
/// 自己的类 | |||||
/// </summary> | |||||
private void ReadOddRegister2() | private void ReadOddRegister2() | ||||
{ | { | ||||
byte slaveId = 1; | byte slaveId = 1; | ||||
@@ -122,13 +124,13 @@ namespace ModbusDemo.VIewModel | |||||
ushort currentChunkSize = 100; | ushort currentChunkSize = 100; | ||||
int chunkIndex = i; | int chunkIndex = i; | ||||
tasks[i] = Task.Run(() => | |||||
tasks[i] = Task.Run(async () => | |||||
{ | { | ||||
ushort[] registers = ReadRegisters(slaveId, startAddress, currentChunkSize); | |||||
Array.Copy(registers, 0, allRegisters, chunkIndex * chunkSize, currentChunkSize); | |||||
ushort[] registers = await ReadRegisters(slaveId, startAddress, currentChunkSize); | |||||
Array.Copy(registers, 0, allRegisters, chunkIndex * chunkSize, currentChunkSize); | |||||
}); | }); | ||||
} | } | ||||
@@ -150,9 +152,9 @@ namespace ModbusDemo.VIewModel | |||||
} | } | ||||
public ushort[] ReadRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints) | |||||
public async Task<ushort[]> ReadRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints) | |||||
{ | { | ||||
object _lock = new object(); | |||||
ushort[] resultValue = null; | ushort[] resultValue = null; | ||||
if (!_serialPort.IsOpen) | if (!_serialPort.IsOpen) | ||||
{ | { | ||||
@@ -186,41 +188,40 @@ namespace ModbusDemo.VIewModel | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
lock (_lock) | |||||
{ | |||||
//使用时间去轮询查询数据 | |||||
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资源 | |||||
Task.Delay(20); | |||||
} | |||||
response = responseData.ToArray(); | |||||
if (response[0] == 0x00) | |||||
//使用时间去轮询查询数据 | |||||
DateTime startTime = DateTime.Now; | |||||
while ((DateTime.Now - startTime).TotalMilliseconds < _serialPort.ReadTimeout) | |||||
{ | |||||
int bytesToRead = _serialPort.BytesToRead; | |||||
if (bytesToRead > 0) | |||||
{ | { | ||||
continue; | |||||
byte[] buffer = new byte[bytesToRead]; | |||||
int bytesRead = _serialPort.Read(buffer, 0, bytesToRead); | |||||
responseData.AddRange(buffer.Take(bytesRead)); | |||||
} | } | ||||
resultValue = ParseRegistersresponse(sendByte, response, numberOfPoints); | |||||
return resultValue; | |||||
//延迟20毫秒,节约cpu资源 | |||||
await Task.Delay(20); | |||||
} | |||||
response = responseData.ToArray(); | |||||
if (response[0] == 0x00) | |||||
{ | |||||
continue; | |||||
} | } | ||||
resultValue = ParseRegistersresponse(sendByte, response, numberOfPoints); | |||||
return resultValue; | |||||
} | } | ||||
catch (Exception) | catch (Exception) | ||||
{ | { | ||||
attempt++; | attempt++; | ||||
} | } | ||||
} | } | ||||
return resultValue; | return resultValue; | ||||
@@ -229,7 +230,7 @@ namespace ModbusDemo.VIewModel | |||||
public ushort[] ParseRegistersresponse(byte[] sendByte, byte[] response, ushort numberOfPoints) | public ushort[] ParseRegistersresponse(byte[] sendByte, byte[] response, ushort numberOfPoints) | ||||
{ | { | ||||
//判断发送回来的数据是否正确 | //判断发送回来的数据是否正确 | ||||
if (CheckData.CheckResponse(response)) | if (CheckData.CheckResponse(response)) | ||||
@@ -1,6 +1,8 @@ | |||||
using ModbusDemo.Device; | using ModbusDemo.Device; | ||||
using ModbusDemo.Event; | |||||
using ModbusDemo.Model; | using ModbusDemo.Model; | ||||
using Prism.Commands; | using Prism.Commands; | ||||
using Prism.Events; | |||||
using Prism.Mvvm; | using Prism.Mvvm; | ||||
using System; | using System; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
@@ -17,6 +19,9 @@ namespace ModbusDemo.VIewModel | |||||
/// </summary> | /// </summary> | ||||
public class CoilUCViewModel : BindableBase | public class CoilUCViewModel : BindableBase | ||||
{ | { | ||||
//事件聚合器 | |||||
private readonly IEventAggregator _eventAggregator; | |||||
//定义数据库操作 | //定义数据库操作 | ||||
private ModbusDbContext _modbusDbContext; | private ModbusDbContext _modbusDbContext; | ||||
//获取读线圈的类 | //获取读线圈的类 | ||||
@@ -41,8 +46,8 @@ namespace ModbusDemo.VIewModel | |||||
RaisePropertyChanged(); | RaisePropertyChanged(); | ||||
} | } | ||||
} | } | ||||
public string SerialPortInfo | |||||
public string SerialPortInfo | |||||
{ | { | ||||
get | get | ||||
{ | { | ||||
@@ -50,9 +55,10 @@ namespace ModbusDemo.VIewModel | |||||
+ ",数据位:" + _serialPort.DataBits + ",校验位:" + _serialPort.Parity + ",停止位:" + _serialPort.StopBits; | + ",数据位:" + _serialPort.DataBits + ",校验位:" + _serialPort.Parity + ",停止位:" + _serialPort.StopBits; | ||||
} | } | ||||
} | } | ||||
#region 读取定义 | #region 读取定义 | ||||
//读取的从站id | //读取的从站id | ||||
@@ -170,18 +176,29 @@ namespace ModbusDemo.VIewModel | |||||
} | } | ||||
public CoilUCViewModel(SerialPort serialPort, ModbusRTU modbusRTU, ModbusDbContext modbusDbContext) | |||||
public CoilUCViewModel(SerialPort serialPort, ModbusRTU modbusRTU, ModbusDbContext modbusDbContext, IEventAggregator eventAggregator) | |||||
{ | { | ||||
_serialPort = serialPort; | _serialPort = serialPort; | ||||
ReadCoilCmm = new DelegateCommand(ReadCoil); | ReadCoilCmm = new DelegateCommand(ReadCoil); | ||||
_modbusRTU = modbusRTU; | _modbusRTU = modbusRTU; | ||||
WriteCoilCmm = new DelegateCommand(WriteCoil); | WriteCoilCmm = new DelegateCommand(WriteCoil); | ||||
_modbusDbContext = modbusDbContext; | _modbusDbContext = modbusDbContext; | ||||
_eventAggregator = eventAggregator; | |||||
// 订阅事件(使用弱引用,避免内存泄漏) | |||||
_eventAggregator.GetEvent<SerialPortSettingsChangedEvent>().Subscribe( | |||||
OnSerialPortSettingsChanged, | |||||
ThreadOption.UIThread, // 在UI线程执行回调 | |||||
false);// 不使用强引用 | |||||
//初始化查询操作 | //初始化查询操作 | ||||
ModbusLogList = GetOperateCoil(); | ModbusLogList = GetOperateCoil(); | ||||
IsEnable = true; | IsEnable = true; | ||||
} | } | ||||
// 事件回调方法:当串口设置变更时触发 | |||||
private void OnSerialPortSettingsChanged() | |||||
{ | |||||
// 强制刷新SerialPortInfo属性,触发UI更新 | |||||
RaisePropertyChanged(nameof(SerialPortInfo)); | |||||
} | |||||
/// <summary> | /// <summary> | ||||
/// 线圈读取操作 | /// 线圈读取操作 | ||||
/// </summary> | /// </summary> | ||||
@@ -1,6 +1,8 @@ | |||||
using ModbusDemo.Device; | using ModbusDemo.Device; | ||||
using ModbusDemo.Event; | |||||
using ModbusDemo.Model; | using ModbusDemo.Model; | ||||
using Prism.Commands; | using Prism.Commands; | ||||
using Prism.Events; | |||||
using Prism.Mvvm; | using Prism.Mvvm; | ||||
using System; | using System; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
@@ -14,6 +16,8 @@ namespace ModbusDemo.VIewModel | |||||
{ | { | ||||
class RegisterUCViewModel : BindableBase | class RegisterUCViewModel : BindableBase | ||||
{ | { | ||||
//事件聚合器 | |||||
private readonly IEventAggregator _eventAggregator; | |||||
//定义数据库操作类 | //定义数据库操作类 | ||||
private ModbusDbContext _modbusDbContext; | private ModbusDbContext _modbusDbContext; | ||||
//获取读线圈的类 | //获取读线圈的类 | ||||
@@ -163,19 +167,29 @@ namespace ModbusDemo.VIewModel | |||||
{ | { | ||||
} | } | ||||
public RegisterUCViewModel(SerialPort serialPort, ModbusRTU modbusRTU, ModbusDbContext modbusDbContext) | |||||
public RegisterUCViewModel(SerialPort serialPort, ModbusRTU modbusRTU, ModbusDbContext modbusDbContext, IEventAggregator eventAggregator) | |||||
{ | { | ||||
_serialPort = serialPort; | _serialPort = serialPort; | ||||
ReadRegisterCmm = new DelegateCommand(ReadRegister); | ReadRegisterCmm = new DelegateCommand(ReadRegister); | ||||
_modbusRTU = modbusRTU; | _modbusRTU = modbusRTU; | ||||
WriteRegisterCmm = new DelegateCommand(WriteRegister); | WriteRegisterCmm = new DelegateCommand(WriteRegister); | ||||
_modbusDbContext = modbusDbContext; | _modbusDbContext = modbusDbContext; | ||||
_eventAggregator = eventAggregator; | |||||
// 订阅事件(使用弱引用,避免内存泄漏) | |||||
_eventAggregator.GetEvent<SerialPortSettingsChangedEvent>().Subscribe( | |||||
OnSerialPortSettingsChanged, | |||||
ThreadOption.UIThread, // 在UI线程执行回调 | |||||
false);// 不使用强引用 | |||||
ModbusLogList = GetOperateRegister(); | ModbusLogList = GetOperateRegister(); | ||||
IsEnable = true; | IsEnable = true; | ||||
} | } | ||||
// 事件回调方法:当串口设置变更时触发 | |||||
private void OnSerialPortSettingsChanged() | |||||
{ | |||||
// 强制刷新SerialPortInfo属性,触发UI更新 | |||||
RaisePropertyChanged(nameof(SerialPortInfo)); | |||||
} | |||||
@@ -1,5 +1,7 @@ | |||||
using ModbusDemo.Uitls; | |||||
using ModbusDemo.Event; | |||||
using ModbusDemo.Uitls; | |||||
using Prism.Commands; | using Prism.Commands; | ||||
using Prism.Events; | |||||
using Prism.Mvvm; | using Prism.Mvvm; | ||||
using Prism.Regions; | using Prism.Regions; | ||||
using System; | using System; | ||||
@@ -15,6 +17,8 @@ namespace ModbusDemo.VIewModel | |||||
class SettingsUCViewModel : BindableBase | class SettingsUCViewModel : BindableBase | ||||
{ | { | ||||
//事件聚合器 | |||||
private readonly IEventAggregator _eventAggregator; | |||||
//控制页面跳转 | //控制页面跳转 | ||||
private readonly IRegionManager _regionManager; | private readonly IRegionManager _regionManager; | ||||
//断开连接的命令 | //断开连接的命令 | ||||
@@ -97,12 +101,13 @@ namespace ModbusDemo.VIewModel | |||||
/// 从容器中获取创建的窗口 | /// 从容器中获取创建的窗口 | ||||
/// </summary> | /// </summary> | ||||
/// <param name="serialPort"></param> | /// <param name="serialPort"></param> | ||||
public SettingsUCViewModel(SerialPort serialPort, IRegionManager regionManager) | |||||
public SettingsUCViewModel(SerialPort serialPort, IRegionManager regionManager, IEventAggregator eventAggregator) | |||||
{ | { | ||||
_serialPort = serialPort; | _serialPort = serialPort; | ||||
ConnectionCmm = new DelegateCommand(Connection); | ConnectionCmm = new DelegateCommand(Connection); | ||||
DisConnectionCmm = new DelegateCommand(DisConnection); | DisConnectionCmm = new DelegateCommand(DisConnection); | ||||
_regionManager = regionManager; | _regionManager = regionManager; | ||||
_eventAggregator = eventAggregator; | |||||
} | } | ||||
private void DisConnection() | private void DisConnection() | ||||
@@ -110,8 +115,9 @@ namespace ModbusDemo.VIewModel | |||||
if (_serialPort.IsOpen) | if (_serialPort.IsOpen) | ||||
{ | { | ||||
_serialPort.Close(); | _serialPort.Close(); | ||||
MessageBox.Show("连接已经断开"); | |||||
} | } | ||||
MessageBox.Show("连接已经断开"); | |||||
} | } | ||||
/// <summary> | /// <summary> | ||||
@@ -126,8 +132,14 @@ namespace ModbusDemo.VIewModel | |||||
_serialPort.PortName = GetComboBoxItemValue(this.PortName); | _serialPort.PortName = GetComboBoxItemValue(this.PortName); | ||||
_serialPort.BaudRate = int.Parse(GetComboBoxItemValue(this.BaudRate)); | _serialPort.BaudRate = int.Parse(GetComboBoxItemValue(this.BaudRate)); | ||||
_serialPort.Parity = this.Parity; | _serialPort.Parity = this.Parity; | ||||
if (this.StopBits == StopBits.None) | |||||
{ | |||||
this.StopBits = StopBits.One; | |||||
MessageBox.Show("当前设备不支持无停止位(None)模式,已自动切换为 1 个停止位。"); | |||||
} | |||||
_serialPort.StopBits = this.StopBits; | _serialPort.StopBits = this.StopBits; | ||||
_serialPort.DataBits = int.Parse(GetComboBoxItemValue(this.DataBits)); | _serialPort.DataBits = int.Parse(GetComboBoxItemValue(this.DataBits)); | ||||
//读取超时时间 | //读取超时时间 | ||||
_serialPort.ReadTimeout = 500; | _serialPort.ReadTimeout = 500; | ||||
//写入超时时间 | //写入超时时间 | ||||
@@ -135,6 +147,8 @@ namespace ModbusDemo.VIewModel | |||||
try | try | ||||
{ | { | ||||
_serialPort.Open(); | _serialPort.Open(); | ||||
// 发布事件通知其他ViewModel | |||||
_eventAggregator.GetEvent<SerialPortSettingsChangedEvent>().Publish(); | |||||
MessageBox.Show("串口链接成功"); | MessageBox.Show("串口链接成功"); | ||||
_regionManager.Regions["ModbusRegion"].RequestNavigate("CoilUC"); | _regionManager.Regions["ModbusRegion"].RequestNavigate("CoilUC"); | ||||
@@ -142,9 +156,13 @@ namespace ModbusDemo.VIewModel | |||||
catch (Exception) | catch (Exception) | ||||
{ | { | ||||
MessageBox.Show("串口已经链接,请先断开链接在尝试","warning",MessageBoxButton.OK,MessageBoxImage.Warning); | |||||
MessageBox.Show("串口已经链接或者断开,请重新检查在尝试","warning",MessageBoxButton.OK,MessageBoxImage.Warning); | |||||
} | } | ||||
} | } | ||||
else | |||||
{ | |||||
MessageBox.Show("当前串口已经连接,请先断开,再连接"); | |||||
} | |||||
} | } | ||||
/// <summary> | /// <summary> | ||||