From 196709ffc4e0c166922b53e93ab8edfb02101224 Mon Sep 17 00:00:00 2001 From: 0xFEEDC0DE64 Date: Wed, 19 Aug 2026 20:40:18 +0200 Subject: [PATCH] Fix solalaweb integration --- evcharger-app/CMakeLists.txt | 1 + evcharger-app/appsettings.cpp | 164 ++++++- evcharger-app/appsettings.h | 37 +- evcharger-app/deviceconnection.cpp | 83 ++-- evcharger-app/deviceconnection.h | 4 + evcharger-app/i18n/qml_da.ts | 420 +++++++++++------ evcharger-app/i18n/qml_de.ts | 424 +++++++++++------- evcharger-app/i18n/qml_en.ts | 4 +- evcharger-app/i18n/qml_fi.ts | 420 +++++++++++------ evcharger-app/i18n/qml_nb.ts | 420 +++++++++++------ evcharger-app/i18n/qml_sv.ts | 420 +++++++++++------ evcharger-app/i18n/qml_tr.ts | 420 +++++++++++------ evcharger-app/qml/AppSettingsPage.qml | 89 ++-- evcharger-app/qml/AppTheme.qml | 1 + evcharger-app/qml/DeviceListScreen.qml | 3 +- evcharger-app/qml/DeviceScreen.qml | 16 + .../qml/HomeAssistantSetupDialog.qml | 70 ++- evcharger-app/qml/InformationsTabPage.qml | 12 +- evcharger-app/qml/SolalawebSetupDialog.qml | 155 +++++++ evcharger-app/qml/qmldir | 1 + 20 files changed, 2145 insertions(+), 1019 deletions(-) create mode 100644 evcharger-app/qml/SolalawebSetupDialog.qml diff --git a/evcharger-app/CMakeLists.txt b/evcharger-app/CMakeLists.txt index ee72922..da74bbc 100644 --- a/evcharger-app/CMakeLists.txt +++ b/evcharger-app/CMakeLists.txt @@ -167,6 +167,7 @@ qt_add_qml_module(evcharger-app qml/SettingsTabPage.qml qml/SetValueHelper.qml qml/SimpleNavigationItem.qml + qml/SolalawebSetupDialog.qml qml/StartStopButton.qml qml/SwitchLanguagePage.qml qml/TimeComponentLabel.qml diff --git a/evcharger-app/appsettings.cpp b/evcharger-app/appsettings.cpp index 02626c3..961af72 100644 --- a/evcharger-app/appsettings.cpp +++ b/evcharger-app/appsettings.cpp @@ -1,7 +1,47 @@ #include "appsettings.h" -#include -#include +#include + +using namespace std::chrono_literals; + +namespace +{ +QByteArray basicAuthorization(const QString &username, const QString &password) +{ + QByteArray credentials = username.toUtf8(); + credentials.append(':'); + credentials.append(password.toUtf8()); + return "Basic " + credentials.toBase64(); +} +} + +AppSettings::AppSettings() +{ + m_solalawebVerificationTimeout.setSingleShot(true); + m_solalawebVerificationTimeout.setInterval(15s); + + connect(&m_solalawebVerificationTimeout, &QTimer::timeout, + this, [this] { + finishSolalawebVerification(false, tr("The Solalaweb authentication check timed out.")); + }); + connect(&m_solalawebVerificationSocket, &QWebSocket::connected, + this, [this] { + finishSolalawebVerification(true); + }); + connect(&m_solalawebVerificationSocket, &QWebSocket::errorOccurred, + this, [this](QAbstractSocket::SocketError) { + finishSolalawebVerification( + false, + tr("Authentication could not be verified: %1") + .arg(m_solalawebVerificationSocket.errorString())); + }); + + // Old installations may still have the visibility flag set from the + // certificate-based implementation. Never expose Solalaweb until the new + // Authentik credentials have completed a successful check. + if (!solalawebCredentialsVerified() && showSolalaweb()) + setShowSolalaweb(false); +} QLocale::Language AppSettings::uiLanguage() const { @@ -48,30 +88,114 @@ void AppSettings::setUiLanguage(QLocale::Language uiLanguage) emit uiLanguageChanged(uiLanguage); } -bool AppSettings::loadSolalawebKey(const QString &url) +QString AppSettings::solalawebUsername() const { - QFile file{QQmlFile::urlToLocalFileOrQrc(url)}; - if (!file.open(QFile::ReadOnly)) - { - qWarning() << "Could not open file:" << file.errorString(); - return false; - } - - setSolalawebKey(file.readAll()); - - return true; + return value("solalawebUsername").toString(); } -bool AppSettings::loadSolalawebCert(const QString &url) +QString AppSettings::solalawebPassword() const { - QFile file{QQmlFile::urlToLocalFileOrQrc(url)}; - if (!file.open(QFile::ReadOnly)) + return value("solalawebPassword").toString(); +} + +bool AppSettings::solalawebCredentialsVerified() const +{ + return value("solalawebCredentialsVerified", false).toBool() + && !solalawebUsername().isEmpty() + && !solalawebPassword().isEmpty(); +} + +void AppSettings::verifySolalawebCredentials(const QString &username, + const QString &appPassword) +{ + if (m_solalawebVerificationInProgress) + return; + + m_pendingSolalawebUsername = username.trimmed(); + m_pendingSolalawebPassword = appPassword; + if (m_pendingSolalawebUsername.isEmpty() || m_pendingSolalawebPassword.isEmpty()) { - qWarning() << "Could not open file:" << file.errorString(); - return false; + setSolalawebVerificationError(tr("Enter both the username and the app password.")); + emit solalawebVerificationFinished(false); + return; } - setSolalawebCert(file.readAll()); + setSolalawebVerificationError({}); + m_solalawebVerificationInProgress = true; + emit solalawebVerificationInProgressChanged(true); - return true; + QNetworkRequest request{QUrl{QStringLiteral("wss://solalaweb.com/123456")}}; + request.setRawHeader("Authorization", + basicAuthorization(m_pendingSolalawebUsername, + m_pendingSolalawebPassword)); + m_solalawebVerificationTimeout.start(); + m_solalawebVerificationSocket.open(request); +} + +void AppSettings::clearSolalawebCredentials() +{ + const auto oldUsername = solalawebUsername(); + remove("solalawebUsername"); + remove("solalawebPassword"); + remove("solalawebCredentialsVerified"); + setShowSolalaweb(false); + setSolalawebVerificationError({}); + if (!oldUsername.isEmpty()) + emit solalawebUsernameChanged({}); + emit solalawebCredentialsVerifiedChanged(false); +} + +void AppSettings::invalidateSolalawebCredentials(const QString &reason) +{ + setSolalawebCredentialsVerified(false); + setShowSolalaweb(false); + setSolalawebVerificationError(reason); +} + +void AppSettings::finishSolalawebVerification(bool success, const QString &error) +{ + if (!m_solalawebVerificationInProgress) + return; + + m_solalawebVerificationInProgress = false; + emit solalawebVerificationInProgressChanged(false); + m_solalawebVerificationTimeout.stop(); + + if (success) + { + const auto oldUsername = solalawebUsername(); + setValue("solalawebUsername", m_pendingSolalawebUsername); + setValue("solalawebPassword", m_pendingSolalawebPassword); + if (oldUsername != m_pendingSolalawebUsername) + emit solalawebUsernameChanged(m_pendingSolalawebUsername); + setSolalawebCredentialsVerified(true); + setSolalawebVerificationError({}); + } + else + { + setSolalawebVerificationError(error); + } + + m_pendingSolalawebUsername.clear(); + m_pendingSolalawebPassword.clear(); + m_solalawebVerificationSocket.abort(); + emit solalawebVerificationFinished(success); +} + +void AppSettings::setSolalawebCredentialsVerified(bool verified) +{ + if (solalawebCredentialsVerified() == verified) + return; + + setValue("solalawebCredentialsVerified", verified); + emit solalawebCredentialsVerifiedChanged(verified); +} + +void AppSettings::setSolalawebVerificationError(const QString &error) +{ + if (m_solalawebVerificationError == error) + return; + + m_solalawebVerificationError = error; + emit solalawebVerificationErrorChanged(error); } diff --git a/evcharger-app/appsettings.h b/evcharger-app/appsettings.h index 7a87040..0d4aba3 100644 --- a/evcharger-app/appsettings.h +++ b/evcharger-app/appsettings.h @@ -1,6 +1,8 @@ #pragma once #include +#include +#include #include #include "goesettings.h" @@ -10,8 +12,14 @@ class AppSettings : public GoeSettings Q_OBJECT QML_ELEMENT Q_PROPERTY(QLocale::Language uiLanguage READ uiLanguage WRITE setUiLanguage NOTIFY uiLanguageChanged FINAL) + Q_PROPERTY(QString solalawebUsername READ solalawebUsername NOTIFY solalawebUsernameChanged FINAL) + Q_PROPERTY(bool solalawebCredentialsVerified READ solalawebCredentialsVerified NOTIFY solalawebCredentialsVerifiedChanged FINAL) + Q_PROPERTY(bool solalawebVerificationInProgress READ solalawebVerificationInProgress NOTIFY solalawebVerificationInProgressChanged FINAL) + Q_PROPERTY(QString solalawebVerificationError READ solalawebVerificationError NOTIFY solalawebVerificationErrorChanged FINAL) public: + AppSettings(); + enum UiLanguageValue { SystemLanguage = QLocale::AnyLanguage, GermanLanguage = QLocale::German, @@ -27,10 +35,35 @@ public: QLocale::Language uiLanguage() const; void setUiLanguage(QLocale::Language uiLanguage); - Q_INVOKABLE bool loadSolalawebKey(const QString &url); - Q_INVOKABLE bool loadSolalawebCert(const QString &url); + QString solalawebUsername() const; + QString solalawebPassword() const; + bool solalawebCredentialsVerified() const; + bool solalawebVerificationInProgress() const { return m_solalawebVerificationInProgress; } + QString solalawebVerificationError() const { return m_solalawebVerificationError; } + + Q_INVOKABLE void verifySolalawebCredentials(const QString &username, + const QString &appPassword); + Q_INVOKABLE void clearSolalawebCredentials(); + void invalidateSolalawebCredentials(const QString &reason); signals: void uiLanguageChanged(QLocale::Language uiLanguage); void homeAssistantConfigurationChanged(); + void solalawebUsernameChanged(const QString &username); + void solalawebCredentialsVerifiedChanged(bool verified); + void solalawebVerificationInProgressChanged(bool inProgress); + void solalawebVerificationErrorChanged(const QString &error); + void solalawebVerificationFinished(bool success); + +private: + void finishSolalawebVerification(bool success, const QString &error = {}); + void setSolalawebCredentialsVerified(bool verified); + void setSolalawebVerificationError(const QString &error); + + QWebSocket m_solalawebVerificationSocket; + QTimer m_solalawebVerificationTimeout; + bool m_solalawebVerificationInProgress{}; + QString m_pendingSolalawebUsername; + QString m_pendingSolalawebPassword; + QString m_solalawebVerificationError; }; diff --git a/evcharger-app/deviceconnection.cpp b/evcharger-app/deviceconnection.cpp index 4dbb1e5..f1edc25 100644 --- a/evcharger-app/deviceconnection.cpp +++ b/evcharger-app/deviceconnection.cpp @@ -4,11 +4,9 @@ #include #include #include +#include #include #include -#include -#include -#include #include #include @@ -51,6 +49,14 @@ QString deriveBcryptPassword(const QString &password, const QString &serial) return QString::fromLatin1(fullHash.mid(salt.size(), 32)); } + +QByteArray basicAuthorization(const QString &username, const QString &password) +{ + QByteArray credentials = username.toUtf8(); + credentials.append(':'); + credentials.append(password.toUtf8()); + return "Basic " + credentials.toBase64(); +} } DeviceConnection::DeviceConnection(QObject *parent) : @@ -94,38 +100,35 @@ void DeviceConnection::setUrl(const QString &url) void DeviceConnection::start() { emit logMessage(tr("Connecting to %0").arg(m_url)); + openWebSocket(); +} - if (m_settings && !m_settings->solalawebKey().isEmpty() && !m_settings->solalawebCert().isEmpty()) +void DeviceConnection::openWebSocket() +{ + QNetworkRequest request{QUrl{m_url}}; + if (isSolalawebConnection()) { - auto sslConfig = m_websocket.sslConfiguration(); - + if (!m_settings || !m_settings->solalawebCredentialsVerified()) { - QSslCertificate cert{m_settings->solalawebCert().toUtf8()}; - if (cert.isNull()) - { - emit logMessage(tr("Could not parse solalaweb certificate!")); - goto after; - } - qDebug() << "cert" << cert.issuerDisplayName(); - sslConfig.setLocalCertificate(cert); + const auto message = tr("Solalaweb authentication must be configured again."); + emit logMessage(message); + emit solalawebAuthenticationRequired(message); + return; } - { - QSslKey key{m_settings->solalawebKey().toUtf8(), QSsl::KeyAlgorithm::Rsa, QSsl::Pem}; - if (key.isNull()) - { - emit logMessage(tr("Could not parse solalaweb key!")); - goto after; - } - qDebug() << "key" << key.algorithm(); - sslConfig.setPrivateKey(key); - } - - m_websocket.setSslConfiguration(sslConfig); + request.setRawHeader("Authorization", + basicAuthorization(m_settings->solalawebUsername(), + m_settings->solalawebPassword())); } -after: - m_websocket.open(QUrl{m_url}); + m_solalawebAuthenticationFailed = false; + m_websocket.open(request); +} + +bool DeviceConnection::isSolalawebConnection() const +{ + return QUrl{m_url}.host().compare(QStringLiteral("solalaweb.com"), + Qt::CaseInsensitive) == 0; } void DeviceConnection::setPassword(const QString &password) @@ -537,9 +540,8 @@ void DeviceConnection::disconnected() emit showDisturbed(); emit logMessage(tr("Reconnecting to %0").arg(m_url)); - QTimer::singleShot(1s, this, [this](){ - m_websocket.open(QUrl{m_url}); - }); + if (!m_solalawebAuthenticationFailed) + QTimer::singleShot(1s, this, &DeviceConnection::openWebSocket); } void DeviceConnection::stateChanged(QAbstractSocket::SocketState state) @@ -580,6 +582,25 @@ void DeviceConnection::errorOccurred(QAbstractSocket::SocketError error) { qDebug() << error; emit logMessage(tr("error occured: %0").arg(enumToString(error))); + + if (!isSolalawebConnection()) + return; + + const auto errorText = m_websocket.errorString(); + if (errorText.contains("401") + || errorText.contains("403") + || errorText.contains("302") + || errorText.contains("unauthorized", Qt::CaseInsensitive) + || errorText.contains("forbidden", Qt::CaseInsensitive) + || errorText.contains("redirect", Qt::CaseInsensitive)) + { + m_solalawebAuthenticationFailed = true; + const auto message = tr("Solalaweb rejected the saved authentication: %1") + .arg(errorText); + if (m_settings) + m_settings->invalidateSolalawebCredentials(message); + emit solalawebAuthenticationRequired(message); + } } void DeviceConnection::peerVerifyError(const QSslError &error) diff --git a/evcharger-app/deviceconnection.h b/evcharger-app/deviceconnection.h index aeb71dd..bf8c6b7 100644 --- a/evcharger-app/deviceconnection.h +++ b/evcharger-app/deviceconnection.h @@ -61,6 +61,7 @@ signals: void authError(const QString &message); void authImpossible(); void authSuccess(); + void solalawebAuthenticationRequired(const QString &message); void fullStatusReceived(); void valueChanged(const QString &key, const QVariant &value); @@ -90,6 +91,8 @@ private: void sendAuthInternal(); void authResponse(const QString &type, const QVariantMap &message); + void openWebSocket(); + bool isSolalawebConnection() const; AppSettings *m_settings{}; @@ -110,6 +113,7 @@ private: PasswordHashAlgorithm m_passwordHashAlgorithm{PasswordHashAlgorithm::Pbkdf2}; QString m_password; + bool m_solalawebAuthenticationFailed{}; QHash m_callbacks; diff --git a/evcharger-app/i18n/qml_da.ts b/evcharger-app/i18n/qml_da.ts index b23f29b..2bbcdda 100644 --- a/evcharger-app/i18n/qml_da.ts +++ b/evcharger-app/i18n/qml_da.ts @@ -165,54 +165,100 @@ https://github.com/goecharger/go-eCharger-API-v1/blob/master/go-eCharger%20API%20v1%20EN.md + + AppSettings + + + The Solalaweb authentication check timed out. + Timeout under kontrollen af Solalaweb-godkendelse. + + + + Authentication could not be verified: %1 + Godkendelsen kunne ikke bekræftes: %1 + + + + Enter both the username and the app password. + Indtast både brugernavn og appadgangskode. + + AppSettingsPage - + App Settings App-indstillinger - + Language Sprog - + Number of app instances: Antal app-forekomster: - + Swipe left or right with three fingers to switch between app instances. Stryg til venstre eller højre med tre fingre for at skifte mellem appinstanser. - + + Solalaweb + Solalaweb + + + + Set up Authentik access to make the private Solalaweb connection available for saved devices. + Konfigurer Authentik-adgang, så den private Solalaweb-forbindelse bliver tilgængelig for gemte enheder. + + + + Authentication verified for %1 + Godkendelse bekræftet for %1 + + + + Authentication has not been verified + Godkendelsen er ikke bekræftet + + + + Change Solalaweb authentication + Skift Solalaweb-godkendelse + + + + Set up Solalaweb + Konfigurer Solalaweb + + + + Show Solalaweb + Vis Solalaweb + + solalaweb key: - solalaweb nøgle: + solalaweb nøgle: - - Select... - Vælg... + Vælg... - - Replace... - Erstat... + Erstat... - solalaweb cert: - solalaweb certifikat: + solalaweb certifikat: - Show solalaweb: - Vis solalaweb: + Vis solalaweb: @@ -1752,227 +1798,235 @@ DeviceConnection - + Connecting to %0 Opretter forbindelse til %0 - Could not parse solalaweb certificate! - Kunne ikke parse solalaweb certifikat! + Kunne ikke parse solalaweb certifikat! - Could not parse solalaweb key! - Kunne ikke parse solalaweb nøgle! + Kunne ikke parse solalaweb nøgle! - + + Solalaweb authentication must be configured again. + Solalaweb-godkendelsen skal konfigureres igen. + + + Received something that is not a json object! Modtog noget, der ikke er et json-objekt! - + Received something that does not contain a type! Modtaget noget, der ikke indeholder en type! - + Received something with a non-string type! Modtaget noget med en ikke-streng type! - + Received message type %0 %1 Modtaget meddelelsestype %0 %1 - + Received hello without serial! Modtaget hej uden føljeton! - + Received hello with a non-string serial! Modtaget hej med en ikke-streng føljeton! - + Received hello with a non-bool secured! Modtaget hej med en ikke-bool sikret! - + Received hello without manufacturer! Modtaget hej uden producent! - + Received hello with a non-string manufacturer! Modtaget hej med en ikke-streng producent! - + Received hello without devicetype! Modtaget hej uden devicetype! - + Received hello with a non-string devicetype! Modtaget hej med en ikke-streng enhedstype! - + Received hello without friendly_name! Modtaget hej uden friendly_name! - + Received hello with a non-string friendly_name! Modtaget hej med et ikke-strengvenligt_navn! - + Received authRequired without token1! Modtog authRequired uden token1! - + Received authRequired with a non-string token1! Modtog authRequired, hvor token1 ikke er en streng! - + Received authRequired without token2! Modtog authRequired uden token2! - + Received authRequired with a non-string token2! Modtog authRequired, hvor token2 ikke er en streng! - + Received authRequired with a non-string hash algorithm! Modtog authRequired, hvor hash-algoritmen ikke er en streng! - + Received authRequired with unsupported hash algorithm %0! Modtog authRequired med hash-algoritmen %0, som ikke understøttes! - + Received fullStatus with a non-bool partial! Modtog fuld status med en ikke-bool partial! - + Received fullStatus without a status! Modtaget fuld status uden status! - + Received fullStatus with a non-object status! Modtaget fuld status med en ikke-objekt status! - + Received partial fullStatus Modtaget delvis fuld status - + Received last fullStatus Modtaget sidste fuldstatus - + Received deltaStatus without a status! Modtaget deltaStatus uden status! - + Received deltaStatus with a non-object status! Modtaget deltaStatus med en ikke-objekt status! - + Received message with a non-string requestId! Modtaget besked med et ikke-streng requestId! - + Sending %0 Sender %0 - + Could not derive bcrypt authentication hash! Kunne ikke udlede bcrypt-godkendelses-hash! - + Connected! Forbundet! - + Disconnected! Ikke forbundet! - + Reconnecting to %0 Genopretter forbindelse til %0 - + state changed: %0 tilstand ændret: %0 - + could not parse received json: %0 at offset %1 kunne ikke parse modtaget json: %0 ved offset %1 - + unknown binary message type %0 received ukendt binær meddelelsestype %0 modtaget - + error occured: %0 der opstod en fejl: %0 - + + Solalaweb rejected the saved authentication: %1 + Solalaweb afviste den gemte godkendelse: %1 + + + ssl peer verify error ssl peer verify fejl - + ssl errors ssl fejl - + ssl alert sent level=%0 type=%1 description=%2 ssl alarm sendt niveau=%0 type=%1 beskrivelse=%2 - + ssl alert received level=%0 type=%1 description=%2 ssl alarm modtaget niveau=%0 type=%1 beskrivelse=%2 - + ssl handshake interrupted on error ssl-håndtryk afbrudt ved fejl - + unknown response type %0 ukendt svartype %0 @@ -2053,7 +2107,7 @@ Solala - + Add or setup device Tilføj eller opsæt enhed @@ -2061,32 +2115,32 @@ DeviceScreen - + Password required Adgangskode påkrævet - + Password: Adgangskode: - + Password Adgangskode - + Authentication impossible! Autentificering umulig! - + To use this password remotely a password has to be setup first. This can be done over the AccessPoint. For fjernadgang skal der først konfigureres en adgangskode. Det kan gøres via adgangspunktet. - + Connection disturbed Forbindelsen forstyrret @@ -2928,37 +2982,37 @@ HomeAssistantSetupDialog - + Edit chart Rediger diagram - + Connect Home Assistant Forbind Home Assistant - + Server Server - + Login Login - + Charts Diagrammer - + %1. %2 %1. %2 - + Before you begin Før du begynder @@ -2981,7 +3035,7 @@ Før diagrammer kan modtage data: • Kontrollér, at laderens entiteter er synlige i Home Assistant. - + Home Assistant must already be installed and running. A Raspberry Pi with Home Assistant on an SD card is one option; other supported Home Assistant installations work as well. Before charts can receive data: @@ -3000,78 +3054,83 @@ Før diagrammer kan modtage data: • Kontrollér, at enhedens entiteter er synlige i Home Assistant. - + Installation guide Installationsvejledning - + MQTT guide MQTT-vejledning - + Enter the address you normally use to open Home Assistant. The app will contact this server directly. Indtast den adresse, du normalt bruger til at åbne Home Assistant. Appen kontakter denne server direkte. - - + + Cancel Annuller - + Next Næste - + Create a long-lived access token in your Home Assistant profile and paste it below. Your Home Assistant password is never entered into this app. Opret et langtidsholdbart adgangstoken i din Home Assistant-profil, og indsæt det nedenfor. Din Home Assistant-adgangskode indtastes aldrig i denne app. - + Open Home Assistant profile Åbn Home Assistant-profil - + Long-lived access token Langtidsholdbart adgangstoken - + Hide Skjul - + Show Vis - + Back Tilbage - + Connect Opret forbindelse - + Create charts and choose exactly which Home Assistant entities each chart should display. Opret diagrammer, og vælg præcist, hvilke Home Assistant-entiteter hvert diagram skal vise. - + Change server or access token Skift server eller adgangstoken + + + Forget Home Assistant configuration + Glem Home Assistant-konfigurationen + - + %n entity(s) %n entitet @@ -3079,42 +3138,42 @@ Før diagrammer kan modtage data: - + Edit Rediger - + Delete Slet - + No charts configured yet. Der er endnu ikke konfigureret nogen diagrammer. - + Add chart Tilføj diagram - + Done Færdig - + Chart title Diagramtitel - + Search by name, entity ID, unit or device class… Søg efter navn, entitets-id, enhed eller enhedsklasse… - + %n entity(s) selected %n entitet valgt @@ -3122,17 +3181,17 @@ Før diagrammer kan modtage data: - + Reload Indlæs igen - + No matching entities found. Ingen matchende entiteter fundet. - + Save chart Gem diagram @@ -3292,7 +3351,7 @@ Før diagrammer kan modtage data: Information - + Idle Inaktiv @@ -3305,138 +3364,137 @@ Før diagrammer kan modtage data: INDLÆSER - + %1 – %2 %1 – %2 - + Receiving manufacturer data… Modtager producentdata… - + Loading manufacturer charts… Indlæser producentdiagrammer… - + %1 images %1 billeder - + %1 charts %1 diagrammer - + Loaded %1 %1 indlæst - + No information data received Ingen informationsdata modtaget - + The manufacturer cloud returned invalid data. Producentens cloud returnerede ugyldige data. - + Requesting manufacturer data… Anmoder om producentdata… - + Information Information - + Manufacturer cloud Producentens cloud - + The manufacturer does not even think you are worth the raw data that you could inspect and zoom. Instead, it sends these ugly low-resolution pictures that you cannot meaningfully interact with—let alone control the displayed time range. Producenten mener ikke engang, at du er værdig til rådataene, som du kunne undersøge og zoome ind i. I stedet sender den disse grimme billeder i lav opløsning, som du ikke kan interagere meningsfuldt med – endsige styre det viste tidsinterval. - + Own your consumption history Bevar ejerskabet over din forbrugshistorik - + Connect the device to your own Home Assistant installation for fast, dependable history that remains under your control. You decide how long data is retained and which measurements are recorded. Forbind enheden med din egen Home Assistant-installation for at få hurtig og pålidelig historik, der forbliver under din kontrol. Du bestemmer, hvor længe data gemmes, og hvilke målinger der registreres. - + Connected to Home Assistant Forbundet med Home Assistant - + Home Assistant is not configured Home Assistant er ikke konfigureret - + Configure Konfigurer - - + + Set up Konfigurer - + Refresh Opdater - + Connect Home Assistant to display history Forbind Home Assistant for at vise historik - + Create your first history chart Opret dit første historikdiagram - + The setup wizard connects to your server and lets you select the entities to display. Opsætningsguiden opretter forbindelse til din server og lader dig vælge de entiteter, der skal vises. - + Open the configuration and add a chart with one or more Home Assistant entities. Åbn konfigurationen, og tilføj et diagram med en eller flere Home Assistant-entiteter. - + Add chart Tilføj diagram - Forget Home Assistant configuration - Glem Home Assistant-konfigurationen + Glem Home Assistant-konfigurationen - + Forget Home Assistant? Glem Home Assistant? - + This removes the server address, access token and all chart definitions stored in this app. Dette fjerner serveradressen, adgangstokenet og alle diagramdefinitioner, der er gemt i appen. @@ -3445,7 +3503,7 @@ Før diagrammer kan modtage data: Begrænset · upålidelig · langsom - + Your own cloud Din egen cloud @@ -3454,22 +3512,22 @@ Før diagrammer kan modtage data: Historik · vedligeholdt · hurtig - + Lacks features · unreliable · slow Mangler funktioner · upålidelig · langsom - + Historical data · properly maintained · fast Historiske data · godt vedligeholdt · hurtig - + The manufacturer cloud provides basic charts, but can be slow, unavailable or limited to the data selected by the manufacturer. Producentens cloud leverer grundlæggende diagrammer, men kan være langsom, utilgængelig eller begrænset til de data, som producenten har valgt. - + Download information Download information @@ -3490,37 +3548,37 @@ Før diagrammer kan modtage data: Opsæt forbindelse til Home Assistant - + Historical data Historiske data - + Day Dag - + Week Uge - + Month Måned - + Year År - + Previous Forrige - + Next Næste @@ -5104,6 +5162,74 @@ Før diagrammer kan modtage data: Licenser + + SolalawebSetupDialog + + + Set up Solalaweb + Konfigurer Solalaweb + + + + Solalaweb now uses Authentik. Create a dedicated app password instead of entering your normal account password. Choose a lifetime long enough for this app, then copy the password itself—not its name. + Solalaweb bruger nu Authentik. Opret en særskilt appadgangskode i stedet for at indtaste din normale kontoadgangskode. Vælg en gyldighedsperiode, der er lang nok til denne app, og kopiér derefter selve adgangskoden – ikke dens navn. + + + + Create an Authentik app password + Opret en Authentik-appadgangskode + + + + Your username is usually your email address. The user-details page shows the exact username expected by Authentik. + Dit brugernavn er normalt din e-mailadresse. Siden med brugeroplysninger viser det nøjagtige brugernavn, som Authentik forventer. + + + + Open Authentik user details + Åbn brugeroplysninger i Authentik + + + + Username + Brugernavn + + + + Username or email address + Brugernavn eller e-mailadresse + + + + App password + Appadgangskode + + + + Authentik app password + Authentik-appadgangskode + + + + Hide + Skjul + + + + Show + Vis + + + + Cancel + Annuller + + + + Verify and save + Bekræft og gem + + StartStopButton diff --git a/evcharger-app/i18n/qml_de.ts b/evcharger-app/i18n/qml_de.ts index 414147b..4c05225 100644 --- a/evcharger-app/i18n/qml_de.ts +++ b/evcharger-app/i18n/qml_de.ts @@ -177,54 +177,100 @@ https://github.com/goecharger/go-eCharger-API-v1/blob/master/go-eCharger%20API%20v1%20DE.md + + AppSettings + + + The Solalaweb authentication check timed out. + Zeitüberschreitung bei der Solalaweb-Authentifizierungsprüfung. + + + + Authentication could not be verified: %1 + Die Authentifizierung konnte nicht überprüft werden: %1 + + + + Enter both the username and the app password. + Gib sowohl den Benutzernamen als auch das App-Passwort ein. + + AppSettingsPage - + App Settings App Einstellungen - + Language Sprache - + Number of app instances: Anzahl an App Instanzen: - + Swipe left or right with three fingers to switch between app instances. Mit drei Fingern nach links oder rechts wischen, um zwischen App-Instanzen zu wechseln. - + + Solalaweb + Solalaweb + + + + Set up Authentik access to make the private Solalaweb connection available for saved devices. + Richte den Authentik-Zugang ein, um die private Solalaweb-Verbindung für gespeicherte Geräte verfügbar zu machen. + + + + Authentication verified for %1 + Authentifizierung für %1 bestätigt + + + + Authentication has not been verified + Die Authentifizierung wurde nicht bestätigt + + + + Change Solalaweb authentication + Solalaweb-Authentifizierung ändern + + + + Set up Solalaweb + Solalaweb einrichten + + + + Show Solalaweb + Solalaweb anzeigen + + solalaweb key: - solalaweb key: + solalaweb key: - - Select... - Auswählen... + Auswählen... - - Replace... - Ersetzen... + Ersetzen... - solalaweb cert: - solalaweb cert: + solalaweb cert: - Show solalaweb: - Zeige solalaweb: + Zeige solalaweb: @@ -1864,227 +1910,227 @@ Unbekannt - + Connecting to %0 Verbinde zu %0 - + Received something that is not a json object! - + Received something that does not contain a type! - + Received something with a non-string type! - + Received hello without serial! - + Received hello with a non-string serial! - + Received hello with a non-bool secured! - + Received hello without manufacturer! - + Received hello with a non-string manufacturer! - + Received hello without friendly_name! - + Received hello with a non-string friendly_name! - + Received hello without devicetype! - - Could not parse solalaweb certificate! - - - - - Could not parse solalaweb key! - - - - + Received hello with a non-string devicetype! - + Received authRequired without token1! - + Received authRequired with a non-string token1! - + Received authRequired without token2! - + Received authRequired with a non-string token2! - + Received fullStatus with a non-bool partial! - + Received fullStatus without a status! - + Received fullStatus with a non-object status! - + Received partial fullStatus - + Received last fullStatus - + Received deltaStatus without a status! - + Received deltaStatus with a non-object status! - + Received message type %0 %1 - + + Solalaweb authentication must be configured again. + Die Solalaweb-Authentifizierung muss erneut eingerichtet werden. + + + Received authRequired with a non-string hash algorithm! - + Received authRequired with unsupported hash algorithm %0! - + Received message with a non-string requestId! - + Sending %0 - + Could not derive bcrypt authentication hash! - + Connected! Verbunden! - + Disconnected! Verbindung verloren! - + Reconnecting to %0 Verbinde wieder zu %0 - + state changed: %0 - + could not parse received json: %0 at offset %1 - + unknown binary message type %0 received - + error occured: %0 - + + Solalaweb rejected the saved authentication: %1 + Solalaweb hat die gespeicherte Authentifizierung abgelehnt: %1 + + + ssl peer verify error - + ssl errors - + ssl alert sent level=%0 type=%1 description=%2 - + ssl alert received level=%0 type=%1 description=%2 - + ssl handshake interrupted on error - + unknown response type %0 @@ -2161,7 +2207,7 @@ Solala - + Add or setup device Gerät hinzufügen oder einrichten @@ -2221,32 +2267,32 @@ DeviceScreen - + Password required Passwort erforderlich - + Password: Passwort: - + Password Passwort - + Authentication impossible! Authentifizierung unmöglich! - + To use this password remotely a password has to be setup first. This can be done over the AccessPoint. Um dieses Gerät aus der Ferne nutzen zu können, müssen Sie erst ein Passwort einrichten. Dies kann über den AccessPoint gemacht werden. - + Connection disturbed Verbindung schwer gestört @@ -3103,37 +3149,37 @@ HomeAssistantSetupDialog - + Edit chart Diagramm bearbeiten - + Connect Home Assistant Home Assistant verbinden - + Server Server - + Login Anmeldung - + Charts Diagramme - + %1. %2 %1. %2 - + Before you begin Bevor du beginnst @@ -3156,7 +3202,7 @@ Bevor Diagramme Daten empfangen können: • Prüfe, ob die Entitäten des Chargers in Home Assistant sichtbar sind. - + Home Assistant must already be installed and running. A Raspberry Pi with Home Assistant on an SD card is one option; other supported Home Assistant installations work as well. Before charts can receive data: @@ -3175,78 +3221,83 @@ Bevor Diagramme Daten empfangen können: • Prüfe, ob die Entitäten des Geräts in Home Assistant sichtbar sind. - + Installation guide Installationsanleitung - + MQTT guide MQTT-Anleitung - + Enter the address you normally use to open Home Assistant. The app will contact this server directly. Gib die Adresse ein, über die du Home Assistant normalerweise öffnest. Die App verbindet sich direkt mit diesem Server. - - + + Cancel Abbrechen - + Next Weiter - + Create a long-lived access token in your Home Assistant profile and paste it below. Your Home Assistant password is never entered into this app. Erstelle in deinem Home-Assistant-Profil ein langlebiges Zugriffstoken und füge es unten ein. Dein Home-Assistant-Passwort wird niemals in diese App eingegeben. - + Open Home Assistant profile Home-Assistant-Profil öffnen - + Long-lived access token Langlebiges Zugriffstoken - + Hide Ausblenden - + Show Anzeigen - + Back Zurück - + Connect Verbinden - + Create charts and choose exactly which Home Assistant entities each chart should display. Erstelle Diagramme und wähle genau aus, welche Home-Assistant-Entitäten jedes Diagramm anzeigen soll. - + Change server or access token Server oder Zugriffstoken ändern + + + Forget Home Assistant configuration + Home-Assistant-Konfiguration vergessen + - + %n entity(s) %n Entität @@ -3254,42 +3305,42 @@ Bevor Diagramme Daten empfangen können: - + Edit Bearbeiten - + Delete Löschen - + No charts configured yet. Noch keine Diagramme eingerichtet. - + Add chart Diagramm hinzufügen - + Done Fertig - + Chart title Diagrammtitel - + Search by name, entity ID, unit or device class… Nach Name, Entitäts-ID, Einheit oder Geräteklasse suchen… - + %n entity(s) selected %n Entität ausgewählt @@ -3297,17 +3348,17 @@ Bevor Diagramme Daten empfangen können: - + Reload Neu laden - + No matching entities found. Keine passenden Entitäten gefunden. - + Save chart Diagramm speichern @@ -3467,143 +3518,142 @@ Bevor Diagramme Daten empfangen können: Informationen - + Idle Inaktiv - + %1 – %2 %1 – %2 - + Receiving manufacturer data… Herstellerdaten werden empfangen… - + Loading manufacturer charts… Herstellerdiagramme werden geladen… - + %1 images %1 Bilder - + %1 charts %1 Diagramme - + Loaded %1 %1 geladen - + No information data received Keine Informationsdaten empfangen - + The manufacturer cloud returned invalid data. Die Hersteller-Cloud hat ungültige Daten zurückgegeben. - + Requesting manufacturer data… Herstellerdaten werden angefordert… - + Information Informationen - + Manufacturer cloud Hersteller-Cloud - + The manufacturer does not even think you are worth the raw data that you could inspect and zoom. Instead, it sends these ugly low-resolution pictures that you cannot meaningfully interact with—let alone control the displayed time range. Der Hersteller hält dich nicht einmal für würdig, die Rohdaten zu erhalten, die du untersuchen und vergrößern könntest. Stattdessen schickt er diese hässlichen Bilder in niedriger Auflösung, mit denen du nicht sinnvoll interagieren kannst – geschweige denn den angezeigten Zeitraum steuern. - + Own your consumption history Dein Verbrauchsverlauf gehört dir - + Connect the device to your own Home Assistant installation for fast, dependable history that remains under your control. You decide how long data is retained and which measurements are recorded. Verbinde das Gerät mit deiner eigenen Home-Assistant-Installation, um einen schnellen, zuverlässigen Verlauf unter deiner Kontrolle zu erhalten. Du bestimmst, wie lange Daten aufbewahrt und welche Messwerte aufgezeichnet werden. - + Connected to Home Assistant Mit Home Assistant verbunden - + Home Assistant is not configured Home Assistant ist nicht eingerichtet - + Configure Konfigurieren - - + + Set up Einrichten - + Refresh Aktualisieren - + Connect Home Assistant to display history Verbinde Home Assistant, um den Verlauf anzuzeigen - + Create your first history chart Erstelle dein erstes Verlaufsdiagramm - + The setup wizard connects to your server and lets you select the entities to display. Der Einrichtungsassistent verbindet sich mit deinem Server und lässt dich die anzuzeigenden Entitäten auswählen. - + Open the configuration and add a chart with one or more Home Assistant entities. Öffne die Konfiguration und füge ein Diagramm mit einer oder mehreren Home-Assistant-Entitäten hinzu. - + Add chart Diagramm hinzufügen - Forget Home Assistant configuration - Home-Assistant-Konfiguration vergessen + Home-Assistant-Konfiguration vergessen - + Forget Home Assistant? Home Assistant vergessen? - + This removes the server address, access token and all chart definitions stored in this app. Dadurch werden die Serveradresse, das Zugriffstoken und alle in dieser App gespeicherten Diagrammdefinitionen entfernt. @@ -3612,7 +3662,7 @@ Bevor Diagramme Daten empfangen können: Eingeschränkt · unzuverlässig · langsam - + Your own cloud Eigene Cloud @@ -3621,22 +3671,22 @@ Bevor Diagramme Daten empfangen können: Verlauf · gepflegt · schnell - + Lacks features · unreliable · slow Fehlende Funktionen · unzuverlässig · langsam - + Historical data · properly maintained · fast Historische Daten · gut gepflegt · schnell - + The manufacturer cloud provides basic charts, but can be slow, unavailable or limited to the data selected by the manufacturer. Die Hersteller-Cloud stellt grundlegende Diagramme bereit, kann jedoch langsam, nicht erreichbar oder auf vom Hersteller ausgewählte Daten beschränkt sein. - + Download information Informationen herunterladen @@ -3657,37 +3707,37 @@ Bevor Diagramme Daten empfangen können: Verbindung zu Home Assistant einrichten - + Historical data Historische Daten - + Day Tag - + Week Woche - + Month Monat - + Year Jahr - + Previous Zurück - + Next Weiter @@ -5400,6 +5450,74 @@ Bevor Diagramme Daten empfangen können: Firmware • Hardwareinformationen • Lizenzen + + SolalawebSetupDialog + + + Set up Solalaweb + Solalaweb einrichten + + + + Solalaweb now uses Authentik. Create a dedicated app password instead of entering your normal account password. Choose a lifetime long enough for this app, then copy the password itself—not its name. + Solalaweb verwendet jetzt Authentik. Erstelle ein eigenes App-Passwort, statt dein normales Kontopasswort einzugeben. Wähle eine für diese App ausreichend lange Gültigkeitsdauer und kopiere dann das Passwort selbst – nicht seinen Namen. + + + + Create an Authentik app password + Authentik-App-Passwort erstellen + + + + Your username is usually your email address. The user-details page shows the exact username expected by Authentik. + Dein Benutzername ist normalerweise deine E-Mail-Adresse. Auf der Seite mit den Benutzerdetails steht der genaue Benutzername, den Authentik erwartet. + + + + Open Authentik user details + Authentik-Benutzerdetails öffnen + + + + Username + Benutzername + + + + Username or email address + Benutzername oder E-Mail-Adresse + + + + App password + App-Passwort + + + + Authentik app password + Authentik-App-Passwort + + + + Hide + Ausblenden + + + + Show + Anzeigen + + + + Cancel + Abbrechen + + + + Verify and save + Überprüfen und speichern + + StartStopButton diff --git a/evcharger-app/i18n/qml_en.ts b/evcharger-app/i18n/qml_en.ts index 4597dcb..97fbde7 100644 --- a/evcharger-app/i18n/qml_en.ts +++ b/evcharger-app/i18n/qml_en.ts @@ -4,14 +4,14 @@ HomeAssistantSetupDialog - + %n entity(s) - + %n entity(s) selected diff --git a/evcharger-app/i18n/qml_fi.ts b/evcharger-app/i18n/qml_fi.ts index 51d2efb..231a7f6 100644 --- a/evcharger-app/i18n/qml_fi.ts +++ b/evcharger-app/i18n/qml_fi.ts @@ -165,54 +165,100 @@ https://github.com/goecharger/go-eCharger-API-v1/blob/master/go-eCharger%20API%20v1%20EN.md + + AppSettings + + + The Solalaweb authentication check timed out. + Solalaweb-todennuksen tarkistus aikakatkaistiin. + + + + Authentication could not be verified: %1 + Todennusta ei voitu vahvistaa: %1 + + + + Enter both the username and the app password. + Syötä sekä käyttäjänimi että sovellussalasana. + + AppSettingsPage - + App Settings Sovellusasetukset - + Language Kieli - + Number of app instances: Sovellusesiintymien määrä: - + Swipe left or right with three fingers to switch between app instances. Vaihda sovellusinstanssien välillä pyyhkäisemällä vasemmalle tai oikealle kolmella sormella. - + + Solalaweb + Solalaweb + + + + Set up Authentik access to make the private Solalaweb connection available for saved devices. + Määritä Authentik-yhteys, jotta yksityinen Solalaweb-yhteys on käytettävissä tallennetuille laitteille. + + + + Authentication verified for %1 + Käyttäjän %1 todennus vahvistettu + + + + Authentication has not been verified + Todennusta ei ole vahvistettu + + + + Change Solalaweb authentication + Muuta Solalaweb-todennusta + + + + Set up Solalaweb + Määritä Solalaweb + + + + Show Solalaweb + Näytä Solalaweb + + solalaweb key: - solalaweb avain: + solalaweb avain: - - Select... - Valitse... + Valitse... - - Replace... - Korvaa... + Korvaa... - solalaweb cert: - solalaweb-sertifikaatti: + solalaweb-sertifikaatti: - Show solalaweb: - Näytä solalaweb: + Näytä solalaweb: @@ -1752,227 +1798,235 @@ DeviceConnection - + Connecting to %0 Yhdistetään laitteeseen %0 - Could not parse solalaweb certificate! - Solalaweb-varmennetta ei voitu jäsentää! + Solalaweb-varmennetta ei voitu jäsentää! - Could not parse solalaweb key! - Solalaweb-avainta ei voitu jäsentää! + Solalaweb-avainta ei voitu jäsentää! - + + Solalaweb authentication must be configured again. + Solalaweb-todennus on määritettävä uudelleen. + + + Received something that is not a json object! Vastaanotettu jotain, joka ei ole json-objekti! - + Received something that does not contain a type! Sain jotain, joka ei sisällä tyyppiä! - + Received something with a non-string type! Sain jotain ei-merkkijonotyyppistä! - + Received message type %0 %1 Vastaanotetun viestin tyyppi %0 %1 - + Received hello without serial! Vastaanotettu tervehdys ilman sarjaa! - + Received hello with a non-string serial! Vastaanotettu tervehdys ei-merkkijonosarjassa! - + Received hello with a non-bool secured! Vastaanotettu tervehdys ilman bool-suojattu! - + Received hello without manufacturer! Vastaanotettu tervehdys ilman valmistajaa! - + Received hello with a non-string manufacturer! Tervehdys ei-merkkijonovalmistajan kanssa! - + Received hello without devicetype! Vastaanotettu tervehdys ilman laitetyyppiä! - + Received hello with a non-string devicetype! Vastaanotettu tervehdys ei-merkkijonoisella laitetyypillä! - + Received hello without friendly_name! Vastaanotettu tervehdys ilman friendly_namea! - + Received hello with a non-string friendly_name! Vastaanotettu tervehdys ei-merkkijonolla friendly_name! - + Received authRequired without token1! Vastaanotettiin authRequired ilman token1-arvoa! - + Received authRequired with a non-string token1! Vastaanotettiin authRequired, jossa token1 ei ole merkkijono! - + Received authRequired without token2! Vastaanotettiin authRequired ilman token2-arvoa! - + Received authRequired with a non-string token2! Vastaanotettiin authRequired, jossa token2 ei ole merkkijono! - + Received authRequired with a non-string hash algorithm! Vastaanotettiin authRequired, jossa hajautusalgoritmi ei ole merkkijono! - + Received authRequired with unsupported hash algorithm %0! Vastaanotettiin authRequired, jonka hajautusalgoritmia %0 ei tueta! - + Received fullStatus with a non-bool partial! Vastaanotettu fullStatus ei-bool-osiolla! - + Received fullStatus without a status! Saatiin fullStatus ilman tilaa! - + Received fullStatus with a non-object status! Vastaanotettu fullStatus ei-objektin tilalla! - + Received partial fullStatus Vastaanotettu osittainen fullStatus - + Received last fullStatus Vastaanotettu viimeksi fullStatus - + Received deltaStatus without a status! Vastaanotettu deltaStatus ilman tilaa! - + Received deltaStatus with a non-object status! Vastaanotettu deltaStatus ei-objektitilassa! - + Received message with a non-string requestId! Vastaanotettu viesti, jossa on ei-merkkijono requestId! - + Sending %0 Lähetetään %0 - + Could not derive bcrypt authentication hash! Bcrypt-todennushajautetta ei voitu johtaa! - + Connected! Yhdistetty! - + Disconnected! Yhteys katkaistu! - + Reconnecting to %0 Yhdistetään uudelleen laitteeseen %0 - + state changed: %0 tila muutettu: %0 - + could not parse received json: %0 at offset %1 vastaanotettua json-tiedostoa ei voitu jäsentää: %0 offsetissa %1 - + unknown binary message type %0 received tuntematon binääriviestityyppi %0 vastaanotettu - + error occured: %0 tapahtui virhe: %0 - + + Solalaweb rejected the saved authentication: %1 + Solalaweb hylkäsi tallennetun todennuksen: %1 + + + ssl peer verify error ssl peer verify -virhe - + ssl errors ssl-virheitä - + ssl alert sent level=%0 type=%1 description=%2 ssl-hälytys lähetetty level=%0 type=%1 kuvaus=%2 - + ssl alert received level=%0 type=%1 description=%2 ssl-hälytys vastaanotettu taso=%0 type=%1 kuvaus=%2 - + ssl handshake interrupted on error ssl-kättely keskeytettiin virheen vuoksi - + unknown response type %0 tuntematon vastaustyyppi %0 @@ -2053,7 +2107,7 @@ Solala - + Add or setup device Lisää tai määritä laite @@ -2061,32 +2115,32 @@ DeviceScreen - + Password required Salasana vaaditaan - + Password: Salasana: - + Password Salasana - + Authentication impossible! Todennus mahdotonta! - + To use this password remotely a password has to be setup first. This can be done over the AccessPoint. Etäkäyttöä varten salasana on ensin määritettävä. Sen voi tehdä tukiaseman kautta. - + Connection disturbed Yhteys häiriintynyt @@ -2928,37 +2982,37 @@ HomeAssistantSetupDialog - + Edit chart Muokkaa kaaviota - + Connect Home Assistant Yhdistä Home Assistantiin - + Server Palvelin - + Login Kirjautuminen - + Charts Kaaviot - + %1. %2 %1. %2 - + Before you begin Ennen aloittamista @@ -2981,7 +3035,7 @@ Ennen kuin kaaviot voivat vastaanottaa tietoja: • Varmista, että laturin entiteetit näkyvät Home Assistantissa. - + Home Assistant must already be installed and running. A Raspberry Pi with Home Assistant on an SD card is one option; other supported Home Assistant installations work as well. Before charts can receive data: @@ -3000,78 +3054,83 @@ Ennen kuin kaaviot voivat vastaanottaa tietoja: • Varmista, että laitteen entiteetit näkyvät Home Assistantissa. - + Installation guide Asennusohje - + MQTT guide MQTT-ohje - + Enter the address you normally use to open Home Assistant. The app will contact this server directly. Anna osoite, jolla yleensä avaat Home Assistantin. Sovellus ottaa suoraan yhteyden tähän palvelimeen. - - + + Cancel Peruuta - + Next Seuraava - + Create a long-lived access token in your Home Assistant profile and paste it below. Your Home Assistant password is never entered into this app. Luo pitkäikäinen käyttöoikeustunnus Home Assistant -profiilissasi ja liitä se alle. Home Assistant -salasanaasi ei koskaan syötetä tähän sovellukseen. - + Open Home Assistant profile Avaa Home Assistant -profiili - + Long-lived access token Pitkäikäinen käyttöoikeustunnus - + Hide Piilota - + Show Näytä - + Back Takaisin - + Connect Yhdistä - + Create charts and choose exactly which Home Assistant entities each chart should display. Luo kaavioita ja valitse tarkasti, mitkä Home Assistant -entiteetit kussakin kaaviossa näytetään. - + Change server or access token Vaihda palvelinta tai käyttöoikeustunnusta + + + Forget Home Assistant configuration + Unohda Home Assistant -määritys + - + %n entity(s) %n entiteetti @@ -3079,42 +3138,42 @@ Ennen kuin kaaviot voivat vastaanottaa tietoja: - + Edit Muokkaa - + Delete Poista - + No charts configured yet. Kaavioita ei ole vielä määritetty. - + Add chart Lisää kaavio - + Done Valmis - + Chart title Kaavion otsikko - + Search by name, entity ID, unit or device class… Hae nimellä, entiteettitunnuksella, yksiköllä tai laiteluokalla… - + %n entity(s) selected %n entiteetti valittu @@ -3122,17 +3181,17 @@ Ennen kuin kaaviot voivat vastaanottaa tietoja: - + Reload Lataa uudelleen - + No matching entities found. Vastaavia entiteettejä ei löytynyt. - + Save chart Tallenna kaavio @@ -3292,7 +3351,7 @@ Ennen kuin kaaviot voivat vastaanottaa tietoja: Tiedot - + Idle Valmiustila @@ -3305,138 +3364,137 @@ Ennen kuin kaaviot voivat vastaanottaa tietoja: LADATAAN - + %1 – %2 %1 – %2 - + Receiving manufacturer data… Vastaanotetaan valmistajan tietoja… - + Loading manufacturer charts… Ladataan valmistajan kaavioita… - + %1 images %1 kuvaa - + %1 charts %1 kaaviota - + Loaded %1 Ladattu: %1 - + No information data received Tietoja ei vastaanotettu - + The manufacturer cloud returned invalid data. Valmistajan pilvipalvelu palautti virheellisiä tietoja. - + Requesting manufacturer data… Pyydetään valmistajan tietoja… - + Information Tiedot - + Manufacturer cloud Valmistajan pilvipalvelu - + The manufacturer does not even think you are worth the raw data that you could inspect and zoom. Instead, it sends these ugly low-resolution pictures that you cannot meaningfully interact with—let alone control the displayed time range. Valmistaja ei edes pidä sinua raakadatan arvoisena, vaikka voisit tarkastella ja zoomata sitä. Sen sijaan se lähettää nämä rumat matalan resoluution kuvat, joita et voi käsitellä mielekkäästi – saati hallita näytettävää aikaväliä. - + Own your consumption history Pidä kulutushistoriasi omassa hallinnassasi - + Connect the device to your own Home Assistant installation for fast, dependable history that remains under your control. You decide how long data is retained and which measurements are recorded. Yhdistä laite omaan Home Assistant -asennukseesi saadaksesi nopean ja luotettavan historian, joka pysyy hallinnassasi. Päätät, kuinka kauan tietoja säilytetään ja mitkä mittaukset tallennetaan. - + Connected to Home Assistant Yhdistetty Home Assistantiin - + Home Assistant is not configured Home Assistantia ei ole määritetty - + Configure Määritä - - + + Set up Määritä - + Refresh Päivitä - + Connect Home Assistant to display history Yhdistä Home Assistant historian näyttämiseksi - + Create your first history chart Luo ensimmäinen historiakaaviosi - + The setup wizard connects to your server and lets you select the entities to display. Ohjattu määritys yhdistää palvelimeesi ja antaa valita näytettävät entiteetit. - + Open the configuration and add a chart with one or more Home Assistant entities. Avaa määritys ja lisää kaavio, jossa on yksi tai useampi Home Assistant -entiteetti. - + Add chart Lisää kaavio - Forget Home Assistant configuration - Unohda Home Assistant -määritys + Unohda Home Assistant -määritys - + Forget Home Assistant? Unohdetaanko Home Assistant? - + This removes the server address, access token and all chart definitions stored in this app. Tämä poistaa palvelimen osoitteen, käyttöoikeustunnuksen ja kaikki tähän sovellukseen tallennetut kaaviomääritykset. @@ -3445,7 +3503,7 @@ Ennen kuin kaaviot voivat vastaanottaa tietoja: Rajallinen · epäluotettava · hidas - + Your own cloud Oma pilvipalvelusi @@ -3454,22 +3512,22 @@ Ennen kuin kaaviot voivat vastaanottaa tietoja: Historia · ylläpidetty · nopea - + Lacks features · unreliable · slow Puutteelliset ominaisuudet · epäluotettava · hidas - + Historical data · properly maintained · fast Historiatiedot · hyvin ylläpidetty · nopea - + The manufacturer cloud provides basic charts, but can be slow, unavailable or limited to the data selected by the manufacturer. Valmistajan pilvipalvelu tarjoaa peruskaavioita, mutta se voi olla hidas, poissa käytöstä tai rajoittunut valmistajan valitsemiin tietoihin. - + Download information Lataa tiedot @@ -3490,37 +3548,37 @@ Ennen kuin kaaviot voivat vastaanottaa tietoja: Määritä yhteys Home Assistantiin - + Historical data Historiatiedot - + Day Päivä - + Week Viikko - + Month Kuukausi - + Year Vuosi - + Previous Edellinen - + Next Seuraava @@ -5104,6 +5162,74 @@ Ennen kuin kaaviot voivat vastaanottaa tietoja: Lisenssit + + SolalawebSetupDialog + + + Set up Solalaweb + Määritä Solalaweb + + + + Solalaweb now uses Authentik. Create a dedicated app password instead of entering your normal account password. Choose a lifetime long enough for this app, then copy the password itself—not its name. + Solalaweb käyttää nyt Authentikia. Luo erillinen sovellussalasana tavallisen tilisalasanasi antamisen sijaan. Valitse tälle sovellukselle riittävän pitkä voimassaoloaika ja kopioi sitten itse salasana – älä sen nimeä. + + + + Create an Authentik app password + Luo Authentik-sovellussalasana + + + + Your username is usually your email address. The user-details page shows the exact username expected by Authentik. + Käyttäjänimesi on yleensä sähköpostiosoitteesi. Käyttäjätietosivu näyttää Authentikin odottaman tarkan käyttäjänimen. + + + + Open Authentik user details + Avaa Authentikin käyttäjätiedot + + + + Username + Käyttäjätunnus + + + + Username or email address + Käyttäjänimi tai sähköpostiosoite + + + + App password + Sovellussalasana + + + + Authentik app password + Authentik-sovellussalasana + + + + Hide + Piilota + + + + Show + Näytä + + + + Cancel + Peruuta + + + + Verify and save + Vahvista ja tallenna + + StartStopButton diff --git a/evcharger-app/i18n/qml_nb.ts b/evcharger-app/i18n/qml_nb.ts index 22d71e8..637b9cf 100644 --- a/evcharger-app/i18n/qml_nb.ts +++ b/evcharger-app/i18n/qml_nb.ts @@ -165,54 +165,100 @@ https://github.com/goecharger/go-eCharger-API-v1/blob/master/go-eCharger%20API%20v1%20EN.md + + AppSettings + + + The Solalaweb authentication check timed out. + Tidsavbrudd under kontrollen av Solalaweb-autentisering. + + + + Authentication could not be verified: %1 + Autentiseringen kunne ikke bekreftes: %1 + + + + Enter both the username and the app password. + Skriv inn både brukernavn og app-passord. + + AppSettingsPage - + App Settings Appinnstillinger - + Language Språk - + Number of app instances: Antall appforekomster: - + Swipe left or right with three fingers to switch between app instances. Sveip mot venstre eller høyre med tre fingre for å bytte mellom appinstanser. - + + Solalaweb + Solalaweb + + + + Set up Authentik access to make the private Solalaweb connection available for saved devices. + Konfigurer Authentik-tilgang for å gjøre den private Solalaweb-tilkoblingen tilgjengelig for lagrede enheter. + + + + Authentication verified for %1 + Autentisering bekreftet for %1 + + + + Authentication has not been verified + Autentiseringen er ikke bekreftet + + + + Change Solalaweb authentication + Endre Solalaweb-autentisering + + + + Set up Solalaweb + Konfigurer Solalaweb + + + + Show Solalaweb + Vis Solalaweb + + solalaweb key: - solalaweb nøkkel: + solalaweb nøkkel: - - Select... - Velg... + Velg... - - Replace... - Bytt ut... + Bytt ut... - solalaweb cert: - solalaweb sertifikat: + solalaweb sertifikat: - Show solalaweb: - Vis solalaweb: + Vis solalaweb: @@ -1752,227 +1798,235 @@ DeviceConnection - + Connecting to %0 Kobler til %0 - Could not parse solalaweb certificate! - Kunne ikke analysere solalaweb-sertifikatet! + Kunne ikke analysere solalaweb-sertifikatet! - Could not parse solalaweb key! - Kunne ikke analysere solalaweb-nøkkelen! + Kunne ikke analysere solalaweb-nøkkelen! - + + Solalaweb authentication must be configured again. + Solalaweb-autentiseringen må konfigureres på nytt. + + + Received something that is not a json object! Mottok noe som ikke er et json-objekt! - + Received something that does not contain a type! Mottatt noe som ikke inneholder en type! - + Received something with a non-string type! Mottatt noe med en ikke-streng type! - + Received message type %0 %1 Mottatt meldingstype %0 %1 - + Received hello without serial! Mottatt hei uten serienummer! - + Received hello with a non-string serial! Mottatt hei med en ikke-streng serie! - + Received hello with a non-bool secured! Mottatt hei med en ikke-bool sikret! - + Received hello without manufacturer! Mottatt hei uten produsent! - + Received hello with a non-string manufacturer! Mottatt hei med en ikke-streng produsent! - + Received hello without devicetype! Mottatt hei uten devicetype! - + Received hello with a non-string devicetype! Mottatt hei med en ikke-streng enhetstype! - + Received hello without friendly_name! Mottatt hei uten friendly_name! - + Received hello with a non-string friendly_name! Mottatt hei med et vennlig_navn uten strenger! - + Received authRequired without token1! Mottok authRequired uten token1! - + Received authRequired with a non-string token1! Mottok authRequired med token1 som ikke er en streng! - + Received authRequired without token2! Mottok authRequired uten token2! - + Received authRequired with a non-string token2! Mottok authRequired med token2 som ikke er en streng! - + Received authRequired with a non-string hash algorithm! Mottok authRequired med en hash-algoritme som ikke er en streng! - + Received authRequired with unsupported hash algorithm %0! Mottok authRequired med hash-algoritmen %0 som ikke støttes! - + Received fullStatus with a non-bool partial! Mottatt fullstatus med en ikke-bool-del! - + Received fullStatus without a status! Mottatt fullstatus uten status! - + Received fullStatus with a non-object status! Mottatt fullstatus med ikke-objekt-status! - + Received partial fullStatus Mottatt delvis fullstatus - + Received last fullStatus Mottatt siste fullstatus - + Received deltaStatus without a status! Mottatt deltaStatus uten status! - + Received deltaStatus with a non-object status! Mottatt deltaStatus med en ikke-objekt status! - + Received message with a non-string requestId! Mottatt melding med en ikke-streng requestId! - + Sending %0 Sender %0 - + Could not derive bcrypt authentication hash! Kunne ikke utlede bcrypt autentisering hash! - + Connected! Tilkoblet! - + Disconnected! Koblet fra! - + Reconnecting to %0 Kobler til %0 på nytt - + state changed: %0 tilstand endret: %0 - + could not parse received json: %0 at offset %1 kunne ikke analysere mottatt json: %0 ved offset %1 - + unknown binary message type %0 received ukjent binær meldingstype %0 mottatt - + error occured: %0 feil oppstod: %0 - + + Solalaweb rejected the saved authentication: %1 + Solalaweb avviste den lagrede autentiseringen: %1 + + + ssl peer verify error ssl peer verify feil - + ssl errors ssl feil - + ssl alert sent level=%0 type=%1 description=%2 ssl-varsel sendt nivå=%0 type=%1 beskrivelse=%2 - + ssl alert received level=%0 type=%1 description=%2 ssl-varsel mottatt nivå=%0 type=%1 beskrivelse=%2 - + ssl handshake interrupted on error ssl-håndtrykk avbrutt ved feil - + unknown response type %0 ukjent svartype %0 @@ -2053,7 +2107,7 @@ Solala - + Add or setup device Legg til eller konfigurer enhet @@ -2061,32 +2115,32 @@ DeviceScreen - + Password required Passord kreves - + Password: Passord: - + Password Passord - + Authentication impossible! Autentisering umulig! - + To use this password remotely a password has to be setup first. This can be done over the AccessPoint. For fjerntilgang må et passord først konfigureres. Dette kan gjøres via tilgangspunktet. - + Connection disturbed Forbindelsen forstyrret @@ -2928,37 +2982,37 @@ HomeAssistantSetupDialog - + Edit chart Rediger diagram - + Connect Home Assistant Koble til Home Assistant - + Server Server - + Login Pålogging - + Charts Diagrammer - + %1. %2 %1. %2 - + Before you begin Før du begynner @@ -2981,7 +3035,7 @@ Før diagrammer kan motta data: • Kontroller at laderens entiteter er synlige i Home Assistant. - + Home Assistant must already be installed and running. A Raspberry Pi with Home Assistant on an SD card is one option; other supported Home Assistant installations work as well. Before charts can receive data: @@ -3000,78 +3054,83 @@ Før diagrammer kan motta data: • Kontroller at enhetens entiteter er synlige i Home Assistant. - + Installation guide Installasjonsveiledning - + MQTT guide MQTT-veiledning - + Enter the address you normally use to open Home Assistant. The app will contact this server directly. Skriv inn adressen du vanligvis bruker for å åpne Home Assistant. Appen kontakter denne serveren direkte. - - + + Cancel Avbryt - + Next Neste - + Create a long-lived access token in your Home Assistant profile and paste it below. Your Home Assistant password is never entered into this app. Opprett et langlivet tilgangstoken i Home Assistant-profilen din, og lim det inn nedenfor. Home Assistant-passordet ditt skrives aldri inn i denne appen. - + Open Home Assistant profile Åpne Home Assistant-profil - + Long-lived access token Langlivet tilgangstoken - + Hide Skjul - + Show Vis - + Back Tilbake - + Connect Koble til - + Create charts and choose exactly which Home Assistant entities each chart should display. Opprett diagrammer og velg nøyaktig hvilke Home Assistant-entiteter hvert diagram skal vise. - + Change server or access token Bytt server eller tilgangstoken + + + Forget Home Assistant configuration + Glem Home Assistant-konfigurasjonen + - + %n entity(s) %n entitet @@ -3079,42 +3138,42 @@ Før diagrammer kan motta data: - + Edit Rediger - + Delete Slett - + No charts configured yet. Ingen diagrammer er konfigurert ennå. - + Add chart Legg til diagram - + Done Ferdig - + Chart title Diagramtittel - + Search by name, entity ID, unit or device class… Søk etter navn, entitets-ID, enhet eller enhetsklasse… - + %n entity(s) selected %n entitet valgt @@ -3122,17 +3181,17 @@ Før diagrammer kan motta data: - + Reload Last inn på nytt - + No matching entities found. Fant ingen samsvarende entiteter. - + Save chart Lagre diagram @@ -3292,7 +3351,7 @@ Før diagrammer kan motta data: Informasjon - + Idle Inaktiv @@ -3305,138 +3364,137 @@ Før diagrammer kan motta data: LASTER INN - + %1 – %2 %1 – %2 - + Receiving manufacturer data… Mottar produsentdata… - + Loading manufacturer charts… Laster produsentdiagrammer… - + %1 images %1 bilder - + %1 charts %1 diagrammer - + Loaded %1 Lastet inn %1 - + No information data received Ingen informasjonsdata mottatt - + The manufacturer cloud returned invalid data. Produsentskyen returnerte ugyldige data. - + Requesting manufacturer data… Ber om produsentdata… - + Information Informasjon - + Manufacturer cloud Produsentsky - + The manufacturer does not even think you are worth the raw data that you could inspect and zoom. Instead, it sends these ugly low-resolution pictures that you cannot meaningfully interact with—let alone control the displayed time range. Produsenten synes ikke engang du er verdt rådataene som du kunne ha undersøkt og zoomet inn i. I stedet sender den disse stygge lavoppløselige bildene som du ikke kan samhandle meningsfullt med – langt mindre styre det viste tidsintervallet. - + Own your consumption history Behold eierskapet til forbrukshistorikken din - + Connect the device to your own Home Assistant installation for fast, dependable history that remains under your control. You decide how long data is retained and which measurements are recorded. Koble enheten til din egen Home Assistant-installasjon for rask og pålitelig historikk som forblir under din kontroll. Du bestemmer hvor lenge data lagres og hvilke målinger som registreres. - + Connected to Home Assistant Koblet til Home Assistant - + Home Assistant is not configured Home Assistant er ikke konfigurert - + Configure Konfigurer - - + + Set up Konfigurer - + Refresh Oppdater - + Connect Home Assistant to display history Koble til Home Assistant for å vise historikk - + Create your first history chart Opprett ditt første historikkdiagram - + The setup wizard connects to your server and lets you select the entities to display. Oppsettsveiviseren kobler til serveren og lar deg velge entitetene som skal vises. - + Open the configuration and add a chart with one or more Home Assistant entities. Åpne konfigurasjonen og legg til et diagram med én eller flere Home Assistant-entiteter. - + Add chart Legg til diagram - Forget Home Assistant configuration - Glem Home Assistant-konfigurasjonen + Glem Home Assistant-konfigurasjonen - + Forget Home Assistant? Glemme Home Assistant? - + This removes the server address, access token and all chart definitions stored in this app. Dette fjerner serveradressen, tilgangstokenet og alle diagramdefinisjoner som er lagret i appen. @@ -3445,7 +3503,7 @@ Før diagrammer kan motta data: Begrenset · upålitelig · treg - + Your own cloud Din egen sky @@ -3454,22 +3512,22 @@ Før diagrammer kan motta data: Historikk · vedlikeholdt · rask - + Lacks features · unreliable · slow Mangler funksjoner · upålitelig · treg - + Historical data · properly maintained · fast Historiske data · godt vedlikeholdt · rask - + The manufacturer cloud provides basic charts, but can be slow, unavailable or limited to the data selected by the manufacturer. Produsentskyen tilbyr grunnleggende diagrammer, men kan være treg, utilgjengelig eller begrenset til data som produsenten har valgt. - + Download information Last ned informasjon @@ -3490,37 +3548,37 @@ Før diagrammer kan motta data: Konfigurer tilkobling til Home Assistant - + Historical data Historiske data - + Day Dag - + Week Uke - + Month Måned - + Year År - + Previous Forrige - + Next Neste @@ -5104,6 +5162,74 @@ Før diagrammer kan motta data: Lisenser + + SolalawebSetupDialog + + + Set up Solalaweb + Konfigurer Solalaweb + + + + Solalaweb now uses Authentik. Create a dedicated app password instead of entering your normal account password. Choose a lifetime long enough for this app, then copy the password itself—not its name. + Solalaweb bruker nå Authentik. Opprett et eget app-passord i stedet for å skrive inn det vanlige kontopassordet. Velg en gyldighetstid som er lang nok for denne appen, og kopier deretter selve passordet – ikke navnet. + + + + Create an Authentik app password + Opprett et Authentik-app-passord + + + + Your username is usually your email address. The user-details page shows the exact username expected by Authentik. + Brukernavnet ditt er vanligvis e-postadressen din. Siden med brukerdetaljer viser det nøyaktige brukernavnet som Authentik forventer. + + + + Open Authentik user details + Åpne brukerdetaljer i Authentik + + + + Username + Brukernavn + + + + Username or email address + Brukernavn eller e-postadresse + + + + App password + App-passord + + + + Authentik app password + Authentik-app-passord + + + + Hide + Skjul + + + + Show + Vis + + + + Cancel + Avbryt + + + + Verify and save + Bekreft og lagre + + StartStopButton diff --git a/evcharger-app/i18n/qml_sv.ts b/evcharger-app/i18n/qml_sv.ts index b1db3b5..9cedc9c 100644 --- a/evcharger-app/i18n/qml_sv.ts +++ b/evcharger-app/i18n/qml_sv.ts @@ -165,54 +165,100 @@ https://github.com/goecharger/go-eCharger-API-v1/blob/master/go-eCharger%20API%20v1%20EN.md + + AppSettings + + + The Solalaweb authentication check timed out. + Tidsgränsen för Solalawebs autentiseringskontroll överskreds. + + + + Authentication could not be verified: %1 + Autentiseringen kunde inte verifieras: %1 + + + + Enter both the username and the app password. + Ange både användarnamn och applösenord. + + AppSettingsPage - + App Settings Appinställningar - + Language Språk - + Number of app instances: Antal appinstanser: - + Swipe left or right with three fingers to switch between app instances. Svep åt vänster eller höger med tre fingrar för att växla mellan appinstanser. - + + Solalaweb + Solalaweb + + + + Set up Authentik access to make the private Solalaweb connection available for saved devices. + Konfigurera Authentik-åtkomst för att göra den privata Solalaweb-anslutningen tillgänglig för sparade enheter. + + + + Authentication verified for %1 + Autentisering verifierad för %1 + + + + Authentication has not been verified + Autentiseringen har inte verifierats + + + + Change Solalaweb authentication + Ändra Solalaweb-autentisering + + + + Set up Solalaweb + Konfigurera Solalaweb + + + + Show Solalaweb + Visa Solalaweb + + solalaweb key: - solalaweb nyckel: + solalaweb nyckel: - - Select... - Välj... + Välj... - - Replace... - Ersätt... + Ersätt... - solalaweb cert: - solalaweb certifikat: + solalaweb certifikat: - Show solalaweb: - Visa solalaweb: + Visa solalaweb: @@ -1752,227 +1798,235 @@ DeviceConnection - + Connecting to %0 Ansluter till %0 - Could not parse solalaweb certificate! - Kunde inte analysera solalaweb-certifikat! + Kunde inte analysera solalaweb-certifikat! - Could not parse solalaweb key! - Kunde inte analysera solalaweb-nyckeln! + Kunde inte analysera solalaweb-nyckeln! - + + Solalaweb authentication must be configured again. + Solalaweb-autentiseringen måste konfigureras igen. + + + Received something that is not a json object! Fick något som inte är ett json-objekt! - + Received something that does not contain a type! Fick något som inte innehåller en typ! - + Received something with a non-string type! Fick något med en icke-sträng typ! - + Received message type %0 %1 Mottaget meddelande typ %0 %1 - + Received hello without serial! Fick hej utan serie! - + Received hello with a non-string serial! Fick hej med en icke-strängad serie! - + Received hello with a non-bool secured! Fick hej med en icke-bool säkrad! - + Received hello without manufacturer! Fick hej utan tillverkare! - + Received hello with a non-string manufacturer! Fick hej med en icke-strängtillverkare! - + Received hello without devicetype! Fick hej utan devicetype! - + Received hello with a non-string devicetype! Fick hej med en icke-strängad enhetstyp! - + Received hello without friendly_name! Fick hej utan friendly_name! - + Received hello with a non-string friendly_name! Fick hej med ett icke-strängat friendly_name! - + Received authRequired without token1! Mottog authRequired utan token1! - + Received authRequired with a non-string token1! Mottog authRequired med token1 som inte är en sträng! - + Received authRequired without token2! Mottog authRequired utan token2! - + Received authRequired with a non-string token2! Mottog authRequired med token2 som inte är en sträng! - + Received authRequired with a non-string hash algorithm! Mottog authRequired med en hash-algoritm som inte är en sträng! - + Received authRequired with unsupported hash algorithm %0! Mottog authRequired med hash-algoritmen %0 som inte stöds! - + Received fullStatus with a non-bool partial! Fick fullstatus med en icke-bool partial! - + Received fullStatus without a status! Fick fullstatus utan status! - + Received fullStatus with a non-object status! Fick fullstatus med en icke-objektstatus! - + Received partial fullStatus Fick delvis fullstatus - + Received last fullStatus Fick senaste fullständiga status - + Received deltaStatus without a status! Fick deltaStatus utan status! - + Received deltaStatus with a non-object status! Mottog deltaStatus med en icke-objektstatus! - + Received message with a non-string requestId! Mottaget meddelande med ett begäran-ID utan sträng! - + Sending %0 Skickar %0 - + Could not derive bcrypt authentication hash! Kunde inte härleda bcrypt-autentiseringshash! - + Connected! Ansluten! - + Disconnected! Frånkopplad! - + Reconnecting to %0 Återansluter till %0 - + state changed: %0 tillstånd ändrat: %0 - + could not parse received json: %0 at offset %1 kunde inte analysera mottagen json: %0 vid offset %1 - + unknown binary message type %0 received okänd binär meddelandetyp %0 mottagen - + error occured: %0 fel uppstod: %0 - + + Solalaweb rejected the saved authentication: %1 + Solalaweb avvisade den sparade autentiseringen: %1 + + + ssl peer verify error ssl peer verifieringsfel - + ssl errors ssl-fel - + ssl alert sent level=%0 type=%1 description=%2 ssl alert skickad nivå=%0 typ=%1 beskrivning=%2 - + ssl alert received level=%0 type=%1 description=%2 ssl alert mottagen nivå=%0 typ=%1 beskrivning=%2 - + ssl handshake interrupted on error ssl-handskakning avbröts vid fel - + unknown response type %0 okänd svarstyp %0 @@ -2053,7 +2107,7 @@ Solala - + Add or setup device Lägg till eller konfigurera enhet @@ -2061,32 +2115,32 @@ DeviceScreen - + Password required Lösenord krävs - + Password: Lösenord: - + Password Lösenord - + Authentication impossible! Autentisering omöjlig! - + To use this password remotely a password has to be setup first. This can be done over the AccessPoint. För fjärråtkomst måste ett lösenord först konfigureras. Det kan göras via åtkomstpunkten. - + Connection disturbed Anslutningen störd @@ -2928,37 +2982,37 @@ HomeAssistantSetupDialog - + Edit chart Redigera diagram - + Connect Home Assistant Anslut Home Assistant - + Server Server - + Login Inloggning - + Charts Diagram - + %1. %2 %1. %2 - + Before you begin Innan du börjar @@ -2981,7 +3035,7 @@ Innan diagram kan ta emot data: • Kontrollera att laddarens entiteter är synliga i Home Assistant. - + Home Assistant must already be installed and running. A Raspberry Pi with Home Assistant on an SD card is one option; other supported Home Assistant installations work as well. Before charts can receive data: @@ -3000,78 +3054,83 @@ Innan diagram kan ta emot data: • Kontrollera att enhetens entiteter är synliga i Home Assistant. - + Installation guide Installationsguide - + MQTT guide MQTT-guide - + Enter the address you normally use to open Home Assistant. The app will contact this server directly. Ange adressen som du normalt använder för att öppna Home Assistant. Appen kontaktar servern direkt. - - + + Cancel Avbryt - + Next Nästa - + Create a long-lived access token in your Home Assistant profile and paste it below. Your Home Assistant password is never entered into this app. Skapa en långlivad åtkomsttoken i din Home Assistant-profil och klistra in den nedan. Ditt Home Assistant-lösenord anges aldrig i appen. - + Open Home Assistant profile Öppna Home Assistant-profil - + Long-lived access token Långlivad åtkomsttoken - + Hide Dölj - + Show Visa - + Back Tillbaka - + Connect Anslut - + Create charts and choose exactly which Home Assistant entities each chart should display. Skapa diagram och välj exakt vilka Home Assistant-entiteter varje diagram ska visa. - + Change server or access token Byt server eller åtkomsttoken + + + Forget Home Assistant configuration + Glöm Home Assistant-konfiguration + - + %n entity(s) %n entitet @@ -3079,42 +3138,42 @@ Innan diagram kan ta emot data: - + Edit Redigera - + Delete Ta bort - + No charts configured yet. Inga diagram har konfigurerats ännu. - + Add chart Lägg till diagram - + Done Klar - + Chart title Diagramrubrik - + Search by name, entity ID, unit or device class… Sök efter namn, entitets-ID, enhet eller enhetsklass… - + %n entity(s) selected %n entitet vald @@ -3122,17 +3181,17 @@ Innan diagram kan ta emot data: - + Reload Läs in igen - + No matching entities found. Inga matchande entiteter hittades. - + Save chart Spara diagram @@ -3292,7 +3351,7 @@ Innan diagram kan ta emot data: Information - + Idle Viloläge @@ -3305,138 +3364,137 @@ Innan diagram kan ta emot data: LÄSER IN - + %1 – %2 %1 – %2 - + Receiving manufacturer data… Tar emot tillverkardata… - + Loading manufacturer charts… Läser in tillverkarens diagram… - + %1 images %1 bilder - + %1 charts %1 diagram - + Loaded %1 %1 inläst - + No information data received Ingen informationsdata mottogs - + The manufacturer cloud returned invalid data. Tillverkarens molntjänst returnerade ogiltiga data. - + Requesting manufacturer data… Begär tillverkardata… - + Information Information - + Manufacturer cloud Tillverkarens moln - + The manufacturer does not even think you are worth the raw data that you could inspect and zoom. Instead, it sends these ugly low-resolution pictures that you cannot meaningfully interact with—let alone control the displayed time range. Tillverkaren tycker inte ens att du är värd rådata som du skulle kunna granska och zooma in. I stället skickar den dessa fula lågupplösta bilder som du inte kan interagera med på ett meningsfullt sätt – än mindre styra det visade tidsintervallet. - + Own your consumption history Äg din förbrukningshistorik - + Connect the device to your own Home Assistant installation for fast, dependable history that remains under your control. You decide how long data is retained and which measurements are recorded. Anslut enheten till din egen Home Assistant-installation för snabb och tillförlitlig historik som förblir under din kontroll. Du bestämmer hur länge data sparas och vilka mätvärden som registreras. - + Connected to Home Assistant Ansluten till Home Assistant - + Home Assistant is not configured Home Assistant är inte konfigurerat - + Configure Konfigurera - - + + Set up Konfigurera - + Refresh Uppdatera - + Connect Home Assistant to display history Anslut Home Assistant för att visa historik - + Create your first history chart Skapa ditt första historikdiagram - + The setup wizard connects to your server and lets you select the entities to display. Installationsguiden ansluter till servern och låter dig välja vilka entiteter som ska visas. - + Open the configuration and add a chart with one or more Home Assistant entities. Öppna konfigurationen och lägg till ett diagram med en eller flera Home Assistant-entiteter. - + Add chart Lägg till diagram - Forget Home Assistant configuration - Glöm Home Assistant-konfiguration + Glöm Home Assistant-konfiguration - + Forget Home Assistant? Glöm Home Assistant? - + This removes the server address, access token and all chart definitions stored in this app. Detta tar bort serveradressen, åtkomsttoken och alla diagramdefinitioner som lagras i appen. @@ -3445,7 +3503,7 @@ Innan diagram kan ta emot data: Begränsat · opålitligt · långsamt - + Your own cloud Ditt eget moln @@ -3454,22 +3512,22 @@ Innan diagram kan ta emot data: Historik · underhållet · snabbt - + Lacks features · unreliable · slow Saknar funktioner · opålitligt · långsamt - + Historical data · properly maintained · fast Historiska data · väl underhållet · snabbt - + The manufacturer cloud provides basic charts, but can be slow, unavailable or limited to the data selected by the manufacturer. Tillverkarens molntjänst erbjuder grundläggande diagram, men kan vara långsam, otillgänglig eller begränsad till data som tillverkaren har valt. - + Download information Hämta information @@ -3490,37 +3548,37 @@ Innan diagram kan ta emot data: Konfigurera anslutning till Home Assistant - + Historical data Historiska data - + Day Dag - + Week Vecka - + Month Månad - + Year År - + Previous Föregående - + Next Nästa @@ -5104,6 +5162,74 @@ Innan diagram kan ta emot data: Licenser + + SolalawebSetupDialog + + + Set up Solalaweb + Konfigurera Solalaweb + + + + Solalaweb now uses Authentik. Create a dedicated app password instead of entering your normal account password. Choose a lifetime long enough for this app, then copy the password itself—not its name. + Solalaweb använder nu Authentik. Skapa ett särskilt applösenord i stället för att ange ditt vanliga kontolösenord. Välj en giltighetstid som är tillräckligt lång för den här appen och kopiera sedan själva lösenordet – inte dess namn. + + + + Create an Authentik app password + Skapa ett Authentik-applösenord + + + + Your username is usually your email address. The user-details page shows the exact username expected by Authentik. + Ditt användarnamn är vanligtvis din e-postadress. Sidan med användaruppgifter visar det exakta användarnamn som Authentik förväntar sig. + + + + Open Authentik user details + Öppna användaruppgifter i Authentik + + + + Username + Användarnamn + + + + Username or email address + Användarnamn eller e-postadress + + + + App password + Applösenord + + + + Authentik app password + Authentik-applösenord + + + + Hide + Dölj + + + + Show + Visa + + + + Cancel + Avbryt + + + + Verify and save + Verifiera och spara + + StartStopButton diff --git a/evcharger-app/i18n/qml_tr.ts b/evcharger-app/i18n/qml_tr.ts index d7a4702..b3ea54c 100644 --- a/evcharger-app/i18n/qml_tr.ts +++ b/evcharger-app/i18n/qml_tr.ts @@ -165,54 +165,100 @@ https://github.com/goecharger/go-eCharger-API-v1/blob/master/go-eCharger%20API%20v1%20EN.md + + AppSettings + + + The Solalaweb authentication check timed out. + Solalaweb kimlik doğrulama kontrolü zaman aşımına uğradı. + + + + Authentication could not be verified: %1 + Kimlik doğrulama doğrulanamadı: %1 + + + + Enter both the username and the app password. + Hem kullanıcı adını hem de uygulama parolasını girin. + + AppSettingsPage - + App Settings Uygulama Ayarları - + Language Dil - + Number of app instances: Uygulama örneklerinin sayısı: - + Swipe left or right with three fingers to switch between app instances. Uygulama örnekleri arasında geçiş yapmak için üç parmağınızla sola veya sağa kaydırın. - + + Solalaweb + Solalaweb + + + + Set up Authentik access to make the private Solalaweb connection available for saved devices. + Kayıtlı cihazlar için özel Solalaweb bağlantısını kullanılabilir hale getirmek üzere Authentik erişimini ayarlayın. + + + + Authentication verified for %1 + %1 için kimlik doğrulama doğrulandı + + + + Authentication has not been verified + Kimlik doğrulama doğrulanmadı + + + + Change Solalaweb authentication + Solalaweb kimlik doğrulamasını değiştir + + + + Set up Solalaweb + Solalaweb'i ayarla + + + + Show Solalaweb + Solalaweb'i göster + + solalaweb key: - solalaweb anahtarı: + solalaweb anahtarı: - - Select... - Seç... + Seç... - - Replace... - Değiştir... + Değiştir... - solalaweb cert: - solalaweb sertifikası: + solalaweb sertifikası: - Show solalaweb: - Solalaweb'i göster: + Solalaweb'i göster: @@ -1752,227 +1798,235 @@ DeviceConnection - + Connecting to %0 %0'ye bağlanma - Could not parse solalaweb certificate! - Solalaweb sertifikası ayrıştırılamadı! + Solalaweb sertifikası ayrıştırılamadı! - Could not parse solalaweb key! - Solalaweb anahtarı ayrıştırılamadı! + Solalaweb anahtarı ayrıştırılamadı! - + + Solalaweb authentication must be configured again. + Solalaweb kimlik doğrulaması yeniden yapılandırılmalıdır. + + + Received something that is not a json object! Json nesnesi olmayan bir şey alındı! - + Received something that does not contain a type! Tür içermeyen bir şey alındı! - + Received something with a non-string type! Dize olmayan türde bir şey alındı! - + Received message type %0 %1 Alınan mesaj türü %0 %1 - + Received hello without serial! Seri olmadan merhaba aldım! - + Received hello with a non-string serial! Dize dışı bir diziyle merhaba aldım! - + Received hello with a non-bool secured! Bool olmayan bir güvenlikle merhaba aldım! - + Received hello without manufacturer! Üretici olmadan merhaba aldım! - + Received hello with a non-string manufacturer! String olmayan bir üreticiden merhaba aldım! - + Received hello without devicetype! Devicetype olmadan merhaba alındı! - + Received hello with a non-string devicetype! Dize dışı bir cihaz türüyle merhaba alındı! - + Received hello without friendly_name! Friendly_name olmadan merhaba aldım! - + Received hello with a non-string friendly_name! Dize olmayan bir dostu_ad ile merhaba aldım! - + Received authRequired without token1! token1 olmadan authRequired alındı! - + Received authRequired with a non-string token1! token1 dize değilken authRequired alındı! - + Received authRequired without token2! token2 olmadan authRequired alındı! - + Received authRequired with a non-string token2! token2 dize değilken authRequired alındı! - + Received authRequired with a non-string hash algorithm! Dize olmayan bir karma algoritmasıyla authRequired alındı! - + Received authRequired with unsupported hash algorithm %0! Desteklenmeyen %0 karma algoritmasıyla authRequired alındı! - + Received fullStatus with a non-bool partial! Bool olmayan bir kısmi ile fullStatus alındı! - + Received fullStatus without a status! Durum olmadan fullStatus alındı! - + Received fullStatus with a non-object status! Nesne olmayan bir durumla fullStatus alındı! - + Received partial fullStatus Kısmi tam durum alındı - + Received last fullStatus En son alınan fullStatus - + Received deltaStatus without a status! Durum olmadan deltaStatus alındı! - + Received deltaStatus with a non-object status! Nesne olmayan bir durumla deltaStatus alındı! - + Received message with a non-string requestId! Dize olmayan bir istek kimliğine sahip ileti alındı! - + Sending %0 %0 gönderiliyor - + Could not derive bcrypt authentication hash! Bcrypt kimlik doğrulama karması türetilemedi! - + Connected! Bağlı! - + Disconnected! Bağlantı kesildi! - + Reconnecting to %0 %0'ye yeniden bağlanılıyor - + state changed: %0 durum değişti: %0 - + could not parse received json: %0 at offset %1 alınan json ayrıştırılamadı: %1 konumunda %0 - + unknown binary message type %0 received bilinmeyen ikili mesaj türü %0 alındı - + error occured: %0 hata oluştu: %0 - + + Solalaweb rejected the saved authentication: %1 + Solalaweb kayıtlı kimlik doğrulamasını reddetti: %1 + + + ssl peer verify error SSL eş doğrulama hatası - + ssl errors SSL hataları - + ssl alert sent level=%0 type=%1 description=%2 SSL uyarısı gönderildi seviye=%0 tür=%1 açıklama=%2 - + ssl alert received level=%0 type=%1 description=%2 SSL uyarısı alındı düzey=%0 tür=%1 açıklama=%2 - + ssl handshake interrupted on error SSL anlaşması hata nedeniyle kesintiye uğradı - + unknown response type %0 bilinmeyen yanıt türü %0 @@ -2053,7 +2107,7 @@ Solala - + Add or setup device Cihaz ekleyin veya kurun @@ -2061,32 +2115,32 @@ DeviceScreen - + Password required Şifre gerekli - + Password: Şifre: - + Password Şifre - + Authentication impossible! Kimlik doğrulama imkansız! - + To use this password remotely a password has to be setup first. This can be done over the AccessPoint. Bu şifreyi uzaktan kullanmak için önce bir şifre ayarlanmalıdır. Bu işlem erişim noktası üzerinden yapılabilir. - + Connection disturbed Bağlantı bozuldu @@ -2928,37 +2982,37 @@ HomeAssistantSetupDialog - + Edit chart Grafiği düzenle - + Connect Home Assistant Home Assistant'ı bağla - + Server Sunucu - + Login Oturum açma - + Charts Grafikler - + %1. %2 %1. %2 - + Before you begin Başlamadan önce @@ -2981,7 +3035,7 @@ Grafiklerin veri alabilmesi için: • Şarj cihazının varlıklarının Home Assistant'ta göründüğünü doğrulayın. - + Home Assistant must already be installed and running. A Raspberry Pi with Home Assistant on an SD card is one option; other supported Home Assistant installations work as well. Before charts can receive data: @@ -3000,137 +3054,142 @@ Grafiklerin veri alabilmesi için: • Cihazın varlıklarının Home Assistant'ta göründüğünü doğrulayın. - + Installation guide Kurulum kılavuzu - + MQTT guide MQTT kılavuzu - + Enter the address you normally use to open Home Assistant. The app will contact this server directly. Home Assistant'ı açmak için normalde kullandığınız adresi girin. Uygulama bu sunucuyla doğrudan iletişim kuracaktır. - - + + Cancel İptal - + Next Sonraki - + Create a long-lived access token in your Home Assistant profile and paste it below. Your Home Assistant password is never entered into this app. Home Assistant profilinizde uzun ömürlü bir erişim belirteci oluşturup aşağıya yapıştırın. Home Assistant parolanız bu uygulamaya hiçbir zaman girilmez. - + Open Home Assistant profile Home Assistant profilini aç - + Long-lived access token Uzun ömürlü erişim belirteci - + Hide Gizle - + Show Göster - + Back Geri - + Connect Bağlan - + Create charts and choose exactly which Home Assistant entities each chart should display. Grafikler oluşturun ve her grafiğin hangi Home Assistant varlıklarını göstereceğini tam olarak seçin. - + Change server or access token Sunucuyu veya erişim belirtecini değiştir + + + Forget Home Assistant configuration + Home Assistant yapılandırmasını unut + - + %n entity(s) %n varlık - + Edit Düzenle - + Delete Sil - + No charts configured yet. Henüz yapılandırılmış grafik yok. - + Add chart Grafik ekle - + Done Bitti - + Chart title Grafik başlığı - + Search by name, entity ID, unit or device class… Ada, varlık kimliğine, birime veya cihaz sınıfına göre ara… - + %n entity(s) selected %n varlık seçildi - + Reload Yeniden yükle - + No matching entities found. Eşleşen varlık bulunamadı. - + Save chart Grafiği kaydet @@ -3290,7 +3349,7 @@ Grafiklerin veri alabilmesi için: Bilgiler - + Idle Boşta @@ -3303,138 +3362,137 @@ Grafiklerin veri alabilmesi için: YÜKLENİYOR - + %1 – %2 %1 – %2 - + Receiving manufacturer data… Üretici verileri alınıyor… - + Loading manufacturer charts… Üretici grafikleri yükleniyor… - + %1 images %1 resim - + %1 charts %1 grafik - + Loaded %1 %1 yüklendi - + No information data received Bilgi verisi alınmadı - + The manufacturer cloud returned invalid data. Üretici bulutu geçersiz veri döndürdü. - + Requesting manufacturer data… Üretici verileri isteniyor… - + Information Bilgi - + Manufacturer cloud Üretici bulutu - + The manufacturer does not even think you are worth the raw data that you could inspect and zoom. Instead, it sends these ugly low-resolution pictures that you cannot meaningfully interact with—let alone control the displayed time range. Üretici, inceleyip yakınlaştırabileceğiniz ham verileri size vermeye değer bile görmüyor. Bunun yerine, anlamlı biçimde etkileşim kuramadığınız bu çirkin, düşük çözünürlüklü görüntüleri gönderiyor; gösterilen zaman aralığını kontrol etmek ise zaten mümkün değil. - + Own your consumption history Tüketim geçmişiniz size ait olsun - + Connect the device to your own Home Assistant installation for fast, dependable history that remains under your control. You decide how long data is retained and which measurements are recorded. Hızlı, güvenilir ve kontrolünüz altında kalan bir geçmiş için cihazı kendi Home Assistant kurulumunuza bağlayın. Verilerin ne kadar süre saklanacağına ve hangi ölçümlerin kaydedileceğine siz karar verirsiniz. - + Connected to Home Assistant Home Assistant'a bağlı - + Home Assistant is not configured Home Assistant yapılandırılmadı - + Configure Yapılandır - - + + Set up Kur - + Refresh Yenile - + Connect Home Assistant to display history Geçmişi görüntülemek için Home Assistant'ı bağlayın - + Create your first history chart İlk geçmiş grafiğinizi oluşturun - + The setup wizard connects to your server and lets you select the entities to display. Kurulum sihirbazı sunucunuza bağlanır ve görüntülenecek varlıkları seçmenizi sağlar. - + Open the configuration and add a chart with one or more Home Assistant entities. Yapılandırmayı açın ve bir veya daha fazla Home Assistant varlığı içeren bir grafik ekleyin. - + Add chart Grafik ekle - Forget Home Assistant configuration - Home Assistant yapılandırmasını unut + Home Assistant yapılandırmasını unut - + Forget Home Assistant? Home Assistant unutulsun mu? - + This removes the server address, access token and all chart definitions stored in this app. Bu işlem sunucu adresini, erişim belirtecini ve bu uygulamada saklanan tüm grafik tanımlarını kaldırır. @@ -3443,7 +3501,7 @@ Grafiklerin veri alabilmesi için: Kısıtlı · güvenilmez · yavaş - + Your own cloud Kendi bulutunuz @@ -3452,22 +3510,22 @@ Grafiklerin veri alabilmesi için: Geçmiş · bakımlı · hızlı - + Lacks features · unreliable · slow Eksik özellikler · güvenilmez · yavaş - + Historical data · properly maintained · fast Geçmiş veriler · iyi bakımlı · hızlı - + The manufacturer cloud provides basic charts, but can be slow, unavailable or limited to the data selected by the manufacturer. Üretici bulutu temel grafikler sağlar, ancak yavaş veya erişilemez olabilir ya da üreticinin seçtiği verilerle sınırlı kalabilir. - + Download information Bilgileri indir @@ -3488,37 +3546,37 @@ Grafiklerin veri alabilmesi için: Home Assistant bağlantısını kur - + Historical data Geçmiş veriler - + Day Gün - + Week Hafta - + Month Ay - + Year Yıl - + Previous Önceki - + Next Sonraki @@ -5102,6 +5160,74 @@ Grafiklerin veri alabilmesi için: Lisanslar + + SolalawebSetupDialog + + + Set up Solalaweb + Solalaweb'i ayarla + + + + Solalaweb now uses Authentik. Create a dedicated app password instead of entering your normal account password. Choose a lifetime long enough for this app, then copy the password itself—not its name. + Solalaweb artık Authentik kullanıyor. Normal hesap parolanızı girmek yerine özel bir uygulama parolası oluşturun. Bu uygulama için yeterince uzun bir geçerlilik süresi seçin, ardından adını değil parolanın kendisini kopyalayın. + + + + Create an Authentik app password + Authentik uygulama parolası oluştur + + + + Your username is usually your email address. The user-details page shows the exact username expected by Authentik. + Kullanıcı adınız genellikle e-posta adresinizdir. Kullanıcı ayrıntıları sayfası, Authentik'in beklediği tam kullanıcı adını gösterir. + + + + Open Authentik user details + Authentik kullanıcı ayrıntılarını aç + + + + Username + Kullanıcı adı + + + + Username or email address + Kullanıcı adı veya e-posta adresi + + + + App password + Uygulama parolası + + + + Authentik app password + Authentik uygulama parolası + + + + Hide + Gizle + + + + Show + Göster + + + + Cancel + İptal + + + + Verify and save + Doğrula ve kaydet + + StartStopButton diff --git a/evcharger-app/qml/AppSettingsPage.qml b/evcharger-app/qml/AppSettingsPage.qml index 9ebc3ff..0652f90 100644 --- a/evcharger-app/qml/AppSettingsPage.qml +++ b/evcharger-app/qml/AppSettingsPage.qml @@ -1,13 +1,18 @@ import QtQuick import QtQuick.Controls -import QtQuick.Dialogs import QtQuick.Layouts import EVChargerApp NavigationPage { + id: page + title: qsTr("App Settings") function backPressed() { + if (solalawebSetupDialog.opened) { + solalawebSetupDialog.close() + return true + } return false } @@ -47,55 +52,47 @@ NavigationPage { } } - WhiteBox { - Layout.fillWidth: true + SettingsCard { + SettingsSectionLabel { text: qsTr("Solalaweb") } - GridLayout { - anchors.fill: parent - columns: 2 + Text { + Layout.fillWidth: true + Layout.minimumWidth: 0 + text: qsTr("Set up Authentik access to make the private Solalaweb connection available for saved devices.") + wrapMode: Text.Wrap + } - Text { - text: qsTr("solalaweb key:") - font.bold: true - wrapMode: Text.Wrap - } + Label { + Layout.fillWidth: true + Layout.minimumWidth: 0 + text: theSettings.solalawebCredentialsVerified + ? qsTr("Authentication verified for %1").arg(theSettings.solalawebUsername) + : qsTr("Authentication has not been verified") + color: theSettings.solalawebCredentialsVerified + ? AppTheme.successColor : palette.placeholderText + wrapMode: Text.Wrap + } - Button { - text: theSettings.solalawebKey == "" ? qsTr("Select...") : qsTr("Replace...") - onClicked: keyFileDialog.open() + Button { + Layout.fillWidth: true + text: theSettings.solalawebCredentialsVerified + ? qsTr("Change Solalaweb authentication") + : qsTr("Set up Solalaweb") + onClicked: solalawebSetupDialog.open() + } - FileDialog { - id: keyFileDialog - fileMode: FileDialog.OpenFile - onAccepted: theSettings.loadSolalawebKey(selectedFile) - } - } - - Text { - text: qsTr("solalaweb cert:") - font.bold: true - wrapMode: Text.Wrap - } - - Button { - text: theSettings.solalawebCert == "" ? qsTr("Select...") : qsTr("Replace...") - onClicked: certFileDialog.open() - - FileDialog { - id: certFileDialog - fileMode: FileDialog.OpenFile - onAccepted: theSettings.loadSolalawebCert(selectedFile) - } - } - - CheckDelegate { - Layout.columnSpan: 2 - Layout.fillWidth: true - - text: qsTr("Show solalaweb:") - checked: theSettings.showSolalaweb - onClicked: theSettings.showSolalaweb = checked - } + WhiteCheckDelegate { + Layout.fillWidth: true + enabled: theSettings.solalawebCredentialsVerified + text: qsTr("Show Solalaweb") + checked: theSettings.solalawebCredentialsVerified + && theSettings.showSolalaweb + onClicked: theSettings.showSolalaweb = checked } } + + SolalawebSetupDialog { + id: solalawebSetupDialog + settings: theSettings + } } diff --git a/evcharger-app/qml/AppTheme.qml b/evcharger-app/qml/AppTheme.qml index f670b8a..b5bd897 100644 --- a/evcharger-app/qml/AppTheme.qml +++ b/evcharger-app/qml/AppTheme.qml @@ -8,4 +8,5 @@ QtObject { readonly property color cardColor: "white" readonly property color cardPressedColor: "#f1f1f1" readonly property color sectionLabelColor: "#5f6368" + readonly property color successColor: "#2e7d32" } diff --git a/evcharger-app/qml/DeviceListScreen.qml b/evcharger-app/qml/DeviceListScreen.qml index 9f1a68e..22df438 100644 --- a/evcharger-app/qml/DeviceListScreen.qml +++ b/evcharger-app/qml/DeviceListScreen.qml @@ -242,7 +242,8 @@ BaseNavigationPage { Layout.fillWidth: true text: qsTr("Solala") onClicked: deviceSelected("wss://solalaweb.com/" + delegate.serial, delegate.password) - visible: theSettings.showSolalaweb + visible: theSettings.solalawebCredentialsVerified + && theSettings.showSolalaweb } } } diff --git a/evcharger-app/qml/DeviceScreen.qml b/evcharger-app/qml/DeviceScreen.qml index d60d786..457f257 100644 --- a/evcharger-app/qml/DeviceScreen.qml +++ b/evcharger-app/qml/DeviceScreen.qml @@ -12,6 +12,11 @@ Loader { property alias password: theDeviceConnection.password function backPressed() { + if (solalawebSetupDialog.opened) { + solalawebSetupDialog.close() + closeRequested() + return true + } if (connectionDisturbed.visible) { connectionDisturbed.visible = false closeRequested() @@ -50,6 +55,10 @@ Loader { passwordDialog.open(); } onAuthImpossible: authImpossibleDialog.open() + onSolalawebAuthenticationRequired: function(message) { + connectionDisturbed.visible = false + solalawebSetupDialog.open() + } } sourceComponent: Component { @@ -141,6 +150,13 @@ Loader { } } + SolalawebSetupDialog { + id: solalawebSetupDialog + settings: theSettings + onAuthenticated: theDeviceConnection.start() + onCancelled: loader.closeRequested() + } + Item { id: connectionDisturbed diff --git a/evcharger-app/qml/HomeAssistantSetupDialog.qml b/evcharger-app/qml/HomeAssistantSetupDialog.qml index b138cea..2dc1e48 100644 --- a/evcharger-app/qml/HomeAssistantSetupDialog.qml +++ b/evcharger-app/qml/HomeAssistantSetupDialog.qml @@ -14,6 +14,8 @@ CenteredDialog { property int selectionRevision: 0 property bool tokenVisible: false + signal forgetRequested() + title: wizardStep === 3 ? qsTr("Edit chart") : qsTr("Connect Home Assistant") modal: true focus: true @@ -335,6 +337,13 @@ CenteredDialog { onClicked: dialog.wizardStep = 0 } + Button { + Layout.fillWidth: true + visible: dialog.client.configured + text: qsTr("Forget Home Assistant configuration") + onClicked: dialog.forgetRequested() + } + ScrollView { Layout.fillWidth: true Layout.fillHeight: true @@ -446,7 +455,7 @@ CenteredDialog { spacing: 1 model: dialog.client.entitiesModel - delegate: CheckDelegate { + delegate: WhiteItemDelegate { id: entityDelegate required property string entityId required property string name @@ -454,30 +463,47 @@ CenteredDialog { required property string deviceClass required property string currentValue width: ListView.view.width - checked: dialog.selected(entityId) - onClicked: dialog.setSelected(entityId, checked) + onClicked: dialog.setSelected(entityId, + !dialog.selected(entityId)) - contentItem: Column { - spacing: 1 - Label { - width: parent.width - text: entityDelegate.name - font.bold: true - elide: Text.ElideRight + contentItem: RowLayout { + spacing: 8 + + CheckBox { + Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter + checked: dialog.selected(entityDelegate.entityId) + Accessible.name: entityDelegate.name + onClicked: dialog.setSelected(entityDelegate.entityId, + checked) } - Label { - width: parent.width - text: { - let details = entityDelegate.entityId - if (entityDelegate.currentValue.length > 0) - details += " · " + entityDelegate.currentValue - if (entityDelegate.unit.length > 0) - details += " " + entityDelegate.unit - return details + + ColumnLayout { + Layout.fillWidth: true + Layout.minimumWidth: 0 + spacing: 1 + + Label { + Layout.fillWidth: true + Layout.minimumWidth: 0 + text: entityDelegate.name + font.bold: true + elide: Text.ElideRight + } + Label { + Layout.fillWidth: true + Layout.minimumWidth: 0 + text: { + let details = entityDelegate.entityId + if (entityDelegate.currentValue.length > 0) + details += " · " + entityDelegate.currentValue + if (entityDelegate.unit.length > 0) + details += " " + entityDelegate.unit + return details + } + color: palette.placeholderText + font.pixelSize: 11 + elide: Text.ElideMiddle } - color: palette.placeholderText - font.pixelSize: 11 - elide: Text.ElideMiddle } } } diff --git a/evcharger-app/qml/InformationsTabPage.qml b/evcharger-app/qml/InformationsTabPage.qml index c817ae7..ccc60cf 100644 --- a/evcharger-app/qml/InformationsTabPage.qml +++ b/evcharger-app/qml/InformationsTabPage.qml @@ -539,25 +539,23 @@ ScrollableTabPage { } } - Button { - Layout.fillWidth: true - visible: homeAssistant.configured - text: qsTr("Forget Home Assistant configuration") - onClicked: forgetHomeAssistantDialog.open() - } } } HomeAssistantSetupDialog { id: homeAssistantDialog client: homeAssistant + onForgetRequested: forgetHomeAssistantDialog.open() } CenteredDialog { id: forgetHomeAssistantDialog title: qsTr("Forget Home Assistant?") standardButtons: Dialog.Cancel | Dialog.Ok - onAccepted: homeAssistant.clearConfiguration() + onAccepted: { + homeAssistant.clearConfiguration() + homeAssistantDialog.close() + } contentItem: ColumnLayout { Text { Layout.fillWidth: true diff --git a/evcharger-app/qml/SolalawebSetupDialog.qml b/evcharger-app/qml/SolalawebSetupDialog.qml new file mode 100644 index 0000000..6d47345 --- /dev/null +++ b/evcharger-app/qml/SolalawebSetupDialog.qml @@ -0,0 +1,155 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import EVChargerApp + +CenteredDialog { + id: dialog + + required property AppSettings settings + property bool passwordVisible: false + + signal authenticated() + signal cancelled() + + title: qsTr("Set up Solalaweb") + modal: true + focus: true + width: Math.min(500, Overlay.overlay.width - 20) + height: Math.min(contentLayout.implicitHeight + topPadding + bottomPadding, + Overlay.overlay.height - 20) + closePolicy: Popup.NoAutoClose + + onOpened: { + usernameInput.text = settings.solalawebUsername + passwordInput.clear() + usernameInput.forceActiveFocus() + } + + Connections { + target: dialog.settings + + function onSolalawebVerificationFinished(success) { + if (!success) + return + dialog.authenticated() + dialog.close() + } + } + + contentItem: ColumnLayout { + id: contentLayout + width: dialog.availableWidth + spacing: 10 + + Text { + Layout.fillWidth: true + Layout.minimumWidth: 0 + text: qsTr("Solalaweb now uses Authentik. Create a dedicated app password instead of entering your normal account password. Choose a lifetime long enough for this app, then copy the password itself—not its name.") + wrapMode: Text.Wrap + } + + Button { + Layout.fillWidth: true + text: qsTr("Create an Authentik app password") + onClicked: Qt.openUrlExternally("https://auth.go-e.com/if/user/#/settings;%7B%22page%22:%22page-tokens%22%7D") + } + + Text { + Layout.fillWidth: true + Layout.minimumWidth: 0 + text: qsTr("Your username is usually your email address. The user-details page shows the exact username expected by Authentik.") + wrapMode: Text.Wrap + color: AppTheme.sectionLabelColor + } + + Button { + Layout.fillWidth: true + text: qsTr("Open Authentik user details") + onClicked: Qt.openUrlExternally("https://auth.go-e.com/if/user/#/settings;%7B%22ak-user-settings-mfa-page%22%3A0%7D") + } + + SettingsLabel { + Layout.fillWidth: true + text: qsTr("Username") + } + + TextField { + id: usernameInput + Layout.fillWidth: true + Layout.minimumWidth: 0 + enabled: !dialog.settings.solalawebVerificationInProgress + inputMethodHints: Qt.ImhEmailCharactersOnly | Qt.ImhNoAutoUppercase + placeholderText: qsTr("Username or email address") + selectByMouse: true + } + + SettingsLabel { + Layout.fillWidth: true + text: qsTr("App password") + } + + RowLayout { + Layout.fillWidth: true + Layout.minimumWidth: 0 + + TextField { + id: passwordInput + Layout.fillWidth: true + Layout.minimumWidth: 0 + enabled: !dialog.settings.solalawebVerificationInProgress + placeholderText: qsTr("Authentik app password") + echoMode: dialog.passwordVisible ? TextInput.Normal + : TextInput.Password + selectByMouse: true + onAccepted: verifyButton.clicked() + } + + ToolButton { + text: dialog.passwordVisible ? qsTr("Hide") : qsTr("Show") + onClicked: dialog.passwordVisible = !dialog.passwordVisible + } + } + + Label { + Layout.fillWidth: true + Layout.minimumWidth: 0 + visible: dialog.settings.solalawebVerificationError.length > 0 + text: dialog.settings.solalawebVerificationError + color: palette.brightText + wrapMode: Text.Wrap + } + + BusyIndicator { + Layout.alignment: Qt.AlignHCenter + visible: dialog.settings.solalawebVerificationInProgress + running: visible + } + + RowLayout { + Layout.fillWidth: true + + Button { + text: qsTr("Cancel") + enabled: !dialog.settings.solalawebVerificationInProgress + onClicked: { + dialog.cancelled() + dialog.close() + } + } + + Item { Layout.fillWidth: true } + + Button { + id: verifyButton + text: qsTr("Verify and save") + enabled: !dialog.settings.solalawebVerificationInProgress + && usernameInput.text.trim().length > 0 + && passwordInput.text.length > 0 + highlighted: true + onClicked: dialog.settings.verifySolalawebCredentials( + usernameInput.text, passwordInput.text) + } + } + } +} diff --git a/evcharger-app/qml/qmldir b/evcharger-app/qml/qmldir index 7facace..e7a0bda 100644 --- a/evcharger-app/qml/qmldir +++ b/evcharger-app/qml/qmldir @@ -90,6 +90,7 @@ EVChargerApp 1.0 SetPriceLimitPage.qml EVChargerApp 1.0 SettingsTabPage.qml EVChargerApp 1.0 SetValueHelper.qml EVChargerApp 1.0 SimpleNavigationItem.qml +EVChargerApp 1.0 SolalawebSetupDialog.qml EVChargerApp 1.0 StartStopButton.qml EVChargerApp 1.0 SwitchLanguagePage.qml EVChargerApp 1.0 TimeComponentLabel.qml