Compare commits
10 Commits
abd8dd2d97
...
5b73038726
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b73038726 | ||
|
|
0070d7e3dd | ||
|
|
ab61ed9a8b | ||
|
|
3c7e1bed4f | ||
|
|
89ad2d0f12 | ||
|
|
028da6a3b4 | ||
|
|
b58c5646df | ||
|
|
53b00a950f | ||
|
|
5eb5c6628b | ||
|
|
a1d0574e20 |
@ -1,3 +1,20 @@
|
|||||||
|
nymea (1.14.2) noble; urgency=medium
|
||||||
|
|
||||||
|
[ Simon Stürz ]
|
||||||
|
* Improve system update plugin API
|
||||||
|
|
||||||
|
-- jenkins <developer@nymea.io> Thu, 19 Feb 2026 16:27:40 +0100
|
||||||
|
|
||||||
|
nymea (1.14.1) noble; urgency=medium
|
||||||
|
|
||||||
|
[ Simon Stürz ]
|
||||||
|
* LogEngine: Improve behavior of disabled logengine
|
||||||
|
* JsonRpc Server: Improve token verification handling
|
||||||
|
* Update default loations for the mac-addresses.db to be more generic
|
||||||
|
* Thing: Add state name based set method for possible values
|
||||||
|
|
||||||
|
-- jenkins <developer@nymea.io> Tue, 10 Feb 2026 12:05:47 +0100
|
||||||
|
|
||||||
nymea (1.14.0) noble; urgency=medium
|
nymea (1.14.0) noble; urgency=medium
|
||||||
|
|
||||||
[ Simon Stürz ]
|
[ Simon Stürz ]
|
||||||
|
|||||||
@ -30,6 +30,7 @@
|
|||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QSqlDatabase>
|
#include <QSqlDatabase>
|
||||||
|
#include <QDir>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QtConcurrent/QtConcurrent>
|
#include <QtConcurrent/QtConcurrent>
|
||||||
|
|
||||||
@ -41,18 +42,30 @@ MacAddressDatabase::MacAddressDatabase(QObject *parent) : QObject(parent)
|
|||||||
{
|
{
|
||||||
// Find database in system data locations
|
// Find database in system data locations
|
||||||
QString databaseFileName;
|
QString databaseFileName;
|
||||||
foreach (const QString &dataLocation, QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation)) {
|
const QStringList dataLocations = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
|
||||||
QFileInfo databaseFileInfo(dataLocation + QDir::separator() + "mac-addresses.db");
|
foreach (const QString &dataLocation, dataLocations) {
|
||||||
if (!databaseFileInfo.exists()) {
|
const QStringList candidateFiles = {
|
||||||
continue;
|
dataLocation + QDir::separator() + "nymea" + QDir::separator() + "nymead" + QDir::separator() + "mac-addresses.db",
|
||||||
|
dataLocation + QDir::separator() + "nymea" + QDir::separator() + "mac-addresses.db",
|
||||||
|
dataLocation + QDir::separator() + "mac-addresses.db"
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (const QString &candidate, candidateFiles) {
|
||||||
|
QFileInfo databaseFileInfo(candidate);
|
||||||
|
if (!databaseFileInfo.exists())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
databaseFileName = databaseFileInfo.absoluteFilePath();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
databaseFileName = databaseFileInfo.absoluteFilePath();
|
if (!databaseFileName.isEmpty())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (databaseFileName.isEmpty()) {
|
if (databaseFileName.isEmpty()) {
|
||||||
qCWarning(dcMacAddressDatabase()) << "Could not find the mac address database in any system data location paths" << QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
|
qCWarning(dcMacAddressDatabase()) << "Could not find the mac address database in any system data location paths" << dataLocations;
|
||||||
qCWarning(dcMacAddressDatabase()) << "The mac address database lookup feature will not be available.";
|
qCWarning(dcMacAddressDatabase()) << "The mac address database lookup feature will not be available.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,7 +50,7 @@ private:
|
|||||||
QSqlDatabase m_db;
|
QSqlDatabase m_db;
|
||||||
bool m_available = false;
|
bool m_available = false;
|
||||||
QString m_connectionName;
|
QString m_connectionName;
|
||||||
QString m_databaseName = "/usr/share/nymea/mac-addresses.db";
|
QString m_databaseName = "/usr/share/nymea/nymead/mac-addresses.db";
|
||||||
|
|
||||||
MacAddressDatabaseReplyImpl *m_currentReply = nullptr;
|
MacAddressDatabaseReplyImpl *m_currentReply = nullptr;
|
||||||
QFutureWatcher<QString> *m_futureWatcher = nullptr;
|
QFutureWatcher<QString> *m_futureWatcher = nullptr;
|
||||||
|
|||||||
@ -789,7 +789,7 @@ JsonReply *IntegrationsHandler::GetThings(const QVariantMap ¶ms, const JsonC
|
|||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
QVariantList things;
|
QVariantList things;
|
||||||
|
|
||||||
if (NymeaCore::instance()->userManager()->hasRestrictedThingAccess(context.token())) {
|
if (NymeaCore::instance()->userManager()->hasRestrictedThingAccess(context.token()) && context.authenticationEnabled()) {
|
||||||
// Restricted things access
|
// Restricted things access
|
||||||
QList<ThingId> allowedThingIds = NymeaCore::instance()->userManager()->getAllowedThingIdsForToken(context.token());
|
QList<ThingId> allowedThingIds = NymeaCore::instance()->userManager()->getAllowedThingIdsForToken(context.token());
|
||||||
if (params.contains("thingId")) {
|
if (params.contains("thingId")) {
|
||||||
@ -983,7 +983,7 @@ JsonReply *IntegrationsHandler::GetStateTypes(const QVariantMap ¶ms, const J
|
|||||||
JsonReply *IntegrationsHandler::GetStateValue(const QVariantMap ¶ms, const JsonContext &context) const
|
JsonReply *IntegrationsHandler::GetStateValue(const QVariantMap ¶ms, const JsonContext &context) const
|
||||||
{
|
{
|
||||||
ThingId thingId(params.value("thingId").toString());
|
ThingId thingId(params.value("thingId").toString());
|
||||||
if (!NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
if (context.authenticationEnabled() && !NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
||||||
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
||||||
|
|
||||||
Thing *thing = m_thingManager->findConfiguredThing(thingId);
|
Thing *thing = m_thingManager->findConfiguredThing(thingId);
|
||||||
@ -1002,7 +1002,7 @@ JsonReply *IntegrationsHandler::GetStateValue(const QVariantMap ¶ms, const J
|
|||||||
JsonReply *IntegrationsHandler::GetStateValues(const QVariantMap ¶ms, const JsonContext &context) const
|
JsonReply *IntegrationsHandler::GetStateValues(const QVariantMap ¶ms, const JsonContext &context) const
|
||||||
{
|
{
|
||||||
ThingId thingId(params.value("thingId").toString());
|
ThingId thingId(params.value("thingId").toString());
|
||||||
if (!NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
if (context.authenticationEnabled() && !NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
||||||
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
||||||
|
|
||||||
Thing *thing = m_thingManager->findConfiguredThing(thingId);
|
Thing *thing = m_thingManager->findConfiguredThing(thingId);
|
||||||
@ -1017,7 +1017,7 @@ JsonReply *IntegrationsHandler::GetStateValues(const QVariantMap ¶ms, const
|
|||||||
JsonReply *IntegrationsHandler::BrowseThing(const QVariantMap ¶ms, const JsonContext &context) const
|
JsonReply *IntegrationsHandler::BrowseThing(const QVariantMap ¶ms, const JsonContext &context) const
|
||||||
{
|
{
|
||||||
ThingId thingId(params.value("thingId").toString());
|
ThingId thingId(params.value("thingId").toString());
|
||||||
if (!NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
if (context.authenticationEnabled() && !NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
||||||
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
||||||
|
|
||||||
QString itemId = params.value("itemId").toString();
|
QString itemId = params.value("itemId").toString();
|
||||||
@ -1047,7 +1047,7 @@ JsonReply *IntegrationsHandler::BrowseThing(const QVariantMap ¶ms, const Jso
|
|||||||
JsonReply *IntegrationsHandler::GetBrowserItem(const QVariantMap ¶ms, const JsonContext &context) const
|
JsonReply *IntegrationsHandler::GetBrowserItem(const QVariantMap ¶ms, const JsonContext &context) const
|
||||||
{
|
{
|
||||||
ThingId thingId(params.value("thingId").toString());
|
ThingId thingId(params.value("thingId").toString());
|
||||||
if (!NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
if (context.authenticationEnabled() && !NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
||||||
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
||||||
|
|
||||||
QString itemId = params.value("itemId").toString();
|
QString itemId = params.value("itemId").toString();
|
||||||
@ -1072,7 +1072,7 @@ JsonReply *IntegrationsHandler::GetBrowserItem(const QVariantMap ¶ms, const
|
|||||||
JsonReply *IntegrationsHandler::ExecuteAction(const QVariantMap ¶ms, const JsonContext &context)
|
JsonReply *IntegrationsHandler::ExecuteAction(const QVariantMap ¶ms, const JsonContext &context)
|
||||||
{
|
{
|
||||||
ThingId thingId(params.value("thingId").toString());
|
ThingId thingId(params.value("thingId").toString());
|
||||||
if (!NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
if (context.authenticationEnabled() && !NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
||||||
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
||||||
|
|
||||||
ActionTypeId actionTypeId(params.value("actionTypeId").toString());
|
ActionTypeId actionTypeId(params.value("actionTypeId").toString());
|
||||||
@ -1101,7 +1101,7 @@ JsonReply *IntegrationsHandler::ExecuteAction(const QVariantMap ¶ms, const J
|
|||||||
JsonReply *IntegrationsHandler::ExecuteBrowserItem(const QVariantMap ¶ms, const JsonContext &context)
|
JsonReply *IntegrationsHandler::ExecuteBrowserItem(const QVariantMap ¶ms, const JsonContext &context)
|
||||||
{
|
{
|
||||||
ThingId thingId = ThingId(params.value("thingId").toString());
|
ThingId thingId = ThingId(params.value("thingId").toString());
|
||||||
if (!NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
if (context.authenticationEnabled() && !NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
||||||
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
||||||
|
|
||||||
QString itemId = params.value("itemId").toString();
|
QString itemId = params.value("itemId").toString();
|
||||||
@ -1126,7 +1126,7 @@ JsonReply *IntegrationsHandler::ExecuteBrowserItem(const QVariantMap ¶ms, co
|
|||||||
JsonReply *IntegrationsHandler::ExecuteBrowserItemAction(const QVariantMap ¶ms, const JsonContext &context)
|
JsonReply *IntegrationsHandler::ExecuteBrowserItemAction(const QVariantMap ¶ms, const JsonContext &context)
|
||||||
{
|
{
|
||||||
ThingId thingId = ThingId(params.value("thingId").toString());
|
ThingId thingId = ThingId(params.value("thingId").toString());
|
||||||
if (!NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
if (context.authenticationEnabled() && !NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
||||||
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
||||||
|
|
||||||
QString itemId = params.value("itemId").toString();
|
QString itemId = params.value("itemId").toString();
|
||||||
@ -1153,7 +1153,7 @@ JsonReply *IntegrationsHandler::ExecuteBrowserItemAction(const QVariantMap ¶
|
|||||||
JsonReply *IntegrationsHandler::GetIOConnections(const QVariantMap ¶ms, const JsonContext &context)
|
JsonReply *IntegrationsHandler::GetIOConnections(const QVariantMap ¶ms, const JsonContext &context)
|
||||||
{
|
{
|
||||||
ThingId thingId = params.value("thingId").toUuid();
|
ThingId thingId = params.value("thingId").toUuid();
|
||||||
if (!NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
if (context.authenticationEnabled() && !NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
||||||
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
||||||
|
|
||||||
IOConnections ioConnections = m_thingManager->ioConnections(thingId);
|
IOConnections ioConnections = m_thingManager->ioConnections(thingId);
|
||||||
|
|||||||
@ -603,7 +603,7 @@ void JsonRPCServerImplementation::processJsonPacket(TransportInterface *interfac
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check if authentication is required for this transport
|
// check if authentication is required for this transport
|
||||||
if (interface->configuration().authenticationEnabled) {
|
if (interface->configuration().authenticationEnabled) {
|
||||||
QStringList authExemptMethodsNoUser = {"JSONRPC.Hello", "JSONRPC.RequestPushButtonAuth", "JSONRPC.CreateUser"};
|
QStringList authExemptMethodsNoUser = {"JSONRPC.Hello", "JSONRPC.RequestPushButtonAuth", "JSONRPC.CreateUser"};
|
||||||
QStringList authExemptMethodsWithUser = {"JSONRPC.Hello", "JSONRPC.Authenticate", "JSONRPC.RequestPushButtonAuth"};
|
QStringList authExemptMethodsWithUser = {"JSONRPC.Hello", "JSONRPC.Authenticate", "JSONRPC.RequestPushButtonAuth"};
|
||||||
// if there is no user in the system yet, let's fail unless this is a special method for authentication itself
|
// if there is no user in the system yet, let's fail unless this is a special method for authentication itself
|
||||||
@ -617,7 +617,7 @@ void JsonRPCServerImplementation::processJsonPacket(TransportInterface *interfac
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// ok, we have a user. if there isn't a valid token, let's fail unless this is a Authenticate, Introspect Hello call
|
// Ok, we have a user. If there isn't a valid token, let's fail unless this is an authentication related call
|
||||||
if (!authExemptMethodsWithUser.contains(methodString)) {
|
if (!authExemptMethodsWithUser.contains(methodString)) {
|
||||||
if (token.isEmpty() || !NymeaCore::instance()->userManager()->verifyToken(token)) {
|
if (token.isEmpty() || !NymeaCore::instance()->userManager()->verifyToken(token)) {
|
||||||
sendUnauthorizedResponse(interface, clientId, commandId, "Forbidden: Invalid token.");
|
sendUnauthorizedResponse(interface, clientId, commandId, "Forbidden: Invalid token.");
|
||||||
@ -681,7 +681,7 @@ void JsonRPCServerImplementation::processJsonPacket(TransportInterface *interfac
|
|||||||
handler->setProperty("transportInterface", reinterpret_cast<qint64>(interface));
|
handler->setProperty("transportInterface", reinterpret_cast<qint64>(interface));
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonContext callContext(clientId, m_clientLocales.value(clientId));
|
JsonContext callContext(clientId, m_clientLocales.value(clientId), interface->configuration().authenticationEnabled);
|
||||||
callContext.setToken(token);
|
callContext.setToken(token);
|
||||||
|
|
||||||
qCDebug(dcJsonRpc()) << "Invoking method" << targetNamespace + '.' + method << "from client" << clientId;
|
qCDebug(dcJsonRpc()) << "Invoking method" << targetNamespace + '.' + method << "from client" << clientId;
|
||||||
@ -809,7 +809,9 @@ void JsonRPCServerImplementation::sendClientNotification(const QVariantMap ¶
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Make sure this client is allowed to receive this notification
|
// Make sure this client is allowed to receive this notification
|
||||||
if (m_clientTokens.contains(clientId)) {
|
TransportInterface *transport = m_clientTransports.value(clientId, nullptr);
|
||||||
|
const bool authEnabled = transport ? transport->configuration().authenticationEnabled : true;
|
||||||
|
if (authEnabled && m_clientTokens.contains(clientId)) {
|
||||||
const QByteArray token = m_clientTokens.value(clientId);
|
const QByteArray token = m_clientTokens.value(clientId);
|
||||||
if (!NymeaCore::instance()->userManager()->accessToThingGranted(thingId, token)) {
|
if (!NymeaCore::instance()->userManager()->accessToThingGranted(thingId, token)) {
|
||||||
qCDebug(dcJsonRpc()) << "Not sending notification to client" << "to client" << clientId.toString()
|
qCDebug(dcJsonRpc()) << "Not sending notification to client" << "to client" << clientId.toString()
|
||||||
@ -849,9 +851,24 @@ void JsonRPCServerImplementation::sendClientNotification(const QVariantMap ¶
|
|||||||
{
|
{
|
||||||
// Send client specific notifications
|
// Send client specific notifications
|
||||||
qCDebug(dcJsonRpc()) << "Sending notification to client" << userInfo.username() << "connections...";
|
qCDebug(dcJsonRpc()) << "Sending notification to client" << userInfo.username() << "connections...";
|
||||||
foreach (const QByteArray &token, m_clientTokens) {
|
for (auto it = m_clientTokens.constBegin(); it != m_clientTokens.constEnd(); ++it) {
|
||||||
|
const QUuid clientId = it.key();
|
||||||
|
const QByteArray token = it.value();
|
||||||
|
|
||||||
|
TransportInterface *transport = m_clientTransports.value(clientId, nullptr);
|
||||||
|
const bool authEnabled = transport ? transport->configuration().authenticationEnabled : true;
|
||||||
|
|
||||||
|
if (!authEnabled) {
|
||||||
|
sendClientNotification(clientId, params);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (NymeaCore::instance()->userManager()->tokenInfo(token).username() == userInfo.username()) {
|
if (NymeaCore::instance()->userManager()->tokenInfo(token).username() == userInfo.username()) {
|
||||||
sendClientNotification(m_clientTokens.key(token), params);
|
sendClientNotification(clientId, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,15 +38,18 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent):
|
|||||||
registerObject<Package, Packages>();
|
registerObject<Package, Packages>();
|
||||||
registerObject<Repository, Repositories>();
|
registerObject<Repository, Repositories>();
|
||||||
|
|
||||||
|
registerEnum<PlatformUpdateController::UpdateType>();
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
QString description; QVariantMap params; QVariantMap returns;
|
QString description; QVariantMap params; QVariantMap returns;
|
||||||
description = "Get the list of capabilites on this system. The property \"powerManagement\" indicates whether "
|
description = "Get the list of capabilites on this system. The property \"powerManagement\" indicates whether "
|
||||||
"restarting nymea and rebooting or shutting down is supported on this system. The property \"updateManagement indicates "
|
"restarting nymea and rebooting or shutting down is supported on this system. The property \"updateManagement\" indicates "
|
||||||
"whether system update features are available in this system. The property \"timeManagement\" "
|
"whether system update features are available in this system. The \"updateManagementType\" indicates which kind of update is "
|
||||||
"indicates whether the system time can be configured on this system. Note that GetTime will be "
|
"supported on this platform. The property \"timeManagement\" indicates whether the system time can be configured "
|
||||||
"available in any case.";
|
"on this system. Note that GetTime will be available in any case.";
|
||||||
returns.insert("powerManagement", enumValueName(Bool));
|
returns.insert("powerManagement", enumValueName(Bool));
|
||||||
returns.insert("updateManagement", enumValueName(Bool));
|
returns.insert("updateManagement", enumValueName(Bool));
|
||||||
|
returns.insert("updateManagementType", enumRef<PlatformUpdateController::UpdateType>());
|
||||||
returns.insert("timeManagement", enumValueName(Bool));
|
returns.insert("timeManagement", enumValueName(Bool));
|
||||||
registerMethod("GetCapabilities", description, params, returns);
|
registerMethod("GetCapabilities", description, params, returns);
|
||||||
|
|
||||||
@ -66,15 +69,17 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent):
|
|||||||
registerMethod("Shutdown", description, params, returns);
|
registerMethod("Shutdown", description, params, returns);
|
||||||
|
|
||||||
params.clear(); returns.clear();
|
params.clear(); returns.clear();
|
||||||
description = "Get the current status of the update system. \"busy\" indicates that the system is current busy with "
|
description = "Get the current status of the update system. \"busy\" indicates that the system is current busy with "
|
||||||
"an operation regarding updates. This does not necessarily mean an actual update is running. When this "
|
"an operation regarding updates. This does not necessarily mean an actual update is running. When this "
|
||||||
"is true, update related functions on the client should be marked as busy and no interaction with update "
|
"is true, update related functions on the client should be marked as busy and no interaction with update "
|
||||||
"components shall be allowed. An example for such a state is when the system queries the server if there "
|
"components shall be allowed. An example for such a state is when the system queries the server if there "
|
||||||
"are updates available, typically after a call to CheckForUpdates. \"updateRunning\" on the other hand "
|
"are updates available, typically after a call to CheckForUpdates. \"updateRunning\" on the other hand "
|
||||||
"indicates an actual update process is ongoing. The user should be informed about it, the system also "
|
"indicates an actual update process is ongoing. The user should be informed about it, the system also "
|
||||||
"might restart at any point while an update is running.";
|
"might restart at any point while an update is running. The \"updateProgress\" property is optional, "
|
||||||
|
"if the backend supports it, a progress >= 0 indicated the update progress in percentage.";
|
||||||
returns.insert("busy", enumValueName(Bool));
|
returns.insert("busy", enumValueName(Bool));
|
||||||
returns.insert("updateRunning", enumValueName(Bool));
|
returns.insert("updateRunning", enumValueName(Bool));
|
||||||
|
returns.insert("o:updateProgress", enumValueName(Int));
|
||||||
registerMethod("GetUpdateStatus", description, params, returns);
|
registerMethod("GetUpdateStatus", description, params, returns);
|
||||||
|
|
||||||
params.clear(); returns.clear();
|
params.clear(); returns.clear();
|
||||||
@ -172,12 +177,14 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent):
|
|||||||
description = "Emitted whenever the system capabilities change.";
|
description = "Emitted whenever the system capabilities change.";
|
||||||
params.insert("powerManagement", enumValueName(Bool));
|
params.insert("powerManagement", enumValueName(Bool));
|
||||||
params.insert("updateManagement", enumValueName(Bool));
|
params.insert("updateManagement", enumValueName(Bool));
|
||||||
|
params.insert("updateManagementType", enumRef<PlatformUpdateController::UpdateType>());
|
||||||
registerNotification("CapabilitiesChanged", description, params);
|
registerNotification("CapabilitiesChanged", description, params);
|
||||||
|
|
||||||
params.clear();
|
params.clear();
|
||||||
description = "Emitted whenever the update status changes.";
|
description = "Emitted whenever the update status changes.";
|
||||||
params.insert("busy", enumValueName(Bool));
|
params.insert("busy", enumValueName(Bool));
|
||||||
params.insert("updateRunning", enumValueName(Bool));
|
params.insert("updateRunning", enumValueName(Bool));
|
||||||
|
params.insert("o:updateProgress", enumValueName(Int));
|
||||||
registerNotification("UpdateStatusChanged", description, params);
|
registerNotification("UpdateStatusChanged", description, params);
|
||||||
|
|
||||||
params.clear();
|
params.clear();
|
||||||
@ -220,18 +227,17 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent):
|
|||||||
|
|
||||||
connect(m_platform->systemController(), &PlatformSystemController::availableChanged, this, &SystemHandler::onCapabilitiesChanged);
|
connect(m_platform->systemController(), &PlatformSystemController::availableChanged, this, &SystemHandler::onCapabilitiesChanged);
|
||||||
connect(m_platform->updateController(), &PlatformUpdateController::availableChanged, this, &SystemHandler::onCapabilitiesChanged);
|
connect(m_platform->updateController(), &PlatformUpdateController::availableChanged, this, &SystemHandler::onCapabilitiesChanged);
|
||||||
|
|
||||||
connect(m_platform->updateController(), &PlatformUpdateController::busyChanged, this, [this](){
|
connect(m_platform->updateController(), &PlatformUpdateController::busyChanged, this, [this](){
|
||||||
QVariantMap params;
|
emit UpdateStatusChanged(buildUpdateStatus());
|
||||||
params.insert("busy", m_platform->updateController()->busy());
|
|
||||||
params.insert("updateRunning", m_platform->updateController()->updateRunning());
|
|
||||||
emit UpdateStatusChanged(params);
|
|
||||||
});
|
});
|
||||||
connect(m_platform->updateController(), &PlatformUpdateController::updateRunningChanged, this, [this](){
|
connect(m_platform->updateController(), &PlatformUpdateController::updateRunningChanged, this, [this](){
|
||||||
QVariantMap params;
|
emit UpdateStatusChanged(buildUpdateStatus());
|
||||||
params.insert("busy", m_platform->updateController()->busy());
|
|
||||||
params.insert("updateRunning", m_platform->updateController()->updateRunning());
|
|
||||||
emit UpdateStatusChanged(params);
|
|
||||||
});
|
});
|
||||||
|
connect(m_platform->updateController(), &PlatformUpdateController::updateProgressChanged, this, [this](){
|
||||||
|
emit UpdateStatusChanged(buildUpdateStatus());
|
||||||
|
});
|
||||||
|
|
||||||
connect(m_platform->updateController(), &PlatformUpdateController::packageAdded, this, [this](const Package &package){
|
connect(m_platform->updateController(), &PlatformUpdateController::packageAdded, this, [this](const Package &package){
|
||||||
QVariantMap params;
|
QVariantMap params;
|
||||||
params.insert("package", pack(package));
|
params.insert("package", pack(package));
|
||||||
@ -247,6 +253,7 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent):
|
|||||||
params.insert("packageId", packageId);
|
params.insert("packageId", packageId);
|
||||||
emit PackageRemoved(params);
|
emit PackageRemoved(params);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(m_platform->updateController(), &PlatformUpdateController::repositoryAdded, this, [this](const Repository &repository){
|
connect(m_platform->updateController(), &PlatformUpdateController::repositoryAdded, this, [this](const Repository &repository){
|
||||||
QVariantMap params;
|
QVariantMap params;
|
||||||
params.insert("repository", pack(repository));
|
params.insert("repository", pack(repository));
|
||||||
@ -262,6 +269,7 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent):
|
|||||||
params.insert("repositoryId", repositoryId);
|
params.insert("repositoryId", repositoryId);
|
||||||
emit RepositoryRemoved(params);
|
emit RepositoryRemoved(params);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(m_platform->systemController(), &PlatformSystemController::timeConfigurationChanged, this, [this](){
|
connect(m_platform->systemController(), &PlatformSystemController::timeConfigurationChanged, this, [this](){
|
||||||
QVariantMap params;
|
QVariantMap params;
|
||||||
params.insert("time", QDateTime::currentMSecsSinceEpoch() / 1000);
|
params.insert("time", QDateTime::currentMSecsSinceEpoch() / 1000);
|
||||||
@ -283,6 +291,7 @@ JsonReply *SystemHandler::GetCapabilities(const QVariantMap ¶ms)
|
|||||||
QVariantMap data;
|
QVariantMap data;
|
||||||
data.insert("powerManagement", m_platform->systemController()->powerManagementAvailable());
|
data.insert("powerManagement", m_platform->systemController()->powerManagementAvailable());
|
||||||
data.insert("updateManagement", m_platform->updateController()->updateManagementAvailable());
|
data.insert("updateManagement", m_platform->updateController()->updateManagementAvailable());
|
||||||
|
data.insert("updateManagementType", enumValueName(m_platform->updateController()->updateType()));
|
||||||
data.insert("timeManagement", m_platform->systemController()->timeManagementAvailable());
|
data.insert("timeManagement", m_platform->systemController()->timeManagementAvailable());
|
||||||
return createReply(data);
|
return createReply(data);
|
||||||
}
|
}
|
||||||
@ -317,10 +326,7 @@ JsonReply *SystemHandler::Shutdown(const QVariantMap ¶ms) const
|
|||||||
JsonReply *SystemHandler::GetUpdateStatus(const QVariantMap ¶ms) const
|
JsonReply *SystemHandler::GetUpdateStatus(const QVariantMap ¶ms) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(params)
|
Q_UNUSED(params)
|
||||||
QVariantMap ret;
|
return createReply(buildUpdateStatus());
|
||||||
ret.insert("busy", m_platform->updateController()->busy());
|
|
||||||
ret.insert("updateRunning", m_platform->updateController()->updateRunning());
|
|
||||||
return createReply(ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonReply *SystemHandler::CheckForUpdates(const QVariantMap ¶ms) const
|
JsonReply *SystemHandler::CheckForUpdates(const QVariantMap ¶ms) const
|
||||||
@ -459,7 +465,19 @@ void SystemHandler::onCapabilitiesChanged()
|
|||||||
QVariantMap caps;
|
QVariantMap caps;
|
||||||
caps.insert("powerManagement", m_platform->systemController()->powerManagementAvailable());
|
caps.insert("powerManagement", m_platform->systemController()->powerManagementAvailable());
|
||||||
caps.insert("updateManagement", m_platform->updateController()->updateManagementAvailable());
|
caps.insert("updateManagement", m_platform->updateController()->updateManagementAvailable());
|
||||||
|
caps.insert("updateManagementType", enumValueName(m_platform->updateController()->updateType()));
|
||||||
emit CapabilitiesChanged(caps);
|
emit CapabilitiesChanged(caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariantMap SystemHandler::buildUpdateStatus() const
|
||||||
|
{
|
||||||
|
QVariantMap params;
|
||||||
|
params.insert("busy", m_platform->updateController()->busy());
|
||||||
|
params.insert("updateRunning", m_platform->updateController()->updateRunning());
|
||||||
|
if (m_platform->updateController()->updateProgress() >= 0)
|
||||||
|
params.insert("updateProgress", m_platform->updateController()->updateProgress());
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -82,6 +82,8 @@ private slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Platform *m_platform = nullptr;
|
Platform *m_platform = nullptr;
|
||||||
|
|
||||||
|
QVariantMap buildUpdateStatus() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -189,15 +189,21 @@ JsonReply *UsersHandler::ChangePassword(const QVariantMap ¶ms, const JsonCon
|
|||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
|
|
||||||
QByteArray currentToken = context.token();
|
QByteArray currentToken = context.token();
|
||||||
if (currentToken.isEmpty()) {
|
if (context.authenticationEnabled()) {
|
||||||
qCWarning(dcJsonRpc()) << "Cannot change password from an unauthenticated connection";
|
if (currentToken.isEmpty()) {
|
||||||
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
qCWarning(dcJsonRpc()) << "Cannot change password from an unauthenticated connection";
|
||||||
return createReply(returns);
|
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
||||||
}
|
return createReply(returns);
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_userManager->verifyToken(currentToken)) {
|
if (!m_userManager->verifyToken(currentToken)) {
|
||||||
// Might happen if the client is connecting via an unauthenticated connection but tries to sneak in an invalid token
|
// Might happen if the client is connecting via an unauthenticated connection but tries to sneak in an invalid token
|
||||||
qCWarning(dcJsonRpc()) << "Invalid token. Is this an unauthenticated connection?";
|
qCWarning(dcJsonRpc()) << "Invalid token. Is this an unauthenticated connection?";
|
||||||
|
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
||||||
|
return createReply(returns);
|
||||||
|
}
|
||||||
|
} else if (currentToken.isEmpty()) {
|
||||||
|
qCWarning(dcJsonRpc()) << "Cannot change password without token even if authentication is disabled for the transport";
|
||||||
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
||||||
return createReply(returns);
|
return createReply(returns);
|
||||||
}
|
}
|
||||||
@ -216,15 +222,21 @@ JsonReply *UsersHandler::ChangeUserPassword(const QVariantMap ¶ms, const Jso
|
|||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
|
|
||||||
QByteArray currentToken = context.token();
|
QByteArray currentToken = context.token();
|
||||||
if (currentToken.isEmpty()) {
|
if (context.authenticationEnabled()) {
|
||||||
qCWarning(dcJsonRpc()) << "Cannot change a user password from an unauthenticated connection";
|
if (currentToken.isEmpty()) {
|
||||||
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
qCWarning(dcJsonRpc()) << "Cannot change a user password from an unauthenticated connection";
|
||||||
return createReply(returns);
|
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
||||||
}
|
return createReply(returns);
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_userManager->verifyToken(currentToken)) {
|
if (!m_userManager->verifyToken(currentToken)) {
|
||||||
// Might happen if the client is connecting via an unauthenticated connection but tries to sneak in an invalid token
|
// Might happen if the client is connecting via an unauthenticated connection but tries to sneak in an invalid token
|
||||||
qCWarning(dcJsonRpc()) << "Invalid token. Cannot change a user password from an unauthenticated connection";
|
qCWarning(dcJsonRpc()) << "Invalid token. Cannot change a user password from an unauthenticated connection";
|
||||||
|
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
||||||
|
return createReply(returns);
|
||||||
|
}
|
||||||
|
} else if (currentToken.isEmpty()) {
|
||||||
|
qCWarning(dcJsonRpc()) << "Cannot change a user password without token even if authentication is disabled for the transport";
|
||||||
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
||||||
return createReply(returns);
|
return createReply(returns);
|
||||||
}
|
}
|
||||||
@ -244,15 +256,21 @@ JsonReply *UsersHandler::GetUserInfo(const QVariantMap ¶ms, const JsonContex
|
|||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
|
|
||||||
QByteArray currentToken = context.token();
|
QByteArray currentToken = context.token();
|
||||||
if (currentToken.isEmpty()) {
|
if (context.authenticationEnabled()) {
|
||||||
qCWarning(dcJsonRpc()) << "Cannot get user info from an unauthenticated connection";
|
if (currentToken.isEmpty()) {
|
||||||
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
qCWarning(dcJsonRpc()) << "Cannot get user info from an unauthenticated connection";
|
||||||
return createReply(returns);
|
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
||||||
}
|
return createReply(returns);
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_userManager->verifyToken(currentToken)) {
|
if (!m_userManager->verifyToken(currentToken)) {
|
||||||
// Might happen if the client is connecting via an unauthenticated connection but tries to sneak in an invalid token
|
// Might happen if the client is connecting via an unauthenticated connection but tries to sneak in an invalid token
|
||||||
qCWarning(dcJsonRpc()) << "Invalid token. Is this an unauthenticated connection?";
|
qCWarning(dcJsonRpc()) << "Invalid token. Is this an unauthenticated connection?";
|
||||||
|
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
||||||
|
return createReply(returns);
|
||||||
|
}
|
||||||
|
} else if (currentToken.isEmpty()) {
|
||||||
|
qCWarning(dcJsonRpc()) << "Cannot get user info without token even if authentication is disabled for the transport";
|
||||||
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
||||||
return createReply(returns);
|
return createReply(returns);
|
||||||
}
|
}
|
||||||
@ -272,15 +290,21 @@ JsonReply *UsersHandler::GetTokens(const QVariantMap ¶ms, const JsonContext
|
|||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
|
|
||||||
QByteArray currentToken = context.token();
|
QByteArray currentToken = context.token();
|
||||||
if (currentToken.isEmpty()) {
|
if (context.authenticationEnabled()) {
|
||||||
qCWarning(dcJsonRpc()) << "Cannot fetch tokens for an unauthenticated connection";
|
if (currentToken.isEmpty()) {
|
||||||
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
qCWarning(dcJsonRpc()) << "Cannot fetch tokens for an unauthenticated connection";
|
||||||
return createReply(returns);
|
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
||||||
}
|
return createReply(returns);
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_userManager->verifyToken(currentToken)) {
|
if (!m_userManager->verifyToken(currentToken)) {
|
||||||
// Might happen if the client is connecting via an unauthenticated connection but tries to sneak in an invalid token
|
// Might happen if the client is connecting via an unauthenticated connection but tries to sneak in an invalid token
|
||||||
qCWarning(dcJsonRpc()) << "Invalid token. Is this an unauthenticated connection?";
|
qCWarning(dcJsonRpc()) << "Invalid token. Is this an unauthenticated connection?";
|
||||||
|
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
||||||
|
return createReply(returns);
|
||||||
|
}
|
||||||
|
} else if (currentToken.isEmpty()) {
|
||||||
|
qCWarning(dcJsonRpc()) << "Cannot fetch tokens without token even if authentication is disabled for the transport";
|
||||||
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
||||||
return createReply(returns);
|
return createReply(returns);
|
||||||
}
|
}
|
||||||
@ -302,15 +326,21 @@ JsonReply *UsersHandler::GetUserTokens(const QVariantMap ¶ms, const JsonCont
|
|||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
|
|
||||||
QByteArray currentToken = context.token();
|
QByteArray currentToken = context.token();
|
||||||
if (currentToken.isEmpty()) {
|
if (context.authenticationEnabled()) {
|
||||||
qCWarning(dcJsonRpc()) << "Cannot fetch tokens for an unauthenticated connection";
|
if (currentToken.isEmpty()) {
|
||||||
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
qCWarning(dcJsonRpc()) << "Cannot fetch tokens for an unauthenticated connection";
|
||||||
return createReply(returns);
|
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
||||||
}
|
return createReply(returns);
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_userManager->verifyToken(currentToken)) {
|
if (!m_userManager->verifyToken(currentToken)) {
|
||||||
// Might happen if the client is connecting via an unauthenticated connection but tries to sneak in an invalid token
|
// Might happen if the client is connecting via an unauthenticated connection but tries to sneak in an invalid token
|
||||||
qCWarning(dcJsonRpc()) << "Invalid token. Is this an unauthenticated connection?";
|
qCWarning(dcJsonRpc()) << "Invalid token. Is this an unauthenticated connection?";
|
||||||
|
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
||||||
|
return createReply(returns);
|
||||||
|
}
|
||||||
|
} else if (currentToken.isEmpty()) {
|
||||||
|
qCWarning(dcJsonRpc()) << "Cannot fetch tokens without token even if authentication is disabled for the transport";
|
||||||
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
||||||
return createReply(returns);
|
return createReply(returns);
|
||||||
}
|
}
|
||||||
@ -333,15 +363,21 @@ JsonReply *UsersHandler::RemoveToken(const QVariantMap ¶ms, const JsonContex
|
|||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
|
|
||||||
QByteArray currentToken = context.token();
|
QByteArray currentToken = context.token();
|
||||||
if (currentToken.isEmpty()) {
|
if (context.authenticationEnabled()) {
|
||||||
qCWarning(dcJsonRpc()) << "Cannot remove a token from an unauthenticated connection.";
|
if (currentToken.isEmpty()) {
|
||||||
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
qCWarning(dcJsonRpc()) << "Cannot remove a token from an unauthenticated connection.";
|
||||||
return createReply(returns);
|
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
||||||
}
|
return createReply(returns);
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_userManager->verifyToken(currentToken)) {
|
if (!m_userManager->verifyToken(currentToken)) {
|
||||||
// Might happen if the client is connecting via an unauthenticated connection but tries to sneak in an invalid token
|
// Might happen if the client is connecting via an unauthenticated connection but tries to sneak in an invalid token
|
||||||
qCWarning(dcJsonRpc()) << "Invalid token. Is this an unauthenticated connection?";
|
qCWarning(dcJsonRpc()) << "Invalid token. Is this an unauthenticated connection?";
|
||||||
|
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
||||||
|
return createReply(returns);
|
||||||
|
}
|
||||||
|
} else if (currentToken.isEmpty()) {
|
||||||
|
qCWarning(dcJsonRpc()) << "Cannot remove a token without token even if authentication is disabled for the transport.";
|
||||||
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
||||||
return createReply(returns);
|
return createReply(returns);
|
||||||
}
|
}
|
||||||
@ -414,7 +450,20 @@ JsonReply *UsersHandler::SetUserInfo(const QVariantMap ¶ms, const JsonContex
|
|||||||
{
|
{
|
||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
|
|
||||||
TokenInfo callingTokenInfo = m_userManager->tokenInfo(context.token());
|
QByteArray currentToken = context.token();
|
||||||
|
if (context.authenticationEnabled()) {
|
||||||
|
if (currentToken.isEmpty()) {
|
||||||
|
qCWarning(dcJsonRpc()) << "Cannot set user info from an unauthenticated connection";
|
||||||
|
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
||||||
|
return createReply(returns);
|
||||||
|
}
|
||||||
|
} else if (currentToken.isEmpty()) {
|
||||||
|
qCWarning(dcJsonRpc()) << "Cannot set user info without token even if authentication is disabled for the transport";
|
||||||
|
returns.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
||||||
|
return createReply(returns);
|
||||||
|
}
|
||||||
|
|
||||||
|
TokenInfo callingTokenInfo = m_userManager->tokenInfo(currentToken);
|
||||||
QString username;
|
QString username;
|
||||||
|
|
||||||
if (params.contains("username")) {
|
if (params.contains("username")) {
|
||||||
|
|||||||
@ -24,18 +24,18 @@
|
|||||||
|
|
||||||
#include "logengineinfluxdb.h"
|
#include "logengineinfluxdb.h"
|
||||||
|
|
||||||
#include <QNetworkReply>
|
|
||||||
#include <QUrlQuery>
|
|
||||||
#include <QJsonDocument>
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QNetworkReply>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
#include <QUrlQuery>
|
||||||
|
|
||||||
LogEngineInfluxDB::LogEngineInfluxDB(const QString &host, const QString &dbName, const QString &username, const QString &password, QObject *parent)
|
LogEngineInfluxDB::LogEngineInfluxDB(const QString &host, const QString &dbName, const QString &username, const QString &password, QObject *parent)
|
||||||
: LogEngine{parent},
|
: LogEngine{parent}
|
||||||
m_host(host),
|
, m_host(host)
|
||||||
m_dbName(dbName),
|
, m_dbName(dbName)
|
||||||
m_username(username),
|
, m_username(username)
|
||||||
m_password(password)
|
, m_password(password)
|
||||||
{
|
{
|
||||||
m_nam = new QNetworkAccessManager(this);
|
m_nam = new QNetworkAccessManager(this);
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ LogEngineInfluxDB::~LogEngineInfluxDB()
|
|||||||
qCInfo(dcLogEngine()) << "Waiting for" << (m_initQueryQueue.count() + m_queryQueue.count() + m_writeQueue.count()) << "jobs to finish... Init status:" << m_initStatus;
|
qCInfo(dcLogEngine()) << "Waiting for" << (m_initQueryQueue.count() + m_queryQueue.count() + m_writeQueue.count()) << "jobs to finish... Init status:" << m_initStatus;
|
||||||
}
|
}
|
||||||
while (jobsRunning()) {
|
while (jobsRunning()) {
|
||||||
// qCDebug(dcLogEngine()) << "Waiting for logs to finish processing." << m_writeQueue.count() << "jobs pending...";
|
// qCDebug(dcLogEngine()) << "Waiting for logs to finish processing." << m_writeQueue.count() << "jobs pending...";
|
||||||
processQueues();
|
processQueues();
|
||||||
qApp->processEvents();
|
qApp->processEvents();
|
||||||
}
|
}
|
||||||
@ -66,12 +66,12 @@ Logger *LogEngineInfluxDB::registerLogSource(const QString &name, const QStringL
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// qCDebug(dcLogEngine()) << "Registering log source" << name << "with tags" << tagNames;
|
// qCDebug(dcLogEngine()) << "Registering log source" << name << "with tags" << tagNames;
|
||||||
|
|
||||||
Logger *logger = createLogger(name, tagNames, loggingType);
|
Logger *logger = createLogger(name, tagNames, loggingType);
|
||||||
m_loggers.insert(name, logger);
|
m_loggers.insert(name, logger);
|
||||||
|
|
||||||
if (loggingType == Types::LoggingTypeSampled) {
|
if (m_initStatus != InitStatusDisabled && loggingType == Types::LoggingTypeSampled) {
|
||||||
qCDebug(dcLogEngine()) << "Setting up log sampling on" << sampleColumn;
|
qCDebug(dcLogEngine()) << "Setting up log sampling on" << sampleColumn;
|
||||||
|
|
||||||
if (sampleColumn.isEmpty()) {
|
if (sampleColumn.isEmpty()) {
|
||||||
@ -84,55 +84,45 @@ Logger *LogEngineInfluxDB::registerLogSource(const QString &name, const QStringL
|
|||||||
columns.append(QString("MEAN(\"%1\") AS %1").arg(sampleColumn));
|
columns.append(QString("MEAN(\"%1\") AS %1").arg(sampleColumn));
|
||||||
QString target = columns.join(", ");
|
QString target = columns.join(", ");
|
||||||
|
|
||||||
QueryJob *minutesJob = query(QString("CREATE CONTINUOUS QUERY \"minutes-%1\" "
|
QueryJob *minutesJob = query(
|
||||||
"ON \"nymea\" "
|
QString(
|
||||||
"BEGIN "
|
"CREATE CONTINUOUS QUERY \"minutes-%1\" " "ON \"nymea\" " "BEGIN " "SELECT %2 " "INTO minutes.\"%1\" " "FROM live.\"%1\" " "GROUP BY time(1m) " "fill(previous)" " " "END")
|
||||||
"SELECT %2 "
|
.arg(name)
|
||||||
"INTO minutes.\"%1\" "
|
.arg(target),
|
||||||
"FROM live.\"%1\" "
|
true);
|
||||||
"GROUP BY time(1m) "
|
connect(minutesJob, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status, const QVariantList &response) {
|
||||||
"fill(previous) "
|
|
||||||
"END").arg(name).arg(target), true);
|
|
||||||
connect(minutesJob, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status, const QVariantList &response){
|
|
||||||
if (status == QNetworkReply::NoError) {
|
if (status == QNetworkReply::NoError) {
|
||||||
qCDebug(dcLogEngine()) << "Created minute based continuous query for" << name << qUtf8Printable(QJsonDocument::fromVariant(response).toJson());
|
qCDebug(dcLogEngine()) << "Created minute based continuous query for" << name << qUtf8Printable(QJsonDocument::fromVariant(response).toJson());
|
||||||
} else {
|
} else {
|
||||||
qCWarning(dcLogEngine()) << "Unable to create minute based continuous query for" << name << qUtf8Printable(QJsonDocument::fromVariant(response).toJson());
|
qCWarning(dcLogEngine()) << "Unable to create minute based continuous query for" << name << qUtf8Printable(QJsonDocument::fromVariant(response).toJson());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
QueryJob *hoursJob = query(QString("CREATE CONTINUOUS QUERY \"hours-%1\" "
|
QueryJob *hoursJob = query(
|
||||||
"ON \"nymea\" "
|
QString(
|
||||||
"BEGIN "
|
"CREATE CONTINUOUS QUERY \"hours-%1\" " "ON \"nymea\" " "BEGIN " "SELECT %2 " "INTO hours.\"%1\" " "FROM minutes.\"%1\" " "GROUP BY time(1h) " "fill(previous) " "END")
|
||||||
"SELECT %2 "
|
.arg(name)
|
||||||
"INTO hours.\"%1\" "
|
.arg(target),
|
||||||
"FROM minutes.\"%1\" "
|
true);
|
||||||
"GROUP BY time(1h) "
|
connect(hoursJob, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status, const QVariantList &response) {
|
||||||
"fill(previous) "
|
|
||||||
"END").arg(name).arg(target), true);
|
|
||||||
connect(hoursJob, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status, const QVariantList &response){
|
|
||||||
if (status == QNetworkReply::NoError) {
|
if (status == QNetworkReply::NoError) {
|
||||||
qCDebug(dcLogEngine()) << "Created hour based continuous query for" << name << qUtf8Printable(QJsonDocument::fromVariant(response).toJson());
|
qCDebug(dcLogEngine()) << "Created hour based continuous query for" << name << qUtf8Printable(QJsonDocument::fromVariant(response).toJson());
|
||||||
} else {
|
} else {
|
||||||
qCWarning(dcLogEngine()) << "Unable to create hour based continuous query for" << name << qUtf8Printable(QJsonDocument::fromVariant(response).toJson());
|
qCWarning(dcLogEngine()) << "Unable to create hour based continuous query for" << name << qUtf8Printable(QJsonDocument::fromVariant(response).toJson());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
QueryJob *daysJob = query(QString("CREATE CONTINUOUS QUERY \"days-%1\" "
|
QueryJob *daysJob = query(
|
||||||
"ON \"nymea\" "
|
QString(
|
||||||
"BEGIN "
|
"CREATE CONTINUOUS QUERY \"days-%1\" " "ON \"nymea\" " "BEGIN " "SELECT %2 " "INTO days.\"%1\" " "FROM hours.\"%1\" " "GROUP BY time(24h) " "fill(previous) " "END")
|
||||||
"SELECT %2 "
|
.arg(name)
|
||||||
"INTO days.\"%1\" "
|
.arg(target),
|
||||||
"FROM hours.\"%1\" "
|
true);
|
||||||
"GROUP BY time(24h) "
|
connect(daysJob, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status, const QVariantList &response) {
|
||||||
"fill(previous) "
|
|
||||||
"END").arg(name).arg(target), true);
|
|
||||||
connect(daysJob, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status, const QVariantList &response){
|
|
||||||
if (status == QNetworkReply::NoError) {
|
if (status == QNetworkReply::NoError) {
|
||||||
qCDebug(dcLogEngine()) << "Created day based continuous query for" << name << qUtf8Printable(QJsonDocument::fromVariant(response).toJson());
|
qCDebug(dcLogEngine()) << "Created day based continuous query for" << name << qUtf8Printable(QJsonDocument::fromVariant(response).toJson());
|
||||||
} else {
|
} else {
|
||||||
qCWarning(dcLogEngine()) << "Unable to create days based continuous query for" << name << qUtf8Printable(QJsonDocument::fromVariant(response).toJson());
|
qCWarning(dcLogEngine()) << "Unable to create days based continuous query for" << name << qUtf8Printable(QJsonDocument::fromVariant(response).toJson());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,12 +137,15 @@ void LogEngineInfluxDB::unregisterLogSource(const QString &name)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_initStatus == InitStatusDisabled)
|
||||||
|
return;
|
||||||
|
|
||||||
QString queryString = QString("DROP MEASUREMENT \"%1\"").arg(name);
|
QString queryString = QString("DROP MEASUREMENT \"%1\"").arg(name);
|
||||||
if (m_initStatus == InitStatusOK)
|
if (m_initStatus == InitStatusOK)
|
||||||
qCDebug(dcLogEngine()) << "Removing log entries:" << queryString;
|
qCDebug(dcLogEngine()) << "Removing log entries:" << queryString;
|
||||||
|
|
||||||
QueryJob *job = query(queryString);
|
QueryJob *job = query(queryString);
|
||||||
connect(job, &QueryJob::finished, this, [name](bool success){
|
connect(job, &QueryJob::finished, this, [name](bool success) {
|
||||||
if (success) {
|
if (success) {
|
||||||
qCDebug(dcLogEngine()) << "Removed log entries for source" << name;
|
qCDebug(dcLogEngine()) << "Removed log entries for source" << name;
|
||||||
} else {
|
} else {
|
||||||
@ -163,6 +156,9 @@ void LogEngineInfluxDB::unregisterLogSource(const QString &name)
|
|||||||
|
|
||||||
void LogEngineInfluxDB::logEvent(Logger *logger, const QStringList &tags, const QVariantMap &values)
|
void LogEngineInfluxDB::logEvent(Logger *logger, const QStringList &tags, const QVariantMap &values)
|
||||||
{
|
{
|
||||||
|
if (m_initStatus == InitStatusDisabled)
|
||||||
|
return;
|
||||||
|
|
||||||
QString measurement = logger->name();
|
QString measurement = logger->name();
|
||||||
QStringList tagsList;
|
QStringList tagsList;
|
||||||
QStringList fieldsList;
|
QStringList fieldsList;
|
||||||
@ -233,7 +229,7 @@ void LogEngineInfluxDB::processQueues()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// qCDebug(dcLogEngine()) << "Processing queue:" << m_initStatus << "init count:" << m_initQueryQueue.count() << "query count:" << m_queryQueue.count() << "write count:" << m_writeQueue.count();
|
// qCDebug(dcLogEngine()) << "Processing queue:" << m_initStatus << "init count:" << m_initQueryQueue.count() << "query count:" << m_queryQueue.count() << "write count:" << m_writeQueue.count();
|
||||||
|
|
||||||
if (!m_currentInitQuery && !m_initQueryQueue.isEmpty()) {
|
if (!m_currentInitQuery && !m_initQueryQueue.isEmpty()) {
|
||||||
QueryJob *job = m_initQueryQueue.takeFirst();
|
QueryJob *job = m_initQueryQueue.takeFirst();
|
||||||
@ -248,10 +244,14 @@ void LogEngineInfluxDB::processQueues()
|
|||||||
|
|
||||||
m_currentInitQuery = job;
|
m_currentInitQuery = job;
|
||||||
|
|
||||||
connect(reply, &QNetworkReply::finished, job, [=](){
|
connect(reply, &QNetworkReply::finished, job, [=]() {
|
||||||
m_currentInitQuery = nullptr;
|
m_currentInitQuery = nullptr;
|
||||||
qCDebug(dcLogEngine()) << "Init query job finished";
|
qCDebug(dcLogEngine()) << "Init query job finished";
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
if (m_initStatus == InitStatusDisabled) {
|
||||||
|
job->finish(reply->error());
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (reply->error() == QNetworkReply::ProtocolInvalidOperationError) {
|
if (reply->error() == QNetworkReply::ProtocolInvalidOperationError) {
|
||||||
qCWarning(dcLogEngine()) << "Influx DB protocol error:" << reply->readAll();
|
qCWarning(dcLogEngine()) << "Influx DB protocol error:" << reply->readAll();
|
||||||
job->finish(reply->error());
|
job->finish(reply->error());
|
||||||
@ -259,6 +259,10 @@ void LogEngineInfluxDB::processQueues()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (reply->error() != QNetworkReply::NoError) {
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
|
if (m_initStatus == InitStatusDisabled) {
|
||||||
|
job->finish(reply->error());
|
||||||
|
return;
|
||||||
|
}
|
||||||
qCWarning(dcLogEngine()) << "Error in influxdb communication:" << reply->error() << reply->errorString() << "for query:" << job->m_request.url().toString();
|
qCWarning(dcLogEngine()) << "Error in influxdb communication:" << reply->error() << reply->errorString() << "for query:" << job->m_request.url().toString();
|
||||||
job->finish(reply->error());
|
job->finish(reply->error());
|
||||||
return;
|
return;
|
||||||
@ -276,7 +280,7 @@ void LogEngineInfluxDB::processQueues()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_initStatus != InitStatusOK ) {
|
if (m_initStatus != InitStatusOK) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,10 +298,15 @@ void LogEngineInfluxDB::processQueues()
|
|||||||
|
|
||||||
m_currentQuery = job;
|
m_currentQuery = job;
|
||||||
|
|
||||||
connect(reply, &QNetworkReply::finished, job, [=](){
|
connect(reply, &QNetworkReply::finished, job, [=]() {
|
||||||
qCDebug(dcLogEngine()) << "Query finished";
|
qCDebug(dcLogEngine()) << "Query finished";
|
||||||
m_currentQuery = nullptr;
|
m_currentQuery = nullptr;
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
if (m_initStatus == InitStatusDisabled) {
|
||||||
|
job->finish(reply->error());
|
||||||
|
processQueues();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (reply->error() == QNetworkReply::ProtocolInvalidOperationError) {
|
if (reply->error() == QNetworkReply::ProtocolInvalidOperationError) {
|
||||||
qCWarning(dcLogEngine()) << "Influx DB protocol error:" << reply->readAll();
|
qCWarning(dcLogEngine()) << "Influx DB protocol error:" << reply->readAll();
|
||||||
job->finish(reply->error());
|
job->finish(reply->error());
|
||||||
@ -306,6 +315,11 @@ void LogEngineInfluxDB::processQueues()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (reply->error() != QNetworkReply::NoError) {
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
|
if (m_initStatus == InitStatusDisabled) {
|
||||||
|
job->finish(reply->error());
|
||||||
|
processQueues();
|
||||||
|
return;
|
||||||
|
}
|
||||||
qCWarning(dcLogEngine()) << "Error in influxdb communication:" << reply->error() << reply->errorString();
|
qCWarning(dcLogEngine()) << "Error in influxdb communication:" << reply->error() << reply->errorString();
|
||||||
job->finish(reply->error());
|
job->finish(reply->error());
|
||||||
processQueues();
|
processQueues();
|
||||||
@ -320,7 +334,7 @@ void LogEngineInfluxDB::processQueues()
|
|||||||
processQueues();
|
processQueues();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// qCDebug(dcLogEngine()) << "Reply" << qUtf8Printable(jsonDoc.toJson(QJsonDocument::Indented));
|
// qCDebug(dcLogEngine()) << "Reply" << qUtf8Printable(jsonDoc.toJson(QJsonDocument::Indented));
|
||||||
|
|
||||||
job->finish(QNetworkReply::NoError, jsonDoc.toVariant().toMap().value("results").toList());
|
job->finish(QNetworkReply::NoError, jsonDoc.toVariant().toMap().value("results").toList());
|
||||||
|
|
||||||
@ -341,11 +355,19 @@ void LogEngineInfluxDB::processQueues()
|
|||||||
qCDebug(dcLogEngine()) << "Started:" << reply->isRunning() << reply->isFinished();
|
qCDebug(dcLogEngine()) << "Started:" << reply->isRunning() << reply->isFinished();
|
||||||
m_currentWriteReply = reply;
|
m_currentWriteReply = reply;
|
||||||
|
|
||||||
connect(reply, &QNetworkReply::finished, this, [=](){
|
connect(reply, &QNetworkReply::finished, this, [=]() {
|
||||||
m_currentWriteReply = nullptr;
|
m_currentWriteReply = nullptr;
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
|
||||||
|
if (m_initStatus == InitStatusDisabled) {
|
||||||
|
processQueues();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (reply->error() != QNetworkReply::NoError) {
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
|
if (m_initStatus == InitStatusDisabled) {
|
||||||
|
processQueues();
|
||||||
|
return;
|
||||||
|
}
|
||||||
qCWarning(dcLogEngine()) << "Unable to connect to influxdb. Cannot log events." << reply->error() << reply->readAll();
|
qCWarning(dcLogEngine()) << "Unable to connect to influxdb. Cannot log events." << reply->error() << reply->readAll();
|
||||||
processQueues();
|
processQueues();
|
||||||
return;
|
return;
|
||||||
@ -362,10 +384,23 @@ void LogEngineInfluxDB::processQueues()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LogFetchJob *LogEngineInfluxDB::fetchLogEntries(const QStringList &sources, const QStringList &columns, const QDateTime &startTime, const QDateTime &endTime, const QVariantMap &filter, Types::SampleRate sampleRate, Qt::SortOrder sortOrder, int offset, int limit)
|
LogFetchJob *LogEngineInfluxDB::fetchLogEntries(const QStringList &sources,
|
||||||
|
const QStringList &columns,
|
||||||
|
const QDateTime &startTime,
|
||||||
|
const QDateTime &endTime,
|
||||||
|
const QVariantMap &filter,
|
||||||
|
Types::SampleRate sampleRate,
|
||||||
|
Qt::SortOrder sortOrder,
|
||||||
|
int offset,
|
||||||
|
int limit)
|
||||||
{
|
{
|
||||||
LogFetchJob *job = new LogFetchJob(this);
|
LogFetchJob *job = new LogFetchJob(this);
|
||||||
|
|
||||||
|
if (m_initStatus == InitStatusDisabled) {
|
||||||
|
finishFetchJob(job, LogEntries());
|
||||||
|
return job;
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: injection attacks possible?
|
// FIXME: injection attacks possible?
|
||||||
QString what = "*";
|
QString what = "*";
|
||||||
if (sampleRate == Types::SampleRateAny) {
|
if (sampleRate == Types::SampleRateAny) {
|
||||||
@ -386,7 +421,6 @@ LogFetchJob *LogEngineInfluxDB::fetchLogEntries(const QStringList &sources, cons
|
|||||||
|
|
||||||
QStringList escapedSourced;
|
QStringList escapedSourced;
|
||||||
foreach (const QString &source, sources) {
|
foreach (const QString &source, sources) {
|
||||||
|
|
||||||
QString retentionPolicy;
|
QString retentionPolicy;
|
||||||
switch (sampleRate) {
|
switch (sampleRate) {
|
||||||
case Types::SampleRate1Min:
|
case Types::SampleRate1Min:
|
||||||
@ -456,9 +490,17 @@ LogFetchJob *LogEngineInfluxDB::fetchLogEntries(const QStringList &sources, cons
|
|||||||
QNetworkRequest request = createQueryRequest(query);
|
QNetworkRequest request = createQueryRequest(query);
|
||||||
qCDebug(dcLogEngine()) << "Request:" << request.url() << filter;
|
qCDebug(dcLogEngine()) << "Request:" << request.url() << filter;
|
||||||
QNetworkReply *reply = m_nam->get(request);
|
QNetworkReply *reply = m_nam->get(request);
|
||||||
connect(reply, &QNetworkReply::finished, this, [=](){
|
connect(reply, &QNetworkReply::finished, this, [=]() {
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
if (m_initStatus == InitStatusDisabled) {
|
||||||
|
finishFetchJob(job, QList<LogEntry>());
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (reply->error() != QNetworkReply::NoError) {
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
|
if (m_initStatus == InitStatusDisabled) {
|
||||||
|
finishFetchJob(job, QList<LogEntry>());
|
||||||
|
return;
|
||||||
|
}
|
||||||
qCWarning(dcLogEngine()) << "Unable to obtain entries from influxdb" << reply->error() << reply->readAll();
|
qCWarning(dcLogEngine()) << "Unable to obtain entries from influxdb" << reply->error() << reply->readAll();
|
||||||
finishFetchJob(job, QList<LogEntry>());
|
finishFetchJob(job, QList<LogEntry>());
|
||||||
return;
|
return;
|
||||||
@ -507,20 +549,18 @@ LogFetchJob *LogEngineInfluxDB::fetchLogEntries(const QStringList &sources, cons
|
|||||||
|
|
||||||
bool LogEngineInfluxDB::jobsRunning() const
|
bool LogEngineInfluxDB::jobsRunning() const
|
||||||
{
|
{
|
||||||
// qCDebug(dcLogEngine()) << "Jobs running:" << m_initStatus << m_writeQueue.count() << m_initQueryQueue.count() << m_queryQueue.count() << m_currentWriteReply;
|
// qCDebug(dcLogEngine()) << "Jobs running:" << m_initStatus << m_writeQueue.count() << m_initQueryQueue.count() << m_queryQueue.count() << m_currentWriteReply;
|
||||||
return m_currentInitQuery
|
return m_currentInitQuery || !m_initQueryQueue.isEmpty() || m_currentQuery || !m_queryQueue.isEmpty() || m_currentWriteReply || !m_writeQueue.isEmpty();
|
||||||
|| !m_initQueryQueue.isEmpty()
|
|
||||||
|| m_currentQuery
|
|
||||||
|| !m_queryQueue.isEmpty()
|
|
||||||
|| m_currentWriteReply
|
|
||||||
|| !m_writeQueue.isEmpty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogEngineInfluxDB::clear(const QString &source)
|
void LogEngineInfluxDB::clear(const QString &source)
|
||||||
{
|
{
|
||||||
|
if (m_initStatus == InitStatusDisabled)
|
||||||
|
return;
|
||||||
|
|
||||||
qCDebug(dcLogEngine()) << "Clearing entries for source:" << source;
|
qCDebug(dcLogEngine()) << "Clearing entries for source:" << source;
|
||||||
QueryJob *job = query(QString("DROP MEASUREMENT \"%1\"").arg(source));
|
QueryJob *job = query(QString("DROP MEASUREMENT \"%1\"").arg(source));
|
||||||
connect(job, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status, const QVariantList &results){
|
connect(job, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status, const QVariantList &results) {
|
||||||
if (status != QNetworkReply::NoError) {
|
if (status != QNetworkReply::NoError) {
|
||||||
qCWarning(dcLogEngine()) << "Unable to clear log entries for" << source << ":" << qUtf8Printable(QJsonDocument::fromVariant(results).toJson());
|
qCWarning(dcLogEngine()) << "Unable to clear log entries for" << source << ":" << qUtf8Printable(QJsonDocument::fromVariant(results).toJson());
|
||||||
}
|
}
|
||||||
@ -552,8 +592,14 @@ void LogEngineInfluxDB::initDB()
|
|||||||
|
|
||||||
void LogEngineInfluxDB::createDB()
|
void LogEngineInfluxDB::createDB()
|
||||||
{
|
{
|
||||||
|
if (m_initStatus == InitStatusDisabled)
|
||||||
|
return;
|
||||||
|
|
||||||
QueryJob *job = query("SHOW DATABASES", false, true);
|
QueryJob *job = query("SHOW DATABASES", false, true);
|
||||||
connect(job, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status, const QVariantList &results){
|
connect(job, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status, const QVariantList &results) {
|
||||||
|
if (m_initStatus == InitStatusDisabled)
|
||||||
|
return;
|
||||||
|
|
||||||
if (status != QNetworkReply::NoError) {
|
if (status != QNetworkReply::NoError) {
|
||||||
if (status == QNetworkReply::ConnectionRefusedError) {
|
if (status == QNetworkReply::ConnectionRefusedError) {
|
||||||
// Influx not up yet? trying again in 5 secs...
|
// Influx not up yet? trying again in 5 secs...
|
||||||
@ -563,6 +609,10 @@ void LogEngineInfluxDB::createDB()
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_initStatus == InitStatusDisabled)
|
||||||
|
return;
|
||||||
|
|
||||||
qCCritical(dcLogEngine()) << "Unable to connect to InfluxDB";
|
qCCritical(dcLogEngine()) << "Unable to connect to InfluxDB";
|
||||||
m_initStatus = InitStatusFailure;
|
m_initStatus = InitStatusFailure;
|
||||||
return;
|
return;
|
||||||
@ -604,6 +654,9 @@ void LogEngineInfluxDB::createDB()
|
|||||||
|
|
||||||
QueryJob *job = query(QString("CREATE DATABASE %1").arg(m_dbName), true, true);
|
QueryJob *job = query(QString("CREATE DATABASE %1").arg(m_dbName), true, true);
|
||||||
connect(job, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status, const QVariantList &result) {
|
connect(job, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status, const QVariantList &result) {
|
||||||
|
if (m_initStatus == InitStatusDisabled)
|
||||||
|
return;
|
||||||
|
|
||||||
if (status != QNetworkReply::NoError) {
|
if (status != QNetworkReply::NoError) {
|
||||||
qCCritical(dcLogEngine()) << "Unable to create" << m_dbName << "database in influxdb:" << QJsonDocument::fromVariant(result).toJson();
|
qCCritical(dcLogEngine()) << "Unable to create" << m_dbName << "database in influxdb:" << QJsonDocument::fromVariant(result).toJson();
|
||||||
m_initStatus = InitStatusFailure;
|
m_initStatus = InitStatusFailure;
|
||||||
@ -617,8 +670,14 @@ void LogEngineInfluxDB::createDB()
|
|||||||
|
|
||||||
void LogEngineInfluxDB::createRetentionPolicies()
|
void LogEngineInfluxDB::createRetentionPolicies()
|
||||||
{
|
{
|
||||||
|
if (m_initStatus == InitStatusDisabled)
|
||||||
|
return;
|
||||||
|
|
||||||
QueryJob *job = query("SHOW RETENTION POLICIES", false, true);
|
QueryJob *job = query("SHOW RETENTION POLICIES", false, true);
|
||||||
connect(job, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status, const QVariantList &results){
|
connect(job, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status, const QVariantList &results) {
|
||||||
|
if (m_initStatus == InitStatusDisabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (status != QNetworkReply::NoError) {
|
if (status != QNetworkReply::NoError) {
|
||||||
qCCritical(dcLogEngine()) << "Unable to query retention policies.";
|
qCCritical(dcLogEngine()) << "Unable to query retention policies.";
|
||||||
m_initStatus = InitStatusFailure;
|
m_initStatus = InitStatusFailure;
|
||||||
@ -679,7 +738,10 @@ void LogEngineInfluxDB::createRetentionPolicies()
|
|||||||
if (!discreteRPFound) {
|
if (!discreteRPFound) {
|
||||||
qCInfo(dcLogEngine()) << "Creating discrete nymea retention policy in influxdb";
|
qCInfo(dcLogEngine()) << "Creating discrete nymea retention policy in influxdb";
|
||||||
QueryJob *job = query(QString("CREATE RETENTION POLICY discrete ON %1 DURATION 8760h REPLICATION 1").arg(m_dbName), true, true);
|
QueryJob *job = query(QString("CREATE RETENTION POLICY discrete ON %1 DURATION 8760h REPLICATION 1").arg(m_dbName), true, true);
|
||||||
connect(job, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status){
|
connect(job, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status) {
|
||||||
|
if (m_initStatus == InitStatusDisabled)
|
||||||
|
return;
|
||||||
|
|
||||||
if (status != QNetworkReply::NoError) {
|
if (status != QNetworkReply::NoError) {
|
||||||
qCWarning(dcLogEngine()) << "Unable to create discrete retention policy in influxdb.";
|
qCWarning(dcLogEngine()) << "Unable to create discrete retention policy in influxdb.";
|
||||||
m_initStatus = InitStatusFailure;
|
m_initStatus = InitStatusFailure;
|
||||||
@ -693,7 +755,10 @@ void LogEngineInfluxDB::createRetentionPolicies()
|
|||||||
if (!liveRPFound) {
|
if (!liveRPFound) {
|
||||||
qCInfo(dcLogEngine()) << "Creating live nymea retention policy in influxdb";
|
qCInfo(dcLogEngine()) << "Creating live nymea retention policy in influxdb";
|
||||||
QueryJob *job = query(QString("CREATE RETENTION POLICY live ON %1 DURATION 24h REPLICATION 1").arg(m_dbName), true, true);
|
QueryJob *job = query(QString("CREATE RETENTION POLICY live ON %1 DURATION 24h REPLICATION 1").arg(m_dbName), true, true);
|
||||||
connect(job, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status){
|
connect(job, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status) {
|
||||||
|
if (m_initStatus == InitStatusDisabled)
|
||||||
|
return;
|
||||||
|
|
||||||
if (status != QNetworkReply::NoError) {
|
if (status != QNetworkReply::NoError) {
|
||||||
qCWarning(dcLogEngine()) << "Unable to create live retention policy in influxdb.";
|
qCWarning(dcLogEngine()) << "Unable to create live retention policy in influxdb.";
|
||||||
m_initStatus = InitStatusFailure;
|
m_initStatus = InitStatusFailure;
|
||||||
@ -707,7 +772,10 @@ void LogEngineInfluxDB::createRetentionPolicies()
|
|||||||
if (!minutesRPFound) {
|
if (!minutesRPFound) {
|
||||||
qCInfo(dcLogEngine()) << "Creating minutes nymea retention policy in influxdb";
|
qCInfo(dcLogEngine()) << "Creating minutes nymea retention policy in influxdb";
|
||||||
QueryJob *job = query(QString("CREATE RETENTION POLICY minutes ON %1 DURATION 168h REPLICATION 1").arg(m_dbName), true, true);
|
QueryJob *job = query(QString("CREATE RETENTION POLICY minutes ON %1 DURATION 168h REPLICATION 1").arg(m_dbName), true, true);
|
||||||
connect(job, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status){
|
connect(job, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status) {
|
||||||
|
if (m_initStatus == InitStatusDisabled)
|
||||||
|
return;
|
||||||
|
|
||||||
if (status != QNetworkReply::NoError) {
|
if (status != QNetworkReply::NoError) {
|
||||||
qCWarning(dcLogEngine()) << "Unable to create minutes retention policy in influxdb.";
|
qCWarning(dcLogEngine()) << "Unable to create minutes retention policy in influxdb.";
|
||||||
m_initStatus = InitStatusFailure;
|
m_initStatus = InitStatusFailure;
|
||||||
@ -721,7 +789,10 @@ void LogEngineInfluxDB::createRetentionPolicies()
|
|||||||
if (!hoursRPFound) {
|
if (!hoursRPFound) {
|
||||||
qCInfo(dcLogEngine()) << "Creating hours nymea retention policy in influxdb";
|
qCInfo(dcLogEngine()) << "Creating hours nymea retention policy in influxdb";
|
||||||
QueryJob *job = query(QString("CREATE RETENTION POLICY hours ON %1 DURATION 26280h REPLICATION 1").arg(m_dbName), true, true);
|
QueryJob *job = query(QString("CREATE RETENTION POLICY hours ON %1 DURATION 26280h REPLICATION 1").arg(m_dbName), true, true);
|
||||||
connect(job, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status){
|
connect(job, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status) {
|
||||||
|
if (m_initStatus == InitStatusDisabled)
|
||||||
|
return;
|
||||||
|
|
||||||
if (status != QNetworkReply::NoError) {
|
if (status != QNetworkReply::NoError) {
|
||||||
qCWarning(dcLogEngine()) << "Unable to create hours retention policy in influxdb.";
|
qCWarning(dcLogEngine()) << "Unable to create hours retention policy in influxdb.";
|
||||||
m_initStatus = InitStatusFailure;
|
m_initStatus = InitStatusFailure;
|
||||||
@ -735,7 +806,10 @@ void LogEngineInfluxDB::createRetentionPolicies()
|
|||||||
if (!daysRPFound) {
|
if (!daysRPFound) {
|
||||||
qCInfo(dcLogEngine()) << "Creating days nymea retention policy in influxdb";
|
qCInfo(dcLogEngine()) << "Creating days nymea retention policy in influxdb";
|
||||||
QueryJob *job = query(QString("CREATE RETENTION POLICY days ON %1 DURATION 175200h REPLICATION 1").arg(m_dbName), true, true);
|
QueryJob *job = query(QString("CREATE RETENTION POLICY days ON %1 DURATION 175200h REPLICATION 1").arg(m_dbName), true, true);
|
||||||
connect(job, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status){
|
connect(job, &QueryJob::finished, this, [=](QNetworkReply::NetworkError status) {
|
||||||
|
if (m_initStatus == InitStatusDisabled)
|
||||||
|
return;
|
||||||
|
|
||||||
if (status != QNetworkReply::NoError) {
|
if (status != QNetworkReply::NoError) {
|
||||||
qCWarning(dcLogEngine()) << "Unable to create days retention policy in influxdb.";
|
qCWarning(dcLogEngine()) << "Unable to create days retention policy in influxdb.";
|
||||||
m_initStatus = InitStatusFailure;
|
m_initStatus = InitStatusFailure;
|
||||||
@ -748,7 +822,8 @@ void LogEngineInfluxDB::createRetentionPolicies()
|
|||||||
|
|
||||||
m_initStatus = InitStatusOK;
|
m_initStatus = InitStatusOK;
|
||||||
|
|
||||||
qCDebug(dcLogEngine()) << "Influx initialized. Starting to process log entries (" << m_initQueryQueue.count() << m_queryQueue.count() << m_writeQueue.count() << "in queue)";
|
qCDebug(dcLogEngine()) << "Influx initialized. Starting to process log entries (" << m_initQueryQueue.count() << m_queryQueue.count() << m_writeQueue.count()
|
||||||
|
<< "in queue)";
|
||||||
processQueues();
|
processQueues();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -819,18 +894,15 @@ QueryJob *LogEngineInfluxDB::query(const QString &query, bool post, bool isInit)
|
|||||||
return job;
|
return job;
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryJob::QueryJob(const QNetworkRequest &request, bool post, bool isInit, QObject *parent):
|
QueryJob::QueryJob(const QNetworkRequest &request, bool post, bool isInit, QObject *parent)
|
||||||
QObject(parent),
|
: QObject(parent)
|
||||||
m_request(request),
|
, m_request(request)
|
||||||
m_post(post),
|
, m_post(post)
|
||||||
m_isInit(isInit)
|
, m_isInit(isInit)
|
||||||
{
|
{}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void QueryJob::finish(QNetworkReply::NetworkError status, const QVariantList &results)
|
void QueryJob::finish(QNetworkReply::NetworkError status, const QVariantList &results)
|
||||||
{
|
{
|
||||||
QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection, Q_ARG(QNetworkReply::NetworkError, status), Q_ARG(QVariantList, results));
|
QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection, Q_ARG(QNetworkReply::NetworkError, status), Q_ARG(QVariantList, results));
|
||||||
QMetaObject::invokeMethod(this, "deleteLater", Qt::QueuedConnection);
|
QMetaObject::invokeMethod(this, "deleteLater", Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -534,7 +534,7 @@ QList<TokenInfo> UserManager::tokens(const QString &username) const
|
|||||||
TokenInfo UserManager::tokenInfo(const QByteArray &token) const
|
TokenInfo UserManager::tokenInfo(const QByteArray &token) const
|
||||||
{
|
{
|
||||||
if (!validateToken(token)) {
|
if (!validateToken(token)) {
|
||||||
qCWarning(dcUserManager) << "Token did not pass validation:" << token;
|
qCWarning(dcUserManager()) << "Token did not pass validation:" << token;
|
||||||
return TokenInfo();
|
return TokenInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013 - 2024, nymea GmbH
|
* Copyright (C) 2013 - 2024, nymea GmbH
|
||||||
* Copyright (C) 2024 - 2025, chargebyte austria GmbH
|
* Copyright (C) 2024 - 2026, chargebyte austria GmbH
|
||||||
*
|
*
|
||||||
* This file is part of nymea.
|
* This file is part of nymea.
|
||||||
*
|
*
|
||||||
@ -25,10 +25,11 @@
|
|||||||
#ifndef BROWSERESULT_H
|
#ifndef BROWSERESULT_H
|
||||||
#define BROWSERESULT_H
|
#define BROWSERESULT_H
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
#include "thing.h"
|
#include "thing.h"
|
||||||
|
#include "types/browseritem.h"
|
||||||
|
|
||||||
class ThingManager;
|
class ThingManager;
|
||||||
|
|
||||||
@ -38,7 +39,7 @@ class BrowseResult : public QObject
|
|||||||
public:
|
public:
|
||||||
explicit BrowseResult(Thing *thing, ThingManager *thingManager, const QString &itemId, const QLocale &locale, QObject *parent, quint32 timeout = 0);
|
explicit BrowseResult(Thing *thing, ThingManager *thingManager, const QString &itemId, const QLocale &locale, QObject *parent, quint32 timeout = 0);
|
||||||
|
|
||||||
Thing* thing() const;
|
Thing *thing() const;
|
||||||
QString itemId() const;
|
QString itemId() const;
|
||||||
QLocale locale() const;
|
QLocale locale() const;
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013 - 2024, nymea GmbH
|
* Copyright (C) 2013 - 2024, nymea GmbH
|
||||||
* Copyright (C) 2024 - 2025, chargebyte austria GmbH
|
* Copyright (C) 2024 - 2026, chargebyte austria GmbH
|
||||||
*
|
*
|
||||||
* This file is part of nymea.
|
* This file is part of nymea.
|
||||||
*
|
*
|
||||||
@ -25,10 +25,11 @@
|
|||||||
#ifndef BROWSERITEMRESULT_H
|
#ifndef BROWSERITEMRESULT_H
|
||||||
#define BROWSERITEMRESULT_H
|
#define BROWSERITEMRESULT_H
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
#include "thing.h"
|
#include "thing.h"
|
||||||
|
#include "types/browseritem.h"
|
||||||
|
|
||||||
class ThingManager;
|
class ThingManager;
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ class BrowserItemResult : public QObject
|
|||||||
public:
|
public:
|
||||||
explicit BrowserItemResult(Thing *thing, ThingManager *thingManager, const QString &itemId, const QLocale &locale, QObject *parent, quint32 timeout = 0);
|
explicit BrowserItemResult(Thing *thing, ThingManager *thingManager, const QString &itemId, const QLocale &locale, QObject *parent, quint32 timeout = 0);
|
||||||
|
|
||||||
Thing* thing() const;
|
Thing *thing() const;
|
||||||
QString itemId() const;
|
QString itemId() const;
|
||||||
QLocale locale() const;
|
QLocale locale() const;
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013 - 2024, nymea GmbH
|
* Copyright (C) 2013 - 2024, nymea GmbH
|
||||||
* Copyright (C) 2024 - 2025, chargebyte austria GmbH
|
* Copyright (C) 2024 - 2026, chargebyte austria GmbH
|
||||||
*
|
*
|
||||||
* This file is part of nymea.
|
* This file is part of nymea.
|
||||||
*
|
*
|
||||||
@ -313,7 +313,6 @@ States Thing::states() const
|
|||||||
return m_states;
|
return m_states;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Returns true, a \l{Param} with the given \a paramTypeId exists for this thing. */
|
/*! Returns true, a \l{Param} with the given \a paramTypeId exists for this thing. */
|
||||||
bool Thing::hasParam(const QString ¶mName) const
|
bool Thing::hasParam(const QString ¶mName) const
|
||||||
{
|
{
|
||||||
@ -321,7 +320,6 @@ bool Thing::hasParam(const QString ¶mName) const
|
|||||||
return m_params.hasParam(paramTypeId);
|
return m_params.hasParam(paramTypeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Returns true, a \l{Param} with the given \a paramTypeId exists for this thing. */
|
/*! Returns true, a \l{Param} with the given \a paramTypeId exists for this thing. */
|
||||||
bool Thing::hasParam(const ParamTypeId ¶mTypeId) const
|
bool Thing::hasParam(const ParamTypeId ¶mTypeId) const
|
||||||
{
|
{
|
||||||
@ -516,7 +514,7 @@ void Thing::setStateValue(const QString &stateName, const QVariant &value)
|
|||||||
setStateValue(stateTypeId, value);
|
setStateValue(stateTypeId, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Sets the minimum value for the \l{State} matching the given \a stateTypeId in this thing to value. */
|
/*! Sets the minimum value for the \l{State} matching the given \a stateTypeId in this thing to \a minValue. */
|
||||||
void Thing::setStateMinValue(const StateTypeId &stateTypeId, const QVariant &minValue)
|
void Thing::setStateMinValue(const StateTypeId &stateTypeId, const QVariant &minValue)
|
||||||
{
|
{
|
||||||
StateType stateType = m_thingClass.stateTypes().findById(stateTypeId);
|
StateType stateType = m_thingClass.stateTypes().findById(stateTypeId);
|
||||||
@ -559,14 +557,14 @@ void Thing::setStateMinValue(const StateTypeId &stateTypeId, const QVariant &min
|
|||||||
qCWarning(dcThing()).nospace() << this << ": Failed setting minimum state value " << stateType.name() << " to " << minValue;
|
qCWarning(dcThing()).nospace() << this << ": Failed setting minimum state value " << stateType.name() << " to " << minValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Sets the minimum value for the \l{State} matching the given \a stateName in this thing to value. */
|
/*! Sets the minimum value for the \l{State} matching the given \a stateName in this thing to \a minValue. */
|
||||||
void Thing::setStateMinValue(const QString &stateName, const QVariant &minValue)
|
void Thing::setStateMinValue(const QString &stateName, const QVariant &minValue)
|
||||||
{
|
{
|
||||||
StateTypeId stateTypeId = m_thingClass.stateTypes().findByName(stateName).id();
|
StateTypeId stateTypeId = m_thingClass.stateTypes().findByName(stateName).id();
|
||||||
setStateMinValue(stateTypeId, minValue);
|
setStateMinValue(stateTypeId, minValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Sets the maximum value for the \l{State} matching the given \a stateTypeId in this thing to value. */
|
/*! Sets the maximum value for the \l{State} matching the given \a stateTypeId in this thing to \a maxValue. */
|
||||||
void Thing::setStateMaxValue(const StateTypeId &stateTypeId, const QVariant &maxValue)
|
void Thing::setStateMaxValue(const StateTypeId &stateTypeId, const QVariant &maxValue)
|
||||||
{
|
{
|
||||||
StateType stateType = m_thingClass.stateTypes().findById(stateTypeId);
|
StateType stateType = m_thingClass.stateTypes().findById(stateTypeId);
|
||||||
@ -619,7 +617,7 @@ void Thing::setStateMaxValue(const StateTypeId &stateTypeId, const QVariant &max
|
|||||||
qCWarning(dcThing()).nospace() << this << ": Failed setting maximum state value " << stateType.name() << " to " << maxValue;
|
qCWarning(dcThing()).nospace() << this << ": Failed setting maximum state value " << stateType.name() << " to " << maxValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Sets the maximum value for the \l{State} matching the given \a stateName in this thing to value. */
|
/*! Sets the maximum value for the \l{State} matching the given \a stateName in this thing to \a maxValue. */
|
||||||
void Thing::setStateMaxValue(const QString &stateName, const QVariant &maxValue)
|
void Thing::setStateMaxValue(const QString &stateName, const QVariant &maxValue)
|
||||||
{
|
{
|
||||||
StateTypeId stateTypeId = m_thingClass.stateTypes().findByName(stateName).id();
|
StateTypeId stateTypeId = m_thingClass.stateTypes().findByName(stateName).id();
|
||||||
@ -697,6 +695,14 @@ void Thing::setStateMinMaxValues(const QString &stateName, const QVariant &minVa
|
|||||||
setStateMinMaxValues(stateTypeId, minValue, maxValue);
|
setStateMinMaxValues(stateTypeId, minValue, maxValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Sets the possible values for the \l{State} matching the given \a stateName in this thing to \a values. */
|
||||||
|
void Thing::setStatePossibleValues(const QString &stateName, const QVariantList &values)
|
||||||
|
{
|
||||||
|
const StateTypeId stateTypeId = m_thingClass.stateTypes().findByName(stateName).id();
|
||||||
|
setStatePossibleValues(stateTypeId, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Sets the possible values for the \l{State} matching the given \a stateTypeId in this thing to \a values. */
|
||||||
void Thing::setStatePossibleValues(const StateTypeId &stateTypeId, const QVariantList &values)
|
void Thing::setStatePossibleValues(const StateTypeId &stateTypeId, const QVariantList &values)
|
||||||
{
|
{
|
||||||
StateType stateType = m_thingClass.stateTypes().findById(stateTypeId);
|
StateType stateType = m_thingClass.stateTypes().findById(stateTypeId);
|
||||||
@ -704,6 +710,7 @@ void Thing::setStatePossibleValues(const StateTypeId &stateTypeId, const QVarian
|
|||||||
qCWarning(dcThing()) << "No such state type" << stateTypeId.toString() << "in" << m_name << "(" + thingClass().name() + ")";
|
qCWarning(dcThing()) << "No such state type" << stateTypeId.toString() << "in" << m_name << "(" + thingClass().name() + ")";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < m_states.count(); ++i) {
|
for (int i = 0; i < m_states.count(); ++i) {
|
||||||
if (m_states.at(i).stateTypeId() == stateTypeId) {
|
if (m_states.at(i).stateTypeId() == stateTypeId) {
|
||||||
if (values == m_states.at(i).possibleValues()) {
|
if (values == m_states.at(i).possibleValues()) {
|
||||||
@ -739,10 +746,10 @@ void Thing::setStatePossibleValues(const StateTypeId &stateTypeId, const QVarian
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qCWarning(dcThing()).nospace() << this << ": Failed setting maximum state value " << stateType.name() << " to " << values;
|
qCWarning(dcThing()).nospace() << this << ": Failed setting possible state values " << stateType.name() << " to " << values;
|
||||||
Q_ASSERT_X(false,
|
Q_ASSERT_X(false,
|
||||||
m_name.toUtf8(),
|
m_name.toUtf8(),
|
||||||
QString("Failed setting possible state values for %1 to %2").arg(stateType.name()).arg(QString(QJsonDocument::fromVariant(values).toJson())).toUtf8());
|
QString("Failed setting possible state values for %1 to %2").arg(stateType.name(), QString(QJsonDocument::fromVariant(values).toJson())).toUtf8());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Returns the \l{State} with the given \a stateTypeId of this thing. */
|
/*! Returns the \l{State} with the given \a stateTypeId of this thing. */
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013 - 2024, nymea GmbH
|
* Copyright (C) 2013 - 2024, nymea GmbH
|
||||||
* Copyright (C) 2024 - 2025, chargebyte austria GmbH
|
* Copyright (C) 2024 - 2026, chargebyte austria GmbH
|
||||||
*
|
*
|
||||||
* This file is part of nymea.
|
* This file is part of nymea.
|
||||||
*
|
*
|
||||||
@ -32,7 +32,6 @@
|
|||||||
#include "types/state.h"
|
#include "types/state.h"
|
||||||
#include "types/param.h"
|
#include "types/param.h"
|
||||||
#include "types/event.h"
|
#include "types/event.h"
|
||||||
#include "types/browseritem.h"
|
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
@ -145,6 +144,7 @@ public:
|
|||||||
Q_INVOKABLE void setStateMinMaxValues(const StateTypeId &stateTypeId, const QVariant &minValue, const QVariant &maxValue);
|
Q_INVOKABLE void setStateMinMaxValues(const StateTypeId &stateTypeId, const QVariant &minValue, const QVariant &maxValue);
|
||||||
Q_INVOKABLE void setStateMinMaxValues(const QString &stateName, const QVariant &minValue, const QVariant &maxValue);
|
Q_INVOKABLE void setStateMinMaxValues(const QString &stateName, const QVariant &minValue, const QVariant &maxValue);
|
||||||
Q_INVOKABLE void setStatePossibleValues(const StateTypeId &stateTypeId, const QVariantList &values);
|
Q_INVOKABLE void setStatePossibleValues(const StateTypeId &stateTypeId, const QVariantList &values);
|
||||||
|
Q_INVOKABLE void setStatePossibleValues(const QString &stateName, const QVariantList &values);
|
||||||
|
|
||||||
Q_INVOKABLE State state(const StateTypeId &stateTypeId) const;
|
Q_INVOKABLE State state(const StateTypeId &stateTypeId) const;
|
||||||
Q_INVOKABLE State state(const QString &stateName) const;
|
Q_INVOKABLE State state(const QString &stateName) const;
|
||||||
|
|||||||
@ -24,9 +24,10 @@
|
|||||||
|
|
||||||
#include "jsoncontext.h"
|
#include "jsoncontext.h"
|
||||||
|
|
||||||
JsonContext::JsonContext(const QUuid &clientId, const QLocale &locale):
|
JsonContext::JsonContext(const QUuid &clientId, const QLocale &locale, bool authenticationEnabled):
|
||||||
m_clientId(clientId),
|
m_clientId(clientId),
|
||||||
m_locale(locale)
|
m_locale(locale),
|
||||||
|
m_authenticationEnabled(authenticationEnabled)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -50,3 +51,13 @@ void JsonContext::setToken(const QByteArray &token)
|
|||||||
{
|
{
|
||||||
m_token = token;
|
m_token = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool JsonContext::authenticationEnabled() const
|
||||||
|
{
|
||||||
|
return m_authenticationEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonContext::setAuthenticationEnabled(bool authenticationEnabled)
|
||||||
|
{
|
||||||
|
m_authenticationEnabled = authenticationEnabled;
|
||||||
|
}
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
class JsonContext
|
class JsonContext
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
JsonContext(const QUuid &clientId, const QLocale &locale);
|
JsonContext(const QUuid &clientId, const QLocale &locale, bool authenticationEnabled = true);
|
||||||
|
|
||||||
QUuid clientId() const;
|
QUuid clientId() const;
|
||||||
QLocale locale() const;
|
QLocale locale() const;
|
||||||
@ -39,10 +39,14 @@ public:
|
|||||||
QByteArray token() const;
|
QByteArray token() const;
|
||||||
void setToken(const QByteArray &token);
|
void setToken(const QByteArray &token);
|
||||||
|
|
||||||
|
bool authenticationEnabled() const;
|
||||||
|
void setAuthenticationEnabled(bool authenticationEnabled);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QUuid m_clientId;
|
QUuid m_clientId;
|
||||||
QLocale m_locale;
|
QLocale m_locale;
|
||||||
QByteArray m_token;
|
QByteArray m_token;
|
||||||
|
bool m_authenticationEnabled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // JSONCONTEXT_H
|
#endif // JSONCONTEXT_H
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013 - 2024, nymea GmbH
|
* Copyright (C) 2013 - 2024, nymea GmbH
|
||||||
* Copyright (C) 2024 - 2025, chargebyte austria GmbH
|
* Copyright (C) 2024 - 2026, chargebyte austria GmbH
|
||||||
*
|
*
|
||||||
* This file is part of nymea.
|
* This file is part of nymea.
|
||||||
*
|
*
|
||||||
@ -24,9 +24,21 @@
|
|||||||
|
|
||||||
#include "platformupdatecontroller.h"
|
#include "platformupdatecontroller.h"
|
||||||
|
|
||||||
PlatformUpdateController::PlatformUpdateController(QObject *parent) : QObject(parent)
|
PlatformUpdateController::PlatformUpdateController(QObject *parent)
|
||||||
{
|
: QObject(parent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*! Indicates whether the update of this platform is package manager based or entire System updates or none.
|
||||||
|
On platforms like debian the update is mostly package manager based using apt in the background.
|
||||||
|
On many products like yocto or mender based systems there are system update images, where the user has no
|
||||||
|
influcence on individual packages, only to select between entire system images and their updates.
|
||||||
|
|
||||||
|
A backend plugin should override this to indicate the type of the system update.
|
||||||
|
*/
|
||||||
|
|
||||||
|
PlatformUpdateController::UpdateType PlatformUpdateController::updateType() const
|
||||||
|
{
|
||||||
|
return PlatformUpdateController::UpdateTypeNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Whether or not the update management is available. Returns true if the system is ready
|
/*! Whether or not the update management is available. Returns true if the system is ready
|
||||||
@ -78,6 +90,16 @@ bool PlatformUpdateController::updateRunning() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Indicates the progress of the update as percentage. Since not all update platforms support this feature,
|
||||||
|
the value defaults to -1 if not supported or not running.
|
||||||
|
|
||||||
|
A backend plugin should override this and return actual update percentage if supported.
|
||||||
|
*/
|
||||||
|
int PlatformUpdateController::updateProgress() const
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Returns a list of packages availabe in the system. If a backend supports installation of new packages,
|
/*! Returns a list of packages availabe in the system. If a backend supports installation of new packages,
|
||||||
the list of packages may contain not installed packages. Such packages are marked by
|
the list of packages may contain not installed packages. Such packages are marked by
|
||||||
returning an empty \l{Package::installedVersion()}. If the backend supports removal
|
returning an empty \l{Package::installedVersion()}. If the backend supports removal
|
||||||
@ -163,4 +185,3 @@ bool PlatformUpdateController::enableRepository(const QString &repositoryId, boo
|
|||||||
Q_UNUSED(enabled)
|
Q_UNUSED(enabled)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013 - 2024, nymea GmbH
|
* Copyright (C) 2013 - 2024, nymea GmbH
|
||||||
* Copyright (C) 2024 - 2025, chargebyte austria GmbH
|
* Copyright (C) 2024 - 2026, chargebyte austria GmbH
|
||||||
*
|
*
|
||||||
* This file is part of nymea.
|
* This file is part of nymea.
|
||||||
*
|
*
|
||||||
@ -34,14 +34,24 @@ class PlatformUpdateController : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
enum UpdateType {
|
||||||
|
UpdateTypeNone,
|
||||||
|
UpdateTypeSystem,
|
||||||
|
UpdateTypePackageManager
|
||||||
|
};
|
||||||
|
Q_ENUM(UpdateType)
|
||||||
|
|
||||||
explicit PlatformUpdateController(QObject *parent = nullptr);
|
explicit PlatformUpdateController(QObject *parent = nullptr);
|
||||||
virtual ~PlatformUpdateController() = default;
|
virtual ~PlatformUpdateController() = default;
|
||||||
|
|
||||||
|
virtual PlatformUpdateController::UpdateType updateType() const;
|
||||||
|
|
||||||
virtual bool updateManagementAvailable() const;
|
virtual bool updateManagementAvailable() const;
|
||||||
|
|
||||||
virtual bool checkForUpdates();
|
virtual bool checkForUpdates();
|
||||||
virtual bool busy() const;
|
virtual bool busy() const;
|
||||||
virtual bool updateRunning() const;
|
virtual bool updateRunning() const;
|
||||||
|
virtual int updateProgress() const;
|
||||||
|
|
||||||
virtual QList<Package> packages() const;
|
virtual QList<Package> packages() const;
|
||||||
virtual QList<Repository> repositories() const;
|
virtual QList<Repository> repositories() const;
|
||||||
@ -56,6 +66,7 @@ signals:
|
|||||||
void availableChanged();
|
void availableChanged();
|
||||||
void busyChanged();
|
void busyChanged();
|
||||||
void updateRunningChanged();
|
void updateRunningChanged();
|
||||||
|
void updateProgressChanged();
|
||||||
void packageAdded(const Package &pacakge);
|
void packageAdded(const Package &pacakge);
|
||||||
void packageChanged(const Package &package);
|
void packageChanged(const Package &package);
|
||||||
void packageRemoved(const QString &packageId);
|
void packageRemoved(const QString &packageId);
|
||||||
|
|||||||
@ -11,10 +11,10 @@ isEmpty(NYMEA_VERSION) {
|
|||||||
|
|
||||||
# define protocol versions
|
# define protocol versions
|
||||||
JSON_PROTOCOL_VERSION_MAJOR=8
|
JSON_PROTOCOL_VERSION_MAJOR=8
|
||||||
JSON_PROTOCOL_VERSION_MINOR=4
|
JSON_PROTOCOL_VERSION_MINOR=5
|
||||||
JSON_PROTOCOL_VERSION="$${JSON_PROTOCOL_VERSION_MAJOR}.$${JSON_PROTOCOL_VERSION_MINOR}"
|
JSON_PROTOCOL_VERSION="$${JSON_PROTOCOL_VERSION_MAJOR}.$${JSON_PROTOCOL_VERSION_MINOR}"
|
||||||
LIBNYMEA_API_VERSION_MAJOR=9
|
LIBNYMEA_API_VERSION_MAJOR=9
|
||||||
LIBNYMEA_API_VERSION_MINOR=0
|
LIBNYMEA_API_VERSION_MINOR=1
|
||||||
LIBNYMEA_API_VERSION_PATCH=0
|
LIBNYMEA_API_VERSION_PATCH=0
|
||||||
LIBNYMEA_API_VERSION="$${LIBNYMEA_API_VERSION_MAJOR}.$${LIBNYMEA_API_VERSION_MINOR}.$${LIBNYMEA_API_VERSION_PATCH}"
|
LIBNYMEA_API_VERSION="$${LIBNYMEA_API_VERSION_MAJOR}.$${LIBNYMEA_API_VERSION_MINOR}.$${LIBNYMEA_API_VERSION_PATCH}"
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
8.4
|
8.5
|
||||||
{
|
{
|
||||||
"enums": {
|
"enums": {
|
||||||
"BasicType": [
|
"BasicType": [
|
||||||
@ -359,6 +359,11 @@
|
|||||||
"UnitLiter",
|
"UnitLiter",
|
||||||
"UnitMicroGrammPerCubicalMeter"
|
"UnitMicroGrammPerCubicalMeter"
|
||||||
],
|
],
|
||||||
|
"UpdateType": [
|
||||||
|
"UpdateTypeNone",
|
||||||
|
"UpdateTypeSystem",
|
||||||
|
"UpdateTypePackageManager"
|
||||||
|
],
|
||||||
"UserError": [
|
"UserError": [
|
||||||
"UserErrorNoError",
|
"UserErrorNoError",
|
||||||
"UserErrorBackendError",
|
"UserErrorBackendError",
|
||||||
@ -1785,14 +1790,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"System.GetCapabilities": {
|
"System.GetCapabilities": {
|
||||||
"description": "Get the list of capabilites on this system. The property \"powerManagement\" indicates whether restarting nymea and rebooting or shutting down is supported on this system. The property \"updateManagement indicates whether system update features are available in this system. The property \"timeManagement\" indicates whether the system time can be configured on this system. Note that GetTime will be available in any case.",
|
"description": "Get the list of capabilites on this system. The property \"powerManagement\" indicates whether restarting nymea and rebooting or shutting down is supported on this system. The property \"updateManagement\" indicates whether system update features are available in this system. The \"updateManagementType\" indicates which kind of update is supported on this platform. The property \"timeManagement\" indicates whether the system time can be configured on this system. Note that GetTime will be available in any case.",
|
||||||
"params": {
|
"params": {
|
||||||
},
|
},
|
||||||
"permissionScope": "PermissionScopeAdmin",
|
"permissionScope": "PermissionScopeAdmin",
|
||||||
"returns": {
|
"returns": {
|
||||||
"powerManagement": "Bool",
|
"powerManagement": "Bool",
|
||||||
"timeManagement": "Bool",
|
"timeManagement": "Bool",
|
||||||
"updateManagement": "Bool"
|
"updateManagement": "Bool",
|
||||||
|
"updateManagementType": "$ref:UpdateType"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"System.GetPackages": {
|
"System.GetPackages": {
|
||||||
@ -1844,12 +1850,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"System.GetUpdateStatus": {
|
"System.GetUpdateStatus": {
|
||||||
"description": "Get the current status of the update system. \"busy\" indicates that the system is current busy with an operation regarding updates. This does not necessarily mean an actual update is running. When this is true, update related functions on the client should be marked as busy and no interaction with update components shall be allowed. An example for such a state is when the system queries the server if there are updates available, typically after a call to CheckForUpdates. \"updateRunning\" on the other hand indicates an actual update process is ongoing. The user should be informed about it, the system also might restart at any point while an update is running.",
|
"description": "Get the current status of the update system. \"busy\" indicates that the system is current busy with an operation regarding updates. This does not necessarily mean an actual update is running. When this is true, update related functions on the client should be marked as busy and no interaction with update components shall be allowed. An example for such a state is when the system queries the server if there are updates available, typically after a call to CheckForUpdates. \"updateRunning\" on the other hand indicates an actual update process is ongoing. The user should be informed about it, the system also might restart at any point while an update is running. The \"updateProgress\" property is optional, if the backend supports it, a progress >= 0 indicated the update progress in percentage.",
|
||||||
"params": {
|
"params": {
|
||||||
},
|
},
|
||||||
"permissionScope": "PermissionScopeAdmin",
|
"permissionScope": "PermissionScopeAdmin",
|
||||||
"returns": {
|
"returns": {
|
||||||
"busy": "Bool",
|
"busy": "Bool",
|
||||||
|
"o:updateProgress": "Int",
|
||||||
"updateRunning": "Bool"
|
"updateRunning": "Bool"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -2684,7 +2691,8 @@
|
|||||||
"description": "Emitted whenever the system capabilities change.",
|
"description": "Emitted whenever the system capabilities change.",
|
||||||
"params": {
|
"params": {
|
||||||
"powerManagement": "Bool",
|
"powerManagement": "Bool",
|
||||||
"updateManagement": "Bool"
|
"updateManagement": "Bool",
|
||||||
|
"updateManagementType": "$ref:UpdateType"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"System.PackageAdded": {
|
"System.PackageAdded": {
|
||||||
@ -2736,6 +2744,7 @@
|
|||||||
"description": "Emitted whenever the update status changes.",
|
"description": "Emitted whenever the update status changes.",
|
||||||
"params": {
|
"params": {
|
||||||
"busy": "Bool",
|
"busy": "Bool",
|
||||||
|
"o:updateProgress": "Int",
|
||||||
"updateRunning": "Bool"
|
"updateRunning": "Bool"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user