Examples

Examples are divided in 2 parts:

The first part are some simple client examples which can be copied and run directly. These examples show the basic functionality of the library.

The second part are more advanced examples, but in order to not duplicate code, this requires you to download the examples directory and run the examples in the directory.

Ready to run examples:

These examples are very basic examples, showing how a client can communicate with a server.

You need to modify the code to adapt it to your situation.

Simple asynchronous client

Source: examples/simple_async_client.py

#!/usr/bin/env python3
"""Pymodbus asynchronous client example.

An example of a single threaded synchronous client.

usage: simple_client_async.py

All options must be adapted in the code
The corresponding server must be started before e.g. as:
    python3 server_sync.py
"""
import asyncio

import pymodbus.client as ModbusClient
from pymodbus import (
    ExceptionResponse,
    FramerType,
    ModbusException,
    pymodbus_apply_logging_config,
)


async def run_async_simple_client(comm, host, port, framer=FramerType.SOCKET):
    """Run async client."""
    # activate debugging
    pymodbus_apply_logging_config("DEBUG")

    print("get client")
    if comm == "tcp":
        client = ModbusClient.AsyncModbusTcpClient(
            host,
            port=port,
            framer=framer,
            # timeout=10,
            # retries=3,
            # retry_on_empty=False,
            # source_address=("localhost", 0),
        )
    elif comm == "udp":
        client = ModbusClient.AsyncModbusUdpClient(
            host,
            port=port,
            framer=framer,
            # timeout=10,
            # retries=3,
            # retry_on_empty=False,
            # source_address=None,
        )
    elif comm == "serial":
        client = ModbusClient.AsyncModbusSerialClient(
            port,
            framer=framer,
            # timeout=10,
            # retries=3,
            # retry_on_empty=False,
            # strict=True,
            baudrate=9600,
            bytesize=8,
            parity="N",
            stopbits=1,
            # handle_local_echo=False,
        )
    elif comm == "tls":
        client = ModbusClient.AsyncModbusTlsClient(
            host,
            port=port,
            framer=FramerType.TLS,
            # timeout=10,
            # retries=3,
            # retry_on_empty=False,
            # sslctx=sslctx,
            certfile="../examples/certificates/pymodbus.crt",
            keyfile="../examples/certificates/pymodbus.key",
            # password="none",
            server_hostname="localhost",
        )
    else:
        print(f"Unknown client {comm} selected")
        return

    print("connect to server")
    await client.connect()
    # test client is connected
    assert client.connected

    print("get and verify data")
    try:
        # See all calls in client_calls.py
        rr = await client.read_coils(1, 1, slave=1)
    except ModbusException as exc:
        print(f"Received ModbusException({exc}) from library")
        client.close()
        return
    if rr.isError():
        print(f"Received Modbus library error({rr})")
        client.close()
        return
    if isinstance(rr, ExceptionResponse):
        print(f"Received Modbus library exception ({rr})")
        # THIS IS NOT A PYTHON EXCEPTION, but a valid modbus message
        client.close()

    print("close connection")
    client.close()


if __name__ == "__main__":
    asyncio.run(
        run_async_simple_client("tcp", "127.0.0.1", 5020), debug=True
    )

Simple synchronous client

Source: examples/simple_sync_client.py

#!/usr/bin/env python3
"""Pymodbus synchronous client example.

An example of a single threaded synchronous client.

usage: simple_client_async.py

All options must be adapted in the code
The corresponding server must be started before e.g. as:
    python3 server_sync.py
"""

# --------------------------------------------------------------------------- #
# import the various client implementations
# --------------------------------------------------------------------------- #
import pymodbus.client as ModbusClient
from pymodbus import (
    ExceptionResponse,
    FramerType,
    ModbusException,
    pymodbus_apply_logging_config,
)


