pub struct AsyncModem<T: Transport + 'static> { /* private fields */ }Expand description
Async handle to an MMDVM modem running in a spawned tokio task.
The handle is generic over the transport type T so that
AsyncModem::shutdown can recover the original transport for
reuse (e.g. to send post-MMDVM CAT commands on the same serial
port).
Dropping the handle closes the command channel, which causes the
spawned loop to exit on its next iteration. For a graceful
shutdown that also flushes the pending TX queue AND recovers the
inner transport, call AsyncModem::shutdown.
Implementations§
Source§impl<T: Transport + 'static> AsyncModem<T>
impl<T: Transport + 'static> AsyncModem<T>
Sourcepub fn spawn(transport: T) -> Self
pub fn spawn(transport: T) -> Self
Spawn the modem loop on the current tokio runtime and return a handle for controlling it.
The transport must be an already-connected duplex byte
stream (serial port, Bluetooth SPP, test duplex). The shell
takes ownership; it is automatically dropped when the loop
exits.
§Example
use mmdvm::AsyncModem;
use tokio::io::duplex;
let (client, _modem_side) = duplex(4096);
let mut modem = AsyncModem::spawn(client);
while let Some(event) = modem.next_event().await {
println!("{event:?}");
}Sourcepub async fn next_event(&mut self) -> Option<Event>
pub async fn next_event(&mut self) -> Option<Event>
Pull the next event from the modem loop.
Returns None once the task has exited and the event channel
has been fully drained.
§Cancellation safety
Cancel-safe — backed by tokio::sync::mpsc::Receiver::recv.
Sourcepub async fn send_dstar_header(
&mut self,
bytes: [u8; 41],
) -> Result<(), ShellError>
pub async fn send_dstar_header( &mut self, bytes: [u8; 41], ) -> Result<(), ShellError>
Enqueue a D-STAR header for transmission.
The frame is placed in the loop’s TX queue and drained only when the modem reports enough D-STAR FIFO space.
§Errors
ShellError::SessionClosedif the loop has exited.
Sourcepub async fn send_dstar_data(
&mut self,
bytes: [u8; 12],
) -> Result<(), ShellError>
pub async fn send_dstar_data( &mut self, bytes: [u8; 12], ) -> Result<(), ShellError>
Enqueue a D-STAR voice data frame for transmission.
§Errors
ShellError::SessionClosedif the loop has exited.
Sourcepub async fn send_dstar_eot(&mut self) -> Result<(), ShellError>
pub async fn send_dstar_eot(&mut self) -> Result<(), ShellError>
Enqueue a D-STAR end-of-transmission marker.
§Errors
ShellError::SessionClosedif the loop has exited.
Sourcepub async fn set_mode(&mut self, mode: ModemMode) -> Result<(), ShellError>
pub async fn set_mode(&mut self, mode: ModemMode) -> Result<(), ShellError>
Set the modem’s operating mode.
§Errors
ShellError::SessionClosedif the loop has exited.ShellError::Ioif writing to the transport fails.ShellError::Coreif the codec rejects the frame.
Sourcepub async fn request_version(&mut self) -> Result<(), ShellError>
pub async fn request_version(&mut self) -> Result<(), ShellError>
Trigger a GetVersion request. The response arrives as
Event::Version.
§Errors
ShellError::SessionClosedif the loop has exited.ShellError::Ioif writing to the transport fails.
Sourcepub async fn request_status(&mut self) -> Result<(), ShellError>
pub async fn request_status(&mut self) -> Result<(), ShellError>
Trigger an immediate GetStatus request. The response
arrives as Event::Status. The loop also polls status
every 250 ms on its own, so this is only needed for explicit
“check now” flows.
§Errors
ShellError::SessionClosedif the loop has exited.ShellError::Ioif writing to the transport fails.
Sourcepub async fn send_raw(
&mut self,
command: u8,
payload: Vec<u8>,
) -> Result<(), ShellError>
pub async fn send_raw( &mut self, command: u8, payload: Vec<u8>, ) -> Result<(), ShellError>
Send a raw frame — escape hatch for protocols we don’t model yet.
§Errors
ShellError::SessionClosedif the loop has exited.ShellError::Ioif writing to the transport fails.ShellError::Coreif the codec rejects the frame (e.g. oversized payload).
Sourcepub async fn shutdown(self) -> Result<T, ShellError>
pub async fn shutdown(self) -> Result<T, ShellError>
Graceful shutdown — flushes the TX queue, exits the loop, and returns the recovered transport.
Consumes the handle. After shutdown returns, the task has
fully wound down and ownership of the transport is handed back
to the caller so it can be reused (e.g. to switch back to CAT
mode on a serial port).
§Errors
ShellError::SessionClosedif the loop had already exited before the shutdown command could be delivered, or the task panicked / was aborted before it could hand the transport back.