add support for paramTypes by name

This commit is contained in:
Michael Zanetti 2018-06-20 19:42:43 +02:00
parent e21c2f16a5
commit abd2305bc0
26 changed files with 404 additions and 55 deletions

View File

@ -182,7 +182,8 @@ void JsonTypes::init()
s_ruleActionParam.insert("o:eventParamTypeId", basicTypeToString(Uuid));
// ParamDescriptor
s_paramDescriptor.insert("paramTypeId", basicTypeToString(Uuid));
s_paramDescriptor.insert("o:paramTypeId", basicTypeToString(Uuid));
s_paramDescriptor.insert("o:paramName", basicTypeToString(Uuid));
s_paramDescriptor.insert("value", basicTypeRef());
s_paramDescriptor.insert("operator", valueOperatorRef());
@ -683,7 +684,11 @@ QVariantMap JsonTypes::packParam(const Param &param)
QVariantMap JsonTypes::packParamDescriptor(const ParamDescriptor &paramDescriptor)
{
QVariantMap variantMap;
variantMap.insert("paramTypeId", paramDescriptor.paramTypeId().toString());
if (!paramDescriptor.paramTypeId().isNull()) {
variantMap.insert("paramTypeId", paramDescriptor.paramTypeId().toString());
} else {
variantMap.insert("paramName", paramDescriptor.paramName());
}
variantMap.insert("value", paramDescriptor.value());
variantMap.insert("operator", s_valueOperator.at(paramDescriptor.operatorType()));
return variantMap;
@ -1389,13 +1394,19 @@ RuleActionParamList JsonTypes::unpackRuleActionParams(const QVariantList &ruleAc
/*! Returns a \l{ParamDescriptor} created from the given \a paramMap. */
ParamDescriptor JsonTypes::unpackParamDescriptor(const QVariantMap &paramMap)
{
ParamDescriptor param(ParamTypeId(paramMap.value("paramTypeId").toString()), paramMap.value("value"));
QString operatorString = paramMap.value("operator").toString();
QMetaObject metaObject = Types::staticMetaObject;
int enumIndex = metaObject.indexOfEnumerator("ValueOperator");
QMetaEnum metaEnum = metaObject.enumerator(enumIndex);
param.setOperatorType((Types::ValueOperator)metaEnum.keyToValue(operatorString.toLatin1().data()));
Types::ValueOperator valueOperator = (Types::ValueOperator)metaEnum.keyToValue(operatorString.toLatin1().data());
if (paramMap.contains("paramTypeId")) {
ParamDescriptor param = ParamDescriptor(ParamTypeId(paramMap.value("paramTypeId").toString()), paramMap.value("value"));
param.setOperatorType(valueOperator);
return param;
}
ParamDescriptor param = ParamDescriptor(paramMap.value("paramName").toString(), paramMap.value("value"));
param.setOperatorType(valueOperator);
return param;
}

View File

@ -58,6 +58,7 @@
#include "loggingcategories.h"
#include <QDebug>
#include <QJsonDocument>
namespace nymeaserver {
@ -215,6 +216,9 @@ JsonReply *RulesHandler::GetRuleDetails(const QVariantMap &params)
return createReply(statusToReply(RuleEngine::RuleErrorRuleNotFound));
}
QVariantMap returns = statusToReply(RuleEngine::RuleErrorNoError);
qWarning() << "Have rule" << rule;
QJsonDocument jsonDoc = QJsonDocument::fromVariant(JsonTypes::packRule(rule));
qWarning() << "packed:" << jsonDoc.toJson();
returns.insert("rule", JsonTypes::packRule(rule));
return createReply(returns);
}

View File

@ -230,4 +230,20 @@ void Rule::setActive(const bool &active)
m_active = active;
}
QDebug operator<<(QDebug dbg, const Rule &rule)
{
dbg.nospace() << endl << "=== Rule begin ===" << endl;
dbg.nospace() << "ID:" << rule.id().toString() << endl;
dbg.nospace() << "Name:" << rule.name() << endl;
dbg.nospace() << "Enabled:" << rule.enabled() << endl;
dbg.nospace() << "Active:" << rule.active() << endl;
dbg.nospace() << rule.eventDescriptors();
dbg.nospace() << rule.timeDescriptor();
dbg.nospace() << rule.stateEvaluator();
dbg.nospace() << "Actions:" << rule.actions();
dbg.nospace() << "ExitActions:" << rule.exitActions();
dbg.nospace() << "=== Rule end ===";
return dbg.space();
}
}

View File

@ -94,6 +94,8 @@ private:
bool m_executable;
};
QDebug operator<<(QDebug dbg, const Rule &rule);
}
#endif // RULE_H

View File

@ -227,20 +227,34 @@ RuleEngine::RuleEngine(QObject *parent) :
settings.beginGroup(eventGroupName);
EventTypeId eventTypeId(settings.value("eventTypeId").toString());
DeviceId deviceId(settings.value("deviceId").toString());
QString interface = settings.value("interface").toString();
QString interfaceEvent = settings.value("interfaceEvent").toString();
QList<ParamDescriptor> params;
foreach (QString groupName, settings.childGroups()) {
if (groupName.startsWith("ParamDescriptor-")) {
settings.beginGroup(groupName);
ParamDescriptor paramDescriptor(ParamTypeId(groupName.remove(QRegExp("^ParamDescriptor-"))), settings.value("value"));
paramDescriptor.setOperatorType((Types::ValueOperator)settings.value("operator").toInt());
params.append(paramDescriptor);
QString strippedGroupName = groupName.remove(QRegExp("^ParamDescriptor-"));
if (!ParamTypeId(strippedGroupName).isNull()) {
ParamDescriptor paramDescriptor(ParamTypeId(strippedGroupName), settings.value("value"));
paramDescriptor.setOperatorType((Types::ValueOperator)settings.value("operator").toInt());
params.append(paramDescriptor);
} else {
ParamDescriptor paramDescriptor(strippedGroupName, settings.value("value"));
paramDescriptor.setOperatorType((Types::ValueOperator)settings.value("operator").toInt());
params.append(paramDescriptor);
}
settings.endGroup();
}
}
EventDescriptor eventDescriptor(eventTypeId, deviceId, params);
eventDescriptorList.append(eventDescriptor);
if (!eventTypeId.isNull()) {
EventDescriptor eventDescriptor(eventTypeId, deviceId, params);
eventDescriptorList.append(eventDescriptor);
} else {
EventDescriptor eventDescriptor(interface, interfaceEvent, params);
eventDescriptorList.append(eventDescriptor);
}
settings.endGroup();
}
}
@ -256,24 +270,40 @@ RuleEngine::RuleEngine(QObject *parent) :
foreach (const QString &actionNumber, settings.childGroups()) {
settings.beginGroup(actionNumber);
RuleAction action = RuleAction(ActionTypeId(settings.value("actionTypeId").toString()),
DeviceId(settings.value("deviceId").toString()));
RuleActionParamList params;
foreach (QString paramTypeIdString, settings.childGroups()) {
if (paramTypeIdString.startsWith("RuleActionParam-")) {
settings.beginGroup(paramTypeIdString);
RuleActionParam param(ParamTypeId(paramTypeIdString.remove(QRegExp("^RuleActionParam-"))),
settings.value("value",QVariant()),
EventTypeId(settings.value("eventTypeId", EventTypeId()).toString()),
settings.value("eventParamTypeId", ParamTypeId()).toString());
params.append(param);
QString strippedParamTypeIdString = paramTypeIdString.remove(QRegExp("^RuleActionParam-"));
EventTypeId eventTypeId = EventTypeId(settings.value("eventTypeId", EventTypeId()).toString());
ParamTypeId eventParamTypeId = ParamTypeId(settings.value("eventParamTypeId", ParamTypeId()).toString());
QVariant value = settings.value("value");
if (!ParamTypeId(strippedParamTypeIdString).isNull()) {
RuleActionParam param(ParamTypeId(strippedParamTypeIdString),
value,
eventTypeId,
eventParamTypeId);
params.append(param);
} else {
RuleActionParam param(strippedParamTypeIdString,
value,
eventTypeId,
eventParamTypeId);
params.append(param);
}
settings.endGroup();
}
}
action.setRuleActionParams(params);
actions.append(action);
if (settings.contains("actionTypeId") && settings.contains("deviceId")) {
RuleAction action = RuleAction(ActionTypeId(settings.value("actionTypeId").toString()), DeviceId(settings.value("deviceId").toString()));
action.setRuleActionParams(params);
actions.append(action);
} else if (settings.contains("interface") && settings.contains("interfaceAction")){
RuleAction action = RuleAction(settings.value("interface").toString(), settings.value("interfaceAction").toString());
action.setRuleActionParams(params);
actions.append(action);
}
settings.endGroup();
}
@ -285,21 +315,33 @@ RuleEngine::RuleEngine(QObject *parent) :
foreach (const QString &actionNumber, settings.childGroups()) {
settings.beginGroup(actionNumber);
RuleAction action = RuleAction(ActionTypeId(settings.value("actionTypeId").toString()),
DeviceId(settings.value("deviceId").toString()));
RuleActionParamList params;
foreach (QString paramTypeIdString, settings.childGroups()) {
if (paramTypeIdString.startsWith("RuleActionParam-")) {
settings.beginGroup(paramTypeIdString);
RuleActionParam param(ParamTypeId(paramTypeIdString.remove(QRegExp("^RuleActionParam-"))),
settings.value("value"));
params.append(param);
QString strippedParamTypeIdString = paramTypeIdString.remove(QRegExp("^RuleActionParam-"));
QVariant value = settings.value("value");
if (!ParamTypeId(strippedParamTypeIdString).isNull()) {
RuleActionParam param(ParamTypeId(strippedParamTypeIdString), value);
params.append(param);
} else {
RuleActionParam param(strippedParamTypeIdString, value);
params.append(param);
}
settings.endGroup();
}
}
action.setRuleActionParams(params);
exitActions.append(action);
if (settings.contains("actionTypeId") && settings.contains("deviceId")) {
RuleAction action = RuleAction(ActionTypeId(settings.value("actionTypeId").toString()), DeviceId(settings.value("deviceId").toString()));
action.setRuleActionParams(params);
exitActions.append(action);
} else if (settings.contains("interface") && settings.contains("interfaceAction")) {
RuleAction action = RuleAction(settings.value("interface").toString(),settings.value("interfaceAction").toString());
action.setRuleActionParams(params);
exitActions.append(action);
}
settings.endGroup();
}
settings.endGroup();
@ -730,7 +772,6 @@ RuleEngine::RuleError RuleEngine::addRule(const Rule &rule, bool fromEdit)
emit ruleAdded(rule);
qCDebug(dcRuleEngine()) << "Rule" << rule.name() << rule.id().toString() << "added successfully.";
return RuleErrorNoError;
}
@ -1004,12 +1045,12 @@ QList<DeviceId> RuleEngine::devicesInRules() const
}
}
foreach (const RuleAction &action, rule.actions()) {
if (!tmp.contains(action.deviceId())) {
if (!tmp.contains(action.deviceId()) && !action.deviceId().isNull()) {
tmp.append(action.deviceId());
}
}
foreach (const RuleAction &exitAction, rule.exitActions()) {
if (!tmp.contains(exitAction.deviceId())) {
if (!tmp.contains(exitAction.deviceId()) && !exitAction.deviceId().isNull()) {
tmp.append(exitAction.deviceId());
}
}
@ -1111,14 +1152,29 @@ bool RuleEngine::containsEvent(const Rule &rule, const Event &event, const Devic
// Ok, either device/eventTypeId or interface/interfaceEvent are matching. Compare the paramdescriptor
bool allOK = true;
foreach (const ParamDescriptor &paramDescriptor, eventDescriptor.paramDescriptors()) {
QVariant paramValue;
if (!paramDescriptor.paramTypeId().isNull()) {
paramValue = event.param(paramDescriptor.paramTypeId()).value();
} else {
if (paramDescriptor.paramName().isEmpty()) {
qWarning(dcRuleEngine()) << "ParamDescriptor invalid. Either paramTypeId or paramName are required";
allOK = false;
continue;
}
DeviceClass dc = NymeaCore::instance()->deviceManager()->findDeviceClass(deviceClassId);
EventType et = dc.eventTypes().findById(event.eventTypeId());
ParamType pt = et.paramTypes().findByName(paramDescriptor.paramName());
paramValue = event.param(pt.id()).value();
}
switch (paramDescriptor.operatorType()) {
case Types::ValueOperatorEquals:
if (event.param(paramDescriptor.paramTypeId()).value() != paramDescriptor.value()) {
if (paramValue != paramDescriptor.value()) {
allOK = false;
}
break;
case Types::ValueOperatorNotEquals:
if (event.param(paramDescriptor.paramTypeId()).value() == paramDescriptor.value()) {
if (paramValue == paramDescriptor.value()) {
allOK = false;
}
break;
@ -1227,6 +1283,7 @@ void RuleEngine::appendRule(const Rule &rule)
{
Rule newRule = rule;
newRule.setStatesActive(newRule.stateEvaluator().evaluate());
qCDebug(dcRuleEngineDebug()) << "Appending new Rule:" << newRule;
m_rules.insert(rule.id(), newRule);
m_ruleIds.append(rule.id());
}
@ -1318,9 +1375,15 @@ void RuleEngine::saveRule(const Rule &rule)
settings.beginGroup("EventDescriptor-" + QString::number(i));
settings.setValue("deviceId", eventDescriptor.deviceId().toString());
settings.setValue("eventTypeId", eventDescriptor.eventTypeId().toString());
settings.setValue("interface", eventDescriptor.interface());
settings.setValue("interfaceEvent", eventDescriptor.interfaceEvent());
foreach (const ParamDescriptor &paramDescriptor, eventDescriptor.paramDescriptors()) {
settings.beginGroup("ParamDescriptor-" + paramDescriptor.paramTypeId().toString());
if (!paramDescriptor.paramTypeId().isNull()) {
settings.beginGroup("ParamDescriptor-" + paramDescriptor.paramTypeId().toString());
} else {
settings.beginGroup("ParamDescriptor-" + paramDescriptor.paramName());
}
settings.setValue("value", paramDescriptor.value());
settings.setValue("operator", paramDescriptor.operatorType());
settings.endGroup();
@ -1337,10 +1400,19 @@ void RuleEngine::saveRule(const Rule &rule)
settings.beginGroup("ruleActions");
foreach (const RuleAction &action, rule.actions()) {
settings.beginGroup(QString::number(i));
settings.setValue("deviceId", action.deviceId().toString());
settings.setValue("actionTypeId", action.actionTypeId().toString());
if (!action.deviceId().isNull() && !action.actionTypeId().isNull()) {
settings.setValue("deviceId", action.deviceId().toString());
settings.setValue("actionTypeId", action.actionTypeId().toString());
} else {
settings.setValue("interface", action.interface());
settings.setValue("interfaceAction", action.interfaceAction());
}
foreach (const RuleActionParam &param, action.ruleActionParams()) {
settings.beginGroup("RuleActionParam-" + param.paramTypeId().toString());
if (!param.paramTypeId().isNull()) {
settings.beginGroup("RuleActionParam-" + param.paramTypeId().toString());
} else {
settings.beginGroup("RuleActionParam-" + param.paramName());
}
settings.setValue("value", param.value());
if (param.eventTypeId() != EventTypeId()) {
settings.setValue("eventTypeId", param.eventTypeId().toString());
@ -1358,10 +1430,19 @@ void RuleEngine::saveRule(const Rule &rule)
i = 0;
foreach (const RuleAction &action, rule.exitActions()) {
settings.beginGroup(QString::number(i));
settings.setValue("deviceId", action.deviceId().toString());
settings.setValue("actionTypeId", action.actionTypeId().toString());
if (!action.deviceId().isNull() && !action.actionTypeId().isNull()) {
settings.setValue("deviceId", action.deviceId().toString());
settings.setValue("actionTypeId", action.actionTypeId().toString());
} else {
settings.setValue("interface", action.interface());
settings.setValue("interfaceAction", action.interfaceAction());
}
foreach (const RuleActionParam &param, action.ruleActionParams()) {
settings.beginGroup("RuleActionParam-" + param.paramTypeId().toString());
if (!param.paramTypeId().isNull()) {
settings.beginGroup("RuleActionParam-" + param.paramTypeId().toString());
} else {
settings.beginGroup("RuleActionParam-" + param.paramName());
}
settings.setValue("value", param.value());
settings.endGroup();
}
@ -1369,6 +1450,7 @@ void RuleEngine::saveRule(const Rule &rule)
settings.endGroup();
}
settings.endGroup();
qWarning() << "#### Saved rule to config:" << rule;
}
}

View File

@ -197,7 +197,9 @@ void StateEvaluator::removeDevice(const DeviceId &deviceId)
QList<DeviceId> StateEvaluator::containedDevices() const
{
QList<DeviceId> ret;
ret.append(m_stateDescriptor.deviceId());
if (!m_stateDescriptor.deviceId().isNull()) {
ret.append(m_stateDescriptor.deviceId());
}
foreach (const StateEvaluator &childEvaluator, m_childEvaluators) {
ret.append(childEvaluator.containedDevices());
}
@ -208,6 +210,7 @@ QList<DeviceId> StateEvaluator::containedDevices() const
The \a groupName will normally be the corresponding \l Rule. */
void StateEvaluator::dumpToSettings(NymeaSettings &settings, const QString &groupName) const
{
qWarning() << "Dumping to settings:" << groupName;
settings.beginGroup(groupName);
settings.beginGroup("stateDescriptor");
@ -260,6 +263,7 @@ StateEvaluator StateEvaluator::loadFromSettings(NymeaSettings &settings, const Q
}
settings.endGroup();
settings.endGroup();
qWarning() << "*** loading from settings" << groupName << ret;
return ret;
}
@ -344,4 +348,13 @@ bool StateEvaluator::isValid() const
return true;
}
QDebug operator<<(QDebug dbg, const StateEvaluator &stateEvaluator)
{
dbg.nospace() << "StateEvaluator: Operator:" << stateEvaluator.operatorType() << endl << " " << stateEvaluator.stateDescriptor() << endl;
for (int i = 0; i < stateEvaluator.childEvaluators().count(); i++) {
dbg.nospace() << " " << i << ": " << stateEvaluator.childEvaluators().at(i);
}
return dbg;
}
}

View File

@ -64,6 +64,8 @@ private:
Types::StateOperator m_operatorType;
};
QDebug operator<<(QDebug dbg, const StateEvaluator &stateEvaluator);
}
#endif // STATEEVALUATOR_H

View File

@ -31,6 +31,8 @@
#include "calendaritem.h"
#include "loggingcategories.h"
#include <QDebug>
namespace nymeaserver {
/*! Construct a invalid \l{CalendarItem}. */
@ -266,5 +268,11 @@ bool CalendarItem::evaluateYearly(const QDateTime &dateTime) const
return false;
}
QDebug operator<<(QDebug dbg, const CalendarItem &calendarItem)
{
dbg.nospace() << "CalendarItem (StartTime:" << calendarItem.startTime() << ", DateTime:" << calendarItem.dateTime().toString() << ", " << calendarItem.repeatingOption() << ", Duration:" << calendarItem.duration() << ")";
return dbg;
}
}

View File

@ -63,6 +63,7 @@ private:
};
QDebug operator<<(QDebug dbg, const CalendarItem &calendarItem);
}
#endif // CALENDARITEM_H

View File

@ -191,4 +191,10 @@ bool RepeatingOption::evaluateMonthDay(const QDateTime &dateTime) const
return false;
}
QDebug operator<<(QDebug dbg, const RepeatingOption &repeatingOption)
{
dbg.nospace() << "RepeatingOption(Mode:" << repeatingOption.mode() << ", Monthdays:" << repeatingOption.monthDays() << "Weekdays:" << repeatingOption.weekDays() << ")";
return dbg;
}
}

View File

@ -65,6 +65,7 @@ private:
};
QDebug operator<<(QDebug dbg, const RepeatingOption &RepeatingOption);
}
#endif // REPEATINGOPTION_H