def run_sync_simple_client(comm, host, port, framer=FramerType.SOCKET):
    """Run sync client."""
    # activate debugging
    pymodbus_apply_logging_config("DEBUG")

    print("get client")
    if comm == "tcp":
        client = ModbusClient.ModbusTcpClient(
            host,
            port=port,
            framer=framer,
            # timeout=10,
            # retries=3,
            # retry_on_empty=False,y
            # source_address=("localhost", 0),
        )
    elif comm == "udp":
        client = ModbusClient.ModbusUdpClient(
            host,
            port=port,
            framer=framer,
            # timeout=10,
            # retries=3,
            # retry_on_empty=False,
            # source_address=None,
        )
    elif comm == "serial":
        client = ModbusClient.ModbusSerialClient(
            port,
            framer=framer,
            # timeout=10,
            # retries=3,
            # retry_on_empty=False,
            # strict=True,
            baudrate=9600,
            bytesize=8,
            parity="N",
            stopbits=1,
            # handle_local_echo=False,
        )
    elif comm == "tls":
        client = ModbusClient.ModbusTlsClient(
            host,
            port=port,
            framer=FramerType.TLS,
            # timeout=10,
            # retries=3,
            # retry_on_empty=False,
            # sslctx=None,
            certfile="../examples/certificates/pymodbus.crt",
            keyfile="../examples/certificates/pymodbus.key",
            # password=None,
            server_hostname="localhost",
        )
    else:
        print(f"Unknown client {comm} selected")
        return

    print("connect to server")
    client.connect()

    print("get and verify data")
    try:
        rr = client.read_coils(1, 1, slave=1)
    except ModbusException as exc:
        print(f"Received ModbusException({exc}) from library")
        client.close()
        return
    if rr.isError():
        print(f"Received Modbus library error({rr})")
        client.close()
        return
    if isinstance(rr, ExceptionResponse):
        print(f"Received Modbus library exception ({rr})")
        # THIS IS NOT A PYTHON EXCEPTION, but a valid modbus message
        client.close()

    print("close connection")
    client.close()


if __name__ == "__main__":
    run_sync_simple_client("tcp", "127.0.0.1", "5020")

Client performance sync vs async

Source: examples/client_performance.py

#!/usr/bin/env python3
"""Test performance of client: sync vs. async.

This example show how much faster the async version is.

example run:

(pymodbus) % ./client_performance.py
--- Testing sync client v3.4.1
running 1000 call (each 10 registers), took 114.10 seconds
Averages 114.10 ms pr call and 11.41 ms pr register.
--- Testing async client v3.4.1
running 1000 call (each 10 registers), took 0.33 seconds
Averages 0.33 ms pr call and 0.03 ms pr register.
"""
import asyncio
import time

from pymodbus import FramerType
from pymodbus.client import AsyncModbusSerialClient, ModbusSerialClient


LOOP_COUNT = 1000
REGISTER_COUNT = 10


def run_sync_client_test():
    """Run sync client."""
    print("--- Testing sync client v3.4.1")
    client = ModbusSerialClient(
        "/dev/ttys007",
        framer_name=FramerType.RTU,
        baudrate=9600,
    )
    client.connect()
    assert client.connected

    start_time = time.time()
    for _i in range(LOOP_COUNT):
        rr = client.read_input_registers(1, REGISTER_COUNT, slave=1)
        if rr.isError():
            print(f"Received Modbus library error({rr})")
            break
    client.close()
    run_time = time.time() - start_time
    avg_call = (run_time / LOOP_COUNT) * 1000
    avg_register = avg_call / REGISTER_COUNT
    print(
        f"running {LOOP_COUNT} call (each {REGISTER_COUNT} registers), took {run_time:.2f} seconds"
    )
    print(f"Averages {avg_call:.2f} ms pr call and {avg_register:.2f} ms pr register.")


async def run_async_client_test():
    """Run async client."""
    print("--- Testing async client v3.4.1")
    client = AsyncModbusSerialClient(
        "/dev/ttys007",
        framer_name=FramerType.RTU,
        baudrate=9600,
    )
    await client.connect()
    assert client.connected

    start_time = time.time()
    for _i in range(LOOP_COUNT):
        rr = await client.read_input_registers(1, REGISTER_COUNT, slave=1)
        if rr.isError():
            print(f"Received Modbus library error({rr})")
            break
    client.close()
    run_time = time.time() - start_time
    avg_call = (run_time / LOOP_COUNT) * 1000
    avg_register = avg_call / REGISTER_COUNT
    print(
        f"running {LOOP_COUNT} call (each {REGISTER_COUNT} registers), took {run_time:.2f} seconds"
    )
    print(f"Averages {avg_call:.2f} ms pr call and {avg_register:.2f} ms pr register.")


if __name__ == "__main__":
    run_sync_client_test()
    asyncio.run(run_async_client_test())

Advanced examples

These examples are considered essential usage examples, and are guaranteed to work, because they are tested automatilly with each dev branch commit using CI.

Tip

The examples needs to be run from within the examples directory, unless you modify them. Most examples use helper.py and client_*.py or server_*.py. This is done to avoid maintaining the same code in multiple files.

Client asynchronous calls

Source: examples/client_async_calls.py

Pymodbus Client modbus async all calls example.

Please see method async_template_call for a template on how to make modbus calls and check for different error conditions.

The handle* functions each handle a set of modbus calls with the same register type (e.g. coils).

