<!-- Source: https://medius.k4tech.net/library/features/async -->
# Async

_AsyncDevice on any executor_

`AsyncDevice` is [`Device`](/library/connection.md) with its queries as futures, behind the off-by-default `async` flag.

```bash
cargo add medius --features async
```

Reply waits use [`flume`](https://crates.io/crates/flume), so futures run under any executor, no [`tokio`](https://tokio.rs).

```bash
cargo add futures
```

`Result` is the fallible return type (see [Errors](/library/types/errors.md)).

See also: [call kinds & timeouts](/library/guides/calls.md#call-kinds), [concurrency](/library/guides/connection.md#threading), [testing](/library/guides/testing.md#testing).

## Constructing an AsyncDevice

_open, find, into_async, into_inner_

```text
fn open(path: impl AsRef<Path>) -> Result<AsyncDevice>
```

_Blocks_

```text
fn find() -> Result<AsyncDevice>
```

_Blocks_

```text
fn into_async(self) -> AsyncDevice
```

_No round-trip_

```text
fn into_inner(self) -> Device
```

_No round-trip_

#### CONSTRUCTORS

| Constructor | Description |
| --- | --- |
| `open` | Takes a serial-port path, opens it, and runs the handshake. It blocks like [`Device::open`](/library/connection.md#open), then hands back an `AsyncDevice`. |
| `find` | Discovers the first medius box by USB id, opens it, and runs the handshake. Blocks like [`Device::find`](/library/connection.md#open), then hands back an `AsyncDevice`. |
| `into_async` | Reinterprets an already-open [`Device`](/library/connection.md) as an `AsyncDevice`. It's zero-cost over the same `Link` core, no new connection. |
| `into_inner` | Hands the sync `Device` back. |

#### EXAMPLE

```rust
// discover and open in one call (runs the handshake, blocks)
let device = AsyncDevice::find()?;

// or by path:
let device = AsyncDevice::open("/dev/ttyACM0")?;

// or reinterpret an already-open Device:
let device = Device::find()?.into_async();
```

> **Note**
>
> Everything else on [`Device`](/library/connection.md) is mirrored on `AsyncDevice` and stays synchronous, including [`counters`](/library/diagnostics.md#counters), [`logs`](/library/diagnostics.md#logs), [`reapply`](/library/lifecycle.md#reapply), and [`reconnect`](/library/lifecycle.md#reconnect). Only the queries are futures.

## Awaiting a query

_every query method is a future_

```text
async fn query_version(&self) -> Result<Version>
```

_Blocks_

```text
async fn query_health(&self) -> Result<Health>
```

_Blocks_

Each future awaits the correlated [`RESP`](/native/commands/requests.md#resp) with the default timeout, then resolves to its struct.

#### RETURNS

| Method | Resolves to | Description |
| --- | --- | --- |
| `query_version().await` | [`Version`](/library/types/structs.md#version) | Firmware identity. |
| `query_health().await` | [`Health`](/library/types/structs.md#health) | Whether the box is wired and ready. |

Two shown; the rest (`device_info`, `caps`, `query_rate`, `query_stats`, `query_locks`, `query_catch`) resolve the same way. The full list is on [`Requests`](/library/requests.md#async).

`.await` is only legal inside an `async` function or block.

#### EXAMPLE

```rust
async fn run(device: &AsyncDevice) -> medius::Result<()> {
    let v = device.query_version().await?;
    let h = device.query_health().await?;
    println!("{v}, link_up={}", h.link_up);
    Ok(())
}
```
