I wish to use sd-bus to query upowerd for my battery's remaining percentage. I have begun by adapting the example program from Lennart's blog post introducing the sd-bus API:
http://0pointer.net/blog/the-new-sd-bus-api-of-systemd.html
However, I cannot succeed in adapting it to my needs. I can read the value of
the Percentage property with
$ busctl introspect org.freedesktop.UPower
/org/freedesktop/UPower/devices/battery_BAT0
This shows me that the Percentage is a double value, and that the Get() method
of the org.freedesktop.DBus.Properties interface returns a variant value.
I can also retrieve the desired datum with busctl:
$ busctl call org.freedesktop.UPower \
/org/freedesktop/UPower/devices/battery_BAT0 \
org.freedesktop.DBus.Properties Get \
ss org.freedesktop.UPower.Device Percentage
I can make the equivalent method call using the sd-bus API from the C program,
but the program errors out at the call to sd_bus_message_read().
When I tell sd_bus_message_read() that my message is of variant type "v", it
fails with -EINVAL. When I instead give it "d", it fails with -ENXIO.
What does sd_bus_message_read() expect in the 2nd argument? Or am I doing
something else wrong?
/*
gcc bus-client.c -o bus-client -lsystemd
*/
#include <stdio.h>
#include <stdlib.h>
#include <systemd/sd-bus.h>
int main() {
sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus_message *m = NULL;
sd_bus *bus = NULL;
int r;
double p;
/* Connect to the system bus */
r = sd_bus_open_system(&bus);
if (r < 0) {
fprintf(stderr, "Failed to connect to system bus: %s\n",
strerror(-r));
goto finish;
}
/* The following call to sd_bus_call_method() should be equivalent to
this cmd:
busctl call org.freedesktop.UPower \
/org/freedesktop/UPower/devices/battery_BAT0 \
org.freedesktop.DBus.Properties Get \
ss org.freedesktop.UPower.Device Percentage
*/
r = sd_bus_call_method(bus,
"org.freedesktop.UPower", /*
service to contact */
"/org/freedesktop/UPower/devices/battery_BAT0", /*
object path */
"org.freedesktop.DBus.Properties", /*
interface name */
"Get", /*
method name */
&error, /*
object to return error in */
&m, /*
return message on success */
"ss" /*
input signature */
,"org.freedesktop.UPower.Device" /*
first argument */
,"Percentage" /*
second argument */
);
if (r < 0) {
fprintf(stderr, "Failed to issue method call: %s\n",
error.message);
goto finish;
}
/* XXX This is where the failure is occurring XXX */
r = sd_bus_message_read(m, "v", &p);
if (r < 0) {
fprintf(stderr, "Failed to parse response message: (%d) %s\n",
r, strerror(-r));
goto finish;
}
printf("Battery %f%%", p);
finish:
sd_bus_error_free(&error);
sd_bus_message_unref(m);
sd_bus_unref(bus);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
/*
* Running this program results in the following output:
*
* % ./bus-client
* Failed to parse response message: (-22) Invalid argument
*
*/
--
Erik Falor
Registered Linux User #445632 http://unnovative.net
signature.asc
Description: PGP signature
_______________________________________________ systemd-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/systemd-devel
