Skip to content

transaction: add number of retries attempted to return calls #2671

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

Closed
wants to merge 10 commits into from
2 changes: 1 addition & 1 deletion pymodbus/client/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ def idle_time(self) -> float:
return 0
return self.last_frame_end + self.silent_interval

def execute(self, no_response_expected: bool, request: ModbusPDU) -> ModbusPDU:
def execute(self, no_response_expected: bool, request: ModbusPDU) -> tuple[ModbusPDU, int]:
"""Execute request and get response (call **sync/async**).

:param no_response_expected: The client will not expect a response to the request
Expand Down
73 changes: 36 additions & 37 deletions pymodbus/client/mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

T = TypeVar("T", covariant=False)


class ModbusClientMixin(Generic[T]): # pylint: disable=too-many-public-methods
"""**ModbusClientMixin**.

Expand Down Expand Up @@ -50,10 +49,10 @@ def __init__(self):
"""Initialize."""

@abstractmethod
def execute(self, no_response_expected: bool, request: ModbusPDU) -> T:
def execute(self, no_response_expected: bool, request: ModbusPDU) -> tuple[T, int]:
"""Execute request."""

def read_coils(self, address: int, *, count: int = 1, device_id: int = 1, no_response_expected: bool = False) -> T:
def read_coils(self, address: int, *, count: int = 1, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Read coils (code 0x01).

:param address: Start address to read from
Expand All @@ -73,7 +72,7 @@ def read_discrete_inputs(self,
*,
count: int = 1,
device_id: int = 1,
no_response_expected: bool = False) -> T:
no_response_expected: bool = False) -> tuple[T, int]:
"""Read discrete inputs (code 0x02).

:param address: Start address to read from
Expand All @@ -94,7 +93,7 @@ def read_holding_registers(self,
*,
count: int = 1,
device_id: int = 1,
no_response_expected: bool = False) -> T:
no_response_expected: bool = False) -> tuple[T, int]:
"""Read holding registers (code 0x03).

:param address: Start address to read from
Expand All @@ -117,7 +116,7 @@ def read_input_registers(self,
*,
count: int = 1,
device_id: int = 1,
no_response_expected: bool = False) -> T:
no_response_expected: bool = False) -> tuple[T, int]:
"""Read input registers (code 0x04).

:param address: Start address to read from
Expand All @@ -135,7 +134,7 @@ def read_input_registers(self,
"""
return self.execute(no_response_expected, pdu_reg.ReadInputRegistersRequest(address=address, count=count, dev_id=device_id))

