Modbus Simulator

基于最近要进行modbus rtu/tcp的数据收集功能,测试代码放在github上,需要的友们,麻烦给个小星星⭐️:

git@github.com:feiyuluoye/mutil-modbus.git

Modbus Simulator 是一个使用 Go 实现的多模组 Modbus TCP 模拟系统,支持单实例模拟器、并发服务器管理、数据采集与文件导出等功能。项目旨在帮助快速构建 Modbus 联调、测试与演示环境。

功能概览

  • 最小 Modbus TCP 服务器,支持读 coils、discrete inputs、holding/input registers。
  • 基于 CSV 的寄存器周期写入,支持单实例与多实例并发运行。
  • 数据采集器可实时拉取点位数据,并按需落盘 JSONL/CSV。
  • 支持一次性快照导出,JSON/CSV 两种格式,便于排查和留存。

目录结构

  • cmd/server/:单服务器模拟器,读取 config.toml
  • cmd/servers/:并发服务器管理器,读取 config/config.yaml,可选快照。
  • cmd/collector/:数据采集器,支持 CLI 启用落盘功能。
  • cmd/export/:一次性快照导出 CLI。
  • internal/:核心实现(Modbus 服务、采集器、输出、模型等)。
  • config/:示例 YAML/TOML 配置。
  • data/:CSV 数据源及采集输出目录。

快速开始

  1. 安装 Go 1.20+
  2. 克隆仓库并进入目录
  3. go mod tidy
  4. 准备配置与 CSV 数据(可使用仓库自带示例)
  5. 参考下方命令运行需要的模块

运行示例

单服务器模拟器 + 客户端

RTU配置参考*.rtu.toml文件

bash 复制代码
go run ./cmd/server --config config.toml
go run ./cmd/client --config config.toml

并发服务器管理器

bash 复制代码
go run ./cmd/servers --config config/config.yaml

# 仅当需要一次性导出快照时,加上 snapshot 参数
go run ./cmd/servers --config config/config.yaml \
  --snapshot-json out.json --snapshot-csv out.csv --snapshot-wait 5s

虚拟串口模拟

复制代码
go run ./cmd/mocktty --config config/mocktty.yaml

展示效果如下:

当提供 --snapshot-json--snapshot-csv 时,程序会等待 --snapshot-wait 时长(默认 3s)以便 CSV 写入生效,随后导出快照并退出;否则常驻运行。

数据采集器

bash 复制代码
go run ./cmd/collector --config config/config.yaml

# CLI 覆盖 storage 相关配置
go run ./cmd/collector --config config/config.yaml \
  --storage-enabled --storage-dir data --storage-queue 20000

system.storage.file_type 决定输出模式:

  • log:仅日志输出(默认 wrapHandler),不落盘。
  • csv:写入 storage-dir/collector.csv
    CSV 表头:timestamp, server_id, device_id, connection, slave_id, point_name, address, register, unit, value

JSONL 字段示例:

json 复制代码
{"timestamp":"2025-09-29T14:45:32Z","server_id":"plc_server_1","device_id":"device_001","connection":"0.0.0.0:1502","slave_id":1,"point_name":"temperature","address":1,"register":"holding","unit":"","raw":21,"value":21}

一次性快照导出 CLI

bash 复制代码
go run ./cmd/export --config config/config.yaml \
  --json out.json --csv out.csv --wait 3s

cmd/export 会自启服务器,等待指定时长后导出当前快照并退出。

数据库与最新点位查询(ORM)

项目已迁移为使用 GORM(gorm.io/gorm)管理 SQLite 数据库,模型定义见 internal/model/modbus.go,ORM 辅助见 internal/db/orm.go

  • 连接与迁移:db.Open(path) 会自动创建并迁移表。
  • 采集入库:采集器通过 DB.SavePointValue() 写入 point_values

最新点位查询(去重规则变更)

DB.LatestPoints(ctx) 返回"最新点位值"列表,去重规则为复合键:server_id + device_id + name。即每个服务器-设备-点位名组合仅保留一条最新记录。

  • 返回结构(PointLatest):
    • server_id, device_id, name, address, register_type, data_type, byte_order, unit, value, timestamp

运行示例(examples/latest)

新增示例 examples/latest 用于查询并输出最新点位值(JSON):

bash 复制代码
# 全量最新点位
go run ./examples/latest -db ./data.sqlite -pretty=false

# 仅过滤某个 server
go run ./examples/latest -db ./data.sqlite -server plc_server_1

# 仅过滤某个 device
go run ./examples/latest -db ./data.sqlite -device device_001

