Improve managing of manual connections

This commit is contained in:
Michael Zanetti 2022-12-16 15:50:09 +01:00
parent 3f5d744ae0
commit d00540e864
15 changed files with 266 additions and 134 deletions

View File

@ -143,6 +143,7 @@ void NymeaDiscovery::cacheHost(NymeaHost *host)
settings.setValue("bearerType", connection->bearerType()); settings.setValue("bearerType", connection->bearerType());
settings.setValue("secure", connection->secure()); settings.setValue("secure", connection->secure());
settings.setValue("displayName", connection->displayName()); settings.setValue("displayName", connection->displayName());
settings.setValue("manual", connection->manual());
settings.endGroup(); settings.endGroup();
} }
settings.endGroup(); settings.endGroup();
@ -221,6 +222,7 @@ void NymeaDiscovery::loadFromDisk()
bool secure = settings.value("secure").toBool(); bool secure = settings.value("secure").toBool();
QString displayName = settings.value("displayName").toString(); QString displayName = settings.value("displayName").toString();
connection = new Connection(url, bearerType, secure, displayName, host); connection = new Connection(url, bearerType, secure, displayName, host);
connection->setManual(settings.value("manual").toBool());
host->connections()->addConnection(connection); host->connections()->addConnection(connection);
qCDebug(dcDiscovery()) << "|- Connection:" << group << connection->url() << connection->bearerType() << "secure:" << connection->secure(); qCDebug(dcDiscovery()) << "|- Connection:" << group << connection->url() << connection->bearerType() << "secure:" << connection->secure();
} }

View File

