pymodbus: обновить контекст работающего сервера - PullRequest
1 голос
/ 19 октября 2019

У меня работает сервер ModbusRTU, следуя этому примеру. Я знаю, как обновить контекст, но я не могу обновить контекст работающего сервера.

Когда я обновляю контекст в функции run_updating_server () (до StartSerialServer ()), тогда он работает нормально. Но когда я пытаюсь обновить текущий контекст, вызывая update_writer (context), он не обновляется.

Также вызов моей собственной функции getUpdatedContext () из-за update_writer () не работает:

 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)

getContext ():

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, я попытался:

  • вызов update_writer (a) из этого «другого скрипта на python», где a = updatedContext.

  • вызов getUpdatedContext () из-за отсутствия update_writer (a), который является функцией в «этом другом скрипте 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()

Как мне взаимодействовать с update_writer? Чего я хочу добиться, так это того, чтобы мой сервер modbusRTU работал и обновлял контекст из другой угрозы, чтобы мой клиент Modbus (основной) мог читать заполненные регистры.

...