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
57 changes: 23 additions & 34 deletions pymodbus/client/asynchronous/async_io/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,19 +231,18 @@ class ReconnectingAsyncioModbusTcpClient:
#: Maximum delay in milli seconds before reconnect is attempted.
DELAY_MAX_MS = 1000 * 60 * 5

def __init__(self, protocol_class=None, loop=None, framer=None, **kwargs):
def __init__(self, protocol_class=None, framer=None, **kwargs):
"""Initialize ReconnectingAsyncioModbusTcpClient.

:param protocol_class: Protocol used to talk to modbus device.
:param loop: Event loop to use
"""
# If there are no loop running a runtime error will be raised
self.loop = asyncio.get_running_loop()
#: Protocol used to talk to modbus device.
self.protocol_class = protocol_class or ModbusClientProtocol
#: Current protocol instance.
self.protocol = None
self.framer = framer if framer else ModbusSocketFramer
#: Event loop to use.
self.loop = loop or asyncio.get_event_loop()
self.host = None
self.port = 0
self.connected = False
Expand Down Expand Up @@ -341,21 +340,20 @@ async def _reconnect(self):
class AsyncioModbusTcpClient:
"""Client to connect to modbus device over TCP/IP."""

def __init__(self, host=None, port=502, protocol_class=None, loop=None, framer=None, **kwargs):
def __init__(self, host=None, port=502, protocol_class=None, framer=None, **kwargs):
"""Initialize Asyncio Modbus Tcp Client

:param host: Host IP address
:param port: Port to connect
:param protocol_class: Protocol used to talk to modbus device.
:param loop: Asyncio Event loop
"""
# If there are no loop running a runtime error will be raised
self.loop = asyncio.get_running_loop()
#: Protocol used to talk to modbus device.
self.protocol_class = protocol_class or ModbusClientProtocol
#: Current protocol instance.
self.protocol = None
self.framer = framer if framer else ModbusSocketFramer
#: Event loop to use.
self.loop = loop or asyncio.get_event_loop()

self.host = host
self.port = port
Expand Down Expand Up @@ -419,17 +417,18 @@ def protocol_lost_connection(self, protocol):
class ReconnectingAsyncioModbusTlsClient(ReconnectingAsyncioModbusTcpClient):
"""Client to connect to modbus device repeatedly over TLS."""

def __init__(self, protocol_class=None, loop=None, framer=None, **kwargs):
def __init__(self, protocol_class=None, framer=None, **kwargs):
"""Initialize ReconnectingAsyncioModbusTcpClient

:param protocol_class: Protocol used to talk to modbus device.
:param loop: Event loop to use
"""
# If there are no loop running a runtime error will be raised
self.loop = asyncio.get_running_loop()
self.framer = framer if framer else ModbusTlsFramer
self.server_hostname = None
self.sslctx = None
ReconnectingAsyncioModbusTcpClient.__init__(
self, protocol_class, loop, framer=self.framer, **kwargs
self, protocol_class, framer=self.framer, **kwargs
)

async def start(self, host, port=802, sslctx=None, server_hostname=None):
Expand Down Expand Up @@ -489,19 +488,18 @@ class ReconnectingAsyncioModbusUdpClient:
#: Maximum delay in milli seconds before reconnect is attempted.
DELAY_MAX_MS = 1000 * 60 * 5

def __init__(self, protocol_class=None, loop=None, framer=None, **kwargs):
def __init__(self, protocol_class=None, framer=None, **kwargs):
"""Initialize ReconnectingAsyncioModbusUdpClient

:param protocol_class: Protocol used to talk to modbus device.
:param loop: Asyncio Event loop
"""
# If there are no loop running a runtime error will be raised
self.loop = asyncio.get_running_loop()
#: Protocol used to talk to modbus device.
self.protocol_class = protocol_class or ModbusUdpClientProtocol
#: Current protocol instance.
self.protocol = None
self.framer = framer if framer else ModbusSocketFramer
#: Event loop to use.
self.loop = loop or asyncio.get_event_loop()

self.host = None
self.port = 0
Expand Down Expand Up @@ -607,25 +605,22 @@ async def _reconnect(self):
class AsyncioModbusUdpClient:
"""Client to connect to modbus device over UDP."""

def __init__(self, host=None, port=502, protocol_class=None, loop=None, framer=None, **kwargs):
def __init__(self, host=None, port=502, protocol_class=None, framer=None, **kwargs):
"""Initialize Asyncio Modbus UDP Client.

:param host: Host IP address
:param port: Port to connect
:param protocol_class: Protocol used to talk to modbus device.
:param loop: Asyncio Event loop
"""
# If there are no loop running a runtime error will be raised
self.loop = asyncio.get_running_loop()
#: Protocol used to talk to modbus device.
self.protocol_class = protocol_class or ModbusUdpClientProtocol
#: Current protocol instance.
self.protocol = None
self.framer = framer if framer else ModbusSocketFramer
#: Event loop to use.
self.loop = loop or asyncio.get_event_loop()

self.host = host
self.port = port

self.connected = False
self._proto_args = kwargs

Expand Down Expand Up @@ -704,7 +699,6 @@ def __init__(
port,
protocol_class=None,
framer=None,
loop=None,
baudrate=9600,
bytesize=8,
parity="N",
Expand All @@ -716,14 +710,13 @@ def __init__(
:param port: Port to connect
:param protocol_class: Protocol used to talk to modbus device.
:param framer: Framer to use
:param loop: Asyncio Event loop
"""
# If there are no loop running a runtime error will be raised
self.loop = asyncio.get_running_loop()
#: Protocol used to talk to modbus device.
self.protocol_class = protocol_class or ModbusRtuFramer
#: Current protocol instance.
self.protocol = None
#: Event loop to use.
self.loop = loop or asyncio.get_event_loop()
self.port = port
self.baudrate = baudrate
self.bytesize = bytesize
Expand Down Expand Up @@ -797,26 +790,24 @@ def protocol_lost_connection(self, protocol):
_logger.error(TEST_FACTORY)


async def init_tcp_client(proto_cls, loop, host, port, **kwargs):
async def init_tcp_client(proto_cls, host, port, **kwargs):
"""Initialize tcp client with helper function.

:param proto_cls:
:param loop:
:param host:
:param port:
:param kwargs:
:return:
"""
client = ReconnectingAsyncioModbusTcpClient(
protocol_class=proto_cls, loop=loop, **kwargs
protocol_class=proto_cls, **kwargs
)
await client.start(host, port)
return client


async def init_tls_client(
proto_cls,
loop,
host,
port,
sslctx=None,
Expand All @@ -827,7 +818,6 @@ async def init_tls_client(
"""Initialize tcp client with Helper function.

:param proto_cls:
:param loop:
:param host:
:param port:
:param sslctx:
Expand All @@ -837,24 +827,23 @@ async def init_tls_client(
:return:
"""
client = ReconnectingAsyncioModbusTlsClient(
protocol_class=proto_cls, loop=loop, framer=framer, **kwargs
protocol_class=proto_cls, framer=framer, **kwargs
)
await client.start(host, port, sslctx, server_hostname)
return client


async def init_udp_client(proto_cls, loop, host, port, **kwargs):
async def init_udp_client(proto_cls, host, port, **kwargs):
"""Initialize UDP client with helper function.

:param proto_cls:
:param loop:
:param host:
:param port:
:param kwargs:
:return:
"""
client = ReconnectingAsyncioModbusUdpClient(
protocol_class=proto_cls, loop=loop, **kwargs
protocol_class=proto_cls, **kwargs
)
await client.start(host, port)
return client
2 changes: 1 addition & 1 deletion pymodbus/client/asynchronous/factory/serial.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def async_io_factory(port=None, framer=None, **kwargs):

proto_cls = kwargs.get("proto_cls") or ModbusClientProtocol

client = AsyncioModbusSerialClient(port, proto_cls, framer, loop, **kwargs)
client = AsyncioModbusSerialClient(port, proto_cls, framer, **kwargs)
coro = client.connect
if not loop.is_running():
loop.run_until_complete(coro())
Expand Down
6 changes: 3 additions & 3 deletions pymodbus/client/asynchronous/factory/tcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ def async_io_factory(host="127.0.0.1", port=Defaults.Port, **kwargs):

if not loop.is_running():
asyncio.set_event_loop(loop)
cor = init_tcp_client(proto_cls, loop, host, port, **kwargs)
cor = init_tcp_client(proto_cls, host, port, **kwargs)
client = loop.run_until_complete(asyncio.gather(cor))[0]

elif loop is asyncio.get_event_loop():
cor = init_tcp_client(proto_cls, loop, host, port, **kwargs)
cor = init_tcp_client(proto_cls, host, port, **kwargs)
client = asyncio.create_task(cor)
else:
cor = init_tcp_client(proto_cls, loop, host, port, **kwargs)
cor = init_tcp_client(proto_cls, host, port, **kwargs)
future = asyncio.run_coroutine_threadsafe(cor, loop=loop)
client = future.result()

Expand Down
6 changes: 3 additions & 3 deletions pymodbus/client/asynchronous/factory/tls.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,16 @@ def async_io_factory(
if not loop.is_running():
asyncio.set_event_loop(loop)
cor = init_tls_client(
proto_cls, loop, host, port, sslctx, server_hostname, framer, **kwargs
proto_cls, host, port, sslctx, server_hostname, framer, **kwargs
)
client = loop.run_until_complete(asyncio.gather(cor))[0]
elif loop is asyncio.get_event_loop():
return loop, init_tls_client(
proto_cls, loop, host, port, sslctx, server_hostname, framer, **kwargs
proto_cls, host, port, sslctx, server_hostname, framer, **kwargs
)
else:
cor = init_tls_client(
proto_cls, loop, host, port, sslctx, server_hostname, framer, **kwargs
proto_cls, host, port, sslctx, server_hostname, framer, **kwargs
)
future = asyncio.run_coroutine_threadsafe(cor, loop=loop)
client = future.result()
Expand Down
8 changes: 4 additions & 4 deletions pymodbus/client/asynchronous/factory/udp.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ def async_io_factory(host="127.0.0.1", port=Defaults.Port, **kwargs):
loop = asyncio.new_event_loop()

proto_cls = kwargs.pop("proto_cls", None)
cor = init_udp_client(proto_cls, loop, host, port, **kwargs)
cor = init_udp_client(proto_cls, host, port, **kwargs)
if not loop.is_running():
cor = init_udp_client(proto_cls, loop, host, port)
cor = init_udp_client(proto_cls, host, port)
client = loop.run_until_complete(asyncio.gather(cor))[0]
elif loop is asyncio.get_event_loop():
return loop, init_udp_client(proto_cls, loop, host, port)
return loop, init_udp_client(proto_cls, host, port)

cor = init_udp_client(proto_cls, loop, host, port)
cor = init_udp_client(proto_cls, host, port)
client = asyncio.run_coroutine_threadsafe(cor, loop=loop)
client = client.result()

Expand Down
18 changes: 5 additions & 13 deletions pymodbus/server/async_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ class ModbusDisconnectedRequestHandler(

def __init__(self, owner):
super().__init__(owner)
_future = asyncio.get_event_loop().create_future()
_future = asyncio.get_running_loop().create_future()
self.server.on_connection_terminated = _future

def connection_lost(self, call_exc):
Expand Down Expand Up @@ -442,7 +442,7 @@ class ModbusTcpServer: # pylint: disable=too-many-instance-attributes
server context instance.
"""

def __init__( # pylint: disable=too-many-arguments
def __init__(
self,
context,
framer=None,
Expand All @@ -453,7 +453,6 @@ def __init__( # pylint: disable=too-many-arguments
allow_reuse_port=False,
defer_start=False,
backlog=20,
loop=None,
**kwargs,
):
"""Initialize the socket server.
Expand All @@ -475,8 +474,6 @@ def __init__( # pylint: disable=too-many-arguments
:param backlog: is the maximum number of queued connections
passed to listen(). Defaults to 20, increase if many
connections are being made and broken to your Modbus slave
:param loop: optional asyncio event loop to run in. Will default to
asyncio.get_event_loop() supplied value if None.
:param ignore_missing_slaves: True to not send errors on a request
to a missing slave
:param broadcast_enable: True to treat unit_id 0 as broadcast address,
Expand All @@ -485,7 +482,7 @@ def __init__( # pylint: disable=too-many-arguments
response
"""
self.active_connections = {}
self.loop = loop or asyncio.get_event_loop()
self.loop = asyncio.get_running_loop()
self.allow_reuse_address = allow_reuse_address
self.decoder = ServerDecoder()
self.framer = framer or ModbusSocketFramer
Expand Down Expand Up @@ -566,7 +563,6 @@ def __init__( # pylint: disable=too-many-arguments
allow_reuse_port=False,
defer_start=False,
backlog=20,
loop=None,
**kwargs,
):
"""Overloaded initializer for the socket server.
Expand Down Expand Up @@ -594,8 +590,6 @@ def __init__( # pylint: disable=too-many-arguments
:param backlog: is the maximum number of queued connections
passed to listen(). Defaults to 20, increase if many
connections are being made and broken to your Modbus slave
:param loop: optional asyncio event loop to run in. Will default to
asyncio.get_event_loop() supplied value if None.
:param ignore_missing_slaves: True to not send errors on a request
to a missing slave
:param broadcast_enable: True to treat unit_id 0 as broadcast address,
Expand All @@ -613,7 +607,6 @@ def __init__( # pylint: disable=too-many-arguments
allow_reuse_port=allow_reuse_port,
defer_start=defer_start,
backlog=backlog,
loop=loop,
**kwargs,
)
self.sslctx = sslctx_provider(sslctx, certfile, keyfile, password, reqclicert)
Expand All @@ -628,7 +621,7 @@ class ModbusUdpServer: # pylint: disable=too-many-instance-attributes
server context instance.
"""

def __init__( # pylint: disable=too-many-arguments
def __init__(
self,
context,
framer=None,
Expand All @@ -639,7 +632,6 @@ def __init__( # pylint: disable=too-many-arguments
allow_reuse_port=False,
defer_start=False, # pylint: disable=unused-argument
backlog=20, # pylint: disable=unused-argument
loop=None,
**kwargs,
):
"""Overloaded initializer for the socket server.
Expand All @@ -660,7 +652,7 @@ def __init__( # pylint: disable=too-many-arguments
:param response_manipulator: Callback method for
manipulating the response
"""
self.loop = loop or asyncio.get_event_loop()
self.loop = asyncio.get_running_loop()
self.decoder = ServerDecoder()
self.framer = framer or ModbusSocketFramer
self.context = context or ModbusServerContext()
Expand Down
5 changes: 4 additions & 1 deletion test/test_client_async2.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ def test_udp_asyncio_client(
ModbusAsciiFramer,
],
)
def test_serial_asyncio_client(
@pytest.mark.asyncio
async def test_serial_asyncio_client(
self,
mock_gather, # pylint: disable=unused-argument
mock_event_loop,
Expand All @@ -104,6 +105,7 @@ def test_serial_asyncio_client(
parity="E",
stopbits=2,
bytesize=7,
timeout=1,
)
assert isinstance(client, AsyncioModbusSerialClient) # nosec
assert isinstance(client.framer, framer) # nosec
Expand All @@ -112,6 +114,7 @@ def test_serial_asyncio_client(
assert client.parity == "E" # nosec
assert client.stopbits == 2 # nosec
assert client.bytesize == 7 # nosec
asyncio.wait_for(client.connect(), timeout=1)
client.stop()
loop.stop()

Expand Down
Loading