英文:
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() -> 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(())
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论