PlcSimulator.Core 2.2.9

dotnet add package PlcSimulator.Core --version 2.2.9
                    
NuGet\Install-Package PlcSimulator.Core -Version 2.2.9
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="PlcSimulator.Core" Version="2.2.9" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="PlcSimulator.Core" Version="2.2.9" />
                    
Directory.Packages.props
<PackageReference Include="PlcSimulator.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add PlcSimulator.Core --version 2.2.9
                    
#r "nuget: PlcSimulator.Core, 2.2.9"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package PlcSimulator.Core@2.2.9
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=PlcSimulator.Core&version=2.2.9
                    
Install as a Cake Addin
#tool nuget:?package=PlcSimulator.Core&version=2.2.9
                    
Install as a Cake Tool

PLC Simulator - 工业级全协议仿真器

这是一个基于 .NET(核心库 netstandard2.0、测试与工具链 net10.0)开发的高性能 PLC 仿真服务器,旨在为工业自动化领域的软件开发、测试和教学提供一个轻量级、跨平台的仿真环境(完美支持 MacOS)。

🌟 核心特性

  • 全协议支持:内置西门子 (S7)、三菱 (MC/A-1E)、欧姆龙 (FINS)、罗克韦尔 (CIP)、Modbus TCP 及 BACnet/IP 等协议仿真。 协议清单以 ProtocolCatalog 为准,当前共 42 种(含 TCP/UDP/串行)。 ⚠️ 平台差异:macOS 上实测 37 种可启动、5 种受限(三菱 MC 的 5000 端口被 AirPlay 占用、 串口类 IEC101/DNP3/Modbus-RTU 无串口设备、BACnet 需 UDP 模式)。 启动后用 critical_failed 与 failed_servers 字段确认实际可用协议。
  • 吞吐能力(实测,非标称):S7 协议面单实例实测—— 单连接顺序读约 2,700~4,600 RPS(受往返时延限制); 4 连接并发约 15,000~20,000 RPS、8 连接并发约 12,000~27,000 RPS。 ⇒ 「10,000+ RPS」需多连接并发方可达成,单连接达不到。 可复现基准见 scripts/benchmark-s7-throughput.sh(macOS/Apple Silicon 实测口径)。
  • 统一内存模型:所有协议共享同一块寄存器空间——7 个固定区各 64KB (M/I/Q/T/C/AI/AQ),外加按需创建的 DB 块(每块 64KB)。支持协议间数据透明互通。

    字节序约定(重要):内存按**规范序(大端 / ABCD)**存放,唯一权威声明是 PlcMemory.CanonicalDataFormat,控制面与类型化访问器(ReadWord/WriteWords 等) 均由它参数化(Docs/247)。 各协议服务器不得把内存字节裸透传上线——透传只对大端线序协议(S7/Modbus/FINS 等)成立; 小端线序协议(三菱 MC、AB CIP、Beckhoff ADS 等)必须在服务器内声明各自的线序 codec (参照 MelsecMcServer.McWireCodec = RegularByteTransform(DataFormat.DCBA)), 并经 PlcMemory 类型化访问器 ⇄ 线序 codec 转换。 跨路径回归锁见 CrossProtocolByteOrderTests(S7/Modbus)与 MelsecMcCrossTests(HSL 真客户端,修复前 11/11 复现 -11772 镜像值)。 详见 Docs/244、Docs/247。

  • 生产级兼容性:支持西门子 S7-200 SMART/1200/1500 模型;DB 块编号不受 10000 限制 (2026-10-02 实测 DB10001、DB19999 均可正常读写)。 ⚠️ 但 DB 块数量上限为 1000 块(PlcMemory.MaxDbBlockCount,防内存耗尽),超出时明确抛错。
  • 跨平台运行:原生支持 MacOS、Linux 和 Windows。

🛡️ 安全特性

  • 报文校验: 部分协议服务器设有 count/长度上限校验,例如三菱 MC/三菱 A1E/欧姆龙 HostLink 均为 2048 点(MaxMcRequestCount 等常量);Allen-Bradley 校验 CIP 路径边界。 ⚠️ 并非全部服务器都有显式上限(2026-10-02 实测:38 个服务器文件中 14 个含 count/长度上限校验), 如 BACnet 未做此类校验。使用方不应假定所有协议等强防护。
  • 全局异常处理: CLI/UI 均配置 UnhandledException 处理,防止静默崩溃。
  • 敏感信息保护: .qwen/、.qoder/、.roo/、.serena/ 等已加入 .gitignore (git check-ignore 实证;其历史提交内容仅含权限白名单、无密钥)。 ⚠️ 已知问题:HslCommunication 的商业授权码硬编码在源码中且已提交进本公开仓库 (自 2026-03-04 起)。该码是功能性依赖(缺失时 HSL 组件 24 小时后失效), 处置需产品决策。详见 Docs/246 §六。