def write_coil(self, address: int, value: bool, *, device_id: int = 1, no_response_expected: bool = False) -> T:
def write_coil(self, address: int, value: bool, *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Write single coil (code 0x05).

:param address: Address to write to
Expand All @@ -151,7 +150,7 @@ def write_coil(self, address: int, value: bool, *, device_id: int = 1, no_respon
pdu = pdu_bit.WriteSingleCoilRequest(address=address, bits=[value], dev_id=device_id)
return self.execute(no_response_expected, pdu)

def write_register(self, address: int, value: int, *, device_id: int = 1, no_response_expected: bool = False) -> T:
def write_register(self, address: int, value: int, *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Write register (code 0x06).

:param address: Address to write to
Expand All @@ -169,7 +168,7 @@ def write_register(self, address: int, value: int, *, device_id: int = 1, no_res
"""
return self.execute(no_response_expected, pdu_reg.WriteSingleRegisterRequest(address=address, registers=[value], dev_id=device_id))

def read_exception_status(self, *, device_id: int = 1, no_response_expected: bool = False) -> T:
def read_exception_status(self, *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Read Exception Status (code 0x07).

:param device_id: (optional) Modbus device ID
Expand All @@ -184,7 +183,7 @@ def read_exception_status(self, *, device_id: int = 1, no_response_expected: boo
"""
return self.execute(no_response_expected, pdu_other_msg.ReadExceptionStatusRequest(dev_id=device_id))

def diag_query_data(self, msg: bytes, *, device_id: int = 1, no_response_expected: bool = False) -> T:
def diag_query_data(self, msg: bytes, *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Diagnose query data (code 0x08 sub 0x00).

:param msg: Message to be returned
Expand All @@ -198,7 +197,7 @@ def diag_query_data(self, msg: bytes, *, device_id: int = 1, no_response_expecte
"""
return self.execute(no_response_expected, pdu_diag.ReturnQueryDataRequest(msg, dev_id=device_id))

def diag_restart_communication(self, toggle: bool, *, device_id: int = 1, no_response_expected: bool = False) -> T:
def diag_restart_communication(self, toggle: bool, *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Diagnose restart communication (code 0x08 sub 0x01).

:param toggle: True if toggled.
Expand All @@ -216,7 +215,7 @@ def diag_restart_communication(self, toggle: bool, *, device_id: int = 1, no_res
msg = ModbusStatus.ON if toggle else ModbusStatus.OFF
return self.execute(no_response_expected, pdu_diag.RestartCommunicationsOptionRequest(message=msg, dev_id=device_id))

def diag_read_diagnostic_register(self, *, device_id: int = 1, no_response_expected: bool = False) -> T:
def diag_read_diagnostic_register(self, *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Diagnose read diagnostic register (code 0x08 sub 0x02).

:param device_id: (optional) Modbus device ID
Expand All @@ -227,7 +226,7 @@ def diag_read_diagnostic_register(self, *, device_id: int = 1, no_response_expec
"""
return self.execute(no_response_expected, pdu_diag.ReturnDiagnosticRegisterRequest(dev_id=device_id))

def diag_change_ascii_input_delimeter(self, *, delimiter: int = 0x0a, device_id: int = 1, no_response_expected: bool = False) -> T:
def diag_change_ascii_input_delimeter(self, *, delimiter: int = 0x0a, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Diagnose change ASCII input delimiter (code 0x08 sub 0x03).

:param delimiter: char to replace LF
Expand All @@ -242,7 +241,7 @@ def diag_change_ascii_input_delimeter(self, *, delimiter: int = 0x0a, device_id:
"""
return self.execute(no_response_expected, pdu_diag.ChangeAsciiInputDelimiterRequest(message=delimiter, dev_id=device_id))

def diag_force_listen_only(self, *, device_id: int = 1, no_response_expected: bool = False) -> T:
def diag_force_listen_only(self, *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Diagnose force listen only (code 0x08 sub 0x04).

:param device_id: (optional) Modbus device ID
Expand All @@ -257,7 +256,7 @@ def diag_force_listen_only(self, *, device_id: int = 1, no_response_expected: bo
"""
return self.execute(no_response_expected, pdu_diag.ForceListenOnlyModeRequest(dev_id=device_id))

def diag_clear_counters(self, *, device_id: int = 1, no_response_expected: bool = False) -> T:
def diag_clear_counters(self, *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Diagnose clear counters (code 0x08 sub 0x0A).

:param device_id: (optional) Modbus device ID
Expand All @@ -268,7 +267,7 @@ def diag_clear_counters(self, *, device_id: int = 1, no_response_expected: bool
"""
return self.execute(no_response_expected, pdu_diag.ClearCountersRequest(dev_id=device_id))

def diag_read_bus_message_count(self, *, device_id: int = 1, no_response_expected: bool = False) -> T:
def diag_read_bus_message_count(self, *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Diagnose read bus message count (code 0x08 sub 0x0B).

:param device_id: (optional) Modbus device ID
Expand All @@ -281,7 +280,7 @@ def diag_read_bus_message_count(self, *, device_id: int = 1, no_response_expecte
"""
return self.execute(no_response_expected, pdu_diag.ReturnBusMessageCountRequest(dev_id=device_id))

def diag_read_bus_comm_error_count(self, *, device_id: int = 1, no_response_expected: bool = False) -> T:
def diag_read_bus_comm_error_count(self, *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Diagnose read Bus Communication Error Count (code 0x08 sub 0x0C).

:param device_id: (optional) Modbus device ID
Expand All @@ -294,7 +293,7 @@ def diag_read_bus_comm_error_count(self, *, device_id: int = 1, no_response_expe
"""
return self.execute(no_response_expected, pdu_diag.ReturnBusCommunicationErrorCountRequest(dev_id=device_id))

def diag_read_bus_exception_error_count(self, *, device_id: int = 1, no_response_expected: bool = False) -> T:
def diag_read_bus_exception_error_count(self, *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Diagnose read Bus Exception Error Count (code 0x08 sub 0x0D).

:param device_id: (optional) Modbus device ID
Expand All @@ -307,7 +306,7 @@ def diag_read_bus_exception_error_count(self, *, device_id: int = 1, no_response
"""
return self.execute(no_response_expected, pdu_diag.ReturnBusExceptionErrorCountRequest(dev_id=device_id))

def diag_read_device_message_count(self, *, device_id: int = 1, no_response_expected: bool = False) -> T:
def diag_read_device_message_count(self, *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Diagnose read device Message Count (code 0x08 sub 0x0E).

:param device_id: (optional) Modbus device ID
Expand All @@ -320,7 +319,7 @@ def diag_read_device_message_count(self, *, device_id: int = 1, no_response_expe
"""
return self.execute(no_response_expected, pdu_diag.ReturnDeviceMessageCountRequest(dev_id=device_id))

def diag_read_device_no_response_count(self, *, device_id: int = 1, no_response_expected: bool = False) -> T:
def diag_read_device_no_response_count(self, *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Diagnose read device No Response Count (code 0x08 sub 0x0F).

:param device_id: (optional) Modbus device ID
Expand All @@ -333,7 +332,7 @@ def diag_read_device_no_response_count(self, *, device_id: int = 1, no_response_
"""
return self.execute(no_response_expected, pdu_diag.ReturnDeviceNoResponseCountRequest(dev_id=device_id))

def diag_read_device_nak_count(self, *, device_id: int = 1, no_response_expected: bool = False) -> T:
def diag_read_device_nak_count(self, *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Diagnose read device NAK Count (code 0x08 sub 0x10).

:param device_id: (optional) Modbus device ID
Expand All @@ -347,7 +346,7 @@ def diag_read_device_nak_count(self, *, device_id: int = 1, no_response_expected
"""
return self.execute(no_response_expected, pdu_diag.ReturnDeviceNAKCountRequest(dev_id=device_id))

def diag_read_device_busy_count(self, *, device_id: int = 1, no_response_expected: bool = False) -> T:
def diag_read_device_busy_count(self, *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Diagnose read device Busy Count (code 0x08 sub 0x11).

:param device_id: (optional) Modbus device ID
Expand All @@ -360,7 +359,7 @@ def diag_read_device_busy_count(self, *, device_id: int = 1, no_response_expecte
"""
return self.execute(no_response_expected, pdu_diag.ReturnDeviceBusyCountRequest(dev_id=device_id))

def diag_read_bus_char_overrun_count(self, *, device_id: int = 1, no_response_expected: bool = False) -> T:
def diag_read_bus_char_overrun_count(self, *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Diagnose read Bus Character Overrun Count (code 0x08 sub 0x12).

:param device_id: (optional) Modbus device ID
Expand All @@ -375,7 +374,7 @@ def diag_read_bus_char_overrun_count(self, *, device_id: int = 1, no_response_ex
"""
return self.execute(no_response_expected, pdu_diag.ReturnDeviceBusCharacterOverrunCountRequest(dev_id=device_id))

def diag_read_iop_overrun_count(self, *, device_id: int = 1, no_response_expected: bool = False) -> T:
def diag_read_iop_overrun_count(self, *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Diagnose read Iop overrun count (code 0x08 sub 0x13).

:param device_id: (optional) Modbus device ID
Expand All @@ -388,7 +387,7 @@ def diag_read_iop_overrun_count(self, *, device_id: int = 1, no_response_expecte
"""
return self.execute(no_response_expected, pdu_diag.ReturnIopOverrunCountRequest(dev_id=device_id))

def diag_clear_overrun_counter(self, *, device_id: int = 1, no_response_expected: bool = False) -> T:
def diag_clear_overrun_counter(self, *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Diagnose Clear Overrun Counter and Flag (code 0x08 sub 0x14).

:param device_id: (optional) Modbus device ID
Expand All @@ -400,7 +399,7 @@ def diag_clear_overrun_counter(self, *, device_id: int = 1, no_response_expected
"""
return self.execute(no_response_expected, pdu_diag.ClearOverrunCountRequest(dev_id=device_id))

def diag_getclear_modbus_response(self, *, data: int = 0, device_id: int = 1, no_response_expected: bool = False) -> T:
def diag_getclear_modbus_response(self, *, data: int = 0, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Diagnose Get/Clear modbus plus (code 0x08 sub 0x15).

:param data: "Get Statistics" or "Clear Statistics"
Expand All @@ -418,7 +417,7 @@ def diag_getclear_modbus_response(self, *, data: int = 0, device_id: int = 1, no
"""
return self.execute(no_response_expected, pdu_diag.GetClearModbusPlusRequest(message=data, dev_id=device_id))

def diag_get_comm_event_counter(self, *, device_id: int = 1, no_response_expected: bool = False) -> T:
def diag_get_comm_event_counter(self, *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Diagnose get event counter (code 0x0B).

:param device_id: (optional) Modbus device ID
Expand All @@ -440,7 +439,7 @@ def diag_get_comm_event_counter(self, *, device_id: int = 1, no_response_expecte
"""
return self.execute(no_response_expected, pdu_other_msg.GetCommEventCounterRequest(dev_id=device_id))

def diag_get_comm_event_log(self, *, device_id: int = 1, no_response_expected: bool = False) -> T:
def diag_get_comm_event_log(self, *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Diagnose get event counter (code 0x0C).

:param device_id: (optional) Modbus device ID
Expand Down Expand Up @@ -474,7 +473,7 @@ def write_coils(
*,
device_id: int = 1,
no_response_expected: bool = False
) -> T:
) -> tuple[T, int]:
"""Write coils (code 0x0F).

:param address: Start address to write to
Expand All @@ -497,7 +496,7 @@ def write_registers(
*,
device_id: int = 1,
no_response_expected: bool = False
) -> T:
) -> tuple[T, int]:
"""Write registers (code 0x10).

:param address: Start address to write to
Expand All @@ -511,7 +510,7 @@ def write_registers(
"""
return self.execute(no_response_expected, pdu_reg.WriteMultipleRegistersRequest(address=address, registers=values,dev_id=device_id))

def report_device_id(self, *, device_id: int = 1, no_response_expected: bool = False) -> T:
def report_device_id(self, *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Report device ID (code 0x11).

:param device_id: (optional) Modbus device ID
Expand All @@ -523,7 +522,7 @@ def report_device_id(self, *, device_id: int = 1, no_response_expected: bool = F
"""
return self.execute(no_response_expected, pdu_other_msg.ReportDeviceIdRequest(dev_id=device_id))

def read_file_record(self, records: list[pdu_file_msg.FileRecord], *, device_id: int = 1, no_response_expected: bool = False) -> T:
def read_file_record(self, records: list[pdu_file_msg.FileRecord], *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Read file record (code 0x14).

:param records: List of FileRecord (Reference type, File number, Record Number)
Expand Down Expand Up @@ -553,7 +552,7 @@ def read_file_record(self, records: list[pdu_file_msg.FileRecord], *, device_id:
"""
return self.execute(no_response_expected, pdu_file_msg.ReadFileRecordRequest(records, dev_id=device_id))

def write_file_record(self, records: list[pdu_file_msg.FileRecord], *, device_id: int = 1, no_response_expected: bool = False) -> T:
def write_file_record(self, records: list[pdu_file_msg.FileRecord], *, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Write file record (code 0x15).

:param records: List of File_record (Reference type, File number, Record Number, Record Length, Record Data)
Expand All @@ -576,7 +575,7 @@ def mask_write_register(
or_mask: int = 0x0000,
device_id: int = 1,
no_response_expected: bool = False
) -> T:
) -> tuple[T, int]:
"""Mask write register (code 0x16).

:param address: The mask pointer address (0x0000 to 0xffff)
Expand All @@ -603,7 +602,7 @@ def readwrite_registers(
values: list[int] | None = None,
device_id: int = 1,
no_response_expected: bool = False
) -> T:
) -> tuple[T, int]:
"""Read/Write registers (code 0x17).

:param read_address: The address to start reading from
Expand All @@ -629,7 +628,7 @@ def readwrite_registers(
write_address = address
return self.execute(no_response_expected, pdu_reg.ReadWriteMultipleRegistersRequest( read_address=read_address, read_count=read_count, write_address=write_address, write_registers=values,dev_id=device_id))

def read_fifo_queue(self, *, address: int = 0x0000, device_id: int = 1, no_response_expected: bool = False) -> T:
def read_fifo_queue(self, *, address: int = 0x0000, device_id: int = 1, no_response_expected: bool = False) -> tuple[T, int]:
"""Read FIFO queue (code 0x18).

:param address: The address to start reading from
Expand All @@ -654,7 +653,7 @@ def read_fifo_queue(self, *, address: int = 0x0000, device_id: int = 1, no_respo
def read_device_information(self, *, read_code: int | None = None,
object_id: int = 0x00,
device_id: int = 1,
no_response_expected: bool = False) -> T:
no_response_expected: bool = False) -> tuple[T, int]:
"""Read FIFO queue (code 0x2B sub 0x0E).

:param read_code: The device information read code
Expand Down
Loading
Loading