Client
Pymodbus offers clients with transport different protocols:
Serial (RS-485) typically using a dongle
TCP
TLS
UDP
The application can use either a synchronous client
or a asynchronous client
.
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.connect()
# set/set information for as many times as needed
rr = client.read_coils(0x01)
client.write_coil(0x01, values)
# disconnect device
client.close()
and a asynchronous example:
# create client object
async_client = AsyncModbusSerial("/dev/tty")
# connect to device
await async_client.connect()
# set/set information for as many times as needed
rr = await async_client.read_coils(0x01)
await async_client.write_coil(0x01, values)
# disconnect device
await async_client.close()
Large parts of the implementation are shared between the different classes, to ensure high stability and efficient maintenance.
The synchronous clients are not thread safe nor is a single client intended to be used from multiple threads. Due to the nature of the modbus protocol, it makes little sense to have client calls split over different threads, however the application can do it with proper locking implemented.
The asynchronous client only runs in the thread where the asyncio loop is created, it does not provide mechanisms to prevent (semi)parallel calls, that must be prevented at application level.
Client classes
- class pymodbus.client.ModbusBaseClient(framer: type[ModbusFramer] = None, timeout: float = 3, retries: int = 3, retry_on_empty: bool = False, close_comm_on_error: bool = False, strict: bool = True, broadcast_enable: bool = False, reconnect_delay: float = 0.1, reconnect_delay_max: float = 300, on_reconnect_callback: Callable[[], None] | None = None, no_resend_on_retry: bool = False, **kwargs: Any)
Bases:
ModbusClientMixin
,ModbusProtocol
ModbusBaseClient
Parameters common to all clients:
- Parameters:
framer – (optional) Modbus Framer class.
timeout – (optional) Timeout for a request, in seconds.
retries – (optional) Max number of retries per request.
retry_on_empty – (optional) Retry on empty response.
close_comm_on_error – (optional) Close connection on error.
strict – (optional) Strict timing, 1.5 character between requests.
broadcast_enable – (optional) True to treat id 0 as broadcast address.
reconnect_delay – (optional) Minimum delay in milliseconds before reconnecting.
reconnect_delay_max – (optional) Maximum delay in milliseconds before reconnecting.
on_reconnect_callback – (optional) Function that will be called just before a reconnection attempt.
no_resend_on_retry – (optional) Do not resend request when retrying due to missing response.
kwargs – (optional) Experimental parameters.
Tip
Common parameters and all external methods for all clients are documented here, and not repeated with each client.
Tip
reconnect_delay doubles automatically with each unsuccessful connect, from reconnect_delay to reconnect_delay_max. Set reconnect_delay=0 to avoid automatic reconnection.
ModbusBaseClient
is normally not referenced outsidepymodbus
.Application methods, common to all clients:
- property connected
Connect internal.
- register(custom_response_class: ModbusResponse) None
Register a custom response class with the decoder (call sync).
- Parameters:
custom_response_class – (optional) Modbus response class.
- Raises:
MessageRegisterException – Check exception text.
Use register() to add non-standard responses (like e.g. a login prompt) and have them interpreted automatically.
- close(reconnect=False) None
Close connection.
- idle_time() float
Time before initiating next transaction (call sync).
Applications can call message functions without checking idle_time(), this is done automatically.
- execute(request: ModbusRequest = None) ModbusResponse
Execute request and get response (call sync/async).
- Parameters:
request – The request to process
- Returns:
The result of the request execution
- Raises:
ConnectionException – Check exception text.
- async async_execute(request=None)
Execute requests asynchronously.
- callback_data(data: bytes, addr: tuple = None) int
Handle received data
returns number of bytes consumed
- callback_disconnected(_reason: Exception) None
Handle lost connection
- async connect()
Connect to the modbus remote host.
- raise_future(my_future, exc)
Set exception of a future if not done.
- class pymodbus.client.AsyncModbusSerialClient(port: str, framer: ~typing.Type[~pymodbus.framer.base.ModbusFramer] = <class 'pymodbus.framer.rtu_framer.ModbusRtuFramer'>, baudrate: int = 19200, bytesize: int = 8, parity: str = 'N', stopbits: int = 1, **kwargs: ~typing.Any)
Bases:
ModbusBaseClient
,Protocol
AsyncModbusSerialClient.
- Parameters:
port – Serial port used for communication.
framer – (optional) Framer class.
baudrate – (optional) Bits per second.
bytesize – (optional) Number of bits per byte 7-8.
parity – (optional) ‘E’ven, ‘O’dd or ‘N’one
stopbits – (optional) Number of stop bits 0-2¡.
handle_local_echo – (optional) Discard local echo from dongle.
kwargs – (optional) Experimental parameters
The serial communication is RS-485 based, and usually used with a usb RS485 dongle.
Example:
from pymodbus.client import AsyncModbusSerialClient async def run(): client = AsyncModbusSerialClient("dev/serial0") await client.connect() ... client.close()
- property connected
Connect internal.
- async connect() bool
Connect Async client.
- class pymodbus.client.ModbusSerialClient(port: str, framer: ~typing.Type[~pymodbus.framer.base.ModbusFramer] = <class 'pymodbus.framer.rtu_framer.ModbusRtuFramer'>, baudrate: int = 19200, bytesize: int = 8, parity: str = 'N', stopbits: int = 1, **kwargs: ~typing.Any)
Bases:
ModbusBaseClient
ModbusSerialClient.
- Parameters:
port – Serial port used for communication.
framer – (optional) Framer class.
baudrate – (optional) Bits per second.
bytesize – (optional) Number of bits per byte 7-8.
parity – (optional) ‘E’ven, ‘O’dd or ‘N’one
stopbits – (optional) Number of stop bits 0-2¡.
handle_local_echo – (optional) Discard local echo from dongle.
kwargs – (optional) Experimental parameters
The serial communication is RS-485 based, and usually used with a usb RS485 dongle.
Example:
from pymodbus.client import ModbusSerialClient def run(): client = ModbusSerialClient("dev/serial0") client.connect() ... client.close()
Remark: There are no automatic reconnect as with AsyncModbusSerialClient
- property connected
Connect internal.
- connect()
Connect to the modbus serial server.
- close()
Close the underlying socket connection.
- send(request)
Send data on the underlying socket.
If receive buffer still holds some data then flush it.
Sleep if last send finished less than 3.5 character times ago.
- recv(size)
Read data from the underlying descriptor.
- is_socket_open()
Check if socket is open.
- class pymodbus.client.AsyncModbusTcpClient(host: str, port: int = 502, framer: ~typing.Type[~pymodbus.framer.base.ModbusFramer] = <class 'pymodbus.framer.socket_framer.ModbusSocketFramer'>, source_address: ~typing.Tuple[str, int] = None, **kwargs: ~typing.Any)
Bases:
ModbusBaseClient
,Protocol
AsyncModbusTcpClient.
- Parameters:
host – Host IP address or host name
port – (optional) Port used for communication
framer – (optional) Framer class
source_address – (optional) source address of client
kwargs – (optional) Experimental parameters
Example:
from pymodbus.client import AsyncModbusTcpClient async def run(): client = AsyncModbusTcpClient("localhost") await client.connect() ... client.close()
- async connect() bool
Initiate connection to start client.
- property connected
Return true if connected.
- class pymodbus.client.ModbusTcpClient(host: str, port: int = 502, framer: ~typing.Type[~pymodbus.framer.base.ModbusFramer] = <class 'pymodbus.framer.socket_framer.ModbusSocketFramer'>, source_address: ~typing.Tuple[str, int] = None, **kwargs: ~typing.Any)
Bases:
ModbusBaseClient
ModbusTcpClient.
- Parameters:
host – Host IP address or host name
port – (optional) Port used for communication
framer – (optional) Framer class
source_address – (optional) source address of client
kwargs – (optional) Experimental parameters
Example:
from pymodbus.client import ModbusTcpClient async def run(): client = ModbusTcpClient("localhost") client.connect() ... client.close()
Remark: There are no automatic reconnect as with AsyncModbusTcpClient
- property connected
Connect internal.
- connect()
Connect to the modbus tcp server.
- close()
Close the underlying socket connection.
- send(request)
Send data on the underlying socket.
- recv(size)
Read data from the underlying descriptor.
- is_socket_open()
Check if socket is open.
- class pymodbus.client.AsyncModbusTlsClient(host: str, port: int = 802, framer: ~typing.Type[~pymodbus.framer.base.ModbusFramer] = <class 'pymodbus.framer.tls_framer.ModbusTlsFramer'>, sslctx: ~ssl.SSLContext = None, certfile: str = None, keyfile: str = None, password: str = None, server_hostname: str = None, **kwargs: ~typing.Any)
Bases:
AsyncModbusTcpClient
AsyncModbusTlsClient.
- Parameters:
host – Host IP address or host name
port – (optional) Port used for communication
framer – (optional) Framer class
source_address – (optional) Source address of client
sslctx – (optional) SSLContext to use for TLS
certfile – (optional) Cert file path for TLS server request
keyfile – (optional) Key file path for TLS server request
password – (optional) Password for for decrypting private key file
server_hostname – (optional) Bind certificate to host
kwargs – (optional) Experimental parameters
- ..tip::
See ModbusBaseClient for common parameters.
Example:
from pymodbus.client import AsyncModbusTlsClient async def run(): client = AsyncModbusTlsClient("localhost") await client.connect() ... client.close()
- async connect() bool
Initiate connection to start client.
- class pymodbus.client.ModbusTlsClient(host: str, port: int = 802, framer: ~typing.Type[~pymodbus.framer.base.ModbusFramer] = <class 'pymodbus.framer.tls_framer.ModbusTlsFramer'>, sslctx: ~ssl.SSLContext = None, certfile: str = None, keyfile: str = None, password: str = None, server_hostname: str = None, **kwargs: ~typing.Any)
Bases:
ModbusTcpClient
ModbusTlsClient.
- Parameters:
host – Host IP address or host name
port – (optional) Port used for communication
framer – (optional) Framer class
source_address – (optional) Source address of client
sslctx – (optional) SSLContext to use for TLS
certfile – (optional) Cert file path for TLS server request
keyfile – (optional) Key file path for TLS server request
password – (optional) Password for decrypting private key file
server_hostname – (optional) Bind certificate to host
kwargs – (optional) Experimental parameters
- ..tip::
See ModbusBaseClient for common parameters.
Example:
from pymodbus.client import ModbusTlsClient async def run(): client = ModbusTlsClient("localhost") client.connect() ... client.close()
Remark: There are no automatic reconnect as with AsyncModbusTlsClient
- property connected
Connect internal.
- connect()
Connect to the modbus tls server.
- class pymodbus.client.AsyncModbusUdpClient(host: str, port: int = 502, framer: ~typing.Type[~pymodbus.framer.base.ModbusFramer] = <class 'pymodbus.framer.socket_framer.ModbusSocketFramer'>, source_address: ~typing.Tuple[str, int] = None, **kwargs: ~typing.Any)
Bases:
ModbusBaseClient
,Protocol
,DatagramProtocol
AsyncModbusUdpClient.
- Parameters:
host – Host IP address or host name
port – (optional) Port used for communication.
framer – (optional) Framer class.
source_address – (optional) source address of client,
kwargs – (optional) Experimental parameters
- ..tip::
See ModbusBaseClient for common parameters.
Example:
from pymodbus.client import AsyncModbusUdpClient async def run(): client = AsyncModbusUdpClient("localhost") await client.connect() ... client.close()
- property connected
Return true if connected.
- class pymodbus.client.ModbusUdpClient(host: str, port: int = 502, framer: ~typing.Type[~pymodbus.framer.base.ModbusFramer] = <class 'pymodbus.framer.socket_framer.ModbusSocketFramer'>, source_address: ~typing.Tuple[str, int] = None, **kwargs: ~typing.Any)
Bases:
ModbusBaseClient
ModbusUdpClient.
- Parameters:
host – Host IP address or host name
port – (optional) Port used for communication.
framer – (optional) Framer class.
source_address – (optional) source address of client,
kwargs – (optional) Experimental parameters
- ..tip::
See ModbusBaseClient for common parameters.
Example:
from pymodbus.client import ModbusUdpClient async def run(): client = ModbusUdpClient("localhost") client.connect() ... client.close()
Remark: There are no automatic reconnect as with AsyncModbusUdpClient
- property connected
Connect internal.
Modbus calls
Pymodbus makes all standard modbus requests/responses available as simple calls.
Using Modbus<transport>Client.register() custom messagees can be added to pymodbus, and handled automatically.
- class pymodbus.client.mixin.ModbusClientMixin
Bases:
object
ModbusClientMixin.
This is an interface class to facilitate the sending requests/receiving responses like read_coils. execute() allows to make a call with non-standard or user defined function codes (remember to add a PDU in the transport class to interpret the request/response).
Simple modbus message call:
response = client.read_coils(1, 10) # or response = await client.read_coils(1, 10)
Advanced modbus message call:
request = ReadCoilsRequest(1,10) response = client.execute(request) # or request = ReadCoilsRequest(1,10) response = await client.execute(request)
Tip
All methods can be used directly (synchronous) or with await <method> (asynchronous) depending on the client used.
- execute(request: ModbusRequest) ModbusResponse
Execute request (code ???).
- Parameters:
request – Request to send
- Raises:
Call with custom function codes.
Tip
Response is not interpreted.
- read_coils(address: int, count: int = 1, slave: int = 0, **kwargs: Any) ModbusResponse
Read coils (code 0x01).
- Parameters:
address – Start address to read from
count – (optional) Number of coils to read
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- read_discrete_inputs(address: int, count: int = 1, slave: int = 0, **kwargs: Any) ModbusResponse
Read discrete inputs (code 0x02).
- Parameters:
address – Start address to read from
count – (optional) Number of coils to read
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- read_holding_registers(address: int, count: int = 1, slave: int = 0, **kwargs: Any) ModbusResponse
Read holding registers (code 0x03).
- Parameters:
address – Start address to read from
count – (optional) Number of coils to read
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- read_input_registers(address: int, count: int = 1, slave: int = 0, **kwargs: Any) ModbusResponse
Read input registers (code 0x04).
- Parameters:
address – Start address to read from
count – (optional) Number of coils to read
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- write_coil(address: int, value: bool, slave: int = 0, **kwargs: Any) ModbusResponse
Write single coil (code 0x05).
- Parameters:
address – Address to write to
value – Boolean to write
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- write_register(address: int, value: int, slave: int = 0, **kwargs: Any) ModbusResponse
Write register (code 0x06).
- Parameters:
address – Address to write to
value – Value to write
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- read_exception_status(slave: int = 0, **kwargs: Any) ModbusResponse
Read Exception Status (code 0x07).
- Parameters:
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- diag_query_data(msg: bytearray, slave: int = 0, **kwargs: Any) ModbusResponse
Diagnose query data (code 0x08 sub 0x00).
- Parameters:
msg – Message to be returned
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- diag_restart_communication(toggle: bool, slave: int = 0, **kwargs: Any) ModbusResponse
Diagnose restart communication (code 0x08 sub 0x01).
- Parameters:
toggle – True if toggled.
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- diag_read_diagnostic_register(slave: int = 0, **kwargs: Any) ModbusResponse
Diagnose read diagnostic register (code 0x08 sub 0x02).
- Parameters:
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- diag_change_ascii_input_delimeter(slave: int = 0, **kwargs: Any) ModbusResponse
Diagnose change ASCII input delimiter (code 0x08 sub 0x03).
- Parameters:
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- diag_force_listen_only(slave: int = 0, **kwargs: Any) ModbusResponse
Diagnose force listen only (code 0x08 sub 0x04).
- Parameters:
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- diag_clear_counters(slave: int = 0, **kwargs: Any) ModbusResponse
Diagnose clear counters (code 0x08 sub 0x0A).
- Parameters:
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- diag_read_bus_message_count(slave: int = 0, **kwargs: Any) ModbusResponse
Diagnose read bus message count (code 0x08 sub 0x0B).
- Parameters:
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- diag_read_bus_comm_error_count(slave: int = 0, **kwargs: Any) ModbusResponse
Diagnose read Bus Communication Error Count (code 0x08 sub 0x0C).
- Parameters:
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- diag_read_bus_exception_error_count(slave: int = 0, **kwargs: Any) ModbusResponse
Diagnose read Bus Exception Error Count (code 0x08 sub 0x0D).
- Parameters:
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- diag_read_slave_message_count(slave: int = 0, **kwargs: Any) ModbusResponse
Diagnose read Slave Message Count (code 0x08 sub 0x0E).
- Parameters:
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- diag_read_slave_no_response_count(slave: int = 0, **kwargs: Any) ModbusResponse
Diagnose read Slave No Response Count (code 0x08 sub 0x0F).
- Parameters:
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- diag_read_slave_nak_count(slave: int = 0, **kwargs: Any) ModbusResponse
Diagnose read Slave NAK Count (code 0x08 sub 0x10).
- Parameters:
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- diag_read_slave_busy_count(slave: int = 0, **kwargs: Any) ModbusResponse
Diagnose read Slave Busy Count (code 0x08 sub 0x11).
- Parameters:
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- diag_read_bus_char_overrun_count(slave: int = 0, **kwargs: Any) ModbusResponse
Diagnose read Bus Character Overrun Count (code 0x08 sub 0x12).
- Parameters:
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- diag_read_iop_overrun_count(slave: int = 0, **kwargs: Any) ModbusResponse
Diagnose read Iop overrun count (code 0x08 sub 0x13).
- Parameters:
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- diag_clear_overrun_counter(slave: int = 0, **kwargs: Any) ModbusResponse
Diagnose Clear Overrun Counter and Flag (code 0x08 sub 0x14).
- Parameters:
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- diag_getclear_modbus_response(slave: int = 0, **kwargs: Any) ModbusResponse
Diagnose Get/Clear modbus plus (code 0x08 sub 0x15).
- Parameters:
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- diag_get_comm_event_counter(**kwargs: Any) ModbusResponse
Diagnose get event counter (code 0x0B).
- Parameters:
kwargs – (optional) Experimental parameters.
- Raises:
- diag_get_comm_event_log(**kwargs: Any) ModbusResponse
Diagnose get event counter (code 0x0C).
- Parameters:
kwargs – (optional) Experimental parameters.
- Raises:
- write_coils(address: int, values: List[bool] | bool, slave: int = 0, **kwargs: Any) ModbusResponse
Write coils (code 0x0F).
- Parameters:
address – Start address to write to
values – List of booleans to write, or a single boolean to write
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- write_registers(address: int, values: List[int] | int, slave: int = 0, **kwargs: Any) ModbusResponse
Write registers (code 0x10).
- Parameters:
address – Start address to write to
values – List of values to write, or a single value to write
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- report_slave_id(slave: int = 0, **kwargs: Any) ModbusResponse
Report slave ID (code 0x11).
- Parameters:
slave – (optional) Modbus slave ID
kwargs – (optional) Experimental parameters.
- Raises:
- read_file_record(records: List[Tuple], **kwargs: Any) ModbusResponse
Read file record (code 0x14).
- Parameters:
records – List of (Reference type, File number, Record Number, Record Length)
kwargs – (optional) Experimental parameters.
- Raises:
- write_file_record(records: List[Tuple], **kwargs: Any) ModbusResponse
Write file record (code 0x15).
- Parameters:
records – List of (Reference type, File number, Record Number, Record Length)
kwargs – (optional) Experimental parameters.
- Raises:
- mask_write_register(address: int = 0, and_mask: int = 65535, or_mask: int = 0, **kwargs: Any) ModbusResponse
Mask write register (code 0x16).
- Parameters:
address – The mask pointer address (0x0000 to 0xffff)
and_mask – The and bitmask to apply to the register address
or_mask – The or bitmask to apply to the register address
kwargs – (optional) Experimental parameters.
- Raises:
- readwrite_registers(read_address: int = 0, read_count: int = 0, write_address: int = 0, values: List[int] | int = 0, slave: int = 0, **kwargs) ModbusResponse
Read/Write registers (code 0x17).
- Parameters:
read_address – The address to start reading from
read_count – The number of registers to read from address
write_address – The address to start writing to
values – List of values to write, or a single value to write
slave – (optional) Modbus slave ID
kwargs –
- Raises:
- read_fifo_queue(address: int = 0, **kwargs: Any) ModbusResponse
Read FIFO queue (code 0x18).
- Parameters:
address – The address to start reading from
kwargs –
- Raises:
- read_device_information(read_code: int = None, object_id: int = 0, **kwargs: Any) ModbusResponse
Read FIFO queue (code 0x2B sub 0x0E).
- Parameters:
read_code – The device information read code
object_id – The object to read from
kwargs –
- Raises:
- class DATATYPE(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)
Bases:
Enum
Datatype enum (name and number of bytes), used for convert_* calls.
- classmethod convert_from_registers(registers: List[int], data_type: DATATYPE) int | float | str
Convert registers to int/float/str.
- Parameters:
registers – list of registers received from e.g. read_holding_registers()
data_type – data type to convert to
- Returns:
int, float or str depending on “data_type”
- Raises:
ModbusException – when size of registers is not 1, 2 or 4
- classmethod convert_to_registers(value: int | float | str, data_type: DATATYPE) List[int]
Convert int/float/str to registers (16/32/64 bit).
- Parameters:
value – value to be converted
data_type – data type to be encoded as registers
- Returns:
List of registers, can be used directly in e.g. write_registers()
- Raises:
TypeError – when there is a mismatch between data_type and value