🧪 测试覆盖

  • 测试框架: xUnit + FluentAssertions
  • 测试数量: 1341 个测试全部通过 / 0 失败 / 6 跳过(2026-10-02 实测:dotnet test src/PlcSimulator.Test/PlcSimulator.Test.csproj,约 110 秒)
  • 测试策略: 部分用例通过反射调用 private 方法;子集为 loopback 自连(绑定 127.0.0.1 随机端口, 并非完全无网络——该子集含 S7ServerTests 等绑定 loopback socket 的用例), 2026-10-02 实测 262 个用例约 78 秒、不依赖外部设备或外网。
  • 覆盖率: ⚠️ 暂无机器化口径——仓库当前无 coverage 产物与覆盖率门禁, 故不声明具体覆盖率数字。协议报文解析的边界用例较密集,但未做量化统计。 (如需该指标,应先引入覆盖率采集与门禁,见 Docs/246)

运行测试:

# 单元测试(无网络依赖)
dotnet test src/PlcSimulator.Test/PlcSimulator.Test.csproj \
  --filter "FullyQualifiedName~PlcAddressHelper|FullyQualifiedName~PlcMemory|FullyQualifiedName~S7ServerTests|FullyQualifiedName~ModbusAddressResolver|FullyQualifiedName~MelsecMcServer|FullyQualifiedName~OmronFinsServer"

# 集成测试(需要网络)
dotnet test src/PlcSimulator.Test/PlcSimulator.Test.csproj

📐 工程化规范

  • 代码风格: .editorconfig 统一 C# 命名约定、缩进、换行、模式匹配偏好
  • SDK 版本: global.json 锁定 .NET 10.0,防止版本漂移
  • 构建属性: Directory.Build.props 统一 Nullable/ImplicitUsings/版本号

📁 项目结构

  • src/PlcSimulator.Core: 核心逻辑、统一内存模型 (PlcMemory) 和服务器接口。
  • src/PlcSimulator.Lite: 协议实现与统一内存模型(PlcMemory、PlcTypeConverter、各协议服务器)。
  • src/PlcSimulator.Cli: 控制台交互式启动程序。
  • src/PlcSimulator.Grpc: gRPC 控制面(proto 定义与生成代码)。
  • src/S7Simulator.Standalone: 独立的 S7 仿真控制台(s7sim 工具,不含 gRPC)。
  • src/PlcSimulator.Test: 基于 HslCommunication 的自动化测试套件。

🚀 快速开始

1. 编译项目

使用 .NET 8 SDK 进行编译:

dotnet build src/PlcSimulator.sln

1.1 UI Linux 桌面支持开关(重要)

src/PlcSimulator.UI/PlcSimulator.UI.csproj 增加了 EnableLinuxDesktopSupport 开关:

  1. 默认值:false
    • 默认正式版构建不引入 Linux X11 桌面链路(避免额外 DBus/X11 依赖风险)。
  2. 需要 Linux 桌面运行时,显式开启:
dotnet build src/PlcSimulator.UI/PlcSimulator.UI.csproj -v minimal /p:EnableLinuxDesktopSupport=true
  1. 运行时行为:
    • macOS:UseAvaloniaNative()
    • Windows:UseWin32()
    • Linux:仅在启用开关的构建下走 UseX11()

2. 启动仿真服务器

dotnet run --project src/PlcSimulator.Cli/PlcSimulator.Cli.csproj

启动后在 PlcSim> 提示符下输入 start 即可开启所有协议监听。

3. 运行自动化测试

我们提供了基于 HslCommunication 的压力与兼容性测试:

dotnet run --project src/PlcSimulator.Test/PlcSimulator.Test.csproj

🛠 协议与端口映射 (MacOS 兼容)

协议 端口 内存映射地址示例
西门子 S7 102 DB1.0, M100, I0, Q0
三菱 MC 3E 5000 D100, M0
三菱 MC 1E 5001 D0 (旧款 A 系列)
欧姆龙 FINS 9600 D100 (映射至 DB1)
Modbus TCP 502 00001, 10001, 30001, 40001
BACnet/IP 47808 AnalogValue:1 (映射至 DB1 偏移 4)
罗克韦尔 AB CIP 44818 TAGA / CIP 映射
Modbus RTU over TCP 1502 与 MBAP 502 分口;错站静默
HART-IP 5094 Cmd3 读 PV(子集)
Omron HostLink(TCP) 9600 与 FinsTcp 同口互斥;主路径 DM
MTConnect Agent 5005 JSON /current(非标准 XML)

