@@ -12,6 +12,8 @@ using System.Data; | |||
using System.DirectoryServices; | |||
using System.IO; | |||
using System.IO.Ports; | |||
using System.Security.Cryptography; | |||
using System.Text; | |||
using System.Windows; | |||
namespace ModbusDemo | |||
@@ -48,7 +50,7 @@ namespace ModbusDemo | |||
//将读线圈注册 | |||
containerRegistry.Register<ModbusRTU>(); | |||
//附加功能如何读取单数寄存器; | |||
containerRegistry.RegisterForNavigation<AttachUC, AttachUCViewModel>(); | |||
//containerRegistry.RegisterForNavigation<AttachUC, AttachUCViewModel>(); | |||
// 1. 加载配置文件 | |||
@@ -56,13 +58,14 @@ namespace ModbusDemo | |||
.SetBasePath(Directory.GetCurrentDirectory()) | |||
.AddJsonFile("appsettings.json") | |||
.Build(); | |||
// 2. 配置 DbContextOptions | |||
// 2.解密连接字符串 | |||
string decryptedConnection = Decrypt(configuration.GetConnectionString("ConnStr")); | |||
// 3. 配置 DbContextOptions | |||
var options = new DbContextOptionsBuilder<ModbusDbContext>() | |||
.UseSqlServer(configuration.GetConnectionString("ConnStr")) | |||
.UseSqlServer(decryptedConnection) | |||
.Options; | |||
// 3. 注册 DbContext | |||
// 4. 注册 DbContext | |||
containerRegistry.Register<ModbusDbContext>(() => new ModbusDbContext(options)); | |||
} | |||
/// <summary> | |||
@@ -74,10 +77,40 @@ namespace ModbusDemo | |||
mainWindowViewModel!.DefultNaigation(); | |||
base.OnInitialized(); | |||
} | |||
//硬编码 | |||
private static readonly byte[] Key = Encoding.UTF8.GetBytes("8Jn3pQ7sV9y$B&E)"); // 16字节,AES-128 | |||
private static readonly byte[] IV = Encoding.UTF8.GetBytes("2r5u8x/A?D*G-KaP"); // 16字节 | |||
/// <summary> | |||
/// 解密字符串 | |||
/// </summary> | |||
/// <param name="encryptedText">加密后的Base64字符串</param> | |||
/// <returns>解密后的原始字符串</returns> | |||
public static string Decrypt(string encryptedText) | |||
{ | |||
if (string.IsNullOrEmpty(encryptedText)) | |||
return string.Empty; | |||
using (Aes aes = Aes.Create()) | |||
{ | |||
aes.Key = Key; | |||
aes.IV = IV; | |||
// 创建解密器 | |||
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV); | |||
using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(encryptedText))) | |||
{ | |||
using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read)) | |||
{ | |||
using (StreamReader sr = new StreamReader(cs)) | |||
{ | |||
return sr.ReadToEnd(); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -19,7 +19,7 @@ namespace ModbusDemo.Device | |||
//用于操作数据库 | |||
private ModbusDbContext _modbusDbContext; | |||
//TODO,修改 | |||
private SerialPortAdapter _portAdapter; | |||
//private SerialPortAdapter _portAdapter; | |||
public ModbusRTU(SerialPort serialPort, ModbusDbContext modbusDbContext) | |||
{ | |||
@@ -72,8 +72,7 @@ namespace ModbusDemo.Device | |||
responseData.Clear(); | |||
// 清除输入缓冲区残留数据 | |||
_serialPort.DiscardInBuffer(); | |||
} | |||
} | |||
try | |||
{ | |||
_serialPort.Write(sendByte, 0, sendByte.Length); | |||
@@ -622,5 +621,7 @@ namespace ModbusDemo.Device | |||
return sb.ToString(); | |||
} | |||
} | |||
} |
@@ -31,8 +31,7 @@ namespace ModbusDemo.ErrorCode | |||
// 重写 ToString 方法 | |||
public override string ToString() => $"Error 0x{Code:X2}: {Description}"; | |||
// 隐式转换为 byte | |||
public static implicit operator byte(ErrorCode error) => error.Code; | |||
// 根据错误码值查找错误码 | |||
public static ErrorCode FromByte(byte code) => AllErrors.FirstOrDefault(e => e.Code == code); | |||
@@ -10,8 +10,8 @@ | |||
xmlns:prism="http://prismlibrary.com/" | |||
xmlns:viewmodel="clr-namespace:ModbusDemo.VIewModel" | |||
Title="MainWindow" | |||
Width="900" | |||
Height="600" | |||
Width="1000" | |||
Height="800" | |||
d:DataContext="{d:DesignInstance Type=viewmodel:MainWindowViewModel, | |||
IsDesignTimeCreatable=True}" | |||
WindowStartupLocation="CenterScreen" | |||
@@ -10,6 +10,8 @@ | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<Compile Remove="Device\IStreamResource.cs" /> | |||
<Compile Remove="Device\SerialPortAdapter.cs" /> | |||
<Compile Remove="ErrorCode\ErrorCodeExtensions.cs" /> | |||
<Compile Remove="ErrorCode\ErrorInfoAttribute.cs" /> | |||
</ItemGroup> | |||
@@ -25,7 +27,6 @@ | |||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.27" /> | |||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.7" /> | |||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.7" /> | |||
<PackageReference Include="NModbus4" Version="2.1.0" /> | |||
<PackageReference Include="Prism.DryIoc" Version="8.1.97" /> | |||
<PackageReference Include="System.IO.Ports" Version="9.0.7" /> | |||
</ItemGroup> | |||
@@ -1,10 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
namespace ModbusDemo.Model | |||
{ | |||
} |
@@ -22,7 +22,7 @@ namespace ModbusDemo.Uitls | |||
return false; | |||
} | |||
// 检查数组长度是否足够 | |||
if (response.Length > 1) | |||
if (response.Length > 3) | |||
{ | |||
byte secondByte = response[1]; // 获取第二个字节(索引为1) | |||
@@ -10,8 +10,8 @@ | |||
d:DataContext="{d:DesignInstance Type=viewmodel:CoilUCViewModel, | |||
IsDesignTimeCreatable=True}" | |||
d:Background="White" | |||
d:DesignHeight="450" | |||
d:DesignWidth="800" | |||
d:DesignHeight="800" | |||
d:DesignWidth="1000" | |||
mc:Ignorable="d"> | |||
<UserControl.Resources> | |||
<Style TargetType="TextBox"> | |||
@@ -25,7 +25,7 @@ | |||
</RowDefinition> | |||
<RowDefinition> | |||
</RowDefinition> | |||
<RowDefinition> | |||
<RowDefinition Height="120"> | |||
</RowDefinition> | |||
<RowDefinition> | |||
</RowDefinition> | |||
@@ -54,7 +54,7 @@ | |||
<Grid.RowDefinitions> | |||
<RowDefinition> | |||
</RowDefinition> | |||
<RowDefinition Height="60"> | |||
<RowDefinition> | |||
</RowDefinition> | |||
</Grid.RowDefinitions> | |||
<!-- 线圈的读取 --> | |||
@@ -79,11 +79,18 @@ | |||
</TextBox> | |||
</StackPanel> | |||
<StackPanel Grid.Row="2" Grid.ColumnSpan="4" HorizontalAlignment="Center" Orientation="Horizontal"> | |||
<StackPanel Grid.Row="2" Grid.ColumnSpan="5" HorizontalAlignment="Center" Orientation="Horizontal"> | |||
<TextBlock Margin="0,20,0,0" Text="读取结果:" FontWeight="Black" /> | |||
<TextBlock Margin="0,50,0,0" Text="读取结果:" FontWeight="Black" /> | |||
<TextBox MinWidth="120" Margin="20,0,0,0" Text="{Binding ReadResult}" Style="{StaticResource MaterialDesignOutlinedTextBox}" /> | |||
<TextBox | |||
MinWidth="900" | |||
MaxWidth="900" | |||
Margin="20,0,0,0" | |||
AcceptsReturn="True" | |||
VerticalScrollBarVisibility="Auto" | |||
Text="{Binding ReadResult}" | |||
Style="{StaticResource MaterialDesignOutlinedTextBox}" /> | |||
</StackPanel> | |||
<Button | |||
Grid.Column="4" | |||
@@ -9,9 +9,9 @@ | |||
xmlns:viewmodel="clr-namespace:ModbusDemo.VIewModel" | |||
d:DataContext="{d:DesignInstance Type=viewmodel:RegisterUCViewModel, | |||
IsDesignTimeCreatable=True}" | |||
d:DesignHeight="450" | |||
d:DesignHeight="800" | |||
d:Background="White" | |||
d:DesignWidth="800" | |||
d:DesignWidth="1000" | |||
mc:Ignorable="d"> | |||
<UserControl.Resources> | |||
<Style TargetType="TextBox"> | |||
@@ -25,7 +25,7 @@ | |||
</RowDefinition> | |||
<RowDefinition> | |||
</RowDefinition> | |||
<RowDefinition> | |||
<RowDefinition Height="120"> | |||
</RowDefinition> | |||
<RowDefinition> | |||
</RowDefinition> | |||
@@ -54,10 +54,10 @@ | |||
<Grid.RowDefinitions> | |||
<RowDefinition> | |||
</RowDefinition> | |||
<RowDefinition Height="60"> | |||
<RowDefinition> | |||
</RowDefinition> | |||
</Grid.RowDefinitions> | |||
<!--读寄存器--> | |||
<!-- 读寄存器 --> | |||
<StackPanel HorizontalAlignment="Center" Orientation="Vertical"> | |||
<TextBlock Margin="20" Text="从站地址"> | |||
</TextBlock> | |||
@@ -79,11 +79,18 @@ | |||
</TextBox> | |||
</StackPanel> | |||
<StackPanel Grid.Row="2" Grid.ColumnSpan="4" HorizontalAlignment="Center" Orientation="Horizontal"> | |||
<StackPanel Grid.Row="2" Grid.ColumnSpan="5" HorizontalAlignment="Center" Orientation="Horizontal"> | |||
<TextBlock Margin="0,20,0,0" Text="读取结果:" FontWeight="Black" /> | |||
<TextBlock Margin="0,50,0,0" Text="读取结果:" FontWeight="Black" /> | |||
<TextBox MinWidth="120" Margin="20,0,0,0" Text="{Binding ReadResult}" Style="{StaticResource MaterialDesignOutlinedTextBox}" /> | |||
<TextBox | |||
MinWidth="900" | |||
MaxWidth="900" | |||
Margin="20,0,0,0" | |||
AcceptsReturn="True" | |||
VerticalScrollBarVisibility="Auto" | |||
Text="{Binding ReadResult}" | |||
Style="{StaticResource MaterialDesignOutlinedTextBox}" /> | |||
</StackPanel> | |||
<Button | |||
Grid.Column="4" | |||
@@ -110,7 +117,7 @@ | |||
<ColumnDefinition> | |||
</ColumnDefinition> | |||
</Grid.ColumnDefinitions> | |||
<!--写寄存器--> | |||
<!-- 写寄存器 --> | |||
<StackPanel HorizontalAlignment="Center" Orientation="Vertical"> | |||
<TextBlock Margin="20" Text="从站地址"> | |||
</TextBlock> | |||
@@ -152,7 +159,7 @@ | |||
</Button> | |||
</Grid> | |||
<Grid Grid.Row="3"> | |||
<!--数据展示--> | |||
<!-- 数据展示 --> | |||
<DataGrid ItemsSource="{Binding ModbusLogList}" AutoGenerateColumns="False" IsReadOnly="True" ColumnWidth="*"> | |||
<DataGrid.Columns> | |||
<!-- 操作类型列 --> | |||
@@ -1,4 +1,4 @@ | |||
using Modbus.Device; | |||
//using Modbus.Device; | |||
using ModbusDemo.Model; | |||
using ModbusDemo.Uitls; | |||
using Prism.Commands; | |||
@@ -50,61 +50,61 @@ namespace ModbusDemo.VIewModel | |||
} | |||
public AttachUCViewModel(SerialPort serialPort) | |||
{ | |||
ReadOddRegisterCmm = new DelegateCommand(ReadOddRegister2); | |||
//ReadOddRegisterCmm = new DelegateCommand(ReadOddRegister); | |||
_serialPort = serialPort; | |||
} | |||
/// <summary> | |||
/// 读1000个寄存器 | |||
/// </summary> | |||
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 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(); | |||
//} | |||
/// <summary> | |||
/// 自己的类 | |||
/// </summary> | |||
@@ -241,10 +241,16 @@ namespace ModbusDemo.VIewModel | |||
} | |||
string temp = ""; | |||
int count = 0; | |||
foreach (var item in result) | |||
{ | |||
count++; | |||
temp += item; | |||
temp += " "; | |||
if(count %25 == 0) | |||
{ | |||
temp += "\n"; | |||
} | |||
} | |||
ReadResult = temp; | |||
MessageBox.Show("读取成功"); | |||
@@ -66,7 +66,7 @@ namespace ModbusDemo.VIewModel | |||
LeftMenusList.Add(new MenusInfo() { Icon = "AllInclusive", MenuName = "线圈操作", ViewName = "CoilUC" }); | |||
LeftMenusList.Add(new MenusInfo() { Icon = "BlurCircular", MenuName = "寄存器操作", ViewName = "RegisterUC" }); | |||
LeftMenusList.Add(new MenusInfo() { Icon = "Settings", MenuName = "串口设置", ViewName = "SettingsUC" }); | |||
LeftMenusList.Add(new MenusInfo() { Icon = "AddCircle", MenuName = "附加功能", ViewName = "AttachUC" }); | |||
//LeftMenusList.Add(new MenusInfo() { Icon = "AddCircle", MenuName = "附加功能", ViewName = "AttachUC" }); | |||
} | |||
public void DefultNaigation() | |||
@@ -232,10 +232,16 @@ namespace ModbusDemo.VIewModel | |||
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("读取成功"); | |||
@@ -10,5 +10,5 @@ | |||
"node_modules", | |||
"wwwroot" | |||
], | |||
"ConnectionStrings": { "ConnStr": "server=.;uid=sa;pwd=123456;database=Modbus;TrustServerCertificate=true" } | |||
"ConnectionStrings": { "ConnStr": "3UiB0x91qCfBGGZJPtN2+6jjYWJL+PmUBwDGk07o3SzhkKx7GbsAJYoj44iejWaPIXfrZZvsvR30gpEgoVxYqVXexcruhQSPCW+B/msrunY=" } | |||
} |