@ -292,9 +292,8 @@ void UpnpDiscovery::networkReplyFinished(QNetworkReply *reply)
Connection *connection = device->connections()->find(url); Connection *connection = device->connections()->find(url);
if (!connection) { if (!connection) {
bool sslEnabled = url.scheme() == "nymeas" || url.scheme() == "wss"; bool sslEnabled = url.scheme() == "nymeas" || url.scheme() == "wss";
QString displayName = QString("%1:%2").arg(url.host()).arg(url.port());
Connection::BearerType bearerType = QHostAddress(url.host()).isLoopback() ? Connection::BearerTypeLoopback : Connection::BearerTypeLan; Connection::BearerType bearerType = QHostAddress(url.host()).isLoopback() ? Connection::BearerTypeLoopback : Connection::BearerTypeLan;
connection = new Connection(url, bearerType, sslEnabled, displayName); connection = new Connection(url, bearerType, sslEnabled, "UPnP");
connection->setOnline(true); connection->setOnline(true);
qCInfo(dcUPnP()) << "Adding new connection to host:" << device->name() << url << bearerType; qCInfo(dcUPnP()) << "Adding new connection to host:" << device->name() << url << bearerType;
device->connections()->addConnection(connection); device->connections()->addConnection(connection);

View File

@ -157,9 +157,8 @@ void ZeroconfDiscovery::serviceEntryAdded(const QZeroConfService &entry)
Connection *connection = host->connections()->find(url); Connection *connection = host->connections()->find(url);
if (!connection) { if (!connection) {
qCInfo(dcZeroConf()) << "Adding new connection to host:" << host->name() << url.toString(); qCInfo(dcZeroConf()) << "Adding new connection to host:" << host->name() << url.toString();
QString displayName = QString("%1:%2").arg(url.host()).arg(url.port());
Connection::BearerType bearerType = QHostAddress(url.host()).isLoopback() ? Connection::BearerTypeLoopback : Connection::BearerTypeLan; Connection::BearerType bearerType = QHostAddress(url.host()).isLoopback() ? Connection::BearerTypeLoopback : Connection::BearerTypeLan;
connection = new Connection(url, bearerType, sslEnabled, displayName); connection = new Connection(url, bearerType, sslEnabled, "mDNS");
connection->setOnline(true); connection->setOnline(true);
host->connections()->addConnection(connection); host->connections()->addConnection(connection);
} else { } else {

View File

@ -128,7 +128,7 @@ void NymeaConnection::setCurrentHost(NymeaHost *host)
return; return;
} }
if (m_preferredConnection) { if (host && m_preferredConnection) {
if (host->connections()->find(m_preferredConnection->url())) { if (host->connections()->find(m_preferredConnection->url())) {
qCInfo(dcNymeaConnection()) << "Setting preferred connection to" << m_preferredConnection->url(); qCInfo(dcNymeaConnection()) << "Setting preferred connection to" << m_preferredConnection->url();
// Unset the preferred connection when it is removed // Unset the preferred connection when it is removed

View File

@ -232,9 +232,10 @@ Connection *Connections::bestMatch(Connection::BearerTypes bearerTypes) const
return best; return best;
} }
void Connections::addConnection(const QUrl &url, Connection::BearerType bearerType, bool secure, const QString &displayName) void Connections::addConnection(const QUrl &url, Connection::BearerType bearerType, bool secure, const QString &displayName, bool manual)
{ {
Connection *connection = new Connection(url, bearerType, secure, displayName); Connection *connection = new Connection(url, bearerType, secure, displayName);
connection->setManual(manual);
addConnection(connection); addConnection(connection);
} }
@ -249,12 +250,12 @@ QHash<int, QByteArray> Connections::roleNames() const
return roles; return roles;
} }
Connection::Connection(const QUrl &url, Connection::BearerType bearerType, bool secure, const QString &displayName, QObject *parent): Connection::Connection(const QUrl &url, Connection::BearerType bearerType, bool secure, const QString &note, QObject *parent):
QObject(parent), QObject(parent),
m_url(url), m_url(url),
m_bearerType(bearerType), m_bearerType(bearerType),
m_secure(secure), m_secure(secure),
m_displayName(displayName) m_displayName(note)
{ {
qRegisterMetaType<Connection::BearerType>("Connection.BearerType"); qRegisterMetaType<Connection::BearerType>("Connection.BearerType");
} }
@ -296,7 +297,7 @@ QString Connection::displayName() const
bool Connection::online() const bool Connection::online() const
{ {
return m_online; return m_manual || m_online;
} }
void Connection::setOnline(bool online) void Connection::setOnline(bool online)
@ -309,6 +310,20 @@ void Connection::setOnline(bool online)
} }
} }
bool Connection::manual() const
{
return m_manual;
}
void Connection::setManual(bool manual)
{
if (m_manual != manual) {
m_manual = manual;
emit onlineChanged();
emit priorityChanged();
}
}
int Connection::priority() const int Connection::priority() const
{ {
int prio = 0; int prio = 0;

View File

@ -76,6 +76,8 @@ public:
QString displayName() const; QString displayName() const;
bool online() const; bool online() const;
void setOnline(bool online); void setOnline(bool online);
bool manual() const;
void setManual(bool manual);
int priority() const; int priority() const;
signals: signals:
@ -88,6 +90,7 @@ private:
bool m_secure = false; bool m_secure = false;
QString m_displayName; QString m_displayName;
bool m_online = false; bool m_online = false;
bool m_manual = false;
QDateTime m_lastSeen; QDateTime m_lastSeen;
}; };
@ -115,7 +118,7 @@ public:
Q_INVOKABLE Connection* bestMatch(Connection::BearerTypes bearerTypes = Connection::BearerTypeAll) const; Q_INVOKABLE Connection* bestMatch(Connection::BearerTypes bearerTypes = Connection::BearerTypeAll) const;
void addConnection(Connection *connection); void addConnection(Connection *connection);
Q_INVOKABLE void addConnection(const QUrl &url, Connection::BearerType bearerType, bool secure, const QString &displayName); Q_INVOKABLE void addConnection(const QUrl &url, Connection::BearerType bearerType, bool secure, const QString &displayName, bool manual = false);
Q_INVOKABLE void removeConnection(Connection *connection); Q_INVOKABLE void removeConnection(Connection *connection);
Q_INVOKABLE void removeConnection(int index); Q_INVOKABLE void removeConnection(int index);

View File

