Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions examples/client_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def setup_client(args):
elif args.comm == "udp":
client = ModbusUdpClient(
"localhost",
# port=502,
port=args.port,
# Common optional paramers:
# modbus_decoder=ClientDecoder,
framer=args.framer,
Expand Down Expand Up @@ -122,9 +122,12 @@ def run_client(modbus_calls=None, args=None):
"""Run sync client."""
_logger.info("### Client ready")
client = setup_client(args)
client.connect()
if modbus_calls:
modbus_calls(client)
try:
client.connect()
if modbus_calls:
modbus_calls(client)
except: # pylint: disable=bare-except # noqa: E722
_logger.error("Got exception in client.")
client.close()
_logger.info("### End of Program")

Expand Down
31 changes: 18 additions & 13 deletions examples/server_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ def setup_server(args):
"""Run server setup."""
if not args:
args = get_commandline()
defer_start = False # No function.
else:
defer_start = True # Needed when running tests, otherwise no function.

# The datastores only respond to the addresses that are initialized
# If you initialize a DataBlock to addresses of 0x00 to 0xFF, a request to
Expand Down Expand Up @@ -136,16 +139,16 @@ def setup_server(args):
)
if args.comm != "serial":
args.port = int(args.port)
return args.comm, args.port, store, identity, args.framer
return args.comm, args.port, store, identity, args.framer, defer_start


async def run_server(args=None):
"""Run server."""
server, port, store, identity, framer = setup_server(args)
server_id, port, store, identity, framer, defer_start = setup_server(args)

