add missing docs
first working calendarItem
This commit is contained in:
parent
76cc3577e1
commit
e5d9823c2b
@ -397,8 +397,7 @@ GuhCore::GuhCore(QObject *parent) :
|
|||||||
connect(m_ruleEngine, &RuleEngine::ruleRemoved, this, &GuhCore::ruleRemoved);
|
connect(m_ruleEngine, &RuleEngine::ruleRemoved, this, &GuhCore::ruleRemoved);
|
||||||
connect(m_ruleEngine, &RuleEngine::ruleConfigurationChanged, this, &GuhCore::ruleConfigurationChanged);
|
connect(m_ruleEngine, &RuleEngine::ruleConfigurationChanged, this, &GuhCore::ruleConfigurationChanged);
|
||||||
|
|
||||||
connect(m_timeManager, &TimeManager::timeChanged, this, &GuhCore::onTimeChanged);
|
connect(m_timeManager, &TimeManager::dateTimeChanged, this, &GuhCore::onDateTimeChanged);
|
||||||
connect(m_timeManager, &TimeManager::dateChanged, this, &GuhCore::onDateChanged);
|
|
||||||
connect(m_timeManager, &TimeManager::tick, m_deviceManager, &DeviceManager::timeTick);
|
connect(m_timeManager, &TimeManager::tick, m_deviceManager, &DeviceManager::timeTick);
|
||||||
|
|
||||||
m_logger->logSystemEvent(true);
|
m_logger->logSystemEvent(true);
|
||||||
@ -462,14 +461,30 @@ void GuhCore::gotEvent(const Event &event)
|
|||||||
executeRuleActions(actions);
|
executeRuleActions(actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuhCore::onTimeChanged(const QTime ¤tTime)
|
void GuhCore::onDateTimeChanged(const QDateTime &dateTime)
|
||||||
{
|
{
|
||||||
qCDebug(dcTimeManager) << currentTime.toString("hh:mm");
|
qCDebug(dcTimeManager) << dateTime.toString("dd.MM.yyyy hh:mm");
|
||||||
}
|
|
||||||
|
|
||||||
void GuhCore::onDateChanged(const QDate ¤tDate)
|
QList<RuleAction> actions;
|
||||||
{
|
foreach (const Rule &rule, m_ruleEngine->evaluateTime(dateTime)) {
|
||||||
qCDebug(dcTimeManager) << currentDate.toString("dd.MM.yyyy");
|
// TimeEvent based
|
||||||
|
if (!rule.timeDescriptor().timeEventItems().isEmpty()) {
|
||||||
|
m_logger->logRuleTriggered(rule);
|
||||||
|
foreach (const RuleAction &action, rule.actions()) {
|
||||||
|
actions.append(action);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Calendar based rule
|
||||||
|
m_logger->logRuleActiveChanged(rule);
|
||||||
|
emit ruleActiveChanged(rule);
|
||||||
|
if (rule.active()) {
|
||||||
|
actions.append(rule.actions());
|
||||||
|
} else {
|
||||||
|
actions.append(rule.exitActions());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
executeRuleActions(actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Return the instance of the log engine */
|
/*! Return the instance of the log engine */
|
||||||
|
|||||||
@ -103,8 +103,7 @@ private:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void gotEvent(const Event &event);
|
void gotEvent(const Event &event);
|
||||||
void onTimeChanged(const QTime ¤tTime);
|
void onDateTimeChanged(const QDateTime &dateTime);
|
||||||
void onDateChanged(const QDate ¤tDate);
|
|
||||||
void actionExecutionFinished(const ActionId &id, DeviceManager::DeviceError status);
|
void actionExecutionFinished(const ActionId &id, DeviceManager::DeviceError status);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1067,6 +1067,7 @@ ParamList JsonTypes::unpackParams(const QVariantList ¶mList)
|
|||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Returns a \l{Rule} created from the given \a ruleMap. */
|
||||||
Rule JsonTypes::unpackRule(const QVariantMap &ruleMap)
|
Rule JsonTypes::unpackRule(const QVariantMap &ruleMap)
|
||||||
{
|
{
|
||||||
// The rule id will only be valid if unpacking for edit
|
// The rule id will only be valid if unpacking for edit
|
||||||
@ -1121,6 +1122,7 @@ Rule JsonTypes::unpackRule(const QVariantMap &ruleMap)
|
|||||||
return rule;
|
return rule;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Returns a \l{RuleAction} created from the given \a ruleActionMap. */
|
||||||
RuleAction JsonTypes::unpackRuleAction(const QVariantMap &ruleActionMap)
|
RuleAction JsonTypes::unpackRuleAction(const QVariantMap &ruleActionMap)
|
||||||
{
|
{
|
||||||
RuleAction action(ActionTypeId(ruleActionMap.value("actionTypeId").toString()), DeviceId(ruleActionMap.value("deviceId").toString()));
|
RuleAction action(ActionTypeId(ruleActionMap.value("actionTypeId").toString()), DeviceId(ruleActionMap.value("deviceId").toString()));
|
||||||
|
|||||||
@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
namespace guhserver {
|
namespace guhserver {
|
||||||
|
|
||||||
/*! Constructs an empty, invalid rule. */
|
/*! Constructs an empty, invalid \l{Rule}. */
|
||||||
Rule::Rule():
|
Rule::Rule():
|
||||||
m_id(RuleId()),
|
m_id(RuleId()),
|
||||||
m_name(QString()),
|
m_name(QString()),
|
||||||
@ -55,12 +55,13 @@ Rule::Rule():
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Returns the id of this Rule. */
|
/*! Returns the id of this \l{Rule}. */
|
||||||
RuleId Rule::id() const
|
RuleId Rule::id() const
|
||||||
{
|
{
|
||||||
return m_id;
|
return m_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Sets the \a ruleId of this \l{Rule}. */
|
||||||
void Rule::setId(const RuleId &ruleId)
|
void Rule::setId(const RuleId &ruleId)
|
||||||
{
|
{
|
||||||
m_id = ruleId;
|
m_id = ruleId;
|
||||||
@ -72,6 +73,7 @@ QString Rule::name() const
|
|||||||
return m_name;
|
return m_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Sets the \a name of this \l{Rule}. */
|
||||||
void Rule::setName(const QString &name)
|
void Rule::setName(const QString &name)
|
||||||
{
|
{
|
||||||
m_name = name;
|
m_name = name;
|
||||||
@ -89,6 +91,7 @@ TimeDescriptor Rule::timeDescriptor() const
|
|||||||
return m_timeDescriptor;
|
return m_timeDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Sets the \a timeDescriptor of this \l{Rule}. */
|
||||||
void Rule::setTimeDescriptor(const TimeDescriptor &timeDescriptor)
|
void Rule::setTimeDescriptor(const TimeDescriptor &timeDescriptor)
|
||||||
{
|
{
|
||||||
m_timeDescriptor = timeDescriptor;
|
m_timeDescriptor = timeDescriptor;
|
||||||
@ -100,6 +103,7 @@ StateEvaluator Rule::stateEvaluator() const
|
|||||||
return m_stateEvaluator;
|
return m_stateEvaluator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Sets the \a stateEvaluator of this \l{Rule}. */
|
||||||
void Rule::setStateEvaluator(const StateEvaluator &stateEvaluator)
|
void Rule::setStateEvaluator(const StateEvaluator &stateEvaluator)
|
||||||
{
|
{
|
||||||
m_stateEvaluator = stateEvaluator;
|
m_stateEvaluator = stateEvaluator;
|
||||||
@ -111,6 +115,7 @@ QList<EventDescriptor> Rule::eventDescriptors() const
|
|||||||
return m_eventDescriptors;
|
return m_eventDescriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Sets the \a eventDescriptors of this \l{Rule}. */
|
||||||
void Rule::setEventDescriptors(const QList<EventDescriptor> &eventDescriptors)
|
void Rule::setEventDescriptors(const QList<EventDescriptor> &eventDescriptors)
|
||||||
{
|
{
|
||||||
m_eventDescriptors = eventDescriptors;
|
m_eventDescriptors = eventDescriptors;
|
||||||
@ -122,6 +127,7 @@ QList<RuleAction> Rule::actions() const
|
|||||||
return m_actions;
|
return m_actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Sets the \a actions of this \l{Rule}. */
|
||||||
void Rule::setActions(const QList<RuleAction> actions)
|
void Rule::setActions(const QList<RuleAction> actions)
|
||||||
{
|
{
|
||||||
m_actions = actions;
|
m_actions = actions;
|
||||||
@ -133,6 +139,7 @@ QList<RuleAction> Rule::exitActions() const
|
|||||||
return m_exitActions;
|
return m_exitActions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Sets the \a exitActions of this \l{Rule}. */
|
||||||
void Rule::setExitActions(const QList<RuleAction> exitActions)
|
void Rule::setExitActions(const QList<RuleAction> exitActions)
|
||||||
{
|
{
|
||||||
m_exitActions = exitActions;
|
m_exitActions = exitActions;
|
||||||
@ -162,11 +169,13 @@ void Rule::setExecutable(const bool &executable)
|
|||||||
m_executable = executable;
|
m_executable = executable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Returns true if this \l{Rule} is valid. A \l{Rule} with a valid \l{id()} is valid. */
|
||||||
bool Rule::isValid() const
|
bool Rule::isValid() const
|
||||||
{
|
{
|
||||||
return !m_id.isNull();
|
return !m_id.isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Returns true if this \l{Rule} is consistent. */
|
||||||
bool Rule::isConsistent() const
|
bool Rule::isConsistent() const
|
||||||
{
|
{
|
||||||
// check if this rules is based on any event and contains exit actions
|
// check if this rules is based on any event and contains exit actions
|
||||||
@ -184,7 +193,6 @@ bool Rule::isConsistent() const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Rule::setActive(const bool &active)
|
void Rule::setActive(const bool &active)
|
||||||
{
|
{
|
||||||
m_active = active;
|
m_active = active;
|
||||||
|
|||||||
@ -74,6 +74,14 @@
|
|||||||
The types of the \l{RuleActionParam} and the corresponding \l{Event} \l{Param} do not match.
|
The types of the \l{RuleActionParam} and the corresponding \l{Event} \l{Param} do not match.
|
||||||
\value RuleErrorNotExecutable
|
\value RuleErrorNotExecutable
|
||||||
This rule is not executable.
|
This rule is not executable.
|
||||||
|
\value RuleErrorInvalidRepeatingOption
|
||||||
|
One of the given \l{RepeatingOption}{RepeatingOption} is not valid.
|
||||||
|
\value RuleErrorInvalidCalendarItem
|
||||||
|
One of the given \l{CalendarItem}{CalendarItems} is not valid.
|
||||||
|
\value RuleErrorInvalidTimeDescriptor
|
||||||
|
One of the given \l{TimeDescriptor}{TimeDescriptors} is not valid.
|
||||||
|
\value RuleErrorInvalidTimeEventItem
|
||||||
|
One of the given \l{TimeEventItem}{TimeEventItems} is not valid.
|
||||||
\value RuleErrorContainsEventBasesAction
|
\value RuleErrorContainsEventBasesAction
|
||||||
This rule contains an \l{Action} which depends on an \l{Event} value. This \l{Rule} cannot execute
|
This rule contains an \l{Action} which depends on an \l{Event} value. This \l{Rule} cannot execute
|
||||||
the \l{Action}{Actions} without the \l{Event} value.
|
the \l{Action}{Actions} without the \l{Event} value.
|
||||||
@ -238,7 +246,7 @@ QList<Rule> RuleEngine::evaluateEvent(const Event &event)
|
|||||||
qCDebug(dcRuleEngine) << "got event:" << event << device->name() << event.eventTypeId();
|
qCDebug(dcRuleEngine) << "got event:" << event << device->name() << event.eventTypeId();
|
||||||
|
|
||||||
QList<Rule> rules;
|
QList<Rule> rules;
|
||||||
foreach (const RuleId &id, m_ruleIds) {
|
foreach (const RuleId &id, ruleIds()) {
|
||||||
Rule rule = m_rules.value(id);
|
Rule rule = m_rules.value(id);
|
||||||
if (!rule.enabled())
|
if (!rule.enabled())
|
||||||
continue;
|
continue;
|
||||||
@ -278,14 +286,65 @@ QList<Rule> RuleEngine::evaluateEvent(const Event &event)
|
|||||||
return rules;
|
return rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Ask the Engine to evaluate all the rules for the given \a dateTime.
|
||||||
|
This will search all the \l{Rule}{Rules} triggered by the given \a dateTime
|
||||||
|
and evaluate their \l{CalendarItem}{CalendarItems} and \l{TimeEventItem}{TimeEventItems}.
|
||||||
|
It will return a list of all \l{Rule}{Rules} that are triggered or change its active state.
|
||||||
|
*/
|
||||||
QList<Rule> RuleEngine::evaluateTime(const QDateTime &dateTime)
|
QList<Rule> RuleEngine::evaluateTime(const QDateTime &dateTime)
|
||||||
{
|
{
|
||||||
Q_UNUSED(dateTime)
|
|
||||||
QList<Rule> rules;
|
QList<Rule> rules;
|
||||||
|
|
||||||
|
foreach (const Rule &r, m_rules.values()) {
|
||||||
|
Rule rule = m_rules.value(r.id());
|
||||||
|
if (!rule.enabled())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// check if this rule is time based
|
||||||
|
if (!rule.timeDescriptor().isEmpty()) {
|
||||||
|
|
||||||
|
// check if this rule is based on calendarItems
|
||||||
|
if (!rule.timeDescriptor().calendarItems().isEmpty()) {
|
||||||
|
qCDebug(dcRuleEngine()) << "Evaluate CalendarItem against" << dateTime.toString("dd:MM:yyyy hh:mm") << "for rule" << rule.id().toString();
|
||||||
|
bool active = rule.timeDescriptor().evaluate(dateTime);
|
||||||
|
if (active) {
|
||||||
|
if (m_activeRules.contains(rule.id())) {
|
||||||
|
qCDebug(dcRuleEngine) << "Rule" << rule.id().toString() << "still active.";
|
||||||
|
} else {
|
||||||
|
qCDebug(dcRuleEngine) << "Rule" << rule.id().toString() << "active.";
|
||||||
|
rule.setActive(true);
|
||||||
|
m_rules[rule.id()] = rule;
|
||||||
|
m_activeRules.append(rule.id());
|
||||||
|
rules.append(rule);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (m_activeRules.contains(rule.id())) {
|
||||||
|
qCDebug(dcRuleEngine) << "Rule" << rule.id().toString() << "inactive.";
|
||||||
|
rule.setActive(false);
|
||||||
|
m_rules[rule.id()] = rule;
|
||||||
|
m_activeRules.removeAll(rule.id());
|
||||||
|
rules.append(rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if this rule is based on timeEventItems
|
||||||
|
if (!rule.timeDescriptor().timeEventItems().isEmpty()) {
|
||||||
|
bool valid = rule.timeDescriptor().evaluate(dateTime);
|
||||||
|
qCDebug(dcRuleEngine()) << "Result:" << (valid ? "valid" : "invalid");
|
||||||
|
if (valid) {
|
||||||
|
rules.append(rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return rules;
|
return rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Add the given \a rule to the system. If the rule will be added
|
||||||
|
from an edit request, the parameter \a fromEdit will be true.
|
||||||
|
*/
|
||||||
RuleEngine::RuleError RuleEngine::addRule(const Rule &rule, bool fromEdit)
|
RuleEngine::RuleError RuleEngine::addRule(const Rule &rule, bool fromEdit)
|
||||||
{
|
{
|
||||||
if (rule.id().isNull())
|
if (rule.id().isNull())
|
||||||
@ -333,7 +392,7 @@ RuleEngine::RuleError RuleEngine::addRule(const Rule &rule, bool fromEdit)
|
|||||||
// Check time descriptor
|
// Check time descriptor
|
||||||
if (!rule.timeDescriptor().isEmpty()) {
|
if (!rule.timeDescriptor().isEmpty()) {
|
||||||
|
|
||||||
if (rule.timeDescriptor().isValid()) {
|
if (!rule.timeDescriptor().isValid()) {
|
||||||
qCDebug(dcRuleEngine()) << "Cannot create rule. Got invalid timeDescriptor.";
|
qCDebug(dcRuleEngine()) << "Cannot create rule. Got invalid timeDescriptor.";
|
||||||
return RuleErrorInvalidTimeDescriptor;
|
return RuleErrorInvalidTimeDescriptor;
|
||||||
}
|
}
|
||||||
@ -484,6 +543,9 @@ RuleEngine::RuleError RuleEngine::addRule(const Rule &rule, bool fromEdit)
|
|||||||
return RuleErrorNoError;
|
return RuleErrorNoError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Edit the given \a rule in the system. The rule with the \l{RuleId} from the given \a rule
|
||||||
|
will be removed from the system and readded with the new parameters in the given \a rule.
|
||||||
|
*/
|
||||||
RuleEngine::RuleError RuleEngine::editRule(const Rule &rule)
|
RuleEngine::RuleError RuleEngine::editRule(const Rule &rule)
|
||||||
{
|
{
|
||||||
if (rule.id().isNull())
|
if (rule.id().isNull())
|
||||||
|
|||||||
@ -29,6 +29,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "calendaritem.h"
|
#include "calendaritem.h"
|
||||||
|
#include "loggingcategories.h"
|
||||||
|
|
||||||
namespace guhserver {
|
namespace guhserver {
|
||||||
|
|
||||||
@ -102,19 +103,16 @@ bool CalendarItem::isValid() const
|
|||||||
/*! Returns true, if the given \a dateTime matches this \l{CalendarItem}. */
|
/*! Returns true, if the given \a dateTime matches this \l{CalendarItem}. */
|
||||||
bool CalendarItem::evaluate(const QDateTime &dateTime) const
|
bool CalendarItem::evaluate(const QDateTime &dateTime) const
|
||||||
{
|
{
|
||||||
|
qCDebug(dcRuleEngine()) << "Evaluate CalendarItem";
|
||||||
|
|
||||||
if (!isValid())
|
if (!isValid())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!repeatingOption().isValid())
|
if (!repeatingOption().isValid())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (m_dateTime.isValid() && !repeatingOption().isEmtpy())
|
if (m_startTime.isValid()) {
|
||||||
return false;
|
switch (m_repeatingOption.mode()) {
|
||||||
|
|
||||||
// Only check repeating option mode if this is not a timedate calendarItem,
|
|
||||||
// which can only be valid once and is not repeatable.
|
|
||||||
if (!m_dateTime.isValid()) {
|
|
||||||
switch (repeatingOption().mode()) {
|
|
||||||
case RepeatingOption::RepeatingModeNone:
|
case RepeatingOption::RepeatingModeNone:
|
||||||
// If there is no repeating option, we assume it is meant daily.
|
// If there is no repeating option, we assume it is meant daily.
|
||||||
return evaluateDaily(dateTime);
|
return evaluateDaily(dateTime);
|
||||||
@ -137,9 +135,20 @@ bool CalendarItem::evaluate(const QDateTime &dateTime) const
|
|||||||
|
|
||||||
bool CalendarItem::evaluateHourly(const QDateTime &dateTime) const
|
bool CalendarItem::evaluateHourly(const QDateTime &dateTime) const
|
||||||
{
|
{
|
||||||
|
qCDebug(dcRuleEngine()) << "Evaluate CalendarItem Hourly";
|
||||||
|
|
||||||
|
// If the duration is longer than a hour, this calendar item is always true
|
||||||
|
// 1 hour has 60 minutes
|
||||||
|
if (duration() >= 60)
|
||||||
|
return true;
|
||||||
|
|
||||||
QDateTime startDateTime = QDateTime(dateTime.date(), QTime(dateTime.time().hour(), startTime().minute()));
|
QDateTime startDateTime = QDateTime(dateTime.date(), QTime(dateTime.time().hour(), startTime().minute()));
|
||||||
QDateTime endDateTime = startDateTime.addSecs(duration() * 60);
|
QDateTime endDateTime = startDateTime.addSecs(duration() * 60);
|
||||||
|
|
||||||
|
qCDebug(dcRuleEngine()) << "current time" << dateTime.toString("hh:mm");
|
||||||
|
qCDebug(dcRuleEngine()) << "startTime" << startDateTime.toString("hh:mm");
|
||||||
|
qCDebug(dcRuleEngine()) << "endTime" << endDateTime.toString("hh:mm");
|
||||||
|
|
||||||
bool timeValid = dateTime >= startDateTime && dateTime < endDateTime;
|
bool timeValid = dateTime >= startDateTime && dateTime < endDateTime;
|
||||||
bool weekdayValid = repeatingOption().evaluateWeekDay(dateTime);
|
bool weekdayValid = repeatingOption().evaluateWeekDay(dateTime);
|
||||||
bool monthdayValid = repeatingOption().evaluateMonthDay(dateTime);
|
bool monthdayValid = repeatingOption().evaluateMonthDay(dateTime);
|
||||||
@ -149,6 +158,8 @@ bool CalendarItem::evaluateHourly(const QDateTime &dateTime) const
|
|||||||
|
|
||||||
bool CalendarItem::evaluateDaily(const QDateTime &dateTime) const
|
bool CalendarItem::evaluateDaily(const QDateTime &dateTime) const
|
||||||
{
|
{
|
||||||
|
qCDebug(dcRuleEngine()) << "Evaluate CalendarItem Hourly";
|
||||||
|
|
||||||
// If the duration is longer than a day, this calendar item is always true
|
// If the duration is longer than a day, this calendar item is always true
|
||||||
// 1 day has 1440 minutes
|
// 1 day has 1440 minutes
|
||||||
if (duration() >= 1440)
|
if (duration() >= 1440)
|
||||||
|
|||||||
@ -69,7 +69,7 @@ void TimeDescriptor::setCalendarItems(const QList<CalendarItem> &calendarItems)
|
|||||||
/*! Returns true if either the calendarItems list is not empty or the timeEventItems list.*/
|
/*! Returns true if either the calendarItems list is not empty or the timeEventItems list.*/
|
||||||
bool TimeDescriptor::isValid() const
|
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.*/
|
/*! Returns true if the calendarItems list and the timeEventItems list is empty.*/
|
||||||
@ -84,7 +84,23 @@ bool TimeDescriptor::isEmpty() const
|
|||||||
*/
|
*/
|
||||||
bool TimeDescriptor::evaluate(const QDateTime &dateTime) const
|
bool TimeDescriptor::evaluate(const QDateTime &dateTime) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(dateTime)
|
// If there are calendarItems (always OR connected)
|
||||||
|
if (!m_calendarItems.isEmpty()) {
|
||||||
|
foreach (const CalendarItem &calendarItem, m_calendarItems) {
|
||||||
|
if (calendarItem.evaluate(dateTime)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are timeEventItems (always OR connected)
|
||||||
|
if (!m_timeEventItems.isEmpty()) {
|
||||||
|
foreach (const TimeEventItem &timeEventItem, m_timeEventItems) {
|
||||||
|
if (timeEventItem.evaluate(dateTime)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,12 +30,8 @@
|
|||||||
Represents the central time tick. Will be emitted every second.
|
Represents the central time tick. Will be emitted every second.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*! \fn void guhserver::TimeManager::dateChanged(const QDate ¤tDate);
|
/*! \fn void guhserver::TimeManager::dateTimeChanged(const QDateTime &dateTime);
|
||||||
Will be emitted when the \a currentDate has changed.
|
Will be emitted when the \a dateTime has changed.
|
||||||
*/
|
|
||||||
|
|
||||||
/*! \fn void guhserver::TimeManager::timeChanged(const QTime ¤tTime);
|
|
||||||
Will be emitted when the \a currentTime has changed.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "timemanager.h"
|
#include "timemanager.h"
|
||||||
@ -106,6 +102,13 @@ void TimeManager::stopTimer()
|
|||||||
// Stop clock (used for testing)
|
// Stop clock (used for testing)
|
||||||
m_guhTimer->stop();
|
m_guhTimer->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TimeManager::setTime(const QDateTime &dateTime)
|
||||||
|
{
|
||||||
|
// This method will only be called for testing
|
||||||
|
emit tick();
|
||||||
|
emit dateTimeChanged(dateTime.toTimeZone(m_timeZone));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void TimeManager::guhTimeout()
|
void TimeManager::guhTimeout()
|
||||||
@ -113,17 +116,11 @@ void TimeManager::guhTimeout()
|
|||||||
// tick for deviceManager
|
// tick for deviceManager
|
||||||
emit tick();
|
emit tick();
|
||||||
|
|
||||||
QDateTime currentDateTime = QDateTime::currentDateTimeUtc();
|
|
||||||
|
|
||||||
// Minute based guh time
|
// Minute based guh time
|
||||||
|
QDateTime currentDateTime = QDateTime::currentDateTimeUtc();
|
||||||
if (m_dateTime.time().minute() != currentDateTime.toTimeZone(m_timeZone).time().minute()) {
|
if (m_dateTime.time().minute() != currentDateTime.toTimeZone(m_timeZone).time().minute()) {
|
||||||
m_dateTime = currentDateTime;
|
m_dateTime = currentDateTime;
|
||||||
emit timeChanged(m_dateTime.toTimeZone(m_timeZone).time());
|
emit dateTimeChanged(m_dateTime.toTimeZone(m_timeZone));
|
||||||
}
|
|
||||||
|
|
||||||
// check if day changed
|
|
||||||
if (m_dateTime.date() != currentDateTime.toTimeZone(m_timeZone).date()) {
|
|
||||||
emit dateChanged(m_dateTime.toTimeZone(m_timeZone).date());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -43,6 +43,7 @@ public:
|
|||||||
|
|
||||||
#ifdef TESTING_ENABLED
|
#ifdef TESTING_ENABLED
|
||||||
void stopTimer();
|
void stopTimer();
|
||||||
|
void setTime(const QDateTime &dateTime);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -52,8 +53,7 @@ private:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void tick();
|
void tick();
|
||||||
void dateChanged(const QDate ¤tDate);
|
void dateTimeChanged(const QDateTime &dateTime);
|
||||||
void timeChanged(const QTime ¤tTime);
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void guhTimeout();
|
void guhTimeout();
|
||||||
|
|||||||
@ -141,7 +141,6 @@ void TestRules::verifyRuleExecuted(const ActionTypeId &actionTypeId)
|
|||||||
qDebug() << "have action history" << actionHistory;
|
qDebug() << "have action history" << actionHistory;
|
||||||
QVERIFY2(actionTypeId == ActionTypeId(actionHistory), "Action not triggered");
|
QVERIFY2(actionTypeId == ActionTypeId(actionHistory), "Action not triggered");
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestRules::verifyRuleNotExecuted()
|
void TestRules::verifyRuleNotExecuted()
|
||||||
@ -157,7 +156,6 @@ void TestRules::verifyRuleNotExecuted()
|
|||||||
qDebug() << "have action history" << actionHistory;
|
qDebug() << "have action history" << actionHistory;
|
||||||
QVERIFY2(actionHistory.isEmpty(), "Action is triggered while it should not have been.");
|
QVERIFY2(actionHistory.isEmpty(), "Action is triggered while it should not have been.");
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -25,10 +25,13 @@
|
|||||||
#include "devicemanager.h"
|
#include "devicemanager.h"
|
||||||
#include "mocktcpserver.h"
|
#include "mocktcpserver.h"
|
||||||
|
|
||||||
#include <QTimeZone>
|
|
||||||
#include <QDateTime>
|
|
||||||
#include <QtTest/QtTest>
|
#include <QtTest/QtTest>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QTimeZone>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
using namespace guhserver;
|
using namespace guhserver;
|
||||||
|
|
||||||
@ -43,7 +46,14 @@ private slots:
|
|||||||
void addTimeDescriptor_data();
|
void addTimeDescriptor_data();
|
||||||
void addTimeDescriptor();
|
void addTimeDescriptor();
|
||||||
|
|
||||||
|
void testCalendarItemHourly();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void verifyRuleExecuted(const ActionTypeId &actionTypeId);
|
||||||
|
void verifyRuleNotExecuted();
|
||||||
|
|
||||||
|
void cleanupMockHistory();
|
||||||
|
|
||||||
QVariantMap createTimeEventItem(const QString &time = QString(), const QVariantMap &repeatingOption = QVariantMap()) const;
|
QVariantMap createTimeEventItem(const QString &time = QString(), const QVariantMap &repeatingOption = QVariantMap()) const;
|
||||||
QVariantMap createTimeEventItem(const int &dateTime, const QVariantMap &repeatingOption = QVariantMap()) const;
|
QVariantMap createTimeEventItem(const int &dateTime, const QVariantMap &repeatingOption = QVariantMap()) const;
|
||||||
QVariantMap createTimeDescriptorTimeEvent(const QVariantMap &timeEventItem) const;
|
QVariantMap createTimeDescriptorTimeEvent(const QVariantMap &timeEventItem) const;
|
||||||
@ -53,7 +63,6 @@ private:
|
|||||||
QVariantMap createCalendarItem(const int &dateTime, const uint &duration = 0, const QVariantMap &repeatingOption = QVariantMap()) const;
|
QVariantMap createCalendarItem(const int &dateTime, const uint &duration = 0, const QVariantMap &repeatingOption = QVariantMap()) const;
|
||||||
QVariantMap createTimeDescriptorCalendar(const QVariantMap &calendarItem) const;
|
QVariantMap createTimeDescriptorCalendar(const QVariantMap &calendarItem) const;
|
||||||
QVariantMap createTimeDescriptorCalendar(const QVariantList &calendarItems) const;
|
QVariantMap createTimeDescriptorCalendar(const QVariantList &calendarItems) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void TestTimeManager::changeTimeZone_data()
|
void TestTimeManager::changeTimeZone_data()
|
||||||
@ -114,6 +123,10 @@ void TestTimeManager::addTimeDescriptor_data()
|
|||||||
repeatingOptionMonthlyMultiple.insert("monthDays", QVariantList() << 20 << 14 << 5);
|
repeatingOptionMonthlyMultiple.insert("monthDays", QVariantList() << 20 << 14 << 5);
|
||||||
|
|
||||||
// invalid RepeatingOptions
|
// invalid RepeatingOptions
|
||||||
|
QVariantMap repeatingOptionInvalidNone;
|
||||||
|
repeatingOptionInvalidNone.insert("mode", "RepeatingModeNone");
|
||||||
|
repeatingOptionInvalidNone.insert("monthDays", QVariantList() << 13 << 12 << 27);
|
||||||
|
|
||||||
QVariantMap repeatingOptionInvalidWeekly;
|
QVariantMap repeatingOptionInvalidWeekly;
|
||||||
repeatingOptionInvalidWeekly.insert("mode", "RepeatingModeWeekly");
|
repeatingOptionInvalidWeekly.insert("mode", "RepeatingModeWeekly");
|
||||||
repeatingOptionInvalidWeekly.insert("monthDays", QVariantList() << 12 << 2 << 7);
|
repeatingOptionInvalidWeekly.insert("monthDays", QVariantList() << 12 << 2 << 7);
|
||||||
@ -168,6 +181,7 @@ void TestTimeManager::addTimeDescriptor_data()
|
|||||||
QTest::newRow("valid: timeEventItem - monthly - multiple days") << createTimeDescriptorTimeEvent(createTimeEventItem("23:00", repeatingOptionMonthlyMultiple)) << RuleEngine::RuleErrorNoError;
|
QTest::newRow("valid: timeEventItem - monthly - multiple days") << createTimeDescriptorTimeEvent(createTimeEventItem("23:00", repeatingOptionMonthlyMultiple)) << RuleEngine::RuleErrorNoError;
|
||||||
|
|
||||||
QTest::newRow("invalid: calendarItem empty") << createTimeDescriptorCalendar(createCalendarItem()) << RuleEngine::RuleErrorInvalidCalendarItem;
|
QTest::newRow("invalid: calendarItem empty") << createTimeDescriptorCalendar(createCalendarItem()) << RuleEngine::RuleErrorInvalidCalendarItem;
|
||||||
|
QTest::newRow("invalid: calendarItem none") << createTimeDescriptorCalendar(createCalendarItem("00:12", 12, repeatingOptionInvalidNone)) << RuleEngine::RuleErrorInvalidRepeatingOption;
|
||||||
QTest::newRow("invalid: calendarItem - dateTime + repeatingOption") << createTimeDescriptorCalendar(createCalendarItem(QDateTime::currentDateTime().toTime_t(), 5, repeatingOptionDaily)) << RuleEngine::RuleErrorInvalidCalendarItem;
|
QTest::newRow("invalid: calendarItem - dateTime + repeatingOption") << createTimeDescriptorCalendar(createCalendarItem(QDateTime::currentDateTime().toTime_t(), 5, repeatingOptionDaily)) << RuleEngine::RuleErrorInvalidCalendarItem;
|
||||||
QTest::newRow("invalid: calendarItem invalid time") << createTimeDescriptorCalendar(createCalendarItem("35:80", 5)) << RuleEngine::RuleErrorInvalidCalendarItem;
|
QTest::newRow("invalid: calendarItem invalid time") << createTimeDescriptorCalendar(createCalendarItem("35:80", 5)) << RuleEngine::RuleErrorInvalidCalendarItem;
|
||||||
QTest::newRow("invalid: calendarItem invalid duration") << createTimeDescriptorCalendar(createCalendarItem("12:00", 0)) << RuleEngine::RuleErrorInvalidCalendarItem;
|
QTest::newRow("invalid: calendarItem invalid duration") << createTimeDescriptorCalendar(createCalendarItem("12:00", 0)) << RuleEngine::RuleErrorInvalidCalendarItem;
|
||||||
@ -179,6 +193,7 @@ void TestTimeManager::addTimeDescriptor_data()
|
|||||||
QTest::newRow("invalid: calendarItem - invalid monthdays (to big)") << createTimeDescriptorCalendar(createCalendarItem("13:13", 5, repeatingOptionInvalidMonthDays2)) << RuleEngine::RuleErrorInvalidRepeatingOption;
|
QTest::newRow("invalid: calendarItem - invalid monthdays (to big)") << createTimeDescriptorCalendar(createCalendarItem("13:13", 5, repeatingOptionInvalidMonthDays2)) << RuleEngine::RuleErrorInvalidRepeatingOption;
|
||||||
|
|
||||||
QTest::newRow("invalid: timeEventItem empty") << createTimeDescriptorTimeEvent(createTimeEventItem()) << RuleEngine::RuleErrorInvalidTimeEventItem;
|
QTest::newRow("invalid: timeEventItem empty") << createTimeDescriptorTimeEvent(createTimeEventItem()) << RuleEngine::RuleErrorInvalidTimeEventItem;
|
||||||
|
QTest::newRow("invalid: timeEventItem none") << createTimeDescriptorTimeEvent(createTimeEventItem("00:12", repeatingOptionInvalidNone)) << RuleEngine::RuleErrorInvalidRepeatingOption;
|
||||||
QTest::newRow("invalid: timeEventItem - dateTime + repeatingOption") << createTimeDescriptorTimeEvent(createTimeEventItem(QDateTime::currentDateTime().toTime_t(), repeatingOptionDaily)) << RuleEngine::RuleErrorInvalidTimeEventItem;
|
QTest::newRow("invalid: timeEventItem - dateTime + repeatingOption") << createTimeDescriptorTimeEvent(createTimeEventItem(QDateTime::currentDateTime().toTime_t(), repeatingOptionDaily)) << RuleEngine::RuleErrorInvalidTimeEventItem;
|
||||||
QTest::newRow("invalid: timeEventItem invalid time") << createTimeDescriptorTimeEvent(createTimeEventItem("35:80")) << RuleEngine::RuleErrorInvalidTimeEventItem;
|
QTest::newRow("invalid: timeEventItem invalid time") << createTimeDescriptorTimeEvent(createTimeEventItem("35:80")) << RuleEngine::RuleErrorInvalidTimeEventItem;
|
||||||
QTest::newRow("invalid: timeEventItem - monthly - weekDays") << createTimeDescriptorTimeEvent(createTimeEventItem("13:13", repeatingOptionInvalidMonthly)) << RuleEngine::RuleErrorInvalidRepeatingOption;
|
QTest::newRow("invalid: timeEventItem - monthly - weekDays") << createTimeDescriptorTimeEvent(createTimeEventItem("13:13", repeatingOptionInvalidMonthly)) << RuleEngine::RuleErrorInvalidRepeatingOption;
|
||||||
@ -211,11 +226,120 @@ void TestTimeManager::addTimeDescriptor()
|
|||||||
|
|
||||||
// Print rule
|
// Print rule
|
||||||
RuleId newRuleId = RuleId(response.toMap().value("params").toMap().value("ruleId").toString());
|
RuleId newRuleId = RuleId(response.toMap().value("params").toMap().value("ruleId").toString());
|
||||||
QVariantMap params;
|
|
||||||
params.insert("ruleId", newRuleId);
|
// REMOVE rule
|
||||||
response = injectAndWait("Rules.GetRuleDetails", params);
|
QVariantMap removeParams;
|
||||||
QVariantMap rule = response.toMap().value("params").toMap().value("rule").toMap();
|
removeParams.insert("ruleId", newRuleId);
|
||||||
qDebug() << QJsonDocument::fromVariant(rule).toJson();
|
response = injectAndWait("Rules.RemoveRule", removeParams);
|
||||||
|
verifyRuleError(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestTimeManager::testCalendarItemHourly()
|
||||||
|
{
|
||||||
|
GuhCore::instance()->timeManager()->stopTimer();
|
||||||
|
qDebug() << GuhCore::instance()->timeManager()->currentDate().toString();
|
||||||
|
qDebug() << GuhCore::instance()->timeManager()->currentTime().toString();
|
||||||
|
qDebug() << GuhCore::instance()->timeManager()->currentDateTime().toString();
|
||||||
|
|
||||||
|
QVariantMap ruleMap; QVariantMap action; QVariantMap exitAction; QVariantMap repeatingOptionHourly;
|
||||||
|
repeatingOptionHourly.insert("mode", "RepeatingModeHourly");
|
||||||
|
action.insert("actionTypeId", mockActionIdNoParams);
|
||||||
|
action.insert("deviceId", m_mockDeviceId);
|
||||||
|
action.insert("ruleActionParams", QVariantList());
|
||||||
|
exitAction.insert("actionTypeId", mockActionIdWithParams);
|
||||||
|
QVariantList actionParams;
|
||||||
|
QVariantMap param1;
|
||||||
|
param1.insert("name", "mockActionParam1");
|
||||||
|
param1.insert("value", 5);
|
||||||
|
actionParams.append(param1);
|
||||||
|
QVariantMap param2;
|
||||||
|
param2.insert("name", "mockActionParam2");
|
||||||
|
param2.insert("value", true);
|
||||||
|
actionParams.append(param2);
|
||||||
|
exitAction.insert("deviceId", m_mockDeviceId);
|
||||||
|
exitAction.insert("ruleActionParams", actionParams);
|
||||||
|
ruleMap.insert("name", "Time based hourly calendar rule");
|
||||||
|
ruleMap.insert("timeDescriptor", createTimeDescriptorCalendar(createCalendarItem("08:05", 5)));
|
||||||
|
ruleMap.insert("actions", QVariantList() << action);
|
||||||
|
ruleMap.insert("exitActions", QVariantList() << exitAction);
|
||||||
|
|
||||||
|
QVariant response = injectAndWait("Rules.AddRule", ruleMap);
|
||||||
|
verifyRuleError(response);
|
||||||
|
RuleId ruleId = RuleId(response.toMap().value("params").toMap().value("ruleId").toString());
|
||||||
|
|
||||||
|
QDateTime currentDateTime = GuhCore::instance()->timeManager()->currentDateTime();
|
||||||
|
|
||||||
|
// check the next 24 hours
|
||||||
|
QDateTime future = QDateTime(currentDateTime.date(), QTime(8, 4));
|
||||||
|
for (int i = 0; i < 24; i++) {
|
||||||
|
// inactive
|
||||||
|
GuhCore::instance()->timeManager()->setTime(future);
|
||||||
|
verifyRuleNotExecuted();
|
||||||
|
// active
|
||||||
|
GuhCore::instance()->timeManager()->setTime(QDateTime(currentDateTime.date(), QTime(future.time().hour(), 5)));
|
||||||
|
verifyRuleExecuted(mockActionIdNoParams);
|
||||||
|
cleanupMockHistory();
|
||||||
|
// active unchanged
|
||||||
|
GuhCore::instance()->timeManager()->setTime(QDateTime(currentDateTime.date(), QTime(future.time().hour(), 7)));
|
||||||
|
verifyRuleNotExecuted();
|
||||||
|
// inactive
|
||||||
|
GuhCore::instance()->timeManager()->setTime(QDateTime(currentDateTime.date(), QTime(future.time().hour(), 10)));
|
||||||
|
verifyRuleExecuted(mockActionIdWithParams);
|
||||||
|
cleanupMockHistory();
|
||||||
|
// inactive unchanged
|
||||||
|
GuhCore::instance()->timeManager()->setTime(QDateTime(currentDateTime.date(), QTime(future.time().hour(), 11)));
|
||||||
|
verifyRuleNotExecuted();
|
||||||
|
|
||||||
|
// One hour "Back to the future"
|
||||||
|
future = future.addSecs(60*60);
|
||||||
|
}
|
||||||
|
|
||||||
|
// REMOVE rule
|
||||||
|
QVariantMap removeParams;
|
||||||
|
removeParams.insert("ruleId", ruleId);
|
||||||
|
response = injectAndWait("Rules.RemoveRule", removeParams);
|
||||||
|
verifyRuleError(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestTimeManager::verifyRuleExecuted(const ActionTypeId &actionTypeId)
|
||||||
|
{
|
||||||
|
// Verify rule got executed
|
||||||
|
QNetworkAccessManager nam;
|
||||||
|
QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*)));
|
||||||
|
QNetworkRequest request(QUrl(QString("http://localhost:%1/actionhistory").arg(QString::number(m_mockDevice1Port))));
|
||||||
|
QNetworkReply *reply = nam.get(request);
|
||||||
|
spy.wait();
|
||||||
|
QCOMPARE(spy.count(), 1);
|
||||||
|
|
||||||
|
QByteArray actionHistory = reply->readAll();
|
||||||
|
qDebug() << "have action history" << actionHistory;
|
||||||
|
QVERIFY2(actionTypeId == ActionTypeId(actionHistory), "Action not triggered");
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestTimeManager::verifyRuleNotExecuted()
|
||||||
|
{
|
||||||
|
QNetworkAccessManager nam;
|
||||||
|
QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*)));
|
||||||
|
QNetworkRequest request(QUrl(QString("http://localhost:%1/actionhistory").arg(QString::number(m_mockDevice1Port))));
|
||||||
|
QNetworkReply *reply = nam.get(request);
|
||||||
|
spy.wait();
|
||||||
|
QCOMPARE(spy.count(), 1);
|
||||||
|
|
||||||
|
QByteArray actionHistory = reply->readAll();
|
||||||
|
qDebug() << "have action history" << actionHistory;
|
||||||
|
QVERIFY2(actionHistory.isEmpty(), "Action is triggered while it should not have been.");
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestTimeManager::cleanupMockHistory() {
|
||||||
|
QNetworkAccessManager nam;
|
||||||
|
QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*)));
|
||||||
|
QNetworkRequest request(QUrl(QString("http://localhost:%1/clearactionhistory").arg(QString::number(m_mockDevice1Port))));
|
||||||
|
QNetworkReply *reply = nam.get(request);
|
||||||
|
spy.wait();
|
||||||
|
QCOMPARE(spy.count(), 1);
|
||||||
|
reply->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantMap TestTimeManager::createTimeEventItem(const QString &time, const QVariantMap &repeatingOption) const
|
QVariantMap TestTimeManager::createTimeEventItem(const QString &time, const QVariantMap &repeatingOption) const
|
||||||
|
|||||||
Reference in New Issue
Block a user