# 同时按 server 与 device 过滤
go run ./examples/latest -db ./data.sqlite -server plc_server_1 -device device_001

可选参数:

  • -db: SQLite 文件路径(默认 ./data.sqlite
  • -pretty: 是否美化 JSON(默认 true
  • -timeout: 查询超时(默认 5s
  • -server: 按 server_id 过滤(可选)
  • -device: 按 device_id 过滤(可选)

配置说明

TOML (config.toml, 供 cmd/server 使用)

toml 复制代码
[server]
listen_address = ":1502"

[[registers]]
name = "temperature"
type = "holding"
address = 1
csv_column = "temperature"

YAML (config/config.yaml, 供 cmd/serverscmd/collector 使用)

  • servers[]: 定义每个服务器、设备与点位;points.name 需与 CSV 列名一致。
  • frequency: server_id -> duration,控制 CSV 写入周期。
  • type / devices_file: 服务器设备来源。
    • type: device(默认):从 devices 数组读取点位定义。
    • type: csvfile:通过 devices_file(相对或绝对路径)加载设备与点位,例如 data/plc_device_point.csv
  • system.storage: 控制采集器输出行为,示例:
yaml 复制代码
system:
  storage:
    enabled: true
    file_type: json+csv   # 支持 log | csv | json | json+csv
    db_path: "data"
    max_workers: 0
    max_queue_size: 10000

CLI 参数 --storage-* 会覆盖上述配置。

CSV 数据 (data/example_data.csv)

列名需与点位名称一致,例如 temperature,humidity,pump,alarm

输出文件说明

  • 模拟器数据源:data/example_data.csv
  • 采集器输出:data/collector.jsonl, data/collector.csv(取决于 file_type
  • 服务器设备清单:data/plc_device_point.csv(示例,供 plc_server_2 使用)
  • 快照导出:按命令指定的 out.json, out.csv

CSV 行示例:

csv 复制代码
timestamp,server_id,device_id,point_name,address,register,unit,value

JSONL 行示例:

json 复制代码
{"timestamp":"2025-09-29T13:38:00.123456789Z","server_id":"plc_server_1","device_id":"device_001","point_name":"temperature","address":1,"register":"holding","unit":"","raw":21,"value":21}

开发提示

  • internal/servermgr/manager.goSnapshot() 会按 YAML 点位读取当前寄存器值。
  • internal/collector/storage.go 使用缓冲队列异步写文件,max_queue_size 可调。
  • internal/output/exporter.go 支持 JSON/CSV 两种快照格式。

欢迎贡献更多协议扩展、输出格式或改进数据处理逻辑!

相关推荐
埃和智能1 天前
快速实现PLC设备、智能仪表的数据转换OPC UA服务端标签(含客户端测试)
数据采集·modbus·opc ua·opc网关·plc通讯·数据标签·ua 服务端
星野云联AIoT技术洞察5 天前
A2A、MCP、OPC UA、Modbus:Agentic IoT 控制平面的分层设计
modbus·opc ua·mcp·a2a·工业 iot·agentic iot·控制平面
星野云联AIoT技术洞察9 天前
工业 IoT 协议适配层应该怎么设计:Modbus、OPC UA、MQTT 与 HTTP 如何统一
mqtt·数据建模·modbus·opc ua·http api·协议适配层·工业 iot
疆鸿智能研发小助手10 天前
全兼容·真实时·稳如磐石:EtherCAT转Modbus网关赋能医药高端制造
modbus·工业自动化·ethercat·工业通讯·modbus rtu·协议转换网关
MDIOT旗舰10 天前
4G低功耗边缘计算网关:让智能抄表与远程运维从未如此简单
运维·人工智能·边缘计算·modbus·红外抄表·plc智能网关
若汝棋茗11 天前
用 TouchSocket.Modbus 从 0 到 1:把 Modbus 主站、从站、对象映射和多设备桥接一次讲透
modbus
MC皮蛋侠客14 天前
Modbus Poll 使用文档
物联网·modbus·调试
疆鸿智能研发小助手15 天前
注塑机协议互通改造:Ethernet IP转Modbus RTU的实战应用
modbus·工业自动化·ethernet ip·工业通讯·modbus rtu·协议转换网关
疆鸿智能研发小助手15 天前
压延机“语言不通”?ETHERNET IP转MODBUS RTU来解决
modbus·工业自动化·ethernet ip·工业通讯·modbus rtu·协议转换网关
星野云联AIoT技术洞察22 天前
OPC UA、MQTT、Modbus 应该如何分层:工业 IoT 接入架构新思路
mqtt·modbus·opc ua·边缘网关·设备接入·协议分层·工业iot