@ -124,8 +124,8 @@ NymeaHost *NymeaHosts::createHost(const QString &name, const QUrl &url, Connecti
{ {
NymeaHost *host = new NymeaHost(this); NymeaHost *host = new NymeaHost(this);
host->setName(name); host->setName(name);
Connection *connection = new Connection(url, bearerType, false, url.toString(), host); Connection *connection = new Connection(url, bearerType, false, name, host);
connection->setOnline(true); connection->setManual(true);
host->connections()->addConnection(connection); host->connections()->addConnection(connection);
addHost(host); addHost(host);
return host; return host;

View File

@ -197,7 +197,7 @@ void JsonRpcClient::notificationReceived(const QVariantMap &data)
m_token = data.value("params").toMap().value("token").toByteArray(); m_token = data.value("params").toMap().value("token").toByteArray();
QSettings settings; QSettings settings;
settings.beginGroup("jsonTokens"); settings.beginGroup("jsonTokens");
settings.setValue(m_serverUuid, m_token); settings.setValue(m_connection->currentHost()->uuid().toString(), m_token);
settings.endGroup(); settings.endGroup();
m_initialSetupRequired = false; m_initialSetupRequired = false;
@ -305,7 +305,7 @@ QString JsonRpcClient::jsonRpcVersion() const
QString JsonRpcClient::serverUuid() const QString JsonRpcClient::serverUuid() const
{ {
return m_serverUuid; return m_connection && m_connection->currentHost() ? m_connection->currentHost()->uuid().toString() : "";
} }
QString JsonRpcClient::serverName() const QString JsonRpcClient::serverName() const
@ -392,7 +392,7 @@ void JsonRpcClient::processAuthenticate(int /*commandId*/, const QVariantMap &da
emit permissionsChanged(); emit permissionsChanged();
QSettings settings; QSettings settings;
settings.beginGroup("jsonTokens"); settings.beginGroup("jsonTokens");
settings.setValue(m_serverUuid, m_token); settings.setValue(m_connection->currentHost()->uuid().toString(), m_token);
settings.endGroup(); settings.endGroup();
emit authenticationRequiredChanged(); emit authenticationRequiredChanged();
@ -598,7 +598,7 @@ void JsonRpcClient::dataReceived(const QByteArray &data)
m_token.clear(); m_token.clear();
QSettings settings; QSettings settings;
settings.beginGroup("jsonTokens"); settings.beginGroup("jsonTokens");
settings.setValue(m_serverUuid, m_token); settings.setValue(serverUuid(), m_token);
settings.endGroup(); settings.endGroup();
emit authenticationRequiredChanged(); emit authenticationRequiredChanged();
m_authenticated = false; m_authenticated = false;
@ -649,8 +649,9 @@ void JsonRpcClient::helloReply(int /*commandId*/, const QVariantMap &params)
m_pushButtonAuthAvailable = params.value("pushButtonAuthAvailable").toBool(); m_pushButtonAuthAvailable = params.value("pushButtonAuthAvailable").toBool();
emit pushButtonAuthAvailableChanged(); emit pushButtonAuthAvailableChanged();
m_serverUuid = params.value("uuid").toString();
m_serverVersion = params.value("version").toString(); m_serverVersion = params.value("version").toString();
QUuid serverUuid = params.value("uuid").toUuid();
QString name = params.value("name").toString();
m_experiences.clear(); m_experiences.clear();
foreach (const QVariant &experience, params.value("experiences").toList()) { foreach (const QVariant &experience, params.value("experiences").toList()) {
m_experiences.insert(experience.toMap().value("name").toString(), experience.toMap().value("version").toString()); m_experiences.insert(experience.toMap().value("name").toString(), experience.toMap().value("version").toString());
@ -666,10 +667,16 @@ void JsonRpcClient::helloReply(int /*commandId*/, const QVariantMap &params)
qCInfo(dcJsonRpc()) << "Handshake reply:" << "Protocol version:" << protoVersionString << "InitRequired:" << m_initialSetupRequired << "AuthRequired:" << m_authenticationRequired << "PushButtonAvailable:" << m_pushButtonAuthAvailable; qCInfo(dcJsonRpc()) << "Handshake reply:" << "Protocol version:" << protoVersionString << "InitRequired:" << m_initialSetupRequired << "AuthRequired:" << m_authenticationRequired << "PushButtonAvailable:" << m_pushButtonAuthAvailable;
if (m_connection->currentHost()->uuid().isNull()) { if (m_connection->currentHost()->uuid().isNull()) {
qCDebug(dcJsonRpc()) << "Updating Server UUID in connection:" << m_connection->currentHost()->uuid().toString() << "->" << m_serverUuid; qCDebug(dcJsonRpc()) << "Updating Server UUID in connection:" << m_connection->currentHost()->uuid().toString() << "->" << serverUuid;
m_connection->currentHost()->setUuid(m_serverUuid); m_connection->currentHost()->setUuid(serverUuid);
} else if (m_connection->currentHost()->uuid() != serverUuid) {
qCWarning(dcJsonRpc()) << "Unexpected server UUID" << serverUuid.toString() << "expected:" << m_connection->currentHost()->uuid();
emit invalidServerUuid(serverUuid);
return;
} }
m_connection->currentHost()->setName(name);
QVersionNumber minimumRequiredVersion = QVersionNumber(5, 0); QVersionNumber minimumRequiredVersion = QVersionNumber(5, 0);
QVersionNumber maximumMajorVersion = QVersionNumber(7); QVersionNumber maximumMajorVersion = QVersionNumber(7);
if (m_jsonRpcVersion < minimumRequiredVersion) { if (m_jsonRpcVersion < minimumRequiredVersion) {
@ -688,11 +695,11 @@ void JsonRpcClient::helloReply(int /*commandId*/, const QVariantMap &params)
if (m_connection->isEncrypted()) { if (m_connection->isEncrypted()) {
QByteArray oldPem; QByteArray oldPem;
QSslCertificate certificate = m_connection->sslCertificate(); QSslCertificate certificate = m_connection->sslCertificate();
if (!loadPem(m_serverUuid, oldPem)) { if (!loadPem(serverUuid, oldPem)) {
qCInfo(dcJsonRpc()) << "No SSL certificate for this host stored. Accepting and pinning new certificate."; qCInfo(dcJsonRpc()) << "No SSL certificate for this host stored. Accepting and pinning new certificate.";
// No certificate yet! Inform ui about it. // No certificate yet! Inform ui about it.
emit newSslCertificate(); emit newSslCertificate();
storePem(m_serverUuid, m_connection->sslCertificate().toPem()); storePem(serverUuid, m_connection->sslCertificate().toPem());
} else { } else {
// We have a certificate pinned already. Check if it's the same // We have a certificate pinned already. Check if it's the same
if (certificate.toPem() != oldPem) { if (certificate.toPem() != oldPem) {
@ -707,7 +714,7 @@ void JsonRpcClient::helloReply(int /*commandId*/, const QVariantMap &params)
// Reject the connection until the UI explicitly accepts this... // Reject the connection until the UI explicitly accepts this...
m_connection->disconnectFromHost(); m_connection->disconnectFromHost();
emit verifyConnectionCertificate(m_serverUuid, issuerInfo, certificate.toPem()); emit verifyConnectionCertificate(serverUuid.toString(), issuerInfo, certificate.toPem());
return; return;
} }
qCInfo(dcJsonRpc()) << "This connections certificate is trusted."; qCInfo(dcJsonRpc()) << "This connections certificate is trusted.";
@ -728,7 +735,7 @@ void JsonRpcClient::helloReply(int /*commandId*/, const QVariantMap &params)
m_token.clear(); m_token.clear();
QSettings settings; QSettings settings;
settings.beginGroup("jsonTokens"); settings.beginGroup("jsonTokens");
settings.setValue(m_serverUuid, m_token); settings.setValue(serverUuid.toString(), m_token);
settings.endGroup(); settings.endGroup();
emit authenticationRequiredChanged(); emit authenticationRequiredChanged();
m_authenticated = false; m_authenticated = false;
@ -755,7 +762,7 @@ void JsonRpcClient::helloReply(int /*commandId*/, const QVariantMap &params)
// Reload the token, now that we're certain about the server uuid. // Reload the token, now that we're certain about the server uuid.
QSettings settings; QSettings settings;
settings.beginGroup("jsonTokens"); settings.beginGroup("jsonTokens");
m_token = settings.value(m_serverUuid).toByteArray(); m_token = settings.value(serverUuid.toString()).toByteArray();
settings.endGroup(); settings.endGroup();
emit authenticationRequiredChanged(); emit authenticationRequiredChanged();

View File

@ -126,6 +126,7 @@ signals:
void tokenChanged(); void tokenChanged();
void invalidMinimumVersion(const QString &actualVersion, const QString &minVersion); void invalidMinimumVersion(const QString &actualVersion, const QString &minVersion);
void invalidMaximumVersion(const QString &actualVersion, const QString &maxVersion); void invalidMaximumVersion(const QString &actualVersion, const QString &maxVersion);
void invalidServerUuid(const QUuid &uuid);
void authenticationFailed(); void authenticationFailed();
void pushButtonAuthFailed(); void pushButtonAuthFailed();
void createUserSucceeded(); void createUserSucceeded();
@ -158,7 +159,6 @@ private:
bool m_pushButtonAuthAvailable = false; bool m_pushButtonAuthAvailable = false;
bool m_authenticated = false; bool m_authenticated = false;
int m_pendingPushButtonTransaction = -1; int m_pendingPushButtonTransaction = -1;
QString m_serverUuid;
QVersionNumber m_jsonRpcVersion; QVersionNumber m_jsonRpcVersion;
QString m_serverVersion; QString m_serverVersion;
QString m_serverQtVersion; QString m_serverQtVersion;

View File

@ -289,5 +289,6 @@
<file>ui/mainviews/energy/ConsumersHistoryPage.qml</file> <file>ui/mainviews/energy/ConsumersHistoryPage.qml</file>
<file>ui/mainviews/energy/ConsumerStatsPage.qml</file> <file>ui/mainviews/energy/ConsumerStatsPage.qml</file>
<file>ui/mainviews/energy/ConsumersPieChartPage.qml</file> <file>ui/mainviews/energy/ConsumersPieChartPage.qml</file>
<file>ui/connection/ManualConnectionEntry.qml</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -88,6 +88,7 @@ Drawer {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
visible: index === configuredHostsModel.currentIndex && !topSectionLayout.configureConnections visible: index === configuredHostsModel.currentIndex && !topSectionLayout.configureConnections
} }
ProgressButton { ProgressButton {
imageSource: "/ui/images/close.svg" imageSource: "/ui/images/close.svg"
visible: topSectionLayout.configureConnections && (autoConnectHost.length === 0 || index > 0) visible: topSectionLayout.configureConnections && (autoConnectHost.length === 0 || index > 0)
@ -104,8 +105,24 @@ Drawer {
} }
} }
onClicked: { onClicked: {
configuredHostsModel.currentIndex = index if (topSectionLayout.configureConnections) {
root.close() var nymeaHost = nymeaDiscovery.nymeaHosts.find(hostDelegate.configuredHost.uuid);
if (nymeaHost) {
var connectionInfoDialog = Qt.createComponent("/ui/components/ConnectionInfoDialog.qml")
var popup = connectionInfoDialog.createObject(app,{nymeaEngine: configuredHost.engine, nymeaHost: nymeaHost})
popup.open()
popup.connectionSelected.connect(function(connection) {
print("...")
configuredHost.engine.jsonRpcClient.disconnectFromHost();
configuredHost.engine.jsonRpcClient.connectToHost(nymeaHost, connection)
configuredHostsModel.currentIndex = index
root.close()
})
}
} else {
configuredHostsModel.currentIndex = index
root.close()
}
} }
} }
} }
@ -233,5 +250,12 @@ Drawer {
} }
} }
} }
// Component {
// id: hostConnectionInfoComponent
// MeaDialog {
// }
// }
} }

View File

@ -150,7 +150,7 @@ Item {
engine.jsonRpcClient.connectToHost(cachedHost) engine.jsonRpcClient.connectToHost(cachedHost)
return; return;
} }
print("Warning: There is a last connected host but UUID is unknown to discovery...") console.warn("There is a last connected host but UUID is unknown to discovery...")
} else if (autoConnectHost.length > 0 && index === 0) { } else if (autoConnectHost.length > 0 && index === 0) {
var host = nymeaDiscovery.nymeaHosts.createLanHost(Configuration.systemName, autoConnectHost); var host = nymeaDiscovery.nymeaHosts.createLanHost(Configuration.systemName, autoConnectHost);
engine.jsonRpcClient.connectToHost(host) engine.jsonRpcClient.connectToHost(host)
@ -295,6 +295,13 @@ Item {
if (engine.jsonRpcClient.connected) { if (engine.jsonRpcClient.connected) {
nymeaDiscovery.cacheHost(engine.jsonRpcClient.currentHost) nymeaDiscovery.cacheHost(engine.jsonRpcClient.currentHost)
configuredHost.uuid = engine.jsonRpcClient.serverUuid configuredHost.uuid = engine.jsonRpcClient.serverUuid
for (var i = 0; i < configuredHostsModel.count; i++) {
if (i != index && configuredHostsModel.get(i).uuid == engine.jsonRpcClient.serverUuid) {
configuredHostsModel.removeHost(i);
break;
}
}
} }
init(); init();
} }
@ -320,6 +327,12 @@ Item {
popup.maxVersion = maxVersion; popup.maxVersion = maxVersion;
popup.open() popup.open()
} }
onInvalidServerUuid: {
var connection = engine.jsonRpcClient.currentConnection;
engine.jsonRpcClient.disconnectFromHost();
engine.jsonRpcClient.currentHost.connections.removeConnection(connection);
nymeaDiscovery.cacheHost(engine.jsonRpcClient.currentHost);
}
} }
Connections { Connections {
@ -365,7 +378,7 @@ Item {
url += ":" + tunnelProxyConfig.port url += ":" + tunnelProxyConfig.port
url += "?uuid=" + engine.jsonRpcClient.currentHost.uuid url += "?uuid=" + engine.jsonRpcClient.currentHost.uuid
console.info("Adding tunnel proxy connection:", url) console.info("Adding tunnel proxy connection:", url)
engine.jsonRpcClient.currentHost.connections.addConnection(url, Connection.BearerTypeCloud, tunnelProxyConfig.sslEnabled, "Remote proxy connection"); engine.jsonRpcClient.currentHost.connections.addConnection(url, Connection.BearerTypeCloud, tunnelProxyConfig.sslEnabled, "Remote proxy connection", true);
} }
nymeaDiscovery.cacheHost(engine.jsonRpcClient.currentHost) nymeaDiscovery.cacheHost(engine.jsonRpcClient.currentHost)
} }

