Repository: pymodbus-dev/pymodbus

Issue:
Running example give me an error

### Versions

- Python:3.9
- OS:Raspbian
- Pymodbus:3.3.0
- Modbus Hardware (if used): Not Applicable at this point

### Pymodbus Specific

- Server: tcp-async


### Description
I have to rewrite a program that used an old version of pymodbus, so I am starting with an example that is similar to the original program, that being [Updating server example](https://pymodbus.readthedocs.io/en/latest/source/examples.html#updating-server) from your documentation. When I try to run an unedited version of this example I get this error: 
Traceback (most recent call last):
  File "/home/user/Flow/test.py", line 33, in <module>
    from examples.server_async import run_async_server, setup_server
ModuleNotFoundError: No module named 'examples'

Any idea what the issue is? I have already tried reinstalling the library.





Discussion:
Did you download the examples directory, probably not because that is your problem.
https://pymodbus.readthedocs.io/en/latest/source/examples.html#
I did download the example folder and got the same error:
user@raspberrypi:~/pymodbus-dev/pymodbus-dev/examples $ ls
build_bcd_payload.py  client_sync.py       message_generator.py  server_simulator.py
certificates          client_sync_test.py  message_parser.py     server_sync.py
client_async.py       client_test.py       modbus_forwarder.py   server_updating.py
client_calls.py       contrib              server_async.py
client_custom_msg.py  helper.py            server_callback.py
client_payload.py     __init__.py          server_payload.py
user@raspberrypi:~/pymodbus-dev/pymodbus-dev/examples $ sudo python3 server_updating.py
Traceback (most recent call last):
  File "/home/user/pymodbus-dev/pymodbus-dev/examples/server_updating.py", line 33, in <module>
    from examples.server_async import run_async_server, setup_server
ModuleNotFoundError: No module named 'examples'

because you do not run the script inside the directory examples.
Closing the issue as it is not a pymodbus problem.
I would suggest adding extra instructions for the pip installer because that's the installer I used and there were no additional instructions for downloading anything and running anything from a different folder.
The pip installer installs the library not the examples, just read the documentation 
but pull request are welcome...however think about where examples get installed with pip, probably not where you want them.
I've been using a previous version of your library for years now and I
never had to do all this to get the examples to work that is all I was
getting at. And I am reading your documentation but the fact that I have to
do the examples in the pi modbus Dev folder to get the examples to work
seems very counterintuitive when I'm trying to rewrite my program now to
meet this new library because I'm not going to be running my program in
your Dev folder.

On Tue, Jun 6, 2023, 12:08 jan iversen ***@***.***> wrote:

> but pull request are welcome...however think about where examples get
> installed with pip, probably not where you want them.
>
> —
> Reply to this email directly, view it on GitHub
> <https://github.com/pymodbus-dev/pymodbus/issues/1585#issuecomment-1579306697>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/ALQY2DPTZCIXAMLMFBANSK3XJ554JANCNFSM6AAAAAAY3M5V6I>
> .
> You are receiving this because you authored the thread.Message ID:
> ***@***.***>
>

Well it seems you have been using version 2.5 of the program, but that version also did not install the examples.

The difference is that in version 2.5.3 the examples was self contained and could just be copied. But as version 3.x is more complex we decided to go for a more normal examples set.
You will find that the shared part is
- helper.py which checks the command line
- (advanced clients) use client_async.py since that is where the client lib is explained.
- tls clients/servers need access to an example certificate 

so really for rewriting start with
- client_sync.py and remove get_comma line then you have what you need.

Resolving patch:
diff --git a/examples/client_async.py b/examples/client_async.py
--- a/examples/client_async.py
+++ b/examples/client_async.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
-"""Pymodbus Aynchronous Client Example.
+"""Pymodbus aynchronous client example.
 
-An example of a single threaded synchronous client.
+An example of a asynchronous client.
 
 usage: client_async.py [-h] [--comm {tcp,udp,serial,tls}]
                        [--framer {ascii,binary,rtu,socket,tls}]
diff --git a/examples/simple_async_client.py b/examples/simple_async_client.py
new file mode 100755
--- /dev/null
+++ b/examples/simple_async_client.py
@@ -0,0 +1,132 @@
+#!/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
+
+from pymodbus import pymodbus_apply_logging_config
+
+# --------------------------------------------------------------------------- #
+# import the various client implementations
+# --------------------------------------------------------------------------- #
+from pymodbus.client import (
+    AsyncModbusSerialClient,
+    AsyncModbusTcpClient,
+    AsyncModbusTlsClient,
+    AsyncModbusUdpClient,
+)
+from pymodbus.exceptions import ModbusException
+from pymodbus.pdu import ExceptionResponse
+from pymodbus.transaction import (
+    #    ModbusAsciiFramer,
+    #    ModbusBinaryFramer,
+    ModbusRtuFramer,
+    ModbusSocketFramer,
+    ModbusTlsFramer,
+)
+
+
+async def run_async_client():
+    """Run async client."""
+
+    # activate debugging
+    pymodbus_apply_logging_config("DEBUG")
+
+    # change to test other client types
+    select_my_client = "tcp"
+
+    print("get client")
+    if select_my_client == "tcp":
+        client = AsyncModbusTcpClient(
+            "127.0.0.1",  # host
+            port=5020,
+            framer=ModbusSocketFramer,
+            # timeout=10,
+            # retries=3,
+            # retry_on_empty=False,
+            # close_comm_on_error=False,
+            # strict=True,
+            # source_address=("localhost", 0),
+        )
+    elif select_my_client == "udp":
+        client = AsyncModbusUdpClient(
+            "127.0.0.1",  # host
+            port=5020,
+            framer=ModbusSocketFramer,
+            # timeout=10,
+            # retries=3,
+            # retry_on_empty=False,
+            # close_comm_on_error=False,
+            # strict=True,
+            # source_address=None,
+        )
+    elif select_my_client == "serial":
+        client = AsyncModbusSerialClient(
+            "/dev/tty01",  # tty port
+            framer=ModbusRtuFramer,
+            # timeout=10,
+            # retries=3,
+            # retry_on_empty=False,
+            # close_comm_on_error=False,
+            # strict=True,
+            baudrate=9600,
+            # bytesize=8,
+            # parity="N",
+            # stopbits=1,
+            # handle_local_echo=False,
+        )
+    elif select_my_client == "tls":
+        client = AsyncModbusTlsClient(
+            "127.0.0.1",  # host
+            port=5020,
+            framer=ModbusTlsFramer,
+            # timeout=10,
+            # retries=3,
+            # retry_on_empty=False,
+            # close_comm_on_error=False,
+            # strict=True,
+            # sslctx=sslctx,
+            certfile="my_cert.crt",
+            keyfile="my_cert.key",
+            # password="none",
+            server_hostname="localhost",
+        )
+    else:
+        print(f"Unknown client {select_my_client} 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_client(), debug=True)
diff --git a/examples/simple_sync_client.py b/examples/simple_sync_client.py
new file mode 100755
--- /dev/null
+++ b/examples/simple_sync_client.py
@@ -0,0 +1,127 @@
+#!/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
+# --------------------------------------------------------------------------- #
+from pymodbus import pymodbus_apply_logging_config
+from pymodbus.client import (
+    ModbusSerialClient,
+    ModbusTcpClient,
+    ModbusTlsClient,
+    ModbusUdpClient,
+)
+from pymodbus.exceptions import ModbusException
+from pymodbus.pdu import ExceptionResponse
+from pymodbus.transaction import (
+    #    ModbusAsciiFramer,
+    #    ModbusBinaryFramer,
+    ModbusRtuFramer,
+    ModbusSocketFramer,
+    ModbusTlsFramer,
+)
+
+
+def run_sync_client():
+    """Run sync client."""
+
+    # activate debugging
+    pymodbus_apply_logging_config("DEBUG")
+
+    # change to test other client types
+    select_my_client = "tcp"
+
+    print("get client")
+    if select_my_client == "tcp":
+        client = ModbusTcpClient(
+            "127.0.0.1",  # host
+            port=5020,
+            framer=ModbusSocketFramer,
+            # timeout=10,
+            # retries=3,
+            # retry_on_empty=False,y
+            # close_comm_on_error=False,
+            # strict=True,
+            # source_address=("localhost", 0),
+        )
+    elif select_my_client == "tcp":
+        client = ModbusUdpClient(
+            "127.0.0.1",  # host
+            port=5020,
+            framer=ModbusSocketFramer,
+            # timeout=10,
+            # retries=3,
+            # retry_on_empty=False,
+            # close_comm_on_error=False,
+            # strict=True,
+            # source_address=None,
+        )
+    elif select_my_client == "serial":
+        client = ModbusSerialClient(
+            "/dev/tty01",  # tty port
+            framer=ModbusRtuFramer,
+            # timeout=10,
+            # retries=3,
+            # retry_on_empty=False,
+            # close_comm_on_error=False,.
+            # strict=True,
+            baudrate=9600,
+            # bytesize=8,
+            # parity="N",
+            # stopbits=1,
+            # handle_local_echo=False,
+        )
+    elif select_my_client == "tls":
+        client = ModbusTlsClient(
+            "127.0.0.1",  # host
+            port=5020,
+            framer=ModbusTlsFramer,
+            # timeout=10,
+            # retries=3,
+            # retry_on_empty=False,
+            # close_comm_on_error=False,
+            # strict=True,
+            # sslctx=None,
+            certfile="my_cert.crt",
+            keyfile="my_cert.key",
+            # password=None,
+            server_hostname="localhost",
+        )
+    else:
+        print(f"Unknown client {select_my_client} 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_client()


Test patch: