add timemanager

add evaluation of calendaritem
add pack/unpack methods
pull/135/head
Simon Stürz 2016-03-30 21:04:24 +02:00 committed by Michael Zanetti
parent 63703e8da0
commit 5f32c11810
18 changed files with 708 additions and 96 deletions

View File

@ -22,6 +22,7 @@
Q_LOGGING_CATEGORY(dcApplication, "Application")
Q_LOGGING_CATEGORY(dcDeviceManager, "DeviceManager")
Q_LOGGING_CATEGORY(dcTimeManager, "TimeManager")
Q_LOGGING_CATEGORY(dcRuleEngine, "RuleEngine")
Q_LOGGING_CATEGORY(dcHardware, "Hardware")
Q_LOGGING_CATEGORY(dcConnection, "Connection")

View File

@ -29,6 +29,7 @@
// Core / libguh
Q_DECLARE_LOGGING_CATEGORY(dcApplication)
Q_DECLARE_LOGGING_CATEGORY(dcDeviceManager)
Q_DECLARE_LOGGING_CATEGORY(dcTimeManager)
Q_DECLARE_LOGGING_CATEGORY(dcRuleEngine)
Q_DECLARE_LOGGING_CATEGORY(dcHardware)
Q_DECLARE_LOGGING_CATEGORY(dcConnection)

View File

@ -356,16 +356,18 @@ RuleEngine *GuhCore::ruleEngine() const
return m_ruleEngine;
}
TimeManager *GuhCore::timeManager() const
{
return m_timeManager;
}
/*! Constructs GuhCore with the given \a parent. This is private.
Use \l{GuhCore::instance()} to access the single instance.*/
GuhCore::GuhCore(QObject *parent) :
QObject(parent)
{
qCDebug(dcApplication) << "Creating centralized timer";
m_guhTimer = new QTimer(this);
m_guhTimer->setInterval(1000);
m_guhTimer->setSingleShot(false);
m_currentDateTime = QDateTime::currentDateTime();
qCDebug(dcApplication()) << "Creating Time Manager";
m_timeManager = new TimeManager(QTimeZone::systemTimeZoneId(), this);
qCDebug(dcApplication) << "Creating Log Engine";
m_logger = new LogEngine(this);
@ -394,10 +396,11 @@ GuhCore::GuhCore(QObject *parent) :
connect(m_ruleEngine, &RuleEngine::ruleRemoved, this, &GuhCore::ruleRemoved);
connect(m_ruleEngine, &RuleEngine::ruleConfigurationChanged, this, &GuhCore::ruleConfigurationChanged);
connect(m_guhTimer, &QTimer::timeout, this, &GuhCore::guhTimeout);
connect(m_timeManager, &TimeManager::timeChanged, this, &GuhCore::onTimeChanged);
connect(m_timeManager, &TimeManager::dateChanged, this, &GuhCore::onDateChanged);
connect(m_timeManager, &TimeManager::tick, m_deviceManager, &DeviceManager::timeTick);
m_logger->logSystemEvent(true);
m_guhTimer->start();
}
/*! Connected to the DeviceManager's emitEvent signal. Events received in
@ -458,21 +461,14 @@ void GuhCore::gotEvent(const Event &event)
executeRuleActions(actions);
}
void GuhCore::guhTimeout()
void GuhCore::onTimeChanged(const QTime &currentTime)
{
m_deviceManager->timeTick();
// TODO: evaluate special times
// Minute based time -> only evaluate time based rules if the minute changed
if (m_currentDateTime.time().minute() != QDateTime::currentDateTime().time().minute()) {
qCDebug(dcApplication) << "Guh time changed" << QDateTime::currentDateTime().time().toString("hh:mm:ss");
m_currentDateTime = QDateTime::currentDateTime();
// TODO: evaluate timeDescriptor based rules
}
qCDebug(dcTimeManager) << currentTime.toString("hh:mm");
}
void GuhCore::onDateChanged(const QDate &currentDate)
{
qCDebug(dcTimeManager) << currentDate.toString("dd.MM.yyyy");
}
/*! Return the instance of the log engine */

View File

@ -32,8 +32,9 @@
#include "ruleengine.h"
#include "servermanager.h"
#include "time/timemanager.h"
#include <QObject>
#include <QDateTime>
class Device;
@ -68,6 +69,7 @@ public:
RestServer *restServer() const;
DeviceManager *deviceManager() const;
RuleEngine *ruleEngine() const;
TimeManager *timeManager() const;
signals:
void eventTriggered(const Event &event);
@ -94,18 +96,15 @@ private:
ServerManager *m_serverManager;
DeviceManager *m_deviceManager;
RuleEngine *m_ruleEngine;
LogEngine *m_logger;
TimeManager *m_timeManager;
QHash<ActionId, Action> m_pendingActions;
QTimer *m_guhTimer;
QDateTime m_currentDateTime;
private slots:
void gotEvent(const Event &event);
void guhTimeout();
void onTimeChanged(const QTime &currentTime);
void onDateChanged(const QDate &currentDate);
void actionExecutionFinished(const ActionId &id, DeviceManager::DeviceError status);
};

