# modbus-slave-simulator **Repository Path**: snove/modbus-slave-simulator ## Basic Information - **Project Name**: modbus-slave-simulator - **Description**: 一款开源的 Modbus TCP 从站模拟工具,无需真实 PLC 设备,即可为主站程序提供完整的 Modbus TCP 从站响应能力。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 4 - **Forks**: 1 - **Created**: 2026-04-19 - **Last Updated**: 2026-05-31 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Modbus Slave Simulator > 一款开源的 Modbus TCP 从站模拟工具,无需真实 PLC 设备,即可为主站程序提供完整的 Modbus TCP 从站响应能力。 [![Java](https://img.shields.io/badge/Java-17-orange)](https://openjdk.org/projects/jdk/17/) [![JavaFX](https://img.shields.io/badge/JavaFX-21-blue)](https://openjfx.io/) [![License](https://img.shields.io/badge/License-MIT-green)](LICENSE) [![Build](https://img.shields.io/badge/Build-Maven-red)](https://maven.apache.org/) --- ## 截图 | 主界面[暗] | 主界面[亮] | |--------|---------| | ![主界面](docs/images/暗色主题.png) | ![主界面](docs/images/模拟器.png) | | 配置策略 | 实时绘图 | |--------|---------| | ![配置策略](docs/images/配置策略.png) | ![实时绘图](docs/images/实时绘图.png) | --- ## 功能特性 ### 🔌 多连接 · 多从站 - 同时监听多个 IP:Port 组合,每个连接独立运行 - 每个连接下支持 1~247 个 Slave ID(Unit ID) - 每个从站独立维护 4 类寄存器空间:线圈、离散输入、保持寄存器、输入寄存器 ### 📊 数据区管理 - 按业务语义划分数据区(Register Block),自定义名称和地址范围 - 同一从站可创建多个数据区,类型和地址均可自由组合 - 新建数据区时自动检测地址重叠,防止配置冲突 ### ⚡ 动态数据策略 每个寄存器地址可独立绑定一种数据生成策略,实时驱动数据变化: | 策略 | 说明 | 典型用途 | |------|------|---------| | 静态(Static) | 固定值 | 配置参数、设备编号 | | 正弦波(Sine) | 周期性正弦变化 | 温度、压力等模拟量 | | 随机(Random) | 区间内随机值 | 噪声信号、随机状态 | | 方波(Square) | 高低电平周期切换 | 开关量、数字信号 | | 锯齿波(Sawtooth) | 线性递增后跳变 | 步进变化量 | | 计数器(Counter) | 按步长递增/递减 | 累计计数、电量脉冲 | ### 🔢 多寄存器数据类型 - **Signed / Unsigned**:单寄存器有符号/无符号 16 位整数 - **INT32 / UINT32**:两个寄存器组合的 32 位整数 - **Float**:两个寄存器组合的 IEEE 754 单精度浮点 - **Double**:四个寄存器组合的双精度浮点 - **INT64**:四个寄存器组合的 64 位整数 - **String(ASCII)**:N 个寄存器存储 ASCII 字符串,长度用户自定义 ### 📡 完整功能码支持 | 功能码 | 名称 | 类型 | |--------|------|------| | 0x01 | 读线圈 | 读 | | 0x02 | 读离散输入 | 读 | | 0x03 | 读保持寄存器 | 读 | | 0x04 | 读输入寄存器 | 读 | | 0x05 | 写单个线圈 | 写 | | 0x06 | 写单个寄存器 | 写 | | 0x0F | 写多个线圈 | 写 | | 0x10 | 写多个寄存器 | 写 | ### 🔴 异常模拟 - 对指定地址范围配置 Modbus 异常码(0x01~0x04) - 可配置触发概率(0%~100%)、响应延迟(ms)、丢包率 - 用于测试主站程序的异常处理能力 ### 📋 通讯日志 - 实时显示请求/响应报文(十六进制) - 解析后的可读描述(功能码、地址、数量、寄存器值) - 鼠标悬停查看完整报文,防止列宽截断 - 支持暂停、续录、清除 ### 💾 快照管理 - 保存当前所有从站的寄存器值、策略绑定为 JSON 快照 - 支持加载快照快速恢复测试场景 - 关闭时自动保存,下次启动自动恢复(可配置) - 多寄存器 group(INT32/Float 等)在快照恢复后完整重建 ### 🎨 界面特性 - AtlantaFX 主题,支持亮色/暗色切换 - 自定义无边框窗体,macOS/Windows/Linux 均可正常拖拽和最大化 - 寄存器值变化时行背景短暂高亮 - 右键菜单快速设置策略、颜色标注、复制粘贴 --- ## 快速开始 ### 环境要求 - JDK 17+ - Maven 3.8+ ### 构建运行 ```bash git clone https://gitee.com/snove/modbus-slave-simulator.git cd modbus-slave-simulator mvn package -pl simulator-desktop -am -DskipTests java -jar simulator-desktop/target/simulator-desktop-1.0.0.jar ``` ### 基本使用流程 1. **新建连接** — 点击工具栏「新建连接」,配置监听 IP 和端口(默认 5020) 2. **新建从站** — 选中连接节点,点击「新建从站」,配置 Slave ID 3. **新建数据区** — 右键从站节点,选择「新建数据区」,配置寄存器类型和地址范围 4. **启动服务** — 点击工具栏「启动服务」 5. **配置策略** — 在数据区表格中右键寄存器行,选择「设置策略」配置动态数据 --- ## 项目结构 ``` modbus-slave-simulator/ ├── simulator-core/ # 核心协议层(无 UI 依赖) │ └── src/main/java/com/modbus/simulator/ │ ├── SimulatorFacade.java # UI 层唯一入口 │ ├── ConnectionManager.java # 多连接管理 │ ├── transport/tcp/ # Netty TCP 服务端 │ ├── pdu/ # Modbus PDU 处理(FC01-10) │ ├── store/ # 寄存器数据存储(AtomicIntegerArray) │ ├── strategy/ # 数据生成策略(Sine/Random/Square...) │ ├── fault/ # 异常模拟规则 │ ├── snapshot/ # 快照序列化(JSON) │ └── model/ # 数据模型 └── simulator-desktop/ # JavaFX 桌面端 └── src/main/java/com/modbus/simulator/desktop/ ├── SimulatorApp.java # 应用入口 └── ui/ ├── MainWindow.java # 主窗口 ├── controller/ # 各功能 Controller ├── layout/ # 工具栏、菜单栏、状态栏 ├── tree/ # 左侧三层树(连接/从站/数据区) └── widget/ # 通用弹窗组件 ``` --- ## 架构设计 ### 多连接共享 RegisterStore 策略引擎(`StrategyEngine`)和各连接的 `PduProcessor` 共享同一个 `RegisterStore` 实例: ``` StrategyEngine(100ms 周期) └── 写入 RegisterStore(AtomicIntegerArray,无锁) ↑ 共享同一对象 PduProcessor(Netty I/O 线程) └── 读取 RegisterStore → 构建响应 ``` 这确保了策略引擎更新的数据能被主站立即读到,不存在数据不一致问题。 ### 线程模型 ``` JavaFX Application Thread — UI 渲染 Netty Boss Thread (1) — 接受 TCP 连接 Netty Worker Threads — 处理 I/O,执行 PDU 处理 Strategy Engine Thread (1) — 100ms 周期驱动策略计算 EventBus Thread — 事件派发(UI 事件通过 Platform.runLater 切回 FX 线程) ``` --- ## 技术栈 | 技术 | 版本 | 用途 | |------|------|------| | Java | 17 | 主语言 | | JavaFX | 21 | UI 框架 | | AtlantaFX | 2.x | 主题(PrimerLight/PrimerDark) | | Netty | 4.1.x | TCP 服务端 | | Jackson | 2.x | JSON 序列化(快照) | | Logback | 1.4.x | 日志 | | Ikonli | - | 图标库(Bootstrap Icons) | --- ## 配置说明 应用启动时使用默认配置,可通过「设置」对话框修改: | 配置项 | 默认值 | 说明 | |--------|--------|------| | 写操作行为 | OVERRIDE_STRATEGY | 主站写入时是否覆盖策略 | | 日志最大条数 | 5000 | 超出后自动丢弃旧条目 | | 自动保存快照 | true | 关闭时自动保存,下次启动恢复 | | 策略引擎周期 | 100ms | 动态数据更新频率 | --- ## 与网关工具配合使用 本工具可与 [Modbus TCP 网关管理系统](https://gitee.com/snove/modbus-gateway) 配合使用: ``` Modbus TCP 网关(主站) ↓ 读取寄存器 Modbus Slave Simulator(从站) ↑ 动态数据策略驱动 ``` **数据类型对应关系**: | 模拟器类型 | 网关 DataType | 寄存器数量 | |-----------|--------------|-----------| | Signed | INT16 | 1 | | Unsigned | UINT16 | 1 | | INT32 | INT32 | 2 | | UINT32 | UINT32 | 2 | | Float | FLOAT32 | 2 | | Double | FLOAT64 | 4 | --- ## License [MIT License](LICENSE) --- ## 贡献 欢迎提交 Issue 和 Pull Request。 - Gitee:https://gitee.com/snove/modbus-slave-simulator