View File

@ -34,6 +34,8 @@
#include "timedescriptor.h"
#include <QDebug>
namespace nymeaserver {
/*! Constructs an invalid \l{TimeDescriptor}.*/
@ -105,4 +107,16 @@ bool TimeDescriptor::evaluate(const QDateTime &lastEvaluationTime, const QDateTi
return false;
}
QDebug operator<<(QDebug dbg, const TimeDescriptor &timeDescriptor)
{
dbg.nospace() << "TimeDescriptor (TimeEventItems:" << timeDescriptor.timeEventItems().count() << ", CalendarItems:" << timeDescriptor.calendarItems().count() << ")" << endl;
for (int i = 0; i < timeDescriptor.timeEventItems().count(); i++) {
dbg.nospace() << " " << i << ": " << timeDescriptor.timeEventItems().at(i);
}
for (int i = 0; i < timeDescriptor.calendarItems().count(); i++) {
dbg.nospace() << " " << i << ": " << timeDescriptor.calendarItems().at(i);
}
return dbg;
}
}

View File

@ -52,6 +52,8 @@ private:
};
QDebug operator<<(QDebug dbg, const TimeDescriptor &timeDescriptor);
}
#endif // TIMEDESCRIPTOR_H

View File

@ -31,6 +31,8 @@
#include "timeeventitem.h"
#include <QDebug>
namespace nymeaserver {
/*! Constructs an invalid \l{TimeEventItem}. */
@ -132,4 +134,10 @@ bool TimeEventItem::evaluate(const QDateTime &lastEvaluationTime, const QDateTim
return lastEvaluationTime < m_dateTime && m_dateTime <= dateTime;
}
QDebug operator<<(QDebug dbg, const TimeEventItem &timeEventItem)
{
dbg.nospace() << "TimeEventItem (Time:" << timeEventItem.time() << ", DateTime:" << timeEventItem.dateTime().toString() << ", " << timeEventItem.repeatingOption() << ")" << endl;
return dbg;
}
}

