【问题标题】:How to build a BLE advertisement with the Bluez DBus API and Qt DBus如何使用 Bluez DBus API 和 Qt DBus 构建 BLE 广告
【发布时间】:2021-10-09 04:43:11
【问题描述】:

我正在尝试弄清楚 Bluez DBus API,但我无法理解其中的一些概念。

我见过的最彻底的 Bluez 示例都使用了 Python 的 dbus-python 库。例如,this python script 演示了如何创建 BLE 广告。很多内容都在Advertisement 类中,它扩展了dbus.service.ObjectAdvertisement 类实现了一个GetAll 方法(来自org.freedesktop.DBus.Properties 接口)和一个Release 方法(来自org.bluez.LEAdvertisement1 接口)。为了注册该广告,它从org.bluez.LEAdvertisingManager1 接口调用RegisterAdvertisement

我被绊倒了,因为我更习惯于 Qt DBus,所以我在想如果使用 PyQt 而不是 dbus-python 完成同样的事情会是什么样子。我认为最大的障碍是:

  1. 我不知道示例中的 Advertisement 类如何适合 Qt Dbus 的接口/适配器模型
  2. 在示例中,Advertisement 类从两个接口实现方法。我找到了this discussion,这意味着它可以做到,但我认为我没有完全理解它的机制

所以,总而言之,如果我想用 Qt DBus 重新实现这个示例,Advertisement 类会是什么样子?它会扩展QDBusAbstractAdaptor 还是QDBusAbstractInterface?它会包含其中一种(或两种)吗?还是我完全错过了其他东西?

编辑:

根据来自@ukBaz 的一些信息,我挖掘得更深一些,并尝试了更多的东西,但到目前为止我还是一无所获。作为参考,我有两个脚本in this github repostock-example.py 脚本直接拉到from the Bluez source treeqt-example.py 脚本是我尝试“翻译”它以使用 QtDBus。

我发现股票脚本和 Qt 脚本都可以正常工作,我可以在我的手机上看到它们在 nRF Connect 上做广告。但是,Qt 应用中对RegisterAdvertisement 的调用总是超时:

class BleAdManager(QDBusAbstractInterface):
    def __init__(self, dbus_obj_path, parent=None):
        self._ble_adapter_dbus_path = dbus_obj_path
        self._dbus_system_bus = QDBusConnection.systemBus()

        super().__init__("org.bluez",
                         self._ble_adapter_dbus_path,
                         "org.bluez.LEAdvertisingManager1",
                         self._dbus_system_bus,
                         parent)

    def RegisterAdvertisement(self, ad_path):
        print("Registering {0}...".format(ad_path))
        msg = self.call('RegisterAdvertisement', QDBusObjectPath(ad_path), {})
        print("Call returned.")
        reply = QDBusReply(msg)

        if reply.isValid():
            print("Valid")
            return reply.value()
        else:
            print(reply.error().message())
            return None

当我运行它时,它会在 QDBusAbstractInterface.call() 上挂起大约 25 秒,然后吐出

Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.

由于股票脚本有效,因此不会是安全策略问题。远程应用程序是否应该给我回复RegisterAdvertisement?如果不是,我如何使用 QtDBus 优雅地处理它(即,没有它挂起并给我一个错误)?如果是这样,为什么我得不到响应,我应该如何尝试调试?

【问题讨论】:

    标签: pyqt5 qt5 dbus bluez


    【解决方案1】:

    BlueZ Advertising D-Bus API 的文档位于:

    https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/advertising-api.txt

    org.bluez.LEAdvertisement1 是发布到 SystemBus 的 D-Bus 服务,负责为广告提供数据。此发布的服务可以位于任何 D-Bus 对象路径。

    org.bluez.LEAdvertisingManager1 是一个 D-Bus 客户端,它通过 RegisterAdvertisement 通知 BlueZ org.bluez.LEAdvertisement1 D-Bus 对象路径是什么。

    我没有在 PyQt 中使用过 D-Bus,所以我去寻找一个示例,发现以下似乎使用了 DBus-Python:

    https://wiki.qt.io/Qt_for_Python_DBusIntegration

    作为旁注https://www.freedesktop.org/wiki/Software/DBusBindings/ 确实说了以下内容:

    新应用程序应使用 pydbus、txdbus 或 GDBus/QtDBus 绑定

    有一个使用pydbus创建广告的例子:

    https://raspberrypi.stackexchange.com/a/114130/121848

    【讨论】:

    • 谢谢,@ukBaz!我认为我的一些问题 Qt 特有的。我很难理解“D-Bus 服务”和“D-Bus 客户端”如何映射到 Qt 的适配器和接口。基于此,似乎我需要一个适配器类来在系统总线上公开我的广告对象,然后我需要一个接口类来与广告管理器对话。但是,适配器似乎还需要实现org.freedesktop.DBus.Propertiesorg.bluez.LEAdvertisement1 接口。这是真的吗,如果是的话,一个类可以继承或包含一个适配器两个接口吗?
    猜你喜欢
    • 2020-11-07
    • 2016-08-25
    • 2021-06-02
    • 2017-09-14
    • 2017-05-17
    • 2014-02-04
    • 2015-10-01
    • 2012-11-29
    • 2019-12-21
    相关资源
    最近更新 更多