View File

@ -43,6 +43,7 @@
\value Bool
\value Variant
\value Color
\value Time
\value Object
*/
@ -283,7 +284,25 @@ void JsonTypes::init()
s_logEntry.insert("o:eventType", loggingEventTypeRef());
s_logEntry.insert("o:errorCode", basicTypeToString(String));
// TimeDescriptor
s_timeDescriptor.insert("o:calendarItems", QVariantList() << calendarItemRef());
s_timeDescriptor.insert("o:timeEventItems", QVariantList() << timeEventItemRef());
// CalendarItem
s_calendarItem.insert("o:datetime", basicTypeToString(QVariant::UInt));
s_calendarItem.insert("o:startTime", basicTypeToString(QVariant::Time));
s_calendarItem.insert("duration", basicTypeToString(QVariant::UInt));
s_calendarItem.insert("o:repeating", repeatingOptionRef());
// TimeEventItem
s_timeEventItem.insert("o:datetime", basicTypeToString(QVariant::UInt));
s_timeEventItem.insert("o:time", basicTypeToString(QVariant::Time));
s_timeEventItem.insert("o:repeating", repeatingOptionRef());
// RepeatingOption
s_repeatingOption.insert("mode", repeatingModeRef());
s_repeatingOption.insert("o:weekDays", QVariantList() << basicTypeToString(Int));
s_repeatingOption.insert("o:monthDays", QVariantList() << basicTypeToString(Int));
s_initialized = true;
}
@ -792,6 +811,71 @@ QVariantList JsonTypes::packCreateMethods(DeviceClass::CreateMethods createMetho
return ret;
}
/*! Returns a variant map of the given \a option. */
QVariantMap JsonTypes::packRepeatingOption(const RepeatingOption &option)
{
QVariantMap optionVariant;
optionVariant.insert("mode", s_repeatingMode.at(option.mode()));
if (!option.weekDays().isEmpty())
optionVariant.insert("weekDays", QVariant::fromValue< QList<int> >(option.weekDays()));
if (!option.monthDays().isEmpty())
optionVariant.insert("monthDays", QVariant::fromValue< QList<int> >(option.monthDays()));
return optionVariant;
}
/*! Returns a variant map of the given \a calendarItem. */
QVariantMap JsonTypes::packCalendarItem(const CalendarItem &calendarItem)
{
QVariantMap calendarItemVariant;
calendarItemVariant.insert("duration", calendarItem.duration());
if (!calendarItem.startTime().isNull())
calendarItemVariant.insert("startTime", calendarItem.startTime().toString("hh:mm"));
if (!calendarItem.dateTime().isNull())
calendarItemVariant.insert("datetime", calendarItem.dateTime().toTime_t());
if (!calendarItem.repeatingOption().isEmtpy())
calendarItemVariant.insert("repeating", packRepeatingOption(calendarItem.repeatingOption()));
return calendarItemVariant;
}
QVariantMap JsonTypes::packTimeEventItem(const TimeEventItem &timeEventItem)
{
QVariantMap timeEventItemVariant;
if (!timeEventItem.dateTime().isNull())
timeEventItemVariant.insert("datetime", timeEventItem.dateTime().toTime_t());
if (!timeEventItem.time().isNull())
timeEventItemVariant.insert("time", timeEventItem.time().toString("hh:mm"));
if (!timeEventItem.repatingOption().isEmtpy())
timeEventItemVariant.insert("repeating", packRepeatingOption(timeEventItem.repatingOption()));
return timeEventItemVariant;
}
/*! Returns a variant map of the given \a timeDescriptor. */
QVariantMap JsonTypes::packTimeDescriptor(const TimeDescriptor &timeDescriptor)
{
QVariantMap timeDescriptorVariant;
if (!timeDescriptor.calendarItems().isEmpty()) {
QVariantList calendarItems;
foreach (const CalendarItem &calendarItem, timeDescriptor.calendarItems()) {
calendarItems.append(packCalendarItem(calendarItem));
}
}
// TODO: TimeEventItems
return timeDescriptorVariant;
}
/*! Returns a variant list of the supported vendors. */
QVariantList JsonTypes::packSupportedVendors()
{
@ -1103,6 +1187,76 @@ LogFilter JsonTypes::unpackLogFilter(const QVariantMap &logFilterMap)
return filter;
}
/*! Returns a \l{RepeatingOption} created from the given \a repeatingOptionMap. */
RepeatingOption JsonTypes::unpackRepeatingOption(const QVariantMap &repeatingOptionMap)
{
RepeatingOption::RepeatingMode mode = (RepeatingOption::RepeatingMode)s_repeatingMode.indexOf(repeatingOptionMap.value("mode").toString());
QList<int> weekDays;
if (repeatingOptionMap.contains("weekDays")) {
foreach (const QVariant weekDayVariant, repeatingOptionMap.value("weekDays").toList()) {
weekDays.append(weekDayVariant.toInt());
}
}
QList<int> monthDays;
if (repeatingOptionMap.contains("monthDays")) {
foreach (const QVariant monthDayVariant, repeatingOptionMap.value("monthDays").toList()) {
monthDays.append(monthDayVariant.toInt());
}
}
return RepeatingOption(mode, weekDays, monthDays);
}
/*! Returns a \l{CalendarItem} created from the given \a calendarItemMap. */
CalendarItem JsonTypes::unpackCalendarItem(const QVariantMap &calendarItemMap)
{
CalendarItem calendarItem;
if (calendarItemMap.contains("datetime"))
calendarItem.setDateTime(QDateTime::fromTime_t(calendarItemMap.value("datetime").toUInt()));
if (calendarItemMap.contains("startTime"))
calendarItem.setStartTime(calendarItemMap.value("startTime").toTime());
if (calendarItemMap.contains("repeating"))
calendarItem.setRepeatingOption(unpackRepeatingOption(calendarItemMap.value("repeating").toMap()));
return calendarItem;
}
TimeEventItem JsonTypes::unpackTimeEventItem(const QVariantMap &timeEventItemMap)
{
TimeEventItem timeEventItem;
if (timeEventItemMap.contains("datetime"))
timeEventItem.setDateTime(timeEventItemMap.value("datetime").toUInt());
if (timeEventItemMap.contains("time"))
timeEventItem.setTime(timeEventItemMap.value("time").toTime());
if (timeEventItemMap.contains("repeating"))
timeEventItem.setRepeatingOption(unpackRepeatingOption(timeEventItemMap.value("repeating").toMap()));
return timeEventItem;
}
TimeDescriptor JsonTypes::unpackTimeDescriptor(const QVariantMap &timeDescriptorMap)
{
TimeDescriptor timeDescriptor;
if (timeDescriptorMap.contains("calendarItems")) {
QList<CalendarItem> calendarItems;
foreach (const QVariant &calendarItemValiant, timeDescriptorMap.value("calendarItems").toList()) {
calendarItems.append(unpackCalendarItem(calendarItemValiant.toMap()));
}
timeDescriptor.setCalendarItems(calendarItems);
}
return timeDescriptor;
}
/*! Compairs the given \a map with the given \a templateMap. Returns the error string and false if
the params are not valid. */
QPair<bool, QString> JsonTypes::validateMap(const QVariantMap &templateMap, const QVariantMap &map)

