Update PlatformUpdateController implementation

Introduce UpdateType for PlatformUpdateController implementations
Add optional update progress
Bump JSON-RPC API version to version 8.5
This commit is contained in:
Simon Stürz 2026-01-19 11:12:59 +01:00
parent ab61ed9a8b
commit 0070d7e3dd
6 changed files with 96 additions and 35 deletions

View File

@ -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 &params)
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 &params) const
JsonReply *SystemHandler::GetUpdateStatus(const QVariantMap &params) const JsonReply *SystemHandler::GetUpdateStatus(const QVariantMap &params) 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 &params) const JsonReply *SystemHandler::CheckForUpdates(const QVariantMap &params) 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;
}
} }

View File

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

View File

@ -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;
} }

View File

@ -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);

View File

@ -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}"

View File

@ -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"
} }
}, },