View File

@ -54,6 +54,8 @@ private:
RepeatingOption m_repeatingOption;
};
QDebug operator<<(QDebug dbg, const TimeEventItem &timeEventItem);
}
#endif // TIMEEVENTITEM_H

View File

@ -146,18 +146,21 @@ bool EventDescriptor::operator ==(const EventDescriptor &other) const
/*! Writes the eventTypeId and the deviceId of the given \a eventDescriptor to \a dbg. */
QDebug operator<<(QDebug dbg, const EventDescriptor &eventDescriptor)
{
dbg.nospace() << "EventDescriptor(EventTypeId: " << eventDescriptor.eventTypeId().toString() << ", DeviceId" << eventDescriptor.deviceId() << ")";
dbg.nospace() << "EventDescriptor(EventTypeId: " << eventDescriptor.eventTypeId().toString() << ", DeviceId:" << eventDescriptor.deviceId().toString() << ", Interface:" << eventDescriptor.interface() << ", InterfaceEvent:" << eventDescriptor.interfaceEvent() << ")" << endl;
for (int i = 0; i < eventDescriptor.paramDescriptors().count(); i++) {
dbg.nospace() << " " << i << ": " << eventDescriptor.paramDescriptors().at(i);
}
return dbg.space();
return dbg;
}
/*! Writes each \a eventDescriptors to \a dbg. */
QDebug operator<<(QDebug dbg, const QList<EventDescriptor> &eventDescriptors)
{
dbg.nospace() << "EventDescriptorList (count:" << eventDescriptors.count() << ")";
dbg.nospace() << "EventDescriptorList (count:" << eventDescriptors.count() << "):" << endl;
for (int i = 0; i < eventDescriptors.count(); i++ ) {
dbg.nospace() << " " << i << ": " << eventDescriptors.at(i);
dbg.nospace() << " " << i << ": " << eventDescriptors.at(i);
}
return dbg.space();
return dbg;
}

