cockpit.js: DBus Clientcockpit.js: DBus Client — DBus API communication |
Synopsis
Cockpit allows access to DBus services via this API.
DBus Types
DBus values are represented as javascript values and objects as follows:
|
Javascript number. |
|
Javascript boolean. |
|
Javascript number. |
|
Javascript number. |
|
Javascript number. |
|
Javascript number. |
|
Javascript number. |
|
Javascript number. |
|
Javascript number. |
|
Javascript string. |
|
Javascript string. |
|
Javascript string. |
|
A string containing base64 encoded data. |
|
A javascript plain object with the keys as property names. |
|
A javascript plain object each key JSON encoded into a string property name. |
|
A javascript array. |
|
A javascript plain object with the |
|
A javascript object that describes a cockpit channel which represents the
passed file descriptor. The |
cockpit.dbus()
client = cockpit.dbus(name, [options])
Create a DBus client for the given bus name
(eg: service name). Use the
following functions to make DBus method calls, watch for events, etc. The optional
options
argument is a javascript plain object, and may include:
|
The DBus bus to connect to. Specifying |
|
The host to open the channel to. If an alternate user or port is
required it can be specified as |
|
Set to Set to |
|
It is valid for a DBus service to exit, and be restarted in such a
way that clients continue to talk to it across the restart. Some services are not
written with this in mind. If the |
If the name
argument is null, and no options other than "bus"
are specified, then a shared DBus client
is created. When using such a client
with a DBus bus, a "name"
option must be specified on various other methods
in order to specify which client to talk to.
client.wait()
promise = client.wait([callback])
Returns a promise
that is ready when the client is ready, or fails if the
client closes. If a callback
is specified, it is attached to the promise.
client.close()
client.close([problem])
Close the DBus client. If problem
is specified it should be a
problem code string.
client.onclose
client.addEventListener("close", options => { ... })
An event triggered when the DBus client closes. This can happen either because client.close() function was called, or the DBus service went away, or some other problem or disconnection.
The options
will contain various close information, including a
"problem"
field which will be set if the channel was closed because
of a problem.
client.onowner
client.addEventListener("owner", (event, owner) => { ... })
An event triggered when the owner of the DBus name changes. The owner value will be the id of the name owner on the bus or null if the name is unowned. The absence of an owner should not be treated as a disconnection. However this makes it possible to take some action based on the actual status of the service, for example disconnecting a pending signal handler.
client.options
Set to the options used when creating the client. Will not change for the life of the client.
client.unique_name
The unique DBus name of the client. Initially null, and becomes valid once the the client is ready.
client.proxy()
proxy = client.proxy([interface, path], [options])
Create proxy javascript object for a DBus interface
. At the
specified DBus object path
. The proxy will have
properties, methods and signals from to the DBus interface, and allows for
natural interaction. If no interface
is specified then the DBus
bus name of the client is used. If no path
is specified, then
the DBus name of the client is converted to a path.
If creating lots of proxies for a given interface
it is more
efficient to use the
client.proxies()
function.
The proxy is loaded when the
proxy.valid
field is
true
, and it is set to false
if the underlying
interface
and/or path
don't or no longer exist, or
the client
has closed. You can wait for proxy to become valid
by passing a callback to its
proxy.wait()
function.
The proxy.onchanged
event will also fire when the proxy becomes valid or invalid. DBus properties and
methods on the proxy are not defined until the proxy becomes valid.
value = proxy.Prop1 proxy.WritableProp = value
All DBus properties on the interface
that start with an upper case
letter (as is convention) will be automatically defined on this proxy, and will update
their values as the DBus property values change. In addition the
proxy.onchanged
event
will fire every time the properties change.
If you assign a value to a writable property on the proxy, the proxy will try to set
that property on the DBus interface
at path
. The actual proxy
property value will not update until the DBus service has notified the proxy of the
change. If setting a property fails a warning will be logged. In order to have more
reliable setting of properties, or track when they have been set, or if setting fails,
use the client.call()
directly.
It should be noted that DBus service implementations may also be inconsistent in
their behavior when setting a property fails.
You can access the raw property data using the
proxy.data
field, including
data for properties that do not start with an upper case letter.
proxy.Method(arg1, arg2) .then((retval1, retval2) => { ... }) .catch(ex => { ... });
All DBus methods on the interface
that start with an upper case
letter (as is convention) will be automatically defined on this proxy. These
methods are called with arguments as normal javascript arguments. A
Promise
that will complete successfully when the method returns, or fail if an error occurs.
The return values from the DBus method will be passed to the then
handler
function directly.
Methods that do not start with an upper case letter can be invoked by using
the usual proxy.call()
directly.
proxy.addEventListener("Signal", (event, arg1, arg2) => { ... });
All DBus signals on the interface
that start with an upper case
letter (as is convention) will be automatically emit events on this proxy. These
events will contain the signal arguments after the standard event
argument.
Signals that do not start with an upper case letter can be subscribed to by
using proxy.onsignal
directly.
Usually a proxy asks the client
to watch and notify it of changes
to the relevant object or path. You can pass an options
argument with
the watch
field set to false
to prevent this.
proxy.valid
Set to true
when the proxy's DBus interface is present at its
DBus path, and all information for the proxy has loaded. Is set to false
while loading, and after the proxy no longer refers a DBus interface and path.
Also set to false
if the client
closes.
Use the by proxy.wait()
function to wait for a proxy to load. The
proxy.onchanged
event will also be emitted when the proxy becomes valid or invalid. DBus properties and
methods on the proxy are not defined until the proxy becomes valid.
proxy.data
A plain javascript object containing all the raw property data that this
proxy has loaded. This will be updated automatically as the proxy is notified
of property changes from the DBus service. The
proxy.onchanged
event will be emitted when it changes.
proxy.call()
invocation = proxy.call(method, args, [options])
Make a DBus method call on this proxy.
For DBus methods that start with an upper case letter, is usually more convenient to call the method directly on the proxy. However if methods that do not follow the usual DBus convention, or specify additional options, or the caller cannot be sure that the method actually exists, you can use this method.
This function also works on proxies that have are still loading and have not become valid yet.
The method
should be a DBus method name, and the args
should be an array of arguments to pass to the method. The options
are described elsewhere.
The returned value is identical to the one returned from client.call(). It is a Promise that will complete successfully when the method returns, or fail if an error occurs.
proxy.wait()
promise = proxy.wait() proxy.wait(() => { ... });
Wait for a proxy to finish loading. This function returns a promise. If a callback function
is passed as an argument then that function will be invoked when the proxy is ready.
If this method is called after a proxy has already loaded, then the promise will be
resolved immediately, and any callback will be invoked immediately. Use the promise or
proxy.valid
to determine whether the proxy is valid.
proxy.onchanged
proxy.addEventListener("changed", (event, data) => { ... });
This event is emitted when the proxy's properties change.
The data
has the following form, and will only include
properties that have changed:
{ "Prop1": "value", "Prop2": 5 }
proxy.onsignal
proxy.addEventListener("signal", (event, name, args) => { ... });
This event is emitted when the proxy's emits an event.
For most events, that have names which start with an upper case letter, you can just connect to that event as a signal directly. However if you wish to be notified when any signal is emitted, or for signals that do not follow the usual DBus convention, you can connect to this event.
The name
is the DBus signal name, and the args
is an array
of arguments that were emitted with the signal.
client.proxies()
proxies = client.proxies([interface], [path_namespace], [options])
Create proxy javascript objects for
a DBus interfaces. The proxies will have properties, methods and signals from
the DBus interface
, and allow for natural interaction. If no
interface
is specified then the DBus bus name of the client is used.
If no path_namespace
is provided then "/"
will be used.
Proxies will be automatically created for instances of the
interface
available at the DBus service. The optional
path_namespace
argument can be used to restrict the proxies for
instances that have DBus paths which have the namespace path prefix.
proxy1 = proxies["/dbus/path1"]; proxy2 = proxies["/dbus/path2"]; for (proxy in proxies) { ... }
The returned proxies
object will is used as a dictionary,
and will have values containing proxies for DBus interface instances, with the
keys being the DBus paths of those instances. It is possible to enumerate over
the returned proxies
.
Proxies will be automatically added and removed from the proxies
object as they appear and disappear in the service. The
proxies.onadded
and proxies.onremoved
events will be emitted. DBus services may not support notifications of paths
disappearing.
Use the proxies.wait()
function to be notified when the initial
set of proxies has been populated.
Usually a proxies ask the client
to watch and be notified of changes
to the relevant object or path. You can pass an options
argument with
the watch
field set to false
to prevent this.
proxies.wait()
promise = proxies.wait() proxies.wait(() => { ... });
Wait for a proxies
object to populate its initial set of proxies.
This function returns a promise. If a callback function is passed as an argument then
that function will be invoked when the proxies are ready. If this method is called after
the proxies have populated, then the promise will be resolved immediately, and any callback
will be invoked immediately.
proxies.path_namespace
Set to the DBus path namespace used which the proxies must have as a DBus path prefix. Will not change.
proxies.onadded
proxies.addEventListener("added", (event, proxy) => { ... })
This event is emitted when a proxy is added to the proxies
object.
The proxy will already have loaded.
proxies.onchanged
proxies.addEventListener("changed", (event, proxy) => { ... })
This event is emitted when one of the proxy in the proxies
object
changes its properties.
proxies.onremoved
proxies.addEventListener("removed", (event, proxy) => { ... })
This event is emitted when a proxy is removed to the proxies
object.
client.call()
invocation = client.call(path, interface, method, args, [options])
Make a DBus method call.
The path
is the DBus object path to make
the call on, interface
is the DBus interface for the method and
method
is the name of the method to call. The args
is an
array of arguments to pass to the method, each of which must be appropriate for the
expected DBus type of that argument. The
args
may be null
if no arguments are to be sent.
The returned value is a Promise that will complete successfully when the method returns, or fail if an error occurs.
If options
is specified it should be a plain javascript object,
which may contain the following properties:
|
A string containing DBus message flags. The character |
|
A valid DBus type signature to use when calling the method. In the absence of this, the DBus service will be introspected (and the result cached) to ask what the method type signature is. |
|
The timeout of the call in milliseconds. The call will fail with
the |
invocation.then()
invocation.then((args, options) => { ... })
This is a standard Promise method. It sets up a handler to be called when the DBus method call finishes successfully.
The args
argument is an array of return values from the DBus method.
Each of them will be converted to an appropriate
javascript type.
The options
argument may contain additional information about the
reply. If the type
option was specified when performing the method call,
then the options
in the reply here will also contain a type
field containing the DBus type signature of the output. If the flags
option
was specified when performing the call then the options
in the reply here
will contain message flags. Possible out message flags are:
|
A big endian message. |
|
A little endian message. |
invocation.catch()
invocation.catch(exception => { ... })
This is a standard Promise method. It sets up a handler to be called when the DBus method call fails.
The exception
object passed to the handler can have the
following properties:
|
A problem code string when
a problem occurred starting or communicating with the DBus service. This is
|
|
The DBus error name. This will be |
|
A DBus error message. This will be |
client.subscribe()
subscription = client.subscribe(match, (path, interface, signal, args) => { ... })
Subscribe to signals. The match
argument is a javascript plain object which
defines what signals to subscribe to. Each property in the match
argument restricts
signals subscribed to. If a property is not present then it is treated as a wildcard, matching
anything. If an empty object is specified as match
then all signals will be
subscribed to. The match
argument may contain the following properties:
|
A DBus interface to match. |
|
A DBus object path to match. May not be used together with the
|
|
A DBus object path prefix to match. Any paths in the hierarchy below this
top path will match. May not be used together with the |
|
The DBus signal name to match. |
|
Matches the first argument of a DBus message, which must be a string. |
The handler passed as the second argument will be invoked when the signal is received.
A subscription
is returned which can be used to remove the subscription by
calling its subscription.remove()
method.
It is not a problem to subscribe to the same signals more than once, with identical
or slightly different match
arguments.
client.watch()
watch = client.watch(path) watch = client.watch({ "path_namespace": path_namespace, "interface": interface })
Watch for property and interface changes on the given DBus object
path
DBus path_namespace
. If interface
is
specified only properties on that DBus interface will be watched.
The client.proxy()
and
client.proxies()
functions and
the objects they return are high level wrappers around client.watch()
.
The property and interface changes will be available in raw form on the
client.onnotify
event.
Property and interface changes that are caused by a method call or signal will show up before that method call reply is received, or signal event is triggered. It should be possible to rely on this guarantee, unless the DBus service in question behaves incorrectly. Internally these watches work well with code that implements the ObjectManager portion of the DBus specification. If no ObjectManager implementation is available, the watch falls back to using DBus Introspection along with the usual PropertiesChanged signal. If the DBus service implements none of these, or implements them in an inconsistent manner, then this function will provide inconsistent or unexpected results.
The parameter is either a DBus path
or a plain javascript object
with zero or more of the following fields. If an empty javascript object is used as
an argument, then all paths, interfaces and properties will be watched.
|
Watch properties on this DBus interface. |
|
Watch interfaces and properties at this DBus path. May not be
used together with the |
|
Watch interfaces and properties under this DBus path. It should
be a valid DBus object path, that is, it should have no trailing slash.
If an ObjectManager implementation is available at this interface, then it
is used. May not be used together with the |
The returned value is a
Promise
that will complete successfully when the watch has populated its initial set of properties
and interfaces, and these have been notified via
client.onnotify
.
A watch can be removed by calling the
watch.remove()
method on
the returned value. If identical watches are added more than once, then they must
also be removed the same number of times before the removal takes effect.
watch.then()
watch.then(() => { ... })
This is a standard Promise method. It sets up a handler to be called when the watch has populated its initial properties and interfaces.
watch.catch()
watch.catch(ex => { ... })
This is a standard Promise method. It sets up a handler to be called if the watch fails to populate its initial properties and interfaces. Note that a watch will only fail if the DBus client closes or is somehow disconnected. It does not fail in the case of missing interfaces or properties.
watch.remove()
watch.remove()
Remove the watch. This may not have any immediate effect if other watches are in place. In particular, if identical watches are added more than once, then they must also be removed the same number of times before the removal takes effect.
client.onnotify
client.addEventListener("notify", data => { ... })
An event triggered when watched properties or interfaces change.
The client.proxy()
and
client.proxies()
functions and
the objects they return are high level wrappers around the data
provided
by this event.
The data
has the following form:
{ "/path1": { "org.Interface1": { "Prop1": "value", "Prop2": 5 }, "org.Interface2": null } }
Multiple paths may be present, each of which may have multiple interfaces, each
of which may have multiple properties. The first time a given path and interface is
emitted from this signal, it will have all its properties and interfaces. Thereafter
only changes are noted. If an interface is set to null
, then that
interface has disappeared.
client.notify()
client.notify(data)
Emits a synthetic notify
event.
The data
argument should follow the same layout as
described for the notify
event.
client.onmeta
client.onmeta = (ev, data) => { ... }
An event triggered when the meta data about watched interfaces is loaded.
The client.proxy()
and
client.proxies()
functions and
the objects they return are high level wrappers around the data
provided
by this event.
The data
has the following form:
{ "org.Interface": { "methods": { "Method1": { "in": [ "s", "v" ], "out": [ "i" ] }, "Method2": { } }, "signals": { "Signal": { "in": [ "b", "s" ] } }, "properties": { "Prop1": { "flags": "rw", "type": "s" }, "Prop2": { "flags": "r", "type": "b" } } } }
Multiple interfaces may be present, each of which may have methods and properties.
This is emitted before the first client.onnotify
event for the relevant interface.
client.meta()
client.meta(data)
Populate DBus introspection metadata about DBus interfaces. Usually this metadata
is automatically introspected from the DBus services called by the client
,
but in certain cases it is useful to populate this info from javascript code. One such
case is when exporting a DBus service from javascript.
The client.onmeta
event will
be emitted by this method call. It's documentation includes information about the form
of the data
.
client.publish()
published = client.publish(path, interface, object, [options])
Publish a DBus interface
at the specified object path
.
Methods on the Javascript object
will be invoked when DBus methods on the
specified interface
are invoked by callers.
The meta data for the DBus interface must have been populated using the
client.meta()
function. The
returned published
object is a promise object. It will resolve when the
DBus interface has been published on the bus. It is not an error to publish the same
interface and path repeatedly: Previously published objects at the interface and
path are replaced by those published later.
published.remove()
published.remove()
Un-publishes a DBus interface at an object path. This method can be invoked
on the published
result returned from the
client.publish()
function.