Getting UPower events through gjs's DBusProxy

I’m working on a small gnome extension that will perform an action whenever a laptop’s AC adapter is plugged in or unplugged.

To do so in javascript, I’m using a Gio DBusProxy for the org.freedesktop.UPower interface. However, the properties of the proxy are never filled (they are null), and as soon as I call a method on the proxy, I’m getting the following error:

ERROR: DBus: Error org.freedesktop.DBus.Error.ServiceUnknown - The name org.freedesktop.UPower was not provided by any .service files

I can successfully create a proxy for another interface,org.gnome.SettingsDaemon.Power’s Screen, using the same approach. The proxy’s Brightness property then has a valid non-null value that I can access. (That one is on the session bus, while the UPower one is on the system bus, I don’t know whether that matters.) This leads me to believe that the general approach is OK.

I can successfully monitor the AC adapter being unplugged / plugged in from the commandline by running gdbus monitor --system --dest org.freedesktop.UPower --object-path /org/freedesktop/UPower

What could be the issue with the UPower proxy?

I’m on Ubuntu 21.10.

Well, it would probably help if you showed us some code :slightly_smiling_face:

Something like this should get you a working proxy:

function getPowerProxy() {
    return new Promise((resolve, reject) => {
        Gio.DBusProxy.new_for_bus(
            Gio.BusType.SYSTEM,
            Gio.DBusProxyFlags.NONE,
            null,
            'org.freedesktop.UPower',
            '/org/freedesktop/UPower/devices/DisplayDevice',
            'org.freedesktop.UPower.Device',
            null,
            (proxy_, result) => {
                try {
                    resolve(Gio.DBusProxy.new_for_bus_finish(result));
                } catch (e) {
                    reject(e);
                }
            }
        );
    });
}

You can watch for property changes with the g-properties-changed signal and get properties with Gio.DBusProxy.get_cached_property().

This is basically what the proxy wrapper code does, just without the automagic property getters/setters. If you’d like help with that, you’ll have to show some code.

Thank you for the example. I’ll give that a try.

The (working) code for the Screen interface, using makeProxyWrapper, is as follows:

const ScreenInterface = `<node>
    <interface name="org.gnome.SettingsDaemon.Power.Screen">
        <property type="i" name="Brightness" access="readwrite">
        </property>
    </interface>
</node>`;
const ScreenProxyClass = Gio.DBusProxy.makeProxyWrapper(ScreenInterface);
let screenProxy = new ScreenProxyClass(
    Gio.DBus.session,
    'org.gnome.SettingsDaemon.Power',
    '/org/gnome/SettingsDaemon/Power'
);
log('Brightness: ' + screenProxy.Brightness + '%')

Output:

Brightness: 28%

So this proxy works as expected.

The code for the UPower interface, using the same approach:

const DBusUPowerInterface = `<node>
    <interface name="org.freedesktop.UPower">
        <method name="EnumerateDevices">
            <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
            <arg type="ao" name="devices" direction="out"/>
        </method>
        <method name="GetDisplayDevice">
            <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
            <arg type="o" name="device" direction="out"/>
        </method>
        <method name="GetCriticalAction">
            <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
            <arg type="s" name="action" direction="out"/>
        </method>
        <signal name="DeviceAdded">
            <arg type="o" name="device"/>
        </signal>
        <signal name="DeviceRemoved">
            <arg type="o" name="device"/>
        </signal>
        <property type="s" name="DaemonVersion" access="read"/>
        <property type="b" name="OnBattery" access="read"/>
        <property type="b" name="LidIsClosed" access="read"/>
        <property type="b" name="LidIsPresent" access="read"/>
    </interface>
</node>`;
const DBusUPowerProxyClass = Gio.DBusProxy.makeProxyWrapper(
    DBusUPowerInterface
);
let uPowerProxy = new DBusUPowerProxyClass(
    Gio.DBus.session,
    'org.freedesktop.UPower',
    '/org/freedesktop/UPower'
)
log('OnBattery: ' + uPowerProxy.OnBattery)
uPowerProxy.EnumerateDevicesSync(); // throws

Output:

OnBattery: null
JS ERROR: Extension example3@example.com: Gio.DBusError: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name org.freedesktop.UPower was not provided by any .service files
_proxyInvoker@resource:///org/gnome/gjs/modules/core/overrides/Gio.js:122:46
_makeProxyMethod/<@resource:///org/gnome/gjs/modules/core/overrides/Gio.js:147:30
disable@/home/chillinr/.local/share/gnome-shell/extensions/example3@example.com/extension.js:251:17
_callExtensionDisable@resource:///org/gnome/shell/ui/extensionSystem.js:109:32
_onEnabledExtensionsChanged/<@resource:///org/gnome/shell/ui/extensionSystem.js:504:45
_onEnabledExtensionsChanged@resource:///org/gnome/shell/ui/extensionSystem.js:504:24

Here you are passing the session bus singleton, instead of the system bus. You should pass Gio.DBus.system here instead and that should work.

That solved it, thank you!

Helped me understand the meaning of that parameter as well.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.