View File

@ -36,6 +36,8 @@
#include "paramdescriptor.h"
#include <QDebug>
/*! Constructs an ParamDescriptor describing an \l{Param} with the given \a paramTypeId and \a value.
* The ValueOperator is by default ValueOperatorEquals. */
ParamDescriptor::ParamDescriptor(const ParamTypeId &paramTypeId, const QVariant &value):
@ -44,6 +46,22 @@ ParamDescriptor::ParamDescriptor(const ParamTypeId &paramTypeId, const QVariant
{
}
/*! Constructs an ParamDescriptor describing an \l{Param} with the given \a paramTypeId and \a value.
* The ValueOperator is by default ValueOperatorEquals. */
ParamDescriptor::ParamDescriptor(const QString &paramName, const QVariant &value):
Param(ParamTypeId(), value),
m_paramName(paramName),
m_operatorType(Types::ValueOperatorEquals)
{
}
/*! Returns the paramName of this ParamDescriptor. */
QString ParamDescriptor::paramName() const
{
return m_paramName;
}
/*! Returns the ValueOperator of this ParamDescriptor. */
Types::ValueOperator ParamDescriptor::operatorType() const
{
@ -56,3 +74,9 @@ void ParamDescriptor::setOperatorType(Types::ValueOperator operatorType)
m_operatorType = operatorType;
}
QDebug operator<<(QDebug dbg, const ParamDescriptor &paramDescriptor)
{
dbg.nospace() << "ParamDescriptor(ParamTypeId: " << paramDescriptor.paramTypeId().toString() << ", Name:" << paramDescriptor.paramName() << ", Value:" << paramDescriptor.value() << ")" << endl;
return dbg;
}

View File

@ -33,12 +33,17 @@ class LIBNYMEA_EXPORT ParamDescriptor : public Param
{
public:
ParamDescriptor(const ParamTypeId &paramTypeId, const QVariant &value = QVariant());
ParamDescriptor(const QString &paramName, const QVariant &value = QVariant());
QString paramName() const;
Types::ValueOperator operatorType() const;
void setOperatorType(Types::ValueOperator operatorType);
private:
QString m_paramName;
Types::ValueOperator m_operatorType;
};
QDebug operator<<(QDebug dbg, const ParamDescriptor &paramDescriptor);
#endif // PARAMDESCRIPTOR_H

View File

@ -190,3 +190,21 @@ void RuleAction::operator=(const RuleAction &other)
m_actionTypeId = other.actionTypeId();
m_ruleActionParams = other.ruleActionParams();
}
QDebug operator<<(QDebug dbg, const RuleAction &ruleAction)
{
dbg.nospace() << "RuleAction(ActionTypeId:" << ruleAction.actionTypeId().toString() << ", DeviceId:" << ruleAction.deviceId().toString() << ", Interface:" << ruleAction.interface() << ", InterfaceAction:" << ruleAction.interfaceAction() << ")" << endl;
for (int i = 0; i < ruleAction.ruleActionParams().count(); i++) {
dbg.nospace() << " " << i << ": " << ruleAction.ruleActionParams().at(i) << endl;
}
return dbg;
}
QDebug operator<<(QDebug dbg, const QList<RuleAction> &ruleActionList)
{
dbg.nospace() << "RuleActionList (count:" << ruleActionList.count() << "):" << endl;
for (int i = 0; i < ruleActionList.count(); i++ ) {
dbg.nospace() << " " << i << ": " << ruleActionList.at(i);
}
return dbg;
}

