1

按照这个例子,我有一个正在运行的 ModbusRTU 服务器。我知道如何更新上下文,但我无法更新正在运行的服务器的上下文。

当我更新 run_updating_server() 函数中的上下文时(在 StartSerialServer() 之前),它工作正常。但是当我尝试通过调用 update_writer(context) 来更新运行上下文时,它不会更新。

从 withingupdate_writer() 调用我自己的函数 'getUpdatedContext()' 也不起作用:

 def updating_writer(a):
    a =(getContext(),)
    """ A worker process that runs every so often and
    updates live values of the context. It should be noted
    that there is a race condition for the update.
    :param arguments: The input arguments to the call
    """

    log.debug("updating the context")
    context = a[0]
    register = 3
    slave_id = 0x41
    address = 0x10
    values = context[slave_id].getValues(register, address, count=5)
    values = [v + 1 for v in values]
    log.debug("new values: " + str(values))
    context[slave_id].setValues(register, address, values)

获取上下文():

def getContext():
    store = ModbusSlaveContext(
      di=ModbusSequentialDataBlock(0, [17]*100),
      co=ModbusSequentialDataBlock(0, [17]*100),
      hr=ModbusSequentialDataBlock(0, [17]*100),
      ir=ModbusSequentialDataBlock(0, [17]*100))

    store.setValues(5, 1, [0])
    context = ModbusServerContext(slaves=store, single=True)
    return context

我的完整代码:

#!/usr/bin/env python

import os
import sys
"""
Pymodbus Server With Updating Thread
--------------------------------------------------------------------------
This is an example of having a background thread updating the
context while the server is operating. This can also be done with
a python thread::
    from threading import Thread
    thread = Thread(target=updating_writer, args=(context,))
    thread.start()
"""
# --------------------------------------------------------------------------- #
# import the modbus libraries we need
# --------------------------------------------------------------------------- #
from pymodbus.server.asynchronous import StartSerialServer
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.datastore import ModbusSequentialDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
from pymodbus.transaction import ModbusRtuFramer, ModbusAsciiFramer

# --------------------------------------------------------------------------- #
# import the twisted libraries we need
# --------------------------------------------------------------------------- #
from twisted.internet.task import LoopingCall

# --------------------------------------------------------------------------- #
# configure the service logging
# --------------------------------------------------------------------------- #
import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)

# --------------------------------------------------------------------------- #
# define your callback process
# --------------------------------------------------------------------------- #
def updating_writer(a):
    """ A worker process that runs every so often and
    updates live values of the context. It should be noted
    that there is a race condition for the update.
    :param arguments: The input arguments to the call
    """

    log.debug("updating the context")
    context = a[0]
    register = 3
    slave_id = 0x41
    address = 0x10
    values = context[slave_id].getValues(register, address, count=5)
    values = [v + 1 for v in values]
    log.debug("new values: " + str(values))
    context[slave_id].setValues(register, address, values)

def run_updating_server():
    # ----------------------------------------------------------------------- # 
    # initialize your data store
    # ----------------------------------------------------------------------- # 

    store = ModbusSlaveContext(
        di=ModbusSequentialDataBlock(0, [17]*100),
        co=ModbusSequentialDataBlock(0, [17]*100),
        hr=ModbusSequentialDataBlock(0, [17]*100),
        ir=ModbusSequentialDataBlock(0, [17]*100))

    context = ModbusServerContext(slaves=store, single=True)

    # ----------------------------------------------------------------------- # 
    # initialize the server information
    # ----------------------------------------------------------------------- # 
    identity = ModbusDeviceIdentification()
    identity.VendorName = 'pymodbus'
    identity.ProductCode = 'PM'
    identity.VendorUrl = 'http://github.com/bashwork/pymodbus/'
    identity.ProductName = 'pymodbus Server'
    identity.ModelName = 'pymodbus Server'
    identity.MajorMinorRevision = '2.2.0'

    # ----------------------------------------------------------------------- # 
    # run the server you want
    # ----------------------------------------------------------------------- # 
    time = 5
    loop = LoopingCall(f=updating_writer, a=(context,))
    loop.start(time, now=False)  # initially delay by time

    log.debug("::: Starting Modbus RTU server :::")

    # RTU:
    StartSerialServer(context, framer=ModbusRtuFramer, identity=identity,
                      port='/dev/ttyUSB0', 
                      timeout=2, 
                      baudrate=115200, 
                      parity='E',
                      bytesize=8,
                      stopbits=1)

def main():
    pid = str(os.getpid())
    filename = 'modbusUpdatingServer.pid'
    pidfile = str(os.getcwd()) + '/' + filename 
    if os.path.isfile(pidfile):
        print (filename + " already exists \n exiting")
        sys.exit()
    open(pidfile, 'w').write(pid)
    try:
        # run server
        run_updating_server()
    finally:
        os.unlink(pidfile)

if __name__ == "__main__":
    main()

我想从另一个 python 脚本更新上下文,我试过:

  • 从该“其他python脚本”调用updated_writer(a),其中a = updatedContext。

  • 从withingupdate_writer(a)调用getUpdatedContext(),这是“那个其他python脚本”中的一个函数,它返回updatedContext

  • 使上下文全局化,添加一个函数 updateContext(a),从另一个 python 脚本调用该函数。

这一切都导致编译代码,但运行服务器的上下文没有得到更新。

这里是来自“其他python脚本”的代码:

from pymodbus.datastore import ModbusSequentialDataBlock, ModbusSlaveContext, ModbusServerContext
from threading import Thread
import os
import subprocess
import sys

from modbusUpdatingServer import updating_writer, run_updating_server

def writeUpdatedContext():
    store = ModbusSlaveContext(
    di=ModbusSequentialDataBlock(0, [17]*100),
    co=ModbusSequentialDataBlock(0, [17]*100),
    hr=ModbusSequentialDataBlock(0, [17]*100),
    ir=ModbusSequentialDataBlock(0, [17]*100))

    store.setValues(5, 1, [0])

    context = ModbusServerContext(slaves=store, single=True)
    updating_writer(a=(context,)   

def main():
    choice = input("press x if you want to update the context")

    if choice == 'x' or choice == 'X':
        writeUpdatedContext()


if __name__ == "__main__":
    main()

我应该如何与updated_writer交互?我想要实现的是我的 modbusRTU 服务器正在运行,并从另一个威胁中更新上下文,所以我的 modbus 客户端(主)可以读取我填写的寄存器。

4

0 回答 0