Modbus 地址区支持说明

当前 Modbus TCP 仿真已支持标准四大地址区:

地址区 功能码 说明 内部映射
0xxxx 01 / 05 / 15 Coil,支持读/写 DB3 偏移 0 起的位区
1xxxx 02 Discrete Input,只读 DB3 偏移 1024 起的位区
3xxxx 04 Input Register,只读 DB2 偏移 0 起
4xxxx 03 / 06 / 16 Holding Register,支持读/写 DB1 偏移 0 起

说明:

  • 30001 和 40001 是相互独立的两块寄存器区,不共享同一内存。
  • 00001 与 10001 也是独立位区,不共享同一字节偏移。
  • UI/工作台地址输入也支持 HR1 / IR1 / COIL1 / DI1 这类前缀形式,便于和不同主站软件的习惯保持一致。
  • 若使用低位端口 502,在 macOS/Linux 上仍需管理员权限或改用高位端口。

注意:在 MacOS/Linux 上,102/502 属于特权端口。无管理员权限时请使用 sudo,或通过 CLI 参数改用高位端口(如 --s7-port 1102 --modbus-port 1502;如需多实例也可使用 --melsec-port/--melsec-a1e-port/--omron-port/--ab-port/--bacnet-port 覆写端口)。

🧱 扩展新协议

由于采用了高度抽象的 IPlcServer 接口和统一的 PlcMemory,扩展新协议非常简单:

  1. 在 Protocols 项目下新建类并实现 IPlcServer。
  2. 在 Start() 中开启监听并解析报文。
  3. 通过 _memory.Read() 或 _memory.Write() 与全局内存交互。
  4. 在 Program.cs 中注册该服务器即可。

📎 与 ZL.IotHub 联调口径(Docs/207)

权威细节见 Docs/207_ZL.IotHub对照仿真补强方案_20260909.md §9。发版对外口径摘录如下。

可宣称

  • IotHub Native/HSL TCP/HTTP 主路径本机联调:本批新增 modbus-rtu-over-tcp / hart-ip / omron-host-link / mtconnect,以及既有 S7/MC/FINS/ADS/Fatek/FxLinks/AB/REST 等
  • 帧级/TCP/CLI 门禁可复现:scripts/verify_iothub_protocol_loop.sh(L1)→ verify_iothub_protocol_tcp.sh(L2)→ iothub_cross_smoke.sh(L3;EXTRA=1 可选 S7/MC/FinsTcp)
  • HostLink 与 FinsTcp 同口会被硬拦;mtconnect 按 JSON AgentUrl 联调
  • 汇川/台达走 Modbus TCP + 驱动侧地址映射(仿真不做服务端二次翻译)

不可宣称

  • 已与 IotHub 全部 Native 键做完驱动包端到端自动化
  • 松下 panasonic-mewtocol 串口驱动已与仿真互通(仿真为 TCP:9090)
  • Hart 支持全部命令/写;HostLink 覆盖全部 FINS 区与 EM bank
  • 标准 MTConnect XML /current Agent
  • 仿真器服务端二次翻译 Inovance/Delta 符号地址

默认端口以 ProtocolDefaultPorts 为准(melsec-mc 仿真默认 5000,与部分 IotHub 文档 6000 不一致时请显式 --ports)。

📚 补充文档

  • IotHub 对照仿真方案(含缺口矩阵):Docs/207_ZL.IotHub对照仿真补强方案_20260909.md
  • CLI 语义命令与 JSON 协议:Docs/PlcSimulator.Cli-语义命令与JSON协议.md
  • CLI-Anything 使用说明:agent-harness/cli_anything/plcsimulator/USAGE.zh-CN.md
  • AI 评选叙事建议:Docs/14-AI评选叙事与落地价值.md

坚持简洁、高效、稳定。本项目是从电检项目演化而来的全领域工控仿真工具。

📄 许可证

本项目采用 Apache License 2.0,全文见仓库根目录 LICENSE。 通过 NuGet 分发的包已在 nuspec 中声明 <license type="expression">Apache-2.0</license>。

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.2.9 107 10/4/2026
2.2.8 98 10/1/2026
2.2.7 92 10/1/2026
2.2.6 98 9/30/2026
2.2.5 95 9/28/2026
2.2.4 90 9/28/2026
2.2.3 95 9/28/2026
2.2.2 94 9/28/2026
2.2.1 179 6/26/2026
1.0.3 134 6/5/2026
1.0.2 142 6/5/2026
1.0.1 133 6/4/2026
1.0.0 139 6/4/2026