View File

@ -171,12 +171,17 @@ public:
static QVariantMap packDevice(Device *device);
static QVariantMap packDeviceDescriptor(const DeviceDescriptor &descriptor);
static QVariantMap packRule(const Rule &rule);
static QVariantList packRules(const QList<Rule> rules);
static QVariantMap packRuleDescription(const Rule &rule);
static QVariantMap packLogEntry(const LogEntry &logEntry);
static QVariantList packCreateMethods(DeviceClass::CreateMethods createMethods);
static QVariantMap packRepeatingOption(const RepeatingOption &option);
static QVariantMap packCalendarItem(const CalendarItem &calendarItem);
static QVariantMap packTimeEventItem(const TimeEventItem &timeEventItem);
static QVariantMap packTimeDescriptor(const TimeDescriptor &timeDescriptor);
// pack resources
static QVariantList packRules(const QList<Rule> rules);
static QVariantList packCreateMethods(DeviceClass::CreateMethods createMethods);
static QVariantList packSupportedVendors();
static QVariantList packSupportedDevices(const VendorId &vendorId);
static QVariantList packConfiguredDevices();
@ -204,6 +209,10 @@ public:
static StateEvaluator unpackStateEvaluator(const QVariantMap &stateEvaluatorMap);
static StateDescriptor unpackStateDescriptor(const QVariantMap &stateDescriptorMap);
static LogFilter unpackLogFilter(const QVariantMap &logFilterMap);
static RepeatingOption unpackRepeatingOption(const QVariantMap &repeatingOptionMap);
static CalendarItem unpackCalendarItem(const QVariantMap &calendarItemMap);
static TimeEventItem unpackTimeEventItem(const QVariantMap &timeEventItemMap);
static TimeDescriptor unpackTimeDescriptor(const QVariantMap &timeDescriptorMap);
// validate
static QPair<bool, QString> validateMap(const QVariantMap &templateMap, const QVariantMap &map);

View File

