pub mod device;
pub mod error;
#[cfg(feature = "mdns")]
pub mod mdns;
#[cfg(feature = "broadcast")]
pub mod broadcast;
pub use device::{Device, DeviceInfo};
pub use error::{DiscoveryError, Result};
use std::time::Duration;
use tokio::sync::mpsc;
#[derive(Debug, Clone)]
pub enum DiscoveryEvent {
Found(Device),
Lost(String), Error(String),
}
#[derive(Debug, Clone)]
pub struct DiscoveryConfig {
pub mdns: bool,
pub broadcast: bool,
pub broadcast_port: u16,
pub timeout: Duration,
}
impl Default for DiscoveryConfig {
fn default() -> Self {
Self {
mdns: true,
broadcast: true,
broadcast_port: clasp_core::DEFAULT_DISCOVERY_PORT,
timeout: Duration::from_secs(5),
}
}
}
pub struct Discovery {
config: DiscoveryConfig,
devices: std::collections::HashMap<String, Device>,
}
impl Discovery {
pub fn new() -> Self {
Self {
config: DiscoveryConfig::default(),
devices: std::collections::HashMap::new(),
}
}
pub fn with_config(config: DiscoveryConfig) -> Self {
Self {
config,
devices: std::collections::HashMap::new(),
}
}
pub async fn start(&mut self) -> Result<mpsc::Receiver<DiscoveryEvent>> {
let (tx, rx) = mpsc::channel(100);
#[cfg(feature = "mdns")]
if self.config.mdns {
let tx_clone = tx.clone();
tokio::spawn(async move {
if let Err(e) = mdns::discover(tx_clone).await {
tracing::warn!("mDNS discovery error: {}", e);
}
});
}
#[cfg(feature = "broadcast")]
if self.config.broadcast {
let tx_clone = tx.clone();
let port = self.config.broadcast_port;
tokio::spawn(async move {
if let Err(e) = broadcast::discover(port, tx_clone).await {
tracing::warn!("Broadcast discovery error: {}", e);
}
});
}
Ok(rx)
}
pub fn devices(&self) -> impl Iterator<Item = &Device> {
self.devices.values()
}
pub fn get(&self, id: &str) -> Option<&Device> {
self.devices.get(id)
}
pub fn add(&mut self, device: Device) {
self.devices.insert(device.id.clone(), device);
}
pub fn remove(&mut self, id: &str) -> Option<Device> {
self.devices.remove(id)
}
}
impl Default for Discovery {
fn default() -> Self {
Self::new()
}
}