基于Pymodbus 2.5.3,运行时更新Modbus Slave上下文的最佳方案
实现Pymodbus 2.5.3 Slave运行时上下文更新
针对你的需求,以下是适配Pymodbus 2.5.3版本的同步Slave运行时更新上下文的最佳实现方案,核心是利用线程安全的上下文访问+后台线程完成动态更新:
核心实现思路
- 为多Slave创建独立的
ModbusSlaveContext,构建多Slave模式的服务器上下文 - 用后台线程定期/按需更新指定Slave的寄存器,通过全局锁保证多线程访问的线程安全
- 直接操作上下文的
getValues/setValues方法完成寄存器值更新,适配2.5.3版本API
完整代码示例
from pymodbus.server.sync import StartSerialServer from pymodbus.device import ModbusDeviceIdentification from pymodbus.datastore import ModbusSequentialDataBlock, ModbusSlaveContext, ModbusServerContext import threading import time # ---------------------- 初始化Slave上下文 ---------------------- # Slave 1:保持寄存器0-3099(共3100个) slave_1_ctx = ModbusSlaveContext( di=ModbusSequentialDataBlock(0, [0]*100), # 离散输入(按需配置) co=ModbusSequentialDataBlock(0, [0]*100), # 线圈(按需配置) hr=ModbusSequentialDataBlock(0, [0]*3100), # 保持寄存器(核心) ir=ModbusSequentialDataBlock(0, [0]*100) # 输入寄存器(按需配置) ) # Slave 248:同样配置3100个保持寄存器 slave_248_ctx = ModbusSlaveContext( di=ModbusSequentialDataBlock(0, [0]*100), co=ModbusSequentialDataBlock(0, [0]*100), hr=ModbusSequentialDataBlock(0, [0]*3100), ir=ModbusSequentialDataBlock(0, [0]*100) ) # 构建多Slave服务器上下文 server_ctx = ModbusServerContext( slaves={1: slave_1_ctx, 248: slave_248_ctx}, single=False # 启用多Slave模式 ) # 服务器标识(可选,可根据需求修改) server_identity = ModbusDeviceIdentification() server_identity.VendorName = 'TestSlave' server_identity.ProductName = 'AutoTestSlave' server_identity.MajorMinorRevision = '2.5.3' # ---------------------- 上下文更新线程 ---------------------- # 全局锁:保证主站读写与后台更新线程的上下文访问互斥 ctx_lock = threading.Lock() def update_slave1_registers(): """后台线程:动态更新Slave 1的保持寄存器""" while True: # 模拟测试数据更新:这里以递增寄存器100-109为例 with ctx_lock: # 获取Slave 1的保持寄存器模块 hr_block = server_ctx[1].hr # 读取当前值(可选,若不需要基于旧值更新可跳过) current_vals = hr_block.getValues(100, count=10) # 生成新测试值(替换为你的自动化测试逻辑) new_vals = [(val + 1) % 65536 for val in current_vals] # 写入新值到寄存器 hr_block.setValues(100, new_vals) print("Slave 1 寄存器100-109已更新") time.sleep(5) # 更新间隔,按需调整 # ---------------------- 启动服务与线程 ---------------------- if __name__ == "__main__": # 启动后台更新线程(设为守护线程,随主进程退出) update_thread = threading.Thread(target=update_slave1_registers, daemon=True) update_thread.start() # 启动同步串口Modbus Slave服务器 # 注意:串口参数必须与STM32主站完全匹配 StartSerialServer( context=server_ctx, identity=server_identity, port='/dev/ttyUSB0', # Windows系统替换为COMx,比如COM3 baudrate=9600, parity='N', stopbits=1, bytesize=8 )
关键注意事项
- 线程安全:所有对上下文的读写操作(包括后台更新和主站的Modbus请求)必须通过
ctx_lock加锁,避免数据竞争导致的异常 - API适配:2.5.3版本中,
ModbusSlaveContext的保持寄存器模块通过.hr访问,getValues/setValues是标准读写方法,不要使用新版本的API - 自定义更新逻辑:将示例中的递增逻辑替换为你的自动化测试数据生成逻辑,比如从测试用例文件读取、根据测试场景生成特定值等
- 串口参数匹配:务必保证
StartSerialServer的串口参数(波特率、奇偶校验、停止位、数据位)与STM32主站完全一致,否则通信会失败
内容的提问来源于stack exchange,提问作者PierreP
相关产品推荐
相关产品推荐

