I have a running ModbusRTU server, following this example. I know how to update the context, but I can't update the context of a running server.
When I update the context in the run_updating_server() function (before StartSerialServer()) then it works fine. But when I try to update the running context by calling updating_writer(context) then it doesn't update.
Also calling my own function 'getUpdatedContext()' from withing updating_writer() does not work:
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
my full code:
#!/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()
I want to update the context from another python script, i tried:
calling updating_writer(a) from that 'other python script', where a = updatedContext.
calling getUpdatedContext(), from withing updating_writer(a), which is a function in 'that other python script' which returns the updatedContext
make the context global, add a function updateContext(a), call that function from another python script.
It all resulted in compiling code, but the context of the running server didn't get updated.
here the code from the 'other python script':
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()
How am I supposed to interact with updating_writer? What I want to achieve is my modbusRTU server running, and updating the context from another threat, so my modbus client(master) can read the registers I've filled.