-1

I'm trying to listen to changes of UPower device. From terminal this easily done by

$ dbus-monitor --system  "type='signal',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',path='/org/freedesktop/UPower/devices/battery_BAT0'"

I'm trying to write a Rust program using zbus crate. I tried many different approaches (PropertiesProxy, DBusProxy), but the only somewhat working solution for me is this (build on obsolete zbus version 1.8):

let connection = Connection::new_system()?;
let object_path = "/org/freedesktop/UPower/devices/battery_BAT0";
let match_rule = format!(
    "type='signal',interface='org.freedesktop.DBus.Properties',path='{}',member='PropertiesChanged'",
    object_path
);
let dbus_proxy = DBusProxy::new(&connection)?;
dbus_proxy.add_match(&match_rule)?;
while let Some(message) = dbus_proxy.next_signal()? {
    dbg!(message);
}

My attempt with recent version

let connection = Connection::system().await?;
let object_path = "/org/freedesktop/UPower/devices/battery_BAT0";
let match_rule = zbus::MatchRule::builder()  // .to_string() shows rule, identical to version above
    .msg_type(MessageType::Signal)
    .path(object_path)?
    .interface("org.freedesktop.DBus.Properties")?
    .member("PropertiesChanged")?
    .build();
let proxy: DBusProxy = DBusProxy::new(&connection).await?;
proxy.add_match_rule(match_rule).await?;
let mut signals_stream = proxy.receive_all_signals().await?; // I tried to enable caching in builder as per documentation, no success
while let Some(message) = signals_stream.next().await {
    dbg!(message);
}

Ok(())

Seems like I missing some fundamental knowledge about DBus (or crate, or both), but at this point I haven't a slightest idea how to do that.

Flowneee
  • 234
  • 1
  • 5
  • 15
  • 1
    I'm not familiar with rust but it seems to have `receive_properties_changed` method on a property proxy https://docs.rs/zbus/latest/zbus/fdo/struct.PropertiesProxy.html#method.receive_properties_changed. Some searching around has turned up this example of working with signals: https://dbus2.github.io/zbus/client.html#signals – ukBaz Jun 13 '23 at 04:46
  • God, how did I miss this book? Thank you @ukBaz, I'll check this example, seems like exactly what I need. I tried `receive_properties_changed`, but with no success. – Flowneee Jun 13 '23 at 07:45

1 Answers1

1

I figured that out: I was missing destination, this works

#[tokio::main]
async fn main() -> Result<(), Error> {
    let connection = Connection::system().await?;

    let properties_proxy = fdo::PropertiesProxy::builder(&connection)
        .destination("org.freedesktop.UPower")?    // <--- this is important
        .path("/org/freedesktop/UPower/devices/battery_BAT0")?
        .build()
        .await?;

    let mut changes_stream = properties_proxy.receive_properties_changed().await?;

    while let Some(change) = changes_stream.next().await {
        println!("Change body: {change:#?}");
    }

    Ok(())
}
Flowneee
  • 234
  • 1
  • 5
  • 15