View File

@ -70,4 +70,7 @@ private:
RuleActionParamList m_ruleActionParams;
};
QDebug operator<<(QDebug dbg, const RuleAction &ruleAction);
QDebug operator<<(QDebug dbg, const QList<RuleAction> &ruleActionList);
#endif // RULEACTION_H

View File

@ -127,13 +127,13 @@ void RuleActionParam::setEventTypeId(const EventTypeId &eventTypeId)
/*! Writes the paramTypeId, value, eventId and eventParamTypeId of the given \a ruleActionParam to \a dbg. */
QDebug operator<<(QDebug dbg, const RuleActionParam &ruleActionParam)
{
dbg.nospace() << "RuleActionParam(ParamTypeId: " << ruleActionParam.paramTypeId() << ", Value:" << ruleActionParam.value();
dbg.nospace() << "RuleActionParam(ParamTypeId: " << ruleActionParam.paramTypeId().toString() << ", Name:" << ruleActionParam.paramName() << ", Value:" << ruleActionParam.value();
if (ruleActionParam.eventTypeId() != EventTypeId()) {
dbg.nospace() << ", EventTypeId:" << ruleActionParam.eventTypeId().toString() << ", EventParamTypeId:" << ruleActionParam.eventParamTypeId().toString() << ")";
} else {
dbg.nospace() << ")";
}
return dbg.space();
return dbg;
}
// ActionTypeParamList

View File

@ -161,3 +161,11 @@ bool StateDescriptor::isValid() const
{
return ((!m_deviceId.isNull() && !m_stateTypeId.isNull()) || (!m_interface.isNull() && !m_interfaceState.isNull())) && m_stateValue.isValid();
}
QDebug operator<<(QDebug dbg, const StateDescriptor &stateDescriptor)
{
dbg.nospace() << "StateDescriptor(DeviceId:" << stateDescriptor.deviceId().toString() << ", StateTypeId:"
<< stateDescriptor.stateTypeId().toString() << ", Interface:" << stateDescriptor.interface()
<< ", InterfaceState:" << stateDescriptor.interfaceState() << ", Operator:" << stateDescriptor.operatorType() << ", Value:" << stateDescriptor.stateValue();
return dbg;
}

View File

@ -73,7 +73,6 @@ private:
Types::ValueOperator m_operatorType;
};
QDebug operator<<(QDebug dbg, const StateDescriptor &eventDescriptor);
QDebug operator<<(QDebug dbg, const QList<StateDescriptor> &eventDescriptors);
QDebug operator<<(QDebug dbg, const StateDescriptor &stateDescriptor);
#endif // STATEDESCRIPTOR_H

View File

