Thursday, July 6, 2017
Dbus Tutorial Create a service
Dbus Tutorial Create a service
Introduction
Introspection
Network Manager
Create a Service
GObject Introspection
A dbus service is usable by other applications. It listens for input from another process, and responds with output.
When you create a service, you need to make a couple decisions about when you want to start your service, and when you want to terminate it...
Start: Startup, login, first-use, on-demand?
End: Each time? logout? Shutdown?
In other words, is this a single-use service, or a forever-running daemon?
Happily, the actual code differences are trivial. Dbus itself can launch a service thats not running yet. (Indeed, a lot of startup and login depends on that!)
Example Dbus Service in Python3
Heres an example of a self-contained daemon written in Python 3 (source). Its introspectable and executable from dbus-send or d-feet. When called, it simply returns a "Hello, World!" string.
It can be started by either dbus or another process (like Upstart or a script). Since it runs in an endless loop awaiting input, it will run until logout. It can also be manually terminated by uncommenting the
Gtk.main_quit()
command.#!/usr/bin/env/python3
# This file is /home/me/test-dbus.py
# Remember to make it executable if you want dbus to launch it
# It works with both Python2 and Python3
from gi.repository import Gtk
import dbus
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop
class MyDBUSService(dbus.service.Object):
def __init__(self):
bus_name = dbus.service.BusName(org.me.test, bus=dbus.SessionBus())
dbus.service.Object.__init__(self, bus_name, /org/me/test)
@dbus.service.method(org.me.test)
def hello(self):
#Gtk.main_quit() # Terminate after running. Daemons dont use this.
return "Hello,World!"
DBusGMainLoop(set_as_default=True)
myservice = MyDBUSService()
Gtk.main()
Daemon that runs all the time
Just run the script at startup (or login). Or send a dbus-send message to the service, and dbus will start it. It will be terminated as part of shutdown (or logout). While its running, its introspectable and visible from d-feet.
Dbus-initiated start
Add a .service file. This file simply tells dbus how to start the service.
Heres an example service file:
# Service file: /usr/share/dbus-1/services/test.service
[D-BUS Service]
Name=org.me.test
Exec="/home/me/test-dbus.py"
Dbus should automatically pick up the new service without need for any restart. Lets test if dbus discovered the service:
$ dbus-send --session --print-reply
--dest="org.freedesktop.DBus"
/org/freedesktop/DBus
org.freedesktop.DBus.ListActivatableNames
| grep test
string "org.me.test"
The new service does not show up in d-feet until after it is run the first time, since before there is nothing to probe or introspect. But it does exist, and is findable and usable by other dbus-aware applications.
Lets try the new service:
$ dbus-send --session --print-reply
--dest="org.me.test" /org/me/test org.me.test.hello
method return sender=:1.239 -> dest=:1.236 reply_serial=2
string "Hello,World!"
$ dbus-send --session --print-reply
--dest="org.me.test" /org/me/test org.me.test.Frank
Error org.freedesktop.DBus.Error.UnknownMethod: Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/dbus/service.py", line 654, in _message_cb
(candidate_method, parent_method) = _method_lookup(self, method_name, interface_name)
File "/usr/lib/python3/dist-packages/dbus/service.py", line 246, in _method_lookup
raise UnknownMethodException(%s is not a valid method of interface %s % (method_name, dbus_interface))
dbus.exceptions.UnknownMethodException: org.freedesktop.DBus.Error.UnknownMethod: Unknown method: Frank is not a valid method of interface org.me.test
It worked! Dbus launches the script, waits for the service to come up, then asks the service for the appropriate method.Upon execution of the method, the waiting loop terminates, and the script finishes and shuts down.
As a test, you can see that hello is indeed a valid method and returns a valid response, while the invalid method Frank causes a not-found error.
Dbus-initiated stop
Dbus doesnt stop scripts or processes. But a script can stop itself.
In order to wait for input, python-dbus uses a
Gtk.main()
loop. In this case, simply uncomment the line Gtk.main_quit()
. When the method is called,the main()
loop gets terminated, and the script continues to the next loop or end.If you use on-demand starting and stopping, be aware that the service will exist, but will be visible in d-feet or introspectable only for the few seconds its actually running.
Obsolete: Before python included introspection, you needed to include an interface definition. But you dont need this anymore - introspection seems to have replaced it. Avoid confusion - some old tutorials out there still include it.
<?xml version="1.0" encoding="UTF-8"?>
<!-- /usr/share/dbus-1/interfaces/org.me.test.xml -->
<node name="/org/me/test">
<interface name="org.me.test">
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="server"/>
<method name="EchoString">
<arg type="s" name="original" direction="in" />
<arg type="s" name="echo" direction="out" />
</method>
<!-- Add more methods/signals if you want -->
</interface>
</node>
download more info
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment