#async #networking #async-networking #network-protocol #upnp

rupnp

An asynchronous library for finding UPnP control points, performing actions on them and reading their service descriptions

12 releases (4 stable)

3.0.0 Apr 25, 2025
2.0.0 Sep 16, 2023
1.1.1 Feb 21, 2022
1.0.0 Dec 23, 2020
0.1.5 Apr 27, 2020

#203 in Network programming

Download history 5990/week @ 2025-01-10 8093/week @ 2025-01-17 11821/week @ 2025-01-24 10900/week @ 2025-01-31 11189/week @ 2025-02-07 11103/week @ 2025-02-14 11389/week @ 2025-02-21 9806/week @ 2025-02-28 9705/week @ 2025-03-07 10652/week @ 2025-03-14 11219/week @ 2025-03-21 9428/week @ 2025-03-28 10837/week @ 2025-04-04 8365/week @ 2025-04-11 9751/week @ 2025-04-18 9881/week @ 2025-04-25

39,723 downloads per month
Used in 10 crates (6 directly)

MIT/Apache

58KB
1.5K SLoC

GitHub last commit Crates.io

rupnp

An asynchronous library for finding UPnP control points, performing actions on them and reading their service descriptions. UPnP stand for Universal Plug and Play and is widely used for routers, WiFi-enabled speakers and media servers.

Spec: http://rupnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v2.0.pdf

Example usage:

The following code searches for devices that have a RenderingControl service and print their names along with their current volume.

use futures::prelude::*;
use std::time::Duration;
use rupnp::ssdp::{SearchTarget, URN};

const RENDERING_CONTROL: URN = URN::service("schemas-upnp-org", "RenderingControl", 1);

#[tokio::main]
async fn main() -> Result<(), rupnp::Error> {
    let search_target = SearchTarget::URN(RENDERING_CONTROL);
    let devices = rupnp::discover(&search_target, Duration::from_secs(3), None).await?;
    let mut devices = std::pin::pin!(devices);

    while let Some(device) = devices.try_next().await? {
        let service = device
            .find_service(&RENDERING_CONTROL)
            .expect("searched for RenderingControl, got something else");

        let args = "<InstanceID>0</InstanceID><Channel>Master</Channel>";
        let response = service.action(device.url(), "GetVolume", args).await?;

        let volume = response.get("CurrentVolume").unwrap();

        println!("'{}' is at volume {}", device.friendly_name(), volume);
    }

    Ok(())
}

License

Licensed under either of

at your option.

Contribution

Please use rustfmt before any pull requests.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Dependencies

~5–14MB
~155K SLoC