var client = ModbusFactory.GetOrCreateTcpMaster("bb", options =>
-{
- options.LocalEndPoint = new IPEndPoint(IPAddress.Loopback, 0);
-});
+3. 通过工厂获得相对应协议 IModbusClient 实例
3. 使用方法
+Modbus 可以通过不同的物理介质传输,主要有以下几种方式:
ITcpSocketClient 实例方法 ConnectAsync 连接远端节点ITcpSocketClient 实例方法 SendAsync 发送协议数据ITcpSocketClient 实例方法 Close 关闭连接ITcpSocketClient 实例方法 SetDataHandler 方法设置数据处理器ITcpSocketClient 实例属性 ReceivedCallBack 方法设置接收数据处理器(注意:此回调未做任何数据处理为原始数据)Modbus RTU (Remote Terminal Unit): 采用二进制编码,使用紧凑的二进制表示数据,效率高,是最常用的串行通信模式。通常基于 RS-485(支持多设备)或 RS-232(点对点)物理层,CRC 校验确保数据完整性。Modbus TCP/IP: 运行于以太网上,使用 TCP/IP 协议,默认端口 502。它在 Modbus RTU 协议基础上添加了 MBAP 报文头,并由于TCP本身是可靠连接的服务,因此去掉了 CRC 校验码。4. 数据处理器
- -在我们实际应用中,建立套接字连接后就会进行数据通信,数据通信不会是杂乱无章的随机数据,在应用中都是有双方遵守的规约简称通讯协议,在通讯协议的约束下,发送方与接收方均根据通讯协议进行编码或解码工作,将数据有条不紊的传输
- -数据处理器设计初衷就是为了契合通讯协议大大简化我们开发逻辑,我们已通讯协议每次通讯电文均为 4 位定长举例说明,在实际的通讯过程中,我们接收到的通讯数据存在粘包或者分包的现象
+IModbusFactory 实例方法
GetOrCreateTcpMaster 方法得到 IModbusTcpClient 实例GetOrCreateUdpMaster 方法得到 IModbusTcpClient 实例GetOrCreateRtuMaster 方法得到 IModbusRtuClient 实例GetOrCreateRtuOverTcpMaster 方法得到 IModbusTcpClient 实例GetOrCreateRtuOverUdpMaster 方法得到 IModbusTcpClient 实例我们内置了一些常用的数据处理类 IDataPackageHandler 接口为数据包处理接口,虚类 DataPackageHandlerBase 作为数据处理器基类已经内置了 粘包 分包 的逻辑,继承此类后专注自己处理的业务即可
使用方法如下:
+调用其对应的 Remove 方法即可从缓存中移除指定名称的 IModbusClient 实例。如
[Inject]
-[NotNull]
-private ITcpSocketFactory? TcpSocketFactory { get; set; }
+ModbusFactory.RemoveTcpMaster("test");
-private async Task CreateClient()
-{
- // 创建 ITcpSocketClient 实例
- var client = TcpSocketFactory.GetOrCreate("localhost", 0);
+4. 数据操作
- // 设置数据适配器 使用 FixLengthDataPackageHandler 数据处理器处理数据定长 4 的数据
- var adapter = new DataPackageAdapter
- {
- DataPackageHandler = new FixLengthDataPackageHandler(4)
- };
+Modbus 数据类型共四种
- // 如果 client 不销毁切记使用 RemoveDataPackageAdapter 移除回调委托防止内存泄露
- client.AddDataPackageAdapter(adapter, buffer =>
- {
- // buffer 即是接收到的数据
- return ValueTask.CompletedTask;
- });
-
- // 连接远端节点 连接成功后自动开始接收数据
- var connected = await client.ConnectAsync("192.168.10.100", 6688);
-}
-
+内置数据处理器
+对应 IModbusClient 实例方法如下
FixLengthDataPackageHandler 固定长度数据处理器 即每个通讯包都是固定长度DelimiterDataPackageHandler 分隔符数据处理器 即通讯包以特定一个或一组字节分割ReadCoilsAsync WriteCoilAsync WriteMultipleCoilsAsyncReadInputsAsyncReadInputRegistersAsyncReadHoldingRegistersAsync WriteRegisterAsync WriteMultipleRegistersAsync5. 数据适配器
- -在我们实际应用中,接收到数据包后(已经过数据处理器)大多情况下是需要将电文转化为应用中的具体数据类型 Class 或 Struct。将原始数据包转化为类或者结构体的过程由我们的数据适配器来实现
数据适配器设计思路如下
- -DataTypeConverterAttribute 标签约定通讯数据使用那个转换类型进行转换 指定类型需继承 IDataConverter
- 接口
- DataPropertyConverterAttribute 标签约定如何转换数据类型 (Property) 属性值[DataTypeConverter(Type = typeof(DataConverter<MockEntity>))]
-class MockEntity
-{
- [DataPropertyConverter(Type = typeof(byte[]), Offset = 0, Length = 5)]
- public byte[]? Header { get; set; }
-
- [DataPropertyConverter(Type = typeof(byte[]), Offset = 5, Length = 2)]
- public byte[]? Body { get; set; }
-
- [DataPropertyConverter(Type = typeof(Foo), Offset = 7, Length = 1, ConverterType = typeof(FooConverter), ConverterParameters = ["test"])]
- public string? Value1 { get; set; }
-}
-
-class FooConverter(string name) : IDataPropertyConverter
-{
- public object? Convert(ReadOnlyMemory<byte> data)
- {
- return new Foo() { Id = data.Span[0], Name = name };
- }
-}
-
-针对第三方程序集的数据类型解决方案如下:
-使用
builder.Services.ConfigureDataConverters(options =>
-{
- options.AddTypeConverter<MockEntity>();
- options.AddPropertyConverter<MockEntity>(entity => entity.Header, new DataPropertyConverterAttribute()
- {
- Offset = 0,
- Length = 5
- });
- options.AddPropertyConverter<MockEntity>(entity => entity.Body, new DataPropertyConverterAttribute()
- {
- Offset = 5,
- Length = 2
- });
-});
-
diff --git a/src/BootstrapBlazor.Server/Components/Samples/Modbus/ModbusFactories.razor.cs b/src/BootstrapBlazor.Server/Components/Samples/Modbus/ModbusFactories.razor.cs
index b6a814450e8..19fb7453a71 100644
--- a/src/BootstrapBlazor.Server/Components/Samples/Modbus/ModbusFactories.razor.cs
+++ b/src/BootstrapBlazor.Server/Components/Samples/Modbus/ModbusFactories.razor.cs
@@ -10,5 +10,5 @@ namespace BootstrapBlazor.Server.Components.Samples.Modbus;
///
public partial class ModbusFactories
{
-
+
}
diff --git a/src/BootstrapBlazor.Server/docs.json b/src/BootstrapBlazor.Server/docs.json
index b69bf4d3956..bf297fd2395 100644
--- a/src/BootstrapBlazor.Server/docs.json
+++ b/src/BootstrapBlazor.Server/docs.json
@@ -253,7 +253,8 @@
"toolbar": "Toolbars",
"opc-da": "OpcDa",
"navbar": "Navbars",
- "task-board": "TaskBoard"
+ "task-board": "TaskBoard",
+ "modbus-factory": "Modbus\\ModbusFactories"
},
"video": {
"table": "BV1ap4y1x7Qn?p=1",