summaryrefslogtreecommitdiffstats
path: root/src/bluetooth
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@qt.io>2018-08-21 11:11:56 +0200
committerAlex Blasche <alexander.blasche@qt.io>2018-08-23 07:44:35 +0000
commit4a20dda27259fad1468370860162b8f22ca53072 (patch)
treebaec5a21ea788b55a97ee1128f674f660df3531a /src/bluetooth
parentb9e3ca7c32da3fdc4bfb6e4c7c540e66229f86ce (diff)
Add QBluetoothDeviceDiscoveryAgent::deviceUpdated signal
For iBeacons and such, it's normal to keep discovering indefinitely, while the advertisement can sometimes carry changing payload data. This signal helps keep the UI up-to-date. Changed setManufacturerData to return a bool indicating whether the data was really modified or not, to avoid sending deviceUpdated in case it was not changed. For convenience QBluetoothDeviceInfo::manufacturerData() was added. WinRT and Apple platforms do not emit the new signal yet and relevant TODO items were added. Done-with: Shawn Rutledge <shawn.rutledge@qt.io> Task-number: QTBUG-46008 Task-number: QTBUG-69747 Change-Id: I6d6b373f6cc5ee3dd6af2ad05d8640dbd25c5d6a Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> Reviewed-by: Oliver Wolff <oliver.wolff@qt.io> Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
Diffstat (limited to 'src/bluetooth')
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent.cpp20
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent.h1
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp23
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp14
-rw-r--r--src/bluetooth/qbluetoothdeviceinfo.cpp34
-rw-r--r--src/bluetooth/qbluetoothdeviceinfo.h11
6 files changed, 93 insertions, 10 deletions
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent.cpp
index a9e35960..ac978349 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent.cpp
@@ -155,6 +155,26 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT)
*/
/*!
+ \fn void QBluetoothDeviceDiscoveryAgent::deviceUpdated(const QBluetoothDeviceInfo &info, QBluetoothDeviceInfo::Fields updatedFields)
+
+ This signal is emitted when the agent receives additional information about
+ the Bluetooth device described by \a info. The \l updatedFields flags tell
+ which information has been updated.
+
+ During discovery, some information can change dynamically, such as
+ \l {signal strength}{QBluetoothDeviceInfo::rssi()} and
+ \l {manufacturerData}{QBluetoothDeviceInfo::manufacturerData()}.
+ This signal informs you that if your application is displaying this data, it
+ can be updated, rather than waiting until the discovery has finished.
+
+ \note This signal is only emitted on Android and BlueZ 5.x.
+
+ \sa QBluetoothDeviceInfo::rssi(), lowEnergyDiscoveryTimeout()
+*/
+
+// TODO deviceUpdated() signal not implemented on WinRT and Apple platforms
+
+/*!
\fn void QBluetoothDeviceDiscoveryAgent::finished()
This signal is emitted when Bluetooth device discovery completes.
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent.h b/src/bluetooth/qbluetoothdevicediscoveryagent.h
index d3e41265..f24478bf 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent.h
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent.h
@@ -112,6 +112,7 @@ public Q_SLOTS:
Q_SIGNALS:
void deviceDiscovered(const QBluetoothDeviceInfo &info);
+ void deviceUpdated(const QBluetoothDeviceInfo &info, QBluetoothDeviceInfo::Fields updatedFields);
void finished();
void error(QBluetoothDeviceDiscoveryAgent::Error error);
void canceled();
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
index c7afd578..50f3aef9 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
@@ -317,12 +317,29 @@ void QBluetoothDeviceDiscoveryAgentPrivate::processDiscoveredDevices(
for (int i = 0; i < discoveredDevices.size(); i++) {
if (discoveredDevices[i].address() == info.address()) {
- if (discoveredDevices[i] == info && lowEnergySearchTimeout > 0) {
- qCDebug(QT_BT_ANDROID) << "Duplicate: " << info.address()
- << "isLeScanResult:" << isLeResult;
+ QBluetoothDeviceInfo::Fields updatedFields = QBluetoothDeviceInfo::Field::None;
+ if (discoveredDevices[i].rssi() != info.rssi()) {
+ qCDebug(QT_BT_ANDROID) << "Updating RSSI for" << info.address()
+ << info.rssi();
+ discoveredDevices[i].setRssi(info.rssi());
+ updatedFields.setFlag(QBluetoothDeviceInfo::Field::RSSI);
+ }
+ if (discoveredDevices[i].manufacturerData() != info.manufacturerData()) {
+ qCDebug(QT_BT_ANDROID) << "Updating manufacturer data for" << info.address();
+ const QVector<quint16> keys = info.manufacturerIds();
+ for (auto key: keys)
+ discoveredDevices[i].setManufacturerData(key, info.manufacturerData(key));
+ updatedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData);
+ }
+
+ if (!updatedFields.testFlag(QBluetoothDeviceInfo::Field::None)) {
+ emit q->deviceUpdated(discoveredDevices[i], updatedFields);
return;
}
+ if (discoveredDevices[i] == info)
+ return;
+
if (discoveredDevices.at(i).name() == info.name()) {
qCDebug(QT_BT_ANDROID) << "Almost Duplicate "<< info.address()
<< info.name() << "- replacing in place";
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp
index a5fdb323..a039c916 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp
@@ -633,23 +633,27 @@ void QBluetoothDeviceDiscoveryAgentPrivate::_q_PropertiesChanged(const QString &
QDBusConnection::systemBus());
for (int i = 0; i < discoveredDevices.size(); i++) {
if (discoveredDevices[i].address().toString() == device.address()) {
+ QBluetoothDeviceInfo::Fields updatedFields = QBluetoothDeviceInfo::Field::None;
if (changed_properties.contains(QStringLiteral("RSSI"))) {
qCDebug(QT_BT_BLUEZ) << "Updating RSSI for" << device.address()
<< changed_properties.value(QStringLiteral("RSSI"));
discoveredDevices[i].setRssi(
changed_properties.value(QStringLiteral("RSSI")).toInt());
+ updatedFields.setFlag(QBluetoothDeviceInfo::Field::RSSI);
}
if (changed_properties.contains(QStringLiteral("ManufacturerData"))) {
qCDebug(QT_BT_BLUEZ) << "Updating ManufacturerData for" << device.address();
-
- QVector<QPair<quint16,QByteArray>> manufacturerData;
ManufacturerDataList changedManufacturerData =
- qvariant_cast< ManufacturerDataList >(changed_properties.value(QStringLiteral("ManufacturerData")));
+ qdbus_cast< ManufacturerDataList >(changed_properties.value(QStringLiteral("ManufacturerData")));
const QList<quint16> keys = changedManufacturerData.keys();
- for (quint16 key : keys)
- discoveredDevices[i].setManufacturerData(key, changedManufacturerData.value(key).variant().toByteArray());
+ for (quint16 key : keys) {
+ if (discoveredDevices[i].setManufacturerData(key, changedManufacturerData.value(key).variant().toByteArray()))
+ updatedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData);
+ }
}
+ if (!updatedFields.testFlag(QBluetoothDeviceInfo::Field::None))
+ emit q->deviceUpdated(discoveredDevices[i], updatedFields);
return;
}
}
diff --git a/src/bluetooth/qbluetoothdeviceinfo.cpp b/src/bluetooth/qbluetoothdeviceinfo.cpp
index 11a60565..bd3b9c00 100644
--- a/src/bluetooth/qbluetoothdeviceinfo.cpp
+++ b/src/bluetooth/qbluetoothdeviceinfo.cpp
@@ -72,6 +72,20 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \enum QBluetoothDeviceInfo::Field
+
+ This enum is used in conjuntion with the \l deviceUpdated() signal and indicates the field
+ that changed.
+
+ \value None None of the values changed.
+ \value RSSI The \l rssi() value of the device changed.
+ \value ManufacturerData The \l manufacturerData() field changed
+ \value All Matches every possible field.
+
+ \since 5.12
+*/
+
+/*!
\enum QBluetoothDeviceInfo::MinorMiscellaneousClass
This enum describes the minor device classes for miscellaneous Bluetooth devices.
@@ -598,20 +612,38 @@ QVector<quint16> QBluetoothDeviceInfo::manufacturerIds() const
*/
QByteArray QBluetoothDeviceInfo::manufacturerData(quint16 manufacturerId) const
{
+ // TODO Currently not implemented on WinRT
Q_D(const QBluetoothDeviceInfo);
return d->manufacturerData.value(manufacturerId);
}
/*!
Sets the advertised manufacturer \a data for the given \a manufacturerId.
+ Returns true if it was inserted or changed, false if it was already known.
\sa manufacturerData,
\since 5.12
*/
-void QBluetoothDeviceInfo::setManufacturerData(quint16 manufacturerId, const QByteArray &data)
+bool QBluetoothDeviceInfo::setManufacturerData(quint16 manufacturerId, const QByteArray &data)
{
Q_D(QBluetoothDeviceInfo);
+ const auto it = d->manufacturerData.find(manufacturerId);
+ if (it != d->manufacturerData.end() && *it == data)
+ return false;
d->manufacturerData.insert(manufacturerId, data);
+ return true;
+}
+
+/*!
+ Returns the complete set of all manufacturer data.
+
+ \sa setManufacturerData
+ \since 5.12
+*/
+QHash<quint16, QByteArray> QBluetoothDeviceInfo::manufacturerData() const
+{
+ Q_D(const QBluetoothDeviceInfo);
+ return d->manufacturerData;
}
/*!
diff --git a/src/bluetooth/qbluetoothdeviceinfo.h b/src/bluetooth/qbluetoothdeviceinfo.h
index 88b477d8..d59eb27d 100644
--- a/src/bluetooth/qbluetoothdeviceinfo.h
+++ b/src/bluetooth/qbluetoothdeviceinfo.h
@@ -198,6 +198,14 @@ public:
DataUnavailable
};
+ enum class Field {
+ None = 0x0000,
+ RSSI = 0x0001,
+ ManufacturerData = 0x0002,
+ All = 0x7fff
+ };
+ Q_DECLARE_FLAGS(Fields, Field)
+
enum CoreConfiguration {
UnknownCoreConfiguration = 0x0,
LowEnergyCoreConfiguration = 0x01,
@@ -239,7 +247,8 @@ public:
QVector<quint16> manufacturerIds() const;
QByteArray manufacturerData(quint16 manufacturerId) const;
- void setManufacturerData(quint16 manufacturerId, const QByteArray &data);
+ bool setManufacturerData(quint16 manufacturerId, const QByteArray &data);
+ QHash<quint16, QByteArray> manufacturerData() const;
void setCoreConfigurations(QBluetoothDeviceInfo::CoreConfigurations coreConfigs);
QBluetoothDeviceInfo::CoreConfigurations coreConfigurations() const;