neiam
/apollos-dbus
public · Issues · Pulls · Labels · Forks · Compare · Actions queued · Badges · Packages
Log in to mark this repository.
| .github | |||
| dist | |||
| plasmoid | |||
| scripts | |||
| src | |||
| .gitignore | 8 B | ||
| Cargo.lock | 38.3 KiB | ||
| Cargo.toml | 1.8 KiB | ||
| LICENSE.md | 33.9 KiB | ||
| README.md | 7.1 KiB |
apollos-dbus
Apollo’s Crib on the session bus.
A small daemon that connects to any number of Ankyrae and Keryxiae and keeps what they say as objects on the session bus – so a Plasma widget, a wallpaper, a panel script or anything else that speaks D-Bus can show a vision without each one holding its own broker connection, credentials and parser.
Nothing is polled. A Pythiae publishes on change, a Keryx on its tick; the daemon subscribes, asks for a fresh copy whenever it (re)connects, and keeps the last of everything on disk so a widget at login shows what was true at shutdown – marked stale – rather than nothing.
apollos-types is the source of
truth for the shapes on the wire.
Install
TLS goes through the system OpenSSL, so building needs its headers and
pkg-config (libssl-dev on Debian/Ubuntu, openssl-devel on Fedora,
libopenssl-3-devel on openSUSE).
cargo build --release
install -Dm755 target/release/apollos-dbus ~/.local/bin/apollos-dbus
install -Dm644 dist/apollos-dbus.service ~/.config/systemd/user/apollos-dbus.service
sed -i "s|/usr/bin|$HOME/.local/bin|" ~/.config/systemd/user/apollos-dbus.service
install -Dm644 dist/config.example.toml ~/.config/apollos-dbus/config.toml # then edit
chmod 600 ~/.config/apollos-dbus/config.toml
systemctl --user enable --now apollos-dbus
cargo deb / cargo generate-rpm package the binary, the unit, and a D-Bus
activation file (dist/io.neiam.ApollosCrib.service) so the first widget to
ask starts it.
Configure
~/.config/apollos-dbus/config.toml – see
dist/config.example.toml. The short version:
[[ankyra]]
name = "home"
link = "apolloscrib://ankyra?host=..&user=..&pass=..&topic=.."
[[keryx]]
name = "desk"
id = 7
link = "apolloscrib://ankyra?host=..&user=..&pass=..&topic=.."
The link is the Pair a Client QR on cfg/ankyra/<id>; copy it out of
the page. Any field next to a link overrides what the link says.
A Keryx is reached with any rabbit user belonging to the account that
owns it – most easily an Ankyra’s, which is why a Keryx entry takes the same
link. Its topics are apollos/keryx/<id>/...; this needs an apollos-crib
with dotted, id-keyed Keryx topics (8a95d37 or later).
The client id defaults to apollos-dbus-<hostname>, and a second
connection appends its source’s name. An Ankyra with auto-registration off
refuses an id it has not been given – add it on the Ankyra’s page.
With tls = true the broker’s certificate is checked against the system’s
roots and its host name. A broker signed by a private CA wants that CA in
the system store, or SSL_CERT_FILE=/path/to/ca.pem in the unit’s
environment.
The interface
Bus name io.neiam.ApollosCrib. Everything is a property, every change a
PropertiesChanged, because that is what Plasma’s QML DBusProperties
binds to. Structured values are JSON strings: a D-Bus struct reaches QML as
an opaque QDBusArgument, a string reaches it as something JSON.parse
reads.
/io/neiam/ApollosCrib — io.neiam.ApollosCrib1
| Type | ||
|---|---|---|
Board |
s |
Every query, keyed <type>-<id>: {name, type, id, query_id, source, updated, stale, data, meta, plus, points} |
Points |
s |
Every query in a few words, flattened: [{key, name, type, text, color?, stale}] |
Queries |
as |
The keys there are objects for |
Sources |
s |
[{name, connected, error?}] |
Connected |
b |
Whether any source is connected |
Refresh() |
Ask every source for fresh data | |
RefreshQuery(s key) |
One query: a Keryx refreshes just it, an Ankyra its whole board | |
QueryUpdated(s key) |
signal | News, as against the clock making something stale |
Also org.freedesktop.DBus.ObjectManager, for GetManagedObjects.
/io/neiam/ApollosCrib/query/<type>_<id> — io.neiam.ApollosCrib1.Query
A key is <type>-<id>, and the id is not always a query’s: a Plani with
a card per stop keys each <source>:<stop>, gtfs-1:2577, in the feed’s
own stop ids. In the path the type’s dash is _ and any other character
outside [A-Za-z0-9] is _ and its hex, so gtfs-12 is gtfs_12 and
gtfs-1:2577 is gtfs_1_3a2577. Reading Board or Queries saves
working that out.
| Type | ||
|---|---|---|
Key |
s |
gtfs-12 |
Type |
s |
gtfs, weather, … |
Id |
s |
Everything after the type: 12, 1:2577 |
QueryId |
u |
The id as a query id; 0 where it is not one |
Name |
s |
The query’s name, or its key if sent bare |
Source |
s |
ankyra:<name> / keryx:<name> |
Updated |
x |
Seconds since the epoch |
Stale |
b |
Unheard from for over stale_after_secs (default 15 min) |
Data |
s |
The condensed reading, JSON, in its apollos-types shape |
Meta |
s |
The query’s meta, JSON |
Plus |
s |
The Plus reading, JSON, null where none |
Points |
as |
The reading in a few words |
Points are for a consumer with room for a sentence and no business
knowing what a GBFS dock is: 14 Heath St · 08:03 08:20, Union Sq: 5 bikes (2 e) · 7 docks, Home: 12°C light rain. Transit, bikeshare, weather,
tides, air quality, sun and moon, and calendar have them; anything else has
none, and Data is still there.
From QML
import org.kde.plasma.workspace.dbus as DBus
DBus.Properties {
id: crib
busType: DBus.BusType.Session
service: "io.neiam.ApollosCrib"
path: "/io/neiam/ApollosCrib"
iface: "io.neiam.ApollosCrib1"
}
Text { text: JSON.parse(crib.properties.Points || "[]").map(p => p.text).join("\n") }
plasmoid/ is the worked example – a widget with a heading per
query, dimmed when stale, picking its queries from the bus:
kpackagetool6 --type Plasma/Applet --install plasmoid # --upgrade thereafter
From a shell
busctl --user get-property io.neiam.ApollosCrib /io/neiam/ApollosCrib io.neiam.ApollosCrib1 Points
busctl --user call io.neiam.ApollosCrib /io/neiam/ApollosCrib io.neiam.ApollosCrib1 Refresh
Not here yet
- The uplink. A Plani follows a client’s position, and the phone reports
one on
<topic>.up.; a desktop does not. - The Ankyra’s image (
<topic>.img), which is for e-paper. - Keryx raw and per-item topics: only
.meta, the condensed reading, is subscribed to. The rest is most of the traffic and none of the summary.