Compare commits

...

2 Commits

Author SHA1 Message Date
jenkins 5b73038726 Jenkins release build 1.14.2 2026-02-19 16:27:40 +01:00
Simon Stürz 0070d7e3dd Update PlatformUpdateController implementation
Introduce UpdateType for PlatformUpdateController implementations
Add optional update progress
Bump JSON-RPC API version to version 8.5
2026-02-19 14:35:20 +01:00
7 changed files with 103 additions and 35 deletions

View File

@ -1,3 +1,10 @@
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 ]

View File

@ -38,15 +38,18 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent):
registerObject<Package, Packages>();
registerObject<Repository, Repositories>();
registerEnum<PlatformUpdateController::UpdateType>();
// Methods
QString description; QVariantMap params; QVariantMap returns;
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.";
"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.";
returns.insert("powerManagement", enumValueName(Bool));
returns.insert("updateManagement", enumValueName(Bool));
returns.insert("updateManagementType", enumRef<PlatformUpdateController::UpdateType>());
returns.insert("timeManagement", enumValueName(Bool));
registerMethod("GetCapabilities", description, params, returns);
@ -66,15 +69,17 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent):
registerMethod("Shutdown", description, params, returns);
params.clear(); returns.clear();
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.";
returns.insert("busy", enumValueName(Bool));
returns.insert("updateRunning", enumValueName(Bool));
returns.insert("o:updateProgress", enumValueName(Int));
registerMethod("GetUpdateStatus", description, params, returns);
params.clear(); returns.clear();
@ -172,12 +177,14 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent):
description = "Emitted whenever the system capabilities change.";
params.insert("powerManagement", enumValueName(Bool));
params.insert("updateManagement", enumValueName(Bool));
params.insert("updateManagementType", enumRef<PlatformUpdateController::UpdateType>());
registerNotification("CapabilitiesChanged", description, params);
params.clear();
description = "Emitted whenever the update status changes.";
params.insert("busy", enumValueName(Bool));
params.insert("updateRunning", enumValueName(Bool));
params.insert("o:updateProgress", enumValueName(Int));
registerNotification("UpdateStatusChanged", description, params);
params.clear();
@ -220,18 +227,17 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent):
connect(m_platform->systemController(), &PlatformSystemController::availableChanged, this, &SystemHandler::onCapabilitiesChanged);
connect(m_platform->updateController(), &PlatformUpdateController::availableChanged, this, &SystemHandler::onCapabilitiesChanged);
connect(m_platform->updateController(), &PlatformUpdateController::busyChanged, this, [this](){
QVariantMap params;
params.insert("busy", m_platform->updateController()->busy());
params.insert("updateRunning", m_platform->updateController()->updateRunning());
emit UpdateStatusChanged(params);
emit UpdateStatusChanged(buildUpdateStatus());
});
connect(m_platform->updateController(), &PlatformUpdateController::updateRunningChanged, this, [this](){
QVariantMap params;
params.insert("busy", m_platform->updateController()->busy());
params.insert("updateRunning", m_platform->updateController()->updateRunning());
emit UpdateStatusChanged(params);
emit UpdateStatusChanged(buildUpdateStatus());
});
connect(m_platform->updateController(), &PlatformUpdateController::updateProgressChanged, this, [this](){
emit UpdateStatusChanged(buildUpdateStatus());
});
connect(m_platform->updateController(), &PlatformUpdateController::packageAdded, this, [this](const Package &package){
QVariantMap params;
params.insert("package", pack(package));
@ -247,6 +253,7 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent):
params.insert("packageId", packageId);
emit PackageRemoved(params);
});
connect(m_platform->updateController(), &PlatformUpdateController::repositoryAdded, this, [this](const Repository &repository){
QVariantMap params;
params.insert("repository", pack(repository));
@ -262,6 +269,7 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent):
params.insert("repositoryId", repositoryId);
emit RepositoryRemoved(params);
});
connect(m_platform->systemController(), &PlatformSystemController::timeConfigurationChanged, this, [this](){
QVariantMap params;
params.insert("time", QDateTime::currentMSecsSinceEpoch() / 1000);
@ -283,6 +291,7 @@ JsonReply *SystemHandler::GetCapabilities(const QVariantMap &params)
QVariantMap data;
data.insert("powerManagement", m_platform->systemController()->powerManagementAvailable());
data.insert("updateManagement", m_platform->updateController()->updateManagementAvailable());
data.insert("updateManagementType", enumValueName(m_platform->updateController()->updateType()));
data.insert("timeManagement", m_platform->systemController()->timeManagementAvailable());
return createReply(data);
}
@ -317,10 +326,7 @@ JsonReply *SystemHandler::Shutdown(const QVariantMap &params) const
JsonReply *SystemHandler::GetUpdateStatus(const QVariantMap &params) const
{
Q_UNUSED(params)
QVariantMap ret;
ret.insert("busy", m_platform->updateController()->busy());
ret.insert("updateRunning", m_platform->updateController()->updateRunning());
return createReply(ret);
return createReply(buildUpdateStatus());
}
JsonReply *SystemHandler::CheckForUpdates(const QVariantMap &params) const
@ -459,7 +465,19 @@ void SystemHandler::onCapabilitiesChanged()
QVariantMap caps;
caps.insert("powerManagement", m_platform->systemController()->powerManagementAvailable());
caps.insert("updateManagement", m_platform->updateController()->updateManagementAvailable());
caps.insert("updateManagementType", enumValueName(m_platform->updateController()->updateType()));
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;
}
}

