pub struct DStarGateway<T: Transport + Unpin + 'static> { /* private fields */ }Expand description
Complete D-STAR gateway client for the TH-D75.
Manages the MMDVM session, tracks voice transmissions, decodes slow data messages, and maintains a last-heard list. This is the building block for D-STAR reflector clients — it handles the radio side of the gateway while the user provides the network side.
See the module-level documentation for architecture details and a full usage example.
Implementations§
Source§impl<T: Transport + Unpin + 'static> DStarGateway<T>
impl<T: Transport + Unpin + 'static> DStarGateway<T>
Sourcepub async fn start(
radio: Radio<T>,
config: DStarGatewayConfig,
) -> Result<Self, (Radio<T>, Error)>
pub async fn start( radio: Radio<T>, config: DStarGatewayConfig, ) -> Result<Self, (Radio<T>, Error)>
Start the D-STAR gateway.
Enters MMDVM mode on the radio, initializes the modem for D-STAR
operation, and returns a ready-to-use gateway. Consumes the
Radio — call stop to exit and reclaim it.
§Errors
On failure, returns the Radio alongside the error so the
caller can continue using CAT mode.
§Panics
Panics if MMDVM was entered and D-STAR init failed AND the subsequent MMDVM exit also failed. This indicates unrecoverable transport state; the caller’s only option is to drop any remaining handles and reconnect to the radio from scratch.
Sourcepub async fn start_gateway_mode(
radio: Radio<T>,
config: DStarGatewayConfig,
) -> Result<Self, Error>
pub async fn start_gateway_mode( radio: Radio<T>, config: DStarGatewayConfig, ) -> Result<Self, Error>
Start the D-STAR gateway on a radio already in MMDVM mode.
Use this when the radio was put into DV Gateway / Reflector
Terminal Mode via MCP write (offset 0x1CA0 = 1). The transport
already speaks MMDVM binary — no TN command is sent.
§Errors
Returns an error if the D-STAR initialization sequence fails.
Sourcepub async fn next_event(&mut self) -> Result<Option<DStarEvent>, Error>
pub async fn next_event(&mut self) -> Result<Option<DStarEvent>, Error>
Process pending I/O and return the next event.
Each call waits up to Self::set_event_timeout for a new MMDVM
event from the modem loop, translates it into a DStarEvent,
and returns. Returns Ok(None) when no MMDVM event arrives
within the timeout.
§Errors
Only returns errors if the underlying transport fails fatally.
Malformed frames are swallowed by the mmdvm crate’s RX loop
as debug diagnostics — propagating a decode error would kill
the whole session on a single malformed byte.
Sourcepub async fn send_header(&mut self, header: &DStarHeader) -> Result<(), Error>
pub async fn send_header(&mut self, header: &DStarHeader) -> Result<(), Error>
Send a D-STAR voice header to the radio for transmission.
Enqueues the header in the mmdvm TX queue, which is drained when the modem reports enough D-STAR FIFO space.
§Errors
Returns Error::Transport if the modem loop has exited.
Sourcepub async fn send_voice(&mut self, frame: &VoiceFrame) -> Result<(), Error>
pub async fn send_voice(&mut self, frame: &VoiceFrame) -> Result<(), Error>
Send a D-STAR voice data frame to the radio for transmission.
Enqueues the frame in the mmdvm TX queue. Pacing is handled inside the mmdvm modem loop — no host-side sleep is introduced here.
§Errors
Returns Error::Transport if the modem loop has exited.
Sourcepub async fn send_voice_unpaced(
&mut self,
frame: &VoiceFrame,
) -> Result<(), Error>
pub async fn send_voice_unpaced( &mut self, frame: &VoiceFrame, ) -> Result<(), Error>
Send a voice frame to the radio without any host-side pacing.
In the current architecture (mmdvm owns pacing via its
buffer-gated TxQueue drain), this method and
Self::send_voice are functionally equivalent; both simply
enqueue the frame and let the modem loop drain when
dstar_space allows. The alias is retained for back-compat
with callers that historically preferred the unpaced variant.
§Errors
Returns Error::Transport if the modem loop has exited.
Sourcepub async fn send_eot(&mut self) -> Result<(), Error>
pub async fn send_eot(&mut self) -> Result<(), Error>
Send end-of-transmission to the radio.
§Errors
Returns Error::Transport if the modem loop has exited.
Sourcepub async fn send_status_header(
&mut self,
reflector: Option<(&str, char)>,
) -> Result<(), Error>
pub async fn send_status_header( &mut self, reflector: Option<(&str, char)>, ) -> Result<(), Error>
Send a status header to the radio indicating connection state.
When connected to a reflector, sets RPT1/RPT2 to the reflector name + module and UR to CQCQCQ. When disconnected, sets RPT1/RPT2 to “DIRECT”.
This updates the radio’s display to show the current gateway
state, matching the behavior of d75link and BlueDV.
§Errors
Returns Error::Transport if the write fails.
Sourcepub const fn set_event_timeout(&mut self, timeout: Duration)
pub const fn set_event_timeout(&mut self, timeout: Duration)
Set the receive timeout for next_event polling.
Lower values make the event loop more responsive but increase CPU usage. Use short timeouts (10-50ms) when actively relaying voice from a reflector.
Sourcepub const fn event_timeout(&self) -> Duration
pub const fn event_timeout(&self) -> Duration
Current receive timeout for next_event polling.
Mirrors Self::set_event_timeout. Callers that temporarily
drop the timeout (e.g. during a tight event-drain loop) use
this to save and restore the prior value.
Sourcepub fn last_heard(&self) -> &[LastHeardEntry]
pub fn last_heard(&self) -> &[LastHeardEntry]
Get the last-heard list (newest first).
Sourcepub async fn poll_status(&mut self) -> Result<ModemStatus, Error>
pub async fn poll_status(&mut self) -> Result<ModemStatus, Error>
Poll the modem status.
Requests an immediate GetStatus and returns the next status
event delivered by the modem loop. The mmdvm modem loop also
polls status periodically (every 250 ms), so callers rarely
need this.
§Errors
Returns an error if the status request fails or the modem loop exits before delivering a status event.
Sourcepub const fn is_receiving(&self) -> bool
pub const fn is_receiving(&self) -> bool
Check if a voice transmission is currently active (RX from radio).
Sourcepub const fn current_header(&self) -> Option<&DStarHeader>
pub const fn current_header(&self) -> Option<&DStarHeader>
Get the current RX header, if a voice transmission is active.
Sourcepub const fn config(&self) -> &DStarGatewayConfig
pub const fn config(&self) -> &DStarGatewayConfig
Get the current configuration.