@ -117,7 +117,7 @@ int main(int argc, char *argv[])
s_loggingFilters.insert("JsonRpc", true);
s_loggingFilters.insert("Rest", true);
s_loggingFilters.insert("OAuth2", false);
s_loggingFilters.insert("Coap", false);
s_loggingFilters.insert("TimeManager", false);
QHash<QString, bool> loggingFiltersPlugins;
foreach (const QJsonObject &pluginMetadata, DeviceManager::pluginsMetadata()) {

View File

@ -1,46 +1,13 @@
# check websocket support
contains(DEFINES, WEBSOCKET){
QT += websockets
SOURCES += $$top_srcdir/server/websocketserver.cpp
HEADERS += $$top_srcdir/server/websocketserver.h
SOURCES += $$top_srcdir/server/websocketserver.cpp
}
RESOURCES += $$top_srcdir/icons.qrc
SOURCES += $$top_srcdir/server/guhcore.cpp \
$$top_srcdir/server/tcpserver.cpp \
$$top_srcdir/server/ruleengine.cpp \
$$top_srcdir/server/rule.cpp \
$$top_srcdir/server/jsonrpc/jsonrpcserver.cpp \
$$top_srcdir/server/jsonrpc/jsonhandler.cpp \
$$top_srcdir/server/jsonrpc/devicehandler.cpp \
$$top_srcdir/server/jsonrpc/jsontypes.cpp \
$$top_srcdir/server/jsonrpc/ruleshandler.cpp \
$$top_srcdir/server/jsonrpc/actionhandler.cpp \
$$top_srcdir/server/jsonrpc/eventhandler.cpp \
$$top_srcdir/server/jsonrpc/statehandler.cpp \
$$top_srcdir/server/jsonrpc/logginghandler.cpp \
$$top_srcdir/server/stateevaluator.cpp \
$$top_srcdir/server/logging/logengine.cpp \
$$top_srcdir/server/logging/logfilter.cpp \
$$top_srcdir/server/logging/logentry.cpp \
$$top_srcdir/server/webserver.cpp \
$$top_srcdir/server/transportinterface.cpp \
$$top_srcdir/server/servermanager.cpp \
$$top_srcdir/server/httprequest.cpp \
$$top_srcdir/server/httpreply.cpp \
$$top_srcdir/server/rest/restserver.cpp \
$$top_srcdir/server/rest/restresource.cpp \
$$top_srcdir/server/rest/devicesresource.cpp \
$$top_srcdir/server/rest/deviceclassesresource.cpp \
$$top_srcdir/server/rest/vendorsresource.cpp \
$$top_srcdir/server/rest/logsresource.cpp \
$$top_srcdir/server/rest/pluginsresource.cpp \
$$top_srcdir/server/rest/rulesresource.cpp \
$$top_srcdir/server/time/timedescriptor.cpp \
$$top_srcdir/server/time/calendaritem.cpp \
$$top_srcdir/server/time/repeatingoption.cpp \
$$top_srcdir/server/time/timeeventitem.cpp \
# icons for the webserver
RESOURCES += $$top_srcdir/icons.qrc
HEADERS += $$top_srcdir/server/guhcore.h \
@ -78,5 +45,41 @@ HEADERS += $$top_srcdir/server/guhcore.h \
$$top_srcdir/server/time/calendaritem.h \
$$top_srcdir/server/time/repeatingoption.h \
$$top_srcdir/server/time/timeeventitem.h \
$$top_srcdir/server/time/timemanager.h
SOURCES += $$top_srcdir/server/guhcore.cpp \
$$top_srcdir/server/tcpserver.cpp \
$$top_srcdir/server/ruleengine.cpp \
$$top_srcdir/server/rule.cpp \
$$top_srcdir/server/jsonrpc/jsonrpcserver.cpp \
$$top_srcdir/server/jsonrpc/jsonhandler.cpp \
$$top_srcdir/server/jsonrpc/devicehandler.cpp \
$$top_srcdir/server/jsonrpc/jsontypes.cpp \
$$top_srcdir/server/jsonrpc/ruleshandler.cpp \
$$top_srcdir/server/jsonrpc/actionhandler.cpp \
$$top_srcdir/server/jsonrpc/eventhandler.cpp \
$$top_srcdir/server/jsonrpc/statehandler.cpp \
$$top_srcdir/server/jsonrpc/logginghandler.cpp \
$$top_srcdir/server/stateevaluator.cpp \
$$top_srcdir/server/logging/logengine.cpp \
$$top_srcdir/server/logging/logfilter.cpp \
$$top_srcdir/server/logging/logentry.cpp \
$$top_srcdir/server/webserver.cpp \
$$top_srcdir/server/transportinterface.cpp \
$$top_srcdir/server/servermanager.cpp \
$$top_srcdir/server/httprequest.cpp \
$$top_srcdir/server/httpreply.cpp \
$$top_srcdir/server/rest/restserver.cpp \
$$top_srcdir/server/rest/restresource.cpp \
$$top_srcdir/server/rest/devicesresource.cpp \
$$top_srcdir/server/rest/deviceclassesresource.cpp \
$$top_srcdir/server/rest/vendorsresource.cpp \
$$top_srcdir/server/rest/logsresource.cpp \
$$top_srcdir/server/rest/pluginsresource.cpp \
$$top_srcdir/server/rest/rulesresource.cpp \
$$top_srcdir/server/time/timedescriptor.cpp \
$$top_srcdir/server/time/calendaritem.cpp \
$$top_srcdir/server/time/repeatingoption.cpp \
$$top_srcdir/server/time/timeeventitem.cpp \
$$top_srcdir/server/time/timemanager.cpp

View File

@ -32,54 +32,183 @@
namespace guhserver {
/*! Construct a invalid \l{CalendarItem}.*/
CalendarItem::CalendarItem()
/*! Construct a invalid \l{CalendarItem}. */
CalendarItem::CalendarItem():
m_duration(0)
{
}
/*! Construct a \l{CalendarItem} with the given \a startTime, \a duration and \a repeatingOption.*/
CalendarItem::CalendarItem(const QTime &startTime, const QTime &duration, const RepeatingOption &repeatingOption) :
m_startTime(startTime),
m_duration(duration),
m_repeatingOption(repeatingOption)
/*! Returns the date time of this \l{CalendarItem}. */
QDateTime CalendarItem::dateTime() const
{
return m_dateTime;
}
/*! Returns the start time of this \l{CalendarItem}.*/
/*! Sets the \a dateTime of this \l{CalendarItem}. */
void CalendarItem::setDateTime(const QDateTime &dateTime)
{
m_dateTime = dateTime;
}
/*! Returns the start time of this \l{CalendarItem}. */
QTime CalendarItem::startTime() const
{
return m_startTime;
}
/*! Returns the duratiorn of this \l{CalendarItem}.*/
QTime CalendarItem::duration() const
/*! Sets the \a startTime of this \l{CalendarItem}. */
void CalendarItem::setStartTime(const QTime &startTime)
{
m_startTime = startTime;
}
/*! Returns the duratiorn of this \l{CalendarItem}. */
uint CalendarItem::duration() const
{
return m_duration;
}
/*! Returns the \l{RepeatingOption} of this \l{CalendarItem}.*/
/*! Sets the \a duration of this \l{CalendarItem}. */
void CalendarItem::setDuration(const uint &duration)
{
m_duration = duration;
}
/*! Returns the \l{RepeatingOption} of this \l{CalendarItem}. */
RepeatingOption CalendarItem::repeatingOption() const
{
return m_repeatingOption;
}
/*! Returns true if this \l{CalendarItem} is valid. A \l{CalendarItem} is valid if the start time and the duration are set.*/
bool CalendarItem::isValid() const
/*! Sets the \a repeatingOption of this \l{CalendarItem}. */
void CalendarItem::setRepeatingOption(const RepeatingOption &repeatingOption)
{
return !m_startTime.isNull() && !m_duration.isNull();
m_repeatingOption = repeatingOption;
}
/*! Returns true, if the given \a dateTime matches this \l{CalendarItem}.*/
/*! Returns true if this \l{CalendarItem} is valid. A \l{CalendarItem} is invalid
if start time and datetime are set or if the duration is 0.
*/
bool CalendarItem::isValid() const
{
return (!m_startTime.isNull() != !m_dateTime.isNull()) && m_duration > 0;
}
/*! Returns true, if the given \a dateTime matches this \l{CalendarItem}. */
bool CalendarItem::evaluate(const QDateTime &dateTime) const
{
Q_UNUSED(dateTime)
if (!isValid())
return false;
// TODO: evaluate the calendar item, return true if the current time matches the calendar item, otherwise false
if (!repeatingOption().isValid())
return false;
switch (repeatingOption().mode()) {
case RepeatingOption::RepeatingModeNone:
// If there is no repeating option, we assume it is meant daily.
return evaluateDaily(dateTime);
case RepeatingOption::RepeatingModeHourly:
return evaluateHourly(dateTime);
case RepeatingOption::RepeatingModeDaily:
return evaluateDaily(dateTime);
case RepeatingOption::RepeatingModeWeekly:
return evaluateWeekly(dateTime);
case RepeatingOption::RepeatingModeMonthly:
return evaluateMonthly(dateTime);
default:
return false;
}
}
bool CalendarItem::evaluateHourly(const QDateTime &dateTime) const
{
// check if
if (startTime().isNull()) {
}
QDateTime startDateTime = QDateTime(dateTime.date(), QTime(dateTime.time().hour(), startTime().minute()));
QDateTime endDateTime = startDateTime.addSecs(duration() * 60);
bool timeValid = dateTime >= startDateTime && dateTime < endDateTime;
bool weekdayValid = repeatingOption().evaluateWeekDay(dateTime);
bool monthdayValid = repeatingOption().evaluateMonthDay(dateTime);
return timeValid && weekdayValid && monthdayValid;
}
bool CalendarItem::evaluateDaily(const QDateTime &dateTime) const
{
// If the duration is longer than a day, this calendar item is always true
// 1 day has 1440 minutes
if (duration() >= 1440)
return true;
QDateTime startDateTime = QDateTime(dateTime.date(), startTime());
QDateTime endDateTime = startDateTime.addSecs(duration() * 60);
bool timeValid = false;
if (startDateTime.date() == endDateTime.date()) {
timeValid = dateTime >= startDateTime && dateTime < endDateTime;
} else {
// If the time duration changes the date,
// check only if the time is smaler than the overlapping time
timeValid = dateTime.time() < endDateTime.time();
}
return timeValid;
}
bool CalendarItem::evaluateWeekly(const QDateTime &dateTime) const
{
// If the duration is longer than a week, this calendar item is always true
// 1 week has 10080 minutes
if (duration() >= 10080)
return true;
// get the first day of this week with the correct start time
QDateTime weekStartDateTime = dateTime.addDays(-dateTime.date().dayOfWeek());
weekStartDateTime.setTime(m_startTime);
// Check each week day in the list
foreach (const int &weekDay, repeatingOption().weekDays()) {
QDateTime startDateTime = weekStartDateTime.addDays(weekDay -1);
QDateTime endDateTime = startDateTime.addSecs(duration() * 60);
bool overlapping = false;
// Check if this calendar item overlaps a week
if (startDateTime.date().weekNumber() != endDateTime.date().weekNumber())
overlapping = true;
if (overlapping) {
// Jump one week into the past
QDateTime startPreviouseDateTime = startDateTime.addDays(-7);
QDateTime endPreviouseDateTime = startPreviouseDateTime.addSecs(duration() * 60);
if (dateTime >= startPreviouseDateTime && dateTime < endPreviouseDateTime)
// return true if the current time is between start
// and end of this calendar item from the previouse week
return true;
} else if (dateTime >= startDateTime && dateTime < endDateTime) {
// return true if the current time is between start
// and end of this calendar item
return true;
}
}
return false;
}
bool CalendarItem::evaluateMonthly(const QDateTime &dateTime) const
{
Q_UNUSED(dateTime)
return false;
}
}

View File

@ -31,22 +31,34 @@ class CalendarItem
{
public:
CalendarItem();
CalendarItem(const QTime &startTime, const QTime &duration, const RepeatingOption &repeatingOption);
QDateTime dateTime() const;
void setDateTime(const QDateTime &dateTime);
QTime startTime() const;
QTime duration() const;
void setStartTime(const QTime &startTime);
uint duration() const;
void setDuration(const uint &duration);
RepeatingOption repeatingOption() const;
void setRepeatingOption(const RepeatingOption &repeatingOption);
bool isValid() const;
bool evaluate(const QDateTime &dateTime) const;
private:
QDateTime m_dateTime;
QTime m_startTime;
QTime m_duration;
QTime m_endTime;
uint m_duration;
RepeatingOption m_repeatingOption;
bool evaluateHourly(const QDateTime &dateTime) const;
bool evaluateDaily(const QDateTime &dateTime) const;
bool evaluateWeekly(const QDateTime &dateTime) const;
bool evaluateMonthly(const QDateTime &dateTime) const;
};
}

