You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Pymodbus 2.5.3,运行时更新Modbus Slave上下文的最佳方案

实现Pymodbus 2.5.3 Slave运行时上下文更新

针对你的需求,以下是适配Pymodbus 2.5.3版本的同步Slave运行时更新上下文的最佳实现方案,核心是利用线程安全的上下文访问+后台线程完成动态更新:

核心实现思路

  1. 为多Slave创建独立的ModbusSlaveContext,构建多Slave模式的服务器上下文
  2. 用后台线程定期/按需更新指定Slave的寄存器,通过全局锁保证多线程访问的线程安全
  3. 直接操作上下文的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 20:26:16