使用zbus从DBus接收属性更改。

huangapple go评论71阅读模式
英文:

Receiving property changes from DBus with zbus

问题

我试图监听UPower设备的更改。从终端中,可以轻松完成如下:

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

我正在尝试使用zbus库编写Rust程序。我尝试了许多不同的方法(PropertiesProxy、DBusProxy),但对我来说唯一有些工作的解决方案是使用过时的zbus版本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);
}

我的尝试与最新版本:

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(())

似乎我缺少一些关于DBus(或库,或两者)的基本知识,但在这一点上,我对如何做到这一点没有一点思路。

英文:

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.

答案1

得分: 1

我找到了问题:我漏掉了 destination,这个代码有效。

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

    let properties_proxy = fdo::PropertiesProxy::builder(&connection)
        .destination("org.freedesktop.UPower")?    // <--- 这很重要
        .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(())
}
英文:

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

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

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

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

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

    Ok(())
}

huangapple
  • 本文由 发表于 2023年6月13日 04:41:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76460189.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定