View File

@ -20,25 +20,76 @@
/*!
\class guhserver::RepeatingOption
\brief Describes a clendar item for a time based \l{guhserver::Rule}{Rule}.
\brief Describes the repeating option of a time item.
\ingroup rules
\inmodule core
The list of \l{weekDays()} can contain following values:
\table
\header
\li Weekday
\li int
\row
\li Monday
\li 1
\row
\li Tuesday
\li 2
\row
\li Wednesday
\li 3
\row
\li Thursday
\li 4
\row
\li Friday
\li 5
\row
\li Saturday
\li 6
\row
\li Sunday
\li 7
\endtable
\sa Rule, TimeDescriptor
*/
/*! \enum guhserver::RepeatingOption::RepeatingMode
This enum type specifies the mode of a \l{RepeatingOption}.
\value RepeatingModeNone
There is no special repeating mode. The \l{RuleEngine} will assume a daily repeating.
\value RepeatingModeHourly
The time item should be repeated hourly.
\value RepeatingModeDaily
The time item should be repeated daily.
\value RepeatingModeWeekly
The time item should be repeated weekly. A week starts at Monday. This mode needs a list of \l{weekDays()}.
The \l{monthDays()} list will be ignored.
\value RepeatingModeMonthly
The time item should be repeated monthly. This mode needs a list of \l{monthDays()}.
The \l{monthDays()} list will be ignored.
*/
#include "repeatingoption.h"
#include <QDateTime>
namespace guhserver {
/*! Constructs an empty \l{RepeatingOption}. */
RepeatingOption::RepeatingOption() :
m_mode(RepeatingModeNone)
{
}
/*! Constructs a \l{RepeatingOption} with the given \a mode, \a weekDays list and \a monthDays list. */
RepeatingOption::RepeatingOption(const RepeatingMode &mode, const QList<int> &weekDays, const QList<int> &monthDays) :
m_mode(mode),
m_weekDays(weekDays),
@ -47,24 +98,83 @@ RepeatingOption::RepeatingOption(const RepeatingMode &mode, const QList<int> &we
}
/*! Returns the mode of this \l{RepeatingOption}. */
RepeatingOption::RepeatingMode RepeatingOption::mode() const
{
return m_mode;
}
/*! Returns the list of week days on which this \l{RepeatingOption} should be valid. */
QList<int> RepeatingOption::weekDays() const
{
return m_weekDays;
}
/*! Returns the list of month days on which this \l{RepeatingOption} should be valid. */
QList<int> RepeatingOption::monthDays() const
{
return m_monthDays;
}
/*! Clears this RepeatingOption */
void RepeatingOption::clear()
{
m_mode = RepeatingModeNone;
m_weekDays.clear();
m_monthDays.clear();
}
/*! Returns true if this \l{RepeatingOption} is empty. */
bool RepeatingOption::isEmtpy() const
{
return m_mode == RepeatingModeNone && m_weekDays.isEmpty() && m_monthDays.isEmpty();
}
/*! Returns true if this \l{RepeatingOption} is valid. */
bool RepeatingOption::isValid() const
{
switch (m_mode) {
case RepeatingModeNone:
return m_weekDays.isEmpty() && m_monthDays.isEmpty();
case RepeatingModeHourly:
return m_weekDays.isEmpty() && m_monthDays.isEmpty();
case RepeatingModeDaily:
return m_weekDays.isEmpty() && m_monthDays.isEmpty();
case RepeatingModeWeekly:
return !m_weekDays.isEmpty() && m_monthDays.isEmpty();
case RepeatingModeMonthly:
return m_weekDays.isEmpty() && !m_monthDays.isEmpty();
default:
return false;
}
}
/*! Returns true if the week day of the given \a dateTime matches this \l{RepeatingOption}. */
bool RepeatingOption::evaluateWeekDay(const QDateTime &dateTime) const
{
// If there is no weekday specified it's always true
if (m_weekDays.isEmpty())
return true;
// Check if dateTime week day matches one of the specified week days
if (m_weekDays.contains(dateTime.date().dayOfWeek()))
return true;
return false;
}
/*! Returns true if the month day of the given \a dateTime matches this \l{RepeatingOption}. */
bool RepeatingOption::evaluateMonthDay(const QDateTime &dateTime) const
{
// If there is no month days specified it's always true
if (m_monthDays.isEmpty())
return true;
// Check if dateTime month day matches one of the specified month days
if (m_monthDays.contains(dateTime.date().day()))
return true;
return false;
}
}

