初学者:如何访问DBus属性>

时间:2019-06-15 06:45:11

标签: vala

我正在尝试将以下python代码转换为vala

def powerStatusAvailable():
    """
    Check if org.freedesktop.UPower is available so that
    :py:func:`tools.onBattery` would return the correct power status.
    Returns:
        bool:   ``True`` if :py:func:`tools.onBattery` can report power status
    """
    if dbus:
        try:
            bus = dbus.SystemBus()
            proxy = bus.get_object('org.freedesktop.UPower',
                                   '/org/freedesktop/UPower')
            return 'OnBattery' in proxy.GetAll('org.freedesktop.UPower',
                            dbus_interface = 'org.freedesktop.DBus.Properties')
        except dbus.exceptions.DBusException:
            pass
    return False

作为vala的入门者,我很失落。 我不了解对象层次结构。 文档和示例使用Bus类。 还有一个类DBusProxy 我应该使用那个吗? ...它具有方法get_cached_property_names

Bus和DBusProxy有什么区别?

这是我的尝试,但是当然失败了。

  using GLib;

// example of a DBus client
[DBus (name = "org.freedesktop.UPower")]
interface UPowerManager : GLib.Object {
    public abstract GLib.ObjectPath[] enumerate_devices () throws GLib.DBusError,GLib.IOError;
    public abstract GLib.ObjectPath get_display_device () throws GLib.DBusError,GLib.IOError;
    public abstract string get_critical_action () throws GLib.DBusError,GLib.IOError;
    public abstract string[] get_cached_property_names () throws GLib.DBusError,GLib.IOError;


}

int main (string[] args)
{

    UPowerManager upower_manager;
    upower_manager = Bus.get_proxy_sync(BusType.SYSTEM,"org.freedesktop.UPower","/org/freedesktop/UPower");
    string[] property_names;
    property_names = upower_manager.get_cached_property_names();


    stdout.printf ("Hello, World!\n");

    return 0;
}

但是编译错误

未捕获的错误:GDBus.Error:org.freedesktop.DBus.Error.UnknownMethod:没有这样的方法'GetCachedPropertyNames'

1 个答案:

答案 0 :(得分:2)

这是我所做的:

首先,我使用DBus.Introspectable得到了XML定义:

dbus-send --system --print-reply --type=method_call --dest=org.freedesktop.UPower /org/freedesktop/UPower org.freedesktop.DBus.Introspectable.Introspect

您可以将该命令的结果转储到.xml文件中,但请确保仅包含XML,该文件应如下所示:

<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
                      "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<!-- GDBus 2.58.3 -->
<node>
  <interface name="org.freedesktop.DBus.Properties">
  … and so on
</node>

下一步是使用vala-dbus-binding-tool创建接口,您可以从https://github.com/freesmartphone/vala-dbus-binding-tool那里获得

vala-dbus-binding-tool -v

这将生成一些vala文件,其中之一包含org.freedesktop.UPower的正确接口。

剩下的就是使用它,这非常简单,这是一个简单的示例:

[DBus (name = "org.freedesktop.UPower", timeout = 120000)]
public interface UPower : GLib.Object {
    [DBus (name = "EnumerateDevices")]
    public abstract async GLib.ObjectPath[] enumerate_devices() throws DBusError, IOError;

    [DBus (name = "GetDisplayDevice")]
    public abstract async GLib.ObjectPath get_display_device() throws DBusError, IOError;

    [DBus (name = "GetCriticalAction")]
    public abstract async string get_critical_action() throws DBusError, IOError;

    [DBus (name = "DeviceAdded")]
    public signal void device_added(GLib.ObjectPath device);

    [DBus (name = "DeviceRemoved")]
    public signal void device_removed(GLib.ObjectPath device);

    [DBus (name = "DaemonVersion")]
    public abstract string daemon_version { owned get; }

    [DBus (name = "OnBattery")]
    public abstract bool on_battery {  get; }

    [DBus (name = "LidIsClosed")]
    public abstract bool lid_is_closed {  get; }

    [DBus (name = "LidIsPresent")]
    public abstract bool lid_is_present {  get; }
}

int main (string[] args)
{
    UPower upower;
    upower = Bus.get_proxy_sync(BusType.SYSTEM, "org.freedesktop.UPower",
                                "/org/freedesktop/UPower");

    if (upower.on_battery) {
        stdout.printf ("System is running on battery\n");
    }
    else {
        stdout.printf ("System is running on line current\n");
    }

    return 0;
}

关于您有关GLib.Bus与GLib.DBusProxy的问题。

我不是专家,但是如果您查看生成的C代码(您可以使用valac -C获得),

static gboolean
upower_dbus_proxy_get_on_battery (UPower* self)
{
        GVariant *_inner_reply;
        gboolean _result;
        _inner_reply = g_dbus_proxy_get_cached_property ((GDBusProxy *) self, "OnBattery");
        if (!_inner_reply) {
                GVariant *_arguments;
                GVariant *_reply;
                GVariantBuilder _arguments_builder;
                g_variant_builder_init (&_arguments_builder, G_VARIANT_TYPE_TUPLE);
                g_variant_builder_add_value (&_arguments_builder, g_variant_new_string ("org.freedesktop.UPower"));
                g_variant_builder_add_value (&_arguments_builder, g_variant_new_string ("OnBattery"));
                _arguments = g_variant_builder_end (&_arguments_builder);
                _reply = g_dbus_proxy_call_sync ((GDBusProxy *) self, "org.freedesktop.DBus.Properties.Get", _arguments$
                if (!_reply) {
                        gboolean _tmp8_ = FALSE;
                        return _tmp8_;
                }
                g_variant_get (_reply, "(v)", &_inner_reply);
                g_variant_unref (_reply);
        }
    _result = g_variant_get_boolean (_inner_reply);
        g_variant_unref (_inner_reply);
        return _result;
}

DBus标记接口的高级功能将自动在内部DBusProxy对象上调用其方法,而无需自己在Vala中编写该低级代码。