From 8335be43a31f310b3b3781fa5f04687c5b44c06d Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Mon, 17 Sep 2018 16:01:32 +0200 Subject: [PATCH] some rework on how we handle the last connected host this isn't good enough, actually worse than the current master but it has some groundwork needed for when we actually improve it --- .../discovery/discoverydevice.cpp | 42 ++++++++++++++ libnymea-app-core/discovery/discoverydevice.h | 4 ++ .../discovery/discoverymodel.cpp | 2 + libnymea-app-core/discovery/discoverymodel.h | 2 + .../discovery/nymeadiscovery.cpp | 55 +++++++++++++++++++ libnymea-app-core/discovery/nymeadiscovery.h | 7 +++ nymea-app/ui/Nymea.qml | 7 +++ nymea-app/ui/connection/ConnectPage.qml | 41 +++++++++----- 8 files changed, 145 insertions(+), 15 deletions(-) diff --git a/libnymea-app-core/discovery/discoverydevice.cpp b/libnymea-app-core/discovery/discoverydevice.cpp index f6d5a45c..d04a265d 100644 --- a/libnymea-app-core/discovery/discoverydevice.cpp +++ b/libnymea-app-core/discovery/discoverydevice.cpp @@ -121,6 +121,7 @@ void Connections::addConnection(Connection *connection) emit dataChanged(index(idx), index(idx), {RoleOnline}); }); endInsertRows(); + emit connectionAdded(connection); emit countChanged(); } @@ -134,6 +135,7 @@ void Connections::removeConnection(Connection *connection) beginRemoveRows(QModelIndex(), idx, idx); m_connections.takeAt(idx)->deleteLater(); endRemoveRows(); + emit connectionRemoved(connection); emit countChanged(); } @@ -157,6 +159,46 @@ Connection* Connections::get(int index) const return nullptr; } +Connection* Connections::bestMatch() const +{ + QList bearerPreference = {Connection::BearerTypeEthernet, Connection::BearerTypeWifi, Connection::BearerTypeCloud, Connection::BearerTypeBluetooth, Connection::BearerTypeUnknown}; + Connection *best = nullptr; + foreach (Connection *c, m_connections) { + if (!best) { + best = c; + continue; + } + uint oldBearerPriority = static_cast(bearerPreference.indexOf(best->bearerType())); + uint newBearerPriority = static_cast(bearerPreference.indexOf(c->bearerType())); + if (newBearerPriority < oldBearerPriority) { + // New one has better bearer, switch + best = c; + continue; + } + if (oldBearerPriority < newBearerPriority) { + // Discard new one as the existing is on a better bearer + continue; + } + + // Same bearer, prefer secure over insecure + if (!best->secure() && c->secure()) { + // New one is secure, old one not. switch + best = c; + continue; + } + if (best->secure() && !c->secure()) { + // Old one is secure, new one isn't, skip new one + continue; + } + + // both options are now on the same bearer and either secure or insecure, prefer nymearpc over websocket for less overhead + if (best->url().scheme().startsWith("ws") && c->url().scheme().startsWith("nymea")) { + best = c; + } + } + return best; +} + QHash Connections::roleNames() const { QHash roles; diff --git a/libnymea-app-core/discovery/discoverydevice.h b/libnymea-app-core/discovery/discoverydevice.h index 4895eaba..8394a48a 100644 --- a/libnymea-app-core/discovery/discoverydevice.h +++ b/libnymea-app-core/discovery/discoverydevice.h @@ -90,7 +90,11 @@ public: Q_INVOKABLE Connection* find(const QUrl &url) const; Q_INVOKABLE Connection* get(int index) const; + Connection *bestMatch() const; + signals: + void connectionAdded(Connection *connection); + void connectionRemoved(Connection *connection); void countChanged(); protected: diff --git a/libnymea-app-core/discovery/discoverymodel.cpp b/libnymea-app-core/discovery/discoverymodel.cpp index d730a316..25c7825d 100644 --- a/libnymea-app-core/discovery/discoverymodel.cpp +++ b/libnymea-app-core/discovery/discoverymodel.cpp @@ -61,6 +61,7 @@ void DiscoveryModel::addDevice(DiscoveryDevice *device) beginInsertRows(QModelIndex(), m_devices.count(), m_devices.count()); m_devices.append(device); endInsertRows(); + emit deviceAdded(device); emit countChanged(); } @@ -74,6 +75,7 @@ void DiscoveryModel::removeDevice(DiscoveryDevice *device) beginRemoveRows(QModelIndex(), idx, idx); m_devices.takeAt(idx); endRemoveRows(); + emit deviceRemoved(device); emit countChanged(); } diff --git a/libnymea-app-core/discovery/discoverymodel.h b/libnymea-app-core/discovery/discoverymodel.h index 47de7faa..bb677bd1 100644 --- a/libnymea-app-core/discovery/discoverymodel.h +++ b/libnymea-app-core/discovery/discoverymodel.h @@ -54,6 +54,8 @@ public: void clearModel(); signals: + void deviceAdded(DiscoveryDevice* device); + void deviceRemoved(DiscoveryDevice* device); void countChanged(); protected: diff --git a/libnymea-app-core/discovery/nymeadiscovery.cpp b/libnymea-app-core/discovery/nymeadiscovery.cpp index d2aed28f..26b90d31 100644 --- a/libnymea-app-core/discovery/nymeadiscovery.cpp +++ b/libnymea-app-core/discovery/nymeadiscovery.cpp @@ -7,10 +7,32 @@ #include #include #include +#include +#include NymeaDiscovery::NymeaDiscovery(QObject *parent) : QObject(parent) { m_discoveryModel = new DiscoveryModel(this); + connect(m_discoveryModel, &DiscoveryModel::deviceAdded, this, [this](DiscoveryDevice *device) { + if (device->uuid() != m_pendingHostResolution) { + return; + } + Connection *c = device->connections()->bestMatch(); + if (!c) { + qDebug() << "Host found but there isn't a valid candidate yet?"; + connect(device->connections(), &Connections::connectionAdded, this, [this, device](Connection *connection) { + if (device->uuid() == m_pendingHostResolution) { + qDebug() << "Host" << m_pendingHostResolution << "resolved to" << connection->url().toString(); + m_pendingHostResolution = QUuid(); + emit serverUuidResolved(connection->url().toString()); + } + }); + return; + } + qDebug() << "Host" << m_pendingHostResolution << "appeared! Best match is" << c->url(); + m_pendingHostResolution = QUuid(); + emit serverUuidResolved(c->url().toString()); + }); m_upnp = new UpnpDiscovery(m_discoveryModel, this); m_zeroConf = new ZeroconfDiscovery(m_discoveryModel, this); @@ -25,6 +47,20 @@ NymeaDiscovery::NymeaDiscovery(QObject *parent) : QObject(parent) m_awsClient->fetchDevices(); } }); + + + QNetworkConfigurationManager manager; + QList configs = manager.allConfigurations(QNetworkConfiguration::Active); + + foreach (const QNetworkConfiguration &config, configs) { + if (config.purpose() != QNetworkConfiguration::PublicPurpose) { + continue; + } + if (config.bearerType() != QNetworkConfiguration::BearerWLAN && config.bearerType() != QNetworkConfiguration::BearerEthernet) { + continue; + } + qDebug() << "Have Network configuration:" << config.name() << config.bearerTypeName() << config.purpose() << config.type(); + } } bool NymeaDiscovery::discovering() const @@ -102,6 +138,25 @@ void NymeaDiscovery::setAwsClient(AWSClient *awsClient) } } +void NymeaDiscovery::resolveServerUuid(const QUuid &uuid) +{ + // Do we already know this host? + DiscoveryDevice *dev = m_discoveryModel->find(uuid); + if (!dev) { + qDebug() << "Host" << uuid << "not known yet..."; + m_pendingHostResolution = uuid; + return; + } + Connection *c = dev->connections()->bestMatch(); + if (!c) { + qDebug() << "Host" << uuid << "is known but doesn't have a usable connection option yet."; + m_pendingHostResolution = uuid; + return; + } + qDebug() << "Host" << uuid << "is known. Best match is" << c->url(); + emit serverUuidResolved(c->url().toString()); +} + void NymeaDiscovery::syncCloudDevices() { for (int i = 0; i < m_awsClient->awsDevices()->rowCount(); i++) { diff --git a/libnymea-app-core/discovery/nymeadiscovery.h b/libnymea-app-core/discovery/nymeadiscovery.h index fd451aa4..0a88b994 100644 --- a/libnymea-app-core/discovery/nymeadiscovery.h +++ b/libnymea-app-core/discovery/nymeadiscovery.h @@ -3,6 +3,7 @@ #include #include +#include #include "connection/awsclient.h" @@ -31,10 +32,14 @@ public: AWSClient* awsClient() const; void setAwsClient(AWSClient *awsClient); + Q_INVOKABLE void resolveServerUuid(const QUuid &uuid); + signals: void discoveringChanged(); void awsClientChanged(); + void serverUuidResolved(const QString &url); + private slots: void syncCloudDevices(); @@ -49,6 +54,8 @@ private: QTimer m_cloudPollTimer; + QUuid m_pendingHostResolution; + }; #endif // NYMEADISCOVERY_H diff --git a/nymea-app/ui/Nymea.qml b/nymea-app/ui/Nymea.qml index 227dfc9d..8ca953f6 100644 --- a/nymea-app/ui/Nymea.qml +++ b/nymea-app/ui/Nymea.qml @@ -52,6 +52,13 @@ ApplicationWindow { anchors.fill: parent } + NymeaDiscovery { + id: discovery + objectName: "discovery" + awsClient: AWSClient + discovering: pageStack.currentItem.objectName === "discoveryPage" + } + onClosing: { rootItem.handleCloseEvent(close) } diff --git a/nymea-app/ui/connection/ConnectPage.qml b/nymea-app/ui/connection/ConnectPage.qml index b8b5fde0..cd3c855a 100644 --- a/nymea-app/ui/connection/ConnectPage.qml +++ b/nymea-app/ui/connection/ConnectPage.qml @@ -11,16 +11,27 @@ Page { readonly property bool haveHosts: discovery.discoveryModel.count > 0 Component.onCompleted: { - print("completed connectPage for tab", connectionTabIndex, "last connected host:", tabSettings.lastConnectedHost) - if (tabSettings.lastConnectedHost.length > 0 && engine.connection.connect(tabSettings.lastConnectedHost)) { - var page = pageStack.push(Qt.resolvedUrl("ConnectingPage.qml")) - page.cancel.connect(function() { - engine.connection.disconnect(); - pageStack.pop(root, StackView.Immediate); - pageStack.push(discoveryPage) - }) - } else { + print("completed connectPage. last connected host:", settings.lastConnectedHost) + if (settings.lastConnectedHost.length > 0) { + discovery.resolveServerUuid(settings.lastConnectedHost) + } + +// if (settings.lastConnectedHost.length > 0 && Engine.connection.connect(tabSettings.lastConnectedHost)) { +// var page = pageStack.push(Qt.resolvedUrl("ConnectingPage.qml")) +// page.cancel.connect(function() { +// Engine.connection.disconnect(); +// pageStack.pop(root, StackView.Immediate); +// pageStack.push(discoveryPage) +// }) +// } else { pageStack.push(discoveryPage) +// } + } + + Connections { + target: discovery + onServerUuidResolved: { + connectToHost(url); } } @@ -34,12 +45,12 @@ Page { engine.connection.connect(url) } - NymeaDiscovery { - id: discovery - objectName: "discovery" - awsClient: AWSClient - discovering: pageStack.currentItem.objectName === "discoveryPage" - } +// NymeaDiscovery { +// id: discovery +// objectName: "discovery" +// awsClient: AWSClient +// discovering: pageStack.currentItem.objectName === "discoveryPage" +// } Connections { target: engine.connection