Snet 框架 -- 协议驱动概览
入口文件: Snet.Core/abstract/DaqAbstract.cs, Snet.Core/subscribe/SubscribeData.cs, Snet.Driver/
目标框架: .NET 8 / .NET 10(net8.0;net10.0)
架构
+----------------------------+
| 应用层 |
+-----------+----------------+
|
+-----------v----------------+
| Snet.Core (抽象层) |
| DaqAbstract<O, D> |
| CoreUnify<O, D> |
| SubscribeData.SCData |
+-----------+----------------+
|
+--------------------+--------------------+
| | |
+-------v-------+ +-------v-------+ +-------v-------+
| Snet.Modbus | | Snet.Siemens | | Snet.Mitsubishi|
| (TCP/UDP/RTU) | | (S7/PPI/FW) | | (MC/A1E/A3C/A4C)|
+---------------+ +---------------+ +---------------+
| | |
+-------v------------------------------------------------
| 36 种协议驱动 (PLC + 仪器仪表) |
+--------------------------------------------------------+
所有协议驱动均继承自 DaqAbstract<O, D>(其继承自 CoreUnify<O, D>),提供统一的单例生命周期管理,内置事件系统、日志、多语言、WebAPI 和订阅引擎。
核心模式
每个驱动仅由两个文件组成,遵循完全一致的架构:
1. 配置 -- {Vendor}Data.cs
namespace Snet.{Vendor}
{
public class {Vendor}Data
{
public class Basics : SubscribeData.SCData
{
public string SN { get; set; } = Guid.NewGuid().ToUpperNString();
public string? IpAddress { get; set; } // TCP 连接地址
public int Port { get; set; } // TCP 端口
public int Station { get; set; } // 站号 / 单元号
public string? SerialPortInfo { get; set; } // "COM3-9600-8-N-1"
public int ConnectTimeOut { get; set; }
public int ReceiveTimeOut { get; set; }
public ProtocolType ProtocolType { get; set; } // 枚举选择协议变体
// ... 供应商特定字段
}
public enum ProtocolType { /* 协议变体列表 */ }
}
}
Basics继承SubscribeData.SCData(提供HandleInterval、ChangeOut、AllOut、TaskNumber)ProtocolType枚举携带[AutoAllocating]特性,可动态暴露与当前变体相关的配置字段
2. 实现 -- {Vendor}Operate.cs
namespace Snet.{Vendor}
{
public class {Vendor}Operate : DaqAbstract<{Vendor}Operate, {Vendor}Data.Basics>, IDaq
{
// 单例工厂方法
public static async Task<{Vendor}Operate> InstanceAsync(Basics config, CancellationToken token = default)
// 必须实现的 8 个抽象方法:
public override async Task<OperateResult> OnAsync(CancellationToken token)
public override async Task<OperateResult> OffAsync(bool hardClose, CancellationToken token)
public override async Task<OperateResult> ReadAsync(Address address, CancellationToken token)
public override async Task<OperateResult> WriteAsync(ConcurrentDictionary<string, (object, EncodingType?)> values, CancellationToken token)
public override async Task<OperateResult> SubscribeAsync(Address address, CancellationToken token)
public override async Task<OperateResult> UnSubscribeAsync(Address address, CancellationToken token)
public override async Task<OperateResult> GetStatusAsync(CancellationToken token)
public override async Task<OperateResult> GetBaseObjectAsync(CancellationToken token)
}
}
- 继承
DaqAbstract<Operate, Basics>,其继承自CoreUnify<Operate, Basics> - 自动获得:单例管理、事件总线(
OnDataEvent/OnInfoEvent)、WebAPI 宿主、日志、多语言 - 每个驱动实现全部 8 个抽象方法,将 Snet Address 模型翻译为供应商特定的通信协议
统一用法(所有驱动通用)
// 第一步: 配置 -- 所有驱动接口完全一致
var config = new ModbusData.Basics
{
IpAddress = "192.168.1.100",
Port = 502,
Station = 1,
ProtocolType = ModbusData.ProtocolType.ModbusTcpNet,
AddressStartWithZero = false
};
// 第二步: 通过单例工厂实例化
var modbus = await ModbusOperate.InstanceAsync(config);
// 第三步: 打开连接
await modbus.OnAsync();
// 第四步: 读取 -- 使用统一的 Address 模型
var address = new Address(new AddressDetails("1", DataType.Int16, length: 1));
var result = await modbus.ReadAsync(address);
// 第五步: 订阅持续轮询
await modbus.SubscribeAsync(address);
modbus.OnDataEventAsync += async (sender, e) =>
{
// ResultData 是按地址名称索引的字典,按名称取值
if (e.Status)
Console.WriteLine($"1 = {e.GetSource<ConcurrentDictionary<string, AddressValue>>()["1"].ResultValue}");
};
// 第六步: 写入
var writes = new ConcurrentDictionary<string, (object value, EncodingType? encodingType)>();
writes.TryAdd("2", (42.5f, null));
await modbus.WriteAsync(writes);
// 第七步: 清理资源
await modbus.UnSubscribeAsync(address);
await modbus.OffAsync();
将
Modbus替换为任意供应商名称(如Siemens、Mitsubishi、Omron)-- API 接口完全一致。
完整驱动目录
欧美 PLC
| 包名 | 供应商 | 协议类型数 | 传输方式 | 主要变体 |
|---|---|---|---|---|
Snet.Siemens |
西门子 | 10 | TCP / 串口 | S7-200, S7-200Smart, S7-300, S7-400, S7-1200, S7-1500, FetchWrite, PPI, PPIOverTcp, S7Plus |
Snet.AllenBradley |
罗克韦尔 | 6 | TCP / 串口 | CIP, ConnectedCIP, Micro800, PCCC, SLC, DF1 |
Snet.Beckhoff |
倍福 | 2 | TCP | ADS (BeckhoffAdsNet), ADS 经官方 Beckhoff.TwinCAT.Ads 路由 (BeckhoffAdsNetWithAdsRouter) |
Snet.GE |
通用电气 | 1 | TCP | SRTP |
日系 PLC
| 包名 | 供应商 | 协议类型数 | 传输方式 | 主要变体 |
|---|---|---|---|---|
Snet.Mitsubishi |
三菱 | 16 | TCP / UDP / 串口 | MC Binary/ASCII TCP/UDP、MC R、A1E、A3C、A4C、FX Serial/Links、CIP |
Snet.Omron |
欧姆龙 | 8 | TCP / UDP / 串口 | FINS TCP/UDP, CIP/ConnectedCIP, HostLink, HostLink C-Mode |
Snet.Keyence |
基恩士 | 5 | TCP / 串口 | MC Binary/ASCII, KV Nano Serial/TCP, KV Old |
Snet.Yaskawa |
安川 | 2 | TCP / UDP | Memobus TCP, Memobus UDP |
Snet.Yokogawa |
横河 | 1 | TCP | Link |
Snet.Fuji |
富士 | 4 | TCP / 串口 | SPH, SPB Serial/TCP, CommandSetting |
Snet.Panasonic |
松下 | 3 | TCP / 串口 | MC, Mewtocol Serial/TCP |
Snet.Toyota |
丰田 / 东洋 | 1 | 串口 | Puc Serial |
Snet.OrientalMotor |
东方马达 | 1 | TCP | EIP |
国产 PLC
| 包名 | 供应商 | 协议类型数 | 传输方式 | 主要变体 |
|---|---|---|---|---|
Snet.Inovance |
汇川 | 6 | TCP / 串口 | TCP, Serial, SerialOverTcp, ComputerLink, ConnectedCIP, EasyNet |
Snet.XinJE |
信捷 | 4 | TCP / 串口 | TCP, Serial, SerialOverTcp, InternalNet |
Snet.Delta |
台达 | 5 | TCP / 串口 | TCP, Serial, SerialOverTcp, ASCII Serial, ASCII SerialOverTcp |
Snet.MegMeet |
麦格米特 | 3 | TCP / 串口 | TCP, Serial, SerialOverTcp |
Snet.Vigor |
丰炜 | 2 | 串口 | Serial, SerialOverTcp |
Snet.WeCon |
维控 | 2 | TCP / 串口 | ModbusTCP, ModbusRTU |
Snet.Fatek |
永宏 | 2 | 串口 | Serial, SerialOverTcp |
标准/通用协议
| 包名 | 协议 | 类型数 | 说明 |
|---|---|---|---|
Snet.Modbus |
Modbus | 6 | TCP, UDP, RTU, RTUOverTcp, ASCII, ASCIIOverTcp -- 支持 30+ 功能码,使用最广泛的驱动 |
Snet.Opc |
OPC | 4 | UA Client, UA Server, DA COM Client, DA HTTP Forward -- OPC 基金会标准 |
Snet.Freedom |
Freedom | 3 | TCP, UDP, Serial -- 用户自定义自由协议 |
其他供应商驱动
| 包名 | 供应商 | 用途 |
|---|---|---|
Snet.Kossi |
Kossi / 高誓 | 韩系 PLC |
Snet.Cimon |
Cimon / 西盟 | 韩系 PLC |
Snet.LSis |
LS 电气 | 韩系 PLC |
Snet.Invt |
英威腾 | 国产 PLC / 变频器 |
Snet.Yamatake |
山武 / Azbil | 日系 PLC |
Snet.Turck |
图尔克 | 工业 I/O 模块 |
Snet.Fanuc |
发那科 | 机器人控制器 (CNC) |
Snet.PQDIF |
PQDIF | 电力通讯规约(DLT698/DLT645/CJT188/DTSU6606) |
仪器仪表驱动
| 包名 | 标准 / 设备 | 用途 |
|---|---|---|
Snet.Driver |
DLT645-2007 / DLT645-1997 | 电表抄读 (国家电网) |
Snet.Driver |
DLT698 | 新一代电表标准 (中国) |
Snet.Driver |
CJT-188 | 水 / 气 / 热表抄读 |
Snet.Driver |
IEC 60870-5-104 | 电力远动 / SCADA |
Snet.RKC |
RKC 温控器 | 精密温度仪表 |
Snet.YuDian |
宇电温控器 | 工业温控仪表 |
Snet.Driver |
DAM3601 | 数据采集模块 |
Snet.Driver |
DTSU6606 | 三相电能表 |
DLT645、DLT698、CJT188、IEC104、DAM3601、DTSU6606 等仪表驱动内置于 Snet.Driver(如 Instrument/DLT/DLT645.cs);RKC 和 YuDian 以独立包发布。
Address 地址模型 (所有驱动统一)
// 核心地址模型 -- 所有驱动使用相同的 Address 结构
var address = new Address(new AddressDetails(
addressName: "1", // 供应商特定的地址字符串
dataType: DataType.Float, // DataType 枚举 (Int16, Float, Bool, String 等)
length: 2, // 读取多少个寄存器/字
encodingType: EncodingType.ASCII // 可选的编码提示
));
| 数据类型 | C# 对应类型 | 典型大小 |
|---|---|---|
Bool / BoolArray |
bool / bool[] |
1 位 |
Byte / ByteArray |
byte / byte[] |
1 字节 |
Int16 / Int16Array |
short / short[] |
2 字节 |
UInt16 / UInt16Array |
ushort / ushort[] |
2 字节 |
Int32 / Int32Array |
int / int[] |
4 字节 |
UInt32 / UInt32Array |
uint / uint[] |
4 字节 |
Int64 / Int64Array |
long / long[] |
8 字节 |
UInt64 / UInt64Array |
ulong / ulong[] |
8 字节 |
Float / FloatArray |
float / float[] |
4 字节 |
Double / DoubleArray |
double / double[] |
8 字节 |
String |
string |
可变 |
Char |
char |
1-2 字节 |
内置 WebAPI
每个 DaqAbstract 驱动自动暴露 HTTP API:
| 端点 | 方法 | 负载 | 说明 |
|---|---|---|---|
/api/on |
POST | 无 | 打开连接 |
/api/off |
POST | 无 | 关闭连接 |
/api/read |
POST | Address (JSON) |
读取单个地址 |
/api/write |
POST | ConcurrentDictionary<string, WriteModel> |
写入多个地址 |
/api/getstatus |
GET | 无 | 获取连接状态 |
/api/switchlanguage |
GET | 无 | 切换 中文/英文 |
启用方式:
var wam = new WAModel { IpAddress = "0.0.0.0", Port = 5000 };
await modbus.WAOnAsync(wam);
订阅引擎
所有驱动通过 SubscribeData.SCData 继承内置订阅系统:
| 属性 | 默认值 | 说明 |
|---|---|---|
HandleInterval |
1000ms | 每个读取周期的轮询间隔 |
ChangeOut |
true |
仅在数据变化时触发事件 |
AllOut |
false |
ChangeOut 为 true 时,是否同时抛出变化项和未变项 |
TaskNumber |
5 | 并行轮询任务队列数量 |
传输层架构
+------------------+ +------------------+ +------------------+
| 串口 | | TCP 客户端 | | UDP |
| (RS-232/RS-485) | | | | (单播/组播/广播) |
+--------+---------+ +--------+---------+ +--------+---------+
| | |
+------------------------+--------------------------+
|
+-------------v-------------+
| Snet.Core 通信层 |
| Channel / Pipeline 层 |
+---------------------------+
| SerialOperate |
| TcpClientOperate |
| UdpClientOperate |
| UdpBroadcastOperate |
| UdpMulticastOperate |
+---------------------------+
每个驱动从核心通信层选择其传输方式,并用供应商特定的协议帧格式进行封装。
相关文档
- 中间件概览 -- MQTT, Kafka, RabbitMQ, NetMQ, Netty, TEP
- Snet.Core 源码:
Snet.Core/abstract/DaqAbstract.cs - Address 模型:
Snet.Model/data/Address.cs
