AdvancedClimateSystems / uModbus

Python implementation of the Modbus protocol.
Mozilla Public License 2.0
211 stars 81 forks source link

Add async version of send_message for both tcp and rtu #110

Open tiagocoutinho opened 3 years ago

tiagocoutinho commented 3 years ago

Now that #86 is out I feel more comfortable making this PR since the new async/await python 3 syntax makes it impossible to use with python 2.

This PR proposes to add an async version of send_message for both tcp and rtu. We will be able to write asyncio based clients like this:

import asyncio

from umodbus import conf
from umodbus.client import tcp

async def main():
    reader, writer = await asyncio.open_connection('localhost', 502)
    message = tcp.write_multiple_coils(slave_id=1, starting_address=1, values=[1, 0, 1, 1])
    response = await tcp.async_send_message(message, reader, writer)
    writer.close()
    await writer.wait_closed()

asyncio.run(main())

We are not restricted to TCP. Any I/O library supporting asyncio StreamReader and StreamWriter interface (example: serial_asyncio) can be used with either the TCP or RTU versions of async_send_message.

OrangeTux commented 3 years ago

Thanks for this PR! I might need a bit of time to review the PR and test it myself. I'll come back to you.

tiagocoutinho commented 3 years ago

You're welcome. No worries, take your time.

tiagocoutinho commented 3 years ago

Hi @jaapz, Thanks for your review.

I am in favour of moving the async_send_message() to it's own module and renaming the function to send_message(). As you probably noticed, I there is no import asyncio in the PR. This is intentional and allows umodbus to state that is is async library agnostic. The idea was that it would be simple to use umodbus in an asyncio application and, by writing a simple adapter, possible to use in a curio, trio or anyio application.

So, long story short, what do you thing about naming the module umodbus.client.tcp.asynch instead?

jaapz commented 3 years ago

@tiagocoutinho that makes complete sense, calling it umodbus.client.tcp.async instead is fine by me. Maybe you could also add a bit of documentation to the readme stating that we are in fact async library agnostic?

tiagocoutinho commented 3 years ago

Maybe you could also add a bit of documentation to the readme stating that we are in fact async library agnostic?

You read my mind :-)

tiagocoutinho commented 3 years ago

I think it should be ready for review now. I re-based from master in order to update the examples with the argument parser. I took the liberty of adding also a reference to gevent in the README and I added a curio tcp client example.

jaapz commented 3 years ago

I've done another small review, everything else looks good to me. Maybe @OrangeTux can take over from here to test it a bit and get this merged and released?

tiagocoutinho commented 3 years ago

Hi @OrangeTux , @jaapz, Just pinging... Does everything look ok with the PR? I don't see any pending changes. Please let me know if you are waiting on me. Thanks

jaapz commented 3 years ago

Hey @tiagocoutinho, I just need some time to properly test this before merging. Sorry for the wait, I'm pretty busy at the moment