YZWater3 基于 HslCommunication 库实现了多 PLC 协议支持,通过统一的 IPlcDriver 接口抽象,可以轻松切换不同品牌的 PLC。
| 协议 | 品牌 | 默认端口 | 说明 |
|---|---|---|---|
| Siemens S7 | 西门子 | 102 | S200/S200Smart/S300/S400/S1200/S1500 |
| Mitsubishi MC | 三菱 | 6000 | Q 系列、iQ-R/iQ-F |
| Omron Fins | 欧姆龙 | 9600 | CJ/CS/CP 系列 |
| Modbus TCP | 通用 | 502 | 仪表、传感器、其他 PLC |
| Allen-Bradley | AB | 44818 | ControlLogix/CompactLogix |
using YZWater.Core.Services.PlcDrivers;
// 创建西门子 S7 驱动
var driver = PlcDriverFactory.Create(
PlcProtocol.SiemensS7,
ipAddress: "192.168.1.100",
port: 102,
extraConfig: new Dictionary<string, object>
{
["PlcSeries"] = "S200Smart"
}
);
// 连接
var result = await driver.ConnectAsync();
if (!result.IsSuccess)
{
Console.WriteLine($"连接失败: {result.Message}");
return;
}
// 读取数据
var floatResult = await driver.ReadFloatAsync("VD100");
if (floatResult.IsSuccess)
{
float value = floatResult.Content;
Console.WriteLine($"VD100 = {value}");
}
// 写入数据
await driver.WriteFloatAsync("VD100", 123.45f);
// 断开
driver.Disconnect();
driver.Dispose();
// 西门子 S7
var siemens = new SiemensS7Driver(SiemensPLCS.S1200);
siemens.SetConnection("192.168.1.100", 102);
// 三菱 MC
var mitsubishi = new MitsubishiMcDriver();
mitsubishi.SetConnection("192.168.1.101", 6000);
// 欧姆龙 Fins
var omron = new OmronFinsDriver();
omron.SetConnection("192.168.1.102", 9600);
omron.SetNodeNumbers(sa1: 0, da1: 0); // 设置节点号
// Modbus TCP
var modbus = new ModbusTcpDriver();
modbus.SetConnection("192.168.1.103", 502, station: 1);
modbus.SetAddressStart(true); // 地址从 0 开始
// AB EtherNet/IP
var ab = new AllenBradleyDriver();
ab.SetConnection("192.168.1.104", 44818);
{
"PlcProtocol": "SiemensS7",
"PlcIp": "192.168.1.100",
"PlcPort": 102,
"PlcExtraConfig": {
"PlcSeries": "S200Smart"
}
}
西门子 S7:
{
"PlcProtocol": "SiemensS7",
"PlcIp": "192.168.1.100",
"PlcPort": 102,
"PlcExtraConfig": {
"PlcSeries": "S1200"
}
}
三菱 MC:
{
"PlcProtocol": "MitsubishiMC",
"PlcIp": "192.168.1.101",
"PlcPort": 6000
}
欧姆龙 Fins:
{
"PlcProtocol": "OmronFins",
"PlcIp": "192.168.1.102",
"PlcPort": 9600,
"PlcExtraConfig": {
"SA1": 0,
"DA1": 0
}
}
Modbus TCP:
{
"PlcProtocol": "ModbusTcp",
"PlcIp": "192.168.1.103",
"PlcPort": 502,
"PlcExtraConfig": {
"Station": 1,
"AddressStartWithZero": true
}
}
Allen-Bradley:
{
"PlcProtocol": "AllenBradley",
"PlcIp": "192.168.1.104",
"PlcPort": 44818
}
| 区域 | 地址格式 | 说明 |
|---|---|---|
| I | I0.0 |
输入位 |
| Q | Q0.0 |
输出位 |
| M | M0.0 |
中间继电器位 |
| DB | DB1.0 |
数据块字节 |
| V/VD | VD100 |
变量区(S200Smart) |
| 区域 | 地址格式 | 说明 |
|---|---|---|
| D | D100 |
数据寄存器 |
| R | R100 |
文件寄存器 |
| W | W100 |
链接寄存器 |
| X | X0 |
输入 |
| Y | Y0 |
输出 |
| M | M0 |
内部继电器 |
| 区域 | 地址格式 | 说明 |
|---|---|---|
| D | D100 |
DM 区 |
| C | C100 |
HR 区 |
| W | W100 |
WR 区 |
| H | H100 |
保持位 |
| 区域 | 地址格式 | 说明 |
|---|---|---|
| 0x | 0x100 |
线圈(000001-099999) |
| 1x | 1x100 |
离散输入(100001-199999) |
| 3x | 3x100 |
输入寄存器(300001-399999) |
| 4x | 4x100 |
保持寄存器(400001-499999) |
| 类型 | 地址格式 | 说明 |
|---|---|---|
| Tag | TagName |
标签名 |
| 数组 | Tag[0] |
数组元素 |
| 结构体 | Tag.Member |
结构体成员 |
实现 IPlcDriver 接口:
public class MyCustomDriver : IPlcDriver
{
public string Name => "My Custom PLC";
public bool IsConnected { get; private set; }
public Task<OperateResult> ConnectAsync()
{
// 实现连接逻辑
}
public void Disconnect()
{
// 实现断开逻辑
}
public Task<OperateResult<byte[]>> ReadBytesAsync(string address, ushort length)
{
// 实现读取逻辑
}
// 实现其他接口方法...
}
然后在 PlcDriverFactory 中添加:
public static IPlcDriver Create(PlcProtocol protocol, ...)
{
IPlcDriver driver = protocol switch
{
PlcProtocol.MyCustom => new MyCustomDriver(...),
// ...
};
return driver;
}
Dispose() 释放资源OperateResult.IsSuccess 判断操作是否成功ReadBytesAsync 而非多次读取单个值| 协议 | 读取延迟 | 吞吐量 | 说明 |
|---|---|---|---|
| S7 | 10-50ms | 高 | 优化良好 |
| MC | 10-50ms | 高 | 优化良好 |
| Fins | 20-80ms | 中 | 相对较慢 |
| Modbus | 50-200ms | 低 | 通用协议,开销大 |
| AB | 20-100ms | 中 | 取决于标签复杂度 |
ping <PLC_IP>Logs/log-*.txt