首页 > 解决方案 > 使用 PyQt5.QtBluetooth 扫描蓝牙设备

问题描述

我正在尝试使用 PyQt5 (5.11.3) 来使用 QtBluetooth API 来扫描蓝牙设备。

设备发现 API 被列为支持我的平台 (macOS 10.14.2) 并且我已经能够执行其他与蓝牙相关的事情,例如获取主机控制器的地址和连接设备的列表地址。

每当检测到新设备、发生错误或扫描完成时,这是一个设置回调(Qt 用语中的插槽?)的尝试。此外,计时器会打印出扫描当前是否处于活动状态,以及到目前为止找到的所有设备的列表。

虽然我的错误回调从未被触发,并且计时器总是打印出扫描处于活动状态,并且我的系统日志显示蓝牙控制器处于扫描模式,但我没有看到任何设备。我知道我应该至少看到一些。

#!/usr/bin/env python
import signal
import sys

from PyQt5 import QtBluetooth as QtBt
from PyQt5 import QtCore


class Application(QtCore.QCoreApplication):
  def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.scan_for_devices()
    self.exec()

  def display_status(self):
    print(self.agent.isActive(), self.agent.discoveredDevices())

  def foo(self, *args, **kwargs):
    print('foo', args, kwargs)

  def scan_for_devices(self):
    self.agent = QtBt.QBluetoothDeviceDiscoveryAgent(self)
    self.agent.deviceDiscovered.connect(self.foo)
    self.agent.finished.connect(self.foo)
    self.agent.error.connect(self.foo)
    self.agent.setLowEnergyDiscoveryTimeout(1000)

    timer = QtCore.QTimer(self.agent)
    timer.start(500)
    timer.timeout.connect(self.display_status)

    self.agent.start()


if __name__ == '__main__':
  import sys
  app = Application(sys.argv)

不过,C++ 示例确实适用于我的系统:http: //doc.qt.io/qt-5/qtbluetooth-btscanner-example.html

标签: macosbluetoothqt5pyqt5

解决方案


事实证明,这是 macOS 上 Qt 的一个已知但(似乎?)未记录的问题。背景是QTBUG-46625。通常,QtCoreApplicationmacOS 上的 a 使用 Qt 自己的事件循环。但是 macOS 上的蓝牙框架需要 CoreFoundation 事件循环,可以在QtCoreApplication创建实例之前像这样激活它:

if sys.platform == 'darwin':
    os.environ['QT_EVENT_DISPATCHER_CORE_FOUNDATION'] = '1'

或者,您可以QtWidget.QApplication改为子类。

不幸的是,这会导致 Python 进程出现停靠图标。我还没想好怎么隐藏。


推荐阅读