All available modbus calls are present.

If you are performing a request that is not available in the client mixin, you have to perform the request like this instead:

from pymodbus.diag_message import ClearCountersRequest
from pymodbus.diag_message import ClearCountersResponse

request  = ClearCountersRequest()
response = client.execute(request)
if isinstance(response, ClearCountersResponse):
    ... do something with the response

This example uses client_async.py and client_sync.py to handle connection, and have the same options.

The corresponding server must be started before e.g. as:

./server_async.py

Client asynchronous

Source: examples/client_async.py

Pymodbus asynchronous client example.

usage:

client_async.py [-h] [-c {tcp,udp,serial,tls}]
                [-f {ascii,rtu,socket,tls}]
                [-l {critical,error,warning,info,debug}] [-p PORT]
                [--baudrate BAUDRATE] [--host HOST]

-h, --help
    show this help message and exit
-c, -comm {tcp,udp,serial,tls}
    set communication, default is tcp
-f, --framer {ascii,rtu,socket,tls}
    set framer, default depends on --comm
-l, --log {critical,error,warning,info,debug}
    set log level, default is info
-p, --port PORT
    set port
--baudrate BAUDRATE
    set serial device baud rate
--host HOST
    set host, default is 127.0.0.1
The corresponding server must be started before e.g. as:

python3 server_sync.py

Client calls

Source: examples/client_calls.py

Pymodbus Client modbus all calls example.

Please see method template_call for a template on how to make modbus calls and check for different error conditions.

The handle* functions each handle a set of modbus calls with the same register type (e.g. coils).

All available modbus calls are present.

If you are performing a request that is not available in the client mixin, you have to perform the request like this instead:

from pymodbus.diag_message import ClearCountersRequest
from pymodbus.diag_message import ClearCountersResponse

request  = ClearCountersRequest()
response = client.execute(request)
if isinstance(response, ClearCountersResponse):
    ... do something with the response

This example uses client_async.py and client_sync.py to handle connection, and have the same options.

The corresponding server must be started before e.g. as:

./server_async.py

Client custom message

Source: examples/client_custom_msg.py

Pymodbus Synchronous Client Examples.

The following is an example of how to use the synchronous modbus client implementation from pymodbus:

with ModbusClient("127.0.0.1") as client:
    result = client.read_coils(1,10)
    print result

Client payload

Source: examples/client_payload.py

Pymodbus Client Payload Example.

This example shows how to build a client with a complicated memory layout using builder.

Works out of the box together with payload_server.py

Client synchronous

Source: examples/client_sync.py

Pymodbus Synchronous Client Example.

An example of a single threaded synchronous client.

usage:

client_sync.py [-h] [-c {tcp,udp,serial,tls}]
                [-f {ascii,rtu,socket,tls}]
                [-l {critical,error,warning,info,debug}] [-p PORT]
                [--baudrate BAUDRATE] [--host HOST]

-h, --help
    show this help message and exit
-c, --comm {tcp,udp,serial,tls}
    set communication, default is tcp
-f, --framer {ascii,rtu,socket,tls}
    set framer, default depends on --comm
-l, --log {critical,error,warning,info,debug}
    set log level, default is info
-p, --port PORT
    set port
--baudrate BAUDRATE
    set serial device baud rate
--host HOST
    set host, default is 127.0.0.1

The corresponding server must be started before e.g. as:

python3 server_sync.py

Server asynchronous

Source: examples/server_async.py

Pymodbus asynchronous Server Example.

An example of a multi threaded asynchronous server.

usage:

server_async.py [-h] [--comm {tcp,udp,serial,tls}]
                [--framer {ascii,rtu,socket,tls}]
                [--log {critical,error,warning,info,debug}]
                [--port PORT] [--store {sequential,sparse,factory,none}]
                [--slaves SLAVES]

-h, --help
    show this help message and exit
-c, --comm {tcp,udp,serial,tls}
    set communication, default is tcp
-f, --framer {ascii,rtu,socket,tls}
    set framer, default depends on --comm
-l, --log {critical,error,warning,info,debug}
    set log level, default is info
-p, --port PORT
    set port
    set serial device baud rate
--store {sequential,sparse,factory,none}
    set datastore type
--slaves SLAVES
    set number of slaves to respond to

The corresponding client can be started as:

python3 client_sync.py

Server callback

Source: examples/server_callback.py

Pymodbus Server With Callbacks.

This is an example of adding callbacks to a running modbus server when a value is written to it.

Server tracer

Source: examples/server_hook.py

Pymodbus Server With request/response manipulator.

This is an example of using the builtin request/response tracer to manipulate the messages to/from the modbus server