View File

@ -2,18 +2,22 @@ import QtQuick 2.9
import Nymea 1.0 import Nymea 1.0
import QtQuick.Controls 2.2 import QtQuick.Controls 2.2
import QtQuick.Layouts 1.2 import QtQuick.Layouts 1.2
import "qrc:/ui/connection"
Dialog { Dialog {
id: dialog id: root
x: (parent.width - width) / 2 x: (parent.width - width) / 2
y: (parent.height - height) / 2 y: (parent.height - height) / 2
modal: true modal: true
title: qsTr("System information") title: qsTr("System information")
standardButtons: Dialog.Ok standardButtons: Dialog.NoButton
property Engine nymeaEngine: null
property var nymeaHost: null property var nymeaHost: null
signal connectionSelected(Connection connection)
header: Item { header: Item {
implicitHeight: headerRow.height + Style.margins * 2 implicitHeight: headerRow.height + Style.margins * 2
implicitWidth: parent.width implicitWidth: parent.width
@ -32,7 +36,7 @@ Dialog {
id: titleLabel id: titleLabel
Layout.fillWidth: true Layout.fillWidth: true
wrapMode: Text.WrapAtWordBoundaryOrAnywhere wrapMode: Text.WrapAtWordBoundaryOrAnywhere
text: dialog.title text: root.title
color: Style.accentColor color: Style.accentColor
font.pixelSize: app.largeFont font.pixelSize: app.largeFont
} }
@ -48,7 +52,7 @@ Dialog {
text: "Name:" text: "Name:"
} }
Label { Label {
text: dialog.nymeaHost.name text: root.nymeaHost.name
Layout.fillWidth: true Layout.fillWidth: true
elide: Text.ElideRight elide: Text.ElideRight
} }
@ -56,7 +60,7 @@ Dialog {
text: "UUID:" text: "UUID:"
} }
Label { Label {
text: dialog.nymeaHost.uuid text: root.nymeaHost.uuid
Layout.fillWidth: true Layout.fillWidth: true
elide: Text.ElideRight elide: Text.ElideRight
} }
@ -64,7 +68,7 @@ Dialog {
text: "Version:" text: "Version:"
} }
Label { Label {
text: dialog.nymeaHost.version text: root.nymeaHost.version
Layout.fillWidth: true Layout.fillWidth: true
elide: Text.ElideRight elide: Text.ElideRight
} }
@ -84,19 +88,19 @@ Dialog {
id: contentColumn id: contentColumn
width: parent.width width: parent.width
Repeater { Repeater {
model: dialog.nymeaHost.connections model: root.nymeaHost.connections
delegate: NymeaSwipeDelegate { delegate: NymeaSwipeDelegate {
Layout.fillWidth: true Layout.fillWidth: true
wrapTexts: false wrapTexts: false
progressive: false progressive: false
text: model.name text: model.url
subText: model.url subText: model.name
prominentSubText: false prominentSubText: false
iconName: { iconName: {
switch (model.bearerType) { switch (model.bearerType) {
case Connection.BearerTypeLan: case Connection.BearerTypeLan:
case Connection.BearerTypeWan: case Connection.BearerTypeWan:
if (engine.jsonRpcClient.availableBearerTypes & NymeaConnection.BearerTypeEthernet != NymeaConnection.BearerTypeNone) { if (nymeaEngine.jsonRpcClient.availableBearerTypes & NymeaConnection.BearerTypeEthernet != NymeaConnection.BearerTypeNone) {
return "../images/connections/network-wired.svg" return "../images/connections/network-wired.svg"
} }
return "../images/connections/network-wifi.svg"; return "../images/connections/network-wifi.svg";
@ -113,14 +117,59 @@ Dialog {
tertiaryIconName: model.secure ? "../images/connections/network-secure.svg" : "" tertiaryIconName: model.secure ? "../images/connections/network-secure.svg" : ""
secondaryIconName: !model.online ? "../images/connections/cloud-error.svg" : "" secondaryIconName: !model.online ? "../images/connections/cloud-error.svg" : ""
secondaryIconColor: "red" secondaryIconColor: "red"
canDelete: root.nymeaEngine.jsonRpcClient.currentConnection !== nymeaHost.connections.get(index)
onDeleteClicked: {
root.nymeaHost.connections.removeConnection(root.nymeaHost.connections.get(index))
nymeaDiscovery.cacheHost(nymeaHost)
}
onClicked: { onClicked: {
dialog.close() print("selecting", root.nymeaHost.connections.get(index))
engine.jsonRpcClient.connectToHost(dialog.nymeaHost, dialog.nymeaHost.connections.get(index)) root.connectionSelected(root.nymeaHost.connections.get(index))
root.close()
} }
} }
} }
} }
} }
RowLayout {
Layout.columnSpan: 2
Button {
text: qsTr("Add")
onClicked: {
var popup = addManualConnectionComponent.createObject(root.parent)
popup.open();
popup.accepted.connect(function() {
root.nymeaHost.connections.addConnection(popup.rpcUrl, Connection.BearerTypeWan, popup.sslEnabled, "Manual connection", true)
})
}
}
Item {
Layout.fillWidth: true
}
Button {
text: qsTr("Close")
onClicked: {
root.close()
}
}
}
}
Component {
id: addManualConnectionComponent
MeaDialog {
id: addManualConnectionDialog
standardButtons: Dialog.Ok | Dialog.Cancel
property alias rpcUrl: manualEntry.rpcUrl
property alias sslEnabled: manualEntry.sslEnabled
ManualConnectionEntry {
id: manualEntry
}
}
} }
} }

