-
Notifications
You must be signed in to change notification settings - Fork 3
Add a simple async API #79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
b0902ab
Migrate shared connect kwargs to a typed `ConnectKwargs`
puddly 56c7541
WIP: Implement `AsyncSerial` wrapper
puddly bb977a4
Migrate all tests!
puddly a49c849
Forego `StreamReader` + `StreamWriter` compat for a better API
puddly 44985dc
Update docs
puddly d6af46e
Clean up
puddly 86c1b2d
Clean up 2
puddly 0214792
More tests
puddly 9e2c313
Test `byte_size` as well
puddly File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| # Async serial | ||
| Python's asyncio module introduces many similar async primitives. serialx provides APIs | ||
| for both high-level and low-level async code. | ||
|
|
||
| ## Async-with | ||
| `async with` is the simplest pattern and is suited for scripts and self-contained code: | ||
|
|
||
| ```python | ||
| import serialx | ||
|
|
||
| async with serialx.async_serial_for_url( | ||
| "/dev/serial/by-id/port", baudrate=115200, | ||
| ) as serial: | ||
| serial.write(b"ping") | ||
| data = await serial.readexactly(4) | ||
| ``` | ||
|
|
||
| Unlike the sync API, you have all of the asyncio primitives at your disposal, including | ||
| granular task cancellation, timeouts, and concurrency: | ||
|
|
||
| ```python | ||
| import asyncio | ||
|
|
||
| async with serialx.async_serial_for_url( | ||
| "/dev/serial/by-id/port", baudrate=115200, | ||
| ) as serial: | ||
| async with asyncio.TaskGroup() as tg: | ||
| async def ping() -> None: | ||
| while True: | ||
| serial.write(b"ping") | ||
| await serial.flush() | ||
| await asyncio.sleep(1) | ||
|
|
||
| tg.create_task(ping()) | ||
|
|
||
| async with asyncio.timeout(30): | ||
| data = await serial.readexactly(4) | ||
|
puddly marked this conversation as resolved.
puddly marked this conversation as resolved.
|
||
| ``` | ||
|
|
||
| ### Manual open and close | ||
| The instance returned by `async_serial_for_url` is unopened. Open and close | ||
| explicitly when you need to keep the connection alive across function boundaries: | ||
|
|
||
| ```python | ||
| serial = serialx.async_serial_for_url( | ||
| "/dev/serial/by-id/port", baudrate=115200, | ||
| ) | ||
|
|
||
| await serial.open() | ||
|
|
||
| try: | ||
| ... | ||
| finally: | ||
| await serial.close() | ||
| ``` | ||
|
|
||
| ### Reading and writing | ||
| Reads are coroutines, writes are synchronous (data is buffered and drained on | ||
| demand): | ||
|
|
||
| ```python | ||
| data = await serial.read(64) # up to 64 bytes | ||
| chunk = await serial.readexactly(32) # exactly 32 bytes | ||
| line = await serial.readline() # through the next \n | ||
| header = await serial.readuntil(b"\r\n") # through a custom delimiter | ||
|
|
||
| serial.write(b"hello ") | ||
| serial.write(b"world\n") | ||
| await serial.flush() # wait until the data has been written | ||
| ``` | ||
|
|
||
| ### Modem pins | ||
| Modem control pins are async, since some transports (ESPHome, RFC2217) round-trip | ||
| to the device: | ||
|
|
||
| ```python | ||
| await serial.set_modem_pins(rts=True, dtr=True) | ||
| pins = await serial.get_modem_pins() | ||
| assert pins.rts is serialx.PinState.HIGH | ||
| ``` | ||
|
|
||
| ## Async protocols and transports | ||
| While the high-level async API is useful for simple code, libraries and other | ||
| high-performance uses should use asyncio transports and protocols. These have the | ||
| benefit of allowing an `asyncio.Protocol` to immediately enqueue data in the same event | ||
| loop cycle as it is received. | ||
|
|
||
| ```python | ||
| import asyncio | ||
| import serialx | ||
|
|
||
| loop = asyncio.get_running_loop() | ||
| transport, protocol = await serialx.create_serial_connection( | ||
| loop=loop, | ||
| protocol_factory=your_protocol_factory, | ||
| url="/dev/serial/by-id/port", | ||
| baudrate=115200, | ||
| ) | ||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.