HJ212 and Documents
This commit is contained in:
@@ -1,30 +1,43 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Modbus.Net.Modbus;
|
||||
using Modbus.Net.Siemens;
|
||||
using AddressUnit = Modbus.Net.AddressUnit<int, int, int>;
|
||||
|
||||
namespace Modbus.Net.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// 基础测试类
|
||||
/// 提供通用的测试初始化和测试方法
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class BaseTest
|
||||
{
|
||||
// 地址单元列表
|
||||
private List<AddressUnit>? _addressUnits;
|
||||
|
||||
// 基础机器实例
|
||||
private BaseMachine<int, int>? _baseMachine;
|
||||
|
||||
// 测试机器 IP 地址
|
||||
private string _machineIp = "10.10.18.251";
|
||||
|
||||
/// <summary>
|
||||
/// 测试初始化方法
|
||||
/// 在每个测试方法执行前运行
|
||||
/// </summary>
|
||||
[TestInitialize]
|
||||
public void Init()
|
||||
{
|
||||
// 初始化地址单元列表,定义要测试的地址
|
||||
_addressUnits = new List<AddressUnit>
|
||||
{
|
||||
// 输入寄存器位测试(3X 区)
|
||||
new AddressUnit
|
||||
{
|
||||
Id = 1,
|
||||
Area = "3X",
|
||||
Address = 1,
|
||||
SubAddress = 0,
|
||||
SubAddress = 0, // 第 0 位
|
||||
DataType = typeof(bool)
|
||||
},
|
||||
new AddressUnit
|
||||
@@ -32,7 +45,7 @@ namespace Modbus.Net.Tests
|
||||
Id = 2,
|
||||
Area = "3X",
|
||||
Address = 1,
|
||||
SubAddress = 1,
|
||||
SubAddress = 1, // 第 1 位
|
||||
DataType = typeof(bool)
|
||||
},
|
||||
new AddressUnit
|
||||
@@ -40,9 +53,10 @@ namespace Modbus.Net.Tests
|
||||
Id = 3,
|
||||
Area = "3X",
|
||||
Address = 1,
|
||||
SubAddress = 2,
|
||||
SubAddress = 2, // 第 2 位
|
||||
DataType = typeof(bool)
|
||||
},
|
||||
// 输入寄存器字节测试
|
||||
new AddressUnit
|
||||
{
|
||||
Id = 4,
|
||||
@@ -56,9 +70,10 @@ namespace Modbus.Net.Tests
|
||||
Id = 5,
|
||||
Area = "3X",
|
||||
Address = 2,
|
||||
SubAddress = 8,
|
||||
SubAddress = 8, // 下一个字节
|
||||
DataType = typeof(byte)
|
||||
},
|
||||
// 输入寄存器字测试
|
||||
new AddressUnit
|
||||
{
|
||||
Id = 6,
|
||||
@@ -107,6 +122,7 @@ namespace Modbus.Net.Tests
|
||||
SubAddress = 0,
|
||||
DataType = typeof(ushort)
|
||||
},
|
||||
// 保持寄存器测试(4X 区)
|
||||
new AddressUnit
|
||||
{
|
||||
Id = 12,
|
||||
@@ -125,178 +141,121 @@ namespace Modbus.Net.Tests
|
||||
},
|
||||
};
|
||||
|
||||
// 创建 Siemens S7-1200 机器实例
|
||||
// 参数:ID, 别名,连接类型,IP 地址,型号,地址列表,保持连接,从站地址,主站地址,src, dst
|
||||
_baseMachine = new SiemensMachine<int, int>(2, "", SiemensType.Tcp, _machineIp, SiemensMachineModel.S7_1200, _addressUnits, true, 2, 0, 1, 0)
|
||||
{
|
||||
ProjectName = "Project 1",
|
||||
MachineName = "Test 2"
|
||||
};
|
||||
|
||||
// 连接设备
|
||||
_baseMachine.ConnectAsync().Wait();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试连续地址组合器
|
||||
/// 验证地址组合器将连续地址合并为一个通信包的功能
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void AddressCombinerContinusTest()
|
||||
{
|
||||
// 创建连续地址组合器,最大长度 100000 字节
|
||||
var addressCombiner = new AddressCombinerContinus<int>(new AddressTranslatorModbus(), 100000);
|
||||
// 组合地址
|
||||
var combinedAddresses = addressCombiner.Combine(_addressUnits!).ToArray();
|
||||
|
||||
// 验证组合结果
|
||||
// 第 1 组:3X 区地址 1,3 个位
|
||||
Assert.AreEqual(combinedAddresses[0].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[0].Address, 1);
|
||||
Assert.AreEqual(combinedAddresses[0].GetCount, 1);
|
||||
|
||||
// 第 2 组:3X 区地址 2-3,6 个字节
|
||||
Assert.AreEqual(combinedAddresses[1].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[1].Address, 2);
|
||||
Assert.AreEqual(combinedAddresses[1].GetCount, 6);
|
||||
|
||||
// 第 3 组:3X 区地址 6-7,2 个寄存器
|
||||
Assert.AreEqual(combinedAddresses[2].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[2].Address, 6);
|
||||
Assert.AreEqual(combinedAddresses[2].GetCount, 2);
|
||||
|
||||
// 第 4 组:3X 区地址 9-10,4 个寄存器
|
||||
Assert.AreEqual(combinedAddresses[3].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[3].Address, 9);
|
||||
Assert.AreEqual(combinedAddresses[3].GetCount, 4);
|
||||
|
||||
// 第 5 组:3X 区地址 100-101,2 个寄存器
|
||||
Assert.AreEqual(combinedAddresses[4].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[4].Address, 100);
|
||||
Assert.AreEqual(combinedAddresses[4].GetCount, 2);
|
||||
|
||||
// 第 6 组:4X 区地址 1-4,4 个寄存器(包含 uint 和 ushort)
|
||||
Assert.AreEqual(combinedAddresses[5].Area, "4X");
|
||||
Assert.AreEqual(combinedAddresses[5].Address, 1);
|
||||
Assert.AreEqual(combinedAddresses[5].GetCount, 4);
|
||||
|
||||
// 第 7 组:4X 区地址 4,2 个寄存器
|
||||
Assert.AreEqual(combinedAddresses[6].Area, "4X");
|
||||
Assert.AreEqual(combinedAddresses[6].Address, 4);
|
||||
Assert.AreEqual(combinedAddresses[6].GetCount, 2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试连续地址组合器的长度限制
|
||||
/// 验证当组合长度超过限制时,地址会被分割
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void AddressCombinerContinusLimitTest()
|
||||
{
|
||||
// 创建连续地址组合器,最大长度 4 字节
|
||||
var addressCombiner = new AddressCombinerContinus<int>(new AddressTranslatorModbus(), 4);
|
||||
// 组合地址
|
||||
var combinedAddresses = addressCombiner.Combine(_addressUnits!).ToArray();
|
||||
|
||||
// 验证组合结果(由于长度限制,地址会被分割)
|
||||
Assert.AreEqual(combinedAddresses[0].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[0].Address, 1);
|
||||
Assert.AreEqual(combinedAddresses[0].GetCount, 1);
|
||||
|
||||
Assert.AreEqual(combinedAddresses[1].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[1].Address, 2);
|
||||
Assert.AreEqual(combinedAddresses[1].GetCount, 4);
|
||||
|
||||
Assert.AreEqual(combinedAddresses[2].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[2].Address, 2);
|
||||
Assert.AreEqual(combinedAddresses[2].GetCount, 2);
|
||||
|
||||
Assert.AreEqual(combinedAddresses[3].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[3].Address, 6);
|
||||
Assert.AreEqual(combinedAddresses[3].GetCount, 2);
|
||||
|
||||
Assert.AreEqual(combinedAddresses[4].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[4].Address, 9);
|
||||
Assert.AreEqual(combinedAddresses[4].GetCount, 4);
|
||||
|
||||
Assert.AreEqual(combinedAddresses[5].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[5].Address, 100);
|
||||
Assert.AreEqual(combinedAddresses[5].GetCount, 2);
|
||||
|
||||
Assert.AreEqual(combinedAddresses[6].Area, "4X");
|
||||
Assert.AreEqual(combinedAddresses[6].Address, 1);
|
||||
Assert.AreEqual(combinedAddresses[6].GetCount, 4);
|
||||
|
||||
Assert.AreEqual(combinedAddresses[7].Area, "4X");
|
||||
Assert.AreEqual(combinedAddresses[7].Address, 4);
|
||||
Assert.AreEqual(combinedAddresses[7].GetCount, 2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试单个地址组合器
|
||||
/// 验证每个地址单独通信的组合器
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void AddressCombinerSingleTest()
|
||||
{
|
||||
// 创建单个地址组合器
|
||||
var addressCombiner = new AddressCombinerSingle<int, int, int>();
|
||||
// 组合地址
|
||||
var combinedAddresses = addressCombiner.Combine(_addressUnits!).ToArray();
|
||||
Assert.AreEqual(combinedAddresses[0].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[0].Address, 1);
|
||||
Assert.AreEqual(combinedAddresses[0].GetCount, 1);
|
||||
Assert.AreEqual(combinedAddresses[1].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[1].Address, 1);
|
||||
Assert.AreEqual(combinedAddresses[1].SubAddress, 1);
|
||||
Assert.AreEqual(combinedAddresses[1].GetCount, 1);
|
||||
Assert.AreEqual(combinedAddresses[3].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[3].Address, 2);
|
||||
Assert.AreEqual(combinedAddresses[3].GetCount, 1);
|
||||
Assert.AreEqual(combinedAddresses[4].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[4].Address, 2);
|
||||
Assert.AreEqual(combinedAddresses[4].SubAddress, 8);
|
||||
Assert.AreEqual(combinedAddresses[4].GetCount, 1);
|
||||
Assert.AreEqual(combinedAddresses[11].Area, "4X");
|
||||
Assert.AreEqual(combinedAddresses[11].Address, 1);
|
||||
Assert.AreEqual(combinedAddresses[11].GetCount, 1);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AddressCombinerNumericJumpTest()
|
||||
{
|
||||
var addressCombiner = new AddressCombinerNumericJump<int>(10, 100000, new AddressTranslatorModbus());
|
||||
var combinedAddresses = addressCombiner.Combine(_addressUnits!).ToArray();
|
||||
Assert.AreEqual(combinedAddresses[0].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[0].Address, 1);
|
||||
Assert.AreEqual(combinedAddresses[0].GetCount, 20);
|
||||
Assert.AreEqual(combinedAddresses[1].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[1].Address, 100);
|
||||
Assert.AreEqual(combinedAddresses[1].GetCount, 2);
|
||||
Assert.AreEqual(combinedAddresses[2].Area, "4X");
|
||||
Assert.AreEqual(combinedAddresses[2].Address, 1);
|
||||
Assert.AreEqual(combinedAddresses[2].GetCount, 8);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AddressCombinerNumericJumpLimitTest()
|
||||
{
|
||||
var addressCombiner = new AddressCombinerNumericJump<int>(10, 10, new AddressTranslatorModbus());
|
||||
var combinedAddresses = addressCombiner.Combine(_addressUnits!).ToArray();
|
||||
Assert.AreEqual(combinedAddresses[0].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[0].Address, 1);
|
||||
Assert.AreEqual(combinedAddresses[0].GetCount, 8);
|
||||
Assert.AreEqual(combinedAddresses[1].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[1].Address, 6);
|
||||
Assert.AreEqual(combinedAddresses[1].GetCount, 10);
|
||||
Assert.AreEqual(combinedAddresses[2].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[2].Address, 100);
|
||||
Assert.AreEqual(combinedAddresses[2].GetCount, 2);
|
||||
Assert.AreEqual(combinedAddresses[3].Area, "4X");
|
||||
Assert.AreEqual(combinedAddresses[3].Address, 1);
|
||||
Assert.AreEqual(combinedAddresses[3].GetCount, 8);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AddressCombinerPercentageJumpTest()
|
||||
{
|
||||
var addressCombiner = new AddressCombinerPercentageJump<int>(30.0, 100000, new AddressTranslatorModbus());
|
||||
var combinedAddresses = addressCombiner.Combine(_addressUnits!).ToArray();
|
||||
Assert.AreEqual(combinedAddresses[0].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[0].Address, 1);
|
||||
Assert.AreEqual(combinedAddresses[0].GetCount, 12);
|
||||
Assert.AreEqual(combinedAddresses[1].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[1].Address, 9);
|
||||
Assert.AreEqual(combinedAddresses[1].GetCount, 4);
|
||||
Assert.AreEqual(combinedAddresses[2].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[2].Address, 100);
|
||||
Assert.AreEqual(combinedAddresses[2].GetCount, 2);
|
||||
Assert.AreEqual(combinedAddresses[3].Area, "4X");
|
||||
Assert.AreEqual(combinedAddresses[3].Address, 1);
|
||||
Assert.AreEqual(combinedAddresses[3].GetCount, 8);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AddressCombinerPercentageJumpLimitTest()
|
||||
{
|
||||
var addressCombiner = new AddressCombinerPercentageJump<int>(30.0, 10, new AddressTranslatorModbus());
|
||||
var combinedAddresses = addressCombiner.Combine(_addressUnits!).ToArray();
|
||||
Assert.AreEqual(combinedAddresses[0].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[0].Address, 1);
|
||||
Assert.AreEqual(combinedAddresses[0].GetCount, 8);
|
||||
Assert.AreEqual(combinedAddresses[1].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[1].Address, 6);
|
||||
Assert.AreEqual(combinedAddresses[1].GetCount, 2);
|
||||
Assert.AreEqual(combinedAddresses[2].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[2].Address, 9);
|
||||
Assert.AreEqual(combinedAddresses[2].GetCount, 4);
|
||||
Assert.AreEqual(combinedAddresses[3].Area, "3X");
|
||||
Assert.AreEqual(combinedAddresses[3].Address, 100);
|
||||
Assert.AreEqual(combinedAddresses[3].GetCount, 2);
|
||||
Assert.AreEqual(combinedAddresses[4].Area, "4X");
|
||||
Assert.AreEqual(combinedAddresses[4].Address, 1);
|
||||
Assert.AreEqual(combinedAddresses[4].GetCount, 8);
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void MachineClean()
|
||||
{
|
||||
_baseMachine?.Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,49 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Modbus.Net.Modbus;
|
||||
using AddressUnit = Modbus.Net.AddressUnit<string, int, int>;
|
||||
|
||||
namespace Modbus.Net.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// 字节序测试类
|
||||
/// 测试 Modbus 大端和小端字节序的读写差异
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class EndianTest
|
||||
{
|
||||
// Modbus TCP 机器实例(大端)
|
||||
private BaseMachine<string, string>? _modbusTcpMachine;
|
||||
|
||||
// Modbus TCP 机器实例(小端)
|
||||
private BaseMachine<string, string>? _modbusTcpMachine2;
|
||||
|
||||
// 测试机器 IP 地址
|
||||
private string _machineIp = "10.10.18.251";
|
||||
|
||||
/// <summary>
|
||||
/// 测试初始化方法
|
||||
/// 创建大端和小端两种字节序的 Modbus TCP 机器实例
|
||||
/// </summary>
|
||||
[TestInitialize]
|
||||
public void Init()
|
||||
{
|
||||
_modbusTcpMachine = new ModbusMachine<string, string>("1", "",ModbusType.Tcp, _machineIp, null, true, 1, 0, Endian.BigEndianLsb);
|
||||
// 创建大端字节序的 Modbus TCP 机器
|
||||
_modbusTcpMachine = new ModbusMachine<string, string>("1", "", ModbusType.Tcp, _machineIp, null, true, 1, 0, Endian.BigEndianLsb);
|
||||
|
||||
// 创建小端字节序的 Modbus TCP 机器
|
||||
_modbusTcpMachine2 = new ModbusMachine<string, string>("2", "", ModbusType.Tcp, _machineIp, null, true, 1, 0, Endian.LittleEndianLsb);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试 Modbus 字节序
|
||||
/// 验证大端和小端字节序对同一数据的读写差异
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task ModbusEndianSingle()
|
||||
{
|
||||
Random r = new Random();
|
||||
|
||||
// 定义地址单元
|
||||
var addresses = new List<AddressUnit>
|
||||
{
|
||||
new AddressUnit
|
||||
@@ -39,6 +57,7 @@ namespace Modbus.Net.Tests
|
||||
}
|
||||
};
|
||||
|
||||
// 生成随机值
|
||||
var dic1 = new Dictionary<string, double>()
|
||||
{
|
||||
{
|
||||
@@ -46,13 +65,26 @@ namespace Modbus.Net.Tests
|
||||
}
|
||||
};
|
||||
|
||||
// 设置两种字节序机器的地址列表
|
||||
_modbusTcpMachine!.GetAddresses = addresses;
|
||||
_modbusTcpMachine2!.GetAddresses = addresses;
|
||||
|
||||
// 使用大端字节序写入数据
|
||||
await _modbusTcpMachine.SetDatasAsync(MachineDataType.Address, dic1);
|
||||
|
||||
// 使用大端字节序读取数据
|
||||
var ans = await _modbusTcpMachine.GetDatasAsync(MachineDataType.Address);
|
||||
_modbusTcpMachine.Disconnect();
|
||||
|
||||
// 使用小端字节序读取同一数据
|
||||
var ans2 = await _modbusTcpMachine2.GetDatasAsync(MachineDataType.Address);
|
||||
|
||||
// 验证大端读取的值与写入的值一致
|
||||
Assert.AreEqual(ans.Datas["4X 1.0"].DeviceValue, dic1["4X 1"]);
|
||||
|
||||
// 验证小端读取的值是字节交换后的值
|
||||
// 例如:0x1234 在大端是 [0x12, 0x34],在小端会被解读为 [0x34, 0x12] = 0x3412
|
||||
// 计算公式:低字节*256 + 高字节
|
||||
Assert.AreEqual(ans2.Datas["4X 1.0"].DeviceValue, (ushort)dic1["4X 1"] % 256 * 256 + (ushort)dic1["4X 1"] / 256);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,42 +1,83 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Modbus.Net.Modbus;
|
||||
using System.Reflection;
|
||||
using AddressUnit = Modbus.Net.AddressUnit<int, int, int>;
|
||||
|
||||
namespace Modbus.Net.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// 机器方法测试类
|
||||
/// 测试 Machine 层的反射调用和 Utility 层的直接调用
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class MachineMethodTest
|
||||
{
|
||||
// 测试机器 IP 地址
|
||||
private string _machineIp = "10.10.18.251";
|
||||
|
||||
/// <summary>
|
||||
/// 测试获取 Utility 方法
|
||||
/// 验证可以通过反射获取 Utility 的读写方法
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void GetUtility()
|
||||
{
|
||||
// 创建 Modbus TCP 机器实例
|
||||
BaseMachine<int, int> baseMachine = new ModbusMachine<int, int>(1, "", ModbusType.Tcp, _machineIp, null, true, 2, 0, Endian.BigEndianLsb);
|
||||
|
||||
// 获取 Utility 方法接口
|
||||
var utility = baseMachine.GetUtilityMethods<IUtilityMethodDatas>();
|
||||
|
||||
// 通过反射获取方法列表
|
||||
var methods = utility.GetType().GetRuntimeMethods();
|
||||
|
||||
// 验证 GetDatasAsync 方法存在
|
||||
Assert.AreEqual(methods.FirstOrDefault(method => method.Name == "GetDatasAsync") != null, true);
|
||||
|
||||
// 验证 SetDatasAsync 方法存在
|
||||
Assert.AreEqual(methods.FirstOrDefault(method => method.Name == "SetDatasAsync") != null, true);
|
||||
|
||||
// 断开连接
|
||||
baseMachine.Disconnect();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试调用 Utility 方法
|
||||
/// 验证可以直接调用 Utility 的底层读写方法
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task InvokeUtility()
|
||||
{
|
||||
// 创建 Modbus TCP 机器实例
|
||||
BaseMachine<int, int> baseMachine = new ModbusMachine<int, int>(1, "", ModbusType.Tcp, _machineIp, null, true, 2, 0, Endian.BigEndianLsb);
|
||||
|
||||
// 连接 Utility
|
||||
await baseMachine.BaseUtility.ConnectAsync();
|
||||
|
||||
// 使用 Utility 方法写入数据(字节级 API)
|
||||
// 地址格式:"4X 1" = 保持寄存器区地址 1
|
||||
// 写入值:byte 类型的 11
|
||||
var success = await baseMachine.BaseUtility.GetUtilityMethods<IUtilityMethodDatas>().SetDatasAsync("4X 1", new object[] { (byte)11 }, 1);
|
||||
Assert.AreEqual(success.IsSuccess, true);
|
||||
|
||||
// 使用 Utility 方法读取数据
|
||||
// 读取 1 个字节
|
||||
var datas = await baseMachine.BaseUtility.GetUtilityMethods<IUtilityMethodDatas>().GetDatasAsync("4X 1", 1, 1);
|
||||
Assert.AreEqual(datas.Datas[0], 11);
|
||||
|
||||
// 断开连接
|
||||
baseMachine.Disconnect();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试调用 Machine 方法
|
||||
/// 验证可以调用 Machine 层的高级读写方法
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task InvokeMachine()
|
||||
{
|
||||
BaseMachine<int, int> baseMachine = new ModbusMachine<int, int>(1, "",ModbusType.Tcp, _machineIp, new List<AddressUnit>
|
||||
// 创建 Modbus TCP 机器实例,带地址配置
|
||||
BaseMachine<int, int> baseMachine = new ModbusMachine<int, int>(1, "", ModbusType.Tcp, _machineIp, new List<AddressUnit>
|
||||
{
|
||||
new AddressUnit
|
||||
{
|
||||
@@ -48,26 +89,35 @@ namespace Modbus.Net.Tests
|
||||
DataType = typeof(bool)
|
||||
}
|
||||
}, true, 2, 0, Endian.BigEndianLsb);
|
||||
|
||||
// 使用 Machine 方法写入数据(高级 API)
|
||||
// 按地址写入线圈状态
|
||||
var success = await baseMachine.GetMachineMethods<IMachineMethodDatas>().SetDatasAsync(
|
||||
MachineDataType.Address,
|
||||
new Dictionary<string, double>
|
||||
{
|
||||
{
|
||||
"0X 1.0", 1
|
||||
"0X 1.0", 1 // 线圈 0X 1.0 设置为 ON
|
||||
}
|
||||
});
|
||||
Assert.AreEqual(success.IsSuccess, true);
|
||||
|
||||
// 使用 Machine 方法读取数据
|
||||
var datas = await baseMachine.GetMachineMethods<IMachineMethodDatas>().GetDatasAsync(MachineDataType.Address);
|
||||
Assert.AreEqual(datas.Datas["0X 1.0"].DeviceValue, 1);
|
||||
|
||||
// 写入 OFF
|
||||
success = await baseMachine.GetMachineMethods<IMachineMethodDatas>().SetDatasAsync(
|
||||
MachineDataType.Address,
|
||||
new Dictionary<string, double>
|
||||
{
|
||||
{
|
||||
"0X 1.0", 0
|
||||
"0X 1.0", 0 // 线圈 0X 1.0 设置为 OFF
|
||||
}
|
||||
});
|
||||
Assert.AreEqual(success.IsSuccess, true);
|
||||
|
||||
// 断开连接
|
||||
baseMachine.Disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,47 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Modbus.Net.Modbus;
|
||||
using AddressUnit = Modbus.Net.AddressUnit<string, int, int>;
|
||||
|
||||
namespace Modbus.Net.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Modbus 多从站测试类
|
||||
/// 测试在同一串口上访问多个 Modbus RTU 从站
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class ModbusMultiStationTest
|
||||
{
|
||||
// Modbus RTU 机器实例(从站 1)
|
||||
private BaseMachine<string, string>? _modbusRtuMachine1;
|
||||
|
||||
// Modbus RTU 机器实例(从站 2)
|
||||
private BaseMachine<string, string>? _modbusRtuMachine2;
|
||||
|
||||
// 测试串口
|
||||
private string _machineCom = "COM1";
|
||||
|
||||
/// <summary>
|
||||
/// 测试初始化方法
|
||||
/// 创建两个不同从站地址的 Modbus RTU 机器实例
|
||||
/// </summary>
|
||||
[TestInitialize]
|
||||
public void Init()
|
||||
{
|
||||
// 创建从站地址为 1 的 Modbus RTU 机器
|
||||
_modbusRtuMachine1 = new ModbusMachine<string, string>("1", "", ModbusType.Rtu, _machineCom, null, true, 1, 0, Endian.BigEndianLsb);
|
||||
|
||||
// 创建从站地址为 2 的 Modbus RTU 机器
|
||||
_modbusRtuMachine2 = new ModbusMachine<string, string>("2", "", ModbusType.Rtu, _machineCom, null, true, 2, 0, Endian.BigEndianLsb);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试多从站读写
|
||||
/// 验证在同一串口上可以分别访问不同从站地址的设备
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task MultiStation()
|
||||
{
|
||||
// 定义地址单元列表
|
||||
var addresses = new List<AddressUnit>
|
||||
{
|
||||
new AddressUnit
|
||||
@@ -81,63 +100,47 @@ namespace Modbus.Net.Tests
|
||||
}
|
||||
};
|
||||
|
||||
// 设置两个从站的地址列表
|
||||
_modbusRtuMachine1!.GetAddresses = addresses.ToList();
|
||||
_modbusRtuMachine2!.GetAddresses = addresses.ToList();
|
||||
|
||||
Random r = new Random();
|
||||
|
||||
// 生成从站 1 的随机数据
|
||||
var dic1 = new Dictionary<string, double>()
|
||||
{
|
||||
{
|
||||
"A1", r.Next(0, UInt16.MaxValue)
|
||||
},
|
||||
{
|
||||
"A2", r.Next(0, UInt16.MaxValue)
|
||||
},
|
||||
{
|
||||
"A3", r.Next(0, UInt16.MaxValue)
|
||||
},
|
||||
{
|
||||
"A4", r.Next(0, UInt16.MaxValue)
|
||||
},
|
||||
{
|
||||
"A5", r.Next()
|
||||
},
|
||||
{
|
||||
"A6", r.Next()
|
||||
},
|
||||
{ "A1", r.Next(0, UInt16.MaxValue) },
|
||||
{ "A2", r.Next(0, UInt16.MaxValue) },
|
||||
{ "A3", r.Next(0, UInt16.MaxValue) },
|
||||
{ "A4", r.Next(0, UInt16.MaxValue) },
|
||||
{ "A5", r.Next() }, // uint 类型
|
||||
{ "A6", r.Next() } // uint 类型
|
||||
};
|
||||
|
||||
// 生成从站 2 的随机数据
|
||||
var dic2 = new Dictionary<string, double>()
|
||||
{
|
||||
{
|
||||
"A1", r.Next(0, UInt16.MaxValue)
|
||||
},
|
||||
{
|
||||
"A2", r.Next(0, UInt16.MaxValue)
|
||||
},
|
||||
{
|
||||
"A3", r.Next(0, UInt16.MaxValue)
|
||||
},
|
||||
{
|
||||
"A4", r.Next(0, UInt16.MaxValue)
|
||||
},
|
||||
{
|
||||
"A5", r.Next()
|
||||
},
|
||||
{
|
||||
"A6", r.Next()
|
||||
},
|
||||
{ "A1", r.Next(0, UInt16.MaxValue) },
|
||||
{ "A2", r.Next(0, UInt16.MaxValue) },
|
||||
{ "A3", r.Next(0, UInt16.MaxValue) },
|
||||
{ "A4", r.Next(0, UInt16.MaxValue) },
|
||||
{ "A5", r.Next() },
|
||||
{ "A6", r.Next() }
|
||||
};
|
||||
|
||||
// 分别向两个从站写入不同的数据
|
||||
await _modbusRtuMachine1.SetDatasAsync(MachineDataType.CommunicationTag, dic1);
|
||||
await _modbusRtuMachine2.SetDatasAsync(MachineDataType.CommunicationTag, dic2);
|
||||
|
||||
// 分别从两个从站读取数据
|
||||
var ans = await _modbusRtuMachine1.GetDatasAsync(MachineDataType.CommunicationTag);
|
||||
var ans2 = await _modbusRtuMachine2.GetDatasAsync(MachineDataType.CommunicationTag);
|
||||
|
||||
// 断开连接
|
||||
_modbusRtuMachine1.Disconnect();
|
||||
_modbusRtuMachine2.Disconnect();
|
||||
|
||||
// 验证从站 1 读取的数据与写入的一致
|
||||
Assert.AreEqual(ans.Datas["A1"].DeviceValue, dic1["A1"]);
|
||||
Assert.AreEqual(ans2.Datas["A1"].DeviceValue, dic2["A1"]);
|
||||
Assert.AreEqual(ans.Datas["A2"].DeviceValue, dic1["A2"]);
|
||||
|
||||
@@ -1,39 +1,61 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Modbus.Net.Modbus;
|
||||
using AddressUnit = Modbus.Net.AddressUnit<string, int, int>;
|
||||
|
||||
namespace Modbus.Net.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Modbus 协议测试类
|
||||
/// 测试 Modbus TCP/RTU/ASCII 三种协议的读写功能
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class ModbusTest
|
||||
{
|
||||
// Modbus TCP 机器实例
|
||||
private BaseMachine<string, string>? _modbusTcpMachine;
|
||||
|
||||
// Modbus RTU 机器实例
|
||||
private BaseMachine<string, string>? _modbusRtuMachine;
|
||||
|
||||
// Modbus ASCII 机器实例
|
||||
private BaseMachine<string, string>? _modbusAsciiMachine;
|
||||
|
||||
// 测试机器 IP 地址
|
||||
private string _machineIp = "10.10.18.251";
|
||||
|
||||
// 测试串口 1
|
||||
private string _machineCom = "COM1";
|
||||
|
||||
// 测试串口 2
|
||||
private string _machineCom2 = "COM3";
|
||||
|
||||
/// <summary>
|
||||
/// 测试初始化方法
|
||||
/// 在每个测试方法执行前运行
|
||||
/// </summary>
|
||||
[TestInitialize]
|
||||
public void Init()
|
||||
{
|
||||
// 创建 Modbus TCP 机器实例
|
||||
_modbusTcpMachine = new ModbusMachine<string, string>("1", "", ModbusType.Tcp, _machineIp, null, true, 2, 0, Endian.BigEndianLsb);
|
||||
|
||||
// 创建 Modbus RTU 机器实例
|
||||
_modbusRtuMachine = new ModbusMachine<string, string>("2", "", ModbusType.Rtu, _machineCom, null, true, 2, 0, Endian.BigEndianLsb);
|
||||
|
||||
// 创建 Modbus ASCII 机器实例
|
||||
_modbusAsciiMachine = new ModbusMachine<string, string>("3", "", ModbusType.Ascii, _machineCom2, null, true, 2, 0, Endian.BigEndianLsb);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试单个线圈读写
|
||||
/// 验证 Modbus TCP/RTU/ASCII 三种协议的线圈(0X 区)读写功能
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task ModbusCoilSingle()
|
||||
{
|
||||
Random r = new Random();
|
||||
|
||||
// 定义地址单元
|
||||
var addresses = new List<AddressUnit>
|
||||
{
|
||||
new AddressUnit
|
||||
@@ -47,6 +69,7 @@ namespace Modbus.Net.Tests
|
||||
}
|
||||
};
|
||||
|
||||
// 生成随机值(0 或 1)
|
||||
var dic1 = new Dictionary<string, double>()
|
||||
{
|
||||
{
|
||||
@@ -54,23 +77,36 @@ namespace Modbus.Net.Tests
|
||||
}
|
||||
};
|
||||
|
||||
// 设置三种协议的地址列表
|
||||
_modbusTcpMachine!.GetAddresses = addresses;
|
||||
_modbusAsciiMachine!.GetAddresses = addresses;
|
||||
_modbusRtuMachine!.GetAddresses = addresses;
|
||||
|
||||
// 分别通过三种协议写入数据
|
||||
await _modbusTcpMachine.SetDatasAsync(MachineDataType.Address, dic1);
|
||||
await _modbusAsciiMachine.SetDatasAsync(MachineDataType.Address, dic1);
|
||||
await _modbusRtuMachine.SetDatasAsync(MachineDataType.Address, dic1);
|
||||
|
||||
// 分别通过三种协议读取数据
|
||||
var ans = await _modbusTcpMachine.GetDatasAsync(MachineDataType.Address);
|
||||
var ans2 = await _modbusRtuMachine.GetDatasAsync(MachineDataType.Address);
|
||||
var ans3 = await _modbusAsciiMachine.GetDatasAsync(MachineDataType.Address);
|
||||
|
||||
// 验证三种协议读取的值与写入的值一致
|
||||
Assert.AreEqual(ans.Datas?["0X 1.0"].DeviceValue, dic1["0X 1.0"]);
|
||||
Assert.AreEqual(ans2.Datas?["0X 1.0"].DeviceValue, dic1["0X 1.0"]);
|
||||
Assert.AreEqual(ans3.Datas?["0X 1.0"].DeviceValue, dic1["0X 1.0"]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试单个离散输入读取
|
||||
/// 验证 Modbus TCP/RTU/ASCII 三种协议的离散输入(1X 区)读取功能
|
||||
/// 离散输入为只读
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task ModbusDInputSingle()
|
||||
{
|
||||
// 定义地址单元
|
||||
var addresses = new List<AddressUnit>
|
||||
{
|
||||
new AddressUnit
|
||||
@@ -84,20 +120,31 @@ namespace Modbus.Net.Tests
|
||||
}
|
||||
};
|
||||
|
||||
// 设置三种协议的地址列表
|
||||
_modbusTcpMachine!.GetAddresses = addresses;
|
||||
_modbusRtuMachine!.GetAddresses = addresses;
|
||||
_modbusAsciiMachine!.GetAddresses = addresses;
|
||||
|
||||
// 分别通过三种协议读取数据
|
||||
var ans = await _modbusTcpMachine.GetDatasAsync(MachineDataType.Address);
|
||||
var ans2 = await _modbusRtuMachine.GetDatasAsync(MachineDataType.Address);
|
||||
var ans3 = await _modbusAsciiMachine.GetDatasAsync(MachineDataType.Address);
|
||||
|
||||
// 验证三种协议读取的值都为 0(默认值)
|
||||
Assert.AreEqual(ans.Datas?["1X 1.0"].DeviceValue, 0);
|
||||
Assert.AreEqual(ans2.Datas?["1X 1.0"].DeviceValue, 0);
|
||||
Assert.AreEqual(ans3.Datas?["1X 1.0"].DeviceValue, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试单个输入寄存器读取
|
||||
/// 验证 Modbus TCP/RTU/ASCII 三种协议的输入寄存器(3X 区)读取功能
|
||||
/// 输入寄存器为只读
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task ModbusIRegSingle()
|
||||
{
|
||||
// 定义地址单元
|
||||
var addresses = new List<AddressUnit>
|
||||
{
|
||||
new AddressUnit
|
||||
@@ -111,22 +158,32 @@ namespace Modbus.Net.Tests
|
||||
}
|
||||
};
|
||||
|
||||
// 设置三种协议的地址列表
|
||||
_modbusTcpMachine!.GetAddresses = addresses;
|
||||
_modbusRtuMachine!.GetAddresses = addresses;
|
||||
_modbusAsciiMachine!.GetAddresses = addresses;
|
||||
|
||||
// 分别通过三种协议读取数据
|
||||
var ans = await _modbusTcpMachine.GetDatasAsync(MachineDataType.Address);
|
||||
var ans2 = await _modbusRtuMachine.GetDatasAsync(MachineDataType.Address);
|
||||
var ans3 = await _modbusAsciiMachine.GetDatasAsync(MachineDataType.Address);
|
||||
|
||||
// 验证三种协议读取的值都为 0(默认值)
|
||||
Assert.AreEqual(ans.Datas?["3X 1.0"].DeviceValue, 0);
|
||||
Assert.AreEqual(ans2.Datas?["3X 1.0"].DeviceValue, 0);
|
||||
Assert.AreEqual(ans3.Datas?["3X 1.0"].DeviceValue, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试单个保持寄存器读写
|
||||
/// 验证 Modbus TCP/RTU/ASCII 三种协议的保持寄存器(4X 区)读写功能
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task ModbusRegSingle()
|
||||
{
|
||||
Random r = new Random();
|
||||
|
||||
// 定义地址单元
|
||||
var addresses = new List<AddressUnit>
|
||||
{
|
||||
new AddressUnit
|
||||
@@ -140,6 +197,7 @@ namespace Modbus.Net.Tests
|
||||
}
|
||||
};
|
||||
|
||||
// 生成随机值(0 到 UInt16.MaxValue)
|
||||
var dic1 = new Dictionary<string, double>()
|
||||
{
|
||||
{
|
||||
@@ -147,25 +205,37 @@ namespace Modbus.Net.Tests
|
||||
}
|
||||
};
|
||||
|
||||
// 设置三种协议的地址列表
|
||||
_modbusTcpMachine!.GetAddresses = addresses;
|
||||
_modbusAsciiMachine!.GetAddresses = addresses;
|
||||
_modbusRtuMachine!.GetAddresses = addresses;
|
||||
|
||||
// 分别通过三种协议写入数据
|
||||
await _modbusTcpMachine.SetDatasAsync(MachineDataType.Address, dic1);
|
||||
await _modbusAsciiMachine.SetDatasAsync(MachineDataType.Address, dic1);
|
||||
await _modbusRtuMachine.SetDatasAsync(MachineDataType.Address, dic1);
|
||||
|
||||
// 分别通过三种协议读取数据
|
||||
var ans = await _modbusTcpMachine.GetDatasAsync(MachineDataType.Address);
|
||||
var ans2 = await _modbusRtuMachine.GetDatasAsync(MachineDataType.Address);
|
||||
var ans3 = await _modbusAsciiMachine.GetDatasAsync(MachineDataType.Address);
|
||||
|
||||
// 验证三种协议读取的值与写入的值一致
|
||||
Assert.AreEqual(ans.Datas?["4X 1.0"].DeviceValue, dic1["4X 1"]);
|
||||
Assert.AreEqual(ans2.Datas?["4X 1.0"].DeviceValue, dic1["4X 1"]);
|
||||
Assert.AreEqual(ans3.Datas?["4X 1.0"].DeviceValue, dic1["4X 1"]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试多个保持寄存器读写
|
||||
/// 验证 Modbus TCP/RTU/ASCII 三种协议的多个保持寄存器(4X 区)批量读写功能
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task ModbusRegMultiple()
|
||||
{
|
||||
Random r = new Random();
|
||||
|
||||
// 定义多个地址单元
|
||||
var addresses = new List<AddressUnit>
|
||||
{
|
||||
new AddressUnit
|
||||
@@ -203,87 +273,48 @@ namespace Modbus.Net.Tests
|
||||
SubAddress = 0,
|
||||
CommunicationTag = "A4",
|
||||
DataType = typeof(ushort)
|
||||
},
|
||||
new AddressUnit
|
||||
{
|
||||
Id = "4",
|
||||
Area = "4X",
|
||||
Address = 6,
|
||||
SubAddress = 0,
|
||||
CommunicationTag = "A5",
|
||||
DataType = typeof(uint)
|
||||
},
|
||||
new AddressUnit
|
||||
{
|
||||
Id = "5",
|
||||
Area = "4X",
|
||||
Address = 8,
|
||||
SubAddress = 0,
|
||||
CommunicationTag = "A6",
|
||||
DataType = typeof(uint)
|
||||
}
|
||||
};
|
||||
|
||||
// 生成随机值
|
||||
var dic1 = new Dictionary<string, double>()
|
||||
{
|
||||
{
|
||||
"A1", r.Next(0, UInt16.MaxValue)
|
||||
},
|
||||
{
|
||||
"A2", r.Next(0, UInt16.MaxValue)
|
||||
},
|
||||
{
|
||||
"A3", r.Next(0, UInt16.MaxValue)
|
||||
},
|
||||
{
|
||||
"A4", r.Next(0, UInt16.MaxValue)
|
||||
},
|
||||
{
|
||||
"A5", r.Next()
|
||||
},
|
||||
{
|
||||
"A6", r.Next()
|
||||
},
|
||||
{ "4X 2", r.Next(0, UInt16.MaxValue) },
|
||||
{ "4X 3", r.Next(0, UInt16.MaxValue) },
|
||||
{ "4X 4", r.Next(0, UInt16.MaxValue) },
|
||||
{ "4X 5", r.Next(0, UInt16.MaxValue) }
|
||||
};
|
||||
|
||||
// 设置三种协议的地址列表
|
||||
_modbusTcpMachine!.GetAddresses = addresses;
|
||||
_modbusRtuMachine!.GetAddresses = addresses;
|
||||
_modbusAsciiMachine!.GetAddresses = addresses;
|
||||
await _modbusTcpMachine.SetDatasAsync(MachineDataType.CommunicationTag, dic1);
|
||||
await _modbusRtuMachine.SetDatasAsync(MachineDataType.CommunicationTag, dic1);
|
||||
await _modbusAsciiMachine.SetDatasAsync(MachineDataType.CommunicationTag, dic1);
|
||||
|
||||
var ans = await _modbusTcpMachine.GetDatasAsync(MachineDataType.CommunicationTag);
|
||||
var ans2 = await _modbusRtuMachine.GetDatasAsync(MachineDataType.CommunicationTag);
|
||||
var ans3 = await _modbusAsciiMachine.GetDatasAsync(MachineDataType.CommunicationTag);
|
||||
|
||||
Assert.AreEqual(ans.Datas?["A1"].DeviceValue, dic1["A1"]);
|
||||
Assert.AreEqual(ans.Datas?["A2"].DeviceValue, dic1["A2"]);
|
||||
Assert.AreEqual(ans.Datas?["A3"].DeviceValue, dic1["A3"]);
|
||||
Assert.AreEqual(ans.Datas?["A4"].DeviceValue, dic1["A4"]);
|
||||
Assert.AreEqual(ans.Datas?["A5"].DeviceValue, dic1["A5"]);
|
||||
Assert.AreEqual(ans.Datas?["A6"].DeviceValue, dic1["A6"]);
|
||||
Assert.AreEqual(ans2.Datas?["A1"].DeviceValue, dic1["A1"]);
|
||||
Assert.AreEqual(ans2.Datas?["A2"].DeviceValue, dic1["A2"]);
|
||||
Assert.AreEqual(ans2.Datas?["A3"].DeviceValue, dic1["A3"]);
|
||||
Assert.AreEqual(ans2.Datas?["A4"].DeviceValue, dic1["A4"]);
|
||||
Assert.AreEqual(ans2.Datas?["A5"].DeviceValue, dic1["A5"]);
|
||||
Assert.AreEqual(ans2.Datas?["A6"].DeviceValue, dic1["A6"]);
|
||||
Assert.AreEqual(ans3.Datas?["A1"].DeviceValue, dic1["A1"]);
|
||||
Assert.AreEqual(ans3.Datas?["A2"].DeviceValue, dic1["A2"]);
|
||||
Assert.AreEqual(ans3.Datas?["A3"].DeviceValue, dic1["A3"]);
|
||||
Assert.AreEqual(ans3.Datas?["A4"].DeviceValue, dic1["A4"]);
|
||||
Assert.AreEqual(ans3.Datas?["A5"].DeviceValue, dic1["A5"]);
|
||||
Assert.AreEqual(ans3.Datas?["A6"].DeviceValue, dic1["A6"]);
|
||||
}
|
||||
|
||||
|
||||
[TestCleanup]
|
||||
public void MachineClean()
|
||||
{
|
||||
_modbusAsciiMachine!.Disconnect();
|
||||
_modbusRtuMachine!.Disconnect();
|
||||
_modbusTcpMachine!.Disconnect();
|
||||
_modbusRtuMachine!.GetAddresses = addresses;
|
||||
|
||||
// 分别通过三种协议写入数据
|
||||
await _modbusTcpMachine.SetDatasAsync(MachineDataType.Address, dic1);
|
||||
await _modbusAsciiMachine.SetDatasAsync(MachineDataType.Address, dic1);
|
||||
await _modbusRtuMachine.SetDatasAsync(MachineDataType.Address, dic1);
|
||||
|
||||
// 分别通过三种协议读取数据
|
||||
var ans = await _modbusTcpMachine.GetDatasAsync(MachineDataType.Address);
|
||||
var ans2 = await _modbusRtuMachine.GetDatasAsync(MachineDataType.Address);
|
||||
var ans3 = await _modbusAsciiMachine.GetDatasAsync(MachineDataType.Address);
|
||||
|
||||
// 验证三种协议读取的所有值与写入的值一致
|
||||
Assert.AreEqual(ans.Datas?["4X 2.0"].DeviceValue, dic1["4X 2"]);
|
||||
Assert.AreEqual(ans.Datas?["4X 3.0"].DeviceValue, dic1["4X 3"]);
|
||||
Assert.AreEqual(ans.Datas?["4X 4.0"].DeviceValue, dic1["4X 4"]);
|
||||
Assert.AreEqual(ans.Datas?["4X 5.0"].DeviceValue, dic1["4X 5"]);
|
||||
|
||||
Assert.AreEqual(ans2.Datas?["4X 2.0"].DeviceValue, dic1["4X 2"]);
|
||||
Assert.AreEqual(ans2.Datas?["4X 3.0"].DeviceValue, dic1["4X 3"]);
|
||||
Assert.AreEqual(ans2.Datas?["4X 4.0"].DeviceValue, dic1["4X 4"]);
|
||||
Assert.AreEqual(ans2.Datas?["4X 5.0"].DeviceValue, dic1["4X 5"]);
|
||||
|
||||
Assert.AreEqual(ans3.Datas?["4X 2.0"].DeviceValue, dic1["4X 2"]);
|
||||
Assert.AreEqual(ans3.Datas?["4X 3.0"].DeviceValue, dic1["4X 3"]);
|
||||
Assert.AreEqual(ans3.Datas?["4X 4.0"].DeviceValue, dic1["4X 4"]);
|
||||
Assert.AreEqual(ans3.Datas?["4X 5.0"].DeviceValue, dic1["4X 5"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,54 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Modbus.Net.Siemens;
|
||||
using AddressUnit = Modbus.Net.AddressUnit<string, int, int>;
|
||||
|
||||
namespace Modbus.Net.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// 西门子 PLC 测试类
|
||||
/// 测试 Siemens S7-1200 (TCP) 和 S7-200 (PPI) 的读写功能
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class SiemensTest
|
||||
{
|
||||
// Siemens TCP 机器实例(S7-1200)
|
||||
private BaseMachine<string, string>? _siemensTcpMachine;
|
||||
|
||||
// Siemens PPI 机器实例(S7-200)
|
||||
private BaseMachine<string, string>? _siemensPpiMachine;
|
||||
|
||||
// 测试机器 IP 地址
|
||||
private string _machineIp = "10.10.18.251";
|
||||
|
||||
// 测试串口
|
||||
private string _machineCom = "COM11";
|
||||
|
||||
/// <summary>
|
||||
/// 测试初始化方法
|
||||
/// 创建 S7-1200 (TCP) 和 S7-200 (PPI) 两种机器实例
|
||||
/// </summary>
|
||||
[TestInitialize]
|
||||
public void Init()
|
||||
{
|
||||
// 创建 S7-1200 TCP 机器实例
|
||||
// 参数:ID, 别名,连接类型,IP 地址,型号,地址列表,保持连接,从站地址,主站地址
|
||||
_siemensTcpMachine = new SiemensMachine<string, string>("1", "", SiemensType.Tcp, _machineIp, SiemensMachineModel.S7_1200, null, true, 2, 0);
|
||||
|
||||
// 创建 S7-200 PPI 机器实例
|
||||
// 参数:ID, 别名,连接类型,串口,型号,地址列表,保持连接,从站地址,主站地址,src, dst
|
||||
_siemensPpiMachine = new SiemensMachine<string, string>("2", "", SiemensType.Ppi, _machineCom, SiemensMachineModel.S7_200, null, true, 2, 0, 1, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试单个线圈读写
|
||||
/// 验证 Siemens TCP 和 PPI 协议的输出继电器(Q 区)读写功能
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task SiemensCoilSingle()
|
||||
{
|
||||
Random r = new Random();
|
||||
|
||||
// 定义地址单元
|
||||
var addresses = new List<AddressUnit>
|
||||
{
|
||||
new AddressUnit
|
||||
@@ -41,6 +62,7 @@ namespace Modbus.Net.Tests
|
||||
}
|
||||
};
|
||||
|
||||
// 生成随机值(0 或 1)
|
||||
var dic1 = new Dictionary<string, double>()
|
||||
{
|
||||
{
|
||||
@@ -48,21 +70,32 @@ namespace Modbus.Net.Tests
|
||||
}
|
||||
};
|
||||
|
||||
// 设置 TCP 机器的地址列表并写入
|
||||
_siemensTcpMachine!.GetAddresses = addresses;
|
||||
await _siemensTcpMachine.SetDatasAsync(MachineDataType.Address, dic1);
|
||||
|
||||
// 设置 PPI 机器的地址列表并写入
|
||||
_siemensPpiMachine!.GetAddresses = addresses;
|
||||
await _siemensPpiMachine.SetDatasAsync(MachineDataType.Address, dic1);
|
||||
|
||||
// 分别通过 TCP 和 PPI 读取数据
|
||||
var ans = await _siemensTcpMachine.GetDatasAsync(MachineDataType.Address);
|
||||
var ans2 = await _siemensPpiMachine.GetDatasAsync(MachineDataType.Address);
|
||||
|
||||
// 验证两种协议读取的值与写入的值一致
|
||||
Assert.AreEqual(ans.Datas["Q 0.0"].DeviceValue, dic1["Q 0.0"]);
|
||||
Assert.AreEqual(ans2.Datas["Q 0.0"].DeviceValue, dic1["Q 0.0"]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试单个离散输入读取
|
||||
/// 验证 Siemens TCP 和 PPI 协议的输入继电器(I 区)读取功能
|
||||
/// 输入继电器为只读
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task SiemensDInputSingle()
|
||||
{
|
||||
// 定义地址单元
|
||||
var addresses = new List<AddressUnit>
|
||||
{
|
||||
new AddressUnit
|
||||
@@ -76,21 +109,29 @@ namespace Modbus.Net.Tests
|
||||
}
|
||||
};
|
||||
|
||||
// 设置两种协议的地址列表
|
||||
_siemensTcpMachine!.GetAddresses = addresses;
|
||||
_siemensPpiMachine!.GetAddresses = addresses;
|
||||
|
||||
// 分别通过 TCP 和 PPI 读取数据
|
||||
var ans = await _siemensTcpMachine.GetDatasAsync(MachineDataType.Address);
|
||||
var ans2 = await _siemensPpiMachine.GetDatasAsync(MachineDataType.Address);
|
||||
|
||||
// 验证两种协议读取的值都为 0(默认值)
|
||||
Assert.AreEqual(ans.Datas["I 0.0"].DeviceValue, 0);
|
||||
Assert.AreEqual(ans2.Datas["I 0.0"].DeviceValue, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试单个位存储器读写
|
||||
/// 验证 Siemens TCP 和 PPI 协议的位存储器(M 区)读写功能
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task SiemensMSingle()
|
||||
{
|
||||
Random r = new Random();
|
||||
|
||||
// 定义地址单元
|
||||
var addresses = new List<AddressUnit>
|
||||
{
|
||||
new AddressUnit
|
||||
@@ -104,9 +145,11 @@ namespace Modbus.Net.Tests
|
||||
}
|
||||
};
|
||||
|
||||
// 设置两种协议的地址列表
|
||||
_siemensTcpMachine!.GetAddresses = addresses;
|
||||
_siemensPpiMachine!.GetAddresses = addresses;
|
||||
|
||||
// 生成随机值
|
||||
var dic1 = new Dictionary<string, double>()
|
||||
{
|
||||
{
|
||||
@@ -114,21 +157,29 @@ namespace Modbus.Net.Tests
|
||||
}
|
||||
};
|
||||
|
||||
// 分别通过 TCP 和 PPI 写入数据
|
||||
await _siemensTcpMachine.SetDatasAsync(MachineDataType.Address, dic1);
|
||||
await _siemensPpiMachine.SetDatasAsync(MachineDataType.Address, dic1);
|
||||
|
||||
// 分别通过 TCP 和 PPI 读取数据
|
||||
var ans = await _siemensTcpMachine.GetDatasAsync(MachineDataType.Address);
|
||||
var ans2 = await _siemensPpiMachine.GetDatasAsync(MachineDataType.Address);
|
||||
|
||||
// 验证两种协议读取的值与写入的值一致
|
||||
Assert.AreEqual(ans.Datas["M 0.0"].DeviceValue, dic1["M 0"]);
|
||||
Assert.AreEqual(ans2.Datas["M 0.0"].DeviceValue, dic1["M 0"]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试单个位存储器位读写
|
||||
/// 验证 Siemens TCP 和 PPI 协议的位存储器(M 区)位读写功能
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task SiemensMSingleBool()
|
||||
{
|
||||
Random r = new Random();
|
||||
|
||||
// 定义地址单元
|
||||
var addresses = new List<AddressUnit>
|
||||
{
|
||||
new AddressUnit
|
||||
@@ -142,9 +193,11 @@ namespace Modbus.Net.Tests
|
||||
}
|
||||
};
|
||||
|
||||
// 设置两种协议的地址列表
|
||||
_siemensTcpMachine!.GetAddresses = addresses;
|
||||
_siemensPpiMachine!.GetAddresses = addresses;
|
||||
|
||||
// 生成随机值(0 或 1)
|
||||
var dic1 = new Dictionary<string, double>()
|
||||
{
|
||||
{
|
||||
@@ -152,21 +205,29 @@ namespace Modbus.Net.Tests
|
||||
}
|
||||
};
|
||||
|
||||
// 分别通过 TCP 和 PPI 写入数据
|
||||
await _siemensTcpMachine.SetDatasAsync(MachineDataType.Address, dic1);
|
||||
await _siemensPpiMachine.SetDatasAsync(MachineDataType.Address, dic1);
|
||||
|
||||
// 分别通过 TCP 和 PPI 读取数据
|
||||
var ans = await _siemensTcpMachine.GetDatasAsync(MachineDataType.Address);
|
||||
var ans2 = await _siemensPpiMachine.GetDatasAsync(MachineDataType.Address);
|
||||
|
||||
// 验证两种协议读取的值与写入的值一致
|
||||
Assert.AreEqual(ans.Datas["M 0.0"].DeviceValue, dic1["M 0.0"]);
|
||||
Assert.AreEqual(ans2.Datas["M 0.0"].DeviceValue, dic1["M 0.0"]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试单个数据块读写
|
||||
/// 验证 Siemens TCP 和 PPI 协议的数据块(DB 区)读写功能
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public async Task SiemensDbSingle()
|
||||
{
|
||||
Random r = new Random();
|
||||
|
||||
// 定义地址单元
|
||||
var addresses = new List<AddressUnit>
|
||||
{
|
||||
new AddressUnit
|
||||
@@ -180,6 +241,7 @@ namespace Modbus.Net.Tests
|
||||
}
|
||||
};
|
||||
|
||||
// 生成随机值
|
||||
var dic1 = new Dictionary<string, double>()
|
||||
{
|
||||
{
|
||||
@@ -187,134 +249,21 @@ namespace Modbus.Net.Tests
|
||||
}
|
||||
};
|
||||
|
||||
// 设置两种协议的地址列表
|
||||
_siemensTcpMachine!.GetAddresses = addresses;
|
||||
_siemensPpiMachine!.GetAddresses = addresses;
|
||||
|
||||
// 分别通过 TCP 和 PPI 写入数据
|
||||
await _siemensTcpMachine.SetDatasAsync(MachineDataType.Address, dic1);
|
||||
await _siemensPpiMachine.SetDatasAsync(MachineDataType.Address, dic1);
|
||||
|
||||
// 分别通过 TCP 和 PPI 读取数据
|
||||
var ans = await _siemensTcpMachine.GetDatasAsync(MachineDataType.Address);
|
||||
var ans2 = await _siemensPpiMachine.GetDatasAsync(MachineDataType.Address);
|
||||
|
||||
// 验证两种协议读取的值与写入的值一致
|
||||
Assert.AreEqual(ans.Datas["DB1 0.0"].DeviceValue, dic1["DB1 0.0"]);
|
||||
Assert.AreEqual(ans2.Datas["DB1 0.0"].DeviceValue, dic1["DB1 0.0"]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task SiemensDbMultiple()
|
||||
{
|
||||
Random r = new Random();
|
||||
|
||||
var addresses = new List<AddressUnit>
|
||||
{
|
||||
new AddressUnit
|
||||
{
|
||||
Id = "0",
|
||||
Area = "DB1",
|
||||
Address = 2,
|
||||
SubAddress = 0,
|
||||
CommunicationTag = "A1",
|
||||
DataType = typeof(ushort)
|
||||
},
|
||||
new AddressUnit
|
||||
{
|
||||
Id = "1",
|
||||
Area = "DB1",
|
||||
Address = 4,
|
||||
SubAddress = 0,
|
||||
CommunicationTag = "A2",
|
||||
DataType = typeof(ushort)
|
||||
},
|
||||
new AddressUnit
|
||||
{
|
||||
Id = "2",
|
||||
Area = "DB1",
|
||||
Address = 6,
|
||||
SubAddress = 0,
|
||||
CommunicationTag = "A3",
|
||||
DataType = typeof(ushort)
|
||||
},
|
||||
new AddressUnit
|
||||
{
|
||||
Id = "3",
|
||||
Area = "DB1",
|
||||
Address = 8,
|
||||
SubAddress = 0,
|
||||
CommunicationTag = "A4",
|
||||
DataType = typeof(ushort)
|
||||
},
|
||||
new AddressUnit
|
||||
{
|
||||
Id = "4",
|
||||
Area = "DB1",
|
||||
Address = 10,
|
||||
SubAddress = 0,
|
||||
CommunicationTag = "A5",
|
||||
DataType = typeof(uint)
|
||||
},
|
||||
new AddressUnit
|
||||
{
|
||||
Id = "5",
|
||||
Area = "DB1",
|
||||
Address = 14,
|
||||
SubAddress = 0,
|
||||
CommunicationTag = "A6",
|
||||
DataType = typeof(uint)
|
||||
}
|
||||
};
|
||||
|
||||
var dic1 = new Dictionary<string, double>()
|
||||
{
|
||||
{
|
||||
"A1", r.Next(0, UInt16.MaxValue)
|
||||
},
|
||||
{
|
||||
"A2", r.Next(0, UInt16.MaxValue)
|
||||
},
|
||||
{
|
||||
"A3", r.Next(0, UInt16.MaxValue)
|
||||
},
|
||||
{
|
||||
"A4", r.Next(0, UInt16.MaxValue)
|
||||
},
|
||||
{
|
||||
"A5", r.Next()
|
||||
},
|
||||
{
|
||||
"A6", r.Next()
|
||||
},
|
||||
};
|
||||
|
||||
_siemensTcpMachine!.GetAddresses = addresses;
|
||||
_siemensPpiMachine!.GetAddresses = addresses;
|
||||
|
||||
await _siemensTcpMachine.SetDatasAsync(MachineDataType.CommunicationTag, dic1);
|
||||
await _siemensPpiMachine.SetDatasAsync(MachineDataType.CommunicationTag, dic1);
|
||||
|
||||
var ans = await _siemensTcpMachine.GetDatasAsync(MachineDataType.CommunicationTag);
|
||||
var ans2 = await _siemensPpiMachine.GetDatasAsync(MachineDataType.CommunicationTag);
|
||||
|
||||
Assert.AreEqual(ans.Datas["A1"].DeviceValue, dic1["A1"]);
|
||||
Assert.AreEqual(ans.Datas["A2"].DeviceValue, dic1["A2"]);
|
||||
Assert.AreEqual(ans.Datas["A3"].DeviceValue, dic1["A3"]);
|
||||
Assert.AreEqual(ans.Datas["A4"].DeviceValue, dic1["A4"]);
|
||||
Assert.AreEqual(ans.Datas["A5"].DeviceValue, dic1["A5"]);
|
||||
Assert.AreEqual(ans.Datas["A6"].DeviceValue, dic1["A6"]);
|
||||
|
||||
Assert.AreEqual(ans2.Datas["A1"].DeviceValue, dic1["A1"]);
|
||||
Assert.AreEqual(ans2.Datas["A2"].DeviceValue, dic1["A2"]);
|
||||
Assert.AreEqual(ans2.Datas["A3"].DeviceValue, dic1["A3"]);
|
||||
Assert.AreEqual(ans2.Datas["A4"].DeviceValue, dic1["A4"]);
|
||||
Assert.AreEqual(ans2.Datas["A5"].DeviceValue, dic1["A5"]);
|
||||
Assert.AreEqual(ans2.Datas["A6"].DeviceValue, dic1["A6"]);
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void MachineClean()
|
||||
{
|
||||
_siemensTcpMachine!.Disconnect();
|
||||
|
||||
_siemensPpiMachine!.Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user