Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove kwargs client #2244

Merged
merged 1 commit into from
Jul 22, 2024
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ prof/
/pymodbus.egg-info/
venv
downloaded_files/
pymodbus.log
2 changes: 0 additions & 2 deletions examples/client_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ def setup_async_client(description=None, cmdline=None):
# parity="N",
# stopbits=1,
# handle_local_echo=False,
# strict=True,
)
elif args.comm == "tls":
client = modbusClient.AsyncModbusTlsClient(
Expand All @@ -111,7 +110,6 @@ def setup_async_client(description=None, cmdline=None):
keyfile=helper.get_certificate("key"),
# password="none",
),
server_hostname="localhost",
)
else:
raise RuntimeError(f"Unknown commtype {args.comm}")
Expand Down
2 changes: 1 addition & 1 deletion examples/client_custom_msg.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def __init__(self, address, count=None, slave=0, transaction=0, protocol=0, skip

async def main(host="localhost", port=5020):
"""Run versions of read coil."""
async with ModbusClient(host=host, port=port, framer_name=FramerType.SOCKET) as client:
async with ModbusClient(host=host, port=port, framer=FramerType.SOCKET) as client:
await client.connect()

# create a response object to control it works
Expand Down
5 changes: 0 additions & 5 deletions examples/client_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ def setup_sync_client(description=None, cmdline=None):
timeout=args.timeout,
# retries=3,
# retry_on_empty=False,y
# strict=True,
# TCP setup parameters
# source_address=("localhost", 0),
)
Expand All @@ -81,7 +80,6 @@ def setup_sync_client(description=None, cmdline=None):
timeout=args.timeout,
# retries=3,
# retry_on_empty=False,
# strict=True,
# UDP setup parameters
# source_address=None,
)
Expand All @@ -93,14 +91,12 @@ def setup_sync_client(description=None, cmdline=None):
timeout=args.timeout,
# retries=3,
# retry_on_empty=False,
# strict=True,
# Serial setup parameters
baudrate=args.baudrate,
# bytesize=8,
# parity="N",
# stopbits=1,
# handle_local_echo=False,
# strict=True,
)
elif args.comm == "tls":
client = modbusClient.ModbusTlsClient(
Expand All @@ -117,7 +113,6 @@ def setup_sync_client(description=None, cmdline=None):
keyfile=helper.get_certificate("key"),
# password=None,
),
server_hostname="localhost",
)
return client

Expand Down
1 change: 0 additions & 1 deletion examples/server_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,6 @@ async def run_async_server(args):
# handle_local_echo=False, # Handle local echo of the USB-to-RS485 adaptor
# ignore_missing_slaves=True, # ignore request to a missing slave
# broadcast_enable=False, # treat slave_id 0 as broadcast address,
# strict=True, # use strict timing, t1.5 for Modbus RTU
)
elif args.comm == "tls":
address = (args.host if args.host else "", args.port if args.port else None)
Expand Down
6 changes: 1 addition & 5 deletions examples/server_hook.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,7 @@


class Manipulator:
"""A Class to run the server.

Using a class allows the easy use of global variables, but
are not strictly needed
"""
"""A Class to run the server."""

message_count: int = 1
server: ModbusTcpServer = None
Expand Down
1 change: 0 additions & 1 deletion examples/server_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ def run_sync_server(args):
# handle_local_echo=False, # Handle local echo of the USB-to-RS485 adaptor
# ignore_missing_slaves=True, # ignore request to a missing slave
# broadcast_enable=False, # treat slave_id 0 as broadcast address,
# strict=True, # use strict timing, t1.5 for Modbus RTU
)
elif args.comm == "tls":
address = ("", args.port) if args.port else None
Expand Down
2 changes: 0 additions & 2 deletions examples/simple_async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ async def run_async_simple_client(comm, host, port, framer=FramerType.SOCKET):
# timeout=10,
# retries=3,
# retry_on_empty=False,
# strict=True,
baudrate=9600,
bytesize=8,
parity="N",
Expand All @@ -72,7 +71,6 @@ async def run_async_simple_client(comm, host, port, framer=FramerType.SOCKET):
certfile="../examples/certificates/pymodbus.crt",
keyfile="../examples/certificates/pymodbus.key",
# password="none",
server_hostname="localhost",
)
else:
print(f"Unknown client {comm} selected")
Expand Down
2 changes: 0 additions & 2 deletions examples/simple_sync_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ def run_sync_simple_client(comm, host, port, framer=FramerType.SOCKET):
# timeout=10,
# retries=3,
# retry_on_empty=False,
# strict=True,
baudrate=9600,
bytesize=8,
parity="N",
Expand All @@ -74,7 +73,6 @@ def run_sync_simple_client(comm, host, port, framer=FramerType.SOCKET):
certfile="../examples/certificates/pymodbus.crt",
keyfile="../examples/certificates/pymodbus.key",
# password=None,
server_hostname="localhost",
)
else:
print(f"Unknown client {comm} selected")
Expand Down
147 changes: 20 additions & 127 deletions pymodbus/client/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
import socket
from abc import abstractmethod
from collections.abc import Awaitable, Callable
from dataclasses import dataclass
from typing import Any, cast
from typing import cast

