diff --git a/plugin/energymanagerdbusclient.cpp b/plugin/energymanagerdbusclient.cpp
new file mode 100644
index 0000000..48d1368
--- /dev/null
+++ b/plugin/energymanagerdbusclient.cpp
@@ -0,0 +1,208 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright (C) 2013 - 2024, nymea GmbH
+* Copyright (C) 2024 - 2025, chargebyte austria GmbH
+*
+* This file is part of nymea-energy-plugin-nymea.
+*
+* nymea-energy-plugin-nymea.s free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* nymea-energy-plugin-nymea.s 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 nymea-energy-plugin-nymea. If not, see .
+*
+* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include "energymanagerdbusclient.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+static const QString kDbusService = QStringLiteral("io.nymea.energymanager");
+static const QString kDbusPath = QStringLiteral("/io/nymea/energymanager");
+static const QString kDbusInterface = QStringLiteral("io.nymea.energymanager");
+
+EnergyManagerDbusClient::EnergyManagerDbusClient(QObject *parent) :
+ QObject(parent),
+ m_connection(QDBusConnection::systemBus())
+{
+ if (!m_connection.isConnected()) {
+ emit errorOccurred(QStringLiteral("DBus system bus not connected"));
+ return;
+ }
+
+ m_serviceWatcher = new QDBusServiceWatcher(kDbusService,
+ m_connection,
+ QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration,
+ this);
+ connect(m_serviceWatcher, &QDBusServiceWatcher::serviceRegistered, this, &EnergyManagerDbusClient::onServiceRegistered);
+ connect(m_serviceWatcher, &QDBusServiceWatcher::serviceUnregistered, this, &EnergyManagerDbusClient::onServiceUnregistered);
+
+ QDBusConnectionInterface *bus = m_connection.interface();
+ if (bus && bus->isServiceRegistered(kDbusService)) {
+ onServiceRegistered(kDbusService);
+ }
+}
+
+EnergyManagerDbusClient::~EnergyManagerDbusClient()
+{
+}
+
+QVariantList EnergyManagerDbusClient::chargingInfos() const
+{
+ return m_chargingInfos;
+}
+
+void EnergyManagerDbusClient::refreshChargingInfos()
+{
+ if (!m_interface || !m_interface->isValid()) {
+ if (!setupInterface()) {
+ emit errorOccurred(QStringLiteral("EnergyManager DBus interface is not available"));
+ return;
+ }
+ }
+
+ if (!m_interface) {
+ emit errorOccurred(QStringLiteral("EnergyManager DBus interface is not available"));
+ return;
+ }
+
+ QDBusReply reply = m_interface->call(QStringLiteral("chargingInfos"));
+ if (!reply.isValid()) {
+ emit errorOccurred(reply.error().message());
+ return;
+ }
+
+ QVariantList convertedInfos;
+ const QVariantList infos = reply.value();
+ for (const QVariant &value : infos) {
+ if (value.canConvert()) {
+ convertedInfos.append(value.toMap());
+ continue;
+ }
+
+ const QDBusArgument arg = value.value();
+ convertedInfos.append(qdbus_cast(arg));
+ }
+
+ m_chargingInfos = convertedInfos;
+ emit chargingInfosUpdated(m_chargingInfos);
+}
+
+void EnergyManagerDbusClient::onChargingInfoAdded(const QVariantMap &chargingInfo)
+{
+ replaceOrAdd(chargingInfo);
+ emit chargingInfoAdded(chargingInfo);
+ emit chargingInfosUpdated(m_chargingInfos);
+}
+
+void EnergyManagerDbusClient::onChargingInfoRemoved(const QString &evChargerId)
+{
+ int index = indexOfInfo(evChargerId);
+ if (index >= 0) {
+ m_chargingInfos.removeAt(index);
+ emit chargingInfoRemoved(evChargerId);
+ emit chargingInfosUpdated(m_chargingInfos);
+ }
+}
+
+void EnergyManagerDbusClient::onChargingInfoChanged(const QVariantMap &chargingInfo)
+{
+ replaceOrAdd(chargingInfo);
+ emit chargingInfoChanged(chargingInfo);
+ emit chargingInfosUpdated(m_chargingInfos);
+}
+
+int EnergyManagerDbusClient::indexOfInfo(const QString &evChargerId) const
+{
+ for (int i = 0; i < m_chargingInfos.count(); ++i) {
+ const QVariantMap map = m_chargingInfos.at(i).toMap();
+ if (map.value(QStringLiteral("evChargerId")).toString() == evChargerId) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+void EnergyManagerDbusClient::replaceOrAdd(const QVariantMap &chargingInfo)
+{
+ const QString evChargerId = chargingInfo.value(QStringLiteral("evChargerId")).toString();
+ int index = indexOfInfo(evChargerId);
+ if (index >= 0) {
+ m_chargingInfos[index] = chargingInfo;
+ } else {
+ m_chargingInfos.append(chargingInfo);
+ }
+}
+
+bool EnergyManagerDbusClient::setupInterface()
+{
+ if (!m_connection.isConnected()) {
+ return false;
+ }
+
+ QDBusConnectionInterface *bus = m_connection.interface();
+ if (!bus || !bus->isServiceRegistered(kDbusService)) {
+ return false;
+ }
+
+ if (m_interface && m_interface->isValid()) {
+ return true;
+ }
+
+ delete m_interface;
+ m_interface = new QDBusInterface(kDbusService, kDbusPath, kDbusInterface, m_connection, this);
+
+ if (!m_interface->isValid()) {
+ emit errorOccurred(QStringLiteral("EnergyManager DBus interface is not available"));
+ delete m_interface;
+ m_interface = nullptr;
+ return false;
+ }
+
+ connect(m_interface, SIGNAL(chargingInfoAdded(QVariantMap)), this, SLOT(onChargingInfoAdded(QVariantMap)), Qt::UniqueConnection);
+ connect(m_interface, SIGNAL(chargingInfoRemoved(QString)), this, SLOT(onChargingInfoRemoved(QString)), Qt::UniqueConnection);
+ connect(m_interface, SIGNAL(chargingInfoChanged(QVariantMap)), this, SLOT(onChargingInfoChanged(QVariantMap)), Qt::UniqueConnection);
+
+ return true;
+}
+
+void EnergyManagerDbusClient::onServiceRegistered(const QString &service)
+{
+ if (service != kDbusService) {
+ return;
+ }
+
+ if (setupInterface()) {
+ refreshChargingInfos();
+ }
+}
+
+void EnergyManagerDbusClient::onServiceUnregistered(const QString &service)
+{
+ if (service != kDbusService) {
+ return;
+ }
+
+ delete m_interface;
+ m_interface = nullptr;
+ m_chargingInfos.clear();
+ emit chargingInfosUpdated(m_chargingInfos);
+}
diff --git a/plugin/energymanagerdbusclient.h b/plugin/energymanagerdbusclient.h
new file mode 100644
index 0000000..2d29828
--- /dev/null
+++ b/plugin/energymanagerdbusclient.h
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright (C) 2013 - 2024, nymea GmbH
+* Copyright (C) 2024 - 2025, chargebyte austria GmbH
+*
+* This file is part of nymea-energy-plugin-nymea.
+*
+* nymea-energy-plugin-nymea.s free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* nymea-energy-plugin-nymea.s 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 nymea-energy-plugin-nymea. If not, see .
+*
+* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#ifndef ENERGYMANAGERDBUSCLIENT_H
+#define ENERGYMANAGERDBUSCLIENT_H
+
+#include
+#include
+#include
+
+class QDBusInterface;
+class QDBusPendingCallWatcher;
+class QDBusServiceWatcher;
+
+class EnergyManagerDbusClient : public QObject
+{
+ Q_OBJECT
+public:
+ explicit EnergyManagerDbusClient(QObject *parent = nullptr);
+ ~EnergyManagerDbusClient();
+
+ QVariantList chargingInfos() const;
+
+public slots:
+ void refreshChargingInfos();
+
+signals:
+ void chargingInfosUpdated(const QVariantList &chargingInfos);
+ void chargingInfoAdded(const QVariantMap &chargingInfo);
+ void chargingInfoRemoved(const QString &evChargerId);
+ void chargingInfoChanged(const QVariantMap &chargingInfo);
+ void errorOccurred(const QString &message);
+
+private slots:
+ void onChargingInfoAdded(const QVariantMap &chargingInfo);
+ void onChargingInfoRemoved(const QString &evChargerId);
+ void onChargingInfoChanged(const QVariantMap &chargingInfo);
+ void onServiceRegistered(const QString &service);
+ void onServiceUnregistered(const QString &service);
+
+private:
+ int indexOfInfo(const QString &evChargerId) const;
+ void replaceOrAdd(const QVariantMap &chargingInfo);
+ bool setupInterface();
+
+ QDBusConnection m_connection;
+ QDBusInterface *m_interface = nullptr;
+ QDBusServiceWatcher *m_serviceWatcher = nullptr;
+ QVariantList m_chargingInfos;
+};
+
+#endif // ENERGYMANAGERDBUSCLIENT_H
diff --git a/plugin/evdashengine.cpp b/plugin/evdashengine.cpp
index d9c8ab2..efe0021 100644
--- a/plugin/evdashengine.cpp
+++ b/plugin/evdashengine.cpp
@@ -31,6 +31,7 @@
#include "evdashengine.h"
#include "evdashsettings.h"
#include "evdashwebserverresource.h"
+#include "energymanagerdbusclient.h"
#include
@@ -101,6 +102,44 @@ EvDashEngine::EvDashEngine(ThingManager *thingManager, EvDashWebServerResource *
bool enabled = settings.value("enabled", false).toBool();
settings.endGroup();
+
+ m_energyManagerClient = new EnergyManagerDbusClient(this);
+ connect(m_energyManagerClient, &EnergyManagerDbusClient::chargingInfosUpdated, this, [](const QVariantList &chargingInfos){
+ qCDebug(dcEvDashExperience()) << "ChargingInfos:";
+ foreach (const QVariant &ciVariant, chargingInfos) {
+ qCDebug(dcEvDashExperience()) << "-->" << ciVariant.toMap();
+ }
+ });
+
+ connect(m_energyManagerClient, &EnergyManagerDbusClient::chargingInfoAdded, this, [this](const QVariantMap &chargingInfo){
+ qCDebug(dcEvDashExperience()) << "ChargingInfo added:" << chargingInfo;
+ Thing *charger = m_thingManager->findConfiguredThing(chargingInfo.value("evChargerId").toUuid());
+ if (charger) {
+ onThingChanged(charger);
+ }
+ });
+
+ connect(m_energyManagerClient, &EnergyManagerDbusClient::chargingInfoChanged, this, [this](const QVariantMap &chargingInfo){
+ qCDebug(dcEvDashExperience()) << "ChargingInfo changed:" << chargingInfo;
+ Thing *charger = m_thingManager->findConfiguredThing(chargingInfo.value("evChargerId").toUuid());
+ if (charger) {
+ onThingChanged(charger);
+ }
+ });
+
+ connect(m_energyManagerClient, &EnergyManagerDbusClient::chargingInfoRemoved, this, [](const QString &evChargerId){
+ qCDebug(dcEvDashExperience()) << "ChargingInfo removed:" << evChargerId;
+ });
+
+ connect(m_energyManagerClient, &EnergyManagerDbusClient::errorOccurred, this, [](const QString &errorMessage){
+ qCWarning(dcEvDashExperience()) << "Energy manager DBus client error:" << errorMessage;
+ });
+
+ qCDebug(dcEvDashExperience()) << "ChargingInfos:" << m_energyManagerClient->chargingInfos();
+ foreach (const QVariant &ciVariant, m_energyManagerClient->chargingInfos()) {
+ qCDebug(dcEvDashExperience()) << "-->" << ciVariant.toMap();
+ }
+
// Start the service if enabled
setEnabled(enabled);
}
@@ -367,11 +406,27 @@ QJsonObject EvDashEngine::packCharger(Thing *charger) const
QJsonObject chargerObject;
chargerObject.insert("id", charger->id().toString(QUuid::WithoutBraces));
chargerObject.insert("name", charger->name());
+
+ foreach (const QVariant &chargingInfoVariant, m_energyManagerClient->chargingInfos()) {
+ QVariantMap chargingInfo = chargingInfoVariant.toMap();
+ if (chargingInfo.value("evChargerId").toUuid() == charger->id()) {
+ if (chargingInfo.value("assignedCarId").toString().isEmpty()) {
+ chargerObject.insert("assignedCar", "");
+ } else {
+ Thing *car = m_thingManager->findConfiguredThing(chargingInfo.value("assignedCarId").toUuid());
+ if (car) {
+ chargerObject.insert("assignedCar", car->name());
+ } else {
+ chargerObject.insert("assignedCar", "");
+ }
+ }
+ }
+ }
+
chargerObject.insert("connected", charger->stateValue("connected").toBool());
+ chargerObject.insert("status", charger->stateValue("status").toString());
chargerObject.insert("chargingCurrent", charger->stateValue("maxChargingCurrent").toDouble());
- chargerObject.insert("chargingAllowed", charger->stateValue("power").toBool());
chargerObject.insert("currentPower", charger->stateValue("currentPower").toDouble());
- chargerObject.insert("pluggedIn", charger->stateValue("pluggedIn").toBool());
if (charger->hasState("currentVersion"))
chargerObject.insert("version", charger->stateValue("currentVersion").toDouble());
diff --git a/plugin/evdashengine.h b/plugin/evdashengine.h
index df6fc47..0c9e436 100644
--- a/plugin/evdashengine.h
+++ b/plugin/evdashengine.h
@@ -42,6 +42,7 @@ class QWebSocketServer;
class Thing;
class ThingManager;
+class EnergyManagerDbusClient;
class EvDashWebServerResource;
class EvDashEngine : public QObject
@@ -75,9 +76,10 @@ private slots:
private:
ThingManager *m_thingManager = nullptr;
EvDashWebServerResource *m_webServerResource = nullptr;
-
bool m_enabled = false;
+ EnergyManagerDbusClient *m_energyManagerClient = nullptr;
+
QWebSocketServer *m_webSocketServer = nullptr;
quint16 m_webSocketPort = 4449;
diff --git a/plugin/plugin.pro b/plugin/plugin.pro
index 673d588..e235dc6 100644
--- a/plugin/plugin.pro
+++ b/plugin/plugin.pro
@@ -9,15 +9,17 @@ PKGCONFIG += nymea
RESOURCES += ../dashboard.qrc
QT -= gui
-QT += network sql websockets
+QT += network sql websockets dbus
HEADERS += experiencepluginevdash.h \
+ energymanagerdbusclient.h \
evdashengine.h \
evdashjsonhandler.h \
evdashsettings.h \
evdashwebserverresource.h
SOURCES += experiencepluginevdash.cpp \
+ energymanagerdbusclient.cpp \
evdashengine.cpp \
evdashjsonhandler.cpp \
evdashsettings.cpp \