Add system api to configure the system time
This gets rid of the locally kept time zone which caused issues in plugins and the ScriptEngine.
This commit is contained in:
parent
6cdcd47f9b
commit
9b07216768
@ -1026,12 +1026,6 @@ DeviceActionInfo *DeviceManagerImplementation::executeAction(const Action &actio
|
||||
return info;
|
||||
}
|
||||
|
||||
/*! Centralized time tick for the NymeaTimer resource. Ticks every second. */
|
||||
void DeviceManagerImplementation::timeTick()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DeviceManagerImplementation::loadPlugins()
|
||||
{
|
||||
foreach (const QString &path, pluginSearchDirs()) {
|
||||
|
||||
@ -114,9 +114,6 @@ public:
|
||||
signals:
|
||||
void loaded();
|
||||
|
||||
public slots:
|
||||
void timeTick();
|
||||
|
||||
private slots:
|
||||
void loadPlugins();
|
||||
void loadPlugin(DevicePlugin *pluginIface, const PluginMetadata &metaData);
|
||||
|
||||
@ -61,6 +61,8 @@
|
||||
#include "configurationhandler.h"
|
||||
#include "nymeacore.h"
|
||||
#include "nymeaconfiguration.h"
|
||||
#include "platform/platform.h"
|
||||
#include "platform/platformsystemcontroller.h"
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
@ -80,21 +82,21 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
|
||||
QString description; QVariantMap params; QVariantMap returns;
|
||||
description = "Get the list of available timezones.";
|
||||
returns.insert("timeZones", QVariantList() << enumValueName(String));
|
||||
registerMethod("GetTimeZones", description, params, returns);
|
||||
registerMethod("GetTimeZones", description, params, returns, "Use System.GetTimeZones instead.");
|
||||
|
||||
params.clear(); returns.clear();
|
||||
description = "DEPRECATED - Use the locale property in the Handshake message instead - Returns a list of locale codes available for the server. i.e. en_US, de_AT";
|
||||
description = "Returns a list of locale codes available for the server. i.e. en_US, de_AT";
|
||||
returns.insert("languages", QVariantList() << enumValueName(String));
|
||||
registerMethod("GetAvailableLanguages", description, params, returns);
|
||||
registerMethod("GetAvailableLanguages", description, params, returns, "Use the locale property in the Handshake message instead.");
|
||||
|
||||
params.clear(); returns.clear();
|
||||
description = "Get all configuration parameters of the server.";
|
||||
QVariantMap basicConfiguration;
|
||||
basicConfiguration.insert("serverName", enumValueName(String));
|
||||
basicConfiguration.insert("serverUuid", enumValueName(Uuid));
|
||||
basicConfiguration.insert("serverTime", enumValueName(Uint));
|
||||
basicConfiguration.insert("timeZone", enumValueName(String));
|
||||
basicConfiguration.insert("language", enumValueName(String));
|
||||
basicConfiguration.insert("d:serverTime", enumValueName(Uint));
|
||||
basicConfiguration.insert("d:timeZone", enumValueName(String));
|
||||
basicConfiguration.insert("d:language", enumValueName(String));
|
||||
basicConfiguration.insert("debugServerEnabled", enumValueName(Bool));
|
||||
returns.insert("basicConfiguration", basicConfiguration);
|
||||
QVariantList tcpServerConfigurations;
|
||||
@ -123,13 +125,13 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
|
||||
description = "Set the time zone of the server. See also: \"GetTimeZones\"";
|
||||
params.insert("timeZone", enumValueName(String));
|
||||
returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>());
|
||||
registerMethod("SetTimeZone", description, params, returns);
|
||||
registerMethod("SetTimeZone", description, params, returns, "Use System.SetTimeZone instead.");
|
||||
|
||||
params.clear(); returns.clear();
|
||||
description = "DEPRECATED - Use the locale property in the Handshake message instead - Sets the server language to the given language. See also: \"GetAvailableLanguages\"";
|
||||
description = "Sets the server language to the given language. See also: \"GetAvailableLanguages\"";
|
||||
params.insert("language", enumValueName(String));
|
||||
returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>());
|
||||
registerMethod("SetLanguage", description, params, returns);
|
||||
registerMethod("SetLanguage", description, params, returns, "Use the locale property in the Handshake message instead.");
|
||||
|
||||
params.clear(); returns.clear();
|
||||
description = "Enable or disable the debug server.";
|
||||
@ -339,7 +341,7 @@ JsonReply *ConfigurationHandler::GetTimeZones(const QVariantMap ¶ms) const
|
||||
{
|
||||
Q_UNUSED(params)
|
||||
QVariantList timeZones;
|
||||
foreach (const QByteArray &timeZoneId, NymeaCore::instance()->timeManager()->availableTimeZones()) {
|
||||
foreach (const QByteArray &timeZoneId, QTimeZone::availableTimeZoneIds()) {
|
||||
timeZones.append(QString::fromUtf8(timeZoneId));
|
||||
}
|
||||
|
||||
@ -371,11 +373,18 @@ JsonReply *ConfigurationHandler::SetTimeZone(const QVariantMap ¶ms) const
|
||||
{
|
||||
qCDebug(dcJsonRpc()) << "Setting time zone to" << params.value("timeZone").toString();
|
||||
|
||||
QByteArray timeZone = params.value("timeZone").toString().toUtf8();
|
||||
if (!NymeaCore::instance()->timeManager()->setTimeZone(timeZone))
|
||||
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidTimeZone));
|
||||
QByteArray timeZoneName = params.value("timeZone").toString().toUtf8();
|
||||
|
||||
QTimeZone timeZone(timeZoneName);
|
||||
if (!timeZone.isValid()) {
|
||||
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidTimeZone));
|
||||
}
|
||||
|
||||
bool success = NymeaCore::instance()->platform()->systemController()->setTimeZone(timeZone);
|
||||
if (!success) {
|
||||
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidTimeZone));
|
||||
}
|
||||
|
||||
NymeaCore::instance()->configuration()->setTimeZone(timeZone);
|
||||
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorNoError));
|
||||
}
|
||||
|
||||
@ -658,7 +667,7 @@ QVariantMap ConfigurationHandler::packBasicConfiguration()
|
||||
basicConfiguration.insert("serverName", NymeaCore::instance()->configuration()->serverName());
|
||||
basicConfiguration.insert("serverUuid", NymeaCore::instance()->configuration()->serverUuid().toString());
|
||||
basicConfiguration.insert("serverTime", NymeaCore::instance()->timeManager()->currentDateTime().toTime_t());
|
||||
basicConfiguration.insert("timeZone", QString::fromUtf8(NymeaCore::instance()->timeManager()->timeZone()));
|
||||
basicConfiguration.insert("timeZone", QTimeZone::systemTimeZoneId());
|
||||
basicConfiguration.insert("language", NymeaCore::instance()->configuration()->locale().name());
|
||||
basicConfiguration.insert("debugServerEnabled", NymeaCore::instance()->configuration()->debugServerEnabled());
|
||||
return basicConfiguration;
|
||||
|
||||
@ -112,7 +112,7 @@ JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const Q
|
||||
continue;
|
||||
}
|
||||
QString trimmedKey = key;
|
||||
trimmedKey.remove(QRegExp("^(o:|r:)"));
|
||||
trimmedKey.remove(QRegExp("^(o:|r:|d:)"));
|
||||
if (!map.contains(trimmedKey)) {
|
||||
return Result(false, "Missing required key: " + key, key);
|
||||
}
|
||||
@ -123,7 +123,7 @@ JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const Q
|
||||
// Is the key allowed in here?
|
||||
QVariant expectedValue = definition.value(key);
|
||||
foreach (const QString &definitionKey, definition.keys()) {
|
||||
QRegExp regExp = QRegExp("(o:|r:)*" + key);
|
||||
QRegExp regExp = QRegExp("(o:|r:|d:)*" + key);
|
||||
if (regExp.exactMatch(definitionKey)) {
|
||||
expectedValue = definition.value(definitionKey);
|
||||
}
|
||||
@ -132,7 +132,7 @@ JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const Q
|
||||
expectedValue = definition.value("o:" + key);
|
||||
}
|
||||
if (!expectedValue.isValid()) {
|
||||
expectedValue = definition.value("o:" + key);
|
||||
expectedValue = definition.value("d:" + key);
|
||||
}
|
||||
if (!expectedValue.isValid()) {
|
||||
return Result(false, "Invalid key: " + key);
|
||||
|
||||
@ -38,9 +38,14 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent):
|
||||
|
||||
// Methods
|
||||
QString description; QVariantMap params; QVariantMap returns;
|
||||
description = "Get the list of capabilites on this system. This allows reading whether things like rebooting or shutting down the system running nymea:core is supported on this host.";
|
||||
description = "Get the list of capabilites on this system. The property \"powerManagement\" indicates whether "
|
||||
"rebooting or shutting down the system running nymea:core is supported on this host. The property "
|
||||
"\"updateManagement indicates whether system update features are available in this API. 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("timeManagement", enumValueName(Bool));
|
||||
registerMethod("GetCapabilities", description, params, returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
@ -116,6 +121,39 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent):
|
||||
returns.insert("success", enumValueName(Bool));
|
||||
registerMethod("EnableRepository", description, params, returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
description = "Get the system time and configuraton. The \"serverTime\" and \"serverTimezone\" properties "
|
||||
"give the current server time and time zone. \"automaticTimeAvailable\" indicates whether "
|
||||
"this system supports automatically setting the clock (e.g. using NTP). \"automaticTime\" will "
|
||||
"be true if the system is configured to automatically update the clock.";
|
||||
returns.insert("time", enumValueName(Uint));
|
||||
returns.insert("timeZone", enumValueName(String));
|
||||
returns.insert("automaticTimeAvailable", enumValueName(Bool));
|
||||
returns.insert("automaticTime", enumValueName(Bool));
|
||||
registerMethod("GetTime", description, params, returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
description = "Set the system time configuraton. The system can be configured to update the time automatically "
|
||||
"by setting \"automaticTime\" to true. This will only work if the \"timeManagement\" capability is "
|
||||
"available on this system and \"GetTime\" indicates the availability of automatic time settngs. If "
|
||||
"any of those requirements are not met, this method will return \"false\" in the \"success\" property. "
|
||||
"In order to manually configure the time, \"automaticTime\" should be set to false and \"time\" should "
|
||||
"be set. Note that if \"automaticTime\" is set to true and a manual \"time\" is still passed, the system "
|
||||
"will attempt to configure automatic time updates and only set the manual time if automatic mode fails. "
|
||||
"A time zone can always be passed optionally to change the system time zone and should be a IANA time zone "
|
||||
"id.";
|
||||
params.insert("o:automaticTime", enumValueName(Bool));
|
||||
params.insert("o:time", enumValueName(Uint));
|
||||
params.insert("o:timeZone", enumValueName(String));
|
||||
returns.insert("success", enumValueName(Bool));
|
||||
registerMethod("SetTime", description, params, returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
description = "Returns the list of IANA specified time zone IDs which can be used to select a time zone. It is not "
|
||||
"required to use this method of the client toolkit already provides means to obtain a list of IANA time "
|
||||
"zone ids.";
|
||||
returns.insert("timeZones", enumValueName(StringList));
|
||||
registerMethod("GetTimeZones", description, params, returns);
|
||||
|
||||
// Notifications
|
||||
params.clear();
|
||||
@ -160,6 +198,13 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent):
|
||||
params.insert("repositoryId", enumValueName(String));
|
||||
registerNotification("RepositoryRemoved", description, params);
|
||||
|
||||
params.clear();
|
||||
description = "Emitted whenever the time configuration is changed";
|
||||
params.insert("time", enumValueName(Uint));
|
||||
params.insert("timeZone", enumValueName(String));
|
||||
params.insert("automaticTimeAvailable", enumValueName(Bool));
|
||||
params.insert("automaticTime", enumValueName(Bool));
|
||||
registerNotification("TimeConfigurationChanged", description, params);
|
||||
|
||||
connect(m_platform->systemController(), &PlatformSystemController::availableChanged, this, &SystemHandler::onCapabilitiesChanged);
|
||||
connect(m_platform->updateController(), &PlatformUpdateController::availableChanged, this, &SystemHandler::onCapabilitiesChanged);
|
||||
@ -205,6 +250,14 @@ 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::currentDateTime().toSecsSinceEpoch());
|
||||
params.insert("timeZone", QTimeZone::systemTimeZoneId());
|
||||
params.insert("automaticTimeAvailable", m_platform->systemController()->automaticTimeAvailable());
|
||||
params.insert("automaticTime", m_platform->systemController()->automaticTime());
|
||||
emit TimeConfigurationChanged(params);
|
||||
}, Qt::QueuedConnection); // Queued to give QDateTime a chance to sync itself to the system
|
||||
}
|
||||
|
||||
QString SystemHandler::name() const
|
||||
@ -218,6 +271,7 @@ JsonReply *SystemHandler::GetCapabilities(const QVariantMap ¶ms)
|
||||
QVariantMap data;
|
||||
data.insert("powerManagement", m_platform->systemController()->powerManagementAvailable());
|
||||
data.insert("updateManagement", m_platform->updateController()->updateManagementAvailable());
|
||||
data.insert("timeManagement", m_platform->systemController()->timeManagementAvailable());
|
||||
return createReply(data);
|
||||
}
|
||||
|
||||
@ -314,6 +368,62 @@ JsonReply *SystemHandler::EnableRepository(const QVariantMap ¶ms) const
|
||||
return createReply(returns);
|
||||
}
|
||||
|
||||
JsonReply *SystemHandler::GetTime(const QVariantMap ¶ms) const
|
||||
{
|
||||
Q_UNUSED(params)
|
||||
QVariantMap returns;
|
||||
returns.insert("automaticTimeAvailable", m_platform->systemController()->automaticTimeAvailable());
|
||||
returns.insert("automaticTime", m_platform->systemController()->automaticTime());
|
||||
returns.insert("time", QDateTime::currentDateTime().toSecsSinceEpoch());
|
||||
returns.insert("timeZone", QTimeZone::systemTimeZoneId());
|
||||
return createReply(returns);
|
||||
}
|
||||
|
||||
JsonReply *SystemHandler::SetTime(const QVariantMap ¶ms) const
|
||||
{
|
||||
QVariantMap returns;
|
||||
bool handled = false;
|
||||
bool automaticTime = params.value("automaticTime", false).toBool();
|
||||
if (params.contains("automaticTime") && m_platform->systemController()->automaticTimeAvailable()) {
|
||||
if (!m_platform->systemController()->setAutomaticTime(automaticTime)) {
|
||||
returns.insert("success", false);
|
||||
return createReply(returns);
|
||||
}
|
||||
handled = true;
|
||||
}
|
||||
if (!automaticTime && params.contains("time")) {
|
||||
QDateTime time = QDateTime::fromSecsSinceEpoch(params.value("time").toUInt());
|
||||
if (!m_platform->systemController()->setTime(time)) {
|
||||
returns.insert("success", false);
|
||||
return createReply(returns);
|
||||
}
|
||||
handled = true;
|
||||
}
|
||||
if (params.contains("timeZone")) {
|
||||
QTimeZone timeZone(params.value("timeZone").toByteArray());
|
||||
if (!m_platform->systemController()->setTimeZone(timeZone)) {
|
||||
returns.insert("success", false);
|
||||
return createReply(returns);
|
||||
}
|
||||
handled = true;
|
||||
}
|
||||
returns.insert("success", handled);
|
||||
return createReply(returns);
|
||||
}
|
||||
|
||||
JsonReply *SystemHandler::GetTimeZones(const QVariantMap ¶ms) const
|
||||
{
|
||||
Q_UNUSED(params)
|
||||
QVariantList timeZones;
|
||||
foreach (const QByteArray &timeZoneId, QTimeZone::availableTimeZoneIds()) {
|
||||
timeZones.append(QString::fromUtf8(timeZoneId));
|
||||
}
|
||||
|
||||
QVariantMap returns;
|
||||
returns.insert("timeZones", timeZones);
|
||||
return createReply(returns);
|
||||
}
|
||||
|
||||
void SystemHandler::onCapabilitiesChanged()
|
||||
{
|
||||
QVariantMap caps;
|
||||
|
||||
@ -53,8 +53,13 @@ public:
|
||||
Q_INVOKABLE JsonReply *GetRepositories(const QVariantMap ¶ms) const;
|
||||
Q_INVOKABLE JsonReply *EnableRepository(const QVariantMap ¶ms) const;
|
||||
|
||||
Q_INVOKABLE JsonReply *GetTime(const QVariantMap ¶ms) const;
|
||||
Q_INVOKABLE JsonReply *SetTime(const QVariantMap ¶ms) const;
|
||||
Q_INVOKABLE JsonReply *GetTimeZones(const QVariantMap ¶ms) const;
|
||||
|
||||
signals:
|
||||
void CapabilitiesChanged(const QVariantMap ¶ms);
|
||||
|
||||
void UpdateStatusChanged(const QVariantMap ¶ms);
|
||||
void PackageAdded(const QVariantMap ¶ms);
|
||||
void PackageChanged(const QVariantMap ¶ms);
|
||||
@ -63,6 +68,8 @@ signals:
|
||||
void RepositoryChanged(const QVariantMap ¶ms);
|
||||
void RepositoryRemoved(const QVariantMap ¶ms);
|
||||
|
||||
void TimeConfigurationChanged(const QVariantMap ¶ms);
|
||||
|
||||
private slots:
|
||||
void onCapabilitiesChanged();
|
||||
|
||||
|
||||
@ -98,6 +98,7 @@
|
||||
#include "tagging/tagsstorage.h"
|
||||
#include "platform/platform.h"
|
||||
#include "experiences/experiencemanager.h"
|
||||
#include "platform/platformsystemcontroller.h"
|
||||
|
||||
#include "devices/devicemanagerimplementation.h"
|
||||
#include "devices/device.h"
|
||||
@ -140,7 +141,14 @@ void NymeaCore::init() {
|
||||
m_configuration = new NymeaConfiguration(this);
|
||||
|
||||
qCDebug(dcApplication()) << "Creating Time Manager";
|
||||
m_timeManager = new TimeManager(m_configuration->timeZone(), this);
|
||||
// Migration path: nymea < 0.18 doesn't use system time zone but stores its own time zone in the config
|
||||
// For migration, let's set the system's time zone to the config now to upgrade to the system time zone based nymea >= 0.18
|
||||
if (QTimeZone(m_configuration->timeZone()).isValid()) {
|
||||
if (m_platform->systemController()->setTimeZone(QTimeZone(m_configuration->timeZone()))) {
|
||||
m_configuration->setTimeZone("");
|
||||
}
|
||||
}
|
||||
m_timeManager = new TimeManager(this);
|
||||
|
||||
qCDebug(dcApplication) << "Creating Log Engine";
|
||||
m_logger = new LogEngine(m_configuration->logDBDriver(), m_configuration->logDBName(), m_configuration->logDBHost(), m_configuration->logDBUser(), m_configuration->logDBPassword(), m_configuration->logDBMaxEntries(), this);
|
||||
@ -199,7 +207,6 @@ void NymeaCore::init() {
|
||||
connect(m_ruleEngine, &RuleEngine::ruleConfigurationChanged, this, &NymeaCore::ruleConfigurationChanged);
|
||||
|
||||
connect(m_timeManager, &TimeManager::dateTimeChanged, this, &NymeaCore::onDateTimeChanged);
|
||||
connect(m_timeManager, &TimeManager::tick, m_deviceManager, &DeviceManagerImplementation::timeTick);
|
||||
|
||||
m_logger->logSystemEvent(m_timeManager->currentDateTime(), true);
|
||||
}
|
||||
|
||||
@ -40,71 +40,16 @@
|
||||
namespace nymeaserver {
|
||||
|
||||
/*! Constructs a new \l{TimeManager} with the given \a timeZone and \a parent. */
|
||||
TimeManager::TimeManager(const QByteArray &timeZone, QObject *parent) :
|
||||
TimeManager::TimeManager(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
m_dateTime = QDateTime::currentDateTimeUtc();
|
||||
m_dateTime.setTimeSpec(Qt::UTC);
|
||||
|
||||
setTimeZone(timeZone);
|
||||
|
||||
m_nymeaTimer = new QTimer(this);
|
||||
m_nymeaTimer->setInterval(1000);
|
||||
m_nymeaTimer->setSingleShot(false);
|
||||
|
||||
connect(m_nymeaTimer, &QTimer::timeout, this, &TimeManager::nymeaTimeout);
|
||||
|
||||
m_nymeaTimer->start();
|
||||
}
|
||||
|
||||
/*! Returns the time zone of this \l{TimeManager}. */
|
||||
QByteArray TimeManager::timeZone() const
|
||||
{
|
||||
return m_timeZone.id();
|
||||
}
|
||||
|
||||
/*! Sets the \a timeZone of this \l{TimeManager}. Allowed values according to the \l{http://www.iana.org/time-zones}{IANA database}.
|
||||
* Returns false if the given timezone is not valid. */
|
||||
bool TimeManager::setTimeZone(const QByteArray &timeZone)
|
||||
{
|
||||
if (!QTimeZone(timeZone).isValid()) {
|
||||
qCWarning(dcTimeManager()) << "Invalid time zone" << timeZone;
|
||||
qCWarning(dcTimeManager()) << "Using system time zone" << QTimeZone::systemTimeZoneId();
|
||||
m_timeZone = QTimeZone(QTimeZone::systemTimeZoneId());
|
||||
emit dateTimeChanged(currentDateTime());
|
||||
return false;
|
||||
}
|
||||
|
||||
qCDebug(dcTimeManager()) << "Set time zone" << timeZone;
|
||||
m_timeZone = QTimeZone(timeZone);
|
||||
qCDebug(dcTimeManager()) << "UTC" << m_dateTime.toString("dd.MM.yyyy hh:mm:ss");
|
||||
qCDebug(dcTimeManager) << "Zone time" << currentDateTime().toString("dd.MM.yyyy hh:mm:ss");
|
||||
emit dateTimeChanged(currentDateTime());
|
||||
return true;
|
||||
m_timerId = startTimer(1000, Qt::VeryCoarseTimer);
|
||||
}
|
||||
|
||||
/*! Returns the current dateTime of this \l{TimeManager}. */
|
||||
QDateTime TimeManager::currentDateTime() const
|
||||
{
|
||||
return QDateTime::currentDateTimeUtc().toTimeZone(m_timeZone);
|
||||
}
|
||||
|
||||
/*! Returns the current time of this \l{TimeManager}. */
|
||||
QTime TimeManager::currentTime() const
|
||||
{
|
||||
return QDateTime::currentDateTimeUtc().toTimeZone(m_timeZone).time();
|
||||
}
|
||||
|
||||
/*! Returns the current date of this \l{TimeManager}. */
|
||||
QDate TimeManager::currentDate() const
|
||||
{
|
||||
return QDateTime::currentDateTimeUtc().toTimeZone(m_timeZone).date();
|
||||
}
|
||||
|
||||
/*! Returns a list of available time zones on this system. */
|
||||
QList<QByteArray> TimeManager::availableTimeZones() const
|
||||
{
|
||||
return QTimeZone::availableTimeZoneIds();
|
||||
return QDateTime::currentDateTime().addSecs(m_overrideDifference);
|
||||
}
|
||||
|
||||
/*! Stop the time.
|
||||
@ -115,7 +60,7 @@ void TimeManager::stopTimer()
|
||||
{
|
||||
qCWarning(dcTimeManager()) << "TimeManager timer stopped. You should only see this in tests.";
|
||||
// Stop clock (used for testing)
|
||||
m_nymeaTimer->stop();
|
||||
killTimer(m_timerId);
|
||||
}
|
||||
|
||||
/*! Set the current time of this TimeManager to the given \a dateTime.
|
||||
@ -125,21 +70,22 @@ void TimeManager::stopTimer()
|
||||
void TimeManager::setTime(const QDateTime &dateTime)
|
||||
{
|
||||
qCWarning(dcTimeManager()) << "TimeManager time changed" << dateTime.toString("dd.MM.yyyy hh:mm:ss") << "You should only see this in tests.";
|
||||
m_overrideDifference = QDateTime::currentDateTime().secsTo(dateTime);
|
||||
// This method will only be called for testing to set the internal time
|
||||
emit tick();
|
||||
emit dateTimeChanged(dateTime);
|
||||
}
|
||||
|
||||
void TimeManager::nymeaTimeout()
|
||||
void TimeManager::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
// tick for deviceManager
|
||||
Q_UNUSED(event)
|
||||
|
||||
emit tick();
|
||||
|
||||
// Minute based nymea time
|
||||
QDateTime utcDateTime = QDateTime::currentDateTimeUtc();
|
||||
if (m_dateTime.time().minute() != utcDateTime.toTimeZone(m_timeZone).time().minute()) {
|
||||
m_dateTime = utcDateTime;
|
||||
emit dateTimeChanged(currentDateTime());
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
if (m_lastEvent.time().minute() != now.time().minute()) {
|
||||
m_lastEvent = now;
|
||||
emit dateTimeChanged(now.addSecs(m_overrideDifference));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -32,32 +32,27 @@ class TimeManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TimeManager(const QByteArray &timeZone, QObject *parent = 0);
|
||||
|
||||
QByteArray timeZone() const;
|
||||
bool setTimeZone(const QByteArray &timeZone = QTimeZone::systemTimeZoneId());
|
||||
explicit TimeManager(QObject *parent = nullptr);
|
||||
|
||||
QDateTime currentDateTime() const;
|
||||
QTime currentTime() const;
|
||||
QDate currentDate() const;
|
||||
|
||||
QList<QByteArray> availableTimeZones() const;
|
||||
|
||||
// For testability only
|
||||
void stopTimer();
|
||||
void setTime(const QDateTime &dateTime);
|
||||
|
||||
private:
|
||||
QTimeZone m_timeZone;
|
||||
QDateTime m_dateTime;
|
||||
QTimer *m_nymeaTimer;
|
||||
|
||||
signals:
|
||||
void tick();
|
||||
void dateTimeChanged(const QDateTime &dateTime);
|
||||
|
||||
private slots:
|
||||
void nymeaTimeout();
|
||||
protected:
|
||||
void timerEvent(QTimerEvent *event) override;
|
||||
|
||||
private:
|
||||
int m_timerId = 0;
|
||||
QDateTime m_lastEvent;
|
||||
|
||||
// For testability
|
||||
qint64 m_overrideDifference = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -22,6 +22,8 @@
|
||||
|
||||
#include "platformsystemcontroller.h"
|
||||
|
||||
#include "loggingcategories.h"
|
||||
|
||||
PlatformSystemController::PlatformSystemController(QObject *parent) : QObject(parent)
|
||||
{
|
||||
|
||||
@ -41,3 +43,39 @@ bool PlatformSystemController::shutdown()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PlatformSystemController::timeManagementAvailable() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PlatformSystemController::automaticTimeAvailable() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PlatformSystemController::automaticTime() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PlatformSystemController::setTime(const QDateTime &time)
|
||||
{
|
||||
Q_UNUSED(time)
|
||||
qCWarning(dcPlatform()) << "setTime not implemented in platform plugin";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PlatformSystemController::setAutomaticTime(bool automaticTime)
|
||||
{
|
||||
Q_UNUSED(automaticTime)
|
||||
qCWarning(dcPlatform()) << "setAutomaticTime not implemented in platform plugin";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PlatformSystemController::setTimeZone(const QTimeZone &timeZone)
|
||||
{
|
||||
Q_UNUSED(timeZone)
|
||||
qCWarning(dcPlatform()) << "setTimeZone not implemented in platform plugin";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#define PLATFORMSYSTEMCONTROLLER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimeZone>
|
||||
|
||||
class PlatformSystemController : public QObject
|
||||
{
|
||||
@ -36,8 +37,19 @@ public:
|
||||
virtual bool reboot();
|
||||
virtual bool shutdown();
|
||||
|
||||
virtual bool timeManagementAvailable() const;
|
||||
virtual bool automaticTimeAvailable() const;
|
||||
virtual bool automaticTime() const;
|
||||
virtual bool setTime(const QDateTime &time);
|
||||
virtual bool setAutomaticTime(bool automaticTime);
|
||||
virtual bool setTimeZone(const QTimeZone &timeZone);
|
||||
|
||||
|
||||
signals:
|
||||
void availableChanged();
|
||||
void timeZoneManagementAvailableChanged();
|
||||
|
||||
void timeConfigurationChanged();
|
||||
};
|
||||
|
||||
Q_DECLARE_INTERFACE(PlatformSystemController, "io.nymea.PlatformSystemController")
|
||||
|
||||
@ -23,6 +23,9 @@
|
||||
#include "nymeacore.h"
|
||||
#include "servers/mocktcpserver.h"
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "platform/platformsystemcontroller.h"
|
||||
|
||||
using namespace nymeaserver;
|
||||
|
||||
class TestTimeManager: public NymeaTestBase
|
||||
@ -37,9 +40,6 @@ private:
|
||||
private slots:
|
||||
void initTestCase();
|
||||
|
||||
void changeTimeZone_data();
|
||||
void changeTimeZone();
|
||||
|
||||
void loadSaveTimeDescriptor_data();
|
||||
void loadSaveTimeDescriptor();
|
||||
|
||||
@ -142,41 +142,6 @@ void TestTimeManager::initTestCase()
|
||||
"TimeManager.debug=true");
|
||||
}
|
||||
|
||||
void TestTimeManager::changeTimeZone_data()
|
||||
{
|
||||
QTest::addColumn<QByteArray>("timeZoneId");
|
||||
QTest::addColumn<bool>("valid");
|
||||
|
||||
QTest::newRow("valid timezone: Asia/Tokyo") << QByteArray("Asia/Tokyo") << true;
|
||||
QTest::newRow("valid timezone: America/Lima") << QByteArray("America/Lima") << true;
|
||||
QTest::newRow("valid timezone: Africa/Harare") << QByteArray("Africa/Harare") << true;
|
||||
QTest::newRow("invalid timezone: Mars/Diacria") << QByteArray("Mars/Diacria") << false;
|
||||
QTest::newRow("invalid timezone: Moon/Kepler") << QByteArray("Moon/Kepler") << false;
|
||||
}
|
||||
|
||||
void TestTimeManager::changeTimeZone()
|
||||
{
|
||||
QFETCH(QByteArray, timeZoneId);
|
||||
QFETCH(bool, valid);
|
||||
|
||||
QTimeZone currentTimeZone(NymeaCore::instance()->timeManager()->timeZone());
|
||||
QTimeZone newTimeZone(timeZoneId);
|
||||
|
||||
|
||||
QDateTime currentDateTime = NymeaCore::instance()->timeManager()->currentDateTime();
|
||||
|
||||
NymeaCore::instance()->timeManager()->setTimeZone(timeZoneId);
|
||||
|
||||
QDateTime newDateTime = NymeaCore::instance()->timeManager()->currentDateTime();
|
||||
|
||||
int offsetOriginal = currentTimeZone.offsetFromUtc(currentDateTime);
|
||||
int offsetNew = newTimeZone.offsetFromUtc(newDateTime);
|
||||
|
||||
if (valid)
|
||||
QVERIFY(offsetOriginal != offsetNew);
|
||||
|
||||
}
|
||||
|
||||
void TestTimeManager::loadSaveTimeDescriptor_data()
|
||||
{
|
||||
// Repeating options
|
||||
@ -2056,8 +2021,7 @@ void TestTimeManager::initTimeManager()
|
||||
removeAllRules();
|
||||
enableNotifications({"Rules", "Devices", "Events"});
|
||||
NymeaCore::instance()->timeManager()->stopTimer();
|
||||
qDebug() << NymeaCore::instance()->timeManager()->currentTime().toString();
|
||||
qDebug() << NymeaCore::instance()->timeManager()->currentDate().toString();
|
||||
qDebug() << NymeaCore::instance()->timeManager()->currentDateTime().toString();
|
||||
}
|
||||
|
||||
void TestTimeManager::verifyRuleExecuted(const ActionTypeId &actionTypeId)
|
||||
|
||||
Reference in New Issue
Block a user