如果需要成百上千个设备 或复杂的数据动态变化逻辑 ,可以用 Python 的 pymodbus 库进行模拟。
Modbus TCP 支持在单个 TCP 端口(如 502) 上基于请求头中的 Unit ID 区分不同从站设备。
1. 安装依赖
Bash
python
pip install pymodbus
2. 模拟多个从站的代码示例
下面的完整代码展示了如何在同一个 TCP 服务端上注册 Slave ID 1、Slave ID 2 和 Slave ID 3,并让它们的数据自动定时更新:
适用于 pymodbus 2.5.3 的完整代码
请直接用下面的代码覆盖你的 py.py:
python
pip uninstall pymodbus -y
pip install pymodbus==2.5.3
python
import threading
import time
import random
# 1. pymodbus 2.5.3 标准导入路径
from pymodbus.server.sync import StartTcpServer
from pymodbus.datastore import (
ModbusSlaveContext,
ModbusServerContext,
ModbusSequentialDataBlock,
)
# 2. 创建设备上下文(寄存器映射)
def create_device_context():
return ModbusSlaveContext(
di=ModbusSequentialDataBlock(0, [0] * 100), # 离散输入
co=ModbusSequentialDataBlock(0, [0] * 100), # 线圈
hr=ModbusSequentialDataBlock(0, [10, 20, 30, 40]), # 保持寄存器
ir=ModbusSequentialDataBlock(0, [100, 200, 300]), # 输入寄存器
)
# 3. 批量生成 500 个设备 (Slave ID: 1 到 500)
TOTAL_DEVICES = 500
slaves = {slave_id: create_device_context() for slave_id in range(1, TOTAL_DEVICES + 1)}
context = ModbusServerContext(slaves=slaves, single=False)
# 4. 后台线程:批量模拟数据动态变化
def update_values(context):
while True:
time.sleep(2) # 每 2 秒更新一次
# 遍历 1 到 500 的所有设备
for slave_id in range(1, TOTAL_DEVICES + 1):
slave_ctx = context[slave_id]
# 读取保持寄存器 0 (对应 40001)
current_val = slave_ctx.getValues(3, 0, count=1)[0]
new_val = (current_val + random.randint(-2, 2)) % 100
# 写入新值
slave_ctx.setValues(3, 0, [new_val])
# 避免 500 条日志刷屏,仅打印前 3 个和后 3 个设备的状态作为示例
val1 = context[1].getValues(3, 0, count=1)[0]
val500 = context[500].getValues(3, 0, count=1)[0]
print(f"[数据更新中] 共有 {TOTAL_DEVICES} 个设备已更新 | 样例 -> Slave 1: {val1} | Slave 500: {val500}")
if __name__ == "__main__":
# 启动后台更新线程
t = threading.Thread(target=update_values, args=(context,), daemon=True)
t.start()
print(f"Modbus TCP 服务端已启动,监听端口 502...")
print(f"已批量激活设备 ID (Unit ID): 1 ~ {TOTAL_DEVICES}")
# 启动同步 Modbus TCP 服务器
StartTcpServer(context=context, address=("0.0.0.0", 502))