Choosing a port
When more than one box is plugged infind grabs the first match. With more than one box, find_medius lists every match as a PortInfo (path, vid, pid) without opening, then open the chosen one.
use medius::{Device, find_medius};
let ports = find_medius();
for port in &ports {
println!("{} (vid={:#06x} pid={:#06x})", port.path, port.vid, port.pid);
}
// open a chosen one (here, the first):
let port = ports.first().ok_or(medius::Error::NotFound)?;
let dev = Device::open(&port.path)?;Threading and Clone
Share one connection across threadsDevice is Send + Sync and clones cheaply (an Arc inside), so one connection serves any number of threads; a clone doesn't reopen the port.
use std::thread;
let worker = device.clone();
let handle = thread::spawn(move || {
worker.move_rel(10, 0)
});
handle.join().unwrap()?;Running queries concurrently
join and cloning across tasksAsyncDevice clones the same way, so hand a clone to another task and await both queries together with futures::future::join.
let (v, h) = futures::future::join(
device.query_version(),
device.query_health(),
).await;
let v = v?;
let h = h?;
println!("{v}, link_up={}", h.link_up);Only the queries need .await; mutators stay synchronous on either handle.
Keepalive and holds
Holding injected input past the silence windowThe box clears every injected input and pending move once no frame arrives for its silence window.
A Device holds your overrides past that itself: a background thread (medius-keepalive) sends a QUERY(HEALTH) every DEFAULT_KEEPALIVE_CADENCE (500 ms) while anything is held. There's no keepalive() to call.
| State | Behavior |
|---|---|
| Override held | Keepalive thread runs; the health reply is dropped. |
| Idle | No override held, so the thread sends nothing. |
device.press(Button::Left)?;
// No further calls. The keepalive thread sends QUERY(HEALTH) on its own,
// so the hold survives well past the 1000 ms silence window.
std::thread::sleep(std::time::Duration::from_secs(5));
device.reset()?;An override is the box holding an input down or up itself, set by press or force_release; the library keeps a copy. After a dropped link, reapply and reconnect restore it.
Releasing the device
Drop it; no close() callThere's no close: dropping the last Arc-backed handle runs its Drop and tears the connection down.
| Step | What drop does |
|---|---|
| Signal | Sets the stop flag the reader and keepalive threads watch. |
| Join | Waits for both threads to exit, so none are left running. |
| Close | Releases the serial port as the transport drops. |
To return the box to passthrough at once, call reset before drop.
// back to passthrough now, not after the silence window:
device.reset()?; // box returns to passthrough immediately
drop(device); // tears down threads and closes the port