Update use pyserial RS485
Fixes: https://github.com/pymodbus-dev/pymodbus/issues/2204
Can't get this passing - it seems that serial_for_url is used by this library, but there's no way to use that to produce instances of pyserial's RS485 class. Perhaps the solution is to implement some kind of custom URL scheme for this purpose?
Open to suggestions - I can't seem to fix it!
I have no suggestions, the serial library is only used in serial transport and there are no other libraries being used.
serial_for_url is essential for pymodbus since it allows simulating serial communication on a socket, but it's strange if the rs485 do not supply it.
OK, I think this is actually a bit of an awkward solution, but ultimately the correct thing to do.
The purpose of using the RS485 class is to be able to configure RS485Settings, and without injecting those, I'll have to reach inside pymodbus and grab things I shouldn't to set rs485_mode on the sync_serial client. So I opted to allow these settings to be injected along with us in the commparams - there is precedent for params in there to be unused for some transports (e.g. the port parameter is not used if you have a serial commtype)
I hope this is an acceptable fix
It is easiest to run locally "pytest --cov"
We have for other reasons decided to make a v3.6.9 that will be done this weekend, so I need an updated PR from you if you want it included.
Still working on this ?
I have a personal project where I write a new software for already existing hardware with RS485 transceiver, but it is based on an AllWinner H3 SBC, where hardware flow control doesn't work very well, but I need to control RTS pin to control the transceiver's direction. So I really would like to have this feature merged, but (with all due respect to @samskiter) I don't think this is implemented properly.
SerialTransport adapts a non-asyncio serial.Serial class by adding async readers and writers to monitor serial port's file descriptor and they invoke callbacks to either read or write the data in a non-blocking fashion using normally blocking read and write methods. But RS485.write method adds additional, blocking delays (for example, it always flushes the port after each write), which should not be executed in the async writer's callbacks, because it's going to block the loop.
Also there's no guarantee that the async writer is going to call the callback only once per SerialTransport.write call as it's possible that the writer would split larger data into smaller chunks. In that case there would be multiple calls to RS485.write method for a single SerialTransport.write call, causing RTS to be toggled (potentially multiple times) in the middle of a single modbus operation, causing it to fail.
That's why the optional software RTS control should be implemented directly in the SerialTransport class, which is actually aware when the whole frame has been sent and RTS can be switched from TX to RX. It would be even better if it could just call program provided callbacks (either sync or async) before transmission starts and after it ends. That way a program could even use any available generic GPIO pin to control the transceiver direction, not just RTS pin.
In general I agree with your arguments, we have over time had many problems with serial, a lot because it is no longer actively maintained.
We have been thinking of changing serial to another library, but never got time to actually do it.
I would however like to see a good RS485 integration! and e.g. enhac3 the transport layer to control RTS would also be welcomed.
So in short, and since this PR looks abandoned, I hope you will submit your ideas as a PR.
I think RTS control can be implemented in the current serial transport, with an extra parameter to turn it on.
The best way would be to make a PR that implement it in serial transport with test, and a second that add the parameter to comm_params and the client/server api.
Sorry for my delays, I will try and get this pr over the line!
On Thu, 25 Jul 2024, 16:43 jan iversen, @.***> wrote:
I think RTS control can be implemented in the current serial transport, with an extra parameter to turn it on.
The best way would be to make a PR that implement it in serial transport with test, and a second that add the parameter to comm_params and the client/server api.
— Reply to this email directly, view it on GitHub https://github.com/pymodbus-dev/pymodbus/pull/2205#issuecomment-2250734486, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJWOWZUT4AGRFLDJ7K6FO3ZOEML3AVCNFSM6AAAAABILVM376VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENJQG4ZTINBYGY . You are receiving this because you were mentioned.Message ID: @.***>
@samskiter good luck, please resolve the conflicts first and then have a close look at the comments from @yawor which I think have a lot of merit.
Ohh and do not forget the review comments I made.
This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.
This PR was closed because it has been stalled for 10 days with no activity.
But
RS485.writemethod adds additional, blocking delays (for example, it always flushes the port after each write), which should not be executed in the async writer's callbacks, because it's going to block the loop.
So it appears pyserial also has some native rs485 support that AFAIU would avoid these issues, reworked this a bit to use that instead in #2460.