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
5 changes: 4 additions & 1 deletion doc/source/library/pymodbus.client.calls.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@ Pymodbus makes a all standard modbus requests/responses available as simple call

All calls are available as synchronous and asynchronous (asyncio based).

.. automodule:: pymodbus.client.mixin
Using Modbus<transport>Client.register() custom messagees can be added to pymodbus,
and handled automatically.

.. autoclass:: pymodbus.client.mixin.ModbusClientMixin
:members:
27 changes: 21 additions & 6 deletions doc/source/library/pymodbus.client.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,37 @@ Pymodbus offers clients with different transport protocols in 2 versions:
- synchronous,
- asynchronous (based on asyncio).

Using a client to set/get information from a device (server) is simple as seen in this
example (more details in below)::
Using pymodbus client to set/get information from a device (server)
is done in a few simple steps, like the following synchronous example::

# create client object
client = ModbusSerial("/dev/tty")

# connect to device
client.start()
client.connect()

# set/set information
client.read_coils(0x01)
rr = client.read_coils(0x01)
client.write_coil(0x01, values)
...

# disconnect device
client.stop()
client.close()

or asynchronous example::

# create client object
async_client = AsyncModbusSerial("/dev/tty")

# connect to device
await async_client.connect()

# set/set information
rr = await async_client.read_coils(0x01)
await async_client.write_coil(0x01, values)

# disconnect device
await async_client.close()


.. toctree::

Expand Down
35 changes: 18 additions & 17 deletions doc/source/library/pymodbus.client.setup.rst
Original file line number Diff line number Diff line change
@@ -1,62 +1,63 @@
Client setup.
=============

Pymodbus offers different transport protocols Serial/TCP/TLS/UDP, which are implemented
as separate classes. Each class defines exactly on transport type.
Pymodbus offers different transport protocols Serial/TCP/TLS/UDP,
which are implemented as separate classes.
Each class defines exactly on transport type.

Applications can add custom transport types as long as the new class inherits
from class BaseOldModbusClient.
from class ModbusBaseClient.

Applications can also custom decoders and customer framers.
Applications can also use customer framers.

All transport types are supplied in 2 versions:

a :mod:`synchronous client <pymodbus.client>` and

a :mod:`asynchronous client based on asyncio <pymodbus.client.asynchronous>`.

Care have been made to ensure that large parts of the actual implementation or shared
between the different classes, to ensure a higher stability.
Large parts of the actual implementation are shared between the different classes,
to ensure a higher stability and more efficient maintenance.

Common parameters for all clients.
----------------------------------
Common parameters/methods for all clients.
------------------------------------------

.. automodule:: pymodbus.client.base
.. autoclass:: pymodbus.client.base.ModbusBaseClient
:members:
:member-order: bysource

Serial RS-485 transport.
------------------------

.. automodule:: pymodbus.client.async_serial
.. autoclass:: pymodbus.client.async_serial.AsyncModbusSerialClient
:members:

.. automodule:: pymodbus.client.sync_serial
.. autoclass:: pymodbus.client.sync_serial.ModbusSerialClient
:members:

TCP transport.
--------------

.. automodule:: pymodbus.client.async_tcp
.. autoclass:: pymodbus.client.async_tcp.AsyncModbusTcpClient
:members:

.. automodule:: pymodbus.client.sync_tcp
.. autoclass:: pymodbus.client.sync_tcp.ModbusTcpClient
:members:

TLS transport.
--------------

.. automodule:: pymodbus.client.async_tls
.. autoclass:: pymodbus.client.async_tls.AsyncModbusTlsClient
:members:

.. automodule:: pymodbus.client.sync_tls
.. autoclass:: pymodbus.client.sync_tls.ModbusTlsClient
:members:

UDP transport.
--------------

.. automodule:: pymodbus.client.async_udp
.. autoclass:: pymodbus.client.async_udp.AsyncModbusUdpClient
:members:

.. automodule:: pymodbus.client.sync_udp
.. autoclass:: pymodbus.client.sync_udp.ModbusUdpClient
:members:
8 changes: 2 additions & 6 deletions examples/client_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ def setup_client(args=None):
"127.0.0.1",
port=args.port, # on which port
# Common optional paramers:
# modbus_decoder=ClientDecoder,
framer=args.framer,
# timeout=10,
# retries=3,
Expand All @@ -71,7 +70,6 @@ def setup_client(args=None):
"127.0.0.1",
port=args.port,
# Common optional paramers:
# modbus_decoder=ClientDecoder,
framer=args.framer,
# timeout=10,
# retries=3,
Expand All @@ -85,7 +83,6 @@ def setup_client(args=None):
client = AsyncModbusSerialClient(
args.port,
# Common optional paramers:
# modbus_decoder=ClientDecoder,
# framer=ModbusRtuFramer,
# timeout=10,
# retries=3,
Expand All @@ -104,7 +101,6 @@ def setup_client(args=None):
"localhost",
port=args.port,
# Common optional paramers:
# modbus_decoder=ClientDecoder,
framer=args.framer,
# timeout=10,
# retries=3,
Expand All @@ -124,11 +120,11 @@ def setup_client(args=None):
async def run_client(client, modbus_calls=None):
"""Run sync client."""
_logger.info("### Client starting")
await client.aConnect()
await client.connect()
assert client.protocol
if modbus_calls:
await modbus_calls(client.protocol)
await client.aClose()
await client.close()
_logger.info("### End of Program")


Expand Down
4 changes: 0 additions & 4 deletions examples/client_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ def setup_client(args=None):
"127.0.0.1",
port=args.port,
# Common optional paramers:
# modbus_decoder=ClientDecoder,
framer=args.framer,
# timeout=10,
# retries=3,
Expand All @@ -68,7 +67,6 @@ def setup_client(args=None):
"localhost",
port=args.port,
# Common optional paramers:
# modbus_decoder=ClientDecoder,
framer=args.framer,
# timeout=10,
# retries=3,
Expand All @@ -82,7 +80,6 @@ def setup_client(args=None):
client = ModbusSerialClient(
port=args.port, # serial port
# Common optional paramers:
# modbus_decoder=ClientDecoder,
# framer=ModbusRtuFramer,
# timeout=10,
# retries=3,
Expand All @@ -101,7 +98,6 @@ def setup_client(args=None):
"localhost",
port=args.port,
# Common optional paramers:
# modbus_decoder=ClientDecoder,
framer=args.framer,
# timeout=10,
# retries=3,
Expand Down
2 changes: 1 addition & 1 deletion examples/contrib/libmodbus_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ class LibmodbusLevel1Client:
"""

@classmethod
def create_tcp_client(cls, my_host="127.0.0.1", my_port=Defaults.Port):
def create_tcp_client(cls, my_host="127.0.0.1", my_port=Defaults.TcpPort):
"""Create a TCP modbus client for the supplied parameters.

:param host: The host to connect to
Expand Down
100 changes: 45 additions & 55 deletions pymodbus/client/async_serial.py
Original file line number Diff line number Diff line change
@@ -1,74 +1,58 @@
"""**Modbus client async serial communication.**

The serial communication is RS-485 based, and usually used vith a usb RS485 dongle.

Example::

from pymodbus.client import AsyncModbusSerialClient

async def run():
client = AsyncModbusSerialClient(
"dev/pty0", # serial port
# Common optional paramers:
# modbus_decoder=ClientDecoder,
# framer=ModbusRtuFramer,
# timeout=10,
# retries=3,
# retry_on_empty=False,
# close_comm_on_error=False,
# strict=True,
# Serial setup parameters
# baudrate=9600,
# bytesize=8,
# parity="N",
# stopbits=1,
# handle_local_echo=False,
)

await client.aConnect()
...
await client.aClose()
"""
"""Modbus client async serial communication."""
import asyncio
import logging

from serial_asyncio import create_serial_connection

from pymodbus.client.base import ModbusClientProtocol
from pymodbus.framer import ModbusFramer
from pymodbus.transaction import ModbusRtuFramer
from pymodbus.client.base import ModbusBaseClient
from pymodbus.constants import Defaults

_logger = logging.getLogger(__name__)


class AsyncModbusSerialClient(ModbusBaseClient):
r"""Modbus client for async serial (RS-485) communication.

:param port: (positional) Serial port used for communication.
:param framer: (optional, default ModbusRtuFramer) Framer class.
:param baudrate: (optional, default 9600) Bits pr second.
:param bytesize: (optional, default 8) Number of bits pr byte 7-8.
:param parity: (optional, default None).
:param stopbits: (optional, default 1) Number of stop bits 0-2 to use.
:param handle_local_echo: (optional, default false) Handle local echo of the USB-to-RS485 dongle.
:param \*\*kwargs: (optional) Extra experimental parameters for transport
:return: client object
"""**AsyncModbusSerialClient**.

:param port: Serial port used for communication.
:param framer: (optional) Framer class.
:param baudrate: (optional) Bits pr second.
:param bytesize: (optional) Number of bits pr byte 7-8.
:param parity: (optional) 'E'ven, 'O'dd or 'N'one
:param stopbits: (optional) Number of stop bits 0-2¡.
:param handle_local_echo: (optional) Discard local echo from dongle.
:param kwargs: (optional) Experimental parameters

The serial communication is RS-485 based, and usually used vith a usb RS485 dongle.

Example::

from pymodbus.client import AsyncModbusSerialClient

async def run():
client = AsyncModbusSerialClient("dev/serial0")

await client.connect()
...
await client.close()
"""

transport = None
framer = None

def __init__(
self,
port,
framer=ModbusRtuFramer,
baudrate=9600,
bytesize=8,
parity="N",
stopbits=1,
handle_local_echo=False,
**kwargs,
):
port: str,
framer: ModbusFramer = ModbusRtuFramer,
baudrate: int = Defaults.Baudrate,
bytesize: int = Defaults.Bytesize,
parity: chr = Defaults.Parity,
stopbits: int = Defaults.Stopbits,
handle_local_echo: bool = Defaults.HandleLocalEcho,
**kwargs: any,
) -> None:
"""Initialize Asyncio Modbus Serial Client."""
super().__init__(framer=framer, **kwargs)
self.params.port = port
Expand All @@ -81,8 +65,11 @@ def __init__(
self.protocol = None
self._connected_event = asyncio.Event()

async def aClose(self):
"""Stop connection."""
async def close(self): # pylint: disable=invalid-overridden-method
"""Stop connection.

:meta private:
"""
if self._connected and self.protocol and self.protocol.transport:
self.protocol.transport.close()

Expand All @@ -97,8 +84,11 @@ def _connected(self):
"""Connect internal."""
return self._connected_event.is_set()

async def aConnect(self):
"""Connect Async client."""
async def connect(self): # pylint: disable=invalid-overridden-method
"""Connect Async client.

:meta private:
"""
# get current loop, if there are no loop a RuntimeError will be raised
self.loop = asyncio.get_running_loop()

Expand Down
Loading