dbus2 / zbus-old

Rust D-Bus crate.
https://gitlab.freedesktop.org/dbus/zbus
Other
49 stars 13 forks source link

object_manager.receive_interfaces_added yields no events #269

Closed zeenix closed 1 year ago

zeenix commented 2 years ago

In GitLab by @WhyNotHugo on Apr 15, 2022, 01:30

The following snippet should receive interface_added events when new interfaces are added to objects:

use zbus::{export::futures_util::StreamExt, fdo::ObjectManagerProxy, Connection};

#[tokio::main]

async fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("Hello, world!");

    let connection = Connection::system().await?;
    let object_manager = ObjectManagerProxy::builder(&connection)
        // .destination("org.freedesktop.ModemManager1")?
        // .interface("org.freedesktop.ModemManager1.Modem")?
        .build()
        .await?;
    let mut interface_stream = object_manager.receive_interfaces_added().await?;

    while let Some(interface_added) = interface_stream.next().await {
        println!(
            "{:?}, {:?}",
            interface_added.interface(),
            interface_added.path()
        );
    }

    unreachable!();
}

In particular, I'm plugging in a Modem, upon which ModemManager exposes a new object with multiple interfaces. Somehow, The above code just prints Hello World and then freezes forever.

I suspect I'm doing something wrong. Any ideas what?

zeenix commented 2 years ago

Could it be because you don't specify the object path?

let object_manager = ObjectManagerProxy::builder(&connection)
        // Also this is commented out in your code.
        .destination("org.freedesktop.ModemManager1")?
        .path("/org/freedesktop/ModemManager1")?
        .build()
        .await?;
zeenix commented 2 years ago

In GitLab by @WhyNotHugo on Apr 15, 2022, 10:23

I don't know the object path ahead of time though, the object looks something like /org/freedesktop/ModemManager1/Modem/0, /org/freedesktop/ModemManager1/Modem/1, etc.

However, even if I do specify the path (just for experimental purposes), I still don't get any events,

    let object_manager = ObjectManagerProxy::builder(&connection)
        .destination("org.freedesktop.ModemManager1")?
        .path("/org/freedesktop/ModemManager1/Modem/1")?
        .build()
        .await?;
zeenix commented 2 years ago

I don't know the object path ahead of time though, the object looks something like /org/freedesktop/ModemManager1/Modem/0, /org/freedesktop/ModemManager1/Modem/1, etc.

Not the path of the modem itself but of the main object providing ObjectManager interface.

However, even if I do specify the path (just for experimental purposes), I still don't get any events,

Try giving the path exactly as I suggested.

zeenix commented 2 years ago

In GitLab by @WhyNotHugo on Apr 15, 2022, 21:41

That makes perfect sense (and works!). Thanks for the help.

Took me a moment to figure out that the interfaces are behind the args() method:

async fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("Hello, world!");

    let connection = Connection::system().await?;
    let object_manager = ObjectManagerProxy::builder(&connection)
        .destination("org.freedesktop.ModemManager1")?
        .path("/org/freedesktop/ModemManager1")?
        .build()
        .await?;
    let mut interface_stream = object_manager.receive_interfaces_added().await?;

    while let Some(interface_added) = interface_stream.next().await {
        println!("{:?}", interface_added.args()?.interfaces_and_properties());
    }

    unreachable!();
}
zeenix commented 2 years ago

In GitLab by @WhyNotHugo on Apr 15, 2022, 21:47

Hmmm... I realise I'm still missing the object path to the newly created objects.

But this API doesn't seem to expose that, should I be using some other technique to find them?

zeenix commented 2 years ago

It's the object_path arg.