Search code examples
qtpython-3.xdbuspyqt5avahi

Using Avahi ServiceBrowser with (PyQt5) QtDbus and connected slots are not called


I'm having a problem using the QtDbus in PyQt5. What I would like to do is discover a certain Avahi-/Zeroconf service type "_mumble._tcp". When I start my script I can see the signals being emitted in dbus-monitor --system when I start/stop the service:

signal sender=:1.138 -> dest=:1.273 serial=1413 path=/Client37/ServiceBrowser1; interface=org.freedesktop.Avahi.ServiceBrowser; member=ItemNew
   int32 5
   int32 0
   string "hetzner"
   string "_mumble._tcp"
   string "local"
   uint32 4

This is my sample code. It does work if I watch for other signals that are broadcasted, but it does not work for discovering services through Avahi using the created ServiceBrowser, i.e. it does not trigger on "ItemNew" emitted by the ServiceBrowser.

#!/usr/bin/python3

import sys

from PyQt5.QtCore import QObject, QVariant, pyqtSlot
from PyQt5.QtWidgets import QApplication
from PyQt5.QtDBus import QDBusConnection, QDBusInterface


class ServiceDiscoverer(QObject):

    def __init__(self):
        super(ServiceDiscoverer, self).__init__()
        bus = QDBusConnection.systemBus()
        server = QDBusInterface(
            'org.freedesktop.Avahi',
            '/',
            'org.freedesktop.Avahi.Server',
            bus
        )
        flags = QVariant(0)
        flags.convert(QVariant.UInt)
        browser_path = server.call(
            'ServiceBrowserNew',
            -1,  # Interface
            -1,  # Protocol -1 = both, 0 = ipv4, 1 = ipv6
            '_mumble._tcp',
            '', # Domain, default to .local
            flags
        )
        bus.connect(
            'org.freedesktop.Avahi',
            browser_path.arguments()[0],
            'org.freedesktop.Avahi.ServiceBrowser',
            'ItemNew',
            self.onServerAdd
        )

    @pyqtSlot(int, int, str, str, str, int)
    def onServerAdd(self, interface, protocol, key, _type, domain, flags):
        print("Avahi peer added:")
        print(" + Interface: %s" % interface)
        print(" + Protocol: %s" % protocol)
        print(" + Key: %s" % key)
        print(" + Type: %s" % _type)
        print(" + Domain: %s" % domain)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    discoverer = ServiceDiscoverer()
    sys.exit(app.exec_())

I guess there is something wrong with the way I call bus.connect(). Does anyone have a suggestion on how to catch the signals?


Solution

  • Qt is not finding your slot properly. You need to redecorate your slot -- what you receive (via DBUS) is not a function call with 6 parameters, it's a single QDBusMessage. Try this:

    ...
        @pyqtSlot(QDBusMessage)
        def onServerAdd (self, msg):
            print("Avahi peer added:")
            print(" + Interface: %s" % msg.arguments()[0])
            print(" + Protocol: %s" % msg.arguments()[1])
            print(" + Key: %s" % msg.arguments()[2])
            print(" + Type: %s" % msg.arguments()[3])
            print(" + Domain: %s" % msg.arguments()[4])
    ...