View File

@ -24,6 +24,8 @@
#include <QList>
#include <QMetaType>
class QDateTime;
namespace guhserver {
class RepeatingOption
@ -48,7 +50,12 @@ public:
QList<int> weekDays() const;
QList<int> monthDays() const;
void clear();
bool isEmtpy() const;
bool isValid() const;
bool evaluateWeekDay(const QDateTime &dateTime) const;
bool evaluateMonthDay(const QDateTime &dateTime) const;
private:
RepeatingMode m_mode;

View File

@ -70,7 +70,24 @@ void TimeDescriptor::setCalendarItems(const QList<CalendarItem> &calendarItems)
/*! Returns true if either the calendarItems list is not empty or the timeEventItems list.*/
bool TimeDescriptor::isValid() const
{
return !m_timeEventItems.isEmpty() || !m_calendarItems.isEmpty();
return !m_timeEventItems.isEmpty() && !m_calendarItems.isEmpty();
}
/*! Returns true if the calendarItems list and the timeEventItems list is empty.*/
bool TimeDescriptor::isEmpty() const
{
return m_calendarItems.isEmpty() && m_timeEventItems.isEmpty();
}
/*! Returns true if this \l{TimeDescriptor} is valid for the given \a dateTime. A \l{TimeDescriptor} is
valid if the \l{TimeEventItem}{TimeEventItems} or \l{CalendarItem}{CalendarItems} match
the given \a dateTime.
*/
bool TimeDescriptor::evaluate(const QDateTime &dateTime) const
{
Q_UNUSED(dateTime)
return false;
}
}

