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
This commit is contained in:
Michael Zanetti 2018-09-17 16:01:32 +02:00
parent 7d6986d683
commit 8335be43a3
8 changed files with 145 additions and 15 deletions

View File

@ -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<Connection::BearerType> 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<uint>(bearerPreference.indexOf(best->bearerType()));
uint newBearerPriority = static_cast<uint>(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<int, QByteArray> Connections::roleNames() const
{
QHash<int, QByteArray> roles;

View File

@ -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:

View File

@ -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();
}

View File

@ -54,6 +54,8 @@ public:
void clearModel();
signals:
void deviceAdded(DiscoveryDevice* device);
void deviceRemoved(DiscoveryDevice* device);
void countChanged();
protected:

View File

@ -7,10 +7,32 @@
#include <QUuid>
#include <QBluetoothUuid>
#include <QUrlQuery>
#include <QNetworkConfigurationManager>
#include <QNetworkSession>
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<QNetworkConfiguration> 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++) {

View File

@ -3,6 +3,7 @@
#include <QObject>
#include <QTimer>
#include <QUuid>
#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

View File

@ -52,6 +52,13 @@ ApplicationWindow {
anchors.fill: parent
}
NymeaDiscovery {
id: discovery
objectName: "discovery"
awsClient: AWSClient
discovering: pageStack.currentItem.objectName === "discoveryPage"
}
onClosing: {
rootItem.handleCloseEvent(close)
}

View File

@ -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