From e0689cc7e8f16d1ac2edd158334982032da7d5aa Mon Sep 17 00:00:00 2001 From: Kevin Whitaker Date: Thu, 7 Nov 2019 23:05:56 -0500 Subject: [PATCH] Add new bluetooth class as model for scanning. Add UI to show scanned devices on top of page. --- src/CMakeLists.txt | 1 + src/contents/ui/main.qml | 53 +++++++++++++++++-- src/main.cpp | 2 + src/miflora/bluetoothdevices.cpp | 71 ++++++++++++++++++++++++++ src/miflora/bluetoothdevices.h | 88 ++++++++++++++++++++++++++++++++ src/miflora/miflora.cpp | 19 ++++--- src/miflora/miflora.h | 8 ++- 7 files changed, 231 insertions(+), 11 deletions(-) create mode 100644 src/miflora/bluetoothdevices.cpp create mode 100644 src/miflora/bluetoothdevices.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 98fac95..1a048c9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,7 @@ set(qiflora_SRCS miflora/miflora.cpp + miflora/bluetoothdevices.cpp main.cpp ) diff --git a/src/contents/ui/main.qml b/src/contents/ui/main.qml index f547254..8173013 100644 --- a/src/contents/ui/main.qml +++ b/src/contents/ui/main.qml @@ -24,7 +24,7 @@ Kirigami.ApplicationWindow { iconName: "view-refresh" text: i18n("Query Device") onTriggered: { - //TODO + deviceSelect.open(); } } title: "Monitor" @@ -57,7 +57,7 @@ Kirigami.ApplicationWindow { Kirigami.Heading { Layouts.Layout.alignment: Qt.AlignCenter level: 4 - text: "Last Measured" + text: i18n("Last Measured") } Kirigami.Heading { Layouts.Layout.alignment: Qt.AlignCenter @@ -73,10 +73,57 @@ Kirigami.ApplicationWindow { } contentItem: Controls.Label { wrapMode: Text.WordWrap - text: model.chartType + text: i18n("") //TODO: replace with graph? } } } + + Kirigami.OverlaySheet { + id: deviceSelect + showCloseButton: false + contentItem: ListView { + header: Column { + Rectangle { + height: 10 + color: "transparent" + width: parent.width + } + Kirigami.Heading { + text: i18n("Select Device to Query") + } + Rectangle { + height: 10 + color: "transparent" + width: parent.width + } + } + id: deviceList + model: qiflora.devices + delegate: Kirigami.AbstractListItem { + Layouts.ColumnLayout { + Kirigami.Heading { + text:model.modelData.name + level: 2 + } + Kirigami.Heading { + text:model.modelData.address + level: 5 + } + } + onClicked: { + qiflora.updateDataFromDevice(model.modelData.address); + deviceSelect.close(); + } + } + } + onSheetOpenChanged: { + if(!sheetOpen) { + qiflora.stopSearch(); + } else { + qiflora.startSearch(); + } + } + } } } } diff --git a/src/main.cpp b/src/main.cpp index 384a0b4..9544a8a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,7 @@ #include #include #include "miflora/miflora.h" +#include "miflora/bluetoothdevices.h" Q_DECL_EXPORT int main(int argc, char *argv[]) { @@ -13,6 +14,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) QCoreApplication::setApplicationName("qiflora"); QQmlApplicationEngine engine; + qmlRegisterType(); qmlRegisterType("org.eyecreate.qiflora",1,0,"QiFlora"); engine.load(QUrl(QStringLiteral("qrc:///main.qml"))); diff --git a/src/miflora/bluetoothdevices.cpp b/src/miflora/bluetoothdevices.cpp new file mode 100644 index 0000000..f9d67f2 --- /dev/null +++ b/src/miflora/bluetoothdevices.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2019 Kevin Whitaker + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "bluetoothdevices.h" +#include + +BluetoothDevices::BluetoothDevices(QBluetoothDeviceInfo info) +{ + this->m_device = info; + this->m_address = info.address().toString(); + this->m_name = info.name(); +} + +QBluetoothDeviceInfo BluetoothDevices::device() const +{ + return m_device; +} + +void BluetoothDevices::setDevice(const QBluetoothDeviceInfo& device) +{ + if (m_device == device) { + return; + } + + m_device = device; + emit deviceChanged(m_device); +} + +QString BluetoothDevices::address() const +{ + return m_address; +} + +void BluetoothDevices::setAddress(const QString& address) +{ + if (m_address == address) { + return; + } + + m_address = address; + emit addressChanged(m_address); +} + +QString BluetoothDevices::name() const +{ + return m_name; +} + +void BluetoothDevices::setName(const QString& name) +{ + if (m_name == name) { + return; + } + + m_name = name; + emit nameChanged(m_name); +} diff --git a/src/miflora/bluetoothdevices.h b/src/miflora/bluetoothdevices.h new file mode 100644 index 0000000..3b66d30 --- /dev/null +++ b/src/miflora/bluetoothdevices.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2019 Kevin Whitaker + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef BLUETOOTHDEVICES_H +#define BLUETOOTHDEVICES_H + +#include +#include + +/** + * Data class used to represent found MiFlora devices. + */ +class BluetoothDevices : public QObject +{ + Q_OBJECT + Q_PROPERTY(QBluetoothDeviceInfo device READ device WRITE setDevice NOTIFY deviceChanged) + Q_PROPERTY(QString address READ address WRITE setAddress NOTIFY addressChanged) + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + +public: + + BluetoothDevices(QBluetoothDeviceInfo info); + + /** + * @return the device + */ + QBluetoothDeviceInfo device() const; + + /** + * @return the address + */ + QString address() const; + + /** + * @return the name + */ + QString name() const; + +public Q_SLOTS: + /** + * Sets the device. + * + * @param device the new device + */ + void setDevice(const QBluetoothDeviceInfo& device); + + /** + * Sets the address. + * + * @param address the new address + */ + void setAddress(const QString& address); + + /** + * Sets the name. + * + * @param name the new name + */ + void setName(const QString& name); + +Q_SIGNALS: + void deviceChanged(const QBluetoothDeviceInfo& device); + + void addressChanged(const QString& address); + + void nameChanged(const QString& name); + +private: + QBluetoothDeviceInfo m_device; + QString m_address; + QString m_name; +}; + +#endif // BLUETOOTHDEVICES_H diff --git a/src/miflora/miflora.cpp b/src/miflora/miflora.cpp index 840cc45..0edeb27 100644 --- a/src/miflora/miflora.cpp +++ b/src/miflora/miflora.cpp @@ -31,6 +31,7 @@ void MiFlora::startSearch() void MiFlora::stopSearch() { if(agent != NULL) { + qDebug() << "Stopping Search."; agent->stop(); agent->disconnect(); delete agent; @@ -39,10 +40,10 @@ void MiFlora::stopSearch() void MiFlora::updateDataFromDevice ( QString mac ) { - for(QBluetoothDeviceInfo info: devices) { - if(info.address().toString() == mac) { - qDebug() << "Discovering on:" + info.name(); - currentController = QLowEnergyController::createCentral(info); + for(BluetoothDevices *info: devices) { + if(info->device().address().toString() == mac) { + qDebug() << "Discovering on:" + info->device().name(); + currentController = QLowEnergyController::createCentral(info->device()); currentController->setRemoteAddressType(QLowEnergyController::PublicAddress); connect(currentController, &QLowEnergyController::serviceDiscovered, this, &MiFlora::serviceDiscovered); connect(currentController, static_cast(&QLowEnergyController::error), this, &MiFlora::logControllerError); @@ -57,11 +58,17 @@ void MiFlora::updateDataFromDevice ( QString mac ) void MiFlora::foundDevice ( const QBluetoothDeviceInfo& device ) { if(device.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration && device.address().toString().startsWith("C4:7C")) { - devices.append(device); - emit newDeviceFound(device.name(), device.address().toString()); + devices.append(new BluetoothDevices(device)); + qDebug() << "Added device"; + emit newDeviceFound(); } } +QQmlListProperty MiFlora::getDeviceList() +{ + return QQmlListProperty(this, devices); +} + void MiFlora::logControllerError ( QLowEnergyController::Error err ) { qDebug() << "Error:" << err; diff --git a/src/miflora/miflora.h b/src/miflora/miflora.h index 13b214a..d0a23db 100644 --- a/src/miflora/miflora.h +++ b/src/miflora/miflora.h @@ -24,6 +24,8 @@ #include #include #include +#include "bluetoothdevices.h" +#include /** * Class using QtBluetooth to find and retrive info from Mi Flora devices. @@ -36,16 +38,18 @@ class MiFlora : public QObject Q_PROPERTY(quint8 moisture NOTIFY moistureChanged MEMBER moisture) Q_PROPERTY(quint16 conduction NOTIFY conductionChanged MEMBER conduct) Q_PROPERTY(quint8 battery NOTIFY batteryChanged MEMBER battery) + Q_PROPERTY(QQmlListProperty devices READ getDeviceList NOTIFY newDeviceFound) public: Q_INVOKABLE void startSearch(); Q_INVOKABLE void stopSearch(); Q_INVOKABLE void updateDataFromDevice(QString mac); + QQmlListProperty getDeviceList(); //TODO:History? signals: - void newDeviceFound(QString name, QString address); + void newDeviceFound(); void temperatureChanged(float temperature); void brightnessChanged(quint32 brightness); void moistureChanged(quint8 moisture); @@ -62,7 +66,7 @@ private: void serviceCharRead(QLowEnergyCharacteristic readChar, QByteArray value); QBluetoothDeviceDiscoveryAgent *agent; - QList devices; + QList devices; QLowEnergyController *currentController; QLowEnergyService *sensorService; -- GitLab