View File

@ -38,10 +38,14 @@ public:
void setCalendarItems(const QList<CalendarItem> &calendarItems);
bool isValid() const;
bool isEmpty() const;
bool evaluate(const QDateTime &dateTime) const;
private:
QList<TimeEventItem> m_timeEventItems;
QList<CalendarItem> m_calendarItems;
};
}

View File

@ -32,7 +32,7 @@ QDateTime TimeEventItem::dateTime() const
return m_dateTimer;
}
void TimeEventItem::setDateTimer(const int &timeStamp)
void TimeEventItem::setDateTime(const int &timeStamp)
{
m_dateTimer = QDateTime::fromTime_t(timeStamp);
}
@ -42,7 +42,7 @@ QTime TimeEventItem::time() const
return m_time;
}
void TimeEventItem::setTimer(const QTime &time)
void TimeEventItem::setTime(const QTime &time)
{
m_time = time;
}
@ -62,4 +62,13 @@ bool TimeEventItem::isValid() const
return !m_dateTimer.isNull() || !m_time.isNull();
}
bool TimeEventItem::evaluate(const QDateTime &dateTime) const
{
Q_UNUSED(dateTime)
// TODO: evaluate the calendar item, return true if the current time matches the calendar item, otherwise false
return false;
}
}

View File