View File

@ -271,8 +271,12 @@ WizardPageBase {
var nymeaHost = hostsProxy.get(index); var nymeaHost = hostsProxy.get(index);
var connectionInfoDialog = Qt.createComponent("/ui/components/ConnectionInfoDialog.qml") var connectionInfoDialog = Qt.createComponent("/ui/components/ConnectionInfoDialog.qml")
print("**", connectionInfoDialog.errorString()) print("**", connectionInfoDialog.errorString())
var popup = connectionInfoDialog.createObject(app,{nymeaHost: nymeaHost}) var popup = connectionInfoDialog.createObject(app,{nymeaEngine: engine, nymeaHost: nymeaHost})
popup.open() popup.open()
popup.connectionSelected.connect(function(connection) {
engine.jsonRpcClient.disconnectFromHost();
engine.jsonRpcClient.connectToHost(nymeaHost, connection)
})
} }
} }
] ]
@ -290,107 +294,18 @@ WizardPageBase {
onBack: pageStack.pop() onBack: pageStack.pop()
onNext: { onNext: {
var rpcUrl var rpcUrl = manualEntry.rpcUrl;
var hostAddress
var port
// Set default to placeholder
if (addressTextInput.text === "") {
hostAddress = addressTextInput.placeholderText
} else {
hostAddress = addressTextInput.text
}
if (portTextInput.text === "") {
port = portTextInput.placeholderText
} else {
port = portTextInput.text
}
if (connectionTypeComboBox.currentIndex == 0) {
if (secureCheckBox.checked) {
rpcUrl = "nymeas://" + hostAddress + ":" + port
} else {
rpcUrl = "nymea://" + hostAddress + ":" + port
}
} else if (connectionTypeComboBox.currentIndex == 1) {
if (secureCheckBox.checked) {
rpcUrl = "wss://" + hostAddress + ":" + port
} else {
rpcUrl = "ws://" + hostAddress + ":" + port
}
} else if (connectionTypeComboBox.currentIndex == 2) {
if (secureCheckBox.checked) {
rpcUrl = "tunnels://" + hostAddress + ":" + port + "?uuid=" + serverUuidTextInput.text
} else {
rpcUrl = "tunnel://" + hostAddress + ":" + port + "?uuid=" + serverUuidTextInput.text
}
}
print("Try to connect ", rpcUrl) print("Try to connect ", rpcUrl)
var host = nymeaDiscovery.nymeaHosts.createWanHost("Manual connection", rpcUrl); var host = nymeaDiscovery.nymeaHosts.createWanHost("Manual connection", rpcUrl);
engine.jsonRpcClient.connectToHost(host) engine.jsonRpcClient.connectToHost(host)
} }
content: ColumnLayout { content: ManualConnectionEntry {
id: manualEntry
Layout.fillWidth: true Layout.fillWidth: true
Layout.margins: Style.margins Layout.margins: Style.margins
Layout.maximumWidth: 500 Layout.maximumWidth: 500
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
GridLayout {
columns: 2
Label {
text: qsTr("Protocol")
}
ComboBox {
id: connectionTypeComboBox
Layout.fillWidth: true
model: [ qsTr("TCP"), qsTr("Websocket"), qsTr("Remote proxy") ]
}
Label {
text: connectionTypeComboBox.currentIndex < 2 ? qsTr("Address:") : qsTr("Proxy address:")
}
TextField {
id: addressTextInput
objectName: "addressTextInput"
Layout.fillWidth: true
placeholderText: connectionTypeComboBox.currentIndex < 2 ? "127.0.0.1" : "tunnelproxy.nymea.io"
}
Label {
text: qsTr("%1 UUID:").arg(Configuration.systemName)
visible: connectionTypeComboBox.currentIndex == 2
}
TextField {
id: serverUuidTextInput
Layout.fillWidth: true
visible: connectionTypeComboBox.currentIndex == 2
}
Label { text: qsTr("Port:") }
TextField {
id: portTextInput
Layout.fillWidth: true
placeholderText: connectionTypeComboBox.currentIndex === 0
? "2222"
: connectionTypeComboBox.currentIndex == 1
? "4444"
: "2213"
validator: IntValidator{bottom: 1; top: 65535;}
}
Label {
Layout.fillWidth: true
text: qsTr("SSL:")
}
CheckBox {
id: secureCheckBox
checked: true
}
}
} }
} }
} }

