A minimal dbus framework which auto-generates bindings for godbus based on the interface-definition-language qface.
qface
describes APIs based on known concepts such as modules, interfaces, properties, structs, signals and enums. Based on these definitions goqface
generates boiler-plate glue bindings for godbus, leaving developers with only business logic implementation.
There are four main components in goqface
architecture.
Interface
declares the methods, properties and signals as described in qfaceBase
implements the properties/signals of theInterface
and is to be embedded inImplementation
DBusAdapter
exports methods, properties and signals to bus fromservice process
DBusProxy
represents theDBusAdapter
on theclient process
Implementation
implements theInterface
methods
where only the last components needs to be implemented and reset are auto-generated.
The initialization sequence starts by DBusAdapter
export
ing an object to bus from service process
. Then on the client process
, given the bus name of service is known (achieved automatically by Object Management), DBusProxy
attempts to fetch all properties upon ConnectToRemoteObject
call. Afterward the status of the connection to the service can be checked by the conventional ready property.
On a successful connection the DBusProxy
is able to call DBusAdapter
methods and listen to its signals and in turn inform the registered observers
.
Properties are available as defined in qface interface both in DBusAdapter
and DBusProxy
.
DBusProxy
fetches all properties
(given a successful connection) on ConnectToRemoteObjec
method call. Properties are always in sync between DBusProxy
and DBusAdapter
by the mean of PropertiesChanged
signal.
Given a property is not defined readonly
in qface, its value might be changed by DBusProxy
. See Set Properties on how to optionally override the default behaviour of Base
.
ready
is a conventional auxiliary property to be checked to ensure that the connection to remote-object was successful and the remote-object DBusAdapter
is actually ready to handle method calls.
Remote method calls are initiated by DBusProxy
invoking the corresponding DBusAdapter
function. Beside normal code path exceptions can be handled as well.
Signals defined in qface interface may be invoked from DBusAdapter
by calling the corresponding function. In turn signals are received by the DBusProxy
side and registered Observers are informed.
Observers
watch signals on DBusProxy
as well as property changes on both DBusAdapter
and DBusProxy
. i.e Observers
are informed in goroutines if watched events emitted.
methods
could handle unexpected inputs and states by returning an optional dbus.Error
.
Override Set<Property>
functions of the Base
to verify values before assignment. Pass correct values to Set<Property>
of the Base
to ensure proper propagation to DBusAdapter
and block wrong ones with an error message.
func (c *Implemenation) Set<Property>(value <Property>Value) error {
if value is accepted {
return c.Base.SetCurrentContact(value)
} else {
return errors.New("Unexpected value!")
}
}
A python script is the code-generator for goqface. It is possible to integrate the code-generation in your go files by leveraging go tools.
Use import plus $GOPATH to locate the codegen.py
and pass the required arguments to the call.
Optionally use gofmt
to format the generated files.
import (
goqface "github.com/idleroamer/goqface/objectManager"
)
//go:generate python3 $GOPATH/pkg/mod/github.com/idleroamer/goqface@v<VERSION>/codegen.py --input <LIST_OF_INPUTS> --dependency [LIST_OF_DEPENDENCIES]
//go:generate gofmt -w <PATH_OF_GENERATED_FILES>
--input
list of all qface input files to generate bindings for.
--dependency
optional path to interdependencies
--output
optional output path of generated files otherwise module name will be used as path.
The goqface python dependency are defined in requirement.txt
file. These dependencies needs to be installed once but nevertheless you can integrate this step as well into go generate.
import (
goqface "github.com/idleroamer/goqface/objectManager"
)
//go:generate pip3 install -r $GOPATH/pkg/mod/github.com/idleroamer/goqface@v<VERSION>/requirements.txt
Modules may import other modules via import
keyword followed by the imported module name and version.
The goqface creates the necessary import annotation for each of input files so that it can be used in the client code. The annotations are stored in the .go.annotate
yaml file next to each .qface
.
NOTE: go module
should be initialized (go mod int
) where outputs are located for a proper import annotation.
Object management in goqface follows the dbus specification of org.freedesktop.DBus.ObjectManager.
The root object /
implements the ObjectManager
interface which can be used to query list of objects in this service.
Besides Object Manager
monitors all related objects on bus in order to figure out to which service a DBusProxy
needs to connect to. See also related services.
As long as prerequisite are in place this is a seamless operation.
Prerequisite
DBusAdapter
andDBusProxy
have the same interface name and object path (see dbus-definition)- Bus name of
DBusAdapter
is in expected format (see also related services) - Service of
DBusAdpater
has a valid object manager under the root object/
A predefined name pattern of bus name makes detection of related services possible. So that all related services and their objects life-cycle can be monitored.
NOTE: The "qface.registry." pattern is used in case "DBUS_SERVICE_NAME_PATTERN" environment variable not defined
Close
will end the DBusAdapter
service on bus.
Consequently ready
property of DBusProxy
will be set to false, given one rely on Object Management instead of setting service name explicitly.
DBusAdapter.Close()
There are some limitation with regards to qface: