Add evdash settings and enable / disable API methods

initial-version
Simon Stürz 2025-11-12 11:43:15 +01:00
parent b7e8925236
commit 0ad69ed5eb
8 changed files with 205 additions and 13 deletions

View File

@ -457,7 +457,7 @@
<section id="loginOverlay" class="login-view" aria-labelledby="loginTitle">
<div class="login-panel">
<h2 id="loginTitle">Sign in</h2>
<p>Please enter your credentials.</p>
<p>Authorization required.</p>
<div id="loginError" class="error-message hidden" role="alert"></div>
<form id="loginForm" autocomplete="on">
<label for="username">Username

View File

@ -29,6 +29,7 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "evdashengine.h"
#include "evdashsettings.h"
#include "evdashwebserverresource.h"
#include <integrations/thingmanager.h>
@ -94,23 +95,48 @@ EvDashEngine::EvDashEngine(ThingManager *thingManager, EvDashWebServerResource *
qCWarning(dcEvDashExperience()) << "WebSocket accept error" << error << m_webSocketServer->errorString();
});
startWebSocket(4449);
EvDashSettings settings;
settings.beginGroup("General");
m_webSocketPort = settings.value("webSocketServerPort", 4449).toUInt();
bool enabled = settings.value("enabled", false).toBool();
settings.endGroup();
// Start the service if enabled
setEnabled(enabled);
}
EvDashEngine::~EvDashEngine()
{
if (m_webSocketServer->isListening())
m_webSocketServer->close();
stopWebSocketServer();
}
for (QWebSocket *client : qAsConst(m_clients)) {
if (client->state() == QAbstractSocket::ConnectedState)
client->close(QWebSocketProtocol::CloseCodeGoingAway, QStringLiteral("Server shutting down"));
bool EvDashEngine::enabled() const
{
return m_enabled;
}
client->deleteLater();
bool EvDashEngine::setEnabled(bool enabled)
{
m_enabled = enabled;
if (m_enabled) {
if (!startWebSocketServer(m_webSocketPort)) {
return false;
}
} else {
stopWebSocketServer();
}
m_clients.clear();
m_authenticatedClients.clear();
qCDebug(dcEvDashExperience()) << "The EV Dash service is now" << (enabled ? "enabled" : "disabled");
m_webServerResource->setEnabled(m_enabled);
EvDashSettings settings;
settings.beginGroup("General");
settings.setValue("enabled", enabled);
settings.endGroup();
emit enabledChanged(m_enabled);
return true;
}
void EvDashEngine::onThingAdded(Thing *thing)
@ -151,7 +177,7 @@ void EvDashEngine::monitorChargerThing(Thing *thing)
});
}
bool EvDashEngine::startWebSocket(quint16 port)
bool EvDashEngine::startWebSocketServer(quint16 port)
{
if (m_webSocketServer->isListening()) {
if (m_webSocketServer->serverPort() == port && port != 0)
@ -171,6 +197,22 @@ bool EvDashEngine::startWebSocket(quint16 port)
return listening;
}
void EvDashEngine::stopWebSocketServer()
{
if (m_webSocketServer->isListening())
m_webSocketServer->close();
for (QWebSocket *client : qAsConst(m_clients)) {
if (client->state() == QAbstractSocket::ConnectedState)
client->close(QWebSocketProtocol::CloseCodeGoingAway, QStringLiteral("Server shutting down"));
client->deleteLater();
}
m_clients.clear();
m_authenticatedClients.clear();
}
void EvDashEngine::processTextMessage(QWebSocket *socket, const QString &message)
{
if (!socket)

View File

@ -48,10 +48,22 @@ class EvDashEngine : public QObject
{
Q_OBJECT
public:
enum EvDashError {
EvDashErrorNoError = 0,
EvDashErrorBackendError,
EvDashErrorDuplicateUser,
EvDashErrorBadPassword
};
Q_ENUM(EvDashError)
explicit EvDashEngine(ThingManager *thingManager, EvDashWebServerResource *webServerResource, QObject *parent = nullptr);
~EvDashEngine() override;
bool enabled() const;
bool setEnabled(bool enabled);
signals:
void enabledChanged(bool enabled);
void webSocketListeningChanged(bool listening);
private slots:
@ -62,7 +74,11 @@ private slots:
private:
ThingManager *m_thingManager = nullptr;
EvDashWebServerResource *m_webServerResource = nullptr;
bool m_enabled = false;
QWebSocketServer *m_webSocketServer = nullptr;
quint16 m_webSocketPort = 4449;
QList<QWebSocket *> m_clients;
QHash<QWebSocket *, QString> m_authenticatedClients;
@ -71,7 +87,8 @@ private:
void monitorChargerThing(Thing *thing);
// Websocket server
bool startWebSocket(quint16 port = 0);
bool startWebSocketServer(quint16 port = 0);
void stopWebSocketServer();
void processTextMessage(QWebSocket *socket, const QString &message);
// Websocket API

View File

@ -38,6 +38,31 @@ EvDashJsonHandler::EvDashJsonHandler(EvDashEngine *engine, QObject *parent):
JsonHandler{parent},
m_engine{engine}
{
registerEnum<EvDashEngine::EvDashError>();
QVariantMap params, returns;
QString description;
params.clear(); returns.clear();
description = "Get the enabled status of EV Dash service.";
returns.insert("enabled", enumValueName(Bool));
registerMethod("GetEnabled", description, params, returns);
params.clear(); returns.clear();
description = "Enable/Disable the EV Dash service.";
params.insert("enabled", enumValueName(Bool));
returns.insert("evDashError", enumRef<EvDashEngine::EvDashError>());
registerMethod("SetEnabled", description, params, returns);
// Notifications
params.clear();
description = "Emitted whenever the EV Dash service has been enabled or disabled.";
params.insert("enabled", enumValueName(Bool));
registerNotification("EnabledChanged", description, params);
connect(m_engine, &EvDashEngine::enabledChanged, this, [=](bool enabled){
emit EnabledChanged({{"enabled", enabled}});
});
}
@ -46,3 +71,25 @@ QString EvDashJsonHandler::name() const
return "EvDash";
}
JsonReply *EvDashJsonHandler::GetEnabled(const QVariantMap &params)
{
Q_UNUSED(params)
QVariantMap returns;
returns.insert("enabled", m_engine->enabled());
return createReply(returns);
}
JsonReply *EvDashJsonHandler::SetEnabled(const QVariantMap &params)
{
bool enabled = params.value("enabled").toBool();
EvDashEngine::EvDashError error = EvDashEngine::EvDashErrorNoError;
if (!m_engine->setEnabled(enabled))
error = EvDashEngine::EvDashErrorBackendError;
QVariantMap returns;
returns.insert("evDashError", enumValueName(error));
return createReply(returns);
}

View File

@ -45,7 +45,8 @@ public:
QString name() const override;
// Q_INVOKABLE JsonReply *SetEnabled(const QVariantMap &params);
Q_INVOKABLE JsonReply *GetEnabled(const QVariantMap &params);
Q_INVOKABLE JsonReply *SetEnabled(const QVariantMap &params);
signals:
void EnabledChanged(const QVariantMap &params);

39
plugin/evdashsettings.cpp Normal file
View File

@ -0,0 +1,39 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2025, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, GNU version 3. This project is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "evdashsettings.h"
#include <nymeasettings.h>
EvDashSettings::EvDashSettings()
: QSettings(NymeaSettings::settingsPath() + "/evdash.conf", QSettings::IniFormat)
{
}

44
plugin/evdashsettings.h Normal file
View File

@ -0,0 +1,44 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2025, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, GNU version 3. This project is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef EVDASHSETTINGS_H
#define EVDASHSETTINGS_H
#include <QObject>
#include <QSettings>
class EvDashSettings : public QSettings
{
public:
explicit EvDashSettings();
};
#endif // EVDASHSETTINGS_H

View File

@ -14,11 +14,13 @@ QT += network sql websockets
HEADERS += experiencepluginevdash.h \
evdashengine.h \
evdashjsonhandler.h \
evdashsettings.h \
evdashwebserverresource.h
SOURCES += experiencepluginevdash.cpp \
evdashengine.cpp \
evdashjsonhandler.cpp \
evdashsettings.cpp \
evdashwebserverresource.cpp
target.path = $$[QT_INSTALL_LIBS]/nymea/experiences/