`TypeError: buildPacket() missing 1 required positional argument: 'message'` when using `ModbusRtuFramer` with async client
Versions
- Python: 3.9.7
- OS: macOS Monterey 12.1
- Pymodbus: 2.5.3 (dev)
- Modbus Hardware (if used): None
Pymodbus Specific
- Server: tcp/async
- Client: tcp/async
Description
(Possibly related to #153)
Tried to use ModbusRtuFramer with the ModbusAsyncTCPClient and received this error:
DEBUG:root:Running Async client
DEBUG:root:------------------------------------------------------
DEBUG:root:---------------------RUN_WITH_NO_LOOP-----------------
DEBUG:asyncio:Using selector: KqueueSelector
DEBUG:pymodbus.client.asynchronous.async_io:Connecting to 127.0.0.1:5020.
DEBUG:pymodbus.client.asynchronous.async_io:Connecting.
DEBUG:pymodbus.client.asynchronous.async_io:Client connected to modbus server
INFO:pymodbus.client.asynchronous.async_io:Protocol made connection.
INFO:pymodbus.client.asynchronous.async_io:Connected to 127.0.0.1:5020.
DEBUG:root:Reading Coils
Traceback (most recent call last):
File "/Users/malte/pymodbus/examples/common/async_asyncio_client.py", line 208, in <module>
run_with_no_loop()
File "/Users/malte/pymodbus/examples/common/async_asyncio_client.py", line 198, in run_with_no_loop
loop.run_until_complete(start_async_test(client.protocol))
File "/Users/malte/.pyenv/versions/3.9.7/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
return future.result()
File "/Users/malte/pymodbus/examples/common/async_asyncio_client.py", line 59, in start_async_test
rr = await client.read_coils(1, 1, unit=0x01)
File "/Users/malte/.pyenv/versions/3.9.7/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pymodbus/client/asynchronous/async_io/__init__.py", line 34, in execute
req = self._execute(request)
File "/Users/malte/.pyenv/versions/3.9.7/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pymodbus/client/asynchronous/async_io/__init__.py", line 141, in _execute
packet = self.framer.buildPacket(request)
TypeError: buildPacket() missing 1 required positional argument: 'message'
Code and Logs
I used the examples from examples/common and only added the framer=ModbusRtuFramer argument to the server and client. This works fine for the synchronous client.
Superficial debugging shows that the framer factory never seems to be called, so that when framer.buildPacket is called, it expects two arguments, self and message. At this point, framer should have been replaced with the product of the factory, I guess?
Submitted the above fix for this issue since I ran into the same problem today. Seems to work with everything I've tried so far.
@maltekliemann After looking at the test failures on my PR it seems that there's a simple workaround:
framer=ModbusRtuFramer(ClientDecoder())
Based on the failures in the tests, in the asynchronous client it seems to be expecting the framer parameter to be an instance rather than a class like in the synchronous one. Not sure whether to leave the PR open and adjust the tests to improve consistency, or what. :)
@diagonalfish sorry for the delayed response, yes you should be initializing the framer. the test might need an update.
@diagonalfish sorry for the delayed response, yes you should be initializing the framer. the test might need an update.
No problem. In this case the test does seem to be initializing the framer, which is why it broke when my PR modified how the framer argument is used. The main thing is that this is different from the API for the synchronous client which seems to expect you to pass the class rather than an instance (https://pymodbus.readthedocs.io/en/latest/source/example/changing_framers.html).
Either is fine as far as I am concerned, it just seems like it would be good if it was consistent between sync and async.
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.
No longer able to reproduce on. 3.0.2