From 99d3bccdf487c31a89d9e2085e3dcd582b272021 Mon Sep 17 00:00:00 2001 From: Alois Hockenschlohe <22458243+aloishockenschlohe@users.noreply.github.com> Date: Thu, 3 Aug 2023 22:19:20 +0200 Subject: [PATCH 1/4] Update server_updating.py Added some comments to explain the code a bit better. Changed the update routine to have a more expressive example. --- examples/server_updating.py | 47 ++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/examples/server_updating.py b/examples/server_updating.py index 91ee4a2f0..3da7ff1a7 100755 --- a/examples/server_updating.py +++ b/examples/server_updating.py @@ -1,7 +1,7 @@ -#!/usr/bin/env python3 -"""Pymodbus asynchronous Server Example. +"""Pymodbus asynchronous Server with updating subroutine Example. -An example of a multi threaded asynchronous server. +An example of an asynchronous server with multiple threads and +a subroutine that runs continuously alongside the server and updates values. usage: server_async.py [-h] [--comm {tcp,udp,serial,tls}] [--framer {ascii,binary,rtu,socket,tls}] @@ -16,6 +16,7 @@ --comm {tcp,udp,serial,tls} "serial", "tcp", "udp" or "tls" --framer {ascii,binary,rtu,socket,tls} + "ascii", "binary", "rtu", "socket" or "tls" --log {critical,error,warning,info,debug} "critical", "error", "warning", "info" or "debug" @@ -42,20 +43,38 @@ async def updating_task(context): - """Run every so often and update live values of the context. + """ + This subroutine will run continously beside the server and + increment each two seconds some values (via asyncio.create_task + in run_updating_server). - It should be noted that there is a race condition for the update. + It should be noted that getValues and setValues are not thread safe. """ - _logger.debug("updating the context") + fc_as_hex = 3 slave_id = 0x00 - address = 0x10 - values = context[slave_id].getValues(fc_as_hex, address, count=5) - values = [v + 1 for v in values] # increment by 1. - txt = f"new values: {values!s}" - _logger.debug(txt) + address = 7 + + # set values to zero + values = context[slave_id].getValues(fc_as_hex, address, count=6) + values = [0 for v in values] context[slave_id].setValues(fc_as_hex, address, values) - await asyncio.sleep(1) + + txt = f"updating_task: started: initialised values: {values!s} at address {address!s}" + print(txt) + _logger.debug(txt) + + # incrementing loop + while True: + await asyncio.sleep(5) + + values = context[slave_id].getValues(fc_as_hex, address, count=6) + values = [v + 1 for v in values] + context[slave_id].setValues(fc_as_hex, address, values) + + txt = f"updating_task: incemented values: {values!s} at address {address!s}" + print(txt) + _logger.debug(txt) def setup_updating_server(cmdline=None): @@ -76,8 +95,8 @@ def setup_updating_server(cmdline=None): async def run_updating_server(args): """Start updater task and async server.""" - asyncio.create_task(updating_task(args.context)) # noqa: RUF006 - await run_async_server(args) + asyncio.create_task(updating_task(args.context)) # start updating_task concurrently with the current task + await run_async_server(args) # start the server async def main(cmdline=None): From 44291d813a4fa07177711df731dabecf50273751 Mon Sep 17 00:00:00 2001 From: Alois Hockenschlohe <22458243+aloishockenschlohe@users.noreply.github.com> Date: Sat, 5 Aug 2023 22:39:17 +0200 Subject: [PATCH 2/4] Update server_updating.py --- examples/server_updating.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/examples/server_updating.py b/examples/server_updating.py index 3da7ff1a7..ada5c1dae 100755 --- a/examples/server_updating.py +++ b/examples/server_updating.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 """Pymodbus asynchronous Server with updating subroutine Example. An example of an asynchronous server with multiple threads and @@ -44,19 +45,21 @@ async def updating_task(context): """ - This subroutine will run continously beside the server and - increment each two seconds some values (via asyncio.create_task - in run_updating_server). + This subroutine runs continously beside the server + (via asyncio.create_task in run_updating_server). + It will increment some values each two seconds. - It should be noted that getValues and setValues are not thread safe. + It should be noted that getValues and setValues are not safe + against concurrent use. """ fc_as_hex = 3 slave_id = 0x00 - address = 7 + address = 0x10 + c = 6 # set values to zero - values = context[slave_id].getValues(fc_as_hex, address, count=6) + values = context[slave_id].getValues(fc_as_hex, address, count=c) values = [0 for v in values] context[slave_id].setValues(fc_as_hex, address, values) @@ -66,13 +69,13 @@ async def updating_task(context): # incrementing loop while True: - await asyncio.sleep(5) + await asyncio.sleep(2) - values = context[slave_id].getValues(fc_as_hex, address, count=6) + values = context[slave_id].getValues(fc_as_hex, address, count=c) values = [v + 1 for v in values] context[slave_id].setValues(fc_as_hex, address, values) - txt = f"updating_task: incemented values: {values!s} at address {address!s}" + txt = f"updating_task: incremented values: {values!s} at address {address!s}" print(txt) _logger.debug(txt) @@ -94,8 +97,9 @@ def setup_updating_server(cmdline=None): async def run_updating_server(args): - """Start updater task and async server.""" - asyncio.create_task(updating_task(args.context)) # start updating_task concurrently with the current task + """start updating_task concurrently with the current task""" + asyncio.create_task(updating_task(args.context)) + """start the server""" await run_async_server(args) # start the server From f3329b7312730a54837a00984668dc5b4d7f4c8a Mon Sep 17 00:00:00 2001 From: jan iversen Date: Sun, 13 Aug 2023 09:37:53 +0200 Subject: [PATCH 3/4] fix. --- examples/server_updating.py | 41 ++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/examples/server_updating.py b/examples/server_updating.py index ada5c1dae..7f99ad251 100755 --- a/examples/server_updating.py +++ b/examples/server_updating.py @@ -1,10 +1,10 @@ #!/usr/bin/env python3 -"""Pymodbus asynchronous Server with updating subroutine Example. +"""Pymodbus asynchronous Server with updating task Example. -An example of an asynchronous server with multiple threads and -a subroutine that runs continuously alongside the server and updates values. +An example of an asynchronous server and +a task that runs continuously alongside the server and updates values. -usage: server_async.py [-h] [--comm {tcp,udp,serial,tls}] +usage: server_updating.py [-h] [--comm {tcp,udp,serial,tls}] [--framer {ascii,binary,rtu,socket,tls}] [--log {critical,error,warning,info,debug}] [--port PORT] [--store {sequential,sparse,factory,none}] @@ -15,14 +15,17 @@ options: -h, --help show this help message and exit --comm {tcp,udp,serial,tls} + "serial", "tcp", "udp" or "tls" --framer {ascii,binary,rtu,socket,tls} "ascii", "binary", "rtu", "socket" or "tls" --log {critical,error,warning,info,debug} + "critical", "error", "warning", "info" or "debug" --port PORT the port to use --store {sequential,sparse,factory,none} + "sequential", "sparse", "factory" or "none" --slaves SLAVES number of slaves to respond to @@ -44,8 +47,9 @@ async def updating_task(context): - """ - This subroutine runs continously beside the server + """Update values in server. + + This task runs continuously beside the server (via asyncio.create_task in run_updating_server). It will increment some values each two seconds. @@ -56,23 +60,25 @@ async def updating_task(context): fc_as_hex = 3 slave_id = 0x00 address = 0x10 - c = 6 - + count = 6 + # set values to zero - values = context[slave_id].getValues(fc_as_hex, address, count=c) + values = context[slave_id].getValues(fc_as_hex, address, count=count) values = [0 for v in values] context[slave_id].setValues(fc_as_hex, address, values) - txt = f"updating_task: started: initialised values: {values!s} at address {address!s}" + txt = ( + f"updating_task: started: initialised values: {values!s} at address {address!s}" + ) print(txt) _logger.debug(txt) - # incrementing loop + # incrementing loop while True: await asyncio.sleep(2) - - values = context[slave_id].getValues(fc_as_hex, address, count=c) - values = [v + 1 for v in values] + + values = context[slave_id].getValues(fc_as_hex, address, count=count) + values = [v + 1 for v in values] context[slave_id].setValues(fc_as_hex, address, values) txt = f"updating_task: incremented values: {values!s} at address {address!s}" @@ -97,10 +103,11 @@ def setup_updating_server(cmdline=None): async def run_updating_server(args): - """start updating_task concurrently with the current task""" - asyncio.create_task(updating_task(args.context)) + """Start updating_task concurrently with the current task""" + task = asyncio.create_task(updating_task(args.context)) """start the server""" - await run_async_server(args) # start the server + await run_async_server(args) # start the server + task.cancel() async def main(cmdline=None): From 510f7fd69ce0bb02f1cb5001b2d21167f21ab81a Mon Sep 17 00:00:00 2001 From: jan iversen Date: Sun, 13 Aug 2023 09:37:53 +0200 Subject: [PATCH 4/4] fix. --- examples/server_updating.py | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/server_updating.py b/examples/server_updating.py index 7f99ad251..2e1ce9875 100755 --- a/examples/server_updating.py +++ b/examples/server_updating.py @@ -105,7 +105,6 @@ def setup_updating_server(cmdline=None): async def run_updating_server(args): """Start updating_task concurrently with the current task""" task = asyncio.create_task(updating_task(args.context)) - """start the server""" await run_async_server(args) # start the server task.cancel()