1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
from PySide6.QtCore import QPoint, Qt, Slot
from PySide6.QtGui import QColor
from PySide6.QtWidgets import QDialog, QListWidgetItem, QMenu
from PySide6.QtBluetooth import (QBluetoothAddress, QBluetoothDeviceDiscoveryAgent,
QBluetoothDeviceInfo, QBluetoothLocalDevice)
from ui_device import Ui_DeviceDiscovery
from service import ServiceDiscoveryDialog
class DeviceDiscoveryDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self._local_device = QBluetoothLocalDevice()
self._ui = Ui_DeviceDiscovery()
self._ui.setupUi(self)
# In case of multiple Bluetooth adapters it is possible to set adapter
# which will be used. Example code:
#
# address = QBluetoothAddress("XX:XX:XX:XX:XX:XX")
# discoveryAgent = QBluetoothDeviceDiscoveryAgent(address)
self._discovery_agent = QBluetoothDeviceDiscoveryAgent()
self._ui.scan.clicked.connect(self.start_scan)
self._discovery_agent.deviceDiscovered.connect(self.add_device)
self._discovery_agent.finished.connect(self.scan_finished)
self._ui.list.itemActivated.connect(self.item_activated)
self._local_device.hostModeStateChanged.connect(self.host_mode_state_changed)
self.host_mode_state_changed(self._local_device.hostMode())
# add context menu for devices to be able to pair device
self._ui.list.setContextMenuPolicy(Qt.CustomContextMenu)
self._ui.list.customContextMenuRequested.connect(self.display_pairing_menu)
self._local_device.pairingFinished.connect(self.pairing_done)
@Slot(QBluetoothDeviceInfo)
def add_device(self, info):
a = info.address().toString()
label = f"{a} {info.name()}"
items = self._ui.list.findItems(label, Qt.MatchExactly)
if not items:
item = QListWidgetItem(label)
pairing_status = self._local_device.pairingStatus(info.address())
if (pairing_status == QBluetoothLocalDevice.Paired
or pairing_status == QBluetoothLocalDevice.AuthorizedPaired):
item.setForeground(QColor(Qt.green))
else:
item.setForeground(QColor(Qt.black))
self._ui.list.addItem(item)
@Slot()
def start_scan(self):
self._discovery_agent.start()
self._ui.scan.setEnabled(False)
@Slot()
def scan_finished(self):
self._ui.scan.setEnabled(True)
@Slot(QListWidgetItem)
def item_activated(self, item):
text = item.text()
index = text.find(' ')
if index == -1:
return
address = QBluetoothAddress(text[0:index])
name = text[index + 1:]
d = ServiceDiscoveryDialog(name, address)
d.exec()
@Slot(bool)
def on_discoverable_clicked(self, clicked):
if clicked:
self._local_device.setHostMode(QBluetoothLocalDevice.HostDiscoverable)
else:
self._local_device.setHostMode(QBluetoothLocalDevice.HostConnectable)
@Slot(bool)
def on_power_clicked(self, clicked):
if clicked:
self._local_device.powerOn()
else:
self._local_device.setHostMode(QBluetoothLocalDevice.HostPoweredOff)
@Slot("QBluetoothLocalDevice::HostMode")
def host_mode_state_changed(self, mode):
self._ui.power.setChecked(mode != QBluetoothLocalDevice.HostPoweredOff)
self._ui.discoverable.setChecked(mode == QBluetoothLocalDevice.HostDiscoverable)
on = mode != QBluetoothLocalDevice.HostPoweredOff
self._ui.scan.setEnabled(on)
self._ui.discoverable.setEnabled(on)
@Slot(QPoint)
def display_pairing_menu(self, pos):
if self._ui.list.count() == 0:
return
menu = QMenu(self)
pair_action = menu.addAction("Pair")
remove_pair_action = menu.addAction("Remove Pairing")
chosen_action = menu.exec(self._ui.list.viewport().mapToGlobal(pos))
current_item = self._ui.list.currentItem()
text = current_item.text()
index = text.find(' ')
if index == -1:
return
address = QBluetoothAddress(text[0:index])
if chosen_action == pair_action:
self._local_device.requestPairing(address, QBluetoothLocalDevice.Paired)
elif chosen_action == remove_pair_action:
self._local_device.requestPairing(address, QBluetoothLocalDevice.Unpaired)
@Slot(QBluetoothAddress, "QBluetoothLocalDevice::Pairing")
def pairing_done(self, address, pairing):
items = self._ui.list.findItems(address.toString(), Qt.MatchContains)
color = QColor(Qt.red)
if (pairing == QBluetoothLocalDevice.Paired
or pairing == QBluetoothLocalDevice.AuthorizedPaired):
color = QColor(Qt.green)
for item in items:
item.setForeground(color)
|