Modbus 驱动 (Modbus Driver)
约 573 字大约 2 分钟
2026-05-19
概述 (Overview)
Modbus 驱动实现了标准的 Modbus TCP 通讯协议,底层基于 EasyModbus 库构建。能够访问 PLC、变频器、智能仪表等广泛设备的线圈 (Coil)、离散输入 (Discrete Input)、保持寄存器 (Holding Register) 及输入寄存器 (Input Register)。
驱动支持在 InternalReadAsync / InternalWriteAsync 中捕获 Socket 错误或通信异常后自动触发状态流转(DriverState.Faulted),由 DriverBase Watchdog 在毫秒级内发起自愈重连。
使用方法 (Usage)
通过 IDriverRegistry 工厂方法创建(推荐,DI 自动装配依赖):
// 通过别名工厂创建(DI 自动装配 ILogger, IUniconCacheProvider, INetworkMonitor)
var driver = _driverRegistry.CreateDriver("Modbus", "Meter_01");
_driverRegistry.Register(driver);
await _connectionManager.RegisterDriverAsync(driver, "ip=192.168.0.50;port=502;unitid=1");参数说明 (Parameters)
连接字符串参数
| 参数名 | 类型 | 说明 | 是否必填 | 默认值 |
|---|---|---|---|---|
| ip | string | Modbus 从站 (Slave) 或服务器的 IP 地址 | 是 | 无 |
| port | int | Modbus 服务的 TCP 端口 | 否 | 502 |
| unitid / slaveid | byte | 从站单元标识符 | 否 | 1 |
| timeout | int | 通讯及连接超时时间(毫秒) | 否 | 2000 |
地址格式 (Address)
格式必须为 [类型]:[偏移地址]:
| 类型前缀 | 寄存器区 | 读写权限 | 说明 |
|---|---|---|---|
coil | 线圈 (0x) | 读写 | 布尔值,如 coil:1 |
discrete | 离散输入 (1x) | 只读 | 布尔值,如 discrete:10001 |
holding | 保持寄存器 (4x) | 读写 | 16 位整型或浮点,如 holding:40001 |
input | 输入寄存器 (3x) | 只读 | 16 位整型,如 input:30001 |
返回值 (Returns)
| 方法 | 返回类型 | 说明 |
|---|---|---|
ReadAsync<T> | UniconResponse<T> | response.Success 为 true 时,response.Data.Value 携带值 |
WriteAsync<T> | UniconResponse<bool> | true 成功,false 包含错误信息 |
SubscribeAsync | Task<string> | 返回订阅 GUID |
使用示例 (Examples)
示例 1:读取保持寄存器
var driver = _driverRegistry.CreateDriver("Modbus", "Meter_01");
_driverRegistry.Register(driver);
await _connectionManager.RegisterDriverAsync(driver, "ip=192.168.0.50;port=502;unitid=1");
var req = new UniconRequest { Address = "holding:1" };
var res = await driver.ReadAsync<int>(req);
if (res.Success && res.Data != null)
{
Console.WriteLine($"寄存器值: {res.Data.Value},质量: {res.Data.Quality}");
}示例 2:读取线圈(布尔)
var req = new UniconRequest { Address = "coil:1" };
var res = await driver.ReadAsync<bool>(req);
Console.WriteLine($"线圈状态: {res.Data?.Value}");示例 3:写入保持寄存器
var writeReq = new UniconRequest { Address = "holding:40001" };
var writeRes = await driver.WriteAsync<int>(writeReq, 1500);
Console.WriteLine(writeRes.Success ? "写入成功" : $"写入失败: {writeRes.Message}");示例 4:后台轮询仪表(ExceptionBased 模式)
await driver.SubscribeAsync(new UniconSubscription
{
Address = "input:30001",
ScanRateMs = 1000,
ScanMode = UniconScanMode.ExceptionBased,
Metadata = new TagMetadata { Unit = "kWh", Deadband = 0.1 },
Callback = async dv =>
{
Console.WriteLine($"[{dv.ServerTimestamp:HH:mm:ss}] 电量: {dv.Value} kWh");
await Task.CompletedTask;
}
});