@ -33,10 +33,10 @@ public:
TimeEventItem();
QDateTime dateTime() const;
void setDateTimer(const int &timeStamp);
void setDateTime(const int &timeStamp);
QTime time() const;
void setTimer(const QTime &time);
void setTime(const QTime &time);
RepeatingOption repatingOption() const;
void setRepeatingOption(const RepeatingOption &repeatingOption);
@ -45,6 +45,8 @@ public:
bool isValid() const;
bool evaluate(const QDateTime &dateTime) const;
private:
QDateTime m_dateTimer;
QTime m_time;

View File

@ -0,0 +1,97 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stuerz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "timemanager.h"
#include "loggingcategories.h"
namespace guhserver {
TimeManager::TimeManager(const QByteArray &timeZone, QObject *parent) :
QObject(parent)
{
m_dateTime = QDateTime::currentDateTimeUtc();
m_dateTime.setTimeSpec(Qt::UTC);
qCDebug(dcTimeManager()) << "UTC" << m_dateTime.toString("dd.MM.yyyy hh:mm:ss");
setTimeZone(timeZone);
qCDebug(dcTimeManager) << m_dateTime.toTimeZone(m_timeZone).toString("dd.MM.yyyy hh:mm:ss");
m_guhTimer = new QTimer(this);
m_guhTimer->setInterval(1000);
m_guhTimer->setSingleShot(false);
connect(m_guhTimer, &QTimer::timeout, this, &TimeManager::guhTimeout);
m_guhTimer->start();
}
QByteArray TimeManager::timeZone() const
{
return m_timeZone.id();
}
void TimeManager::setTimeZone(const QByteArray &timeZone)
{
if (!QTimeZone(timeZone).isValid()) {
qCWarning(dcTimeManager()) << "Invalid time zone" << timeZone;
qCWarning(dcTimeManager()) << "Using default system timezone" << QTimeZone::systemTimeZoneId();
m_timeZone = QTimeZone(QTimeZone::systemTimeZoneId());
} else {
qCDebug(dcTimeManager()) << "Set time zone" << timeZone;
m_timeZone = QTimeZone(timeZone);
}
}
QDateTime TimeManager::currentDateTime() const
{
return QDateTime::currentDateTimeUtc().toTimeZone(m_timeZone);
}
QTime TimeManager::currentTime() const
{
return QDateTime::currentDateTimeUtc().toTimeZone(m_timeZone).time();
}
QDate TimeManager::currentDate() const
{
return QDateTime::currentDateTimeUtc().toTimeZone(m_timeZone).date();
}
void TimeManager::guhTimeout()
{
// tick for deviceManager
emit tick();
QDateTime currentDateTime = QDateTime::currentDateTimeUtc();
//qCDebug(dcTimeManager) << "Time changed" << currentDateTime.toTimeZone(m_timeZone).time().toString("hh:mm:ss");
// Minute based guh time
if (m_dateTime.time().minute() != currentDateTime.toTimeZone(m_timeZone).time().minute()) {
m_dateTime = currentDateTime;
emit timeChanged(m_dateTime.toTimeZone(m_timeZone).time());
}
// check if day changed
if (m_dateTime.date() != currentDateTime.toTimeZone(m_timeZone).date()) {
emit dateChanged(m_dateTime.toTimeZone(m_timeZone).date());
}
}
}

62
server/time/timemanager.h Normal file
View File

@ -0,0 +1,62 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stuerz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef TIMEMANAGER_H
#define TIMEMANAGER_H
#include <QTimer>
#include <QObject>
#include <QDateTime>
#include <QTimeZone>
namespace guhserver {
class TimeManager : public QObject
{
Q_OBJECT
public:
explicit TimeManager(const QByteArray &timeZone, QObject *parent = 0);
QByteArray timeZone() const;
void setTimeZone(const QByteArray &timeZone = QTimeZone::systemTimeZoneId());
QDateTime currentDateTime() const;
QTime currentTime() const;
QDate currentDate() const;
private:
QTimeZone m_timeZone;
QDateTime m_dateTime;
QTimer *m_guhTimer;
signals:
void tick();
void dateChanged(const QDate &currentDate);
void timeChanged(const QTime &currentTime);
private slots:
void guhTimeout();
};
}
#endif // TIMEMANAGER_H