Вала новичок: как получить доступ к свойствам DBus> - PullRequest
1 голос
/ 15 июня 2019

Я пытаюсь преобразовать следующий код 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 Ответ

2 голосов
/ 15 июня 2019

Вот что я сделал:

Сначала я получил определение XML, используя DBus.Introspectable:

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 (который вы можете получить с помощью * 1023)*):

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.

...