Server payload

Source: examples/server_payload.py

Pymodbus Server Payload Example.

This example shows how to initialize a server with a complicated memory layout using builder.

Server synchronous

Source: examples/server_sync.py

Pymodbus Synchronous Server Example.

An example of a single threaded synchronous server.

usage:

server_sync.py [-h] [--comm {tcp,udp,serial,tls}]
               [--framer {ascii,rtu,socket,tls}]
               [--log {critical,error,warning,info,debug}]
               [--port PORT] [--store {sequential,sparse,factory,none}]
               [--slaves SLAVES]

-h, --help
    show this help message and exit
-c, --comm {tcp,udp,serial,tls}
    set communication, default is tcp
-f, --framer {ascii,rtu,socket,tls}
    set framer, default depends on --comm
-l, --log {critical,error,warning,info,debug}
    set log level, default is info
-p, --port PORT
    set port
    set serial device baud rate
--store {sequential,sparse,factory,none}
    set datastore type
--slaves SLAVES
    set number of slaves to respond to
The corresponding client can be started as:

python3 client_sync.py

REMARK It is recommended to use the async server! The sync server is just a thin cover on top of the async server and is in some aspects a lot slower.

Server updating

Source: examples/server_updating.py

Pymodbus asynchronous Server with updating task Example.

An example of an asynchronous server and a task that runs continuously alongside the server and updates values.

usage:

server_updating.py [-h] [--comm {tcp,udp,serial,tls}]
                   [--framer {ascii,rtu,socket,tls}]
                   [--log {critical,error,warning,info,debug}]
                   [--port PORT] [--store {sequential,sparse,factory,none}]
                   [--slaves SLAVES]

-h, --help
    show this help message and exit
-c, --comm {tcp,udp,serial,tls}
    set communication, default is tcp
-f, --framer {ascii,rtu,socket,tls}
    set framer, default depends on --comm
-l, --log {critical,error,warning,info,debug}
    set log level, default is info
-p, --port PORT
    set port
    set serial device baud rate
--store {sequential,sparse,factory,none}
    set datastore type
--slaves SLAVES
    set number of slaves to respond to
The corresponding client can be started as:

python3 client_sync.py

Simulator example

Source: examples/simulator.py

Pymodbus simulator server/client Example.

An example of how to use the simulator (server) with a client.

for usage see documentation of simulator

Tip

pymodbus.simulator starts the server directly from the commandline

Simulator datastore (shared storage) example

Source: examples/datastore_simulator_share.py

Pymodbus datastore simulator Example.

An example of using simulator datastore with json interface.

Detailed description of the device definition can be found at:

usage:

datastore_simulator_share.py [-h]
                    [--log {critical,error,warning,info,debug}]
                    [--port PORT]
                    [--test_client]

-h, --help
    show this help message and exit
-l, --log {critical,error,warning,info,debug}
    set log level
-p, --port PORT
    set port to use
--test_client
    starts a client to test the configuration
The corresponding client can be started as:

python3 client_sync.py

Tip

This is NOT the pymodbus simulator, that is started as pymodbus.simulator.

Message generator

Source: examples/message_generator.py

Modbus Message Generator.

Message Parser

Source: examples/message_parser.py

Modbus Message Parser.

The following is an example of how to parse modbus messages using the supplied framers.

Modbus forwarder

Source: examples/modbus_forwarder.py

Pymodbus synchronous forwarder.

This is a repeater or converter and an example of just how powerful datastore is.

It consist of a server (any comm) and a client (any comm), functionality:

  1. server receives a read/write request from external client:

    • client sends a new read/write request to target server

    • client receives response and updates the datastore

    • server sends new response to external client

Both server and client are tcp based, but it can be easily modified to any server/client (see client_sync.py and server_sync.py for other communication types)

WARNING This example is a simple solution, that do only forward read requests.

Examples contributions

These examples are supplied by users of pymodbus. The pymodbus team thanks for sharing the examples.

Solar

Source: examples/contrib/solar.py

Pymodbus Synchronous Client Example.

Modified to test long term connection.

Redis datastore

Source: examples/contrib/redis_datastore.py

Datastore using redis.

Serial Forwarder

Source: examples/contrib/serial_forwarder.py

Pymodbus SerialRTU2TCP Forwarder

usage : python3 serial_forwarder.py –log DEBUG –port “/dev/ttyUSB0” –baudrate 9600 –server_ip “192.168.1.27” –server_port 5020 –slaves 1 2 3

Sqlalchemy datastore

Source: examples/contrib/sql_datastore.py

Datastore using SQL.