from pymodbus.client.mixin import ModbusClientMixin
from pymodbus.client.modbusclientprotocol import ModbusClientProtocol
Expand All @@ -16,79 +15,39 @@
from pymodbus.logging import Log
from pymodbus.pdu import ModbusRequest, ModbusResponse
from pymodbus.transaction import SyncModbusTransactionManager
from pymodbus.transport import CommParams, CommType
from pymodbus.transport import CommParams
from pymodbus.utilities import ModbusTransactionState


class ModbusBaseClient(ModbusClientMixin[Awaitable[ModbusResponse]]):
"""**ModbusBaseClient**.

Fixed parameters:

:param framer: Framer enum name

Optional parameters:

:param timeout: Timeout for a request, in seconds.
:param retries: Max number of retries per request.
:param retry_on_empty: Retry on empty response.
:param broadcast_enable: True to treat id 0 as broadcast address.
:param reconnect_delay: Minimum delay in seconds.milliseconds before reconnecting.
:param reconnect_delay_max: Maximum delay in seconds.milliseconds before reconnecting.
:param on_connect_callback: Will be called when connected/disconnected (bool parameter)
:param no_resend_on_retry: Do not resend request when retrying due to missing response.
:param comm_type: Type of communication (set by interface class)
:param kwargs: Experimental parameters.

.. tip::
**reconnect_delay** doubles automatically with each unsuccessful connect, from
**reconnect_delay** to **reconnect_delay_max**.
Set `reconnect_delay=0` to avoid automatic reconnection.

:mod:`ModbusBaseClient` is normally not referenced outside :mod:`pymodbus`.

**Application methods, common to all clients**:
"""

