ModernIndustrial.Protocols.Keyence
1.0.0
dotnet add package ModernIndustrial.Protocols.Keyence --version 1.0.0
NuGet\Install-Package ModernIndustrial.Protocols.Keyence -Version 1.0.0
<PackageReference Include="ModernIndustrial.Protocols.Keyence" Version="1.0.0" />
<PackageVersion Include="ModernIndustrial.Protocols.Keyence" Version="1.0.0" />
<PackageReference Include="ModernIndustrial.Protocols.Keyence" />
paket add ModernIndustrial.Protocols.Keyence --version 1.0.0
#r "nuget: ModernIndustrial.Protocols.Keyence, 1.0.0"
#:package ModernIndustrial.Protocols.Keyence@1.0.0
#addin nuget:?package=ModernIndustrial.Protocols.Keyence&version=1.0.0
#tool nuget:?package=ModernIndustrial.Protocols.Keyence&version=1.0.0
ModernIndustrial.Net
基于 .NET 10 构建的现代化工业通信框架 — 零分配、AOT 兼容、高性能管道调度
功能树
graph TD
A[ModernIndustrial.Net工业通信框架] --> B[通信协议支持]
A --> C[PLC设备管理]
A --> D[数据解析与序列化]
A --> E[弹性与可靠性机制]
A --> F[开发体验增强]
A --> G[测试与模拟]
B --> B1[Modbus协议]
B --> B2[西门子S7协议]
B --> B3[汇川Inovance协议]
B --> B4[欧姆龙FINS协议]
B --> B5[基恩士MC协议]
B --> B6[三菱MC协议]
B1 --> B1a[地址解析]
B1 --> B1b[帧构建]
B1 --> B1c[响应匹配]
B1 --> B1d[Modbus TCP设备]
B2 --> B2a[S7地址解析]
B2 --> B2b[S7帧构建]
B2 --> B2c[S7响应匹配]
B2 --> B2d[S7字符串编解码]
B3 --> B3a[Inovance地址解析]
B3 --> B3b[Inovance帧构建]
B3 --> B3c[Inovance响应匹配]
B3 --> B3d[InovanceTcpDevice]
B4 --> B4a[Omron地址解析]
B4 --> B4b[Omron帧构建]
B4 --> B4c[Omron响应匹配]
B4 --> B4d[OmronFinsDevice]
B5 --> B5a[Keyence地址解析]
B5 --> B5b[Keyence帧构建]
B5 --> B5c[Keyence响应匹配]
B5 --> B5d[KeyenceMcDevice]
B6 --> B6a[Mitsubishi地址解析]
B6 --> B6b[Mitsubishi帧构建]
B6 --> B6c[Mitsubishi响应匹配]
B6 --> B6d[MitsubishiMcDevice]
C --> C1[设备工厂]
C --> C2[连接配置]
C --> C3[健康检查]
C --> C4[连接池管理]
D --> D1[端序解析]
D --> D2[批量类型转换]
D --> D3[PLC字符串解码]
D1 --> D1a[ABCD模式]
D1 --> D1b[DCBA模式]
D1 --> D1c[BADC模式]
D1 --> D1d[CDAB模式]
E --> E1[连接状态机]
E --> E2[指数退避重连]
E --> E3[挂起队列缓冲]
E --> E4[防击穿缓存]
F --> F1[源生成实体映射]
F --> F2[依赖注入扩展]
G --> G1[虚拟Modbus服务器]
G --> G2[核心功能单元测试]
设计哲学
ModernIndustrial.Net 是对 HslCommunication 等传统工控通信库的 现代化重构。它利用 .NET 10 的全新技术栈,在极端 AOT 亲和性、零 GC 抖动、极高吞吐量三个维度实现全面超越。
核心技术栈
| 传统技术 | 现代 .NET 10 替代 | 收益 |
|---|---|---|
NetworkStream.Read/Write + new byte[] |
System.IO.Pipelines + MemoryPool<byte> |
零分配高吞吐数据流 |
lock(obj) 阻塞排队 |
System.Threading.Channels |
无锁调度 + 背压控制 |
BitConverter + Array.Reverse |
BinaryPrimitives + Unsafe.BitCast |
SIMD 向量化端序解析 |
ReadInt16 / ReadFloat 方法爆炸 |
INumber<T> 泛型数学 |
单一泛型方法覆盖所有值类型 |
string.Split / Regex 地址解析 |
ReadOnlySpan<char> + ISpanParsable<T> |
地址解析零堆分配 |
System.Reflection 实体映射 |
Roslyn Source Generators | 编译期生成,100% AOT |
Thread/Timer + event 轮询 |
IAsyncEnumerable<T> + PeriodicTimer |
不占线程、无内存泄漏 |
| 手动加锁缓存 | HybridCache |
API 级防击穿保护 |
解决方案结构
ModernIndustrial.sln
│
├── src/
│ ├── ModernIndustrial.Abstractions ← 零依赖契约层
│ ├── ModernIndustrial.Core ← 管道调度 / 端序解析 / 弹性重连
│ ├── ModernIndustrial.Protocols.Modbus ← Modbus TCP/RTU
│ ├── ModernIndustrial.Protocols.Siemens ← 西门子 S7
│ ├── ModernIndustrial.Protocols.Inovance ← 汇川 AM400/AM400_800
│ ├── ModernIndustrial.Protocols.Omron ← 欧姆龙 FINS TCP
│ ├── ModernIndustrial.Protocols.Keyence ← 基恩士 MC Protocol
│ ├── ModernIndustrial.Protocols.Mitsubishi ← 三菱 MC Protocol
│ ├── ModernIndustrial.Extensions.Hosting ← DI / 连接池 / HybridCache
│ └── ModernIndustrial.Generators ← Roslyn 源生成器 (AOT 实体映射)
│
└── tests/
├── ModernIndustrial.Tests ← 单元 + 集成测试
└── ModernIndustrial.Simulator ← 内存 PLC 模拟器
支持的 PLC 协议
| 品牌 | 系列 | 协议 | 默认端口 | 支持的存储区域 |
|---|---|---|---|---|
| 西门子 | S7-200/300/400/1200/1500 | S7comm | 102 | DB/M/I/Q/T/C |
| Modbus | 标准 Modbus TCP | Modbus TCP | 502 | 0x/4x 寄存器 |
| 汇川 | AM400/AM400_800 | 专有 TCP | 501 | D/M/X/Y/S/T/C/R/V |
| 汇川 | H3U/H5U/Easy/XP | Modbus TCP | 502 | 同 Modbus |
| 欧姆龙 | CJ/CS/CP/CV/NX/NJ | FINS TCP | 9600 | CIO/W/H/A/D/EM/T/C |
| 基恩士 | KV-8000/7000/5000/3000/1000 | MC Protocol | 8501 | MR/CR/HR/AR/LR/DM/EM/TM/CM |
| 三菱 | Q/L/iQ-R/iQ-F/FX | MC Protocol | 5007 | X/Y/M/D/L/R/Z/TN/CN |
快速开始
1. 注册服务
// Program.cs 或 MauiProgram.cs
services.AddModernIndustrial(builder =>
{
// 西门子 S7-1200/1500
builder.AddS7("Line1_Siemens", "192.168.1.100", rack: 0, slot: 1, options =>
{
options.FloatOrder = FloatByteOrder.BADC; // 西门子浮点端序 (字交换)
});
// Modbus TCP 设备
builder.AddModbusTcp("Inverter1", "192.168.1.200", port: 502, options =>
{
options.RequestTimeout = TimeSpan.FromSeconds(5);
});
// 汇川 AM400/AM400_800
builder.AddInovance("InovancePLC", "192.168.1.150", port: 501);
// 欧姆龙 CJ/NJ/NX 系列
builder.AddOmron("OmronPLC", "192.168.1.160", port: 9600);
// 基恩士 KV-8000/7000
builder.AddKeyence("KeyencePLC", "192.168.1.170", port: 8501);
// 三菱 Q/L/iQ-F/FX 系列
builder.AddMitsubishi("MitsubishiPLC", "192.168.1.180", port: 5007);
});
2. 单值读取
public class ProductionMonitor(IPlcDeviceManager manager)
{
private readonly IPlcDevice _plc = manager.GetDevice("Line1_Siemens");
public async Task<float> GetTemperatureAsync()
{
var result = await _plc.ReadAsync<float>("DB1.DBD10");
return result.IsSuccess ? result.Value : throw new Exception(result.Error.Message);
}
}
3. 持续订阅流(替代 Timer + Event)
public async Task StartMonitoringAsync(CancellationToken ct)
{
// 每 200ms 轮询一次,数据以异步流形式推送
await foreach (var data in _plc.PollAsync<float>("DB1.DBD10", TimeSpan.FromMilliseconds(200), ct))
{
if (data.IsSuccess)
{
CurrentTemperature = data.Value;
NotifyStateChanged();
}
}
}
4. HybridCache 防击穿保护
public class ProductionDataService(IPlcDeviceManager manager, HybridCache cache)
{
public async ValueTask<short> GetMachineStatusAsync(CancellationToken ct)
{
return await cache.GetOrCreateAsync(
"Machine1_Status",
async (cancel) =>
{
var result = await _manager.GetDevice("Line1_Siemens")
.ReadAsync<short>("DB1.DBW20", cancel);
return result.IsSuccess ? result.Value : throw new Exception();
},
cancellationToken: ct
);
}
}
5. 编译期实体映射(零反射,100% AOT)
// 1. 定义实体类(partial class + Attribute)
[PlcEntity]
public partial class ProcessRecipe
{
[PlcAddress("DB1.DBD0")] public float Temperature { get; set; }
[PlcAddress("DB1.DBD4")] public float Pressure { get; set; }
[PlcAddress("DB1.DBW8")] public short Status { get; set; }
}
// 2. 编译期自动生成的代码(用户不可见)
// ProcessRecipeMapper.ParseFromSpan(span, reader)
// ProcessRecipeMapper.WriteToSpan(recipe, span, reader)
// 3. 业务层调用
byte[] buffer = new byte[ProcessRecipeMapper.GetTotalByteLength()];
await _plc.ReadRawAsync("DB1.DBD0", buffer.Length, buffer);
var recipe = ProcessRecipeMapper.ParseFromSpan(buffer, _endianReader);
各品牌 PLC 使用示例
汇川 (Inovance) AM400/AM400_800
// 注册
builder.AddInovance("AM400", "192.168.1.150", port: 501);
// 读取 D 寄存器(数据寄存器)
var device = manager.GetDevice("AM400");
var dValue = await device.ReadAsync<short>("D100");
// 读取 M 继电器(位)
var mValue = await device.ReadAsync<byte>("M200");
bool isOn = mValue.IsSuccess && mValue.Value != 0;
// 批量读取 D 寄存器数组
byte[] buffer = new byte[20]; // 10个寄存器
await device.ReadBlockAsync("D100", buffer);
// 或使用类型安全的便捷方法(如果直接持有 InovanceTcpDevice)
if (device is InovanceTcpDevice inovance)
{
short dReg = await inovance.ReadDAsync(100);
bool mRelay = await inovance.ReadMAsync(200);
short[] dArray = await inovance.ReadDArrayAsync(100, 10);
}
支持的存储区域:
- D - 数据寄存器(Word 读写,最常用)
- M - 辅助继电器(Bit 读写)
- X/Y - 输入/输出(Bit 读/写)
- S - 状态继电器(Bit 读写)
- T/C - 定时器/计数器(Word 读/写)
- R - 闪存寄存器(Word 读写,断电保持)
- V - 变量寄存器(Word 读写)
欧姆龙 (Omron) FINS TCP
// 注册
builder.AddOmron("OmronCJ", "192.168.1.160", port: 9600);
// 读取 DM 区域(数据存储器)
var device = manager.GetDevice("OmronCJ");
var dmValue = await device.ReadAsync<short>("DM100");
// 读取 CIO 区域(位)
var cioValue = await device.ReadAsync<byte>("CIO100.05"); // 位地址
// 读取工作继电器
var wrValue = await device.ReadAsync<byte>("W200.03");
// 批量读取
byte[] buffer = new byte[20];
await device.ReadBlockAsync("DM100", buffer);
支持的存储区域:
- D - DM 数据存储器(Word 读写)
- CIO - CIO 区域(Bit 读写)
- W/H/A - 工作/保持/辅助继电器(Bit 读写)
- EM - 扩展存储器(Word 读写)
- T/C - 定时器/计数器(Word 读)
基恩士 (Keyence) MC Protocol
// 注册
builder.AddKeyence("KeyenceKV", "192.168.1.170", port: 8501);
// 读取 DM 寄存器
var device = manager.GetDevice("KeyenceKV");
var dmValue = await device.ReadAsync<short>("DM100");
// 读取 MR 继电器(位)
var mrValue = await device.ReadAsync<byte>("MR200.05");
// 批量读取
byte[] buffer = new byte[20];
await device.ReadBlockAsync("DM100", buffer);
支持的存储区域:
- DM - 数据存储器(Word 读写)
- MR/CR/HR/AR/LR - 各类继电器(Bit 读写)
- EM - 扩展存储器(Word 读写)
- WDM - 文件寄存器(Word 读写)
- TM/CM - 定时器/计数器(Word 读)
三菱 (Mitsubishi) MC Protocol
// 注册
builder.AddMitsubishi("MitsubishiQ", "192.168.1.180", port: 5007);
// 读取 D 寄存器
var device = manager.GetDevice("MitsubishiQ");
var dValue = await device.ReadAsync<short>("D100");
// 读取 X 输入(位)
var xValue = await device.ReadAsync<byte>("X0");
// 读取 Y 输出(位)
var yValue = await device.ReadAsync<byte>("Y10");
// 读取 M 继电器
var mValue = await device.ReadAsync<byte>("M200");
// 批量读取
byte[] buffer = new byte[20];
await device.ReadBlockAsync("D100", buffer);
支持的存储区域:
- D - 数据寄存器(Word 读写,最常用)
- X/Y - 输入/输出(Bit 读/写)
- M - 内部继电器(Bit 读写)
- L - 锁存继电器(Bit 读写)
- R - 文件寄存器(Word 读写)
- Z - 变址寄存器(Word 读写)
- TN/CN - 定时器/计数器当前值(Word 读)
- TC/CC - 定时器/计数器触点(Bit 读)
高级特性
浮点数端序支持
工业设备的浮点存储有四种标准模式,框架在连接级别支持配置:
| 模式 | 字节序 | 常见设备 |
|---|---|---|
| ABCD | Big-Endian | Modicon / 施耐德 |
| DCBA | Little-Endian | 部分国产 PLC |
| BADC | 字交换 (Mid-Big) | 西门子 S7 |
| CDAB | 字交换 (Mid-Little) | AB / 罗克韦尔 |
自动断线重连
设备内部维护状态机(Disconnected → Connecting → Connected → Faulted → Reconnecting),使用指数退避算法自动重连。连接断开时,业务层的请求会在 BoundedChannel 中安全挂起,重连成功后自动恢复流转。
背压控制
发送队列采用 BoundedChannel(默认 256 深度),当请求堆积达到上限时,新请求会被挂起等待而非无限堆积,从根源上保护 PLC 设备不被冲垮。
API 参考
IPlcDevice 核心接口
| 方法 | 签名 | 说明 |
|---|---|---|
ReadAsync<T> |
ValueTask<PlcResult<T>> ReadAsync<T>(string address, CancellationToken ct = default) |
单值泛型读取,T: unmanaged, INumber<T> |
WriteAsync<T> |
ValueTask<PlcResult> WriteAsync<T>(string address, T value, CancellationToken ct = default) |
单值泛型写入 |
ReadBlockAsync |
ValueTask<PlcResult<int>> ReadBlockAsync(string startAddress, Memory<byte> buffer, CancellationToken ct = default) |
批量块读取(零拷贝) |
WriteBlockAsync |
ValueTask<PlcResult> WriteBlockAsync(string startAddress, ReadOnlyMemory<byte> data, CancellationToken ct = default) |
批量块写入 |
ReadRawAsync |
ValueTask<PlcResult<int>> ReadRawAsync(string address, int byteLength, Memory<byte> buffer, CancellationToken ct = default) |
原始字节读取(供 Source Generator 调用) |
ReadStringAsync |
ValueTask<PlcStringResult> ReadStringAsync(string address, int maxLength, CancellationToken ct = default) |
字符串读取 |
PollAsync<T> |
IAsyncEnumerable<PlcResult<T>> PollAsync<T>(string address, TimeSpan interval, CancellationToken ct = default) |
持续订阅流 |
PlcResult<T> 结果结构
public readonly record struct PlcResult<T> where T : unmanaged
{
public T Value { get; init; }
public PlcError Error { get; init; }
public bool IsSuccess => Error.Code == 0;
public static implicit operator PlcResult<T>(T value);
public static implicit operator PlcResult<T>(PlcError error);
}
测试
# 运行全部测试
dotnet test tests/ModernIndustrial.Tests --verbosity normal
# 仅运行集成测试
dotnet test tests/ModernIndustrial.Tests --filter "ModbusTcpIntegrationTests"
测试包含一个内存 Modbus TCP 模拟器,无需物理 PLC 即可运行端到端集成测试。
编译要求
- .NET SDK 10.0+
- 支持的操作系统:Windows / Linux / macOS
- 支持 Native AOT 发布
# 编译全部项目
dotnet build ModernIndustrial.sln
# Native AOT 发布(需具体目标运行时)
dotnet publish -c Release -r linux-x64 --aot
许可证
MIT License
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- ModernIndustrial.Core (>= 1.0.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on ModernIndustrial.Protocols.Keyence:
| Package | Downloads |
|---|---|
|
ModernIndustrial.Extensions.Hosting
DI extensions, connection pooling, and HybridCache integration for ModernIndustrial. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated | |
|---|---|---|---|
| 1.0.0 | 192 | 4/17/2026 |