[prev in list] [next in list] [prev in thread] [next in thread] 

List:       pykde
Subject:    QLowEnergyService discoverDetails() silent crash on Windows 11
From:       Benjamin Griffiths <ben () familygriffiths ! me ! uk>
Date:       2024-05-14 15:45:04
Message-ID: 30235444.199970.1715701504726 () email ! ionos ! co ! uk
[Download RAW message or body]

[Attachment #2 (unknown)]

<!doctype html>
<html>
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 </head>
 <body>
  <div class="default-style">
    Hi there,
  </div>
  <div class="default-style">
    &nbsp;
  </div>
  <div class="default-style">
    The <strong>discoverDetails()</strong> function call on a \
<strong>QLowEnergyService</strong> object causes my application to crash on Windows \
11, it works fine on Windows 10 however.  </div>
  <div class="default-style">
    &nbsp;
  </div>
  <div class="default-style">
    It seems this issue has been around for a few years, and is related to PyQt/Qt \
for Python:  </div>
  <div class="default-style">
    (Apologies in advance if this issue has already been raised on this mailing list)
  </div>
  <div class="default-style">
    &nbsp;
  </div>
  <div class="default-style"> <a \
href="https://forum.qt.io/topic/146796/qtbluetooth-crashes-at-discoverdetails-on-win11 \
">https://forum.qt.io/topic/146796/qtbluetooth-crashes-at-discoverdetails-on-win11</a>
  </div>
  <div class="default-style"> <a \
href="https://bugreports.qt.io/browse/QTBUG-109510">https://bugreports.qt.io/browse/QTBUG-109510</a>
  </div>
  <div class="default-style">
    &nbsp;
  </div>
  <div class="default-style">
    I have attached a minimal reproducable example that displays a list of discovered \
BLE devices. Click on a device and then click connect. When the device is connected \
and a service is discovered, the discoverDetails() function call on line 78 causes \
the crash.  </div>
  <div class="default-style">
    &nbsp;
  </div>
  <div class="default-style">
    Any support would be greatly appreciated.
  </div>
  <div class="default-style">
    &nbsp;
  </div>
  <div class="default-style">
    Many thanks,
  </div>
  <div class="default-style">
    &nbsp;
  </div>
  <div class="default-style">
    Ben
  </div>
  <div class="default-style">
    &nbsp;
  </div>
  <div class="default-style">
    &nbsp;
  </div>
 </body>
</html>


["ble_discover_details_test.py" (text/x-python)]

import sys

from PyQt6.QtBluetooth import (
    QBluetoothDeviceDiscoveryAgent,
    QBluetoothDeviceInfo,
    QBluetoothUuid,
    QLowEnergyController,
)
from PyQt6.QtCore import Qt, pyqtSlot
from PyQt6.QtGui import QStandardItem, QStandardItemModel
from PyQt6.QtWidgets import (
    QApplication,
    QListView,
    QMainWindow,
    QPushButton,
    QVBoxLayout,
    QWidget,
)


class MainWindow(QMainWindow):
    def __init__(self) -> None:
        QMainWindow.__init__(self)
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        self.main_layout = QVBoxLayout(self.central_widget)

        self.model = QStandardItemModel()
        self.view = QListView()
        self.view.setModel(self.model)
        self.main_layout.addWidget(self.view)

        self.connect_btn = QPushButton("Connect")
        self.connect_btn.clicked.connect(self.connect)
        self.main_layout.addWidget(self.connect_btn)

        self.discovery_agent = QBluetoothDeviceDiscoveryAgent()
        self.discovery_agent.deviceDiscovered.connect(self.on_device_discovered)
        self.discovery_agent.start(
            QBluetoothDeviceDiscoveryAgent.DiscoveryMethod.LowEnergyMethod
        )

        self.show()

    def connect(self) -> None:
        item = self.model.itemFromIndex(self.view.currentIndex())

        if not item:
            print("Device not selected")
            return

        device: QBluetoothDeviceInfo = item.data(Qt.ItemDataRole.UserRole)
        print(f"Connecting to {device.name()} [{device.address().toString()}]")

        self.ble_controller = QLowEnergyController.createCentral(device)
        self.ble_controller.connected.connect(self.ble_controller.discoverServices)
        self.ble_controller.serviceDiscovered.connect(self.on_service_discovered)
        self.ble_controller.connectToDevice()

    @pyqtSlot(QBluetoothDeviceInfo)
    def on_device_discovered(self, device: QBluetoothDeviceInfo):
        """ """
        item = QStandardItem()
        item.setData(
            f"{device.name()} [{device.address().toString()}]",
            Qt.ItemDataRole.DisplayRole,
        )
        item.setData(device, Qt.ItemDataRole.UserRole)
        self.model.appendRow([item])

    @pyqtSlot(QBluetoothUuid)
    def on_service_discovered(self, uuid: QBluetoothUuid) -> None:
        """ """
        service = self.ble_controller.createServiceObject(uuid)
        print(
            f"Service discovered: {service.serviceName()} [{service.serviceUuid().toString()}]"
        )
        service.discoverDetails()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    main_window = MainWindow()
    sys.exit(app.exec())


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic