From 57c78507354f25d6786e3a686f62b942add651f8 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Wed, 4 Aug 2021 12:05:13 +0200 Subject: [PATCH] Update to latest bt discovery code --- libnymea-app/libnymea-app-core.h | 1 + .../wifisetup/bluetoothdeviceinfos.cpp | 124 ++++++++++++++++++ libnymea-app/wifisetup/bluetoothdeviceinfos.h | 53 ++++++++ libnymea-app/wifisetup/bluetoothdiscovery.cpp | 15 +-- .../ui/connection/NewConnectionWizard.qml | 12 +- .../wifisetup/BluetoothDiscoveryPage.qml | 12 +- 6 files changed, 198 insertions(+), 19 deletions(-) diff --git a/libnymea-app/libnymea-app-core.h b/libnymea-app/libnymea-app-core.h index 66fefece..e8909e8d 100644 --- a/libnymea-app/libnymea-app-core.h +++ b/libnymea-app/libnymea-app-core.h @@ -279,6 +279,7 @@ void registerQmlTypes() { qmlRegisterType(uri, 1, 0, "BluetoothDiscovery"); qmlRegisterUncreatableType(uri, 1, 0, "BluetoothDeviceInfo", "Can't create this in QML. Get it from the DeviceInfos."); qmlRegisterUncreatableType(uri, 1, 0, "BluetoothDeviceInfos", "Can't create this in QML. Get it from the BluetoothDiscovery."); + qmlRegisterType(uri, 1, 0, "BluetoothDeviceInfosProxy"); qmlRegisterUncreatableType(uri, 1, 0, "WirelessAccessPoint", "Can't create this in QML. Get it from the WirelessAccessPoints."); qmlRegisterUncreatableType(uri, 1, 0, "WirelessAccessPoints", "Can't create this in QML. Get it from the Engine instance."); qmlRegisterType(uri, 1, 0, "WirelessAccessPointsProxy"); diff --git a/libnymea-app/wifisetup/bluetoothdeviceinfos.cpp b/libnymea-app/wifisetup/bluetoothdeviceinfos.cpp index f23ef63b..38fe20b1 100644 --- a/libnymea-app/wifisetup/bluetoothdeviceinfos.cpp +++ b/libnymea-app/wifisetup/bluetoothdeviceinfos.cpp @@ -31,6 +31,7 @@ #include "bluetoothdeviceinfos.h" #include +#include BluetoothDeviceInfos::BluetoothDeviceInfos(QObject *parent) : QAbstractListModel(parent) { @@ -108,3 +109,126 @@ QHash BluetoothDeviceInfos::roleNames() const roles[BluetoothDeviceInfoRoleSignalStrength] = "signalStrength"; return roles; } + +BluetoothDeviceInfosProxy::BluetoothDeviceInfosProxy(QObject *parent): QSortFilterProxyModel(parent) +{ + +} + +BluetoothDeviceInfos *BluetoothDeviceInfosProxy::model() const +{ + return m_model; +} + +void BluetoothDeviceInfosProxy::setModel(BluetoothDeviceInfos *model) +{ + if (m_model == model) { + return; + } + + if (m_model) { + disconnect(m_model, &BluetoothDeviceInfos::countChanged, this, &BluetoothDeviceInfosProxy::countChanged); + } + + m_model = model; + setSourceModel(model); + emit modelChanged(); + emit countChanged(); + + if (m_model) { + connect(m_model, &BluetoothDeviceInfos::countChanged, this, &BluetoothDeviceInfosProxy::countChanged); + } +} + +QStringList BluetoothDeviceInfosProxy::nameWhitelist() const +{ + return m_nameWhitelist; +} + +void BluetoothDeviceInfosProxy::setNameWhitelist(const QStringList &nameWhitelist) +{ + if (m_nameWhitelist != nameWhitelist) { + m_nameWhitelist = nameWhitelist; + emit nameWhitelistChanged(); + invalidateFilter(); + emit countChanged(); + } +} + +bool BluetoothDeviceInfosProxy::filterForLowEnergy() const +{ + return m_filterForLowEnergy; +} + +void BluetoothDeviceInfosProxy::setFilterForLowEnergy(bool filterForLowEnergy) +{ + if (m_filterForLowEnergy != filterForLowEnergy) { + m_filterForLowEnergy = filterForLowEnergy; + emit filterForLowEnergyChanged(); + invalidateFilter(); + emit countChanged(); + } +} + +QString BluetoothDeviceInfosProxy::filterForServiceUUID() const +{ + return m_filterForServiceUUID.toString(); +} + +void BluetoothDeviceInfosProxy::setFilterForServiceUUID(const QString &filterForServiceUUID) +{ + if (m_filterForServiceUUID != filterForServiceUUID) { + m_filterForServiceUUID = filterForServiceUUID; + emit filterForServiceUUIDChanged(); + invalidateFilter(); + emit countChanged(); + } +} + +QString BluetoothDeviceInfosProxy::filterForName() const +{ + return m_filterForName; +} + +void BluetoothDeviceInfosProxy::setFilterForName(const QString &name) +{ + if (m_filterForName != name) { + m_filterForName = name; + emit filterForNameChanged(); + + invalidateFilter(); + emit countChanged(); + } +} + +BluetoothDeviceInfo *BluetoothDeviceInfosProxy::get(int index) const +{ + return m_model->get(mapToSource(this->index(index, 0)).row()); +} + +bool BluetoothDeviceInfosProxy::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const +{ + Q_UNUSED(source_parent) + + BluetoothDeviceInfo *info = m_model->get(source_row); + + if (!m_nameWhitelist.isEmpty()) { + if (m_nameWhitelist.contains(info->name())) { + return true; + } + } + + if (m_filterForLowEnergy && !info->bluetoothDeviceInfo().coreConfigurations().testFlag(QBluetoothDeviceInfo::LowEnergyCoreConfiguration)) { + return false; + } + + if (!m_filterForServiceUUID.isNull() && !info->bluetoothDeviceInfo().serviceUuids().contains(QBluetoothUuid(m_filterForServiceUUID))) { + return false; + } + + if (!m_filterForName.isEmpty() && info->name() != m_filterForName) { + return false; + } + + return true; +} diff --git a/libnymea-app/wifisetup/bluetoothdeviceinfos.h b/libnymea-app/wifisetup/bluetoothdeviceinfos.h index 0271d12f..c2af122c 100644 --- a/libnymea-app/wifisetup/bluetoothdeviceinfos.h +++ b/libnymea-app/wifisetup/bluetoothdeviceinfos.h @@ -33,6 +33,8 @@ #include #include +#include +#include #include "bluetoothdeviceinfo.h" @@ -72,4 +74,55 @@ private: QList m_deviceInfos; }; +class BluetoothDeviceInfosProxy: public QSortFilterProxyModel +{ + Q_OBJECT + Q_PROPERTY(BluetoothDeviceInfos* model READ model WRITE setModel NOTIFY modelChanged) + Q_PROPERTY(int count READ rowCount NOTIFY countChanged) + + // Workaround for allowing particular names, even if they'd fail the filters below (used for legacy compatibility) + Q_PROPERTY(QStringList nameWhitelist READ nameWhitelist WRITE setNameWhitelist NOTIFY nameWhitelistChanged) + + Q_PROPERTY(bool filterForLowEnergy READ filterForLowEnergy WRITE setFilterForLowEnergy NOTIFY filterForLowEnergyChanged) + Q_PROPERTY(QString filterForServiceUUID READ filterForServiceUUID WRITE setFilterForServiceUUID NOTIFY filterForServiceUUIDChanged) + Q_PROPERTY(QString filterForName READ filterForName WRITE setFilterForName NOTIFY filterForNameChanged) +public: + BluetoothDeviceInfosProxy(QObject *parent = nullptr); + + BluetoothDeviceInfos* model() const; + void setModel(BluetoothDeviceInfos *model); + + QStringList nameWhitelist() const; + void setNameWhitelist(const QStringList &nameWhitelist); + + bool filterForLowEnergy() const; + void setFilterForLowEnergy(bool filterForLowEnergy); + + QString filterForServiceUUID() const; + void setFilterForServiceUUID(const QString &filterForServiceUUID); + + QString filterForName() const; + void setFilterForName(const QString &name); + + Q_INVOKABLE BluetoothDeviceInfo* get(int index) const; + +signals: + void modelChanged(); + void countChanged(); + void nameWhitelistChanged(); + void filterForLowEnergyChanged(); + void filterForServiceUUIDChanged(); + void filterForNameChanged(); + +protected: + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; + +private: + BluetoothDeviceInfos *m_model = nullptr; + QStringList m_nameWhitelist; + bool m_filterForLowEnergy = false; + QUuid m_filterForServiceUUID; + QString m_filterForName; +}; + #endif // BLUETOOTHDEVICEINFOS_H diff --git a/libnymea-app/wifisetup/bluetoothdiscovery.cpp b/libnymea-app/wifisetup/bluetoothdiscovery.cpp index 9efd73a5..b97e9cc3 100644 --- a/libnymea-app/wifisetup/bluetoothdiscovery.cpp +++ b/libnymea-app/wifisetup/bluetoothdiscovery.cpp @@ -175,19 +175,6 @@ void BluetoothDiscovery::onBluetoothHostModeChanged(const QBluetoothLocalDevice: void BluetoothDiscovery::deviceDiscovered(const QBluetoothDeviceInfo &deviceInfo) { - if (!deviceInfo.isValid() - || !deviceInfo.coreConfigurations().testFlag(QBluetoothDeviceInfo::LowEnergyCoreConfiguration) - || deviceInfo.name().isEmpty()) { - return; - } - - // Only show devices that either list the wifi service uuid or are called BT WLAN setup (for legacy reasons) - static QBluetoothUuid wifiServiceUuid = QBluetoothUuid(QUuid("e081fec0-f757-4449-b9c9-bfa83133f7fc")); - if (!deviceInfo.serviceUuids().contains(wifiServiceUuid) && deviceInfo.name() != "BT WLAN setup") { - qDebug() << "Skipping device" << deviceInfo.name() << deviceInfo.serviceUuids(); - return; - } - foreach (BluetoothDeviceInfo *di, m_deviceInfos->deviceInfos()) { if (di->address() == deviceInfo.address().toString()) { di->setBluetoothDeviceInfo(deviceInfo); @@ -197,7 +184,7 @@ void BluetoothDiscovery::deviceDiscovered(const QBluetoothDeviceInfo &deviceInfo BluetoothDeviceInfo *deviceInformation = new BluetoothDeviceInfo(deviceInfo); -// qDebug() << "BluetoothDiscovery: [+]" << deviceInformation->name() << "(" << deviceInformation->address() << ")" << (isLowEnergy ? "LE" : "") << deviceInfo.majorDeviceClass() << deviceInfo.minorDeviceClass() << deviceInfo.serviceClasses(); + qDebug() << "BluetoothDiscovery: [+]" << deviceInformation->name() << "(" << deviceInformation->address() << ")" << (deviceInformation->isLowEnergy() ? "LE" : "") << deviceInfo.serviceUuids(); m_deviceInfos->addBluetoothDeviceInfo(deviceInformation); } diff --git a/nymea-app/ui/connection/NewConnectionWizard.qml b/nymea-app/ui/connection/NewConnectionWizard.qml index 5f7016af..0ff8a6d7 100644 --- a/nymea-app/ui/connection/NewConnectionWizard.qml +++ b/nymea-app/ui/connection/NewConnectionWizard.qml @@ -447,11 +447,17 @@ WizardPageBase { content: ListView { anchors.fill: parent - model: bluetoothDiscovery.deviceInfos + model: BluetoothDeviceInfosProxy { + id: deviceInfosProxy + model: bluetoothDiscovery.deviceInfos + filterForLowEnergy: true + filterForServiceUUID: "e081fec0-f757-4449-b9c9-bfa83133f7fc" + nameWhitelist: ["BT WLAN setup"] + } BusyIndicator { anchors.centerIn: parent - visible: bluetoothDiscovery.discovering && bluetoothDiscovery.deviceInfos.count == 0 + visible: bluetoothDiscovery.discovering && deviceInfosProxy.count == 0 } delegate: NymeaSwipeDelegate { @@ -461,7 +467,7 @@ WizardPageBase { subText: model.address onClicked: { - wifiSetup.connectToDevice(bluetoothDiscovery.deviceInfos.get(index)) + wifiSetup.connectToDevice(deviceInfosProxy.get(index)) pageStack.push(wirelessBluetoothConnectingComponent) } } diff --git a/nymea-app/ui/connection/wifisetup/BluetoothDiscoveryPage.qml b/nymea-app/ui/connection/wifisetup/BluetoothDiscoveryPage.qml index 7a8b1463..10a4b432 100644 --- a/nymea-app/ui/connection/wifisetup/BluetoothDiscoveryPage.qml +++ b/nymea-app/ui/connection/wifisetup/BluetoothDiscoveryPage.qml @@ -46,6 +46,14 @@ Page { discoveryEnabled: pageStack.currentItem === root } + BluetoothDeviceInfosProxy { + id: deviceInfosProxy + model: bluetoothDiscovery.deviceInfos + filterForLowEnergy: true + filterForServiceUUID: "e081fec0-f757-4449-b9c9-bfa83133f7fc" + nameWhitelist: ["BT WLAN setup"] + } + BtWiFiSetup { id: wifiSetup @@ -129,7 +137,7 @@ Page { Layout.fillWidth: true Layout.fillHeight: true - model: bluetoothDiscovery.deviceInfos + model: deviceInfosProxy clip: true delegate: NymeaSwipeDelegate { @@ -139,7 +147,7 @@ Page { subText: model.address onClicked: { - root.connectDevice(bluetoothDiscovery.deviceInfos.get(index)) + root.connectDevice(deviceInfosProxy.get(index)) } } }