Async queriesQueries await a reply, everything else fires and forgets

With the async feature, the QUERY methods are async fns that await their RESP (listed on Requests). Every other method is fire-and-forget and stays synchronous.

Futures without a runtimefutures::executor::block_on

block_on runs one future to completion on the current thread, with no async runtime.

EXAMPLE
use futures::executor::block_on;

let device = Device::find()?.into_async();
let v = block_on(device.query_version())?;
println!("{v}");

Inside an async main, .await the same future instead. It runs unchanged under tokio, async-std, or smol.

Query timeoutDefault timeout and QueryTimeout

A query, sync or async, waits DEFAULT_QUERY_TIMEOUT (1 s), then returns Err(Error::QueryTimeout).

EXAMPLE
match device.query_health() {
    Ok(h) => println!("{h:?}"),
    Err(medius::Error::QueryTimeout) => eprintln!("no reply in time"),
    Err(e) => return Err(e),
}

QueryTimeout is a query past its deadline; NoReply is a silent handshake. Both are on Errors.

Smooth motionSubdivide the delta, pace the steps

move_rel applies its delta at once. To spread it over time, send smaller steps ~1 ms apart.

EXAMPLE
use std::thread::sleep;
use std::time::Duration;

// ~400 counts right over 200 steps (~200 ms at 1 kHz).
for _ in 0..200 {
    device.move_rel(2, 0)?;
    sleep(Duration::from_millis(1));
}

The library applies no rate limit: a loop with no sleep queues frames faster than 6 Mbaud drains.

ClicksPress, wait, release

A click is press, a wait, then release, which clears only the box's override.

EXAMPLE
use std::{thread, time::Duration};
use medius::Button;

device.press(Button::LEFT)?;
thread::sleep(Duration::from_millis(20));
device.release(Button::LEFT)?;

reset drops every override at once. reapply re-asserts a held press on reconnect.