View File

@ -0,0 +1,105 @@
import QtQuick 2.3
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.2
import "../components"
import Nymea 1.0
ColumnLayout {
property string rpcUrl: {
var rpcUrl
var hostAddress
var port
// Set default to placeholder
if (addressTextInput.text === "") {
hostAddress = addressTextInput.placeholderText
} else {
hostAddress = addressTextInput.text
}
if (portTextInput.text === "") {
port = portTextInput.placeholderText
} else {
port = portTextInput.text
}
if (connectionTypeComboBox.currentIndex == 0) {
if (secureCheckBox.checked) {
rpcUrl = "nymeas://" + hostAddress + ":" + port
} else {
rpcUrl = "nymea://" + hostAddress + ":" + port
}
} else if (connectionTypeComboBox.currentIndex == 1) {
if (secureCheckBox.checked) {
rpcUrl = "wss://" + hostAddress + ":" + port
} else {
rpcUrl = "ws://" + hostAddress + ":" + port
}
} else if (connectionTypeComboBox.currentIndex == 2) {
if (secureCheckBox.checked) {
rpcUrl = "tunnels://" + hostAddress + ":" + port + "?uuid=" + serverUuidTextInput.text
} else {
rpcUrl = "tunnel://" + hostAddress + ":" + port + "?uuid=" + serverUuidTextInput.text
}
}
return rpcUrl;
}
property bool sslEnabled: secureCheckBox.checked
GridLayout {
columns: 2
Label {
text: qsTr("Protocol")
}
ComboBox {
id: connectionTypeComboBox
Layout.fillWidth: true
model: [ qsTr("TCP"), qsTr("Websocket"), qsTr("Remote proxy") ]
}
Label {
text: connectionTypeComboBox.currentIndex < 2 ? qsTr("Address:") : qsTr("Proxy address:")
}
TextField {
id: addressTextInput
objectName: "addressTextInput"
Layout.fillWidth: true
placeholderText: connectionTypeComboBox.currentIndex < 2 ? "127.0.0.1" : "tunnelproxy.nymea.io"
}
Label {
text: qsTr("%1 UUID:").arg(Configuration.systemName)
visible: connectionTypeComboBox.currentIndex == 2
}
TextField {
id: serverUuidTextInput
Layout.fillWidth: true
visible: connectionTypeComboBox.currentIndex == 2
}
Label { text: qsTr("Port:") }
TextField {
id: portTextInput
Layout.fillWidth: true
placeholderText: connectionTypeComboBox.currentIndex === 0
? "2222"
: connectionTypeComboBox.currentIndex == 1
? "4444"
: "2213"
validator: IntValidator{bottom: 1; top: 65535;}
}
Label {
Layout.fillWidth: true
text: qsTr("SSL:")
}
CheckBox {
id: secureCheckBox
checked: true
}
}
}