diff --git a/libnymea-app-core/connection/awsclient.cpp b/libnymea-app-core/connection/awsclient.cpp index 39268c80..b2a0cdd1 100644 --- a/libnymea-app-core/connection/awsclient.cpp +++ b/libnymea-app-core/connection/awsclient.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "sigv4utils.h" @@ -872,6 +873,11 @@ bool AWSClient::postToMQTT(const QString &boxId, const QString ×tamp, std:: // } // qDebug() << "Payload:" << payload; QNetworkReply *reply = m_nam->post(request, payload); + QTimer::singleShot(5000, reply, [reply, callback](){ + reply->deleteLater(); + qWarning() << "Timeout posting to MQTT"; + callback(false); + }); connect(reply, &QNetworkReply::finished, this, [reply, callback]() { reply->deleteLater(); QByteArray data = reply->readAll(); diff --git a/libnymea-app-core/connection/cloudtransport.cpp b/libnymea-app-core/connection/cloudtransport.cpp index 03818ad8..c30cac62 100644 --- a/libnymea-app-core/connection/cloudtransport.cpp +++ b/libnymea-app-core/connection/cloudtransport.cpp @@ -54,6 +54,7 @@ bool CloudTransport::connect(const QUrl &url) m_timestamp = QDateTime::currentDateTime(); bool postResult = m_awsClient->postToMQTT(url.host(), QString::number(m_timestamp.toMSecsSinceEpoch()), [this](bool success) { if (success) { + qDebug() << "MQTT Post done. Connecting to remote proxy"; m_remoteproxyConnection->connectServer(QUrl("wss://remoteproxy.nymea.io")); } else { qDebug() << "Posting to MQTT failed"; diff --git a/libnymea-app-core/connection/discovery/zeroconfdiscovery.cpp b/libnymea-app-core/connection/discovery/zeroconfdiscovery.cpp index fff26f0c..836e75d6 100644 --- a/libnymea-app-core/connection/discovery/zeroconfdiscovery.cpp +++ b/libnymea-app-core/connection/discovery/zeroconfdiscovery.cpp @@ -180,12 +180,13 @@ void ZeroconfDiscovery::serviceEntryRemoved(const QZeroConfService &entry) } // Ok, now we need to remove it - host->connections()->removeConnection(connection); +// host->connections()->removeConnection(connection); + connection->setOnline(false); // And if there aren't any connections left, remove the entire device - if (host->connections()->rowCount() == 0) { - qDebug() << "Zeroconf: Removing connection from host:" << host->name() << url.toString(); - m_nymeaHosts->removeHost(host); - } +// if (host->connections()->rowCount() == 0) { +// qDebug() << "Zeroconf: Removing connection from host:" << host->name() << url.toString(); +// m_nymeaHosts->removeHost(host); +// } } #endif diff --git a/libnymea-app-core/connection/nymeaconnection.cpp b/libnymea-app-core/connection/nymeaconnection.cpp index 9be30e90..717e4ae3 100644 --- a/libnymea-app-core/connection/nymeaconnection.cpp +++ b/libnymea-app-core/connection/nymeaconnection.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "nymeatransportinterface.h" @@ -32,6 +33,9 @@ NymeaConnection::NymeaConnection(QObject *parent) : QObject(parent) void NymeaConnection::acceptCertificate(const QString &url, const QByteArray &pem) { storePem(url, pem); + if (m_currentHost) { + connectInternal(m_currentHost); + } } bool NymeaConnection::isTrusted(const QString &url) @@ -62,6 +66,11 @@ bool NymeaConnection::connected() return m_currentHost && m_currentTransport && m_currentTransport->connectionState() == NymeaTransportInterface::ConnectionStateConnected; } +NymeaConnection::ConnectionStatus NymeaConnection::connectionStatus() const +{ + return m_connectionStatus; +} + NymeaHost *NymeaConnection::currentHost() const { return m_currentHost; @@ -91,6 +100,9 @@ void NymeaConnection::setCurrentHost(NymeaHost *host) m_currentHost = host; emit currentHostChanged(); + m_connectionStatus = ConnectionStatusConnecting; + emit connectionStatusChanged(); + if (m_currentHost) { connectInternal(m_currentHost); } @@ -175,6 +187,8 @@ void NymeaConnection::onSslErrors(const QList &errors) // info << tr("Name Qualifier:")<< error.certificate().issuerInfo(QSslCertificate::DistinguishedNameQualifier); // info << tr("Email:")<< error.certificate().issuerInfo(QSslCertificate::EmailAddress); + m_connectionStatus = ConnectionStatusSslUntrusted; + emit connectionStatusChanged(); emit verifyConnectionCertificate(transport->url().toString(), info, certificateFingerprint, error.certificate().toPem()); } } else { @@ -196,22 +210,58 @@ void NymeaConnection::onError(QAbstractSocket::SocketError error) NymeaTransportInterface* transport = qobject_cast(sender()); + ConnectionStatus errorStatus = ConnectionStatusUnknownError; + switch (error) { + case QAbstractSocket::ConnectionRefusedError: + errorStatus = ConnectionStatusConnectionRefused; + break; + case QAbstractSocket::HostNotFoundError: + errorStatus = ConnectionStatusHostNotFound; + break; + case QAbstractSocket::NetworkError: + errorStatus = ConnectionStatusBearerFailed; + break; + case QAbstractSocket::RemoteHostClosedError: + errorStatus = ConnectionStatusRemoteHostClosed; + break; + case QAbstractSocket::SocketTimeoutError: + errorStatus = ConnectionStatusTimeout; + break; + case QAbstractSocket::SslInternalError: + case QAbstractSocket::SslInvalidUserDataError: + errorStatus = ConnectionStatusSslError; + break; + case QAbstractSocket::SslHandshakeFailedError: + errorStatus = ConnectionStatusSslUntrusted; + break; + default: + errorStatus = ConnectionStatusUnknownError; + } + if (transport == m_currentTransport) { qDebug() << "Current transport failed:" << error; // The current transport failed, forward the error - emit connectionError(errorString); + m_connectionStatus = errorStatus; + emit connectionStatusChanged(); return; } if (!m_currentTransport) { // We're trying to connect and one of the transports failed... - qDebug() << "A transport error happened for" << transport->url() << error; + qDebug() << "A transport error happened for" << transport->url() << error << "(Still trying on" << m_transportCandidates.count() << "connections)"; if (m_transportCandidates.contains(transport)) { m_transportCandidates.remove(transport); transport->deleteLater(); } if (m_transportCandidates.isEmpty()) { - emit connectionError(errorString); + m_connectionStatus = errorStatus; + emit connectionStatusChanged(); + + if (m_connectionStatus != ConnectionStatusSslUntrusted) { + QTimer::singleShot(1000, m_currentHost, [this](){ + connectInternal(m_currentHost); + }); + } } } } @@ -263,7 +313,10 @@ void NymeaConnection::onDisconnected() qDebug() << "NymeaConnection: disconnected."; emit connectedChanged(false); - connectInternal(m_currentHost); + // Try to reconnect, only if we're not waiting for SSL certs to be trusted. + if (m_connectionStatus != ConnectionStatusSslUntrusted) { + connectInternal(m_currentHost); + } } void NymeaConnection::updateActiveBearers() @@ -277,18 +330,20 @@ void NymeaConnection::updateActiveBearers() } // qDebug() << "Available bearers:" << availableBearerTypes; if (m_availableBearerTypes != availableBearerTypes) { - qDebug() << "Available Bearer Types changed:" << availableBearerTypes; + qDebug() << "Available Bearer Types changed:" << availableBearerTypes; m_availableBearerTypes = availableBearerTypes; emit availableBearerTypesChanged(); } if (!m_currentHost) { // No host set... Nothing to do... + qDebug() << "No current host... Nothing to do..."; return; } if (!m_currentTransport) { // There's a host but no connection. Try connecting now... + qDebug() << "There's a host but no connection. Trying to connect now..."; connectInternal(m_currentHost); } @@ -338,6 +393,7 @@ bool NymeaConnection::storePem(const QUrl &host, const QByteArray &pem) bool NymeaConnection::loadPem(const QUrl &host, QByteArray &pem) { QDir dir(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/sslcerts/"); + qDebug() << "Loading certificates from:" << dir.absoluteFilePath(host.host() + ".pem"); QFile certFile(dir.absoluteFilePath(host.host() + ".pem")); if (!certFile.open(QFile::ReadOnly)) { return false; @@ -361,6 +417,12 @@ void NymeaConnection::connect(NymeaHost *nymeaHost) void NymeaConnection::connectInternal(NymeaHost *host) { + if (m_availableBearerTypes == Connection::BearerTypeNone) { + qDebug() << "No available bearer. Not connecting... (" << m_availableBearerTypes << ")"; + m_connectionStatus = ConnectionStatusNoBearerAvailable; + emit connectionStatusChanged(); + return; + } if (m_availableBearerTypes.testFlag(Connection::BearerTypeWifi) || m_availableBearerTypes.testFlag(Connection::BearerTypeEthernet)) { Connection* lanConnection = host->connections()->bestMatch(Connection::BearerTypeWifi | Connection::BearerTypeEthernet); if (lanConnection) { diff --git a/libnymea-app-core/connection/nymeaconnection.h b/libnymea-app-core/connection/nymeaconnection.h index 91771d68..faeba0a4 100644 --- a/libnymea-app-core/connection/nymeaconnection.h +++ b/libnymea-app-core/connection/nymeaconnection.h @@ -21,8 +21,24 @@ class NymeaConnection : public QObject Q_PROPERTY(NymeaHost* currentHost READ currentHost WRITE setCurrentHost NOTIFY currentHostChanged) Q_PROPERTY(Connection* currentConnection READ currentConnection NOTIFY currentConnectionChanged) Q_PROPERTY(Connection::BearerTypes availableBearerTypes READ availableBearerTypes NOTIFY availableBearerTypesChanged) + Q_PROPERTY(ConnectionStatus connectionStatus READ connectionStatus NOTIFY connectionStatusChanged) public: + enum ConnectionStatus { + ConnectionStatusUnconnected, + ConnectionStatusConnecting, + ConnectionStatusNoBearerAvailable, + ConnectionStatusBearerFailed, + ConnectionStatusHostNotFound, + ConnectionStatusConnectionRefused, + ConnectionStatusRemoteHostClosed, + ConnectionStatusTimeout, + ConnectionStatusSslError, + ConnectionStatusSslUntrusted, + ConnectionStatusUnknownError, + ConnectionStatusConnected + }; + Q_ENUM(ConnectionStatus) explicit NymeaConnection(QObject *parent = nullptr); void registerTransport(NymeaTransportInterfaceFactory *transportFactory); @@ -35,12 +51,14 @@ public: Connection::BearerTypes availableBearerTypes() const; bool connected(); + ConnectionStatus connectionStatus() const; NymeaHost* currentHost() const; void setCurrentHost(NymeaHost *host); Connection* currentConnection() const; + void sendData(const QByteArray &data); signals: @@ -48,8 +66,8 @@ signals: void verifyConnectionCertificate(const QString &url, const QStringList &issuerInfo, const QByteArray &fingerprint, const QByteArray &pem); void currentHostChanged(); void connectedChanged(bool connected); + void connectionStatusChanged(); void currentConnectionChanged(); - void connectionError(const QString &error); void dataAvailable(const QByteArray &data); private slots: @@ -69,6 +87,7 @@ private: Connection::BearerType qBearerTypeToNymeaBearerType(QNetworkConfiguration::BearerType type) const; private: + ConnectionStatus m_connectionStatus = ConnectionStatusUnconnected; QNetworkConfigurationManager *m_networkConfigManager = nullptr; Connection::BearerTypes m_availableBearerTypes = Connection::BearerTypeNone; diff --git a/libnymea-app-core/connection/nymeahosts.cpp b/libnymea-app-core/connection/nymeahosts.cpp index 2fe4d4d0..112e79cd 100644 --- a/libnymea-app-core/connection/nymeahosts.cpp +++ b/libnymea-app-core/connection/nymeahosts.cpp @@ -158,7 +158,7 @@ void NymeaHostsFilterModel::setNymeaConnection(NymeaConnection *nymeaConnection) emit nymeaConnectionChanged(); connect(m_nymeaConnection, &NymeaConnection::availableBearerTypesChanged, this, [this](){ - qDebug() << "Bearer Types Changed!"; +// qDebug() << "Bearer Types Changed!"; invalidateFilter(); emit countChanged(); }); diff --git a/nymea-app/resources.qrc b/nymea-app/resources.qrc index 11cbd132..a994706d 100644 --- a/nymea-app/resources.qrc +++ b/nymea-app/resources.qrc @@ -163,5 +163,6 @@ ui/thingconfiguration/SetupWizard.qml ui/thingconfiguration/EditThingsPage.qml ui/thingconfiguration/ConfigureThingPage.qml + ui/connection/CertificateDialog.qml diff --git a/nymea-app/ui/RootItem.qml b/nymea-app/ui/RootItem.qml index 93979105..2adae4a4 100644 --- a/nymea-app/ui/RootItem.qml +++ b/nymea-app/ui/RootItem.qml @@ -75,7 +75,7 @@ Item { height: swipeView.height width: swipeView.width objectName: "pageStack" - initialItem: ConnectPage {} + initialItem: Page {} property var tabSettings: Settings { category: "tabSettings" + index @@ -98,23 +98,30 @@ Item { } Component.onCompleted: { -// pageStack.push(Qt.resolvedUrl("connection/ConnectPage.qml"), StackView.Immediate) -// setupPushNotifications(); + if (tabSettings.lastConnectedHost.length > 0) { + print("Last connected host was", tabSettings.lastConnectedHost) + var cachedHost = discovery.nymeaHosts.find(tabSettings.lastConnectedHost); + if (cachedHost) { + engine.connection.currentHost = cachedHost + } else { + print("Warning: There is a last connected host but UUID is unknown to discovery...") + } + } else { + PlatformHelper.hideSplashScreen(); + pageStack.push(Qt.resolvedUrl("connection/ConnectPage.qml"), StackView.Immediate) + } } + function init() { print("calling init. Auth required:", engine.jsonRpcClient.authenticationRequired, "initial setup required:", engine.jsonRpcClient.initialSetupRequired, "jsonrpc connected:", engine.jsonRpcClient.connected, "Current host:", engine.connection.currentHost) pageStack.clear() if (!engine.connection.currentHost) { + print("pushing ConnectPage") pageStack.push(Qt.resolvedUrl("connection/ConnectPage.qml")) PlatformHelper.hideSplashScreen(); return; } - if (engine.jsonRpcClient.connected) { - pageStack.push(Qt.resolvedUrl("MainPage.qml")) - PlatformHelper.hideSplashScreen(); - return; - } if (engine.jsonRpcClient.authenticationRequired || engine.jsonRpcClient.initialSetupRequired) { PlatformHelper.hideSplashScreen(); @@ -126,6 +133,7 @@ Item { engine.connection.disconnect(); init(); }) + return; } else { var page = pageStack.push(Qt.resolvedUrl("LoginPage.qml")); page.backPressed.connect(function() { @@ -133,9 +141,22 @@ Item { engine.connection.disconnect() init(); }) + return; } } - pageStack.push(Qt.resolvedUrl("connection/ConnectingPage.qml")) + + if (engine.jsonRpcClient.connected) { + pageStack.push(Qt.resolvedUrl("MainPage.qml")) + PlatformHelper.hideSplashScreen(); + return; + } + + print("pushing ConnectingPage") + PlatformHelper.hideSplashScreen(); + var page = pageStack.push(Qt.resolvedUrl("connection/ConnectingPage.qml")); + page.cancel.connect(function(){ + engine.connection.disconnect(); + }) } function handleCloseEvent(close) { @@ -179,8 +200,15 @@ Item { onCurrentHostChanged: { init(); } + onVerifyConnectionCertificate: { + print("verify cert!") + var certDialogComponent = Qt.createComponent(Qt.resolvedUrl("connection/CertificateDialog.qml")); + var popup = certDialogComponent.createObject(root, {url: url, issuerInfo: issuerInfo, fingerprint: fingerprint, pem: pem}); + popup.open(); + } } + Connections { target: engine.jsonRpcClient onConnectedChanged: { diff --git a/nymea-app/ui/connection/CertificateDialog.qml b/nymea-app/ui/connection/CertificateDialog.qml new file mode 100644 index 00000000..dc1c62dc --- /dev/null +++ b/nymea-app/ui/connection/CertificateDialog.qml @@ -0,0 +1,110 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.2 +import QtQuick.Controls.Material 2.2 +import QtQuick.Layouts 1.3 +import Nymea 1.0 +import "../components" + +Dialog { + id: certDialog + width: Math.min(parent.width * .9, 400) + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + standardButtons: Dialog.Yes | Dialog.No + + property string url + property var fingerprint + property var issuerInfo + property var pem + + readonly property bool hasOldFingerprint: engine.connection.isTrusted(url) + + ColumnLayout { + id: certLayout + anchors.fill: parent + // spacing: app.margins + + RowLayout { + Layout.fillWidth: true + spacing: app.margins + ColorIcon { + Layout.preferredHeight: app.iconSize * 2 + Layout.preferredWidth: height + name: certDialog.hasOldFingerprint ? "../images/lock-broken.svg" : "../images/info.svg" + color: certDialog.hasOldFingerprint ? "red" : app.accentColor + } + + Label { + id: titleLabel + Layout.fillWidth: true + wrapMode: Text.WordWrap + text: certDialog.hasOldFingerprint ? qsTr("Warning") : qsTr("Hi there!") + color: certDialog.hasOldFingerprint ? "red" : app.accentColor + font.pixelSize: app.largeFont + } + } + + Label { + Layout.fillWidth: true + wrapMode: Text.WordWrap + text: certDialog.hasOldFingerprint ? qsTr("The certificate of this %1 box has changed!").arg(app.systemName) : qsTr("It seems this is the first time you connect to this %1 box.").arg(app.systemName) + } + + Label { + Layout.fillWidth: true + wrapMode: Text.WordWrap + text: certDialog.hasOldFingerprint ? qsTr("Did you change the box's configuration? Verify if this information is correct.") : qsTr("This is the box's certificate. Once you trust it, an encrypted connection will be established.") + } + + ThinDivider {} + Item { + Layout.fillWidth: true + Layout.fillHeight: true + implicitHeight: certGridLayout.implicitHeight + Flickable { + anchors.fill: parent + contentHeight: certGridLayout.implicitHeight + clip: true + + ScrollBar.vertical: ScrollBar { + policy: contentHeight > height ? ScrollBar.AlwaysOn : ScrollBar.AsNeeded + } + + GridLayout { + id: certGridLayout + columns: 2 + width: parent.width + + Repeater { + model: certDialog.issuerInfo + + Label { + Layout.fillWidth: true + wrapMode: Text.WordWrap + text: modelData + } + } + Label { + Layout.fillWidth: true + Layout.columnSpan: 2 + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + text: qsTr("Fingerprint: ") + certDialog.fingerprint + } + } + } + } + + ThinDivider {} + + Label { + Layout.fillWidth: true + wrapMode: Text.WordWrap + text: certDialog.hasOldFingerprint ? qsTr("Do you want to connect nevertheless?") : qsTr("Do you want to trust this device?") + font.bold: true + } + } + + onAccepted: { + engine.connection.acceptCertificate(certDialog.url, certDialog.pem) + } +} diff --git a/nymea-app/ui/connection/ConnectPage.qml b/nymea-app/ui/connection/ConnectPage.qml index 55618cc9..f2eaa5c7 100644 --- a/nymea-app/ui/connection/ConnectPage.qml +++ b/nymea-app/ui/connection/ConnectPage.qml @@ -12,28 +12,8 @@ Page { Component.onCompleted: { print("Ready to connect") - if (tabSettings.lastConnectedHost.length > 0) { - print("Last connected host was", tabSettings.lastConnectedHost) - var cachedHost = discovery.nymeaHosts.find(tabSettings.lastConnectedHost); - if (cachedHost) { - engine.connection.currentHost = cachedHost - } else { - print("Warning: There is a last connected host but UUID is unknown to discovery...") - } - } else { - PlatformHelper.hideSplashScreen(); - } -// 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, StackView.Immediate) -// } + pageStack.push(discoveryPage, StackView.Immediate) } @@ -65,55 +45,6 @@ Page { nymeaConnection: engine.connection } - Connections { - target: engine.connection - onVerifyConnectionCertificate: { - print("verify cert!") - var popup = certDialogComponent.createObject(root, {url: url, issuerInfo: issuerInfo, fingerprint: fingerprint, pem: pem}); - popup.open(); - } - onConnectionError: { - var errorMessage; - switch (error) { - case "ConnectionRefusedError": - errorMessage = qsTr("The host has rejected our connection. This probably means that %1 stopped running. Did you unplug your %1 box?").arg(app.systemName); - break; - case "SslInvalidUserDataError": - case "SslHandshakeFailedError": - // silently ignore. They'll be handled by the SSL logic - return; - case "HostNotFoundError": - errorMessage = qsTr("%1:core could not be found on this address. Please make sure you entered the address correctly and that the box is powered on.").arg(app.systemName); - break; - case "NetworkError": - errorMessage = qsTr("It seems you're not connected to the network."); - break; - case "RemoteHostClosedError": - errorMessage = qsTr("%1:core has closed the connection. This probably means it has been turned off or restarted.").arg(app.systemName); - break; - case "SocketTimeoutError": - errorMessage = qsTr("%1:core did not respond. Please make sure your network connection works properly").arg(app.systemName); - break; - default: - errorMessage = qsTr("An unknown error happened. We're very sorry for that. (Error code: %1)").arg(error); - } - - pageStack.pop(root, StackView.Immediate) - pageStack.push(discoveryPage) - - print("opening ErrorDialog with message:", errorMessage, error) - var comp = Qt.createComponent(Qt.resolvedUrl("../components/ErrorDialog.qml")) - var popup = comp.createObject(app, {text: errorMessage}) - popup.open() - } - onConnectedChanged: { - if (!connected) { - pageStack.pop(root, StackView.Immediate) - pageStack.push(discoveryPage) - } - } - } - Component { id: discoveryPage @@ -357,116 +288,6 @@ Page { } } - Component { - id: certDialogComponent - - Dialog { - id: certDialog - width: Math.min(parent.width * .9, 400) - x: (parent.width - width) / 2 - y: (parent.height - height) / 2 - standardButtons: Dialog.Yes | Dialog.No - - property string url - property var fingerprint - property var issuerInfo - property var pem - - readonly property bool hasOldFingerprint: engine.connection.isTrusted(url) - - ColumnLayout { - id: certLayout - anchors.fill: parent - // spacing: app.margins - - RowLayout { - Layout.fillWidth: true - spacing: app.margins - ColorIcon { - Layout.preferredHeight: app.iconSize * 2 - Layout.preferredWidth: height - name: certDialog.hasOldFingerprint ? "../images/lock-broken.svg" : "../images/info.svg" - color: certDialog.hasOldFingerprint ? "red" : app.accentColor - } - - Label { - id: titleLabel - Layout.fillWidth: true - wrapMode: Text.WordWrap - text: certDialog.hasOldFingerprint ? qsTr("Warning") : qsTr("Hi there!") - color: certDialog.hasOldFingerprint ? "red" : app.accentColor - font.pixelSize: app.largeFont - } - } - - Label { - Layout.fillWidth: true - wrapMode: Text.WordWrap - text: certDialog.hasOldFingerprint ? qsTr("The certificate of this %1 box has changed!").arg(app.systemName) : qsTr("It seems this is the first time you connect to this %1 box.").arg(app.systemName) - } - - Label { - Layout.fillWidth: true - wrapMode: Text.WordWrap - text: certDialog.hasOldFingerprint ? qsTr("Did you change the box's configuration? Verify if this information is correct.") : qsTr("This is the box's certificate. Once you trust it, an encrypted connection will be established.") - } - - ThinDivider {} - Item { - Layout.fillWidth: true - Layout.fillHeight: true - implicitHeight: certGridLayout.implicitHeight - Flickable { - anchors.fill: parent - contentHeight: certGridLayout.implicitHeight - clip: true - - ScrollBar.vertical: ScrollBar { - policy: contentHeight > height ? ScrollBar.AlwaysOn : ScrollBar.AsNeeded - } - - GridLayout { - id: certGridLayout - columns: 2 - width: parent.width - - Repeater { - model: certDialog.issuerInfo - - Label { - Layout.fillWidth: true - wrapMode: Text.WordWrap - text: modelData - } - } - Label { - Layout.fillWidth: true - Layout.columnSpan: 2 - wrapMode: Text.WrapAtWordBoundaryOrAnywhere - text: qsTr("Fingerprint: ") + certDialog.fingerprint - } - } - } - } - - ThinDivider {} - - Label { - Layout.fillWidth: true - wrapMode: Text.WordWrap - text: certDialog.hasOldFingerprint ? qsTr("Do you want to connect nevertheless?") : qsTr("Do you want to trust this device?") - font.bold: true - } - } - - onAccepted: { - engine.connection.acceptCertificate(certDialog.url, certDialog.pem) - root.connectToHost(certDialog.url) - } - } - } - - Component { id: infoDialog Dialog { diff --git a/nymea-app/ui/connection/ConnectingPage.qml b/nymea-app/ui/connection/ConnectingPage.qml index ca2132d9..dff23c2f 100644 --- a/nymea-app/ui/connection/ConnectingPage.qml +++ b/nymea-app/ui/connection/ConnectingPage.qml @@ -33,6 +33,51 @@ Page { wrapMode: Text.WrapAtWordBoundaryOrAnywhere horizontalAlignment: Text.AlignHCenter } + Label { + Layout.fillWidth: true + text: { + var errorMessage; + switch (engine.connection.connectionStatus) { + case NymeaConnection.ConnectionStatusUnconnected: + case NymeaConnection.ConnectionStatusConnecting: + case NymeaConnection.ConnectionStatusConnected: + errorMessage = ""; + break; + case NymeaConnection.ConnectionStatusBearerFailed: + errorMessage = qsTr("The network connection failed.") + break; + case NymeaConnection.ConnectionStatusNoBearerAvailable: + errorMessage = qsTr("It seems you're not connected to the network."); + break; + case NymeaConnection.ConnectionStatusHostNotFound: + errorMessage = qsTr("%1:core could not be found on this address. Please make sure you entered the address correctly and that the box is powered on.").arg(app.systemName); + break; + case NymeaConnection.ConnectionStatusConnectionRefused: + errorMessage = qsTr("The host has rejected our connection. This probably means that %1 stopped running. Did you unplug your %1 box?").arg(app.systemName); + break; + case NymeaConnection.ConnectionStatusRemoteHostClosed: + errorMessage = qsTr("%1:core has closed the connection. This probably means it has been turned off or restarted.").arg(app.systemName); + break; + + case NymeaConnection.ConnectionStatusTimeout: + errorMessage = qsTr("%1:core did not respond. Please make sure your network connection works properly").arg(app.systemName); + break; + case NymeaConnection.ConnectionStatusSslError: + errorMessage = qsTr("An unrecovareable SSL Error happened. Please make sure certificates are installed correctly."); + break; + case NymeaConnection.ConnectionStatusSslUntrusted: + errorMessage = qsTr("The SSL Certificate is not trusted."); + break; + case NymeaConnection.ConnectionStatusUnknownError: + default: + errorMessage = qsTr("An unknown error happened. We're very sorry for that. (Error code: %1)").arg(engine.connection.connectionStatus); + } + return errorMessage; + } + font.pixelSize: app.smallFont + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + horizontalAlignment: Text.AlignHCenter + } } Button {