@@ -1,10 +1,12 @@ | |||||
| | ||||
Microsoft Visual Studio Solution File, Format Version 12.00 | Microsoft Visual Studio Solution File, Format Version 12.00 | ||||
# Visual Studio Version 17 | # Visual Studio Version 17 | ||||
VisualStudioVersion = 17.14.36301.6 d17.14 | |||||
VisualStudioVersion = 17.14.36301.6 | |||||
MinimumVisualStudioVersion = 10.0.40219.1 | MinimumVisualStudioVersion = 10.0.40219.1 | ||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModbusDemo", "ModbusDemo\ModbusDemo.csproj", "{4F00ED24-6BEE-4192-9CA4-656802B78A6D}" | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModbusDemo", "ModbusDemo\ModbusDemo.csproj", "{4F00ED24-6BEE-4192-9CA4-656802B78A6D}" | ||||
EndProject | EndProject | ||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModbusTest", "ModbusTest\ModbusTest.csproj", "{83697BB7-2138-4D7A-BA1C-6FCAFE5CC37A}" | |||||
EndProject | |||||
Global | Global | ||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
Debug|Any CPU = Debug|Any CPU | Debug|Any CPU = Debug|Any CPU | ||||
@@ -15,6 +17,10 @@ Global | |||||
{4F00ED24-6BEE-4192-9CA4-656802B78A6D}.Debug|Any CPU.Build.0 = Debug|Any CPU | {4F00ED24-6BEE-4192-9CA4-656802B78A6D}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
{4F00ED24-6BEE-4192-9CA4-656802B78A6D}.Release|Any CPU.ActiveCfg = Release|Any CPU | {4F00ED24-6BEE-4192-9CA4-656802B78A6D}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
{4F00ED24-6BEE-4192-9CA4-656802B78A6D}.Release|Any CPU.Build.0 = Release|Any CPU | {4F00ED24-6BEE-4192-9CA4-656802B78A6D}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
{83697BB7-2138-4D7A-BA1C-6FCAFE5CC37A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
{83697BB7-2138-4D7A-BA1C-6FCAFE5CC37A}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
{83697BB7-2138-4D7A-BA1C-6FCAFE5CC37A}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
{83697BB7-2138-4D7A-BA1C-6FCAFE5CC37A}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
EndGlobalSection | EndGlobalSection | ||||
GlobalSection(SolutionProperties) = preSolution | GlobalSection(SolutionProperties) = preSolution | ||||
HideSolutionNode = FALSE | HideSolutionNode = FALSE | ||||
@@ -6,7 +6,7 @@ using System.Threading.Tasks; | |||||
namespace ModbusDemo.Device | namespace ModbusDemo.Device | ||||
{ | { | ||||
interface IModbusRTU | |||||
public interface IModbusRTU | |||||
{ | { | ||||
public bool[] ReadCoil(byte slaveAddress, ushort startAddress, ushort numberOfPoints); | public bool[] ReadCoil(byte slaveAddress, ushort startAddress, ushort numberOfPoints); | ||||
@@ -17,6 +17,7 @@ namespace ModbusDemo.Device | |||||
private SerialPort _serialPort; | private SerialPort _serialPort; | ||||
//用于操作数据库 | //用于操作数据库 | ||||
private ModbusDbContext _modbusDbContext; | private ModbusDbContext _modbusDbContext; | ||||
public ModbusRTU(SerialPort serialPort, ModbusDbContext modbusDbContext) | public ModbusRTU(SerialPort serialPort, ModbusDbContext modbusDbContext) | ||||
{ | { | ||||
_serialPort = serialPort; | _serialPort = serialPort; | ||||
@@ -9,7 +9,9 @@ namespace ModbusDemo.Model | |||||
{ | { | ||||
public class ModbusDbContext:DbContext | public class ModbusDbContext:DbContext | ||||
{ | { | ||||
protected ModbusDbContext() | |||||
{ | |||||
} | |||||
public ModbusDbContext(DbContextOptions<ModbusDbContext> options) :base(options) | public ModbusDbContext(DbContextOptions<ModbusDbContext> options) :base(options) | ||||
{ | { | ||||
@@ -87,8 +87,8 @@ | |||||
<Button | <Button | ||||
Grid.Column="4" | Grid.Column="4" | ||||
Width="80" | Width="80" | ||||
Height="30" | |||||
materialDesign:ButtonAssist.CornerRadius="15" | |||||
Height="40" | |||||
materialDesign:ButtonAssist.CornerRadius="20" | |||||
Command="{Binding ReadCoilCmm}" | Command="{Binding ReadCoilCmm}" | ||||
Content="读取" | Content="读取" | ||||
Style="{StaticResource MaterialDesignRaisedDarkButton}"> | Style="{StaticResource MaterialDesignRaisedDarkButton}"> | ||||
@@ -140,8 +140,8 @@ | |||||
<Button | <Button | ||||
Grid.Column="4" | Grid.Column="4" | ||||
Width="80" | Width="80" | ||||
Height="30" | |||||
materialDesign:ButtonAssist.CornerRadius="15" | |||||
Height="40" | |||||
materialDesign:ButtonAssist.CornerRadius="20" | |||||
Command="{Binding WriteCoilCmm}" | Command="{Binding WriteCoilCmm}" | ||||
Content="写入" | Content="写入" | ||||
Style="{StaticResource MaterialDesignRaisedDarkButton}"> | Style="{StaticResource MaterialDesignRaisedDarkButton}"> | ||||
@@ -87,8 +87,8 @@ | |||||
<Button | <Button | ||||
Grid.Column="4" | Grid.Column="4" | ||||
Width="80" | Width="80" | ||||
Height="30" | |||||
materialDesign:ButtonAssist.CornerRadius="15" | |||||
Height="40" | |||||
materialDesign:ButtonAssist.CornerRadius="20" | |||||
Command="{Binding ReadRegisterCmm}" | Command="{Binding ReadRegisterCmm}" | ||||
Content="读取" | Content="读取" | ||||
Style="{StaticResource MaterialDesignRaisedDarkButton}"> | Style="{StaticResource MaterialDesignRaisedDarkButton}"> | ||||
@@ -133,15 +133,15 @@ | |||||
Margin="0,-50,0,0" | Margin="0,-50,0,0" | ||||
HorizontalAlignment="Center" | HorizontalAlignment="Center" | ||||
VerticalAlignment="Center" | VerticalAlignment="Center" | ||||
Text="1代表Ture,0代表flase"> | |||||
Text="数据之间加空格"> | |||||
</TextBlock> | </TextBlock> | ||||
<Button | <Button | ||||
Grid.Column="4" | Grid.Column="4" | ||||
Width="80" | Width="80" | ||||
Height="30" | |||||
materialDesign:ButtonAssist.CornerRadius="15" | |||||
Height="40" | |||||
materialDesign:ButtonAssist.CornerRadius="20" | |||||
Command="{Binding WriteRegisterCmm}" | Command="{Binding WriteRegisterCmm}" | ||||
Content="写入" | Content="写入" | ||||
Style="{StaticResource MaterialDesignRaisedDarkButton}"> | Style="{StaticResource MaterialDesignRaisedDarkButton}"> | ||||
@@ -139,18 +139,18 @@ | |||||
</ColumnDefinition> | </ColumnDefinition> | ||||
</Grid.ColumnDefinitions> | </Grid.ColumnDefinitions> | ||||
<Button | <Button | ||||
Width="100" | |||||
Height="50" | |||||
materialDesign:ButtonAssist.CornerRadius="25" | |||||
Width="80" | |||||
Height="40" | |||||
materialDesign:ButtonAssist.CornerRadius="20" | |||||
Style="{StaticResource MaterialDesignRaisedDarkButton}" | Style="{StaticResource MaterialDesignRaisedDarkButton}" | ||||
Content="连接" | Content="连接" | ||||
Command="{Binding ConnectionCmm}"> | Command="{Binding ConnectionCmm}"> | ||||
</Button> | </Button> | ||||
<Button | <Button | ||||
Grid.Column="1" | Grid.Column="1" | ||||
Width="100" | |||||
Height="50" | |||||
materialDesign:ButtonAssist.CornerRadius="25" | |||||
Width="80" | |||||
Height="40" | |||||
materialDesign:ButtonAssist.CornerRadius="20" | |||||
Style="{StaticResource MaterialDesignRaisedDarkButton}" | Style="{StaticResource MaterialDesignRaisedDarkButton}" | ||||
Content="断开" | Content="断开" | ||||
Command="{Binding DisConnectionCmm}"> | Command="{Binding DisConnectionCmm}"> | ||||
@@ -28,20 +28,6 @@ namespace ModbusDemo.VIew | |||||
_ModbusDbContext = ModbusDbContext; | _ModbusDbContext = ModbusDbContext; | ||||
} | } | ||||
private void Button_Click(object sender, RoutedEventArgs e) | |||||
{ | |||||
ModbusLog m = new ModbusLog(); | |||||
m.OperationType = "read"; | |||||
m.ResponseData = "0120"; | |||||
m.RequestData = "8888"; | |||||
_ModbusDbContext.Add(m); | |||||
_ModbusDbContext.SaveChanges(); | |||||
} | |||||
} | } | ||||
} | } |
@@ -32,7 +32,7 @@ namespace ModbusDemo.VIewModel | |||||
{ | { | ||||
get | get | ||||
{ | { | ||||
return "当前链接的状态:" + "串口号:" + _serialPort.PortName + ",波特率:" + _serialPort.BaudRate | |||||
return "当前为读写线圈:" + "串口号:" + _serialPort.PortName + ",波特率:" + _serialPort.BaudRate | |||||
+ ",数据位:" + _serialPort.DataBits + ",校验位:" + _serialPort.Parity + ",停止位:" + _serialPort.StopBits; | + ",数据位:" + _serialPort.DataBits + ",校验位:" + _serialPort.Parity + ",停止位:" + _serialPort.StopBits; | ||||
} | } | ||||
@@ -29,7 +29,7 @@ namespace ModbusDemo.VIewModel | |||||
{ | { | ||||
get | get | ||||
{ | { | ||||
return "当前链接的状态:" + "串口号:" + _serialPort.PortName + ",波特率:" + _serialPort.BaudRate | |||||
return "当前为读写寄存器:" + "串口号:" + _serialPort.PortName + ",波特率:" + _serialPort.BaudRate | |||||
+ ",数据位:" + _serialPort.DataBits + ",校验位:" + _serialPort.Parity + ",停止位:" + _serialPort.StopBits; | + ",数据位:" + _serialPort.DataBits + ",校验位:" + _serialPort.Parity + ",停止位:" + _serialPort.StopBits; | ||||
} | } | ||||
@@ -0,0 +1,141 @@ | |||||
using DryIoc; | |||||
using Microsoft.EntityFrameworkCore; | |||||
using ModbusDemo.Device; | |||||
using ModbusDemo.Model; | |||||
using Moq; | |||||
using Prism.Ioc; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.IO.Ports; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace ModbusTest | |||||
{ | |||||
public class ModbusRTUTest | |||||
{ | |||||
//设计缺陷,应该使用适配器模式重写SerialPort | |||||
private SerialPort _serialport; | |||||
private Mock<ModbusDbContext> _mockDbContext; | |||||
private ModbusRTU _modbusRtu; | |||||
[SetUp] | |||||
public void Setup() | |||||
{ | |||||
_serialport = new SerialPort(); | |||||
_serialport.PortName = "COM3"; | |||||
_serialport.DataBits = 8; | |||||
_serialport.BaudRate = 9600; | |||||
_serialport.Parity = Parity.Even; | |||||
_serialport.StopBits = StopBits.One; | |||||
_serialport.ReadTimeout = 500; | |||||
_serialport.WriteTimeout = 500; | |||||
_serialport.Open(); | |||||
_mockDbContext = new Mock<ModbusDbContext>(); | |||||
_modbusRtu = new ModbusRTU(_serialport, _mockDbContext.Object); | |||||
} | |||||
[TearDown] | |||||
public void TearDown() | |||||
{ | |||||
// 确保在测试结束后释放资源 | |||||
_serialport.Dispose(); | |||||
} | |||||
/// <summary> | |||||
/// 测试线圈读取 | |||||
/// </summary> | |||||
[Test] | |||||
public void ReadCoil1() | |||||
{ | |||||
var result = _modbusRtu.ReadCoil(1, 300, 5); | |||||
// 创建包含5个true的预期数组 | |||||
var expected = new bool[5]; | |||||
Array.Fill(expected, false); | |||||
CollectionAssert.AreEqual(expected, result); | |||||
} | |||||
[Test] | |||||
public void ReadCoil2() | |||||
{ | |||||
var result = _modbusRtu.ReadCoil(1, 305, 5); | |||||
// 创建包含5个flase的预期数组 | |||||
var expected = new bool[5]; | |||||
Array.Fill(expected, true); | |||||
CollectionAssert.AreEqual(expected, result); | |||||
} | |||||
[Test] | |||||
public void WriteCoil1() | |||||
{ | |||||
var data = new bool[5]; | |||||
Array.Fill(data, true); | |||||
_modbusRtu.WriteCoil(1, 310, data); | |||||
// 创建包含5个true的预期数组 | |||||
var expected = _modbusRtu.ReadCoil(1, 310, 5); | |||||
CollectionAssert.AreEqual(data, expected); | |||||
} | |||||
[Test] | |||||
public void WriteCoil2() | |||||
{ | |||||
var data = new bool[5]; | |||||
Array.Fill(data, false); | |||||
_modbusRtu.WriteCoil(1, 315, data); | |||||
// 创建包含5个flase的预期数组 | |||||
var expected = _modbusRtu.ReadCoil(1, 315, 5); | |||||
CollectionAssert.AreEqual(data, expected); | |||||
} | |||||
[Test] | |||||
public void ReadRegister1() | |||||
{ | |||||
ushort[] data = new ushort[5]; | |||||
Array.Fill(data, (ushort)0); | |||||
var expected = _modbusRtu.ReadRegisters(1, 300, 5); | |||||
CollectionAssert.AreEqual(data, expected); | |||||
} | |||||
[Test] | |||||
public void ReadRegister2() | |||||
{ | |||||
ushort[] data = new ushort[5]; | |||||
Array.Fill(data, (ushort)1); | |||||
var expected = _modbusRtu.ReadRegisters(1, 305, 5); | |||||
CollectionAssert.AreEqual(data, expected); | |||||
} | |||||
[Test] | |||||
public void WriteRegister1() | |||||
{ | |||||
ushort[] data = new ushort[5]; | |||||
Array.Fill(data, (ushort)1); | |||||
_modbusRtu.WriteRegisters(1, 310, data); | |||||
var expected = _modbusRtu.ReadRegisters(1, 310, 5); | |||||
CollectionAssert.AreEqual(data, expected); | |||||
} | |||||
[Test] | |||||
public void WriteRegister2() | |||||
{ | |||||
ushort[] data = new ushort[5]; | |||||
Array.Fill(data, (ushort)2); | |||||
_modbusRtu.WriteRegisters(1, 315, data); | |||||
var expected = _modbusRtu.ReadRegisters(1, 315, 5); | |||||
CollectionAssert.AreEqual(data, expected); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,29 @@ | |||||
<Project Sdk="Microsoft.NET.Sdk"> | |||||
<PropertyGroup> | |||||
<TargetFramework>net8.0-windows</TargetFramework> | |||||
<ImplicitUsings>enable</ImplicitUsings> | |||||
<Nullable>enable</Nullable> | |||||
<IsPackable>false</IsPackable> | |||||
<IsTestProject>true</IsTestProject> | |||||
</PropertyGroup> | |||||
<ItemGroup> | |||||
<PackageReference Include="coverlet.collector" Version="6.0.0" /> | |||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" /> | |||||
<PackageReference Include="Moq" Version="4.20.72" /> | |||||
<PackageReference Include="NUnit" Version="3.14.0" /> | |||||
<PackageReference Include="NUnit.Analyzers" Version="3.9.0" /> | |||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<ProjectReference Include="..\ModbusDemo\ModbusDemo.csproj" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<Using Include="NUnit.Framework" /> | |||||
</ItemGroup> | |||||
</Project> |
@@ -0,0 +1,16 @@ | |||||
namespace ModbusTest | |||||
{ | |||||
public class Tests | |||||
{ | |||||
[SetUp] | |||||
public void Setup() | |||||
{ | |||||
} | |||||
[Test] | |||||
public void Test1() | |||||
{ | |||||
Assert.Pass(); | |||||
} | |||||
} | |||||
} |