rupnp/
discovery.rs

1use crate::{Device, Error, Result};
2use futures_util::stream::{Stream, StreamExt, TryStreamExt};
3use ssdp_client::SearchTarget;
4use std::time::Duration;
5
6/// Discovers UPnP devices on the network.
7///
8/// # Example usage:
9/// ```rust,no_run
10/// use futures::prelude::*;
11/// use std::time::Duration;
12/// use rupnp::ssdp::SearchTarget;
13///
14/// # async fn discover() -> Result<(), rupnp::Error> {
15/// let devices = rupnp::discover(&SearchTarget::RootDevice, Duration::from_secs(3), None).await?;
16/// let mut devices = std::pin::pin!(devices);
17///
18/// while let Some(device) = devices.try_next().await? {
19///     println!(
20///         "{} - {} @ {}",
21///         device.device_type(),
22///         device.friendly_name(),
23///         device.url()
24///     );
25/// }
26///
27/// # Ok(())
28/// # }
29/// ```
30// TODO: doc include once stable
31pub async fn discover(
32    search_target: &SearchTarget,
33    timeout: Duration,
34    ttl: Option<u32>,
35) -> Result<impl Stream<Item = Result<Device>>> {
36    return discover_with_properties(search_target, timeout, ttl, &[]).await;
37}
38
39/// Discovers UPnP devices on the network and saves extra_fields in device descriptions
40///
41/// # Example usage:
42/// ```rust,no_run
43/// use futures::prelude::*;
44/// use std::time::Duration;
45/// use rupnp::ssdp::SearchTarget;
46///
47/// # async fn discover_with_properties() -> Result<(), rupnp::Error> {
48/// let devices = rupnp::discover_with_properties(&SearchTarget::RootDevice, Duration::from_secs(3), None, &["manufacturer", "manufacturerURL"]).await?;
49/// let mut devices = std::pin::pin!(devices);
50///
51/// while let Some(device) = devices.try_next().await? {
52///     println!(
53///         "{} - {} @ {}",
54///         device.device_type(),
55///         device.get_extra_property("manufacturer").unwrap_or_default(),
56///         device.get_extra_property("manufacturerURL").unwrap_or_default()
57///     );
58/// }
59///
60/// # Ok(())
61/// # }
62/// ```
63pub async fn discover_with_properties<'a>(
64    search_target: &SearchTarget,
65    timeout: Duration,
66    ttl: Option<u32>,
67    extra_keys: &'a [&'a str],
68) -> Result<impl Stream<Item = Result<Device>> + 'a> {
69    Ok(ssdp_client::search(search_target, timeout, 3, ttl)
70        .await?
71        .map_err(Error::SSDPError)
72        .map(|res| Ok(res?.location().parse()?))
73        .and_then(move |url| Device::from_url_and_properties(url, extra_keys)))
74}