diff options
Diffstat (limited to 'src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp')
-rw-r--r-- | src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp | 361 |
1 files changed, 330 insertions, 31 deletions
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp index ef2a69b1..e0209693 100644 --- a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp @@ -47,9 +47,12 @@ #endif #include "qfunctions_winrt.h" +#include <QtBluetooth/private/qtbluetoothglobal_p.h> +#include <QtBluetooth/private/qbluetoothutils_winrt_p.h> #include <QtCore/QLoggingCategory> #include <QtCore/private/qeventdispatcher_winrt_p.h> +#include <robuffer.h> #include <wrl.h> #include <windows.devices.enumeration.h> #include <windows.devices.bluetooth.h> @@ -66,6 +69,7 @@ using namespace ABI::Windows::Devices; using namespace ABI::Windows::Devices::Bluetooth; using namespace ABI::Windows::Devices::Bluetooth::Advertisement; using namespace ABI::Windows::Devices::Enumeration; +using namespace ABI::Windows::Storage::Streams; QT_BEGIN_NAMESPACE @@ -77,6 +81,54 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINRT) ret; \ } +#define WARN_AND_CONTINUE_IF_FAILED(msg) \ + if (FAILED(hr)) { \ + qCWarning(QT_BT_WINRT) << msg; \ + continue; \ + } + +static QByteArray byteArrayFromBuffer(const ComPtr<IBuffer> &buffer) +{ + ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteAccess; + HRESULT hr = buffer.As(&byteAccess); + Q_ASSERT_SUCCEEDED(hr); + char *data; + hr = byteAccess->Buffer(reinterpret_cast<byte **>(&data)); + Q_ASSERT_SUCCEEDED(hr); + UINT32 size; + hr = buffer->get_Length(&size); + Q_ASSERT_SUCCEEDED(hr); + return QByteArray(data, int(size)); +} + + +static ManufacturerData extractManufacturerData(ComPtr<IBluetoothLEAdvertisement> ad) +{ + ManufacturerData ret; + ComPtr<IVector<BluetoothLEManufacturerData*>> data; + HRESULT hr = ad->get_ManufacturerData(&data); + WARN_AND_RETURN_IF_FAILED("Could not obtain list of manufacturer data.", return ret); + quint32 size; + hr = data->get_Size(&size); + WARN_AND_RETURN_IF_FAILED("Could not obtain manufacturer data's list size.", return ret); + for (quint32 i = 0; i < size; ++i) { + ComPtr<IBluetoothLEManufacturerData> d; + hr = data->GetAt(i, &d); + WARN_AND_CONTINUE_IF_FAILED("Could not obtain manufacturer data."); + quint16 id; + hr = d->get_CompanyId(&id); + WARN_AND_CONTINUE_IF_FAILED("Could not obtain manufacturer data company id."); + ComPtr<IBuffer> buffer; + hr = d->get_Data(&buffer); + WARN_AND_CONTINUE_IF_FAILED("Could not obtain manufacturer data set."); + const QByteArray bufferData = byteArrayFromBuffer(buffer); + if (ret.contains(id)) + qCWarning(QT_BT_WINRT) << "Company ID already present in manufacturer data."; + ret.insert(id, bufferData); + } + return ret; +} + class QWinRTBluetoothDeviceDiscoveryWorker : public QObject { Q_OBJECT @@ -84,7 +136,7 @@ public: explicit QWinRTBluetoothDeviceDiscoveryWorker(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods); ~QWinRTBluetoothDeviceDiscoveryWorker(); void start(); - void stop(); + void stopLEWatcher(); private: void startDeviceDiscovery(QBluetoothDeviceDiscoveryAgent::DiscoveryMethod mode); @@ -105,13 +157,18 @@ private: CheckForPairing, OmitPairingCheck }; - HRESULT onBluetoothLEDeviceFound(ComPtr<IBluetoothLEDevice> device, PairingCheck pairingCheck = CheckForPairing); + HRESULT onBluetoothLEDeviceFound(ComPtr<IBluetoothLEDevice> device, PairingCheck pairingCheck); +#if QT_CONFIG(winrt_btle_no_pairing) + HRESULT onBluetoothLEDeviceFound(ComPtr<IBluetoothLEDevice> device); +#endif public slots: void finishDiscovery(); Q_SIGNALS: void deviceFound(const QBluetoothDeviceInfo &info); + void deviceDataChanged(const QBluetoothAddress &address, QBluetoothDeviceInfo::Fields, + qint16 rssi, ManufacturerData manufacturerData); void scanFinished(); public: @@ -120,7 +177,17 @@ public: private: ComPtr<IBluetoothLEAdvertisementWatcher> m_leWatcher; EventRegistrationToken m_leDeviceAddedToken; - QVector<quint64> m_foundLEDevices; +#if QT_CONFIG(winrt_btle_no_pairing) + QMutex m_foundDevicesMutex; + struct LEAdvertisingInfo { + QVector<QBluetoothUuid> services; + qint16 rssi = 0; + }; + + QMap<quint64, LEAdvertisingInfo> m_foundLEDevicesMap; +#endif + QMap<quint64, qint16> m_foundLEDevices; + QMap<quint64, ManufacturerData> m_foundLEManufacturerData; int m_pendingPairedDevices; ComPtr<IBluetoothDeviceStatics> m_deviceStatics; @@ -132,6 +199,8 @@ QWinRTBluetoothDeviceDiscoveryWorker::QWinRTBluetoothDeviceDiscoveryWorker(QBlue , m_pendingPairedDevices(0) { qRegisterMetaType<QBluetoothDeviceInfo>(); + qRegisterMetaType<QBluetoothDeviceInfo::Fields>(); + qRegisterMetaType<ManufacturerData>(); #ifdef CLASSIC_APP_BUILD CoInitialize(NULL); @@ -144,7 +213,7 @@ QWinRTBluetoothDeviceDiscoveryWorker::QWinRTBluetoothDeviceDiscoveryWorker(QBlue QWinRTBluetoothDeviceDiscoveryWorker::~QWinRTBluetoothDeviceDiscoveryWorker() { - stop(); + stopLEWatcher(); #ifdef CLASSIC_APP_BUILD CoUninitialize(); #endif @@ -166,7 +235,7 @@ void QWinRTBluetoothDeviceDiscoveryWorker::start() qCDebug(QT_BT_WINRT) << "Worker started"; } -void QWinRTBluetoothDeviceDiscoveryWorker::stop() +void QWinRTBluetoothDeviceDiscoveryWorker::stopLEWatcher() { if (m_leWatcher) { HRESULT hr = m_leWatcher->Stop(); @@ -191,9 +260,11 @@ void QWinRTBluetoothDeviceDiscoveryWorker::startDeviceDiscovery(QBluetoothDevice ComPtr<IAsyncOperation<DeviceInformationCollection *>> op; hr = deviceInformationStatics->FindAllAsyncAqsFilter(deviceSelector.Get(), &op); WARN_AND_RETURN_IF_FAILED("Could not start bluetooth device discovery operation", return); + QPointer<QWinRTBluetoothDeviceDiscoveryWorker> thisPointer(this); hr = op->put_Completed( - Callback<IAsyncOperationCompletedHandler<DeviceInformationCollection *>>([this, mode](IAsyncOperation<DeviceInformationCollection *> *op, AsyncStatus) { - onDeviceDiscoveryFinished(op, mode); + Callback<IAsyncOperationCompletedHandler<DeviceInformationCollection *>>([thisPointer, mode](IAsyncOperation<DeviceInformationCollection *> *op, AsyncStatus status) { + if (status == Completed && thisPointer) + thisPointer->onDeviceDiscoveryFinished(op, mode); return S_OK; }).Get()); WARN_AND_RETURN_IF_FAILED("Could not add callback to bluetooth device discovery operation", return); @@ -239,7 +310,8 @@ void QWinRTBluetoothDeviceDiscoveryWorker::gatherMultipleDeviceInformation(quint { for (quint32 i = 0; i < deviceCount; ++i) { ComPtr<IDeviceInformation> device; - HRESULT hr = devices->GetAt(i, &device); + HRESULT hr; + hr = devices->GetAt(i, &device); Q_ASSERT_SUCCEEDED(hr); gatherDeviceInformation(device.Get(), mode); } @@ -249,15 +321,104 @@ void QWinRTBluetoothDeviceDiscoveryWorker::setupLEDeviceWatcher() { HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Devices_Bluetooth_Advertisement_BluetoothLEAdvertisementWatcher).Get(), &m_leWatcher); Q_ASSERT_SUCCEEDED(hr); +#if QT_CONFIG(winrt_btle_no_pairing) + if (supportsNewLEApi()) { + hr = m_leWatcher->put_ScanningMode(BluetoothLEScanningMode_Active); + Q_ASSERT_SUCCEEDED(hr); + } +#endif // winrt_btle_no_pairing hr = m_leWatcher->add_Received(Callback<ITypedEventHandler<BluetoothLEAdvertisementWatcher *, BluetoothLEAdvertisementReceivedEventArgs *>>([this](IBluetoothLEAdvertisementWatcher *, IBluetoothLEAdvertisementReceivedEventArgs *args) { quint64 address; HRESULT hr; hr = args->get_BluetoothAddress(&address); Q_ASSERT_SUCCEEDED(hr); - if (m_foundLEDevices.contains(address)) - return S_OK; - - m_foundLEDevices.append(address); + qint16 rssi; + hr = args->get_RawSignalStrengthInDBm(&rssi); + Q_ASSERT_SUCCEEDED(hr); + ComPtr<IBluetoothLEAdvertisement> ad; + hr = args->get_Advertisement(&ad); + Q_ASSERT_SUCCEEDED(hr); + const ManufacturerData manufacturerData = extractManufacturerData(ad); + QBluetoothDeviceInfo::Fields changedFields = QBluetoothDeviceInfo::Field::None; + if (!m_foundLEManufacturerData.contains(address)) { + m_foundLEManufacturerData.insert(address, manufacturerData); + changedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData); + } else if (m_foundLEManufacturerData.value(address) != manufacturerData) { + m_foundLEManufacturerData[address] = manufacturerData; + changedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData); + } +#if QT_CONFIG(winrt_btle_no_pairing) + if (supportsNewLEApi()) { + ComPtr<IVector<GUID>> guids; + hr = ad->get_ServiceUuids(&guids); + Q_ASSERT_SUCCEEDED(hr); + quint32 size; + hr = guids->get_Size(&size); + Q_ASSERT_SUCCEEDED(hr); + QVector<QBluetoothUuid> serviceUuids; + for (quint32 i = 0; i < size; ++i) { + GUID guid; + hr = guids->GetAt(i, &guid); + Q_ASSERT_SUCCEEDED(hr); + QBluetoothUuid uuid(guid); + serviceUuids.append(uuid); + } + QMutexLocker locker(&m_foundDevicesMutex); + // Merge newly found services with list of currently found ones + if (m_foundLEDevicesMap.contains(address)) { + if (size == 0) + return S_OK; + const LEAdvertisingInfo adInfo = m_foundLEDevicesMap.value(address); + QVector<QBluetoothUuid> foundServices = adInfo.services; + if (adInfo.rssi != rssi) { + m_foundLEDevicesMap[address].rssi = rssi; + changedFields.setFlag(QBluetoothDeviceInfo::Field::RSSI); + } + bool newServiceAdded = false; + for (const QBluetoothUuid &uuid : qAsConst(serviceUuids)) { + if (!foundServices.contains(uuid)) { + foundServices.append(uuid); + newServiceAdded = true; + } + } + if (!newServiceAdded) { + if (!changedFields.testFlag(QBluetoothDeviceInfo::Field::None)) { + QMetaObject::invokeMethod(this, "deviceDataChanged", Qt::AutoConnection, + Q_ARG(QBluetoothAddress, QBluetoothAddress(address)), + Q_ARG(QBluetoothDeviceInfo::Fields, changedFields), + Q_ARG(qint16, rssi), + Q_ARG(ManufacturerData, manufacturerData)); + } + return S_OK; + } + m_foundLEDevicesMap[address].services = foundServices; + } else { + LEAdvertisingInfo info; + info.services = std::move(serviceUuids); + info.rssi = rssi; + m_foundLEDevicesMap.insert(address, info); + } + + locker.unlock(); + } else +#endif + { + if (m_foundLEDevices.contains(address)) { + if (m_foundLEDevices.value(address) != rssi) { + m_foundLEDevices[address] = rssi; + changedFields.setFlag(QBluetoothDeviceInfo::Field::RSSI); + } + if (!changedFields.testFlag(QBluetoothDeviceInfo::Field::None)) { + QMetaObject::invokeMethod(this, "deviceDataChanged", Qt::AutoConnection, + Q_ARG(QBluetoothAddress, QBluetoothAddress(address)), + Q_ARG(QBluetoothDeviceInfo::Fields, changedFields), + Q_ARG(qint16, rssi), + Q_ARG(ManufacturerData, manufacturerData)); + } + return S_OK; + } + m_foundLEDevices.insert(address, rssi); + } leBluetoothInfoFromAddressAsync(address); return S_OK; }).Get(), &m_leDeviceAddedToken); @@ -269,6 +430,7 @@ void QWinRTBluetoothDeviceDiscoveryWorker::setupLEDeviceWatcher() void QWinRTBluetoothDeviceDiscoveryWorker::finishDiscovery() { emit scanFinished(); + stopLEWatcher(); deleteLater(); } @@ -288,9 +450,14 @@ void QWinRTBluetoothDeviceDiscoveryWorker::classicBluetoothInfoFromDeviceIdAsync qCWarning(QT_BT_WINRT) << "Could not obtain bluetooth device from id"; return S_OK; } - + QPointer<QWinRTBluetoothDeviceDiscoveryWorker> thisPointer(this); hr = deviceFromIdOperation->put_Completed(Callback<IAsyncOperationCompletedHandler<BluetoothDevice *>> - (this, &QWinRTBluetoothDeviceDiscoveryWorker::onPairedClassicBluetoothDeviceFoundAsync).Get()); + ([thisPointer](IAsyncOperation<BluetoothDevice *> *op, AsyncStatus status) + { + if (status == Completed && thisPointer) + thisPointer->onPairedClassicBluetoothDeviceFoundAsync(op, status); + return S_OK; + }).Get()); if (FAILED(hr)) { --m_pendingPairedDevices; if (!m_pendingPairedDevices @@ -317,9 +484,14 @@ void QWinRTBluetoothDeviceDiscoveryWorker::leBluetoothInfoFromDeviceIdAsync(HSTR qCWarning(QT_BT_WINRT) << "Could not obtain bluetooth device from id"; return S_OK; } - + QPointer<QWinRTBluetoothDeviceDiscoveryWorker> thisPointer(this); hr = deviceFromIdOperation->put_Completed(Callback<IAsyncOperationCompletedHandler<BluetoothLEDevice *>> - (this, &QWinRTBluetoothDeviceDiscoveryWorker::onPairedBluetoothLEDeviceFoundAsync).Get()); + ([thisPointer] (IAsyncOperation<BluetoothLEDevice *> *op, AsyncStatus status) + { + if (status == Completed && thisPointer) + thisPointer->onPairedBluetoothLEDeviceFoundAsync(op, status); + return S_OK; + }).Get()); if (FAILED(hr)) { --m_pendingPairedDevices; qCWarning(QT_BT_WINRT) << "Could not register device found callback"; @@ -343,9 +515,14 @@ void QWinRTBluetoothDeviceDiscoveryWorker::leBluetoothInfoFromAddressAsync(quint qCWarning(QT_BT_WINRT) << "Could not obtain bluetooth device from address"; return S_OK; } - + QPointer<QWinRTBluetoothDeviceDiscoveryWorker> thisPointer(this); hr = deviceFromAddressOperation->put_Completed(Callback<IAsyncOperationCompletedHandler<BluetoothLEDevice *>> - (this, &QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFoundAsync).Get()); + ([thisPointer](IAsyncOperation<BluetoothLEDevice *> *op, AsyncStatus status) + { + if (status == Completed && thisPointer) + thisPointer->onBluetoothLEDeviceFoundAsync(op, status); + return S_OK; + }).Get()); if (FAILED(hr)) { qCWarning(QT_BT_WINRT) << "Could not register device found callback"; return S_OK; @@ -391,7 +568,7 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onPairedClassicBluetoothDeviceFoun uint serviceCount; hr = deviceServices->get_Size(&serviceCount); Q_ASSERT_SUCCEEDED(hr); - QList<QBluetoothUuid> uuids; + QVector<QBluetoothUuid> uuids; for (uint i = 0; i < serviceCount; ++i) { ComPtr<Rfcomm::IRfcommDeviceService> service; hr = deviceServices->GetAt(i, &service); @@ -410,7 +587,7 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onPairedClassicBluetoothDeviceFoun QBluetoothDeviceInfo info(QBluetoothAddress(address), btName, classOfDeviceInt); info.setCoreConfigurations(QBluetoothDeviceInfo::BaseRateCoreConfiguration); - info.setServiceUuids(uuids, QBluetoothDeviceInfo::DataIncomplete); + info.setServiceUuids(uuids); info.setCached(true); QMetaObject::invokeMethod(this, "deviceFound", Qt::AutoConnection, @@ -431,7 +608,12 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onPairedBluetoothLEDeviceFoundAsyn HRESULT hr; hr = op->GetResults(&device); Q_ASSERT_SUCCEEDED(hr); - return onBluetoothLEDeviceFound(device, OmitPairingCheck); +#if QT_CONFIG(winrt_btle_no_pairing) + if (supportsNewLEApi()) + return onBluetoothLEDeviceFound(device); + else +#endif + return onBluetoothLEDeviceFound(device, OmitPairingCheck); } HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFoundAsync(IAsyncOperation<BluetoothLEDevice *> *op, AsyncStatus status) @@ -443,7 +625,12 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFoundAsync(IAsy HRESULT hr; hr = op->GetResults(&device); Q_ASSERT_SUCCEEDED(hr); - return onBluetoothLEDeviceFound(device, PairingCheck::CheckForPairing); +#if QT_CONFIG(winrt_btle_no_pairing) + if (supportsNewLEApi()) + return onBluetoothLEDeviceFound(device); + else +#endif + return onBluetoothLEDeviceFound(device, PairingCheck::CheckForPairing); } HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IBluetoothLEDevice> device, PairingCheck pairingCheck) @@ -479,7 +666,7 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IB QPointer<QWinRTBluetoothDeviceDiscoveryWorker> tPointer(this); hr = pairing.Get()->PairAsync(&pairingOp); Q_ASSERT_SUCCEEDED(hr); - pairingOp.Get()->put_Completed( + pairingOp->put_Completed( Callback<IAsyncOperationCompletedHandler<DevicePairingResult *>>([device, tPointer](IAsyncOperation<DevicePairingResult *> *op, AsyncStatus status) { if (!tPointer) return S_OK; @@ -520,7 +707,7 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IB uint serviceCount; hr = deviceServices->get_Size(&serviceCount); Q_ASSERT_SUCCEEDED(hr); - QList<QBluetoothUuid> uuids; + QVector<QBluetoothUuid> uuids; for (uint i = 0; i < serviceCount; ++i) { ComPtr<GenericAttributeProfile::IGattDeviceService> service; hr = deviceServices->GetAt(i, &service); @@ -531,19 +718,104 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IB Q_ASSERT_SUCCEEDED(hr); uuids.append(QBluetoothUuid(uuid)); } + const qint16 rssi = m_foundLEDevices.value(address); + const ManufacturerData manufacturerData = m_foundLEManufacturerData.value(address); qCDebug(QT_BT_WINRT) << "Discovered BTLE device: " << QString::number(address) << btName - << "Num UUIDs" << uuids.count(); + << "Num UUIDs" << uuids.count() << "RSSI:" << rssi + << "Num manufacturer data" << manufacturerData.count(); + + QBluetoothDeviceInfo info(QBluetoothAddress(address), btName, 0); + info.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration); + info.setServiceUuids(uuids); + info.setRssi(rssi); + for (const quint16 key : manufacturerData.keys()) + info.setManufacturerData(key, manufacturerData.value(key)); + info.setCached(true); + + QMetaObject::invokeMethod(this, "deviceFound", Qt::AutoConnection, + Q_ARG(QBluetoothDeviceInfo, info)); + return S_OK; +} + +#if QT_CONFIG(winrt_btle_no_pairing) +HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IBluetoothLEDevice> device) +{ + if (!device) { + qCDebug(QT_BT_WINRT) << "onBluetoothLEDeviceFound: No device given"; + return S_OK; + } + + UINT64 address; + HString name; + HRESULT hr = device->get_BluetoothAddress(&address); + Q_ASSERT_SUCCEEDED(hr); + hr = device->get_Name(name.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + const QString btName = QString::fromWCharArray(WindowsGetStringRawBuffer(name.Get(), nullptr)); + + ComPtr<IBluetoothLEDevice2> device2; + hr = device.As(&device2); + Q_ASSERT_SUCCEEDED(hr); + ComPtr<IDeviceInformation> deviceInfo; + hr = device2->get_DeviceInformation(&deviceInfo); + Q_ASSERT_SUCCEEDED(hr); + if (!deviceInfo) { + qCDebug(QT_BT_WINRT) << "onBluetoothLEDeviceFound: Could not obtain device information"; + return S_OK; + } + ComPtr<IDeviceInformation2> deviceInfo2; + hr = deviceInfo.As(&deviceInfo2); + Q_ASSERT_SUCCEEDED(hr); + ComPtr<IDeviceInformationPairing> pairing; + hr = deviceInfo2->get_Pairing(&pairing); + Q_ASSERT_SUCCEEDED(hr); + boolean isPaired; + hr = pairing->get_IsPaired(&isPaired); + Q_ASSERT_SUCCEEDED(hr); + QList<QBluetoothUuid> uuids; + + const LEAdvertisingInfo adInfo = m_foundLEDevicesMap.value(address); + const qint16 rssi = adInfo.rssi; + // Use the services obtained from the advertisement data if the device is not paired + if (!isPaired) { + uuids = adInfo.services.toList(); + } else { + IVectorView <GenericAttributeProfile::GattDeviceService *> *deviceServices; + hr = device->get_GattServices(&deviceServices); + Q_ASSERT_SUCCEEDED(hr); + uint serviceCount; + hr = deviceServices->get_Size(&serviceCount); + Q_ASSERT_SUCCEEDED(hr); + for (uint i = 0; i < serviceCount; ++i) { + ComPtr<GenericAttributeProfile::IGattDeviceService> service; + hr = deviceServices->GetAt(i, &service); + Q_ASSERT_SUCCEEDED(hr); + GUID uuid; + hr = service->get_Uuid(&uuid); + Q_ASSERT_SUCCEEDED(hr); + uuids.append(QBluetoothUuid(uuid)); + } + } + const ManufacturerData manufacturerData = m_foundLEManufacturerData.value(address); + + qCDebug(QT_BT_WINRT) << "Discovered BTLE device: " << QString::number(address) << btName + << "Num UUIDs" << uuids.count() << "RSSI:" << rssi + << "Num manufacturer data" << manufacturerData.count(); QBluetoothDeviceInfo info(QBluetoothAddress(address), btName, 0); info.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration); info.setServiceUuids(uuids, QBluetoothDeviceInfo::DataIncomplete); + info.setRssi(rssi); + for (quint16 key : manufacturerData.keys()) + info.setManufacturerData(key, manufacturerData.value(key)); info.setCached(true); QMetaObject::invokeMethod(this, "deviceFound", Qt::AutoConnection, Q_ARG(QBluetoothDeviceInfo, info)); return S_OK; } +#endif // QT_CONFIG(winrt_btle_no_pairing) QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate( const QBluetoothAddress &deviceAdapter, @@ -582,6 +854,8 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent discoveredDevices.clear(); connect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::deviceFound, this, &QBluetoothDeviceDiscoveryAgentPrivate::registerDevice); + connect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::deviceDataChanged, + this, &QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData); connect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::scanFinished, this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished); worker->start(); @@ -602,7 +876,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::stop() { Q_Q(QBluetoothDeviceDiscoveryAgent); if (worker) { - worker->stop(); + worker->stopLEWatcher(); disconnectAndClearWorker(); emit q->canceled(); } @@ -625,7 +899,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::registerDevice(const QBluetoothDevic uuids.append(info.serviceUuids()); const QSet<QBluetoothUuid> uuidSet = uuids.toSet(); if (iter->serviceUuids().count() != uuidSet.count()) - iter->setServiceUuids(uuidSet.toList(), QBluetoothDeviceInfo::DataIncomplete); + iter->setServiceUuids(uuidSet.toList().toVector()); if (iter->coreConfigurations() != info.coreConfigurations()) iter->setCoreConfigurations(QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration); return; @@ -636,6 +910,30 @@ void QBluetoothDeviceDiscoveryAgentPrivate::registerDevice(const QBluetoothDevic emit q->deviceDiscovered(info); } +void QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData(const QBluetoothAddress &address, + QBluetoothDeviceInfo::Fields fields, + qint16 rssi, + ManufacturerData manufacturerData) +{ + if (fields.testFlag(QBluetoothDeviceInfo::Field::None)) + return; + + Q_Q(QBluetoothDeviceDiscoveryAgent); + for (QList<QBluetoothDeviceInfo>::iterator iter = discoveredDevices.begin(); + iter != discoveredDevices.end(); ++iter) { + if (iter->address() == address) { + qCDebug(QT_BT_WINRT) << "Updating data for device" << iter->name() << iter->address(); + if (fields.testFlag(QBluetoothDeviceInfo::Field::RSSI)) + iter->setRssi(rssi); + if (fields.testFlag(QBluetoothDeviceInfo::Field::ManufacturerData)) + for (quint16 key : manufacturerData.keys()) + iter->setManufacturerData(key, manufacturerData.value(key)); + emit q->deviceUpdated(*iter, fields); + return; + } + } +} + void QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished() { Q_Q(QBluetoothDeviceDiscoveryAgent); @@ -645,17 +943,18 @@ void QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished() void QBluetoothDeviceDiscoveryAgentPrivate::disconnectAndClearWorker() { - Q_Q(QBluetoothDeviceDiscoveryAgent); if (!worker) return; disconnect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::scanFinished, - this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished); + this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished); disconnect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::deviceFound, - q, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered); + this, &QBluetoothDeviceDiscoveryAgentPrivate::registerDevice); + disconnect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::deviceDataChanged, + this, &QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData); if (leScanTimer) { disconnect(leScanTimer, &QTimer::timeout, - worker, &QWinRTBluetoothDeviceDiscoveryWorker::finishDiscovery); + worker, &QWinRTBluetoothDeviceDiscoveryWorker::finishDiscovery); } worker.clear(); } |