diff --git a/libnymea-core/debugserverhandler.cpp b/libnymea-core/debugserverhandler.cpp
index 69d92c80..30f49e8e 100644
--- a/libnymea-core/debugserverhandler.cpp
+++ b/libnymea-core/debugserverhandler.cpp
@@ -1777,21 +1777,21 @@ QByteArray DebugServerHandler::createDebugXmlDocument()
};
foreach (const QString &loggingCategory, loggingCategories) {
writer.writeStartElement("div");
- writer.writeAttribute("class", "debug-category");
- writer.writeTextElement("p", loggingCategory);
- writer.writeStartElement("label");
- writer.writeStartElement("select");
- writer.writeAttribute("class", "debug-select");
- writer.writeAttribute("onchange", QString("toggleLoggingCategory('%1', this)").arg(loggingCategory));
- writer.writeAttribute("id", QString("debug-category-%1").arg(loggingCategory));
- foreach (const QString &option, QStringList({"debug", "info", "warning", "critical"})) {
- writer.writeStartElement("option");
- writer.writeAttribute("value", option);
- writer.writeCharacters(categoryMap.value(option));
- writer.writeEndElement();
- }
- writer.writeEndElement(); // select
- writer.writeEndElement(); // label
+ writer.writeAttribute("class", "debug-category");
+ writer.writeTextElement("p", loggingCategory);
+ writer.writeStartElement("label");
+ writer.writeStartElement("select");
+ writer.writeAttribute("class", "debug-select");
+ writer.writeAttribute("onchange", QString("toggleLoggingCategory('%1', this)").arg(loggingCategory));
+ writer.writeAttribute("id", QString("debug-category-%1").arg(loggingCategory));
+ foreach (const QString &option, QStringList({"debug", "info", "warning", "critical"})) {
+ writer.writeStartElement("option");
+ writer.writeAttribute("value", option);
+ writer.writeCharacters(categoryMap.value(option));
+ writer.writeEndElement();
+ }
+ writer.writeEndElement(); // select
+ writer.writeEndElement(); // label
writer.writeEndElement(); // div debug-category
}
@@ -1813,15 +1813,15 @@ QByteArray DebugServerHandler::createDebugXmlDocument()
writer.writeTextElement("p", loggingCategory);
writer.writeStartElement("label");
writer.writeStartElement("select");
- writer.writeAttribute("class", "debug-select");
- writer.writeAttribute("onchange", QString("toggleLoggingCategory('%1', this)").arg(loggingCategory));
- writer.writeAttribute("id", QString("debug-category-%1").arg(loggingCategory));
- foreach (const QString &option, QStringList({"debug", "info", "warning", "critical"})) {
- writer.writeStartElement("option");
- writer.writeAttribute("value", option);
- writer.writeCharacters(categoryMap.value(option));
- writer.writeEndElement();
- }
+ writer.writeAttribute("class", "debug-select");
+ writer.writeAttribute("onchange", QString("toggleLoggingCategory('%1', this)").arg(loggingCategory));
+ writer.writeAttribute("id", QString("debug-category-%1").arg(loggingCategory));
+ foreach (const QString &option, QStringList({"debug", "info", "warning", "critical"})) {
+ writer.writeStartElement("option");
+ writer.writeAttribute("value", option);
+ writer.writeCharacters(categoryMap.value(option));
+ writer.writeEndElement();
+ }
writer.writeEndElement(); // select
writer.writeEndElement(); // label
writer.writeEndElement(); // div debug-category
diff --git a/libnymea-core/jsonrpc/debughandler.cpp b/libnymea-core/jsonrpc/debughandler.cpp
new file mode 100644
index 00000000..4fee0e90
--- /dev/null
+++ b/libnymea-core/jsonrpc/debughandler.cpp
@@ -0,0 +1,221 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2024, 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 .
+*
+* 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 "debughandler.h"
+
+#include "nymeacore.h"
+#include "nymeasettings.h"
+#include "loggingcategories.h"
+
+namespace nymeaserver {
+
+DebugHandler::DebugHandler(QObject *parent)
+ : JsonHandler{parent}
+{
+ // Types
+ registerEnum();
+ registerEnum();
+ registerEnum();
+
+ QVariantMap loggingCategory;
+ loggingCategory.insert("name", enumValueName(String));
+ loggingCategory.insert("level", enumRef());
+ loggingCategory.insert("type", enumRef());
+ registerObject("LoggingCategory", loggingCategory);
+
+ QVariantMap params, returns;
+ QString description;
+
+ // Methods
+ params.clear(); returns.clear();
+ description = "Get all available logging categories.";
+ returns.insert("loggingCategories", QVariantList() << objectRef("LoggingCategory"));
+ registerMethod("GetLoggingCategories", description, params, returns);
+
+ params.clear(); returns.clear();
+ description = "Set the logging category with the given name to the given logging level.";
+ params.insert("name", enumValueName(String));
+ params.insert("level", enumRef());
+ returns.insert("debugError", enumRef());
+ registerMethod("SetLoggingCategoryLevel", description, params, returns);
+
+ // Notifications
+ params.clear(); returns.clear();
+ description = "Emitted whenever a logging category has changed the logging level.";
+ params.insert("name", enumValueName(String));
+ params.insert("level", enumRef());
+ registerNotification("LoggingCategoryLevelChanged", description, params);
+}
+
+QString DebugHandler::name() const
+{
+ return "Debug";
+}
+
+JsonReply *DebugHandler::GetLoggingCategories(const QVariantMap ¶ms)
+{
+ Q_UNUSED(params)
+
+ QVariantList categories;
+ QStringList allCategories;
+
+ NymeaSettings settings(NymeaSettings::SettingsRoleGlobal);
+ settings.beginGroup("LoggingRules");
+
+ // System
+ foreach (const QString &loggingCategory, NymeaCore::loggingFilters()) {
+ allCategories.append(loggingCategory);
+
+ LoggingLevel level = DebugHandler::LoggingLevelCritical;
+ if (settings.value(QString("%1.warning").arg(loggingCategory), true).toBool()) {
+ level = DebugHandler::LoggingLevelWarning;
+ }
+ if (settings.value(QString("%1.info").arg(loggingCategory), false).toBool()) {
+ level = DebugHandler::LoggingLevelInfo;
+ }
+ if (settings.value(QString("%1.debug").arg(loggingCategory), false).toBool()) {
+ level = DebugHandler::LoggingLevelDebug;
+ }
+
+ QVariantMap category;
+ category.insert("name", loggingCategory);
+ category.insert("level", enumValueName(level));
+ category.insert("type", enumValueName(LoggingCategoryTypeSystem));
+ categories.append(category);
+ }
+
+ // Plugins
+ foreach (const QString &loggingCategory, NymeaCore::loggingFiltersPlugins()) {
+ allCategories.append(loggingCategory);
+
+ LoggingLevel level = DebugHandler::LoggingLevelCritical;
+ if (settings.value(QString("%1.warning").arg(loggingCategory), true).toBool()) {
+ level = DebugHandler::LoggingLevelWarning;
+ }
+ if (settings.value(QString("%1.info").arg(loggingCategory), false).toBool()) {
+ level = DebugHandler::LoggingLevelInfo;
+ }
+ if (settings.value(QString("%1.debug").arg(loggingCategory), false).toBool()) {
+ level = DebugHandler::LoggingLevelDebug;
+ }
+
+ QVariantMap category;
+ category.insert("name", loggingCategory);
+ category.insert("level", enumValueName(level));
+ category.insert("type", enumValueName(LoggingCategoryTypePlugin));
+ categories.append(category);
+ }
+
+ // Now create all categories, which are not nymea system related
+ foreach (const QString &categoryFilter, settings.childGroups()) {
+ QStringList categoryParts = categoryFilter.split(".");
+ if (categoryParts.isEmpty())
+ continue;
+
+ QString loggingCategory = categoryParts.first();
+ if (allCategories.contains(loggingCategory) || loggingCategory.isEmpty())
+ continue;
+
+ LoggingLevel level = DebugHandler::LoggingLevelCritical;
+ if (settings.value(QString("%1.warning").arg(loggingCategory), true).toBool()) {
+ level = DebugHandler::LoggingLevelWarning;
+ }
+ if (settings.value(QString("%1.info").arg(loggingCategory), false).toBool()) {
+ level = DebugHandler::LoggingLevelInfo;
+ }
+ if (settings.value(QString("%1.debug").arg(loggingCategory), false).toBool()) {
+ level = DebugHandler::LoggingLevelDebug;
+ }
+
+ QVariantMap category;
+ category.insert("name", loggingCategory);
+ category.insert("level", enumValueName(level));
+ category.insert("type", enumValueName(LoggingCategoryTypeCustom));
+ categories.append(category);
+ }
+
+ settings.endGroup(); // LoggingRules
+
+ QVariantMap returns;
+ returns.insert("loggingCategories", categories);
+ return createReply(returns);
+}
+
+JsonReply *DebugHandler::SetLoggingCategoryLevel(const QVariantMap ¶ms)
+{
+ QString category = params.value("name").toString();
+ LoggingLevel level = enumNameToValue(params.value("level").toString());
+
+ NymeaSettings settings(NymeaSettings::SettingsRoleGlobal);
+ settings.beginGroup("LoggingRules");
+
+ qCDebug(dcDebugServer()) << "Logging category" << category << level;
+
+ switch (level) {
+ case LoggingLevelCritical:
+ settings.setValue(QString("%1.warning").arg(category), false);
+ settings.setValue(QString("%1.info").arg(category), false);
+ settings.setValue(QString("%1.debug").arg(category), false);
+ break;
+ case LoggingLevelWarning:
+ settings.setValue(QString("%1.warning").arg(category), true);
+ settings.setValue(QString("%1.info").arg(category), false);
+ settings.setValue(QString("%1.debug").arg(category), false);
+ break;
+ case LoggingLevelInfo:
+ settings.setValue(QString("%1.warning").arg(category), true);
+ settings.setValue(QString("%1.info").arg(category), true);
+ settings.setValue(QString("%1.debug").arg(category), false);
+ break;
+ case LoggingLevelDebug:
+ settings.setValue(QString("%1.warning").arg(category), true);
+ settings.setValue(QString("%1.info").arg(category), true);
+ settings.setValue(QString("%1.debug").arg(category), true);
+ break;
+ }
+
+ // Update logging filter rules according to the nw settings
+ QStringList loggingRules;
+ loggingRules << "*.debug=false";
+ // Load the rules from nymead.conf file and append them to the rules
+ foreach (const QString &category, settings.childKeys()) {
+ loggingRules << QString("%1=%2").arg(category).arg(settings.value(category, "false").toString());
+ }
+ settings.endGroup();
+ QLoggingCategory::setFilterRules(loggingRules.join('\n'));
+
+ emit LoggingCategoryLevelChanged(params);
+
+ QVariantMap returns;
+ returns.insert("debugError", enumValueName(DebugErrorNoError));
+ return createReply(returns);
+ }
+
+}
diff --git a/libnymea-core/jsonrpc/debughandler.h b/libnymea-core/jsonrpc/debughandler.h
new file mode 100644
index 00000000..1cd5165f
--- /dev/null
+++ b/libnymea-core/jsonrpc/debughandler.h
@@ -0,0 +1,79 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2024, 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 .
+*
+* 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 DEBUGHANDLER_H
+#define DEBUGHANDLER_H
+
+#include
+
+#include "jsonrpc/jsonhandler.h"
+
+namespace nymeaserver {
+
+class DebugHandler : public JsonHandler
+{
+ Q_OBJECT
+public:
+ enum DebugError {
+ DebugErrorNoError
+ };
+ Q_ENUM(DebugError)
+
+ enum LoggingCategoryType {
+ LoggingCategoryTypeSystem,
+ LoggingCategoryTypePlugin,
+ LoggingCategoryTypeCustom
+ };
+ Q_ENUM(LoggingCategoryType)
+
+ enum LoggingLevel {
+ LoggingLevelCritical,
+ LoggingLevelWarning,
+ LoggingLevelInfo,
+ LoggingLevelDebug
+ };
+ Q_ENUM(LoggingLevel)
+
+ explicit DebugHandler(QObject *parent = nullptr);
+
+ QString name() const override;
+
+public slots:
+ JsonReply* GetLoggingCategories(const QVariantMap ¶ms);
+ JsonReply* SetLoggingCategoryLevel(const QVariantMap ¶ms);
+
+signals:
+ void LoggingCategoryLevelChanged(const QVariantMap ¶ms);
+
+};
+
+}
+
+#endif // DEBUGHANDLER_H
diff --git a/libnymea-core/libnymea-core.pro b/libnymea-core/libnymea-core.pro
index 98253acc..a058dca2 100644
--- a/libnymea-core/libnymea-core.pro
+++ b/libnymea-core/libnymea-core.pro
@@ -63,6 +63,7 @@ HEADERS += nymeacore.h \
hardware/network/macaddressdatabasereplyimpl.h \
hardware/serialport/serialportmonitor.h \
hardware/zwave/zwavehardwareresourceimplementation.h \
+ jsonrpc/debughandler.h \
logging/logengineinfluxdb.h \
scriptengine/scriptthing.h \
scriptengine/scriptthings.h \
@@ -172,6 +173,7 @@ SOURCES += nymeacore.cpp \
hardware/network/macaddressdatabasereplyimpl.cpp \
hardware/serialport/serialportmonitor.cpp \
hardware/zwave/zwavehardwareresourceimplementation.cpp \
+ jsonrpc/debughandler.cpp \
logging/logengineinfluxdb.cpp \
scriptengine/scriptthing.cpp \
scriptengine/scriptthings.cpp \
diff --git a/libnymea-core/nymeacore.cpp b/libnymea-core/nymeacore.cpp
index 4b1f5c1b..c80c3489 100644
--- a/libnymea-core/nymeacore.cpp
+++ b/libnymea-core/nymeacore.cpp
@@ -41,6 +41,7 @@
#include "logging/logengineinfluxdb.h"
#include "scriptengine/scriptengine.h"
#include "jsonrpc/scriptshandler.h"
+#include "jsonrpc/debughandler.h"
#include "version.h"
#include "integrations/thingmanagerimplementation.h"
@@ -153,10 +154,12 @@ void NymeaCore::init(const QStringList &additionalInterfaces, bool disableLogEng
qCDebug(dcCore) << "Creating Debug Server Handler";
m_debugServerHandler = new DebugServerHandler(this);
+ qCDebug(dcCore) << "Register Debug Handler";
+ m_serverManager->jsonServer()->registerHandler(new DebugHandler(m_serverManager->jsonServer()));
+
qCDebug(dcCore()) << "Loading experiences";
m_experienceManager = new ExperienceManager(m_thingManager, m_serverManager->jsonServer(), this);
-
connect(m_configuration, &NymeaConfiguration::serverNameChanged, m_serverManager, &ServerManager::setServerName);
connect(m_thingManager, &ThingManagerImplementation::loaded, this, &NymeaCore::thingManagerLoaded);
diff --git a/libnymea/loggingcategories.h b/libnymea/loggingcategories.h
index 9f8f20d7..1ac57c5e 100644
--- a/libnymea/loggingcategories.h
+++ b/libnymea/loggingcategories.h
@@ -39,7 +39,11 @@ QStringList& nymeaLoggingCategories();
#define NYMEA_LOGGING_CATEGORY(name, string) \
class NymeaLoggingCategory##name: public QLoggingCategory { \
public: \
- NymeaLoggingCategory##name(): QLoggingCategory(string) { nymeaLoggingCategories().append(string); } \
+ NymeaLoggingCategory##name(): QLoggingCategory(string) { \
+ if (!nymeaLoggingCategories().contains(string)) { \
+ nymeaLoggingCategories().append(string); \
+ } \
+ } \
}; \
static NymeaLoggingCategory##name s_##name; \
const QLoggingCategory &name() \
@@ -47,6 +51,7 @@ QStringList& nymeaLoggingCategories();
return s_##name; \
} \
+
// FIXME: Those should eventually disappear from here
Q_DECLARE_LOGGING_CATEGORY(dcThing)
Q_DECLARE_LOGGING_CATEGORY(dcThingManager)
diff --git a/nymea.pro b/nymea.pro
index bb1d03bf..481c232e 100644
--- a/nymea.pro
+++ b/nymea.pro
@@ -11,7 +11,7 @@ isEmpty(NYMEA_VERSION) {
# define protocol versions
JSON_PROTOCOL_VERSION_MAJOR=8
-JSON_PROTOCOL_VERSION_MINOR=1
+JSON_PROTOCOL_VERSION_MINOR=2
JSON_PROTOCOL_VERSION="$${JSON_PROTOCOL_VERSION_MAJOR}.$${JSON_PROTOCOL_VERSION_MINOR}"
LIBNYMEA_API_VERSION_MAJOR=8
LIBNYMEA_API_VERSION_MINOR=0
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index 70e8a865..18c89b12 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -2,6 +2,7 @@ TEMPLATE = subdirs
SUBDIRS = \
configurations \
+ debughandler \
integrations \
ioconnections \
jsonrpc \
diff --git a/tests/auto/debughandler/debughandler.pro b/tests/auto/debughandler/debughandler.pro
new file mode 100644
index 00000000..48961170
--- /dev/null
+++ b/tests/auto/debughandler/debughandler.pro
@@ -0,0 +1,7 @@
+TARGET = nymeatestdebughandler
+
+include(../../../nymea.pri)
+include(../autotests.pri)
+
+SOURCES += testdebughandler.cpp
+
diff --git a/tests/auto/debughandler/testdebughandler.cpp b/tests/auto/debughandler/testdebughandler.cpp
new file mode 100644
index 00000000..e8ea7d25
--- /dev/null
+++ b/tests/auto/debughandler/testdebughandler.cpp
@@ -0,0 +1,70 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2024, 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 .
+*
+* 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 "nymeatestbase.h"
+
+using namespace nymeaserver;
+
+class TestDebugHandler: public NymeaTestBase
+{
+ Q_OBJECT
+
+protected slots:
+ void initTestCase();
+
+private slots:
+ void getLoggingFilters();
+
+};
+
+void TestDebugHandler::initTestCase()
+{
+ NymeaTestBase::initTestCase("*.debug=false\nApplication.debug=true\nTests.debug=true\nServerManager.debug=true");
+}
+
+void TestDebugHandler::getLoggingFilters()
+{
+ QVariant response = injectAndWait("Debug.GetLoggingCategories");
+ QVariantMap loggingFilters = response.toMap().value("params").toMap();
+
+ QVERIFY(loggingFilters.contains("loggingCategories"));
+ QVariantList loggingCategoriesList = loggingFilters.value("loggingCategories").toList();
+ QVERIFY(!loggingCategoriesList.isEmpty());
+
+ foreach(const QVariant &categoryVariant, loggingCategoriesList) {
+ QVariantMap categoryMap = categoryVariant.toMap();
+ QVERIFY(categoryMap.contains("level"));
+ QVERIFY(categoryMap.contains("name"));
+ QVERIFY(categoryMap.contains("type"));
+ }
+}
+
+#include "testdebughandler.moc"
+QTEST_MAIN(TestDebugHandler)