Skip to content

Commit

Permalink
Merge pull request #521 from intgr/simpler-signals-example
Browse files Browse the repository at this point in the history
📝 book: Add a simpler D-Bus signals example
  • Loading branch information
zeenix authored Dec 11, 2023
2 parents f1e3675 + 481631b commit c089c38
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 2 deletions.
51 changes: 49 additions & 2 deletions book/src/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,54 @@ Signals are like methods, except they don't expect a reply. They are typically e
to notify interested peers of any changes to the state of the service. zbus provides you a
[`Stream`]-based API for receiving signals.

Let's look at this API in action, with an example where we get our location from
Let's look at this API in action, with an example where we monitor started systemd units.

```rust,no_run
# // NOTE: When changing this, please also keep `zbus/examples/watch-systemd-jobs.rs` in sync.
use async_std::stream::StreamExt;
use zbus::Connection;
use zbus_macros::dbus_proxy;
use zvariant::OwnedObjectPath;
# fn main() {
# async_io::block_on(watch_systemd_jobs()).expect("Error listening to signal");
# }
#[dbus_proxy(
default_service = "org.freedesktop.systemd1",
default_path = "/org/freedesktop/systemd1",
interface = "org.freedesktop.systemd1.Manager"
)]
trait Systemd1Manager {
// Defines signature for D-Bus signal named `JobNew`
#[dbus_proxy(signal)]
fn job_new(&self, id: u32, job: OwnedObjectPath, unit: String) -> zbus::Result<()>;
}
async fn watch_systemd_jobs() -> zbus::Result<()> {
let connection = Connection::system().await?;
// `Systemd1ManagerProxy` is generated from `Systemd1Manager` trait
let systemd_proxy = Systemd1ManagerProxy::new(&connection).await?;
// Method `receive_job_new` is generated from `job_new` signal
let mut new_jobs_stream = systemd_proxy.receive_job_new().await?;
while let Some(msg) = new_jobs_stream.next().await {
// struct `JobNewArgs` is generated from `job_new` signal function arguments
let args: JobNewArgs = msg.args().expect("Error parsing message");
println!(
"JobNew received: unit={} id={} path={}",
args.unit, args.id, args.job
);
}
panic!("Stream ended unexpectedly");
}
```

#### More advanced example

Here is a more elaborate example, where we get our location from
[Geoclue](https://gitlab.freedesktop.org/geoclue/geoclue/-/blob/master/README.md):

```rust,no_run
Expand Down Expand Up @@ -568,7 +615,7 @@ There you have it, a Rust-friendly binding for your D-Bus service!
[`gdbus-codegen`]: https://docs.gtk.org/gio/migrating-gdbus.html#generating-code-and-docs
[`pkg-config`]: https://www.freedesktop.org/wiki/Software/pkg-config/
[cob]: blocking.html
[`Stream`]: https://docs.rs/futures/0.3.17/futures/stream/trait.Stream.html
[`Stream`]: https://docs.rs/futures/latest/futures/stream/trait.Stream.html
[`Value`]: https://docs.rs/zvariant/latest/zvariant/derive.Value.html
[`OwnedValue`]: https://docs.rs/zvariant/latest/zvariant/derive.OwnedValue.html

Expand Down
48 changes: 48 additions & 0 deletions zbus/examples/watch-systemd-jobs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//! Example demonstrating how to monitor for D-Bus Signal events.
//!
//! Prints a message every time a systemd service or other job starts.
//!
//! Run with command: `cargo run --example watch-systemd-jobs`
use async_std::stream::StreamExt;
use zbus::Connection;
use zbus_macros::dbus_proxy;
use zvariant::OwnedObjectPath;

fn main() {
async_io::block_on(watch_systemd_jobs()).expect("Error listening to signal");
}

#[dbus_proxy(
default_service = "org.freedesktop.systemd1",
default_path = "/org/freedesktop/systemd1",
interface = "org.freedesktop.systemd1.Manager"
)]
trait Systemd1Manager {
// Defines signature for D-Bus signal named `JobNew`
#[dbus_proxy(signal)]
fn job_new(&self, id: u32, job: OwnedObjectPath, unit: String) -> zbus::Result<()>;
}

// NOTE: When changing this, please also keep `book/src/client.md` in sync.
async fn watch_systemd_jobs() -> zbus::Result<()> {
let connection = Connection::system().await?;
// `Systemd1ManagerProxy` is generated from `Systemd1Manager` trait
let systemd_proxy = Systemd1ManagerProxy::new(&connection).await?;
// Method `receive_job_new` is generated from `job_new` signal
let mut new_jobs_stream = systemd_proxy.receive_job_new().await?;

println!("Monitoring started systemd services or jobs...");

while let Some(msg) = new_jobs_stream.next().await {
// struct `JobNewArgs` is generated from `job_new` signal function arguments
let args: JobNewArgs = msg.args().expect("Error parsing message");

println!(
"JobNew received: unit={} id={} path={}",
args.unit, args.id, args.job
);
}

panic!("Stream ended unexpectedly");
}

0 comments on commit c089c38

Please sign in to comment.