Repository: pymodbus-dev/pymodbus

Issue:
ModbusRtuFramer object is not callable
<!--
Please use the Pymodbus gitter channel at https://gitter.im/pymodbus_dev/Lobby or Stack Overflow(tag [pymodbus](https://stackoverflow.com/questions/tagged/pymodbus) for
support questions.

Before opening a new issue, make sure you do the following:
    * check that your issue isn't already filed: https://github.com/riptideio/pymodbus/issues
    * check the discussions forum https://github.com/riptideio/pymodbus/discussions
    * prepare a short, runnable example that reproduce the issue with the latest development version of Pymodbus
-->

### Versions

* Python: 3.10
* OS: Ubuntu 22.04
* Pymodbus: 3.0.0.dev5 9bc2fb0 (latest dev branch commit)
* Modbus Hardware (if used): 

### Pymodbus Specific
* Server: rtu async
* Client: rtu async

### Description

I'm trying to run serial rtu async client with the code below, however I'm running into some issues.
Directly after calling the .connnect() function, I receive that ModbusRtuFramer' is not callable.
The other error "int has not len()" is received after calling read_holding_registers.

What am I missing?

Thank you.


### Code and Logs
```
13:10:52 WARNING serial:111 Failed to connect: 'ModbusRtuFramer' object is not callable
```

```
File "/home/-/projects/-/src/main_meter_3.py", line 17, in <module>
    asyncio.run(run(client), debug=True)
  File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.10/asyncio/base_events.py", line 646, in run_until_complete
    return future.result()
  File "/home/-/projects/-/src/main_meter_3.py", line 12, in run
    await run_async_client(client)
  File "/home/-/projects/-/src/main_meter_3.py", line 6, in run_async_client
    rr = await client.read_holding_registers(1, 1, unit=1) # this has been changed
  File "/home/-/.cache/pypoetry/virtualenvs/--XI0Oy1ie-py3.10/lib/python3.10/site-packages/pymodbus/client/mixin.py", line 118, in read_holding_registers
    return self.execute(request)
  File "/home/-/.cache/pypoetry/virtualenvs/--XI0Oy1ie-py3.10/lib/python3.10/site-packages/pymodbus/client/base.py", line 179, in execute
    return self.transaction.execute(request)
  File "/home/-/.cache/pypoetry/virtualenvs/--XI0Oy1ie-py3.10/lib/python3.10/site-packages/pymodbus/transaction.py", line 168, in execute
    response, last_exception = self._transact(
  File "/home/-/.cache/pypoetry/virtualenvs/--XI0Oy1ie-py3.10/lib/python3.10/site-packages/pymodbus/transaction.py", line 323, in _transact
    result = self._recv(response_length, full)
  File "/home/-/.cache/pypoetry/virtualenvs/--XI0Oy1ie-py3.10/lib/python3.10/site-packages/pymodbus/transaction.py", line 363, in _recv
    if len(read_min) != min_size:
TypeError: object of type 'int' has no len()
```

```python
from pymodbus.client import AsyncModbusSerialClient
import asyncio


async def run_async_client(client):
    rr = await client.read_holding_registers(1, 1, unit=1)
    assert rr.registers[0] == 10  # test the expected value


async def run(client):
    await client.connect()
    await run_async_client(client)


if __name__ == "__main__":
    client = AsyncModbusSerialClient(port="/dev/ttyUSB0", baudrate=115200)
    asyncio.run(run(client), debug=True)
```

ModbusRtuFramer object is not callable
<!--
Please use the Pymodbus gitter channel at https://gitter.im/pymodbus_dev/Lobby or Stack Overflow(tag [pymodbus](https://stackoverflow.com/questions/tagged/pymodbus) for
support questions.

Before opening a new issue, make sure you do the following:
    * check that your issue isn't already filed: https://github.com/riptideio/pymodbus/issues
    * check the discussions forum https://github.com/riptideio/pymodbus/discussions
    * prepare a short, runnable example that reproduce the issue with the latest development version of Pymodbus
-->

### Versions

* Python: 3.10
* OS: Ubuntu 22.04
* Pymodbus: 3.0.0.dev5 9bc2fb0 (latest dev branch commit)
* Modbus Hardware (if used): 

### Pymodbus Specific
* Server: rtu async
* Client: rtu async

### Description

I'm trying to run serial rtu async client with the code below, however I'm running into some issues.
Directly after calling the .connnect() function, I receive that ModbusRtuFramer' is not callable.
The other error "int has not len()" is received after calling read_holding_registers.

What am I missing?

Thank you.


### Code and Logs
```
13:10:52 WARNING serial:111 Failed to connect: 'ModbusRtuFramer' object is not callable
```

```
File "/home/-/projects/-/src/main_meter_3.py", line 17, in <module>
    asyncio.run(run(client), debug=True)
  File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.10/asyncio/base_events.py", line 646, in run_until_complete
    return future.result()
  File "/home/-/projects/-/src/main_meter_3.py", line 12, in run
    await run_async_client(client)
  File "/home/-/projects/-/src/main_meter_3.py", line 6, in run_async_client
    rr = await client.read_holding_registers(1, 1, unit=1) # this has been changed
  File "/home/-/.cache/pypoetry/virtualenvs/--XI0Oy1ie-py3.10/lib/python3.10/site-packages/pymodbus/client/mixin.py", line 118, in read_holding_registers
    return self.execute(request)
  File "/home/-/.cache/pypoetry/virtualenvs/--XI0Oy1ie-py3.10/lib/python3.10/site-packages/pymodbus/client/base.py", line 179, in execute
    return self.transaction.execute(request)
  File "/home/-/.cache/pypoetry/virtualenvs/--XI0Oy1ie-py3.10/lib/python3.10/site-packages/pymodbus/transaction.py", line 168, in execute
    response, last_exception = self._transact(
  File "/home/-/.cache/pypoetry/virtualenvs/--XI0Oy1ie-py3.10/lib/python3.10/site-packages/pymodbus/transaction.py", line 323, in _transact
    result = self._recv(response_length, full)
  File "/home/-/.cache/pypoetry/virtualenvs/--XI0Oy1ie-py3.10/lib/python3.10/site-packages/pymodbus/transaction.py", line 363, in _recv
    if len(read_min) != min_size:
TypeError: object of type 'int' has no len()
```

```python
from pymodbus.client import AsyncModbusSerialClient
import asyncio


async def run_async_client(client):
    rr = await client.read_holding_registers(1, 1, unit=1)
    assert rr.registers[0] == 10  # test the expected value


async def run(client):
    await client.connect()
    await run_async_client(client)


if __name__ == "__main__":
    client = AsyncModbusSerialClient(port="/dev/ttyUSB0", baudrate=115200)
    asyncio.run(run(client), debug=True)
```



Discussion:
Sounds like 2 real problem, let me have a look.
First error has been solved, however second seems to be a separate error and remains the same.

Weirdly, recvPacket() calls the ModbusBaseClient recv(), which returns an int, instead of the derived Serial.
The second issue is not as easy to solve, I have just compared to older versions, and do not understand with recvPacket is called at all. I will need to make some test cases before I can solve this, so it might take some time.
The `recv` method is not overrided for `AsyncModbusSerialClient` , it should be similar to sync client `recv` refer https://github.com/riptideio/pymodbus/blob/dev/pymodbus/client/serial.py#L293

@dhoomakethu that does not sound right, when I go back to v2.5.3 AsyncModbusSerialClient does not have a receive nor can I find it in other commits.

In async normally data_received is called and that starts calling the framer and transaction. For some reason here recvPacket() in transaction is called, as if it is the other way round. I am pretty sure the problem is something different, but look forward to hear why you think recv() is missing.
Sounds like 2 real problem, let me have a look.
First error has been solved, however second seems to be a separate error and remains the same.

Weirdly, recvPacket() calls the ModbusBaseClient recv(), which returns an int, instead of the derived Serial.
The second issue is not as easy to solve, I have just compared to older versions, and do not understand with recvPacket is called at all. I will need to make some test cases before I can solve this, so it might take some time.
The `recv` method is not overrided for `AsyncModbusSerialClient` , it should be similar to sync client `recv` refer https://github.com/riptideio/pymodbus/blob/dev/pymodbus/client/serial.py#L293

@dhoomakethu that does not sound right, when I go back to v2.5.3 AsyncModbusSerialClient does not have a receive nor can I find it in other commits.

In async normally data_received is called and that starts calling the framer and transaction. For some reason here recvPacket() in transaction is called, as if it is the other way round. I am pretty sure the problem is something different, but look forward to hear why you think recv() is missing.

Resolving patch:
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@ def get_commandline():
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@ def get_commandline():
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()


Test patch: