Traveling heavily recently, I've become fatigued from typing all the WiFi passphrases. My phone can happily connect via a QR code. Why does my laptop required so much typing, I asked. So I proposed a simple project.
Researching how I might use my web-cam to connect to WiFi networks, I came
across the Network Manager and Rust's Zbus article on
rbs.io. I use
NewtworkManager
and I enjoy working with rust. I know next to nothing about
DBus
, but I thought some knowledge of hacking Linux networks couldn't do me any
harm. Besides I had some free time.
The above article set me on the right path. The zbus
documentation is still a
little obscure in some salient details, however. Hopefully this post will help
fill those in. The finished code is hosted in the
scampi repo.
HashMap
s with structs.I first needed to generate a settings.rs
with zbus-xmlgen
as described in
the above article. It is also straightforward to create a connection by building
the nested structures of HashMaps
also described there. While that solution
works, it is tedious, unsightly and doesn't make the most of rust's type
system. Finding the issue for using DeserializeStruct
with nested
structs closed, I hoped there might
now be a more ergonomic way forward.
With the help of the zbus book I
managed to piece together a solution that feels a little more rust-like. Of
course there are many pieces to the puzzle. You need serde
and the zvariant::Type
macro. But all that is gleaned fairly easily from the documentation, I think. The more
salient discovery was that zbus
allows declaring DBbus
signatures on your
types. This is done via a macro, like so:
#[zvariant(signature = "a{sa{sv}}")]
struct MyType{..}
Declaring the correct signature(a{sa{sv}}
) on the struct passed to
NetworkManager
s Settings.add_connection()
allowed it to navigate Dbus
's
type system. Its children don't have any children of their own, so
SerializedDict
and DeserializeDict
works fine on them.
For a more complete example you can have a look at the code.
I believe I could go further and replace some fields defined as String
with
more appropriate types, but it's one more thing to learn and I think this is good
enough for now.