View File

@ -82,6 +82,8 @@ private slots:
private:
Platform *m_platform = nullptr;
QVariantMap buildUpdateStatus() const;
};
}

View File

@ -3,7 +3,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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.
*
@ -24,9 +24,21 @@
#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
@ -78,6 +90,16 @@ bool PlatformUpdateController::updateRunning() const
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,
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
@ -163,4 +185,3 @@ bool PlatformUpdateController::enableRepository(const QString &repositoryId, boo
Q_UNUSED(enabled)
return false;
}

View File

@ -3,7 +3,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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.
*
@ -34,14 +34,24 @@ class PlatformUpdateController : public QObject
{
Q_OBJECT
public:
enum UpdateType {
UpdateTypeNone,
UpdateTypeSystem,
UpdateTypePackageManager
};
Q_ENUM(UpdateType)
explicit PlatformUpdateController(QObject *parent = nullptr);
virtual ~PlatformUpdateController() = default;
virtual PlatformUpdateController::UpdateType updateType() const;
virtual bool updateManagementAvailable() const;
virtual bool checkForUpdates();
virtual bool busy() const;
virtual bool updateRunning() const;
virtual int updateProgress() const;
virtual QList<Package> packages() const;
virtual QList<Repository> repositories() const;
@ -56,6 +66,7 @@ signals:
void availableChanged();
void busyChanged();
void updateRunningChanged();
void updateProgressChanged();
void packageAdded(const Package &pacakge);
void packageChanged(const Package &package);
void packageRemoved(const QString &packageId);

View File

@ -11,10 +11,10 @@ isEmpty(NYMEA_VERSION) {
# define protocol versions
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}"
LIBNYMEA_API_VERSION_MAJOR=9
LIBNYMEA_API_VERSION_MINOR=0
LIBNYMEA_API_VERSION_MINOR=1
LIBNYMEA_API_VERSION_PATCH=0
LIBNYMEA_API_VERSION="$${LIBNYMEA_API_VERSION_MAJOR}.$${LIBNYMEA_API_VERSION_MINOR}.$${LIBNYMEA_API_VERSION_PATCH}"

View File

@ -1,4 +1,4 @@
8.4
8.5
{
"enums": {
"BasicType": [
@ -359,6 +359,11 @@
"UnitLiter",
"UnitMicroGrammPerCubicalMeter"
],
"UpdateType": [
"UpdateTypeNone",
"UpdateTypeSystem",
"UpdateTypePackageManager"
],
"UserError": [
"UserErrorNoError",
"UserErrorBackendError",
@ -1785,14 +1790,15 @@
}
},
"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": {
},
"permissionScope": "PermissionScopeAdmin",
"returns": {
"powerManagement": "Bool",
"timeManagement": "Bool",
"updateManagement": "Bool"
"updateManagement": "Bool",
"updateManagementType": "$ref:UpdateType"
}
},
"System.GetPackages": {
@ -1844,12 +1850,13 @@
}
},
"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": {
},
"permissionScope": "PermissionScopeAdmin",
"returns": {
"busy": "Bool",
"o:updateProgress": "Int",
"updateRunning": "Bool"
}
},
@ -2684,7 +2691,8 @@
"description": "Emitted whenever the system capabilities change.",
"params": {
"powerManagement": "Bool",
"updateManagement": "Bool"
"updateManagement": "Bool",
"updateManagementType": "$ref:UpdateType"
}
},
"System.PackageAdded": {
@ -2736,6 +2744,7 @@
"description": "Emitted whenever the update status changes.",
"params": {
"busy": "Bool",
"o:updateProgress": "Int",
"updateRunning": "Bool"
}
},