_logger.info("### start server")
if server == "tcp":
server_obj = await StartTcpServer(
if server_id == "tcp":
server = StartTcpServer(
context=store, # Data storage
identity=identity, # server identify
# TBD host=
Expand All @@ -159,9 +162,10 @@ async def run_server(args=None):
broadcast_enable=False, # treat unit_id 0 as broadcast address,
# TBD timeout=1, # waiting time for request to complete
# TBD strict=True, # use strict timing, t1.5 for Modbus RTU
defer_start=defer_start # Only define server do not activate
)
elif server == "udp":
server_obj = await StartUdpServer(
elif server_id == "udp":
server = StartUdpServer(
context=store, # Data storage
identity=identity, # server identify
address=("", port), # listen address
Expand All @@ -173,11 +177,12 @@ async def run_server(args=None):
broadcast_enable=False, # treat unit_id 0 as broadcast address,
# TBD timeout=1, # waiting time for request to complete
# TBD strict=True, # use strict timing, t1.5 for Modbus RTU
defer_start=defer_start # Only define server do not activate
)
elif server == "serial":
elif server_id == "serial":
# socat -d -d PTY,link=/tmp/ptyp0,raw,echo=0,ispeed=9600 PTY,
# link=/tmp/ttyp0,raw,echo=0,ospeed=9600
server_obj = await StartSerialServer(
server = StartSerialServer(
context=store, # Data storage
identity=identity, # server identify
timeout=0.005, # waiting time for request to complete
Expand All @@ -193,9 +198,10 @@ async def run_server(args=None):
ignore_missing_slaves=True, # ignore request to a missing slave
broadcast_enable=False, # treat unit_id 0 as broadcast address,
strict=True, # use strict timing, t1.5 for Modbus RTU
defer_start=defer_start # Only define server do not activate
)
elif server == "tls":
server_obj = await StartTlsServer(
elif server_id == "tls":
server = StartTlsServer(
context=store, # Data storage
host="localhost", # define tcp address where to connect to.
port=port, # on which port
Expand All @@ -214,10 +220,9 @@ async def run_server(args=None):
broadcast_enable=False, # treat unit_id 0 as broadcast address,
# TBD timeout=1, # waiting time for request to complete
# TBD strict=True, # use strict timing, t1.5 for Modbus RTU
defer_start=defer_start # Only define server do not activate
)
asyncio.get_event_loop().call_later(20, lambda: server.serve_forever)
await server_obj.serve_forever()

return server

# --------------------------------------------------------------------------- #
# Extra code, to allow commandline parameters instead of changing the code
Expand Down
26 changes: 17 additions & 9 deletions examples/server_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ def setup_server(args):
"""Run server setup."""
if not args:
args = get_commandline()
defer_start = False # No function.
else:
defer_start = True # Needed when running tests, otherwise no function.

# The datastores only respond to the addresses that are initialized
# If you initialize a DataBlock to addresses of 0x00 to 0xFF, a request to
Expand Down Expand Up @@ -135,14 +138,14 @@ def setup_server(args):
)
if args.comm != "serial":
args.port = int(args.port)
return args.comm, args.port, store, identity, args.framer, args.prepare
return args.comm, args.port, store, identity, args.framer, defer_start


def run_server(args=None):
"""Run server."""
server_id, port, store, identity, framer, prepare = setup_server(args)

_logger.info("### start server")
server_id, port, store, identity, framer, defer_start = setup_server(args)
txt = f"### start server, listening on {port} - {server_id}"
_logger.info(txt)
if server_id == "tcp":
server = StartTcpServer(
context=store, # Data storage
Expand All @@ -158,21 +161,24 @@ def run_server(args=None):
# broadcast_enable=False, # treat unit_id 0 as broadcast address,
# TBD timeout=1, # waiting time for request to complete
# TBD strict=True, # use strict timing, t1.5 for Modbus RTU
prepare=prepare # Only prepare server do not activate, INTERNAL.
defer_start=defer_start # Only define server do not activate
)
elif server_id == "udp":
server = StartUdpServer(
context=store, # Data storage
identity=identity, # server identify
# TBD host=
# TBD port=
address=("", port), # listen address
custom_functions=[], # allow custom handling
# custom_functions=[], # allow custom handling
framer=framer, # The framer strategy to use
handler=None, # handler for each session
# TBD handler=None, # handler for each session
# TBD allow_reuse_address=True, # allow the reuse of an address
ignore_missing_slaves=True, # ignore request to a missing slave
broadcast_enable=False, # treat unit_id 0 as broadcast address,
# ignore_missing_slaves=True, # ignore request to a missing slave
# broadcast_enable=False, # treat unit_id 0 as broadcast address,
# TBD timeout=1, # waiting time for request to complete
# TBD strict=True, # use strict timing, t1.5 for Modbus RTU
defer_start=defer_start # Only define server do not activate
)
elif server_id == "serial":
# socat -d -d PTY,link=/tmp/ptyp0,raw,echo=0,ispeed=9600 PTY,
Expand All @@ -193,6 +199,7 @@ def run_server(args=None):
ignore_missing_slaves=True, # ignore request to a missing slave
broadcast_enable=False, # treat unit_id 0 as broadcast address,
strict=True, # use strict timing, t1.5 for Modbus RTU
defer_start=defer_start # Only define server do not activate
)
elif server_id == "tls":
server = StartTlsServer(
Expand All @@ -214,6 +221,7 @@ def run_server(args=None):
broadcast_enable=False, # treat unit_id 0 as broadcast address,
# TBD timeout=1, # waiting time for request to complete
# TBD strict=True, # use strict timing, t1.5 for Modbus RTU
defer_start=defer_start # Only define server do not activate
)
return server

Expand Down
56 changes: 26 additions & 30 deletions pymodbus/server/async_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,7 @@ def connection_lost(self, call_exc):
_logger.debug(txt)

self.running = False

except Exception as exc: # pragma: no cover pylint: disable=broad-except
except Exception as exc: # pylint: disable=broad-except
txt = (
f"Datastore unable to fulfill request: {exc}; {traceback.format_exc()}"
)
Expand Down Expand Up @@ -858,9 +857,9 @@ async def StartTcpServer( # pylint: disable=invalid-name,dangerous-default-valu
:param address: An optional (interface, port) to bind to.
:param custom_functions: An optional list of custom function classes
supported by server instance.
:param defer_start: if set, a coroutine which can be started and stopped
will be returned. Otherwise, the server will be immediately spun
up without the ability to shut it off from within the asyncio loop
:param defer_start: if set, the server object will be returned ready to start.
Otherwise, the server will be immediately spun
up without the ability to shut it off
:param kwargs: The rest
:return: an initialized but inactive server object coroutine
"""
Expand All @@ -870,10 +869,9 @@ async def StartTcpServer( # pylint: disable=invalid-name,dangerous-default-valu
for func in custom_functions:
server.decoder.register(func) # pragma: no cover

if not defer_start:
await server.serve_forever()

return server
if defer_start:
return server
await server.serve_forever()


async def StartTlsServer( # pylint: disable=invalid-name,dangerous-default-value,too-many-arguments
Expand Down Expand Up @@ -906,9 +904,9 @@ async def StartTlsServer( # pylint: disable=invalid-name,dangerous-default-valu
:param allow_reuse_port: Whether the server will allow the reuse of a port.
:param custom_functions: An optional list of custom function classes
supported by server instance.
:param defer_start: if set, a coroutine which can be started and stopped
will be returned. Otherwise, the server will be immediately spun
up without the ability to shut it off from within the asyncio loop
:param defer_start: if set, the server object will be returned ready to start.
Otherwise, the server will be immediately spun
up without the ability to shut it off
:param kwargs: The rest
:return: an initialized but inactive server object coroutine
"""
Expand All @@ -931,10 +929,9 @@ async def StartTlsServer( # pylint: disable=invalid-name,dangerous-default-valu
for func in custom_functions:
server.decoder.register(func) # pragma: no cover

if not defer_start:
await server.serve_forever()

return server
if defer_start:
return server
await server.serve_forever()


async def StartUdpServer( # pylint: disable=invalid-name,dangerous-default-value
Expand All @@ -952,7 +949,9 @@ async def StartUdpServer( # pylint: disable=invalid-name,dangerous-default-valu
:param address: An optional (interface, port) to bind to.
:param custom_functions: An optional list of custom function classes
supported by server instance.
:param defer_start: start with delay
:param defer_start: if set, the server object will be returned ready to start.
Otherwise, the server will be immediately spun
up without the ability to shut it off
:param kwargs:
"""
framer = kwargs.pop("framer", ModbusSocketFramer)
Expand All @@ -961,16 +960,16 @@ async def StartUdpServer( # pylint: disable=invalid-name,dangerous-default-valu
for func in custom_functions:
server.decoder.register(func) # pragma: no cover

if not defer_start:
await server.serve_forever() # pragma: no cover

return server
if defer_start:
return server
await server.serve_forever()


async def StartSerialServer( # pylint: disable=invalid-name,dangerous-default-value
context=None,
identity=None,
custom_functions=[],
defer_start=False,
**kwargs,
): # pragma: no cover
"""Start and run a serial modbus server.
Expand All @@ -979,25 +978,22 @@ async def StartSerialServer( # pylint: disable=invalid-name,dangerous-default-v
:param identity: An optional identify structure
:param custom_functions: An optional list of custom function classes
supported by server instance.
:param defer_start: if set, the server object will be returned ready to start.
Otherwise, the server will be immediately spun
up without the ability to shut it off
:param kwargs: The rest
"""
framer = kwargs.pop("framer", ModbusAsciiFramer)
server = ModbusSerialServer(context, framer, identity=identity, **kwargs)
for func in custom_functions:
server.decoder.register(func)

if defer_start:
return server
await server.start()
await server.serve_forever()


def StopServer(): # pylint: disable=invalid-name
"""Stop Async Server."""
warnings.warn(
"deprecated API for asyncio. Call server_close() on "
"server object returned by StartXxxServer",
DeprecationWarning,
)


# --------------------------------------------------------------------------- #
# Exported symbols
# --------------------------------------------------------------------------- #
Expand Down
Loading