Closed aryker closed 1 year ago
First of all you use a serial line, so alone for that reason you cannot run multiple requests in parallel, I am not sure how you expect that to work ?
Pymodbus in general do not support parallel requests, because the modbus protocol is a request/response protocol, and even though tcp in principle allows multiple requests, most devices do not accept it.
If you execute the requests sequentially there are no need for delay between the requests.
I'm not sure I understand your point. My understanding of Python's asynchronous event loop is that it is not truly parallel. If asynchronous calls like this are not possible with a serial device then why does an asynchronous version of the serial client exist? What am I missing conceptually here?
You must ensure that your pymodbus calls are serialised. You cannot have 2 calls open at any time.
Async means you can do a lot of other things while the call is executing, except calling a pymodbus function.
Alright, that is helpful, thank you.
If I am using the asynchronous pymodbus clients, is there a way to tell before calling a pymodbus function whether another one is currently running and it is thus unsafe to do so? In my actual application I am doing other things between pymodbus calls, but it seems like there are cases where I am not doing "enough" and I would need to wait before making another call.
no, that is responsibility of the app. You could isolate the pymodbus call in a method in your app and secure it with a lock.
Hi, I also noticed that in Pymodbus version 3.5.2 (pyserial version 3.5) pymodbus does not read the packets that are correctly received from the server, even though the poll message was sent only once and that too using sync-client. Pymodbus always throw ModbusIOException. Hence I thought of updating here rather than opening a new thread. I am testing in Ubuntu 22.04 with python 3.10 in venv using /dev/ttyUSB0.
While debugging I also noticed that the slave responded immediately but pymodbus is waiting for 6 sec to wait for the packets whereas the packets are already received. I am mentioning 6 sec based on the debug messages which are placed below. ---Reading Holding Registers - 03--- 2023-10-01 21:55:49,848 MainThread INFO LGMeter_Interface:62 ### Creating a modbus client with LG6435_Meter PLC ### 2023-10-01 21:55:49,850 MainThread INFO LGMeter_Interface:195 ### Opening the connection with LG6435_Meter PLC### 2023-10-01 21:55:49,851 MainThread DEBUG logging :102 Current transaction state - IDLE 2023-10-01 21:55:49,851 MainThread DEBUG logging :102 Running transaction 1 2023-10-01 21:55:49,851 MainThread DEBUG logging :102 SEND: 0xed 0x3 0x0 0x8e 0x0 0x2 0xb2 0x8c 2023-10-01 21:55:49,852 MainThread DEBUG logging :102 New Transaction state "SENDING" 2023-10-01 21:55:49,852 MainThread DEBUG logging :102 Changing transaction state from "SENDING" to "WAITING FOR REPLY" 2023-10-01 21:55:55,868 MainThread DEBUG logging :102 No response received, Expected 9 bytes Received 0 bytes !!!! 2023-10-01 21:55:55,868 MainThread DEBUG logging :102 Changing transaction state from "WAITING FOR REPLY" to "PROCESSING REPLY" 2023-10-01 21:55:55,869 MainThread DEBUG logging :102 RECV: 2023-10-01 21:55:55,869 MainThread DEBUG logging :102 Processing: 2023-10-01 21:55:55,869 MainThread DEBUG logging :102 Getting transaction 237 2023-10-01 21:55:55,869 MainThread DEBUG logging :102 Changing transaction state from "PROCESSING REPLY" to "TRANSACTION_COMPLETE" 2023-10-01 21:55:55,869 MainThread INFO LGMeter_Interface:205 ### Client is closed### Traceback (most recent call last): AttributeError: 'ModbusIOException' object has no attribute 'registers'
At 2023-10-01 21:55:49,852, the state is SENDING and the packets were sent and response also immediately received. At 2023-10-01 21:55:55,868, waiting for the bytes. The issue is same when client.strict is set to FALSE as well & retry_on_empty is set to TRUE as well.
Your problem is here:
2023-10-01 21:55:55,868 MainThread DEBUG logging :102 No response received, Expected 9 bytes Received 0 bytes !!!!
your device do not respond so pymodbus makes a retry.
But I have printed out the response from the slave device using serial monitor. Hence at the beginning of my thread, I have clearified that for every poll, indeed the slave had responded but pymodbus is failing to receive it as it is waiting for the timeout. I have installed modpoll the commandline tool in ubuntu and verified that the slave device indeed responded.
Modpoll might have another timeout than what you defined for pymodbus, fact is that pymodbus do not get a response and thus reconnects.
The problem can be in your usb device, many times using a larger timeout solved the problem,
Hi, I am trying to confirmly saying here that the slave device indeed responded right after the polling message is sent and no need for pymodbus client to wait for the timeout. Since the response is less than a sec, why the requirement for greater timeout arise. I have printed using serial monitor to print the response in the termainal. I could notice that right after the response was sent, response was received in the USB device.
While the slave device is sending response, pymodbus is waiting for the delay for 6 sec. Waiting for 6 sec is constant irrespective of the timeout value and number of retries.
Would like to confirm there is response from the slave device for each query sent from pymodbus.
You might see it on the serial monitor, but as you can see from the log message pymodbus do not receive it !
This can be caused by a lot of things outside the control of pymodbus:
Pymodbus is NOT waiting 6 seconds if it receives a response, but 6 seconds sounds a lot like the first retry.
If you want to convince yourself that the throughput is higher than 1 message pr 6 seconds, try our performance example.
And just to be clear timeout > 6 do affect the response time in your case, because pymodbus waits longer to receive a response.
Just had another look at your code, you must guarantee that the calls are sequential (one call terminates before issuing the next). That is due to the nature of the modbus protocol.
Your problem is likely because your app tries to make multiple reads in parallel.
You might see it on the serial monitor, but as you can see from the log message pymodbus do not receive it !
This can be caused by a lot of things outside the control of pymodbus:
- your usb device buffers the data
- the os buffers the data
- your device responds with another slave id (did you check what is on the serial line).
I have only one device connected to it. So in the RS485 network of 38.4K baud, one pymodbus and the slave device. if my USB device buffers the data, how the response is printed in serial monitor. Secondly how come other modbus client in the same m/c (of course pymodbus is OFF when other client is made active), gets the response. Somehow I am not technically convinced.
You cannot have multiple calls in parallel that is not supported neither by pymodbus nor by the modbus protocol.
Pull requests are welcome if you want that to be supported, but bear in mind that on the RS485 you can only have 1 request outstanding (request/response protocol).
Just had another look at your code, you must guarantee that the calls are sequential (one call terminates before issuing the next). That is due to the nature of the modbus protocol.
Your problem is likely because your app tries to make multiple reads in parallel.
This is not the same message as you see in the first thread raised by aryker. So I am not sending multiple message parallel. Since I am facing the similar issue I used this thread instead of creating a new. Pls refer my first comment.
This code '''
def main(): tasks = [] tasks.append(test_connect()) tasks.append(test_read(101)) tasks.append(test_read(102)) # Comment this line and the line below out for working code. tasks.append(test_read(105)) # Comment this line and the line above out for working code. loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.gather(*tasks)) '''
Can make multiple calls in parallel, actually you do not even ensure that connect() terminates before starting to read.
If your code is different then why piggy back on this issue, it is not very helpful for anybody.
Hi Janiversen, If you want, I will create new thread. But the problem statement is PYSERIAL is not recognizing the packets that are received foor the function code 6 (READ_HIOLDING_REG) For me the topic lookes same. and hence I coninued here. Sorry for that...
If you intend to open an new issue and discuss there, I am ready to do the same. Pls suggest.
Well it is quite different, since you do not have multiple calls in parallel.
You need to make a proper issue with log, code etc....I am not even sure if you use async or sync.
BUT the response, based on your log, is still the same, pymodbus do not receive the response! it might be that PYSERIAL have a problem but that is another project!
And please do you really think that pymodbus would be useable if every request took 6 seconds to respond to ? Pymodbus can serve around 40-50 request pr second.
Hi, Sorry for the confusion. If you suggest to move to new thread, I am OK.
I use sync_client.
I am concerned why pymodbus to wait for 6 sec. Please suggest me to where to change this wait time, I can try and give you feedback.
Versions
Pymodbus Specific
Description
I have three slave devices connected to my modbus hub, and I am trying to read a holding register from each one. When I make more than one asynchronous call to read_holding_registers in quick succession, pymodbus reports a ModbusIOException stating that no response was received after 3 retries. This does not happen when I only call the read method once, or if I wait long enough between asynchronous calls. It also does not happen with synchronous calls. My USB-Serial modem has a TX/RX light that flashes green whenever data is traveling to/from the modbus device. Using this, I can confirm that in the erroneous situation, pymodbus is not sending data over the line at all (the light does not come on).
Code and Logs