To expose an interface on the D-Bus, you must subclass ServiceInterface and define your members using specific decorators. Once defined, you use MessageBus.export() to make the interface available at a specific object path on a connected bus.
Core Components
ServiceInterface: The base class for all exported services. You must call super().__init__('interface.name') in your constructor.@method(): Defines a D-Bus method. Parameters and return values must be annotated with DBus type signature strings (e.g., 'i' for integer, 's' for string). If using aio.MessageBus, methods can be coroutines.@dbus_property(): Defines a D-Bus property getter. Use the standard Python @<property_name>.setter syntax to define a setter. Property getters/setters can be coroutines in aio.MessageBus.@signal(): Defines a D-Bus signal. The value returned by the decorated method is broadcast to listeners. If the signal has multiple arguments, return them as a list.DBusError: You can raise DBusError within methods or properties to send detailed error information back to the D-Bus client.
Requesting a Well-Known Name
If you want clients to find your service using a predictable name rather than a connection-specific one, call MessageBus.request_name('your.well-known.name') after connecting.
from dbus_next.aio import MessageBus
from dbus_next.service import ServiceInterface, method, dbus_property, signal
class ExampleInterface(ServiceInterface):
def __init__(self):
super().__init__('com.example.SampleInterface0')
self._bar = 105
@method()
def Frobate(self, foo: 'i', bar: 's') -> 'a{us}':
return {1: 'one', 2: 'two'}
@dbus_property()
def Bar(self) -> 'y':
return self._bar
@Bar.setter
def Bar(self, val: 'y'):
self._bar = val
@signal()
def Changed(self) -> 'b':
return True
async def main():
bus = await MessageBus().connect()
interface = ExampleInterface()
bus.export('/com/example/sample0', interface)
await bus.request_name('com.example.name')
await bus.wait_for_disconnect()