Repository: pymodbus-dev/pymodbus

Issue:
Pymodbus 3.4.0, bug in async_execute
Python: 3.8
Pymodbus: 3.4.0
used on: UDP Client (for our example connection to nowhere, or not existed address)

Bug:
https://github.com/pymodbus-dev/pymodbus/blob/dev/pymodbus/client/base.py#L193
Future is created only ONCE

code tries to use retries, first time it is ok, when more times then `wait_for` using CANCELLED future!

FIX:
move `req = self._build_response(request.transaction_id)` to wait_for

```py3
async def async_execute(self, request=None):
        """Execute requests asynchronously."""
        request.transaction_id = self.transaction.getNextTID()
        packet = self.framer.buildPacket(request)
        self.transport_send(packet)        
        if self.params.broadcast_enable and not request.slave_id:
            resp = b"Broadcast write sent - no response expected"
        else:
            count = 0
            while count < self.params.retries:
                count += 1
                try:
                    req = self._build_response(request.transaction_id)
                    resp = await asyncio.wait_for(
                        req, timeout=self.comm_params.timeout_connect
                    )
                    break
                except asyncio.exceptions.TimeoutError:
                    pass
            if count == self.params.retries:
                self.close(reconnect=True)
                raise ModbusIOException(
                    f"ERROR: No response received after {self.params.retries} retries"
                )
        return resp
```


Discussion:
Pull requests are welcome.
v3.4.1 will be released this weekend, so that is the deadline for a PR, that is if you want it in the next release cycle.
> v3.4.1 will be released this weekend, so that is the deadline for a PR, that is if you want it in the next release cycle.

I'm on vacation. i shall do it, but after vacation.
Have a nice vacation.
> Have a nice vacation.

thanks

Resolving patch:
diff --git a/pymodbus/client/base.py b/pymodbus/client/base.py
--- a/pymodbus/client/base.py
+++ b/pymodbus/client/base.py
@@ -190,22 +190,19 @@ async def async_execute(self, request=None):
         request.transaction_id = self.transaction.getNextTID()
         packet = self.framer.buildPacket(request)
         self.transport_send(packet)
-        req = self._build_response(request.transaction_id)
         if self.params.broadcast_enable and not request.slave_id:
             resp = b"Broadcast write sent - no response expected"
         else:
             count = 0
             while count <= self.params.retries:
-                count += 1
                 try:
                     req = self._build_response(request.transaction_id)
                     resp = await asyncio.wait_for(
                         req, timeout=self.comm_params.timeout_connect
                     )
-                    count = 0
                     break
                 except asyncio.exceptions.TimeoutError:
-                    pass
+                    count += 1
             if count > self.params.retries:
                 self.close(reconnect=True)
                 raise ModbusIOException(


Test patch: