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}