@ -83,8 +83,13 @@ void HttpDaemon::readClient()
QUrl url("http://foo.bar" + tokens[1]);
QUrlQuery query(url);
if (url.path() == "/setstate") {
qCDebug(dcMockDevice) << "Set state value" << query.queryItems().first().second;
emit setState(StateTypeId(query.queryItems().first().first), QVariant(query.queryItems().first().second));
StateTypeId stateTypeId = StateTypeId(query.queryItems().first().first);
QVariant stateValue = query.queryItems().first().second;
if (stateTypeId == mockBoolValueStateTypeId || stateTypeId == mockBatteryCriticalStateTypeId) {
stateValue.convert(QVariant::Bool);
}
qCDebug(dcMockDevice) << "Set state value" << stateValue;
emit setState(stateTypeId, stateValue);
} else if (url.path() == "/generateevent") {
emit triggerEvent(EventTypeId(query.queryItemValue("eventtypeid")));
} else if (url.path() == "/actionhistory") {

View File

@ -1147,6 +1147,44 @@ void TestRules::loadStoreConfig()
validEventDescriptor3.insert("paramDescriptors", QVariantList());
validEventDescriptors3.append(validEventDescriptor3);
// Interface based event descriptor
QVariantMap eventDescriptorInterfaces;
eventDescriptorInterfaces.insert("interface", "battery");
eventDescriptorInterfaces.insert("interfaceEvent", "batteryCritical");
QVariantMap eventDescriptorInterfacesParam;
eventDescriptorInterfacesParam.insert("paramName", "batteryCritical");
eventDescriptorInterfacesParam.insert("value", true);
eventDescriptorInterfacesParam.insert("operator", "ValueOperatorEquals");
QVariantList eventDescriptorInterfacesParams;
eventDescriptorInterfacesParams.append(eventDescriptorInterfacesParam);
eventDescriptorInterfaces.insert("paramDescriptors", eventDescriptorInterfacesParams);
QVariantList eventDescriptorsInterfaces;
eventDescriptorsInterfaces.append(eventDescriptorInterfaces);
// Interface based state evaluator
QVariantMap stateDescriptorInterfaces;
stateDescriptorInterfaces.insert("interface", "battery");
stateDescriptorInterfaces.insert("interfaceState", "batteryCritical");
stateDescriptorInterfaces.insert("operator", "ValueOperatorEquals");
stateDescriptorInterfaces.insert("value", true);
QVariantMap stateEvaluatorInterfaces;
stateEvaluatorInterfaces.insert("stateDescriptor", stateDescriptorInterfaces);
stateEvaluatorInterfaces.insert("operator", "StateOperatorAnd");
// Interface based actions
QVariantMap ruleActionParamInterfaces;
ruleActionParamInterfaces.insert("paramName", "power");
ruleActionParamInterfaces.insert("value", true);
QVariantList ruleActionParamsInterfaces;
ruleActionParamsInterfaces.append(ruleActionParamInterfaces);
QVariantMap actionInterfaces;
actionInterfaces.insert("interface", "light");
actionInterfaces.insert("interfaceAction", "power");
actionInterfaces.insert("ruleActionParams", ruleActionParamsInterfaces);
QVariantList actionsInterfaces;
actionsInterfaces.append(actionInterfaces);
// rule 1
QVariantMap params;
QVariantList actions;
@ -1188,6 +1226,17 @@ void TestRules::loadStoreConfig()
RuleId newRuleId3 = RuleId(response3.toMap().value("params").toMap().value("ruleId").toString());
verifyRuleError(response3);
// rule 4, interface based
QVariantMap params4;
params4.insert("name", "TestRule4 - Interface based");
params4.insert("eventDescriptors", eventDescriptorsInterfaces);
params4.insert("stateEvaluator", stateEvaluatorInterfaces);
params4.insert("actions", actionsInterfaces);
QVariant response4 = injectAndWait("Rules.AddRule", params4);
RuleId newRuleId4 = RuleId(response4.toMap().value("params").toMap().value("ruleId").toString());
verifyRuleError(response4);
response = injectAndWait("Rules.GetRules");
QVariantList rules = response.toMap().value("params").toMap().value("ruleDescriptions").toList();
qDebug() << "GetRules before server shutdown:" << response;
@ -1197,7 +1246,7 @@ void TestRules::loadStoreConfig()
response = injectAndWait("Rules.GetRules");
rules = response.toMap().value("params").toMap().value("ruleDescriptions").toList();
QVERIFY2(rules.count() == 3, "There should be exactly three rule.");
QVERIFY2(rules.count() == 4, "There should be exactly four rule.");
QStringList idList;
foreach (const QVariant &ruleDescription, rules) {
@ -1207,6 +1256,7 @@ void TestRules::loadStoreConfig()
QVERIFY2(idList.contains(newRuleId.toString()), "Rule 1 should be in ruleIds list.");
QVERIFY2(idList.contains(newRuleId2.toString()), "Rule 2 should be in ruleIds list.");
QVERIFY2(idList.contains(newRuleId3.toString()), "Rule 3 should be in ruleIds list.");
QVERIFY2(idList.contains(newRuleId4.toString()), "Rule 4 should be in ruleIds list.");
// Rule 1
params.clear();
@ -1379,6 +1429,48 @@ void TestRules::loadStoreConfig()
QVERIFY2(found, "Action not found after loading from config.");
}
// Rule 4
params.clear();
params.insert("ruleId", newRuleId4);
response.clear();
response = injectAndWait("Rules.GetRuleDetails", params);
QVariantMap rule4 = response.toMap().value("params").toMap().value("rule").toMap();
qDebug() << rule4;
QVariantList eventDescriptors4 = rule4.value("eventDescriptors").toList();
QVERIFY2(eventDescriptors4.count() == 1, "There should be exactly 1 eventDescriptor");
eventDescriptor = eventDescriptors4.first().toMap();
QVERIFY2(eventDescriptor.value("interface").toString() == "battery", "Loaded the wrong interface name in rule 4");
QVERIFY2(eventDescriptor.value("interfaceEvent").toString() == "batteryCritical", "Loaded the wrong interfaceEvent from eventDescriptor in rule 4");
QCOMPARE(eventDescriptor.value("paramDescriptors").toList().count(), 1);
QVERIFY2(eventDescriptor.value("paramDescriptors").toList().first().toMap().value("paramName").toString() == "batteryCritical", "Loaded wrong ParamDescriptor in rule 4");
QVERIFY2(eventDescriptor.value("paramDescriptors").toList().first().toMap().value("value").toBool() == true, "Loaded wrong ParamDescriptor in rule 3");
QVariantList replyActions4 = rule4.value("actions").toList();
QVERIFY2(replyActions4.count() == 1, "Rule 4 should have exactly 1 action");
foreach (const QVariant &actionVariant, actionsInterfaces) {
bool found = false;
foreach (const QVariant &replyActionVariant, replyActions4) {
if (actionVariant.toMap().value("interface") == replyActionVariant.toMap().value("interface") &&
actionVariant.toMap().value("interfaceAction") == replyActionVariant.toMap().value("interfaceAction")) {
found = true;
// Check rule action params
QVariantList actionParams = actionVariant.toMap().value("ruleActionParams").toList();
QVariantList replyActionParams = replyActionVariant.toMap().value("ruleActionParams").toList();
QVERIFY2(actionParams.count() == replyActionParams.count(), "Not the same list size of action params");
foreach (const QVariant &ruleParam, actionParams) {
QVERIFY(replyActionParams.contains(ruleParam));
}
}
}
QVERIFY2(found, "Action not found after loading from config.");
}
QVariantList replyExitActions4 = rule4.value("exitActions").toList();
QVERIFY2(replyExitActions4.isEmpty(), "Rule 4 should not have any exitAction");
// Remove Rule1
params.clear();
params.insert("ruleId", newRuleId);
@ -2288,6 +2380,11 @@ void TestRules::testInterfaceBasedEventRule()
QVariantMap lowBatteryEvent;
lowBatteryEvent.insert("interface", "battery");
lowBatteryEvent.insert("interfaceEvent", "batteryCritical");
QVariantMap eventParams;
eventParams.insert("paramName", "batteryCritical");
eventParams.insert("value", true);
eventParams.insert("operator", "ValueOperatorEquals");
lowBatteryEvent.insert("paramDescriptors", QVariantList() << eventParams);
QVariantMap addRuleParams;
addRuleParams.insert("name", "TestInterfaceBasedRule");
@ -2314,15 +2411,29 @@ void TestRules::testInterfaceBasedEventRule()
QCOMPARE(response.toMap().value("params").toMap().value("rule").toMap().value("actions").toList().first().toMap().value("ruleActionParams").toList().first().toMap().value("value").toString(), QString("true"));
// Change the state
// Change the state to true, action should trigger
spy.clear();
request = QNetworkRequest(QUrl(QString("http://localhost:%1/clearactionhistory").arg(m_mockDevice1Port)));
reply = nam.get(request);
spy.wait(); spy.clear();
request = QNetworkRequest(QUrl(QString("http://localhost:%1/setstate?%2=%3").arg(m_mockDevice1Port).arg(mockBatteryCriticalStateId.toString()).arg(true)));
reply = nam.get(request);
spy.wait();
QCOMPARE(spy.count(), 1);
reply->deleteLater();
verifyRuleExecuted(mockActionIdPower);
// Change the state to false, action should not trigger
spy.clear();
request = QNetworkRequest(QUrl(QString("http://localhost:%1/clearactionhistory").arg(m_mockDevice1Port)));
reply = nam.get(request);
spy.wait(); spy.clear();
request = QNetworkRequest(QUrl(QString("http://localhost:%1/setstate?%2=%3").arg(m_mockDevice1Port).arg(mockBatteryCriticalStateId.toString()).arg(false)));
reply = nam.get(request);
spy.wait();
QCOMPARE(spy.count(), 1);
reply->deleteLater();
verifyRuleNotExecuted();
}
void TestRules::testInterfaceBasedStateRule()

View File

@ -3,5 +3,6 @@
if [ -z $2 ]; then
echo "usage: $0 host ruleId"
else
echo '{"id":1, "method":"Rules.GetRuleDetails", "params": {"ruleId": "'$2'"}}'
(echo '{"id":1, "method":"Rules.GetRuleDetails", "params": {"ruleId": "'$2'"}}'; sleep 1) | nc $1 2222
fi