def __init__( # pylint: disable=too-many-arguments
def __init__(
self,
framer: FramerType,
timeout: float = 3,
retries: int = 3,
comm_params: CommParams | None = None,
retry_on_empty: bool = False,
broadcast_enable: bool = False,
reconnect_delay: float = 0.1,
reconnect_delay_max: float = 300,
on_connect_callback: Callable[[bool], None] | None = None,
no_resend_on_retry: bool = False,
comm_type: CommType | None = None,
source_address: tuple[str, int] | None = None,
**kwargs: Any,
on_connect_callback: Callable[[bool], None] | None = None,
) -> None:
"""Initialize a client instance."""
ModbusClientMixin.__init__(self) # type: ignore[arg-type]
if comm_params:
self.comm_params = comm_params
self.retries = retries
self.retry_on_empty = retry_on_empty
self.ctx = ModbusClientProtocol(
framer,
CommParams(
comm_type=comm_type,
comm_name="comm",
source_address=source_address,
reconnect_delay=reconnect_delay,
reconnect_delay_max=reconnect_delay_max,
timeout_connect=timeout,
host=kwargs.get("host", None),
port=kwargs.get("port", 0),
sslctx=kwargs.get("sslctx", None),
baudrate=kwargs.get("baudrate", None),
bytesize=kwargs.get("bytesize", None),
parity=kwargs.get("parity", None),
stopbits=kwargs.get("stopbits", None),
handle_local_echo=kwargs.get("handle_local_echo", False),
),
self.comm_params,
on_connect_callback,
)
self.no_resend_on_retry = no_resend_on_retry
self.broadcast_enable = broadcast_enable
self.retries = retries

# Common variables.
self.use_udp = False
Expand All @@ -97,9 +56,6 @@ def __init__( # pylint: disable=too-many-arguments
self.silent_interval: float = 0
self._lock = asyncio.Lock()

# ----------------------------------------------------------------------- #
# Client external interface
# ----------------------------------------------------------------------- #
@property
def connected(self) -> bool:
"""Return state of connection."""
Expand All @@ -115,7 +71,6 @@ async def connect(self) -> bool:
)
return await self.ctx.connect()


def register(self, custom_response_class: ModbusResponse) -> None:
"""Register a custom response class with the decoder (call **sync**).

Expand Down Expand Up @@ -155,9 +110,6 @@ def execute(self, request: ModbusRequest):
raise ConnectionException(f"Not connected[{self!s}]")
return self.async_execute(request)

# ----------------------------------------------------------------------- #
# Merged client methods
# ----------------------------------------------------------------------- #
async def async_execute(self, request) -> ModbusResponse:
"""Execute requests asynchronously."""
request.transaction_id = self.ctx.transaction.getNextTID()
Expand Down Expand Up @@ -199,9 +151,6 @@ def build_response(self, request: ModbusRequest):
self.ctx.transaction.addTransaction(request)
return my_future

# ----------------------------------------------------------------------- #
# The magic methods
# ----------------------------------------------------------------------- #
async def __aenter__(self):
"""Implement the client with enter block.

Expand All @@ -228,79 +177,25 @@ def __str__(self):
class ModbusBaseSyncClient(ModbusClientMixin[ModbusResponse]):
"""**ModbusBaseClient**.

Fixed parameters:

:param framer: Framer enum name

Optional parameters:

:param timeout: Timeout for a request, in seconds.
:param retries: Max number of retries per request.
:param retry_on_empty: Retry on empty response.
:param broadcast_enable: True to treat id 0 as broadcast address.
:param reconnect_delay: Minimum delay in seconds.milliseconds before reconnecting.
:param reconnect_delay_max: Maximum delay in seconds.milliseconds before reconnecting.
:param no_resend_on_retry: Do not resend request when retrying due to missing response.
:param source_address: source address of client
:param kwargs: Experimental parameters.

.. tip::
**reconnect_delay** doubles automatically with each unsuccessful connect, from
**reconnect_delay** to **reconnect_delay_max**.
Set `reconnect_delay=0` to avoid automatic reconnection.

:mod:`ModbusBaseClient` is normally not referenced outside :mod:`pymodbus`.

**Application methods, common to all clients**:
"""

@dataclass
class _params:
"""Parameter class."""

retries: int | None = None
retry_on_empty: bool | None = None
broadcast_enable: bool | None = None
reconnect_delay: int | None = None
source_address: tuple[str, int] | None = None

def __init__( # pylint: disable=too-many-arguments
def __init__(
self,
framer: FramerType,
timeout: float = 3,
retries: int = 3,
comm_params: CommParams | None = None,
retry_on_empty: bool = False,
broadcast_enable: bool = False,
reconnect_delay: float = 0.1,
reconnect_delay_max: float = 300.0,
no_resend_on_retry: bool = False,
comm_type: CommType | None = None,
source_address: tuple[str, int] | None = None,
**kwargs: Any,
) -> None:
"""Initialize a client instance."""
ModbusClientMixin.__init__(self) # type: ignore[arg-type]
self.comm_params = CommParams(
comm_type=comm_type,
comm_name="comm",
source_address=source_address,
reconnect_delay=reconnect_delay,
reconnect_delay_max=reconnect_delay_max,
timeout_connect=timeout,
host=kwargs.get("host", None),
port=kwargs.get("port", 0),
sslctx=kwargs.get("sslctx", None),
baudrate=kwargs.get("baudrate", None),
bytesize=kwargs.get("bytesize", None),
parity=kwargs.get("parity", None),
stopbits=kwargs.get("stopbits", None),
handle_local_echo=kwargs.get("handle_local_echo", False),
)
self.params = self._params()
self.params.retries = int(retries)
self.params.retry_on_empty = bool(retry_on_empty)
self.params.broadcast_enable = bool(broadcast_enable)
self.retry_on_empty: int = 0
if comm_params:
self.comm_params = comm_params
self.retries = retries
self.broadcast_enable = bool(broadcast_enable)
self.retry_on_empty = retry_on_empty
self.no_resend_on_retry = no_resend_on_retry
self.slaves: list[int] = []

Expand All @@ -310,12 +205,10 @@ def __init__( # pylint: disable=too-many-arguments
)(ClientDecoder(), self)
self.transaction = SyncModbusTransactionManager(
self,
kwargs.get("backoff", 0.3),
retry_on_empty,
kwargs.get("retry_on_invalid", False),
retries,
self.retries,
)
self.reconnect_delay_current = self.params.reconnect_delay or 0
self.reconnect_delay_current = self.comm_params.reconnect_delay or 0
self.use_udp = False
self.state = ModbusTransactionState.IDLE
self.last_frame_end: float | None = 0
Expand Down
Loading